@viglet/viglet-design-system 2026.3.5 → 2026.3.8

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.
@@ -0,0 +1,167 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <script src="./support.js"></script>
6
+ </head>
7
+ <body>
8
+ <x-dc>
9
+ <helmet>
10
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
11
+ <style>
12
+ body { margin: 0; background: #ffffff; }
13
+ /* Opened straight from the file tree, `x-dc` is an unknown element and so
14
+ lays out inline, and `helmet` would render its own contents as text. The
15
+ canvas runtime replaces both; these two rules only matter for the raw
16
+ open, which is how a reader in this repository will look at it. */
17
+ x-dc { display: block; }
18
+ helmet { display: none; }
19
+ a { color: #1447e6; text-decoration: none; }
20
+ a:hover { color: #193cb8; }
21
+ .vg { font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; }
22
+ .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
23
+ .eyebrow { font-size: 10.5px; font-weight: 600; letter-spacing: 0.09em; }
24
+ .glass { background: rgba(255,255,255,0.72); border: 1px solid rgba(229,229,229,0.7); backdrop-filter: blur(18px) saturate(180%); -webkit-backdrop-filter: blur(18px) saturate(180%); }
25
+ .chip { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 11px; background-image: linear-gradient(to bottom right, #155dfc, #4f39f6); color: #ffffff; flex: 0 0 auto; }
26
+ .field { height: 30px; border: 1px solid #e5e5e5; border-radius: 10px; background: #ffffff; }
27
+ .flabel { font-size: 10px; color: #737373; margin-bottom: 4px; }
28
+ .btn { display: inline-flex; align-items: center; height: 30px; padding: 0 12px; border-radius: 10px; font-size: 12px; font-weight: 500; }
29
+ </style>
30
+ </helmet>
31
+
32
+ <div class="vg" style="position:relative;width:1280px;height:760px;background:#fafafa;color:#0a0a0a;overflow:hidden;display:flex;flex-direction:column">
33
+
34
+ <div style="padding:16px 24px 0">
35
+ <div class="eyebrow" style="color:#1447e6">REFERENCE</div>
36
+ <div style="display:flex;align-items:baseline;gap:12px;margin-top:4px">
37
+ <div style="font-size:21px;font-weight:600;letter-spacing:-0.015em">A detail screen, and the morph</div>
38
+ <div style="font-size:12.5px;color:#737373"><span class="mono" style="font-size:12px">BentoEntityShell</span> wrapping a form. One page, drawn at both ends of the scroll.</div>
39
+ </div>
40
+ </div>
41
+
42
+ <div style="flex:1;min-height:0;display:grid;grid-template-columns:1fr 1fr;gap:20px;padding:14px 24px 0">
43
+
44
+ <!-- at the top -->
45
+ <div style="display:flex;flex-direction:column;gap:9px;min-height:0">
46
+ <div style="display:flex;align-items:center;gap:9px">
47
+ <span class="mono" style="display:inline-flex;align-items:center;height:22px;padding:0 9px;border-radius:999px;background:#f5f5f5;color:#525252;font-size:11px;font-weight:600">--bento-fade: 0</span>
48
+ <span style="font-size:11px;color:#737373">the hero in full force</span>
49
+ </div>
50
+
51
+ <div style="flex:1;min-height:0;border-radius:14px;background:#ffffff;border:1px solid #e5e5e5;padding:16px;overflow:hidden">
52
+ <!-- identity hero: the shell's, never the form's -->
53
+ <div style="position:relative;border:1px dashed rgba(20,71,230,0.4);border-radius:14px;padding:12px;margin-bottom:14px">
54
+ <div class="mono" style="position:absolute;right:9px;top:-8px;background:#ffffff;padding:0 5px;font-size:9px;color:#1447e6">the shell owns this</div>
55
+ <a href="#" style="display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:500;margin-bottom:7px"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M14 6l-6 6 6 6"></path></svg>Collection name</a>
56
+ <div style="display:flex;align-items:flex-start;gap:11px">
57
+ <div class="chip" style="width:40px;height:40px;border-radius:13px"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><circle cx="12" cy="12" r="8"></circle></svg></div>
58
+ <div style="flex:1;min-width:0">
59
+ <div style="font-size:18px;font-weight:600;letter-spacing:-0.015em">Entity name</div>
60
+ <div style="font-size:11.5px;color:#737373;margin-top:2px">Description. Icon, title, description and enabled state are all here.</div>
61
+ </div>
62
+ <div style="display:flex;align-items:center;gap:7px">
63
+ <div style="width:34px;height:19px;border-radius:999px;background:#1447e6;position:relative"><div style="position:absolute;right:2px;top:2px;width:15px;height:15px;border-radius:999px;background:#ffffff"></div></div>
64
+ <div class="btn" style="border:1px solid rgba(251,44,54,0.4);color:#c10007">Delete</div>
65
+ </div>
66
+ </div>
67
+ <div style="display:flex;justify-content:flex-end;gap:7px;margin-top:11px">
68
+ <div class="btn" style="border:1px solid #e5e5e5;color:#404040">Discard</div>
69
+ <div class="btn" style="background:#171717;color:#fafafa">Save changes</div>
70
+ </div>
71
+ </div>
72
+
73
+ <!-- form sections -->
74
+ <div class="glass" style="border-radius:24px;padding:14px;margin-bottom:11px">
75
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:11px">
76
+ <div class="chip" style="width:26px;height:26px;border-radius:9px"></div>
77
+ <div style="font-size:13px;font-weight:600">Field group</div>
78
+ </div>
79
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
80
+ <div><div class="flabel">Label</div><div class="field"></div></div>
81
+ <div><div class="flabel">Label</div><div class="field"></div></div>
82
+ <div style="grid-column:span 2"><div class="flabel">Label</div><div class="field" style="height:52px"></div></div>
83
+ </div>
84
+ </div>
85
+ <div class="glass" style="border-radius:24px;padding:14px">
86
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:11px">
87
+ <div class="chip" style="width:26px;height:26px;border-radius:9px"></div>
88
+ <div style="font-size:13px;font-weight:600">Field group</div>
89
+ </div>
90
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
91
+ <div><div class="flabel">Label</div><div class="field"></div></div>
92
+ <div><div class="flabel">Label</div><div class="field"></div></div>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <div style="font-size:11px;color:#404040;line-height:1.45">The form is a render prop taking <span class="mono" style="font-size:10.5px">{ staged, onStateChange }</span>. It groups fields and nothing else -- no shell mechanics, no identity field.</div>
98
+ </div>
99
+
100
+ <!-- scrolled -->
101
+ <div style="display:flex;flex-direction:column;gap:9px;min-height:0">
102
+ <div style="display:flex;align-items:center;gap:9px">
103
+ <span class="mono" style="display:inline-flex;align-items:center;height:22px;padding:0 9px;border-radius:999px;background:#f5f5f5;color:#525252;font-size:11px;font-weight:600">--bento-fade: 1</span>
104
+ <span style="font-size:11px;color:#737373">the bar settled, and the title gone</span>
105
+ </div>
106
+
107
+ <div style="position:relative;flex:1;min-height:0;border-radius:14px;background:#ffffff;border:1px solid #e5e5e5;padding:16px;overflow:hidden">
108
+ <!-- the hero, faded out -->
109
+ <div style="opacity:0.14;border:1px dashed #d4d4d4;border-radius:14px;padding:12px;margin-bottom:14px;transform:translateY(-8px)">
110
+ <div style="display:flex;align-items:flex-start;gap:11px">
111
+ <div style="width:40px;height:40px;border-radius:13px;background:#e5e5e5"></div>
112
+ <div style="flex:1"><div style="height:16px;width:150px;border-radius:6px;background:#e5e5e5;margin-bottom:5px"></div><div style="height:10px;width:230px;border-radius:999px;background:#efefef"></div></div>
113
+ </div>
114
+ </div>
115
+
116
+ <!-- the fixed bar, faded in -->
117
+ <div class="glass" style="position:absolute;left:16px;right:16px;top:16px;z-index:4;display:flex;align-items:center;gap:11px;border-radius:16px;padding:9px 12px;box-shadow:0 8px 22px -14px rgba(0,0,0,0.45)">
118
+ <div style="width:26px;height:26px;border-radius:9px;background-image:linear-gradient(to bottom right,#155dfc,#4f39f6)"></div>
119
+ <div style="font-size:12.5px;font-weight:500;color:#404040;flex:1">Entity name</div>
120
+ <div class="btn" style="border:1px solid #e5e5e5;color:#404040">Discard</div>
121
+ <div class="btn" style="background:#171717;color:#fafafa">Save changes</div>
122
+ </div>
123
+ <div class="mono" style="position:absolute;right:20px;top:62px;z-index:5;font-size:9px;color:#1447e6">the same two controls, not a second pair</div>
124
+
125
+ <div class="glass" style="border-radius:24px;padding:14px;margin-top:34px;margin-bottom:11px">
126
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:11px">
127
+ <div class="chip" style="width:26px;height:26px;border-radius:9px"></div>
128
+ <div style="font-size:13px;font-weight:600">Field group</div>
129
+ </div>
130
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
131
+ <div><div class="flabel">Label</div><div class="field"></div></div>
132
+ <div><div class="flabel">Label</div><div class="field" style="border-color:rgba(20,71,230,0.6)"></div></div>
133
+ <div style="grid-column:span 2"><div class="flabel">Label</div><div class="field" style="height:52px"></div></div>
134
+ </div>
135
+ </div>
136
+ <div class="glass" style="border-radius:24px;padding:14px">
137
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:11px">
138
+ <div class="chip" style="width:26px;height:26px;border-radius:9px"></div>
139
+ <div style="font-size:13px;font-weight:600">Field group</div>
140
+ </div>
141
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
142
+ <div><div class="flabel">Label</div><div class="field"></div></div>
143
+ <div><div class="flabel">Label</div><div class="field"></div></div>
144
+ </div>
145
+ </div>
146
+ </div>
147
+
148
+ <div style="font-size:11px;color:#404040;line-height:1.45">Notice what is <em>not</em> on the bar: the delete. A controlled dialog rendered in both halves opens two modals, and an action in the fade-out group vanishes as the reader scrolls.</div>
149
+ </div>
150
+ </div>
151
+
152
+ <div style="margin:14px 24px 18px;border:1px solid #e5e5e5;background:#ffffff;border-radius:12px;padding:11px 14px;display:flex;gap:18px;align-items:flex-start">
153
+ <div style="flex:1">
154
+ <div class="eyebrow" style="color:#737373;margin-bottom:4px">IDENTITY LIVES IN THE HERO, NEVER IN THE FORM</div>
155
+ <div style="font-size:12px;color:#404040;line-height:1.5">Title, description, icon and enabled state are the shell's. A form field for any of them is a second place to edit one thing, and the two will disagree about which was saved.</div>
156
+ </div>
157
+ <div style="width:1px;align-self:stretch;background:#ededed"></div>
158
+ <div style="flex:1">
159
+ <div class="eyebrow" style="color:#737373;margin-bottom:4px">THE SAVE BAR IS ALWAYS THE MORPH</div>
160
+ <div style="font-size:12px;color:#404040;line-height:1.5">Controls start in the hero and the fixed bar fades in as the hero leaves, so nothing is duplicated on screen and the bar arrives exactly when the title goes. Never a hand-rolled sticky div, and never a bar that is always there.</div>
161
+ </div>
162
+ </div>
163
+
164
+ </div>
165
+ </x-dc>
166
+ </body>
167
+ </html>
@@ -0,0 +1,135 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <script src="./support.js"></script>
6
+ </head>
7
+ <body>
8
+ <x-dc>
9
+ <helmet>
10
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
11
+ <style>
12
+ body { margin: 0; background: #ffffff; }
13
+ /* Opened straight from the file tree, `x-dc` is an unknown element and so
14
+ lays out inline, and `helmet` would render its own contents as text. The
15
+ canvas runtime replaces both; these two rules only matter for the raw
16
+ open, which is how a reader in this repository will look at it. */
17
+ x-dc { display: block; }
18
+ helmet { display: none; }
19
+ a { color: #1447e6; text-decoration: none; }
20
+ a:hover { color: #193cb8; }
21
+ .vg { font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; }
22
+ .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
23
+ .eyebrow { font-size: 10.5px; font-weight: 600; letter-spacing: 0.09em; }
24
+ .glass { background: rgba(255,255,255,0.72); border: 1px solid rgba(229,229,229,0.7); backdrop-filter: blur(18px) saturate(180%); -webkit-backdrop-filter: blur(18px) saturate(180%); }
25
+ .chip { display: flex; align-items: center; justify-content: center; border-radius: 11px; background-image: linear-gradient(to bottom right, #155dfc, #4f39f6); color: #ffffff; flex: 0 0 auto; }
26
+ .field { height: 30px; border: 1px solid #e5e5e5; border-radius: 10px; background: #ffffff; }
27
+ .flabel { font-size: 10px; color: #737373; margin-bottom: 4px; }
28
+ .btn { display: inline-flex; align-items: center; height: 30px; padding: 0 12px; border-radius: 10px; font-size: 12px; font-weight: 500; }
29
+ </style>
30
+ </helmet>
31
+
32
+ <div class="vg" style="position:relative;width:1080px;height:680px;background:#fafafa;color:#0a0a0a;overflow:hidden;display:flex;flex-direction:column">
33
+
34
+ <div style="padding:16px 24px 0">
35
+ <div class="eyebrow" style="color:#1447e6">REFERENCE</div>
36
+ <div style="display:flex;align-items:baseline;gap:12px;margin-top:4px">
37
+ <div style="font-size:21px;font-weight:600;letter-spacing:-0.015em">A form screen with its own hero</div>
38
+ <div style="font-size:12.5px;color:#737373"><span class="mono" style="font-size:12px">BentoFormHero</span> as the first child inside the <span class="mono" style="font-size:12px">form</span> it submits.</div>
39
+ </div>
40
+ </div>
41
+
42
+ <div style="flex:1;min-height:0;display:grid;grid-template-columns:1.15fr 1fr;gap:20px;padding:14px 24px 0">
43
+
44
+ <!-- the page -->
45
+ <div style="display:flex;flex-direction:column;gap:9px;min-height:0">
46
+ <div style="position:relative;flex:1;min-height:0;border-radius:14px;background:#ffffff;border:1px solid #e5e5e5;padding:16px;overflow:hidden">
47
+
48
+ <div class="mono" style="position:absolute;left:16px;top:8px;font-size:9px;color:#a1a1a1">&lt;form&gt;</div>
49
+
50
+ <div style="border:1px dashed rgba(20,71,230,0.4);border-radius:14px;padding:12px;margin:14px 0;position:relative">
51
+ <div class="mono" style="position:absolute;right:9px;top:-8px;background:#ffffff;padding:0 5px;font-size:9px;color:#1447e6">BentoFormHero -- first child</div>
52
+ <div style="display:flex;align-items:flex-start;gap:11px">
53
+ <div class="chip" style="width:40px;height:40px;border-radius:13px"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"><path d="M5 12h14M12 5v14"></path></svg></div>
54
+ <div style="flex:1;min-width:0">
55
+ <div style="font-size:10px;color:#737373;letter-spacing:0.05em;font-weight:600">EYEBROW</div>
56
+ <div style="font-size:18px;font-weight:600;letter-spacing:-0.015em;margin-top:2px">New entity</div>
57
+ <div style="font-size:11.5px;color:#737373;margin-top:2px">A form with no entity behind it yet, so the hero is the form's.</div>
58
+ </div>
59
+ <div style="display:flex;align-items:center;gap:7px">
60
+ <div class="btn" style="border:1px solid #e5e5e5;color:#404040">Cancel</div>
61
+ <div class="btn" style="background:#171717;color:#fafafa">Create</div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+
66
+ <div class="glass" style="border-radius:24px;padding:14px;margin-bottom:11px">
67
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:11px">
68
+ <div class="chip" style="width:26px;height:26px;border-radius:9px"></div>
69
+ <div style="font-size:13px;font-weight:600">Field group</div>
70
+ </div>
71
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
72
+ <div><div class="flabel">Label</div><div class="field"></div></div>
73
+ <div><div class="flabel">Label</div><div class="field"></div></div>
74
+ <div style="grid-column:span 2"><div class="flabel">Label</div><div class="field" style="height:48px"></div></div>
75
+ </div>
76
+ </div>
77
+ <div class="glass" style="border-radius:24px;padding:14px">
78
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:11px">
79
+ <div class="chip" style="width:26px;height:26px;border-radius:9px"></div>
80
+ <div style="font-size:13px;font-weight:600">Field group</div>
81
+ </div>
82
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
83
+ <div><div class="flabel">Label</div><div class="field"></div></div>
84
+ <div><div class="flabel">Label</div><div class="field"></div></div>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ </div>
89
+
90
+ <!-- the rules -->
91
+ <div style="display:flex;flex-direction:column;gap:11px;min-height:0">
92
+
93
+ <div style="border:1px solid #e5e5e5;background:#ffffff;border-radius:14px;padding:13px">
94
+ <div class="eyebrow" style="color:#737373;margin-bottom:7px">IT RENDERS BOTH HALVES ITSELF</div>
95
+ <div style="font-size:11.5px;color:#404040;line-height:1.5;margin-bottom:11px">Do not compose a fade-out control group and a scroll save bar by hand. They are two halves of one thing and they drift.</div>
96
+ <div style="display:flex;flex-direction:column;gap:7px">
97
+ <div style="border:1px solid #ededed;border-radius:10px;padding:8px 10px;display:flex;align-items:center;gap:8px">
98
+ <span class="mono" style="font-size:9.5px;color:#a1a1a1;width:34px">fade 0</span>
99
+ <div style="flex:1;height:8px;border-radius:999px;background:#ededed"></div>
100
+ <div style="width:44px;height:16px;border-radius:5px;background:#171717"></div>
101
+ </div>
102
+ <div style="border:1px solid #ededed;border-radius:10px;padding:8px 10px;display:flex;align-items:center;gap:8px;background:#fafafa">
103
+ <span class="mono" style="font-size:9.5px;color:#a1a1a1;width:34px">fade 1</span>
104
+ <div style="flex:1;height:8px;border-radius:999px;background:#f5f5f5"></div>
105
+ <div style="width:44px;height:16px;border-radius:5px;background:#171717"></div>
106
+ </div>
107
+ </div>
108
+ </div>
109
+
110
+ <div style="border:1px solid #e5e5e5;background:#ffffff;border-radius:14px;padding:13px">
111
+ <div class="eyebrow" style="color:#737373;margin-bottom:7px">A PAGE THAT SAVES IMPERATIVELY</div>
112
+ <div style="font-size:11.5px;color:#404040;line-height:1.5">Pass your own buttons through <span class="mono" style="font-size:11px">actions</span>. That replaces the default pair in <em>both</em> copies and keeps the morph -- which adding a button beside the hero would not.</div>
113
+ <div style="display:flex;gap:6px;margin-top:9px">
114
+ <div class="btn" style="border:1px solid #e5e5e5;color:#404040;height:26px;font-size:11px">Validate</div>
115
+ <div class="btn" style="border:1px solid #e5e5e5;color:#404040;height:26px;font-size:11px">Dry run</div>
116
+ <div class="btn" style="background:#171717;color:#fafafa;height:26px;font-size:11px">Run</div>
117
+ </div>
118
+ </div>
119
+
120
+ <div style="border:1px solid rgba(251,44,54,0.3);background:rgba(251,44,54,0.05);border-radius:14px;padding:13px">
121
+ <div class="eyebrow" style="color:#c10007;margin-bottom:5px">AND THE DESTRUCTIVE ONE STAYS OUT</div>
122
+ <div style="font-size:11.5px;color:#404040;line-height:1.5">Keep it in the hero's <span class="mono" style="font-size:11px">trailing</span> only. In both halves it opens two dialogs at once; in the fade-out group it disappears as the reader scrolls.</div>
123
+ </div>
124
+
125
+ <div style="flex:1"></div>
126
+
127
+ <div style="font-size:11px;color:#737373;line-height:1.45">The other shape is <span class="mono" style="font-size:10.5px">BentoEntityShell</span>, which owns the hero for you. Reach for this one only when there is no entity yet.</div>
128
+ </div>
129
+ </div>
130
+
131
+ <div style="height:18px"></div>
132
+ </div>
133
+ </x-dc>
134
+ </body>
135
+ </html>
@@ -0,0 +1,140 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <script src="./support.js"></script>
6
+ </head>
7
+ <body>
8
+ <x-dc>
9
+ <helmet>
10
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
11
+ <style>
12
+ body { margin: 0; background: #ffffff; }
13
+ /* Opened straight from the file tree, `x-dc` is an unknown element and so
14
+ lays out inline, and `helmet` would render its own contents as text. The
15
+ canvas runtime replaces both; these two rules only matter for the raw
16
+ open, which is how a reader in this repository will look at it. */
17
+ x-dc { display: block; }
18
+ helmet { display: none; }
19
+ a { color: #1447e6; text-decoration: none; }
20
+ a:hover { color: #193cb8; }
21
+ .vg { font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; }
22
+ .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
23
+ .eyebrow { font-size: 10.5px; font-weight: 600; letter-spacing: 0.09em; }
24
+ .ratio { display: inline-flex; align-items: center; height: 18px; padding: 0 7px; border-radius: 5px; font-size: 9.5px; font-weight: 700; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
25
+ .pass { border: 1px solid rgba(0,188,125,0.4); background: rgba(0,188,125,0.1); color: #007a55; }
26
+ .passd { border: 1px solid rgba(0,188,125,0.4); background: rgba(0,188,125,0.1); color: #00d492; }
27
+ </style>
28
+ </helmet>
29
+
30
+ <div class="vg" style="position:relative;width:1180px;height:700px;background:#fafafa;color:#0a0a0a;overflow:hidden;display:flex;flex-direction:column">
31
+
32
+ <div style="padding:16px 24px 0">
33
+ <div class="eyebrow" style="color:#1447e6">REFERENCE</div>
34
+ <div style="display:flex;align-items:baseline;gap:12px;margin-top:4px">
35
+ <div style="font-size:21px;font-weight:600;letter-spacing:-0.015em">Both grounds, and nothing told by colour alone</div>
36
+ <div style="font-size:12.5px;color:#737373">The same components twice. Every state carries a dot or a word as well as a hue.</div>
37
+ </div>
38
+ </div>
39
+
40
+ <div style="flex:1;min-height:0;display:grid;grid-template-columns:1fr 1fr;gap:18px;padding:14px 24px 0">
41
+
42
+ <!-- LIGHT -->
43
+ <div style="border:1px solid #e5e5e5;border-radius:14px;background:#ffffff;padding:15px;display:flex;flex-direction:column;gap:12px;overflow:hidden">
44
+ <div style="display:flex;align-items:center;gap:9px">
45
+ <span class="eyebrow" style="color:#737373">LIGHT</span>
46
+ <span class="mono" style="font-size:10px;color:#a1a1a1">--vg-background oklch(1 0 0)</span>
47
+ </div>
48
+
49
+ <div style="border:1px solid #e5e5e5;border-radius:16px;padding:12px">
50
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:6px">
51
+ <div style="width:26px;height:26px;border-radius:9px;background-image:linear-gradient(to bottom right,#155dfc,#4f39f6)"></div>
52
+ <div style="font-size:13px;font-weight:600;color:#0a0a0a">Entity name</div>
53
+ <div style="flex:1"></div>
54
+ <span class="ratio pass">19.8:1</span>
55
+ </div>
56
+ <div style="font-size:11.5px;color:#737373;line-height:1.45">A line of muted description, which is the pair a panel is most likely to reach for.</div>
57
+ <div style="display:flex;align-items:center;gap:7px;margin-top:7px"><span class="ratio pass">4.73:1</span><span style="font-size:10px;color:#737373">muted on the ground</span></div>
58
+ </div>
59
+
60
+ <div>
61
+ <div class="eyebrow" style="color:#737373;margin-bottom:7px">STATUS -- A DOT AND A WORD</div>
62
+ <div style="display:flex;flex-wrap:wrap;gap:6px">
63
+ <span style="display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(0,188,125,0.4);background:rgba(0,188,125,0.1);color:#007a55;font-size:11px;font-weight:600"><span style="width:6px;height:6px;border-radius:999px;background:#00bc7d"></span>On</span>
64
+ <span style="display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(254,154,0,0.4);background:rgba(254,154,0,0.1);color:#973c00;font-size:11px;font-weight:600"><span style="width:6px;height:6px;border-radius:999px;background:#fe9a00"></span>Warn</span>
65
+ <span style="display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(251,44,54,0.4);background:rgba(251,44,54,0.1);color:#c10007;font-size:11px;font-weight:600"><span style="width:6px;height:6px;border-radius:999px;background:#fb2c36"></span>Error</span>
66
+ </div>
67
+ <div style="font-size:10px;color:#737373;margin-top:6px">Tinted surfaces take the darker text token here, which is the whole reason there are two.</div>
68
+ </div>
69
+
70
+ <div>
71
+ <div class="eyebrow" style="color:#737373;margin-bottom:7px">THE ACCENT, AND THE FOCUS RING</div>
72
+ <div style="display:flex;align-items:center;gap:9px">
73
+ <div style="display:inline-flex;align-items:center;height:32px;padding:0 13px;border-radius:10px;background:#1447e6;color:#ffffff;font-size:12.5px;font-weight:500">Primary</div>
74
+ <div style="display:inline-flex;align-items:center;height:32px;padding:0 13px;border-radius:10px;border:1px solid #e5e5e5;color:#0a0a0a;font-size:12.5px;font-weight:500;box-shadow:0 0 0 3px rgba(20,71,230,0.35)">Focused</div>
75
+ <span class="ratio pass">6.83:1</span>
76
+ </div>
77
+ </div>
78
+
79
+ <div style="flex:1"></div>
80
+ <div style="font-size:11px;color:#404040;line-height:1.45">Contrast holds at 4.5:1 for text and 3:1 for a focus indicator. The catalogue's stories run under axe on every push, so a violation is a failing build.</div>
81
+ </div>
82
+
83
+ <!-- DARK -->
84
+ <div style="border:1px solid rgba(255,255,255,0.14);border-radius:14px;background:#171717;color:#dedede;padding:15px;display:flex;flex-direction:column;gap:12px;overflow:hidden">
85
+ <div style="display:flex;align-items:center;gap:9px">
86
+ <span class="eyebrow" style="color:#ababab">DARK</span>
87
+ <span class="mono" style="font-size:10px;color:#8a8a8a">--vg-background oklch(0.205 0 0)</span>
88
+ </div>
89
+
90
+ <div style="border:1px solid rgba(255,255,255,0.14);border-radius:16px;padding:12px;background:#262626">
91
+ <div style="display:flex;align-items:center;gap:9px;margin-bottom:6px">
92
+ <div style="width:26px;height:26px;border-radius:9px;background-image:linear-gradient(to bottom right,#155dfc,#4f39f6)"></div>
93
+ <div style="font-size:13px;font-weight:600;color:#dedede">Entity name</div>
94
+ <div style="flex:1"></div>
95
+ <span class="ratio passd">13.3:1</span>
96
+ </div>
97
+ <div style="font-size:11.5px;color:#ababab;line-height:1.45">A line of muted description, which is the pair a panel is most likely to reach for.</div>
98
+ <div style="display:flex;align-items:center;gap:7px;margin-top:7px"><span class="ratio passd">6.79:1</span><span style="font-size:10px;color:#8a8a8a">muted on a card</span></div>
99
+ </div>
100
+
101
+ <div>
102
+ <div class="eyebrow" style="color:#ababab;margin-bottom:7px">STATUS -- A DOT AND A WORD</div>
103
+ <div style="display:flex;flex-wrap:wrap;gap:6px">
104
+ <span style="display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(0,188,125,0.4);background:rgba(0,188,125,0.1);color:#00d492;font-size:11px;font-weight:600"><span style="width:6px;height:6px;border-radius:999px;background:#00bc7d"></span>On</span>
105
+ <span style="display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(254,154,0,0.4);background:rgba(254,154,0,0.1);color:#fdc700;font-size:11px;font-weight:600"><span style="width:6px;height:6px;border-radius:999px;background:#fe9a00"></span>Warn</span>
106
+ <span style="display:inline-flex;align-items:center;gap:6px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(251,44,54,0.4);background:rgba(251,44,54,0.1);color:#ff6467;font-size:11px;font-weight:600"><span style="width:6px;height:6px;border-radius:999px;background:#fb2c36"></span>Error</span>
107
+ </div>
108
+ <div style="font-size:10px;color:#8a8a8a;margin-top:6px">Same marks, lighter text. The mark is the token that does not move between grounds.</div>
109
+ </div>
110
+
111
+ <div>
112
+ <div class="eyebrow" style="color:#ababab;margin-bottom:7px">THE ACCENT, AND THE FOCUS RING</div>
113
+ <div style="display:flex;align-items:center;gap:9px">
114
+ <div style="display:inline-flex;align-items:center;height:32px;padding:0 13px;border-radius:10px;background:#51a2ff;color:#171717;font-size:12.5px;font-weight:500">Primary</div>
115
+ <div style="display:inline-flex;align-items:center;height:32px;padding:0 13px;border-radius:10px;border:1px solid rgba(255,255,255,0.34);color:#dedede;font-size:12.5px;font-weight:500;box-shadow:0 0 0 3px rgba(81,162,255,0.4)">Focused</div>
116
+ <span class="ratio passd">6.79:1</span>
117
+ </div>
118
+ </div>
119
+
120
+ <div style="flex:1"></div>
121
+ <div style="font-size:11px;color:#ababab;line-height:1.45">The dark surfaces sit a step above black on purpose: near-black under near-white overshoots AAA and the glyphs bloom at the edges.</div>
122
+ </div>
123
+ </div>
124
+
125
+ <div style="margin:14px 24px 18px;border:1px solid #e5e5e5;background:#ffffff;border-radius:12px;padding:11px 14px;display:flex;gap:18px;align-items:flex-start">
126
+ <div style="flex:1">
127
+ <div class="eyebrow" style="color:#737373;margin-bottom:4px">THE ACCENT IS THE SAME RATIO ON BOTH GROUNDS</div>
128
+ <div style="font-size:12px;color:#404040;line-height:1.5">6.83 and 6.79. That is not luck -- it is what the two readable inputs are for. A product that states one accent value and lets the other ground inherit gets one of these numbers and not the other.</div>
129
+ </div>
130
+ <div style="width:1px;align-self:stretch;background:#ededed"></div>
131
+ <div style="width:340px">
132
+ <div class="eyebrow" style="color:#737373;margin-bottom:4px">A STATE IS NEVER ONLY A HUE</div>
133
+ <div style="font-size:12px;color:#404040;line-height:1.5">Every pill above carries a dot and a word. A reader who cannot separate the three hues still reads three states.</div>
134
+ </div>
135
+ </div>
136
+
137
+ </div>
138
+ </x-dc>
139
+ </body>
140
+ </html>
@@ -0,0 +1,147 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <script src="./support.js"></script>
6
+ </head>
7
+ <body>
8
+ <x-dc>
9
+ <helmet>
10
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap">
11
+ <style>
12
+ body { margin: 0; background: #ffffff; }
13
+ /* Opened straight from the file tree, `x-dc` is an unknown element and so
14
+ lays out inline, and `helmet` would render its own contents as text. The
15
+ canvas runtime replaces both; these two rules only matter for the raw
16
+ open, which is how a reader in this repository will look at it. */
17
+ x-dc { display: block; }
18
+ helmet { display: none; }
19
+ a { color: #1447e6; text-decoration: none; }
20
+ a:hover { color: #193cb8; }
21
+ .vg { font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-font-smoothing: antialiased; }
22
+ .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
23
+ .eyebrow { font-size: 10.5px; font-weight: 600; letter-spacing: 0.09em; }
24
+ .glass { background: rgba(255,255,255,0.72); border: 1px solid rgba(229,229,229,0.7); backdrop-filter: blur(18px) saturate(180%); -webkit-backdrop-filter: blur(18px) saturate(180%); }
25
+ .chip { display: flex; align-items: center; justify-content: center; width: 34px; height: 34px; border-radius: 11px; background-image: linear-gradient(to bottom right, #155dfc, #4f39f6); color: #ffffff; flex: 0 0 auto; }
26
+ .pill { display: inline-flex; align-items: center; gap: 5px; height: 19px; padding: 0 7px; border-radius: 999px; border: 1px solid rgba(0,188,125,0.4); background: rgba(0,188,125,0.1); color: #007a55; font-size: 10px; font-weight: 600; }
27
+ .row { display: grid; grid-template-columns: 1fr 92px 74px 60px; gap: 12px; align-items: center; padding: 7px 14px; border-bottom: 1px solid #f4f4f4; font-size: 11.5px; }
28
+ </style>
29
+ </helmet>
30
+
31
+ <div class="vg" style="position:relative;width:1280px;height:720px;background:#fafafa;color:#0a0a0a;overflow:hidden;display:flex;flex-direction:column">
32
+
33
+ <div style="padding:16px 24px 0">
34
+ <div class="eyebrow" style="color:#1447e6">REFERENCE</div>
35
+ <div style="display:flex;align-items:baseline;gap:12px;margin-top:4px">
36
+ <div style="font-size:21px;font-weight:600;letter-spacing:-0.015em">A list screen, and when it is not tiles</div>
37
+ <div style="font-size:12.5px;color:#737373">One <span class="mono" style="font-size:12px">BentoListPage</span> call with a <span class="mono" style="font-size:12px">renderTile</span>. The same entities, twice.</div>
38
+ </div>
39
+ </div>
40
+
41
+ <div style="flex:1;min-height:0;display:grid;grid-template-columns:1fr 1fr;gap:20px;padding:14px 24px 0">
42
+
43
+ <!-- tiles -->
44
+ <div style="display:flex;flex-direction:column;gap:9px;min-height:0">
45
+ <div style="display:flex;align-items:center;gap:9px">
46
+ <span style="display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(20,71,230,0.4);background:rgba(20,71,230,0.08);color:#1447e6;font-size:11px;font-weight:600">arrive to pick one</span>
47
+ <span class="mono" style="font-size:10.5px;color:#737373">BentoEntityTile</span>
48
+ </div>
49
+
50
+ <div style="flex:1;min-height:0;border-radius:14px;background:#ffffff;border:1px solid #e5e5e5;padding:16px;overflow:hidden">
51
+ <!-- hero -->
52
+ <div style="display:flex;align-items:flex-start;gap:12px;margin-bottom:16px">
53
+ <div class="chip" style="width:42px;height:42px;border-radius:13px"><svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><rect x="4" y="4" width="7" height="7" rx="2"></rect><rect x="13" y="4" width="7" height="7" rx="2"></rect><rect x="4" y="13" width="7" height="7" rx="2"></rect></svg></div>
54
+ <div style="flex:1;min-width:0">
55
+ <div style="font-size:10px;color:#737373;letter-spacing:0.05em;font-weight:600">EYEBROW</div>
56
+ <div style="font-size:19px;font-weight:600;letter-spacing:-0.015em;margin-top:2px">Collection name</div>
57
+ <div style="font-size:11.5px;color:#737373;margin-top:2px">One sentence of subtitle, which the shell does not own.</div>
58
+ </div>
59
+ <div style="display:inline-flex;align-items:center;height:30px;padding:0 12px;border-radius:10px;background:#171717;color:#fafafa;font-size:12px;font-weight:500">New</div>
60
+ </div>
61
+
62
+ <!-- mosaic: spans in multiples of two -->
63
+ <div style="display:grid;grid-template-columns:repeat(6, minmax(0, 1fr));gap:11px">
64
+ <div class="glass" style="grid-column:span 4;border-radius:24px;padding:13px;display:flex;flex-direction:column;gap:8px;height:118px">
65
+ <div class="chip"></div>
66
+ <div style="font-size:12.5px;font-weight:600">Entity name</div>
67
+ <div style="font-size:10.5px;color:#737373;line-height:1.35">Description, two lines at most, from the entity itself.</div>
68
+ <div style="flex:1"></div>
69
+ <div><span class="pill"><span style="width:5px;height:5px;border-radius:999px;background:#00bc7d"></span>Status</span></div>
70
+ </div>
71
+ <div class="glass" style="grid-column:span 2;border-radius:24px;padding:13px;display:flex;flex-direction:column;gap:7px;height:118px">
72
+ <div class="chip"></div>
73
+ <div style="font-size:12.5px;font-weight:600">Entity name</div>
74
+ <div style="flex:1"></div>
75
+ <div style="font-size:10px;color:#737373">Meta</div>
76
+ </div>
77
+ <div class="glass" style="grid-column:span 2;border-radius:24px;padding:13px;display:flex;flex-direction:column;gap:7px;height:104px">
78
+ <div class="chip" style="width:28px;height:28px;border-radius:9px"></div>
79
+ <div style="font-size:12px;font-weight:600">Entity name</div>
80
+ <div style="flex:1"></div>
81
+ <div style="font-size:10px;color:#737373">Meta</div>
82
+ </div>
83
+ <div class="glass" style="grid-column:span 2;border-radius:24px;padding:13px;display:flex;flex-direction:column;gap:7px;height:104px">
84
+ <div class="chip" style="width:28px;height:28px;border-radius:9px"></div>
85
+ <div style="font-size:12px;font-weight:600">Entity name</div>
86
+ <div style="flex:1"></div>
87
+ <div style="font-size:10px;color:#737373">Meta</div>
88
+ </div>
89
+ <div style="grid-column:span 2;border-radius:24px;height:104px;border:1px dashed #d4d4d4;display:flex;align-items:center;justify-content:center;color:#a1a1a1;font-size:11.5px">New</div>
90
+ </div>
91
+ </div>
92
+
93
+ <div style="font-size:11px;color:#404040;line-height:1.45">Spans in multiples of two, so the mosaic reflows without a gap at every breakpoint. The dashed tile is the one affordance the grid adds.</div>
94
+ </div>
95
+
96
+ <!-- rows -->
97
+ <div style="display:flex;flex-direction:column;gap:9px;min-height:0">
98
+ <div style="display:flex;align-items:center;gap:9px">
99
+ <span style="display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 9px;border-radius:999px;border:1px solid rgba(254,154,0,0.45);background:rgba(254,154,0,0.1);color:#973c00;font-size:11px;font-weight:600">arrive to compare many</span>
100
+ <span class="mono" style="font-size:10.5px;color:#737373">a table inside BentoPanel, contentClassName p-0</span>
101
+ </div>
102
+
103
+ <div style="flex:1;min-height:0;border-radius:14px;background:#ffffff;border:1px solid #e5e5e5;padding:16px;overflow:hidden">
104
+ <div style="display:flex;align-items:flex-start;gap:12px;margin-bottom:16px">
105
+ <div class="chip" style="width:42px;height:42px;border-radius:13px"><svg width="21" height="21" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M9 6h11M9 12h11M9 18h11"></path><path d="M4.5 6h.01M4.5 12h.01M4.5 18h.01"></path></svg></div>
106
+ <div style="flex:1;min-width:0">
107
+ <div style="font-size:10px;color:#737373;letter-spacing:0.05em;font-weight:600">EYEBROW</div>
108
+ <div style="font-size:19px;font-weight:600;letter-spacing:-0.015em;margin-top:2px">Collection name</div>
109
+ <div style="font-size:11.5px;color:#737373;margin-top:2px">The same hero. Only what sits under it changed.</div>
110
+ </div>
111
+ <div style="display:inline-flex;align-items:center;height:30px;padding:0 12px;border-radius:10px;background:#171717;color:#fafafa;font-size:12px;font-weight:500">New</div>
112
+ </div>
113
+
114
+ <div class="glass" style="border-radius:24px;overflow:hidden">
115
+ <div class="row" style="background:rgba(245,245,245,0.6);font-size:9.5px;font-weight:600;letter-spacing:0.06em;color:#737373;border-bottom:1px solid #ededed">
116
+ <div>ENTITY</div><div>META</div><div>STATUS</div><div></div>
117
+ </div>
118
+ <div class="row"><div>Entity name</div><div style="color:#737373">Meta</div><div><span class="pill"><span style="width:5px;height:5px;border-radius:999px;background:#00bc7d"></span>On</span></div><div style="color:#a1a1a1">…</div></div>
119
+ <div class="row"><div>Entity name</div><div style="color:#737373">Meta</div><div><span class="pill"><span style="width:5px;height:5px;border-radius:999px;background:#00bc7d"></span>On</span></div><div style="color:#a1a1a1">…</div></div>
120
+ <div class="row"><div>Entity name</div><div style="color:#737373">Meta</div><div><span class="pill" style="border-color:rgba(254,154,0,0.4);background:rgba(254,154,0,0.1);color:#973c00"><span style="width:5px;height:5px;border-radius:999px;background:#fe9a00"></span>Warn</span></div><div style="color:#a1a1a1">…</div></div>
121
+ <div class="row"><div>Entity name</div><div style="color:#737373">Meta</div><div><span class="pill"><span style="width:5px;height:5px;border-radius:999px;background:#00bc7d"></span>On</span></div><div style="color:#a1a1a1">…</div></div>
122
+ <div class="row"><div>Entity name</div><div style="color:#737373">Meta</div><div><span class="pill"><span style="width:5px;height:5px;border-radius:999px;background:#00bc7d"></span>On</span></div><div style="color:#a1a1a1">…</div></div>
123
+ <div class="row"><div>Entity name</div><div style="color:#737373">Meta</div><div><span class="pill"><span style="width:5px;height:5px;border-radius:999px;background:#00bc7d"></span>On</span></div><div style="color:#a1a1a1">…</div></div>
124
+ <div class="row" style="border-bottom:none"><div>Entity name</div><div style="color:#737373">Meta</div><div><span class="pill"><span style="width:5px;height:5px;border-radius:999px;background:#00bc7d"></span>On</span></div><div style="color:#a1a1a1">…</div></div>
125
+ </div>
126
+ </div>
127
+
128
+ <div style="font-size:11px;color:#404040;line-height:1.45">Still the layer: the hero is the hero, the frosted surface is the panel, the pills are the same intents. Density did not mean leaving.</div>
129
+ </div>
130
+ </div>
131
+
132
+ <div style="margin:14px 24px 18px;border:1px solid #e5e5e5;background:#ffffff;border-radius:12px;padding:11px 14px;display:flex;gap:18px;align-items:flex-start">
133
+ <div style="flex:1">
134
+ <div class="eyebrow" style="color:#737373;margin-bottom:4px">THE DISCRIMINATOR</div>
135
+ <div style="font-size:12px;color:#404040;line-height:1.5">Does the reader arrive to <strong>pick one</strong>, or to <strong>compare many</strong>? Picking is tiles: the chip carries identity, the span carries weight, and eight of them fill a screen. Comparing is rows: the eye runs down a column, and a tile that has to be scanned against six others is a tile the reader is fighting.</div>
136
+ </div>
137
+ <div style="width:1px;align-self:stretch;background:#ededed"></div>
138
+ <div style="width:340px">
139
+ <div class="eyebrow" style="color:#737373;margin-bottom:4px">WHY IT IS WORTH SAYING</div>
140
+ <div style="font-size:12px;color:#404040;line-height:1.5">Without it, density reads as a reason to drop out of the layer and hand-roll a card and a table -- which is how one product ends up with two eras of chrome on one screen.</div>
141
+ </div>
142
+ </div>
143
+
144
+ </div>
145
+ </x-dc>
146
+ </body>
147
+ </html>