@heuresys/ui 0.1.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/README.md +22 -0
- package/dist/index.cjs +9259 -0
- package/dist/index.d.cts +2528 -0
- package/dist/index.d.ts +2528 -0
- package/dist/index.mjs +8971 -0
- package/package.json +166 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/README.md +31 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-A-full.svg +11 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-A-symbol.svg +8 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-B-full.svg +12 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-B-symbol.svg +9 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-C-full.svg +13 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-C-symbol.svg +10 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-D-full.svg +6 -0
- package/src/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-D-symbol.svg +4 -0
- package/src/assets/brand/legacy/README.md +34 -0
- package/src/assets/brand/legacy/favicon.svg +16 -0
- package/src/assets/brand/legacy/heuresys-mark.svg +14 -0
- package/src/assets/brand/legacy/heuresys-wordmark-monochrome-dark.svg +15 -0
- package/src/assets/brand/legacy/heuresys-wordmark-monochrome-light.svg +15 -0
- package/src/assets/brand/legacy/heuresys-wordmark.svg +21 -0
- package/src/assets/brand/legacy/og-image-template.svg +44 -0
- package/src/assets/brand/logo/heuresys-mark-16.png +0 -0
- package/src/assets/brand/logo/heuresys-mark-180.png +0 -0
- package/src/assets/brand/logo/heuresys-mark-192.png +0 -0
- package/src/assets/brand/logo/heuresys-mark-32.png +0 -0
- package/src/assets/brand/logo/heuresys-mark-48.png +0 -0
- package/src/assets/brand/logo/heuresys-mark-512.png +0 -0
- package/src/assets/brand/logo/heuresys-mark-64.png +0 -0
- package/src/assets/brand/social/linkedin-banner-1200x627.png +0 -0
- package/src/assets/brand/social/og-image-1200x630.png +0 -0
- package/src/assets/brand/social/twitter-card-1200x628.png +0 -0
- package/src/components/brand/candidates/LogoCandidateA.tsx +87 -0
- package/src/components/brand/candidates/LogoCandidateB.tsx +65 -0
- package/src/components/brand/candidates/LogoCandidateC.tsx +68 -0
- package/src/components/brand/candidates/LogoCandidateD.tsx +77 -0
- package/src/components/brand/candidates/index.ts +4 -0
- package/src/styles/globals.css +21 -0
- package/src/styles/hover-affordance.css +280 -0
- package/src/styles/tokens.css +109 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { SVGProps } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UXIX-0007 candidate C — Triangle constellation mark.
|
|
5
|
+
*
|
|
6
|
+
* Circle scaffold + three nodes forming a triangle. People / role / capability
|
|
7
|
+
* triangulation. Lightest of the three, more editorial, leans into "workforce
|
|
8
|
+
* intelligence" positioning.
|
|
9
|
+
*
|
|
10
|
+
* Wordmark: 300 (light), letter-spacing +1, all-lowercase.
|
|
11
|
+
*
|
|
12
|
+
* Raw SVG source: `@heuresys/ui/assets/brand/candidates/UXIX-0007-logo/heuresys-logo-C-{symbol,full}.svg`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export function LogoCandidateCSymbol(props: SVGProps<SVGSVGElement>) {
|
|
16
|
+
return (
|
|
17
|
+
<svg
|
|
18
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
19
|
+
viewBox="0 0 48 48"
|
|
20
|
+
role="img"
|
|
21
|
+
aria-label="Heuresys candidate C — triangle constellation mark"
|
|
22
|
+
{...props}
|
|
23
|
+
>
|
|
24
|
+
<title>Heuresys candidate C — triangle constellation mark</title>
|
|
25
|
+
<circle cx="24" cy="24" r="20" fill="none" stroke="currentColor" strokeWidth="2" opacity="0.4" />
|
|
26
|
+
<circle cx="24" cy="12" r="4" fill="currentColor" />
|
|
27
|
+
<circle cx="13" cy="32" r="4" fill="currentColor" />
|
|
28
|
+
<circle cx="35" cy="32" r="4" fill="currentColor" />
|
|
29
|
+
<line x1="24" y1="12" x2="13" y2="32" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
|
30
|
+
<line x1="24" y1="12" x2="35" y2="32" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
|
31
|
+
<line x1="13" y1="32" x2="35" y2="32" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
|
32
|
+
</svg>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function LogoCandidateCFull(props: SVGProps<SVGSVGElement>) {
|
|
37
|
+
return (
|
|
38
|
+
<svg
|
|
39
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
40
|
+
viewBox="0 0 220 48"
|
|
41
|
+
role="img"
|
|
42
|
+
aria-label="Heuresys candidate C — triangle constellation + wordmark"
|
|
43
|
+
{...props}
|
|
44
|
+
>
|
|
45
|
+
<title>Heuresys candidate C — triangle constellation + wordmark</title>
|
|
46
|
+
<g>
|
|
47
|
+
<circle cx="24" cy="24" r="20" fill="none" stroke="currentColor" strokeWidth="2" opacity="0.4" />
|
|
48
|
+
<circle cx="24" cy="12" r="4" fill="currentColor" />
|
|
49
|
+
<circle cx="13" cy="32" r="4" fill="currentColor" />
|
|
50
|
+
<circle cx="35" cy="32" r="4" fill="currentColor" />
|
|
51
|
+
<line x1="24" y1="12" x2="13" y2="32" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
|
52
|
+
<line x1="24" y1="12" x2="35" y2="32" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
|
53
|
+
<line x1="13" y1="32" x2="35" y2="32" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
|
|
54
|
+
</g>
|
|
55
|
+
<text
|
|
56
|
+
x="56"
|
|
57
|
+
y="32"
|
|
58
|
+
fontFamily="'Exo 2', system-ui, -apple-system, 'Segoe UI', sans-serif"
|
|
59
|
+
fontSize="22"
|
|
60
|
+
fontWeight="300"
|
|
61
|
+
letterSpacing="1"
|
|
62
|
+
fill="currentColor"
|
|
63
|
+
>
|
|
64
|
+
heuresys
|
|
65
|
+
</text>
|
|
66
|
+
</svg>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { SVGProps } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UXIX-0007 candidate D — Y-accent wordmark (legacy port).
|
|
5
|
+
*
|
|
6
|
+
* Inherited from the evo.heuresys.com legacy brand identity:
|
|
7
|
+
* `heuresys` lowercase wordmark in Exo 2 700, with the middle "y" rendered
|
|
8
|
+
* in a contrast accent color while the rest is in the primary blue. The
|
|
9
|
+
* standalone mark is the "y" letterform alone — typographic, not geometric.
|
|
10
|
+
*
|
|
11
|
+
* Two palette behaviours:
|
|
12
|
+
* - Default (no className override): hardcoded legacy colors blue #3B82F6
|
|
13
|
+
* + purple #A855F7 — brand-direct, palette-independent.
|
|
14
|
+
* - Adaptive: wrap with className that sets `color` for the body letters
|
|
15
|
+
* (currentColor) and `--logo-accent` CSS var for the "y" (e.g.
|
|
16
|
+
* `style={{ "--logo-accent": "var(--palette-2)" }} className="text-[var(--palette-1)]"`).
|
|
17
|
+
* This allows the logo to follow the active palette when theme switches.
|
|
18
|
+
*
|
|
19
|
+
* Legacy assets archived in `D:\ux-design-shared\ui\src\assets\brand\legacy\`.
|
|
20
|
+
* Raw SVG twins in `../../assets/brand/candidates/UXIX-0007-logo/heuresys-logo-D-{symbol,full}.svg`.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const LEGACY_BLUE = "#3B82F6";
|
|
24
|
+
const LEGACY_PURPLE = "#A855F7";
|
|
25
|
+
|
|
26
|
+
export function LogoCandidateDSymbol(props: SVGProps<SVGSVGElement>) {
|
|
27
|
+
return (
|
|
28
|
+
<svg
|
|
29
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
30
|
+
viewBox="0 0 48 48"
|
|
31
|
+
role="img"
|
|
32
|
+
aria-label="Heuresys candidate D — Y-accent mark"
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
<title>Heuresys candidate D — Y-accent mark (legacy port)</title>
|
|
36
|
+
<text
|
|
37
|
+
x="24"
|
|
38
|
+
y="38"
|
|
39
|
+
textAnchor="middle"
|
|
40
|
+
fontFamily="'Exo 2', system-ui, -apple-system, 'Segoe UI', sans-serif"
|
|
41
|
+
fontSize="44"
|
|
42
|
+
fontWeight="700"
|
|
43
|
+
letterSpacing="0"
|
|
44
|
+
fill={`var(--logo-accent, ${LEGACY_PURPLE})`}
|
|
45
|
+
>
|
|
46
|
+
y
|
|
47
|
+
</text>
|
|
48
|
+
</svg>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function LogoCandidateDFull(props: SVGProps<SVGSVGElement>) {
|
|
53
|
+
return (
|
|
54
|
+
<svg
|
|
55
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
56
|
+
viewBox="0 0 220 48"
|
|
57
|
+
role="img"
|
|
58
|
+
aria-label="Heuresys candidate D — Y-accent wordmark"
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
<title>Heuresys candidate D — Y-accent wordmark (legacy port)</title>
|
|
62
|
+
<text
|
|
63
|
+
x="110"
|
|
64
|
+
y="34"
|
|
65
|
+
textAnchor="middle"
|
|
66
|
+
fontFamily="'Exo 2', system-ui, -apple-system, 'Segoe UI', sans-serif"
|
|
67
|
+
fontSize="34"
|
|
68
|
+
fontWeight="700"
|
|
69
|
+
letterSpacing="-0.5"
|
|
70
|
+
>
|
|
71
|
+
<tspan fill={`var(--logo-body, ${LEGACY_BLUE})`}>heures</tspan>
|
|
72
|
+
<tspan fill={`var(--logo-accent, ${LEGACY_PURPLE})`}>y</tspan>
|
|
73
|
+
<tspan fill={`var(--logo-body, ${LEGACY_BLUE})`}>s</tspan>
|
|
74
|
+
</text>
|
|
75
|
+
</svg>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "./hover-affordance.css";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Design tokens (placeholder) — TBD by brand definition.
|
|
6
|
+
* Tokens use OKLCH for perceptual uniformity. Values picked to read well on
|
|
7
|
+
* white and dark backgrounds; replace once the official Heuresys palette is
|
|
8
|
+
* confirmed.
|
|
9
|
+
*/
|
|
10
|
+
@theme {
|
|
11
|
+
--font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
12
|
+
|
|
13
|
+
--color-primary: oklch(0.55 0.18 250);
|
|
14
|
+
--color-primary-fg: oklch(1.00 0.00 0);
|
|
15
|
+
--color-destructive: oklch(0.55 0.20 25);
|
|
16
|
+
--color-destructive-fg: oklch(1.00 0.00 0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
html, body {
|
|
20
|
+
font-family: var(--font-sans);
|
|
21
|
+
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
Heuresys universal hover + interaction sheet (canonical).
|
|
3
|
+
============================================================
|
|
4
|
+
Source: ux-design/prototypes/superuser-system-health.html
|
|
5
|
+
Mirror at heuresys-advanced/.../code_examples/src/styles/hover-affordance.css
|
|
6
|
+
|
|
7
|
+
IMPORTANT — color tokens convention:
|
|
8
|
+
This sheet uses `color-mix(in srgb, var(--X) N%, transparent)` rather than
|
|
9
|
+
`hsl(var(--X) / N)`. The latter syntax requires the var to be a bare HSL
|
|
10
|
+
triple ("221 83% 53%"); apps/web emits hex values via PaletteProvider, so
|
|
11
|
+
hsl()-wrapped vars would resolve to `hsl(#2563EB / 0.18)` which is invalid
|
|
12
|
+
and falls back to transparent (= the bug that made cross-hair / hover
|
|
13
|
+
invisible). color-mix() accepts any color format.
|
|
14
|
+
============================================================ */
|
|
15
|
+
|
|
16
|
+
/* ---------- Cards (every <article> with a border) ---------- */
|
|
17
|
+
article {
|
|
18
|
+
transition:
|
|
19
|
+
border-color 180ms ease,
|
|
20
|
+
box-shadow 180ms ease,
|
|
21
|
+
transform 180ms ease;
|
|
22
|
+
transform-origin: center;
|
|
23
|
+
}
|
|
24
|
+
article:hover {
|
|
25
|
+
border-color: color-mix(in srgb, var(--primary) 85%, transparent) !important;
|
|
26
|
+
box-shadow:
|
|
27
|
+
0 0 0 1px color-mix(in srgb, var(--primary) 35%, transparent),
|
|
28
|
+
0 6px 18px color-mix(in srgb, var(--primary) 12%, transparent),
|
|
29
|
+
var(--shadow-card, 0 1px 2px rgba(0, 0, 0, 0.06));
|
|
30
|
+
transform: scale(1.012);
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
z-index: 1;
|
|
33
|
+
position: relative;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* ---------- Alert banner ---------- */
|
|
37
|
+
[role="alert"] {
|
|
38
|
+
transition: border-color 180ms ease, box-shadow 180ms ease;
|
|
39
|
+
}
|
|
40
|
+
[role="alert"]:hover {
|
|
41
|
+
border-color: color-mix(in srgb, var(--primary) 85%, transparent) !important;
|
|
42
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--primary) 30%, transparent);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ---------- Table rows (every tbody row) ---------- */
|
|
46
|
+
tbody tr {
|
|
47
|
+
transition: background-color 150ms ease, box-shadow 150ms ease;
|
|
48
|
+
}
|
|
49
|
+
tbody tr:hover {
|
|
50
|
+
background: color-mix(in srgb, var(--accent) 90%, transparent) !important;
|
|
51
|
+
box-shadow:
|
|
52
|
+
inset 4px 0 0 var(--primary),
|
|
53
|
+
inset 0 1px 0 color-mix(in srgb, var(--primary) 40%, transparent),
|
|
54
|
+
inset 0 -1px 0 color-mix(in srgb, var(--primary) 40%, transparent);
|
|
55
|
+
cursor: pointer;
|
|
56
|
+
}
|
|
57
|
+
/* Sticky cells need explicit row-hover override */
|
|
58
|
+
tbody tr:hover > td.sticky,
|
|
59
|
+
tbody tr:hover > td[class*="sticky"] {
|
|
60
|
+
background-color: color-mix(in srgb, var(--accent) 90%, transparent) !important;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ---------- Log stream lines ---------- */
|
|
64
|
+
.log-line {
|
|
65
|
+
transition: background-color 150ms ease, box-shadow 150ms ease;
|
|
66
|
+
font-size: 12px;
|
|
67
|
+
}
|
|
68
|
+
.log-line .ts { color: var(--muted-foreground); }
|
|
69
|
+
.log-line .lvl-info { color: var(--info); }
|
|
70
|
+
.log-line .lvl-warn { color: var(--warning); }
|
|
71
|
+
.log-line .lvl-error { color: var(--danger); }
|
|
72
|
+
.log-line .lvl-debug { color: var(--muted-foreground); }
|
|
73
|
+
.log-line .lvl-trace { color: var(--palette-3); }
|
|
74
|
+
.log-line:hover {
|
|
75
|
+
background: color-mix(in srgb, var(--accent) 90%, transparent) !important;
|
|
76
|
+
box-shadow:
|
|
77
|
+
inset 4px 0 0 var(--info),
|
|
78
|
+
inset 0 1px 0 color-mix(in srgb, var(--info) 40%, transparent),
|
|
79
|
+
inset 0 -1px 0 color-mix(in srgb, var(--info) 40%, transparent);
|
|
80
|
+
cursor: pointer;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* ---------- Feed items: audit feed + incident timeline ---------- */
|
|
84
|
+
ul[class*="divide-y"] > li,
|
|
85
|
+
ol[class*="space-y"] > li {
|
|
86
|
+
transition: background-color 150ms ease, box-shadow 150ms ease;
|
|
87
|
+
}
|
|
88
|
+
ul[class*="divide-y"] > li:hover {
|
|
89
|
+
background: color-mix(in srgb, var(--accent) 75%, transparent);
|
|
90
|
+
box-shadow:
|
|
91
|
+
inset 4px 0 0 var(--primary),
|
|
92
|
+
inset 0 1px 0 color-mix(in srgb, var(--primary) 35%, transparent),
|
|
93
|
+
inset 0 -1px 0 color-mix(in srgb, var(--primary) 35%, transparent);
|
|
94
|
+
cursor: pointer;
|
|
95
|
+
}
|
|
96
|
+
ol[class*="space-y"] > li:hover {
|
|
97
|
+
box-shadow:
|
|
98
|
+
inset 4px 0 0 var(--primary),
|
|
99
|
+
inset 0 1px 0 color-mix(in srgb, var(--primary) 35%, transparent),
|
|
100
|
+
inset 0 -1px 0 color-mix(in srgb, var(--primary) 35%, transparent);
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* ---------- Sidebar nav links ---------- */
|
|
105
|
+
.nav-link {
|
|
106
|
+
border: 1px solid transparent;
|
|
107
|
+
transition:
|
|
108
|
+
background-color 180ms ease,
|
|
109
|
+
border-color 180ms ease,
|
|
110
|
+
color 180ms ease;
|
|
111
|
+
}
|
|
112
|
+
.nav-link:hover {
|
|
113
|
+
border-color: color-mix(in srgb, var(--primary) 40%, transparent);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* ============================================================
|
|
117
|
+
Table cross-hair — JS toggles col-cross, cell-cross,
|
|
118
|
+
col-hover-header on mouseenter/leave of th and td.
|
|
119
|
+
Helper: lib/table-cursor.ts → attachCrossHair(table).
|
|
120
|
+
============================================================ */
|
|
121
|
+
table {
|
|
122
|
+
position: relative;
|
|
123
|
+
}
|
|
124
|
+
tbody td.col-cross {
|
|
125
|
+
background-color: color-mix(in srgb, var(--primary) 8%, transparent) !important;
|
|
126
|
+
transition: background-color 100ms ease;
|
|
127
|
+
}
|
|
128
|
+
tbody tr.row-cross > td {
|
|
129
|
+
background-color: color-mix(in srgb, var(--primary) 6%, transparent) !important;
|
|
130
|
+
}
|
|
131
|
+
tbody td.cell-cross {
|
|
132
|
+
background-color: color-mix(in srgb, var(--primary) 18%, transparent) !important;
|
|
133
|
+
box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--primary) 70%, transparent);
|
|
134
|
+
position: relative;
|
|
135
|
+
z-index: 2;
|
|
136
|
+
}
|
|
137
|
+
thead th.col-hover-header {
|
|
138
|
+
background-color: color-mix(in srgb, var(--primary) 15%, transparent) !important;
|
|
139
|
+
color: var(--primary);
|
|
140
|
+
box-shadow: inset 0 -2px 0 var(--primary);
|
|
141
|
+
}
|
|
142
|
+
/* Sticky cells too */
|
|
143
|
+
tbody td.sticky.col-cross,
|
|
144
|
+
tbody td[class*="sticky"].col-cross {
|
|
145
|
+
background-color: color-mix(in srgb, var(--primary) 8%, transparent) !important;
|
|
146
|
+
}
|
|
147
|
+
tbody td.sticky.cell-cross,
|
|
148
|
+
tbody td[class*="sticky"].cell-cross {
|
|
149
|
+
background-color: color-mix(in srgb, var(--primary) 18%, transparent) !important;
|
|
150
|
+
}
|
|
151
|
+
thead th.sticky.col-hover-header,
|
|
152
|
+
thead th[class*="sticky"].col-hover-header {
|
|
153
|
+
background-color: color-mix(in srgb, var(--primary) 15%, transparent) !important;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* ============================================================
|
|
157
|
+
Sidebar collapsed state — body[data-sidebar="collapsed"]
|
|
158
|
+
============================================================ */
|
|
159
|
+
body[data-sidebar="collapsed"] [data-shell="grid"] {
|
|
160
|
+
grid-template-columns: 72px 1fr !important;
|
|
161
|
+
}
|
|
162
|
+
body[data-sidebar="collapsed"] aside .sidebar-section-label,
|
|
163
|
+
body[data-sidebar="collapsed"] aside .sidebar-group-toggle,
|
|
164
|
+
body[data-sidebar="collapsed"] aside .sidebar-subtree,
|
|
165
|
+
body[data-sidebar="collapsed"] aside .sidebar-footer-card,
|
|
166
|
+
body[data-sidebar="collapsed"] aside .nav-label,
|
|
167
|
+
body[data-sidebar="collapsed"] aside .nav-aux {
|
|
168
|
+
display: none !important;
|
|
169
|
+
}
|
|
170
|
+
body[data-sidebar="collapsed"] aside .nav-link {
|
|
171
|
+
justify-content: center;
|
|
172
|
+
}
|
|
173
|
+
body[data-sidebar="collapsed"] .sidebar-icon-collapse { display: none; }
|
|
174
|
+
body[data-sidebar="collapsed"] .sidebar-icon-expand { display: block; }
|
|
175
|
+
|
|
176
|
+
/* ============================================================
|
|
177
|
+
Sidebar group expand/collapse — aria-expanded driven
|
|
178
|
+
============================================================ */
|
|
179
|
+
.sidebar-group-toggle[aria-expanded="false"] + .sidebar-group-content {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
[data-group-chevron] {
|
|
183
|
+
transition: transform 200ms ease;
|
|
184
|
+
}
|
|
185
|
+
.sidebar-group-toggle[aria-expanded="false"] [data-group-chevron] {
|
|
186
|
+
transform: rotate(-90deg);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* ============================================================
|
|
190
|
+
Palette dropdown chevron rotation
|
|
191
|
+
============================================================ */
|
|
192
|
+
#js-palette-trigger[aria-expanded="true"] [data-palette-chevron] {
|
|
193
|
+
transform: rotate(180deg);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* ============================================================
|
|
197
|
+
Custom scrollbar — quiet, premium (port from prototype)
|
|
198
|
+
============================================================ */
|
|
199
|
+
::-webkit-scrollbar {
|
|
200
|
+
width: 10px;
|
|
201
|
+
height: 10px;
|
|
202
|
+
}
|
|
203
|
+
::-webkit-scrollbar-track {
|
|
204
|
+
background: transparent;
|
|
205
|
+
}
|
|
206
|
+
::-webkit-scrollbar-thumb {
|
|
207
|
+
background: var(--border);
|
|
208
|
+
border-radius: 6px;
|
|
209
|
+
}
|
|
210
|
+
::-webkit-scrollbar-thumb:hover {
|
|
211
|
+
background: color-mix(in srgb, var(--muted-foreground) 40%, transparent);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* ============================================================
|
|
215
|
+
Focus ring system-wide
|
|
216
|
+
============================================================ */
|
|
217
|
+
:focus-visible {
|
|
218
|
+
outline: 2px solid var(--primary);
|
|
219
|
+
outline-offset: 2px;
|
|
220
|
+
border-radius: 6px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* ============================================================
|
|
224
|
+
Animations — pulse-dot, shimmer-bar (port from prototype)
|
|
225
|
+
============================================================ */
|
|
226
|
+
@keyframes pulse-dot {
|
|
227
|
+
0%, 100% { opacity: 1; }
|
|
228
|
+
50% { opacity: 0.35; }
|
|
229
|
+
}
|
|
230
|
+
.pulse-dot {
|
|
231
|
+
animation: pulse-dot 2s ease-in-out infinite;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@keyframes shimmer {
|
|
235
|
+
0% { transform: translateX(-100%); }
|
|
236
|
+
100% { transform: translateX(100%); }
|
|
237
|
+
}
|
|
238
|
+
.shimmer-bar {
|
|
239
|
+
position: relative;
|
|
240
|
+
overflow: hidden;
|
|
241
|
+
}
|
|
242
|
+
.shimmer-bar::after {
|
|
243
|
+
content: '';
|
|
244
|
+
position: absolute;
|
|
245
|
+
inset: 0;
|
|
246
|
+
background: linear-gradient(
|
|
247
|
+
90deg,
|
|
248
|
+
transparent,
|
|
249
|
+
color-mix(in srgb, var(--primary) 8%, transparent),
|
|
250
|
+
transparent
|
|
251
|
+
);
|
|
252
|
+
animation: shimmer 3s ease-in-out infinite;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* Tabular numerics (port from prototype) */
|
|
256
|
+
.num {
|
|
257
|
+
font-feature-settings: 'tnum' 1, 'cv03' 1;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* ============================================================
|
|
261
|
+
prefers-reduced-motion — kill all transitions + transforms
|
|
262
|
+
============================================================ */
|
|
263
|
+
@media (prefers-reduced-motion: reduce) {
|
|
264
|
+
article,
|
|
265
|
+
[role="alert"],
|
|
266
|
+
tbody tr,
|
|
267
|
+
.log-line,
|
|
268
|
+
ul[class*="divide-y"] > li,
|
|
269
|
+
ol[class*="space-y"] > li,
|
|
270
|
+
.nav-link,
|
|
271
|
+
[data-group-chevron],
|
|
272
|
+
[data-palette-chevron],
|
|
273
|
+
[data-shell="grid"],
|
|
274
|
+
.pulse-dot,
|
|
275
|
+
.shimmer-bar::after {
|
|
276
|
+
transition: none !important;
|
|
277
|
+
transform: none !important;
|
|
278
|
+
animation: none !important;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design tokens (RTGB B7.1-B7.4).
|
|
3
|
+
*
|
|
4
|
+
* OKLCH color space for perceptual uniformity. All semantic colors are
|
|
5
|
+
* exposed as CSS custom properties at :root and overridden in .dark.
|
|
6
|
+
*
|
|
7
|
+
* Tailwind 4 @theme directive maps these to utility classes (e.g.,
|
|
8
|
+
* `bg-background`, `text-foreground`, `border-border`).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
@theme {
|
|
12
|
+
/* ---- Color: surfaces ---- */
|
|
13
|
+
--color-background: oklch(0.99 0.005 264);
|
|
14
|
+
--color-foreground: oklch(0.22 0.018 252);
|
|
15
|
+
|
|
16
|
+
/* ---- Color: primary / brand ---- */
|
|
17
|
+
--color-primary: oklch(0.55 0.18 264);
|
|
18
|
+
--color-primary-fg: oklch(0.99 0 0);
|
|
19
|
+
|
|
20
|
+
/* ---- Color: secondary / muted ---- */
|
|
21
|
+
--color-secondary: oklch(0.96 0.005 252);
|
|
22
|
+
--color-secondary-fg: oklch(0.22 0.018 252);
|
|
23
|
+
--color-muted: oklch(0.96 0.005 252);
|
|
24
|
+
--color-muted-fg: oklch(0.5 0.012 252);
|
|
25
|
+
--color-accent: oklch(0.96 0.005 252);
|
|
26
|
+
--color-accent-fg: oklch(0.22 0.018 252);
|
|
27
|
+
|
|
28
|
+
/* ---- Color: feedback ---- */
|
|
29
|
+
--color-destructive: oklch(0.6 0.22 22);
|
|
30
|
+
--color-destructive-fg: oklch(0.99 0 0);
|
|
31
|
+
--color-success: oklch(0.65 0.16 145);
|
|
32
|
+
--color-success-fg: oklch(0.99 0 0);
|
|
33
|
+
--color-warning: oklch(0.78 0.16 80);
|
|
34
|
+
--color-warning-fg: oklch(0.22 0.018 252);
|
|
35
|
+
--color-info: oklch(0.65 0.16 240);
|
|
36
|
+
--color-info-fg: oklch(0.99 0 0);
|
|
37
|
+
|
|
38
|
+
/* ---- Color: chrome ---- */
|
|
39
|
+
--color-border: oklch(0.92 0.008 252);
|
|
40
|
+
--color-input: oklch(0.92 0.008 252);
|
|
41
|
+
--color-ring: oklch(0.55 0.18 264);
|
|
42
|
+
|
|
43
|
+
/* ---- Typography ---- */
|
|
44
|
+
--font-sans:
|
|
45
|
+
ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
46
|
+
--font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif;
|
|
47
|
+
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
48
|
+
|
|
49
|
+
/* Fluid type scale: clamp(min, preferred, max) */
|
|
50
|
+
--text-xs: clamp(0.7rem, 0.66rem + 0.2vw, 0.78rem);
|
|
51
|
+
--text-sm: clamp(0.82rem, 0.78rem + 0.2vw, 0.9rem);
|
|
52
|
+
--text-base: clamp(0.95rem, 0.9rem + 0.25vw, 1.05rem);
|
|
53
|
+
--text-lg: clamp(1.1rem, 1.04rem + 0.3vw, 1.22rem);
|
|
54
|
+
--text-xl: clamp(1.3rem, 1.22rem + 0.4vw, 1.45rem);
|
|
55
|
+
--text-2xl: clamp(1.55rem, 1.4rem + 0.6vw, 1.8rem);
|
|
56
|
+
--text-3xl: clamp(1.9rem, 1.7rem + 1vw, 2.4rem);
|
|
57
|
+
|
|
58
|
+
/* ---- Radius ---- */
|
|
59
|
+
--radius-xs: 0.25rem;
|
|
60
|
+
--radius-sm: 0.375rem;
|
|
61
|
+
--radius-md: 0.5rem;
|
|
62
|
+
--radius-lg: 0.75rem;
|
|
63
|
+
--radius-xl: 1rem;
|
|
64
|
+
|
|
65
|
+
/* ---- Motion ---- */
|
|
66
|
+
--motion-duration-fast: 120ms;
|
|
67
|
+
--motion-duration-base: 200ms;
|
|
68
|
+
--motion-duration-slow: 320ms;
|
|
69
|
+
--motion-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
70
|
+
--motion-ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
71
|
+
--motion-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* ---- Dark mode overrides ---- */
|
|
75
|
+
.dark {
|
|
76
|
+
--color-background: oklch(0.18 0.02 252);
|
|
77
|
+
--color-foreground: oklch(0.96 0.005 252);
|
|
78
|
+
|
|
79
|
+
--color-primary: oklch(0.7 0.18 264);
|
|
80
|
+
--color-primary-fg: oklch(0.18 0.02 252);
|
|
81
|
+
|
|
82
|
+
--color-secondary: oklch(0.28 0.018 252);
|
|
83
|
+
--color-secondary-fg: oklch(0.96 0.005 252);
|
|
84
|
+
--color-muted: oklch(0.28 0.018 252);
|
|
85
|
+
--color-muted-fg: oklch(0.7 0.012 252);
|
|
86
|
+
--color-accent: oklch(0.32 0.025 252);
|
|
87
|
+
--color-accent-fg: oklch(0.96 0.005 252);
|
|
88
|
+
|
|
89
|
+
--color-destructive: oklch(0.65 0.22 22);
|
|
90
|
+
--color-success: oklch(0.7 0.16 145);
|
|
91
|
+
--color-warning: oklch(0.82 0.16 80);
|
|
92
|
+
--color-info: oklch(0.7 0.16 240);
|
|
93
|
+
|
|
94
|
+
--color-border: oklch(0.32 0.018 252);
|
|
95
|
+
--color-input: oklch(0.32 0.018 252);
|
|
96
|
+
--color-ring: oklch(0.7 0.18 264);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* ---- Reduced motion respect (a11y) ---- */
|
|
100
|
+
@media (prefers-reduced-motion: reduce) {
|
|
101
|
+
*,
|
|
102
|
+
*::before,
|
|
103
|
+
*::after {
|
|
104
|
+
animation-duration: 0.01ms !important;
|
|
105
|
+
animation-iteration-count: 1 !important;
|
|
106
|
+
transition-duration: 0.01ms !important;
|
|
107
|
+
scroll-behavior: auto !important;
|
|
108
|
+
}
|
|
109
|
+
}
|