sonance-brand-mcp 1.4.3 → 1.4.7
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/dist/assets/BRAND_GUIDELINES.md +2 -2
- package/dist/assets/brand-system.ts +2 -2
- package/dist/assets/components/theme-toggle.tsx +7 -7
- package/dist/assets/dataviz/index.json +17 -0
- package/dist/assets/dataviz/teal-ignition.json +196 -0
- package/dist/assets/globals.css +448 -31
- package/dist/assets/logo-manifest.json +3 -0
- package/dist/assets/logos/sonance/Sonance_Beam_Fade_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Beam_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Beam_RGB.svg +13 -0
- package/dist/assets/logos-optimized/sonance/Sonance_Beam_Fade_RGB.png +0 -0
- package/dist/assets/logos-optimized/sonance/Sonance_Beam_RGB.png +0 -0
- package/dist/assets/logos-optimized/sonance/Sonance_Beam_RGB.svg +13 -0
- package/dist/assets/motion/index.json +5 -0
- package/dist/assets/motion/sonance-logo-amber.json +19 -0
- package/dist/assets/sections.json +5 -0
- package/dist/assets/styles/brand-overrides.css +1 -1
- package/dist/bloom-assets.d.ts +68 -0
- package/dist/bloom-assets.js +207 -0
- package/dist/index.js +14 -7
- package/package.json +1 -1
|
@@ -71,8 +71,8 @@ font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-s
|
|
|
71
71
|
| Black | `#000000` | `--sonance-black` | `bg-sonance-black` | Text on light backgrounds |
|
|
72
72
|
|
|
73
73
|
**Print Specifications** (for reference):
|
|
74
|
-
- Charcoal: Pantone 7545 C, CMYK
|
|
75
|
-
- The Beam: Pantone 3262 C, CMYK
|
|
74
|
+
- Charcoal: Pantone 7545 C, CMYK 65/43/26/78, RAL 7024
|
|
75
|
+
- The Beam: Pantone 3262 C, CMYK 82/11/0/0
|
|
76
76
|
|
|
77
77
|
### Gray Scale (derived from Charcoal)
|
|
78
78
|
| Level | Hex | CSS Variable |
|
|
@@ -115,8 +115,8 @@ export const brandPresets: BrandPreset[] = [
|
|
|
115
115
|
|
|
116
116
|
export const brandLogos: Record<BrandId, BrandLogos> = {
|
|
117
117
|
sonance: {
|
|
118
|
-
light: '/logos/sonance
|
|
119
|
-
dark: '/logos/sonance
|
|
118
|
+
light: '/logos/sonance/Sonance_Logo_2C_Dark_RGB.png',
|
|
119
|
+
dark: '/logos/sonance/Sonance_Logo_2C_Light_RGB.png',
|
|
120
120
|
alt: 'Sonance',
|
|
121
121
|
},
|
|
122
122
|
iport: {
|
|
@@ -16,36 +16,36 @@ export function ThemeToggle({ className }: { className?: string }) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
|
-
<div data-sonance-name="theme-toggle" className={cn("flex items-center gap-1 p-1 bg-background-secondary rounded-sm", className)}>
|
|
19
|
+
<div data-sonance-name="theme-toggle" className={cn("flex items-center gap-1 p-1 bg-background-secondary rounded-sm theme-toggle-container", className)}>
|
|
20
20
|
<button
|
|
21
21
|
onClick={() => setTheme("light")}
|
|
22
22
|
className={cn(
|
|
23
|
-
"
|
|
23
|
+
"theme-toggle-btn",
|
|
24
24
|
theme === "light" ? "bg-background text-foreground" : "text-foreground-muted hover:text-foreground"
|
|
25
25
|
)}
|
|
26
26
|
aria-label="Light mode"
|
|
27
27
|
>
|
|
28
|
-
<Sun className="
|
|
28
|
+
<Sun className="theme-toggle-icon" />
|
|
29
29
|
</button>
|
|
30
30
|
<button
|
|
31
31
|
onClick={() => setTheme("dark")}
|
|
32
32
|
className={cn(
|
|
33
|
-
"
|
|
33
|
+
"theme-toggle-btn",
|
|
34
34
|
theme === "dark" ? "bg-background text-foreground" : "text-foreground-muted hover:text-foreground"
|
|
35
35
|
)}
|
|
36
36
|
aria-label="Dark mode"
|
|
37
37
|
>
|
|
38
|
-
<Moon className="
|
|
38
|
+
<Moon className="theme-toggle-icon" />
|
|
39
39
|
</button>
|
|
40
40
|
<button
|
|
41
41
|
onClick={() => setTheme("system")}
|
|
42
42
|
className={cn(
|
|
43
|
-
"
|
|
43
|
+
"theme-toggle-btn",
|
|
44
44
|
theme === "system" ? "bg-background text-foreground" : "text-foreground-muted hover:text-foreground"
|
|
45
45
|
)}
|
|
46
46
|
aria-label="System theme"
|
|
47
47
|
>
|
|
48
|
-
<Monitor className="
|
|
48
|
+
<Monitor className="theme-toggle-icon" />
|
|
49
49
|
</button>
|
|
50
50
|
</div>
|
|
51
51
|
);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "bloom-dataviz-registry/v1",
|
|
3
|
+
"updatedAt": "2026-07-13T00:00:00.000Z",
|
|
4
|
+
"themes": [
|
|
5
|
+
{
|
|
6
|
+
"id": "teal-ignition",
|
|
7
|
+
"label": "Teal Ignition",
|
|
8
|
+
"brand": "sonance",
|
|
9
|
+
"scope": {
|
|
10
|
+
"kind": "library"
|
|
11
|
+
},
|
|
12
|
+
"file": "teal-ignition.json",
|
|
13
|
+
"cover": null,
|
|
14
|
+
"publishedAt": "2026-07-13T00:00:00.000Z"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "bloom-viz-theme/v1",
|
|
3
|
+
"id": "teal-ignition",
|
|
4
|
+
"label": "Teal Ignition",
|
|
5
|
+
"brand": "sonance",
|
|
6
|
+
"scope": {
|
|
7
|
+
"kind": "library"
|
|
8
|
+
},
|
|
9
|
+
"story": {
|
|
10
|
+
"title": "Sonance Data-Viz · Teal Ignition",
|
|
11
|
+
"description": "Teal Pulse opens in the dark like a held breath. A bioluminescent form gathers itself from nothing, petal over translucent petal, teal deepening to near-black at the seams. Threads of amber and violet flicker beneath the surface — capillaries of stray color that never break the surface calm. The bloom widens, contracts, widens again, patient as tide. Toward the bottom third, the glow surrenders to charcoal void, unhurried, as if the mural remembers it is also night."
|
|
12
|
+
},
|
|
13
|
+
"publishedAt": "2026-07-14T16:23:57.822Z",
|
|
14
|
+
"source": {
|
|
15
|
+
"app": "bloom",
|
|
16
|
+
"assetId": "ast_viz5de80f12"
|
|
17
|
+
},
|
|
18
|
+
"cover": "/dataviz/teal-ignition-cover.png",
|
|
19
|
+
"mural": "/dataviz/teal-ignition-mural.mp4",
|
|
20
|
+
"theme": {
|
|
21
|
+
"label": "Teal Ignition",
|
|
22
|
+
"reasoning": "Leads with electric teal instead of brand blue to give the dashboard a livelier, more energetic pulse, while glass surfaces, whitespace, and calm draw-ins keep it wall-display quiet.",
|
|
23
|
+
"light": {
|
|
24
|
+
"surface": "#ffffff",
|
|
25
|
+
"plane": "#f8f9fa",
|
|
26
|
+
"inkPrimary": "#333f48",
|
|
27
|
+
"inkSecondary": "#515c64",
|
|
28
|
+
"inkMuted": "#8f999f",
|
|
29
|
+
"grid": "#eceeef",
|
|
30
|
+
"baseline": "#e2e5e6",
|
|
31
|
+
"categorical": [
|
|
32
|
+
"#009b93",
|
|
33
|
+
"#ed9e2c",
|
|
34
|
+
"#8b5cf6",
|
|
35
|
+
"#00a3e1",
|
|
36
|
+
"#ff5a5f",
|
|
37
|
+
"#8bc34a",
|
|
38
|
+
"#e0449c",
|
|
39
|
+
"#5468ff"
|
|
40
|
+
],
|
|
41
|
+
"sequential": [
|
|
42
|
+
"#e4f4fc",
|
|
43
|
+
"#bee6f7",
|
|
44
|
+
"#8fd4f0",
|
|
45
|
+
"#57bee6",
|
|
46
|
+
"#1fa3d8",
|
|
47
|
+
"#0884b9",
|
|
48
|
+
"#056090"
|
|
49
|
+
],
|
|
50
|
+
"diverging": {
|
|
51
|
+
"neg": [
|
|
52
|
+
"#0b72b9",
|
|
53
|
+
"#5fa9d9",
|
|
54
|
+
"#afd6ec"
|
|
55
|
+
],
|
|
56
|
+
"mid": "#9aa3a8",
|
|
57
|
+
"pos": [
|
|
58
|
+
"#ffd59e",
|
|
59
|
+
"#ffa84d",
|
|
60
|
+
"#e8752a"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
"status": {
|
|
64
|
+
"good": "#2bb673",
|
|
65
|
+
"warning": "#e8a23c",
|
|
66
|
+
"serious": "#f2622e",
|
|
67
|
+
"critical": "#e1341e"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"dark": {
|
|
71
|
+
"surface": "#242a31",
|
|
72
|
+
"plane": "#1a1f24",
|
|
73
|
+
"inkPrimary": "#f5f5f5",
|
|
74
|
+
"inkSecondary": "#d9d9d6",
|
|
75
|
+
"inkMuted": "#8f999f",
|
|
76
|
+
"grid": "#2b323a",
|
|
77
|
+
"baseline": "#343c45",
|
|
78
|
+
"categorical": [
|
|
79
|
+
"#009b93",
|
|
80
|
+
"#c48300",
|
|
81
|
+
"#987ce9",
|
|
82
|
+
"#00a0d1",
|
|
83
|
+
"#e46268",
|
|
84
|
+
"#6ea532",
|
|
85
|
+
"#df5aa4",
|
|
86
|
+
"#6e82ff"
|
|
87
|
+
],
|
|
88
|
+
"sequential": [
|
|
89
|
+
"#063a57",
|
|
90
|
+
"#0a5878",
|
|
91
|
+
"#0f7ca0",
|
|
92
|
+
"#1aa0c8",
|
|
93
|
+
"#3fbee0",
|
|
94
|
+
"#7dd6ee",
|
|
95
|
+
"#c9eef8"
|
|
96
|
+
],
|
|
97
|
+
"diverging": {
|
|
98
|
+
"neg": [
|
|
99
|
+
"#4fa8d9",
|
|
100
|
+
"#7cc4e6",
|
|
101
|
+
"#b9e1f2"
|
|
102
|
+
],
|
|
103
|
+
"mid": "#7b848a",
|
|
104
|
+
"pos": [
|
|
105
|
+
"#ffb877",
|
|
106
|
+
"#ff9645",
|
|
107
|
+
"#e86a25"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
"status": {
|
|
111
|
+
"good": "#35cc82",
|
|
112
|
+
"warning": "#f0b24e",
|
|
113
|
+
"serious": "#ff7a46",
|
|
114
|
+
"critical": "#ff4c38"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"marks": {
|
|
118
|
+
"barRadius": 5,
|
|
119
|
+
"barMax": 20,
|
|
120
|
+
"gap": 2,
|
|
121
|
+
"lineWidth": 2,
|
|
122
|
+
"markerSize": 9,
|
|
123
|
+
"areaAlpha": 0.13,
|
|
124
|
+
"glow": 0.45
|
|
125
|
+
},
|
|
126
|
+
"chrome": {
|
|
127
|
+
"style": "glass",
|
|
128
|
+
"tag": "#00b2a9"
|
|
129
|
+
},
|
|
130
|
+
"type": {
|
|
131
|
+
"family": "Montserrat",
|
|
132
|
+
"axisSize": 11
|
|
133
|
+
},
|
|
134
|
+
"motion": {
|
|
135
|
+
"style": "rise",
|
|
136
|
+
"duration": 650,
|
|
137
|
+
"easing": "cubic-bezier(0.16,1,0.3,1)",
|
|
138
|
+
"stagger": 70,
|
|
139
|
+
"breathe": true
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"tokensCss": "/* ============================================================\n Sonance DATA-VIZ TOKENS — \"Teal Ignition\"\n Designed in Bloom Studio · 2026-07-14\n Drop next to globals.css; dark mode keys off [data-theme=\"dark\"]\n (same convention as the Sonance brand theme).\n ============================================================ */\n\n:root {\n --viz-surface: #ffffff;\n --viz-plane: #f8f9fa;\n --viz-ink: #333f48;\n --viz-ink-secondary: #515c64;\n --viz-ink-muted: #8f999f;\n --viz-grid: #eceeef;\n --viz-baseline: #e2e5e6;\n --viz-cat-1: #009b93;\n --viz-cat-2: #ed9e2c;\n --viz-cat-3: #8b5cf6;\n --viz-cat-4: #00a3e1;\n --viz-cat-5: #ff5a5f;\n --viz-cat-6: #8bc34a;\n --viz-cat-7: #e0449c;\n --viz-cat-8: #5468ff;\n --viz-seq-100: #e4f4fc;\n --viz-seq-200: #bee6f7;\n --viz-seq-300: #8fd4f0;\n --viz-seq-400: #57bee6;\n --viz-seq-500: #1fa3d8;\n --viz-seq-600: #0884b9;\n --viz-seq-700: #056090;\n --viz-div-neg-1: #0b72b9;\n --viz-div-neg-2: #5fa9d9;\n --viz-div-neg-3: #afd6ec;\n --viz-div-mid: #9aa3a8;\n --viz-div-pos-1: #ffd59e;\n --viz-div-pos-2: #ffa84d;\n --viz-div-pos-3: #e8752a;\n --viz-status-good: #2bb673;\n --viz-status-warning: #e8a23c;\n --viz-status-serious: #f2622e;\n --viz-status-critical: #e1341e;\n\n /* marks */\n --viz-bar-radius: 5px;\n --viz-bar-max: 20px;\n --viz-gap: 2px;\n --viz-line-width: 2px;\n --viz-marker-size: 9px;\n --viz-area-alpha: 0.13;\n\n /* chrome */\n --viz-chrome: glass;\n --viz-tag: #00b2a9;\n --viz-glow: 0.45;\n\n /* motion */\n --viz-duration: 650ms;\n --viz-easing: cubic-bezier(0.16,1,0.3,1);\n --viz-stagger: 70ms;\n}\n\n[data-theme=\"dark\"] {\n --viz-surface: #242a31;\n --viz-plane: #1a1f24;\n --viz-ink: #f5f5f5;\n --viz-ink-secondary: #d9d9d6;\n --viz-ink-muted: #8f999f;\n --viz-grid: #2b323a;\n --viz-baseline: #343c45;\n --viz-cat-1: #009b93;\n --viz-cat-2: #c48300;\n --viz-cat-3: #987ce9;\n --viz-cat-4: #00a0d1;\n --viz-cat-5: #e46268;\n --viz-cat-6: #6ea532;\n --viz-cat-7: #df5aa4;\n --viz-cat-8: #6e82ff;\n --viz-seq-100: #063a57;\n --viz-seq-200: #0a5878;\n --viz-seq-300: #0f7ca0;\n --viz-seq-400: #1aa0c8;\n --viz-seq-500: #3fbee0;\n --viz-seq-600: #7dd6ee;\n --viz-seq-700: #c9eef8;\n --viz-div-neg-1: #4fa8d9;\n --viz-div-neg-2: #7cc4e6;\n --viz-div-neg-3: #b9e1f2;\n --viz-div-mid: #7b848a;\n --viz-div-pos-1: #ffb877;\n --viz-div-pos-2: #ff9645;\n --viz-div-pos-3: #e86a25;\n --viz-status-good: #35cc82;\n --viz-status-warning: #f0b24e;\n --viz-status-serious: #ff7a46;\n --viz-status-critical: #ff4c38;\n}\n",
|
|
143
|
+
"recharts": "// Sonance data-viz theme — \"Teal Ignition\"\n// Designed in Bloom Studio. Pairs with components/ui/chart.tsx (ChartContainer).\n// Colors resolve through the --viz-* CSS variables (dataviz-tokens.css), so\n// light/dark follow the app's data-theme automatically.\nimport { type ChartConfig } from \"@/components/ui/chart\";\n\n/** Fixed categorical order — assign series to slots in order, never cycle. */\nexport const VIZ_SERIES = [\"var(--viz-cat-1)\", \"var(--viz-cat-2)\", \"var(--viz-cat-3)\", \"var(--viz-cat-4)\", \"var(--viz-cat-5)\", \"var(--viz-cat-6)\", \"var(--viz-cat-7)\", \"var(--viz-cat-8)\"] as const;\n\nexport const VIZ_SEQUENTIAL = [\"var(--viz-seq-100)\", \"var(--viz-seq-200)\", \"var(--viz-seq-300)\", \"var(--viz-seq-400)\", \"var(--viz-seq-500)\", \"var(--viz-seq-600)\", \"var(--viz-seq-700)\"] as const;\n\nexport const VIZ_STATUS = {\n good: \"var(--viz-status-good)\",\n warning: \"var(--viz-status-warning)\",\n serious: \"var(--viz-status-serious)\",\n critical: \"var(--viz-status-critical)\",\n} as const;\n\n/** Build a ChartConfig assigning each series key its fixed slot color. */\nexport function vizConfig(keys: string[], labels?: Record<string, string>): ChartConfig {\n const cfg: ChartConfig = {};\n keys.forEach((k, i) => {\n cfg[k] = { label: labels?.[k] ?? k, color: VIZ_SERIES[i % VIZ_SERIES.length] };\n });\n return cfg;\n}\n\n/** Shared cartesian defaults matching the specimen sheet. */\nexport const VIZ_CARTESIAN = {\n grid: { stroke: \"var(--viz-grid)\", strokeWidth: 1, vertical: false },\n axisTick: { fill: \"var(--viz-ink-muted)\", fontSize: 11 },\n axisLine: { stroke: \"var(--viz-baseline)\", strokeWidth: 1 },\n bar: { radius: [5, 5, 0, 0] as [number, number, number, number], maxBarSize: 20 },\n line: { strokeWidth: 2, dot: false },\n activeDot: { r: 5, stroke: \"var(--viz-surface)\", strokeWidth: 2 },\n} as const;\n",
|
|
144
|
+
"validation": {
|
|
145
|
+
"light": {
|
|
146
|
+
"ok": true,
|
|
147
|
+
"checks": [
|
|
148
|
+
{
|
|
149
|
+
"check": "Lightness band",
|
|
150
|
+
"state": "true",
|
|
151
|
+
"detail": "all 8 inside L 0.43–0.77"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"check": "Chroma floor",
|
|
155
|
+
"state": "true",
|
|
156
|
+
"detail": "all 8 >= 0.1"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"check": "CVD separation",
|
|
160
|
+
"state": "pass",
|
|
161
|
+
"detail": "worst adjacent #8bc34a↔#ff5a5f ΔE 13.2 (deutan) · tritan 39.2 · normal 69.3"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"check": "Contrast vs surface",
|
|
165
|
+
"state": "relief",
|
|
166
|
+
"detail": "below 3:1 — relief required (visible labels or table view): [[\"#ed9e2c\",2.2],[\"#00a3e1\",2.87],[\"#8bc34a\",2.1]]"
|
|
167
|
+
}
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
"dark": {
|
|
171
|
+
"ok": true,
|
|
172
|
+
"checks": [
|
|
173
|
+
{
|
|
174
|
+
"check": "Lightness band",
|
|
175
|
+
"state": "true",
|
|
176
|
+
"detail": "all 8 inside L 0.48–0.67"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"check": "Chroma floor",
|
|
180
|
+
"state": "true",
|
|
181
|
+
"detail": "all 8 >= 0.1"
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"check": "CVD separation",
|
|
185
|
+
"state": "pass",
|
|
186
|
+
"detail": "worst adjacent #00a0d1↔#987ce9 ΔE 13.3 (deutan) · tritan 36.0 · normal 55.0"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"check": "Contrast vs surface",
|
|
190
|
+
"state": "pass",
|
|
191
|
+
"detail": "all 8 >= 3:1"
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
package/dist/assets/globals.css
CHANGED
|
@@ -10,13 +10,17 @@
|
|
|
10
10
|
============================================ */
|
|
11
11
|
|
|
12
12
|
:root {
|
|
13
|
+
/* Bloom Accent Colors */
|
|
14
|
+
--bloom-emerald: #3fe0a5;
|
|
15
|
+
--bloom-violet: #a78bfa;
|
|
16
|
+
|
|
13
17
|
/* Core Brand Colors - Official Sonance Palette (from Brand Guidelines PDF) */
|
|
14
18
|
--sonance-charcoal: #333F48;
|
|
15
19
|
--sonance-blue: #00A3E1; /* "The Beam" - cyan accent on logo | Pantone 2191C/2191U */
|
|
16
20
|
--sonance-light-gray: #D9D9D6;
|
|
17
21
|
--sonance-white: #FFFFFF;
|
|
18
22
|
--sonance-black: #000000;
|
|
19
|
-
|
|
23
|
+
|
|
20
24
|
/* Sonance Foundation Colors */
|
|
21
25
|
--foundation-green: #00B2A9;
|
|
22
26
|
|
|
@@ -78,6 +82,7 @@
|
|
|
78
82
|
--background-secondary: #f8f9fa;
|
|
79
83
|
--background-tertiary: #f0f2f3;
|
|
80
84
|
--background-elevated: #FFFFFF;
|
|
85
|
+
--bg-2: #f0f2f3;
|
|
81
86
|
|
|
82
87
|
/* Light Mode - Foreground / Text */
|
|
83
88
|
--foreground: #333F48;
|
|
@@ -90,6 +95,7 @@
|
|
|
90
95
|
--border-hover: #b8bfc4;
|
|
91
96
|
--border-focus: #333F48;
|
|
92
97
|
--divider: #f0f2f3;
|
|
98
|
+
--line-2: #e2e2e2;
|
|
93
99
|
|
|
94
100
|
/* Light Mode - Interactive Elements */
|
|
95
101
|
--primary: #333F48;
|
|
@@ -233,11 +239,12 @@
|
|
|
233
239
|
|
|
234
240
|
/* Dark Mode */
|
|
235
241
|
[data-theme="dark"] {
|
|
236
|
-
/* Backgrounds */
|
|
237
|
-
--background: #
|
|
238
|
-
--background-secondary: #
|
|
239
|
-
--background-tertiary: #
|
|
240
|
-
--background-elevated: #
|
|
242
|
+
/* Backgrounds - Bloom Aesthetic */
|
|
243
|
+
--background: #07080c;
|
|
244
|
+
--background-secondary: #0f121b;
|
|
245
|
+
--background-tertiary: #0f121b;
|
|
246
|
+
--background-elevated: #0f121b;
|
|
247
|
+
--bg-2: #0b0d14;
|
|
241
248
|
|
|
242
249
|
/* Foreground / Text */
|
|
243
250
|
--foreground: #FFFFFF;
|
|
@@ -246,10 +253,11 @@
|
|
|
246
253
|
--foreground-subtle: #6b7780;
|
|
247
254
|
|
|
248
255
|
/* Borders & Dividers */
|
|
249
|
-
--border: #
|
|
250
|
-
--border-hover: #
|
|
256
|
+
--border: #1f2937;
|
|
257
|
+
--border-hover: #374151;
|
|
251
258
|
--border-focus: #D9D9D6;
|
|
252
|
-
--divider: #
|
|
259
|
+
--divider: #1f2937;
|
|
260
|
+
--line-2: rgba(255, 255, 255, 0.08);
|
|
253
261
|
|
|
254
262
|
/* Interactive Elements */
|
|
255
263
|
--primary: #FFFFFF;
|
|
@@ -262,13 +270,13 @@
|
|
|
262
270
|
--secondary-foreground: #FFFFFF;
|
|
263
271
|
|
|
264
272
|
/* Cards & Surfaces */
|
|
265
|
-
--card: #
|
|
266
|
-
--card-hover: #
|
|
267
|
-
--card-border: #
|
|
273
|
+
--card: #0f121b;
|
|
274
|
+
--card-hover: #1a1d2a;
|
|
275
|
+
--card-border: #1f2937;
|
|
268
276
|
|
|
269
277
|
/* Input Fields */
|
|
270
|
-
--input: #
|
|
271
|
-
--input-border: #
|
|
278
|
+
--input: #0f121b;
|
|
279
|
+
--input-border: #1f2937;
|
|
272
280
|
--input-focus: #FFFFFF;
|
|
273
281
|
--input-placeholder: #7a8389;
|
|
274
282
|
|
|
@@ -294,13 +302,13 @@
|
|
|
294
302
|
--info-light: rgba(66, 165, 245, 0.15);
|
|
295
303
|
|
|
296
304
|
/* Sidebar Colors - Dark Mode */
|
|
297
|
-
--sidebar-background: #
|
|
305
|
+
--sidebar-background: #07080c;
|
|
298
306
|
--sidebar-foreground: #FFFFFF;
|
|
299
307
|
--sidebar-primary: #FFFFFF;
|
|
300
308
|
--sidebar-primary-foreground: #333F48;
|
|
301
|
-
--sidebar-accent: #
|
|
309
|
+
--sidebar-accent: #0f121b;
|
|
302
310
|
--sidebar-accent-foreground: #FFFFFF;
|
|
303
|
-
--sidebar-border: #
|
|
311
|
+
--sidebar-border: #1f2937;
|
|
304
312
|
--sidebar-ring: #00A3E1;
|
|
305
313
|
|
|
306
314
|
/* ============================================
|
|
@@ -338,18 +346,18 @@
|
|
|
338
346
|
/* System preference detection fallback */
|
|
339
347
|
@media (prefers-color-scheme: dark) {
|
|
340
348
|
:root:not([data-theme="light"]) {
|
|
341
|
-
--background: #
|
|
342
|
-
--background-secondary: #
|
|
343
|
-
--background-tertiary: #
|
|
344
|
-
--background-elevated: #
|
|
349
|
+
--background: #07080c;
|
|
350
|
+
--background-secondary: #0f121b;
|
|
351
|
+
--background-tertiary: #0f121b;
|
|
352
|
+
--background-elevated: #0f121b;
|
|
345
353
|
--foreground: #FFFFFF;
|
|
346
354
|
--foreground-secondary: #D9D9D6;
|
|
347
355
|
--foreground-muted: #8f999f;
|
|
348
356
|
--foreground-subtle: #6b7780;
|
|
349
|
-
--border: #
|
|
350
|
-
--border-hover: #
|
|
357
|
+
--border: #1f2937;
|
|
358
|
+
--border-hover: #374151;
|
|
351
359
|
--border-focus: #D9D9D6;
|
|
352
|
-
--divider: #
|
|
360
|
+
--divider: #1f2937;
|
|
353
361
|
--primary: #FFFFFF;
|
|
354
362
|
--primary-hover: #D9D9D6;
|
|
355
363
|
--primary-active: #b8bfc4;
|
|
@@ -357,11 +365,11 @@
|
|
|
357
365
|
--secondary: transparent;
|
|
358
366
|
--secondary-hover: #2d343c;
|
|
359
367
|
--secondary-foreground: #FFFFFF;
|
|
360
|
-
--card: #
|
|
361
|
-
--card-hover: #
|
|
362
|
-
--card-border: #
|
|
363
|
-
--input: #
|
|
364
|
-
--input-border: #
|
|
368
|
+
--card: #0f121b;
|
|
369
|
+
--card-hover: #1a1d2a;
|
|
370
|
+
--card-border: #1f2937;
|
|
371
|
+
--input: #0f121b;
|
|
372
|
+
--input-border: #1f2937;
|
|
365
373
|
--input-focus: #FFFFFF;
|
|
366
374
|
--input-placeholder: #6b7780;
|
|
367
375
|
--overlay: rgba(0, 0, 0, 0.7);
|
|
@@ -432,6 +440,10 @@
|
|
|
432
440
|
--color-sidebar-border: var(--sidebar-border);
|
|
433
441
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
434
442
|
|
|
443
|
+
/* Bloom Accent Colors */
|
|
444
|
+
--color-bloom-emerald: var(--bloom-emerald);
|
|
445
|
+
--color-bloom-violet: var(--bloom-violet);
|
|
446
|
+
|
|
435
447
|
/* Brand Colors */
|
|
436
448
|
--color-sonance-charcoal: var(--sonance-charcoal);
|
|
437
449
|
--color-sonance-blue: var(--sonance-blue);
|
|
@@ -516,6 +528,391 @@ body {
|
|
|
516
528
|
-moz-osx-font-smoothing: grayscale;
|
|
517
529
|
}
|
|
518
530
|
|
|
531
|
+
/* Bloom Dark Mode Ambient Gradients */
|
|
532
|
+
[data-theme="dark"] body {
|
|
533
|
+
background:
|
|
534
|
+
radial-gradient(1200px 700px at 82% -8%, rgba(167, 139, 250, 0.10), transparent 60%),
|
|
535
|
+
radial-gradient(1000px 650px at -6% 108%, rgba(63, 224, 165, 0.09), transparent 55%),
|
|
536
|
+
#07080c;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/* ============================================
|
|
540
|
+
BLOOM-STYLE APP SHELL & SIDEBAR
|
|
541
|
+
============================================ */
|
|
542
|
+
|
|
543
|
+
/* App Shell Layout */
|
|
544
|
+
.app-shell {
|
|
545
|
+
display: grid;
|
|
546
|
+
grid-template-columns: 252px minmax(0, 1fr);
|
|
547
|
+
min-height: 100vh;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/* Main Content Area with Bloom's 90% zoom */
|
|
551
|
+
.app-main {
|
|
552
|
+
zoom: 0.9;
|
|
553
|
+
padding-top: 0;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/* Remove zoom on smaller screens where it would make text too small */
|
|
557
|
+
@media (max-width: 1000px) {
|
|
558
|
+
.app-main {
|
|
559
|
+
zoom: 1;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/* Floating Sidebar Card - Desktop */
|
|
564
|
+
.app-side {
|
|
565
|
+
position: sticky;
|
|
566
|
+
left: 14px;
|
|
567
|
+
width: 252px;
|
|
568
|
+
background: #FFFFFF;
|
|
569
|
+
border: 1px solid var(--border);
|
|
570
|
+
border-radius: 22px;
|
|
571
|
+
overflow: hidden;
|
|
572
|
+
display: flex;
|
|
573
|
+
flex-direction: column;
|
|
574
|
+
box-shadow:
|
|
575
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.05),
|
|
576
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.05),
|
|
577
|
+
0 20px 25px -5px rgba(0, 0, 0, 0.04);
|
|
578
|
+
z-index: 40;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
[data-theme="dark"] .app-side {
|
|
582
|
+
background: #0f121b;
|
|
583
|
+
border-color: rgba(255, 255, 255, 0.08);
|
|
584
|
+
box-shadow:
|
|
585
|
+
0 4px 6px -1px rgba(0, 0, 0, 0.3),
|
|
586
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.2);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/* Sidebar Navigation Scroll Container */
|
|
590
|
+
.app-side nav {
|
|
591
|
+
overflow-y: auto;
|
|
592
|
+
overflow-x: hidden;
|
|
593
|
+
max-height: calc(100% - 160px); /* Account for header and footer */
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/* Smooth scrolling for sidebar */
|
|
597
|
+
.app-side nav {
|
|
598
|
+
scroll-behavior: smooth;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/* Custom scrollbar for sidebar */
|
|
602
|
+
.app-side nav::-webkit-scrollbar {
|
|
603
|
+
width: 6px;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.app-side nav::-webkit-scrollbar-track {
|
|
607
|
+
background: transparent;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.app-side nav::-webkit-scrollbar-thumb {
|
|
611
|
+
background: var(--border);
|
|
612
|
+
border-radius: 3px;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.app-side nav::-webkit-scrollbar-thumb:hover {
|
|
616
|
+
background: var(--border-hover);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/* Navigation Links - Bloom Style */
|
|
620
|
+
.side-link {
|
|
621
|
+
display: flex;
|
|
622
|
+
align-items: center;
|
|
623
|
+
gap: 12px;
|
|
624
|
+
padding: 10px 12px;
|
|
625
|
+
border-radius: 10px;
|
|
626
|
+
font-size: 14px;
|
|
627
|
+
font-weight: 500;
|
|
628
|
+
color: var(--foreground-secondary);
|
|
629
|
+
transition: all 0.15s ease-out;
|
|
630
|
+
text-decoration: none;
|
|
631
|
+
position: relative;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
.side-link:hover {
|
|
635
|
+
background: #f0f2f3;
|
|
636
|
+
color: var(--foreground);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
[data-theme="dark"] .side-link:hover {
|
|
640
|
+
background: #0b0d14;
|
|
641
|
+
color: #FFFFFF;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/* Active State - Bloom Gradient */
|
|
645
|
+
.side-link.on {
|
|
646
|
+
background: linear-gradient(90deg, rgba(63, 224, 165, 0.16), rgba(167, 139, 250, 0.10));
|
|
647
|
+
color: var(--foreground);
|
|
648
|
+
font-weight: 600;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
[data-theme="dark"] .side-link.on {
|
|
652
|
+
background: linear-gradient(90deg, rgba(63, 224, 165, 0.16), rgba(167, 139, 250, 0.10));
|
|
653
|
+
color: #FFFFFF;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/* Sidebar Footer */
|
|
657
|
+
.side-footer {
|
|
658
|
+
border-top: 1px solid var(--border);
|
|
659
|
+
padding: 16px;
|
|
660
|
+
flex-shrink: 0;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
[data-theme="dark"] .side-footer {
|
|
664
|
+
border-color: rgba(255, 255, 255, 0.08);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/* ============================================
|
|
668
|
+
RESPONSIVE SIDEBAR ENHANCEMENTS
|
|
669
|
+
============================================ */
|
|
670
|
+
|
|
671
|
+
/* Fluid Logo Scaling */
|
|
672
|
+
.sidebar-logo-container {
|
|
673
|
+
min-height: 80px;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
.sidebar-logo {
|
|
677
|
+
max-width: clamp(140px, 85%, 200px);
|
|
678
|
+
height: auto !important;
|
|
679
|
+
width: auto !important;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/* Nested Navigation Layout */
|
|
683
|
+
.nested-nav-container {
|
|
684
|
+
margin-left: 12px;
|
|
685
|
+
margin-top: 6px;
|
|
686
|
+
padding-left: clamp(20px, 1.25rem, 28px);
|
|
687
|
+
border-left: 1px solid var(--border);
|
|
688
|
+
display: flex;
|
|
689
|
+
flex-direction: column;
|
|
690
|
+
gap: 4px;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
.nested-nav-item {
|
|
694
|
+
display: flex;
|
|
695
|
+
align-items: center;
|
|
696
|
+
gap: 8px;
|
|
697
|
+
padding: 6px 12px;
|
|
698
|
+
text-sm: 14px;
|
|
699
|
+
transition: color 0.15s ease-out;
|
|
700
|
+
border-radius: 6px;
|
|
701
|
+
min-width: 0; /* Enable text truncation */
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.nested-nav-item:hover {
|
|
705
|
+
background: rgba(0, 0, 0, 0.03);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
[data-theme="dark"] .nested-nav-item:hover {
|
|
709
|
+
background: rgba(255, 255, 255, 0.03);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/* Theme Toggle Responsive Sizing */
|
|
713
|
+
.theme-toggle-container {
|
|
714
|
+
display: flex;
|
|
715
|
+
align-items: center;
|
|
716
|
+
justify-content: center;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.theme-toggle-btn {
|
|
720
|
+
padding: clamp(6px, 0.5rem, 10px);
|
|
721
|
+
border-radius: 8px;
|
|
722
|
+
transition: all 0.15s ease-out;
|
|
723
|
+
display: flex;
|
|
724
|
+
align-items: center;
|
|
725
|
+
justify-content: center;
|
|
726
|
+
min-width: 32px;
|
|
727
|
+
min-height: 32px;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
.theme-toggle-icon {
|
|
731
|
+
width: clamp(14px, 1rem, 18px);
|
|
732
|
+
height: clamp(14px, 1rem, 18px);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
/* Mobile Drawer Backdrop - Hidden on desktop */
|
|
737
|
+
.mobile-drawer-backdrop {
|
|
738
|
+
display: none;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
@media (max-width: 600px) {
|
|
742
|
+
.mobile-drawer-backdrop {
|
|
743
|
+
display: block;
|
|
744
|
+
position: fixed;
|
|
745
|
+
inset: 0;
|
|
746
|
+
background: rgba(0, 0, 0, 0.5);
|
|
747
|
+
z-index: 49;
|
|
748
|
+
opacity: 0;
|
|
749
|
+
pointer-events: none;
|
|
750
|
+
transition: opacity 0.2s ease-out;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
.mobile-drawer-backdrop.open {
|
|
754
|
+
opacity: 1;
|
|
755
|
+
pointer-events: auto;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
[data-theme="dark"] .mobile-drawer-backdrop {
|
|
759
|
+
background: rgba(0, 0, 0, 0.7);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/* Hide mobile header and bottom tab bar on desktop */
|
|
764
|
+
.mobile-header,
|
|
765
|
+
.bottom-tab-bar {
|
|
766
|
+
display: none;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/* Mobile Drawer - Full sidebar access */
|
|
770
|
+
@media (max-width: 600px) {
|
|
771
|
+
/* Mobile Header */
|
|
772
|
+
.mobile-header {
|
|
773
|
+
display: flex;
|
|
774
|
+
position: fixed;
|
|
775
|
+
top: 0;
|
|
776
|
+
left: 0;
|
|
777
|
+
right: 0;
|
|
778
|
+
height: 64px;
|
|
779
|
+
background: var(--background);
|
|
780
|
+
border-bottom: 1px solid var(--border);
|
|
781
|
+
align-items: center;
|
|
782
|
+
justify-content: center;
|
|
783
|
+
padding: 0 16px;
|
|
784
|
+
z-index: 50;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
[data-theme="dark"] .mobile-header {
|
|
788
|
+
background: #0f121b;
|
|
789
|
+
border-bottom-color: rgba(255, 255, 255, 0.08);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
/* Drawer Sidebar - Override desktop floating styles */
|
|
793
|
+
.app-side {
|
|
794
|
+
position: fixed !important;
|
|
795
|
+
top: 0 !important;
|
|
796
|
+
left: 0;
|
|
797
|
+
bottom: 0;
|
|
798
|
+
width: 280px;
|
|
799
|
+
height: 100vh !important;
|
|
800
|
+
border-radius: 0 !important;
|
|
801
|
+
border: none;
|
|
802
|
+
border-right: 1px solid var(--border);
|
|
803
|
+
transform: translateX(-100%);
|
|
804
|
+
transition: transform 0.25s ease-out;
|
|
805
|
+
z-index: 50;
|
|
806
|
+
overflow-y: auto;
|
|
807
|
+
box-shadow: none !important;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
.app-side.open {
|
|
811
|
+
transform: translateX(0);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
[data-theme="dark"] .app-side {
|
|
815
|
+
border-right-color: rgba(255, 255, 255, 0.08);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/* Drawer navigation scrollable */
|
|
819
|
+
.app-side nav {
|
|
820
|
+
max-height: none !important;
|
|
821
|
+
overflow-y: auto;
|
|
822
|
+
padding-bottom: 24px;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/* Logo section visible in drawer */
|
|
826
|
+
.app-side > div:first-child {
|
|
827
|
+
display: flex !important;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/* Mobile logo sizing */
|
|
831
|
+
.sidebar-logo {
|
|
832
|
+
max-width: clamp(160px, 90%, 220px);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/* Mobile theme toggle - horizontal layout */
|
|
836
|
+
.theme-toggle-container {
|
|
837
|
+
flex-direction: row;
|
|
838
|
+
gap: 2px;
|
|
839
|
+
padding: 2px;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
.theme-toggle-btn {
|
|
843
|
+
min-width: 40px;
|
|
844
|
+
min-height: 40px;
|
|
845
|
+
padding: 8px;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.theme-toggle-icon {
|
|
849
|
+
width: 18px;
|
|
850
|
+
height: 18px;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/* Bottom Tab Bar - Essential items only */
|
|
854
|
+
.app-shell {
|
|
855
|
+
grid-template-columns: 1fr;
|
|
856
|
+
padding-top: 64px; /* Account for mobile header */
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
.app-main {
|
|
860
|
+
padding-bottom: 64px; /* Account for tab bar */
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
.bottom-tab-bar {
|
|
864
|
+
display: flex;
|
|
865
|
+
position: fixed;
|
|
866
|
+
bottom: 0;
|
|
867
|
+
left: 0;
|
|
868
|
+
right: 0;
|
|
869
|
+
height: 64px;
|
|
870
|
+
background: var(--background);
|
|
871
|
+
border-top: 1px solid var(--border);
|
|
872
|
+
align-items: center;
|
|
873
|
+
justify-content: space-around;
|
|
874
|
+
padding: 8px;
|
|
875
|
+
z-index: 40;
|
|
876
|
+
box-shadow: 0 -4px 6px -1px rgba(0, 0, 0, 0.05);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
[data-theme="dark"] .bottom-tab-bar {
|
|
880
|
+
background: #0f121b;
|
|
881
|
+
border-top-color: rgba(255, 255, 255, 0.08);
|
|
882
|
+
box-shadow: 0 -4px 6px -1px rgba(0, 0, 0, 0.3);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
.tab-bar-item {
|
|
886
|
+
display: flex;
|
|
887
|
+
flex-direction: column;
|
|
888
|
+
align-items: center;
|
|
889
|
+
gap: 4px;
|
|
890
|
+
padding: 8px 12px;
|
|
891
|
+
min-width: 64px;
|
|
892
|
+
color: var(--foreground-muted);
|
|
893
|
+
text-decoration: none;
|
|
894
|
+
transition: color 0.15s ease-out;
|
|
895
|
+
border-radius: 8px;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.tab-bar-item:hover,
|
|
899
|
+
.tab-bar-item.active {
|
|
900
|
+
color: var(--foreground);
|
|
901
|
+
background: var(--secondary-hover);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.tab-bar-item svg {
|
|
905
|
+
width: 20px;
|
|
906
|
+
height: 20px;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
.tab-bar-item span {
|
|
910
|
+
font-size: 11px;
|
|
911
|
+
font-weight: 500;
|
|
912
|
+
line-height: 1;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
519
916
|
/* Prevent flash of unstyled content */
|
|
520
917
|
html {
|
|
521
918
|
color-scheme: light dark;
|
|
@@ -525,6 +922,26 @@ html {
|
|
|
525
922
|
UTILITY CLASSES
|
|
526
923
|
============================================ */
|
|
527
924
|
|
|
925
|
+
/* Responsive Content Padding - Adapts to sidebar width */
|
|
926
|
+
.content-responsive {
|
|
927
|
+
padding-left: 2rem;
|
|
928
|
+
padding-right: 2rem;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
@media (max-width: 860px) {
|
|
932
|
+
.content-responsive {
|
|
933
|
+
padding-left: 1.5rem;
|
|
934
|
+
padding-right: 1.5rem;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
@media (max-width: 600px) {
|
|
939
|
+
.content-responsive {
|
|
940
|
+
padding-left: 1rem;
|
|
941
|
+
padding-right: 1rem;
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
528
945
|
/* Color swatch display */
|
|
529
946
|
.color-swatch {
|
|
530
947
|
width: 100%;
|
|
@@ -596,8 +1013,8 @@ html {
|
|
|
596
1013
|
}
|
|
597
1014
|
|
|
598
1015
|
[data-theme="dark"] ::selection {
|
|
599
|
-
background:
|
|
600
|
-
color: var(--sonance-
|
|
1016
|
+
background: rgba(167, 139, 250, 0.35);
|
|
1017
|
+
color: var(--sonance-white);
|
|
601
1018
|
}
|
|
602
1019
|
|
|
603
1020
|
/* Code block selection - ensure visibility on dark backgrounds */
|
|
@@ -49,6 +49,9 @@
|
|
|
49
49
|
"/logos/my-sonance/My.Sonance_Logo_2C_Reverse_RGB.png",
|
|
50
50
|
"/logos/my-sonance/My.Sonance_Logo_Black_RGB.png",
|
|
51
51
|
"/logos/my-sonance/My.Sonance_Logo_Reverse_RGB.png",
|
|
52
|
+
"/logos/sonance/Sonance_Beam_Fade_RGB.png",
|
|
53
|
+
"/logos/sonance/Sonance_Beam_RGB.png",
|
|
54
|
+
"/logos/sonance/Sonance_Beam_RGB.svg",
|
|
52
55
|
"/logos/sonance/Sonance_Logo_2C_Dark_RGB.png",
|
|
53
56
|
"/logos/sonance/Sonance_Logo_2C_Light_RGB.png",
|
|
54
57
|
"/logos/sonance/Sonance_Logo_2C_Reverse_RGB.png",
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="LockUp_2C_Dark" data-name="LockUp 2C Dark" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 792 612">
|
|
3
|
+
<defs>
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #00a8e4;
|
|
7
|
+
stroke-width: 0px;
|
|
8
|
+
}
|
|
9
|
+
</style>
|
|
10
|
+
</defs>
|
|
11
|
+
<path class="cls-1" d="M583.26,450.92h-68.73l-116.01-252.86-116.65,252.86h-66.2L371.09,118.1h56.74l155.43,332.81Z"/>
|
|
12
|
+
<path class="cls-1" d="M583.26,450.92h-68.73l-116.01-252.86-116.65,252.86h-66.2L371.09,118.1h56.74l155.43,332.81Z"/>
|
|
13
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg id="LockUp_2C_Dark" data-name="LockUp 2C Dark" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 792 612">
|
|
3
|
+
<defs>
|
|
4
|
+
<style>
|
|
5
|
+
.cls-1 {
|
|
6
|
+
fill: #00a8e4;
|
|
7
|
+
stroke-width: 0px;
|
|
8
|
+
}
|
|
9
|
+
</style>
|
|
10
|
+
</defs>
|
|
11
|
+
<path class="cls-1" d="M583.26,450.92h-68.73l-116.01-252.86-116.65,252.86h-66.2L371.09,118.1h56.74l155.43,332.81Z"/>
|
|
12
|
+
<path class="cls-1" d="M583.26,450.92h-68.73l-116.01-252.86-116.65,252.86h-66.2L371.09,118.1h56.74l155.43,332.81Z"/>
|
|
13
|
+
</svg>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "bloom-motion/v1",
|
|
3
|
+
"id": "sonance-logo-amber",
|
|
4
|
+
"name": "Sonance logo Amber",
|
|
5
|
+
"kind": "logo",
|
|
6
|
+
"brand": "sonance",
|
|
7
|
+
"file": "/motion/sonance-logo-amber.mp4",
|
|
8
|
+
"poster": "/motion/sonance-logo-amber-poster.png",
|
|
9
|
+
"story": {
|
|
10
|
+
"title": "Sonance logo Amber",
|
|
11
|
+
"description": "The mark hovers unlit at first, a dark umber field with no edges to hold onto. Then embers rise—slow, warm, unhurried—drifting upward like sparks remembering fire. Bokeh depth folds the background into soft distance, while heat shimmer trembles along the borders, alive but never intruding on the calm dark center. No letters form, no symbol resolves. Sonance appears instead as atmosphere: a mark you feel arriving before you see it, composed entirely of warmth, patience, and rising light."
|
|
12
|
+
},
|
|
13
|
+
"duration": null,
|
|
14
|
+
"publishedAt": "2026-07-14T01:30:30.104Z",
|
|
15
|
+
"source": {
|
|
16
|
+
"app": "bloom",
|
|
17
|
+
"assetId": "ast_logo1de502f0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bloom → Sonance Brand studio assets
|
|
3
|
+
*
|
|
4
|
+
* Serves design languages and motion assets published from the Bloom studio.
|
|
5
|
+
* Directory-derived: each published item is its own JSON file, so there is no
|
|
6
|
+
* shared index to overwrite. These tools read every item file across the
|
|
7
|
+
* built-in Data Viz / Motion sections AND any Bloom-created custom section,
|
|
8
|
+
* so a design language is reachable by id no matter where it's filed.
|
|
9
|
+
*
|
|
10
|
+
* Wired into index.ts with three lines:
|
|
11
|
+
* import { BLOOM_TOOLS, handleBloomTool } from "./bloom-assets.js";
|
|
12
|
+
* ...BLOOM_TOOLS, (inside the ListTools tools array)
|
|
13
|
+
* const bloom = await handleBloomTool(name, args); if (bloom) return bloom;
|
|
14
|
+
*/
|
|
15
|
+
export declare const BLOOM_TOOLS: ({
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: string;
|
|
20
|
+
properties: {
|
|
21
|
+
theme_id?: undefined;
|
|
22
|
+
include?: undefined;
|
|
23
|
+
asset_id?: undefined;
|
|
24
|
+
};
|
|
25
|
+
required: never[];
|
|
26
|
+
};
|
|
27
|
+
} | {
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
inputSchema: {
|
|
31
|
+
type: string;
|
|
32
|
+
properties: {
|
|
33
|
+
theme_id: {
|
|
34
|
+
type: string;
|
|
35
|
+
description: string;
|
|
36
|
+
};
|
|
37
|
+
include: {
|
|
38
|
+
type: string;
|
|
39
|
+
enum: string[];
|
|
40
|
+
description: string;
|
|
41
|
+
};
|
|
42
|
+
asset_id?: undefined;
|
|
43
|
+
};
|
|
44
|
+
required: string[];
|
|
45
|
+
};
|
|
46
|
+
} | {
|
|
47
|
+
name: string;
|
|
48
|
+
description: string;
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: string;
|
|
51
|
+
properties: {
|
|
52
|
+
asset_id: {
|
|
53
|
+
type: string;
|
|
54
|
+
description: string;
|
|
55
|
+
};
|
|
56
|
+
theme_id?: undefined;
|
|
57
|
+
include?: undefined;
|
|
58
|
+
};
|
|
59
|
+
required: string[];
|
|
60
|
+
};
|
|
61
|
+
})[];
|
|
62
|
+
export declare function handleBloomTool(name: string, args: unknown): Promise<{
|
|
63
|
+
content: {
|
|
64
|
+
type: "text";
|
|
65
|
+
text: string;
|
|
66
|
+
}[];
|
|
67
|
+
isError?: boolean;
|
|
68
|
+
} | null>;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bloom → Sonance Brand studio assets
|
|
3
|
+
*
|
|
4
|
+
* Serves design languages and motion assets published from the Bloom studio.
|
|
5
|
+
* Directory-derived: each published item is its own JSON file, so there is no
|
|
6
|
+
* shared index to overwrite. These tools read every item file across the
|
|
7
|
+
* built-in Data Viz / Motion sections AND any Bloom-created custom section,
|
|
8
|
+
* so a design language is reachable by id no matter where it's filed.
|
|
9
|
+
*
|
|
10
|
+
* Wired into index.ts with three lines:
|
|
11
|
+
* import { BLOOM_TOOLS, handleBloomTool } from "./bloom-assets.js";
|
|
12
|
+
* ...BLOOM_TOOLS, (inside the ListTools tools array)
|
|
13
|
+
* const bloom = await handleBloomTool(name, args); if (bloom) return bloom;
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from "fs";
|
|
16
|
+
import * as path from "path";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = path.dirname(__filename);
|
|
20
|
+
const BUNDLED_ASSETS = path.join(__dirname, "assets");
|
|
21
|
+
const IS_BUNDLED = fs.existsSync(BUNDLED_ASSETS);
|
|
22
|
+
const DEV_PROJECT_ROOT = path.resolve(__dirname, "../..");
|
|
23
|
+
const SITE_BASE_URL = "https://brand.sonance.com";
|
|
24
|
+
const dataRoot = () => (IS_BUNDLED ? BUNDLED_ASSETS : path.join(DEV_PROJECT_ROOT, "src/data"));
|
|
25
|
+
function readJson(file) {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(fs.readFileSync(file, "utf-8"));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Every item file in a directory (skip the legacy index + section-meta files).
|
|
34
|
+
function itemsInDir(dir) {
|
|
35
|
+
try {
|
|
36
|
+
return fs
|
|
37
|
+
.readdirSync(dir)
|
|
38
|
+
.filter((f) => f.endsWith(".json") && f !== "index.json" && !f.startsWith("_"))
|
|
39
|
+
.map((f) => readJson(path.join(dir, f)))
|
|
40
|
+
.filter(Boolean);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function sections() {
|
|
47
|
+
return readJson(path.join(dataRoot(), "sections.json"))?.sections || [];
|
|
48
|
+
}
|
|
49
|
+
// Built-in dir for a kind + every custom section of that kind.
|
|
50
|
+
function sourceDirs(kind) {
|
|
51
|
+
const out = [{ dir: path.join(dataRoot(), kind), section: kind === "dataviz" ? "Data Viz" : "Motion" }];
|
|
52
|
+
for (const s of sections())
|
|
53
|
+
if (s.kind === kind)
|
|
54
|
+
out.push({ dir: path.join(dataRoot(), "sections", s.slug), section: s.name });
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
function text(t) {
|
|
58
|
+
return { content: [{ type: "text", text: t }] };
|
|
59
|
+
}
|
|
60
|
+
function errorText(t) {
|
|
61
|
+
return { content: [{ type: "text", text: t }], isError: true };
|
|
62
|
+
}
|
|
63
|
+
const DATAVIZ_USAGE = `## Using a Bloom data-viz language
|
|
64
|
+
|
|
65
|
+
1. **Tokens first.** Import the theme's tokens CSS (all variables are prefixed \`--viz-*\`,
|
|
66
|
+
with a \`[data-theme="dark"]\` block). Never hardcode the hex values in app code.
|
|
67
|
+
2. **Categorical order is fixed.** Series take colors in the exact order of
|
|
68
|
+
\`categorical[0..7]\` — slot 0 is the accent/primary series. Do not re-sort by preference;
|
|
69
|
+
the ordering is CVD-verified (adjacent-color deltas are checked for deuteranopia/protanopia).
|
|
70
|
+
3. **Recharts.** The \`recharts\` export is a ready ChartConfig-style module for the Sonance
|
|
71
|
+
\`@/components/ui/chart\` wrapper (ChartContainer). Use \`vizConfig\`/\`VIZ_CARTESIAN\` from it.
|
|
72
|
+
4. **Sequential / diverging / status** ramps are included for heatmaps, deltas, and states.
|
|
73
|
+
5. **Marks** (bar radius, line width, area alpha, glow) and **motion** (duration, easing,
|
|
74
|
+
stagger) are part of the language — apply them, don't restyle per chart.`;
|
|
75
|
+
export const BLOOM_TOOLS = [
|
|
76
|
+
{
|
|
77
|
+
name: "list_dataviz_themes",
|
|
78
|
+
description: "Lists the data-viz design languages published from the Bloom studio (bar/line/area/donut/scatter/heatmap etc. styling: categorical palettes, sequential/diverging ramps, marks, motion) across all brand sections. Use get_dataviz_theme for the full payload.",
|
|
79
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "get_dataviz_theme",
|
|
83
|
+
description: "Returns a published Bloom data-viz language: the full bloom-viz-theme/v1 JSON (light+dark palettes, marks, motion, chrome), its CSS custom-property tokens, and a Recharts config for the Sonance chart component. Use list_dataviz_themes to see available ids.",
|
|
84
|
+
inputSchema: {
|
|
85
|
+
type: "object",
|
|
86
|
+
properties: {
|
|
87
|
+
theme_id: { type: "string", description: "Registry id of the theme (e.g. 'teal-ignition')." },
|
|
88
|
+
include: {
|
|
89
|
+
type: "string",
|
|
90
|
+
enum: ["all", "theme", "tokens", "recharts"],
|
|
91
|
+
description: "Which payload to return. Defaults to 'all'.",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
required: ["theme_id"],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "list_motion_assets",
|
|
99
|
+
description: "Lists motion/brand assets published from the Bloom studio (animated logo treatments, generative scenes, living data murals) across all brand sections, with their public URLs.",
|
|
100
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "get_motion_asset",
|
|
104
|
+
description: "Returns a published Bloom motion asset's metadata, story, and public URLs (video + poster) for embedding. Use list_motion_assets to see available ids.",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: { asset_id: { type: "string", description: "Registry id of the motion asset." } },
|
|
108
|
+
required: ["asset_id"],
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
export async function handleBloomTool(name, args) {
|
|
113
|
+
switch (name) {
|
|
114
|
+
case "list_dataviz_themes": {
|
|
115
|
+
const rows = [];
|
|
116
|
+
for (const { dir, section } of sourceDirs("dataviz"))
|
|
117
|
+
for (const t of itemsInDir(dir))
|
|
118
|
+
rows.push({
|
|
119
|
+
id: t.id,
|
|
120
|
+
label: t.label,
|
|
121
|
+
brand: t.brand,
|
|
122
|
+
section,
|
|
123
|
+
scope: t.scope?.kind === "component" ? `single component (${t.scope.form})` : "full library",
|
|
124
|
+
publishedAt: t.publishedAt,
|
|
125
|
+
});
|
|
126
|
+
if (!rows.length)
|
|
127
|
+
return text("No data-viz languages have been published yet. They arrive via Bloom publish PRs.");
|
|
128
|
+
return text(`# Bloom data-viz languages (${rows.length})\n\n` +
|
|
129
|
+
JSON.stringify(rows, null, 2) +
|
|
130
|
+
`\n\nCall get_dataviz_theme with a theme_id for tokens + palettes + Recharts config.`);
|
|
131
|
+
}
|
|
132
|
+
case "get_dataviz_theme": {
|
|
133
|
+
const { theme_id, include = "all" } = args || {};
|
|
134
|
+
if (!theme_id)
|
|
135
|
+
return errorText("theme_id is required — call list_dataviz_themes for ids.");
|
|
136
|
+
let payload = null;
|
|
137
|
+
const known = [];
|
|
138
|
+
for (const { dir } of sourceDirs("dataviz")) {
|
|
139
|
+
for (const t of itemsInDir(dir)) {
|
|
140
|
+
known.push(t.id);
|
|
141
|
+
if (t.id === theme_id)
|
|
142
|
+
payload = t;
|
|
143
|
+
}
|
|
144
|
+
if (payload)
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
if (!payload)
|
|
148
|
+
return errorText(`Unknown theme '${theme_id}'. Available: ${known.join(", ") || "(none)"}`);
|
|
149
|
+
const parts = [`# ${payload.label} — Bloom data-viz language (${payload.brand})`];
|
|
150
|
+
if (payload.story?.description)
|
|
151
|
+
parts.push(payload.story.description);
|
|
152
|
+
if (include === "all" || include === "theme")
|
|
153
|
+
parts.push(`## Theme JSON (bloom-viz-theme/v1)\n\n\`\`\`json\n${JSON.stringify(payload.theme, null, 2)}\n\`\`\``);
|
|
154
|
+
if (include === "all" || include === "tokens")
|
|
155
|
+
parts.push(`## Tokens CSS\n\n\`\`\`css\n${payload.tokensCss || "/* not included */"}\n\`\`\``);
|
|
156
|
+
if (include === "all" || include === "recharts")
|
|
157
|
+
parts.push(`## Recharts config (for @/components/ui/chart)\n\n\`\`\`ts\n${payload.recharts || "// not included"}\n\`\`\``);
|
|
158
|
+
parts.push(DATAVIZ_USAGE);
|
|
159
|
+
parts.push(`Live specimens: ${SITE_BASE_URL}/dataviz`);
|
|
160
|
+
return text(parts.join("\n\n"));
|
|
161
|
+
}
|
|
162
|
+
case "list_motion_assets": {
|
|
163
|
+
const rows = [];
|
|
164
|
+
for (const { dir, section } of sourceDirs("motion"))
|
|
165
|
+
for (const a of itemsInDir(dir))
|
|
166
|
+
rows.push({
|
|
167
|
+
id: a.id,
|
|
168
|
+
name: a.name,
|
|
169
|
+
kind: a.kind,
|
|
170
|
+
brand: a.brand,
|
|
171
|
+
section,
|
|
172
|
+
url: `${SITE_BASE_URL}${a.file}`,
|
|
173
|
+
poster: a.poster ? `${SITE_BASE_URL}${a.poster}` : null,
|
|
174
|
+
publishedAt: a.publishedAt,
|
|
175
|
+
});
|
|
176
|
+
if (!rows.length)
|
|
177
|
+
return text("No motion assets have been published yet. They arrive via Bloom publish PRs.");
|
|
178
|
+
return text(`# Bloom motion assets (${rows.length})\n\n` + JSON.stringify(rows, null, 2));
|
|
179
|
+
}
|
|
180
|
+
case "get_motion_asset": {
|
|
181
|
+
const { asset_id } = args || {};
|
|
182
|
+
if (!asset_id)
|
|
183
|
+
return errorText("asset_id is required — call list_motion_assets for ids.");
|
|
184
|
+
let a = null;
|
|
185
|
+
for (const { dir } of sourceDirs("motion")) {
|
|
186
|
+
a = itemsInDir(dir).find((x) => x.id === asset_id);
|
|
187
|
+
if (a)
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
if (!a)
|
|
191
|
+
return errorText(`Unknown motion asset '${asset_id}'.`);
|
|
192
|
+
const lines = [
|
|
193
|
+
`# ${a.name} (${a.kind})`,
|
|
194
|
+
a.story?.description || "",
|
|
195
|
+
"",
|
|
196
|
+
`- Video: ${SITE_BASE_URL}${a.file}`,
|
|
197
|
+
a.poster ? `- Poster: ${SITE_BASE_URL}${a.poster}` : "",
|
|
198
|
+
`- Brand: ${a.brand} · Published ${a.publishedAt}`,
|
|
199
|
+
"",
|
|
200
|
+
`Embed:\n\`\`\`html\n<video src="${SITE_BASE_URL}${a.file}"${a.poster ? ` poster="${SITE_BASE_URL}${a.poster}"` : ""} autoplay loop muted playsinline></video>\n\`\`\``,
|
|
201
|
+
].filter(Boolean);
|
|
202
|
+
return text(lines.join("\n"));
|
|
203
|
+
}
|
|
204
|
+
default:
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import * as path from "path";
|
|
|
7
7
|
import * as os from "os";
|
|
8
8
|
import { fileURLToPath } from "url";
|
|
9
9
|
import { execSync } from "child_process";
|
|
10
|
+
import { BLOOM_TOOLS, handleBloomTool } from "./bloom-assets.js";
|
|
10
11
|
// sharp is dynamically imported — optional for .mcpb builds where native modules aren't bundled
|
|
11
12
|
import { formatCodeBlock, } from "./utils/response-formatter.js";
|
|
12
13
|
import { RESPONSIVE_BREAKPOINTS, SECTION_PATTERNS, PAGE_COMPOSITIONS, DESIGN_REFERENCE_URLS, COMPOSITION_PRINCIPLES, ANIMATION_SYSTEM, DOCUMENT_PATTERNS, detectLayoutType, detectOutputType, } from "./layout-references.js";
|
|
@@ -1501,15 +1502,15 @@ function getImageMimeType(filePath) {
|
|
|
1501
1502
|
* Dark = logo for dark backgrounds (typically lighter/reversed logo)
|
|
1502
1503
|
*/
|
|
1503
1504
|
const LOGO_MAP = {
|
|
1504
|
-
//
|
|
1505
|
+
// Sonance standalone logo — the default brand mark (no tri-brand lockup)
|
|
1505
1506
|
default: {
|
|
1506
|
-
light: "/logos/sonance
|
|
1507
|
-
dark: "/logos/sonance
|
|
1507
|
+
light: "/logos/sonance/Sonance_Logo_2C_Dark_RGB.png",
|
|
1508
|
+
dark: "/logos/sonance/Sonance_Logo_2C_Light_RGB.png",
|
|
1508
1509
|
},
|
|
1509
1510
|
// Horizontal lockup — for navbars/footers where a wide, thin logo is intentional
|
|
1510
1511
|
"default-horizontal": {
|
|
1511
|
-
light: "/logos/sonance
|
|
1512
|
-
dark: "/logos/sonance
|
|
1512
|
+
light: "/logos/sonance/Sonance_Logo_2C_Dark_RGB.png",
|
|
1513
|
+
dark: "/logos/sonance/Sonance_Logo_2C_Light_RGB.png",
|
|
1513
1514
|
},
|
|
1514
1515
|
sonance: {
|
|
1515
1516
|
light: "/logos/sonance/Sonance_Logo_2C_Dark_RGB.png",
|
|
@@ -2804,6 +2805,8 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
2804
2805
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
2805
2806
|
return {
|
|
2806
2807
|
tools: [
|
|
2808
|
+
// Bloom studio assets (dataviz languages + motion) — data-driven, see bloom-assets.ts
|
|
2809
|
+
...BLOOM_TOOLS,
|
|
2807
2810
|
{
|
|
2808
2811
|
name: "get_brand_guidelines",
|
|
2809
2812
|
description: "Returns the complete Sonance Brand Guidelines including colors, typography rules, logo usage, and design principles for Sonance, IPORT, and Blaze Audio brands.",
|
|
@@ -2946,7 +2949,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
2946
2949
|
logo_preference: {
|
|
2947
2950
|
type: "string",
|
|
2948
2951
|
enum: ["default", "sonance", "iport", "blaze", "james"],
|
|
2949
|
-
description: "Which logo to use. 'default' = Sonance
|
|
2952
|
+
description: "Which logo to use. 'default' = standalone Sonance logo. Or specify 'sonance', 'iport', 'blaze', or 'james' for individual brand logos. Defaults to 'default' if not specified.",
|
|
2950
2953
|
},
|
|
2951
2954
|
output_type: {
|
|
2952
2955
|
type: "string",
|
|
@@ -3039,7 +3042,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3039
3042
|
},
|
|
3040
3043
|
{
|
|
3041
3044
|
name: "rebrand_document",
|
|
3042
|
-
description: "Returns universal rebranding instructions for converting ANY existing document to a specific brand (Sonance, IPORT, or Blaze) with mandatory content preservation workflow, non-Latin character handling, page break management, and AUTO-EMBEDDED logo variants. Provides color replacements, font substitutions, and logo placement rules. Default: Sonance
|
|
3045
|
+
description: "Returns universal rebranding instructions for converting ANY existing document to a specific brand (Sonance, IPORT, or Blaze) with mandatory content preservation workflow, non-Latin character handling, page break management, and AUTO-EMBEDDED logo variants. Provides color replacements, font substitutions, and logo placement rules. Default: standalone Sonance logo for Sonance brand.",
|
|
3043
3046
|
inputSchema: {
|
|
3044
3047
|
type: "object",
|
|
3045
3048
|
properties: {
|
|
@@ -3209,6 +3212,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
3209
3212
|
});
|
|
3210
3213
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
3211
3214
|
const { name, arguments: args } = request.params;
|
|
3215
|
+
// Bloom studio asset tools are handled in their own module (bloom-assets.ts)
|
|
3216
|
+
const bloomResult = await handleBloomTool(name, args);
|
|
3217
|
+
if (bloomResult)
|
|
3218
|
+
return bloomResult;
|
|
3212
3219
|
switch (name) {
|
|
3213
3220
|
case "get_brand_guidelines": {
|
|
3214
3221
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.7",
|
|
4
4
|
"description": "MCP Server for Sonance Brand Guidelines and Component Library - gives Claude instant access to brand colors, typography, and UI components.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|