@brewedby/ds 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,492 @@
1
+ /*
2
+ * fynd-tokens.css
3
+ * Fynd One Design System — CSS Custom Properties
4
+ * Source of truth: One Design System (Figma) + devlink/global.css
5
+ * Last synced: March 2026
6
+ *
7
+ * USAGE:
8
+ * HTML: <link rel="stylesheet" href="fynd-tokens.css">
9
+ * CSS: @import 'fynd-tokens.css';
10
+ * JS/TS: import './fynd-tokens.css';
11
+ * Astro: import '../styles/fynd-tokens.css';
12
+ *
13
+ * Always import this file BEFORE any component CSS.
14
+ * Do NOT override tokens directly — extend via semantic aliases.
15
+ */
16
+
17
+ /* ─────────────────────────────────────────────────────
18
+ FONTS
19
+ ─────────────────────────────────────────────────────
20
+
21
+ FYND SANS (proprietary — titles / headings)
22
+ ─────────────────────────────────────────────
23
+ Self-hosted only. Font files must be placed at:
24
+ /assets/fonts/FyndSans-Regular.woff2
25
+ /assets/fonts/FyndSans-Medium.woff2
26
+ /assets/fonts/FyndSans-SemiBold.woff2
27
+ /assets/fonts/FyndSans-Bold.woff2
28
+
29
+ Source: Fynd brand team / design assets repo.
30
+ Do NOT load via Google Fonts or any public CDN.
31
+ Contact design@fynd.com to obtain the font files.
32
+ ─────────────────────────────────────────────────────
33
+ */
34
+
35
+ @font-face {
36
+ font-family: 'Fynd Sans';
37
+ src: url('/assets/fonts/FyndSans-Regular.woff2') format('woff2');
38
+ font-weight: 400;
39
+ font-style: normal;
40
+ font-display: swap;
41
+ }
42
+ @font-face {
43
+ font-family: 'Fynd Sans';
44
+ src: url('/assets/fonts/FyndSans-Medium.woff2') format('woff2');
45
+ font-weight: 500;
46
+ font-style: normal;
47
+ font-display: swap;
48
+ }
49
+ @font-face {
50
+ font-family: 'Fynd Sans';
51
+ src: url('/assets/fonts/FyndSans-SemiBold.woff2') format('woff2');
52
+ font-weight: 600;
53
+ font-style: normal;
54
+ font-display: swap;
55
+ }
56
+ @font-face {
57
+ font-family: 'Fynd Sans';
58
+ src: url('/assets/fonts/FyndSans-Bold.woff2') format('woff2');
59
+ font-weight: 700;
60
+ font-style: normal;
61
+ font-display: swap;
62
+ }
63
+
64
+ /*
65
+ INTER DISPLAY (body text)
66
+ Source: Google Fonts CDN or self-hosted via @fontsource/inter-display
67
+ npm: npm install @fontsource/inter-display
68
+ */
69
+ @import url('https://fonts.googleapis.com/css2?family=Inter+Display:wght@400;500;600;700&display=swap');
70
+
71
+ /*
72
+ INTER (buttons / UI labels)
73
+ Source: Google Fonts CDN or self-hosted via @fontsource/inter
74
+ npm: npm install @fontsource/inter
75
+ */
76
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
77
+
78
+ /* ─────────────────────────────────────────────────────
79
+ ICON LIBRARY
80
+ Source: Lucide Icons (MIT license)
81
+ CDN: https://unpkg.com/lucide@latest
82
+ npm: npm install lucide / npm install lucide-react
83
+ Docs: https://lucide.dev
84
+ Usage (HTML): <i data-lucide="shopping-bag"></i>
85
+ <script src="https://unpkg.com/lucide@latest"></script>
86
+ <script>lucide.createIcons();</script>
87
+ Usage (React): import { ShoppingBag } from 'lucide-react'
88
+ Usage (Astro): import { ShoppingBag } from 'lucide-react' (with React integration)
89
+ Stroke width convention: 1.5px (matches Fynd icon style)
90
+ Size convention: 16px (ui), 20px (feature), 24px (decorative)
91
+ ───────────────────────────────────────────────────── */
92
+
93
+ :root {
94
+ --icon-stroke-width: 1.5px;
95
+ --icon-size-ui: 16px;
96
+ --icon-size-feature: 20px;
97
+ --icon-size-decorative: 24px;
98
+ }
99
+
100
+ /* ─────────────────────────────────────────────────────
101
+ TYPOGRAPHY
102
+ ───────────────────────────────────────────────────── */
103
+
104
+ :root {
105
+ /* Font families */
106
+ --font-family--primary: 'Fynd Sans', Arial, sans-serif; /* headings / titles — PROPRIETARY, self-host only */
107
+ --font-family--secondary: 'Inter Display', Arial, sans-serif; /* body / subtext */
108
+ --font-family--ui: 'Inter', Arial, sans-serif; /* buttons / labels */
109
+
110
+ /* Figma aliases (slash convention) */
111
+ --typeface--font-family--title: var(--font-family--primary);
112
+ --typeface--font-family--body: var(--font-family--secondary);
113
+ --font-family--sans: var(--font-family--ui);
114
+
115
+ /* Font sizes */
116
+ --font-size--body-xs: 0.75rem; /* 12px */
117
+ --font-size--body-s: 0.875rem; /* 14px */
118
+ --font-size--body-m: 1rem; /* 16px */
119
+ --font-size--body-l: 1.125rem; /* 18px */
120
+ --font-size--body-xl: 1.25rem; /* 20px */
121
+ --font-size--h6: 1rem; /* 16px */
122
+ --font-size--h5: 1.5rem; /* 24px */
123
+ --font-size--h4: 2rem; /* 32px */
124
+ --font-size--h3: 2.5rem; /* 40px */
125
+ --font-size--h2: 3.5rem; /* 56px */
126
+ --font-size--h1: 4.5rem; /* 72px */
127
+
128
+ /* Figma button scale */
129
+ --font-size--ui-s: 0.75rem; /* 12px */
130
+ --font-size--ui-m: 0.875rem; /* 14px — button default */
131
+ --font-size--ui-l: 1rem; /* 16px */
132
+
133
+ /* Font weights */
134
+ --font-weight--regular: 400;
135
+ --font-weight--medium: 500;
136
+ --font-weight--semibold: 600;
137
+ --font-weight--bold: 700;
138
+
139
+ /* Line heights */
140
+ --line-height--110: 1.1;
141
+ --line-height--120: 1.2;
142
+ --line-height--130: 1.3;
143
+ --line-height--140: 1.4;
144
+ --line-height--150: 1.5;
145
+ --line-height--160: 1.6;
146
+ --line-height--170: 1.7;
147
+
148
+ /* Figma line-height aliases */
149
+ --line-height--ui-m: 20px; /* button line-height */
150
+
151
+ /* Letter spacing */
152
+ --letter-spacing--heading-1: -0.04em;
153
+ --letter-spacing--heading-2: -0.04em;
154
+ --letter-spacing--heading-3: -0.03em;
155
+ --letter-spacing--heading-4: -0.02em;
156
+ --letter-spacing--heading-5: -0.02em;
157
+ --letter-spacing--baggy: 0px; /* buttons / UI labels */
158
+ }
159
+
160
+ /* ─────────────────────────────────────────────────────
161
+ COLOR PRIMITIVES — NEUTRALS
162
+ ───────────────────────────────────────────────────── */
163
+
164
+ :root {
165
+ --neutral--neutral-0: #ffffff;
166
+ --neutral--neutral-10: #f8f8f9;
167
+ --neutral--neutral-20: #f2f2f2;
168
+ --neutral--neutral-30: #d7d7d7;
169
+ --neutral--neutral-40: #a0a1a2;
170
+ --neutral--neutral-50: #797a7c;
171
+ --neutral--neutral-60: #5b5c5d;
172
+ --neutral--neutral-80: #4a4b4c;
173
+ --neutral--neutral-100: #0e0e0e; /* canonical — use for text/title */
174
+
175
+ /* ⚠️ devlink neutral-100 is #101319 — use #0e0e0e (Figma) for text, #101319 for dark fill backgrounds */
176
+ --neutral--neutral-100--devlink: #101319;
177
+ }
178
+
179
+ /* ─────────────────────────────────────────────────────
180
+ COLOR PRIMITIVES — BRAND
181
+ ───────────────────────────────────────────────────── */
182
+
183
+ :root {
184
+ /* Blue */
185
+ --blue--blue-10: #f9fbff;
186
+ --blue--blue-20: #d8e2f5;
187
+ --blue--blue-40: #5c98f7;
188
+ --blue--blue-50: #2f7af6;
189
+ --blue--blue-60: #084bb8;
190
+ --blue--blue-90: #07285a;
191
+
192
+ /* Peach */
193
+ --peach--peach-10: #fbf7f4;
194
+ --peach--peach-20: #e7cdbc;
195
+ --peach--peach-40: #f2c49f;
196
+ --peach--peach-50: #eeb384;
197
+ --peach--peach-60: #a4521e;
198
+ --peach--peach-90: #793c16;
199
+
200
+ /* Green */
201
+ --green--green-10: #f4fbf7;
202
+ --green--green-20: #c4d9cd;
203
+ --green--green-40: #a2ddb7;
204
+ --green--green-50: #80d99f;
205
+ --green--green-60: #187b3f;
206
+ --green--green-90: #124f2a;
207
+
208
+ /* Gold */
209
+ --gold--gold-10: #fdf5db;
210
+ --gold--gold-20: #fbe9ae;
211
+ --gold--gold-40: #f8d160;
212
+ --gold--gold-50: #ebb537;
213
+ --gold--gold-60: #8b6b20;
214
+ --gold--gold-90: #362a0d;
215
+
216
+ /* Lavender */
217
+ --lavender--lavender-10: #f0e9fd;
218
+ --lavender--lavender-20: #ceb8fa;
219
+ --lavender--lavender-40: #8d61f6;
220
+ --lavender--lavender-50: #703ff5;
221
+ --lavender--lavender-60: #4322c8;
222
+ --lavender--lavender-90: #27126c;
223
+
224
+ /* Red */
225
+ --red--red-10: #f8cfd1;
226
+ --red--red-20: #f1a1a4;
227
+ --red--red-40: #ea5252;
228
+ --red--red-50: #e9372e;
229
+ --red--red-60: #a72218;
230
+ --red--red-90: #51110b;
231
+ }
232
+
233
+ /* ─────────────────────────────────────────────────────
234
+ COLOR PALETTE SHORTCUTS (semantic per-brand aliases)
235
+ ───────────────────────────────────────────────────── */
236
+
237
+ :root {
238
+ /* Blue shortcuts */
239
+ --blue--blue-primary: var(--blue--blue-40);
240
+ --blue--blue-text: var(--blue--blue-90);
241
+ --blue--blue-fill: var(--blue--blue-10);
242
+ --blue--blue-stroke: var(--blue--blue-20);
243
+
244
+ /* Peach shortcuts */
245
+ --peach--peach-primary: var(--peach--peach-40);
246
+ --peach--peach-text: var(--peach--peach-90);
247
+ --peach--peach-fill: var(--peach--peach-10);
248
+ --peach--peach-stroke: var(--peach--peach-20);
249
+
250
+ /* Green shortcuts */
251
+ --green--green-primary: var(--green--green-40);
252
+ --green--green-text: var(--green--green-90);
253
+ --green--green-fill: var(--green--green-10);
254
+ --green--green-stroke: var(--green--green-20);
255
+
256
+ /* Gold shortcuts */
257
+ --gold--gold-primary: var(--gold--gold-40);
258
+ --gold--gold-text: var(--gold--gold-90);
259
+ --gold--gold-fill: var(--gold--gold-10);
260
+ --gold--gold-stroke: var(--gold--gold-20);
261
+
262
+ /* Lavender shortcuts */
263
+ --lavender--lavender-primary: var(--lavender--lavender-40);
264
+ --lavender--lavender-text: var(--lavender--lavender-90);
265
+ --lavender--lavender-fill: var(--lavender--lavender-10);
266
+ --lavender--lavender-stroke: var(--lavender--lavender-20);
267
+
268
+ /* Red shortcuts */
269
+ --red--red-primary: var(--red--red-40);
270
+ --red--red-text: var(--red--red-90);
271
+ --red--red-fill: var(--red--red-10);
272
+ --red--red-stroke: var(--red--red-20);
273
+ }
274
+
275
+ /* ─────────────────────────────────────────────────────
276
+ SEMANTIC COLOR ALIASES
277
+ ───────────────────────────────────────────────────── */
278
+
279
+ :root {
280
+ /* Text */
281
+ --text--title: var(--neutral--neutral-100); /* #0e0e0e */
282
+ --text--subtext: var(--neutral--neutral-60); /* #5b5c5d */
283
+ --text--title-inverse: var(--neutral--neutral-0); /* #ffffff */
284
+ --text--subtext-inverse: var(--neutral--neutral-40); /* #a0a1a2 */
285
+
286
+ /* Figma slash aliases (use in components from Figma) */
287
+ --text--title-figma: #0e0e0e;
288
+ --text--subtext-figma: #5b5c5d;
289
+
290
+ /* Backgrounds */
291
+ --background--background-light: var(--neutral--neutral-0); /* white */
292
+ --background--background-medium: var(--neutral--neutral-10); /* #f8f8f9 */
293
+ --background--background-dark: var(--neutral--neutral-60); /* #5b5c5d */
294
+ --background--background-darkest: #0e0e0e; /* near-black */
295
+
296
+ /* Borders */
297
+ --border--border-light: var(--neutral--neutral-10); /* #f8f8f9 */
298
+ --border--border-medium: var(--neutral--neutral-20); /* #f2f2f2 */
299
+ --border--border-dark: var(--neutral--neutral-50); /* #797a7c */
300
+ --border--border-darkest: var(--neutral--neutral-80); /* #4a4b4c */
301
+
302
+ /* Status (feature comparison / data tables) */
303
+ --status--yes: #0d7a3a;
304
+ --status--partial: #9a6700;
305
+ --status--no: #c13515;
306
+ }
307
+
308
+ /* ─────────────────────────────────────────────────────
309
+ SPACING SCALE
310
+ ───────────────────────────────────────────────────── */
311
+
312
+ :root {
313
+ --spacing--4: 0.25rem; /* 4px */
314
+ --spacing--8: 0.5rem; /* 8px */
315
+ --spacing--12: 0.75rem; /* 12px */
316
+ --spacing--16: 1rem; /* 16px */
317
+ --spacing--20: 1.25rem; /* 20px */
318
+ --spacing--24: 1.5rem; /* 24px */
319
+ --spacing--32: 2rem; /* 32px */
320
+ --spacing--40: 2.5rem; /* 40px */
321
+ --spacing--56: 3.5rem; /* 56px */
322
+ --spacing--80: 5rem; /* 80px */
323
+ --spacing--120: 7.5rem; /* 120px */
324
+
325
+ /* Figma shorthand aliases (use when building from Figma components) */
326
+ --4: var(--spacing--4);
327
+ --8: var(--spacing--8);
328
+ --12: var(--spacing--12);
329
+ --16: var(--spacing--16);
330
+ --20: var(--spacing--20);
331
+ --24: var(--spacing--24);
332
+ --32: var(--spacing--32);
333
+ --40: var(--spacing--40);
334
+ --56: var(--spacing--56);
335
+ --80: var(--spacing--80);
336
+ --120: var(--spacing--120);
337
+ }
338
+
339
+ /* ─────────────────────────────────────────────────────
340
+ SIZES SCALE (general-purpose)
341
+ ───────────────────────────────────────────────────── */
342
+
343
+ :root {
344
+ --sizes--0: 0rem;
345
+ --sizes--2: 0.125rem;
346
+ --sizes--4: 0.25rem;
347
+ --sizes--6: 0.375rem;
348
+ --sizes--8: 0.5rem;
349
+ --sizes--12: 0.75rem;
350
+ --sizes--14: 0.875rem;
351
+ --sizes--16: 1rem;
352
+ --sizes--18: 1.125rem;
353
+ --sizes--20: 1.25rem;
354
+ --sizes--24: 1.5rem;
355
+ --sizes--32: 2rem;
356
+ --sizes--40: 2.5rem;
357
+ --sizes--48: 3rem;
358
+ --sizes--56: 3.5rem;
359
+ --sizes--64: 4rem;
360
+ --sizes--72: 4.5rem;
361
+ --sizes--80: 5rem;
362
+ --sizes--96: 6rem;
363
+ --sizes--128: 8rem;
364
+ --sizes--160: 10rem;
365
+ --sizes--192: 12rem;
366
+ --sizes--256: 16rem;
367
+ }
368
+
369
+ /* ─────────────────────────────────────────────────────
370
+ BORDER RADIUS
371
+ ───────────────────────────────────────────────────── */
372
+
373
+ :root {
374
+ --border-radius--8: 0.5rem; /* 8px — inputs, small cards */
375
+ --border-radius--12: 0.75rem; /* 12px */
376
+ --border-radius--16: 1rem; /* 16px — cards */
377
+ --border-radius--24: 1.5rem; /* 24px — CTA boxes */
378
+ --border-radius--32: 2rem; /* 32px */
379
+ --border-radius--pill: 250px; /* fully rounded — buttons, badges, tags */
380
+ --border-radius--tag: 2000px; /* tag / badge (from Figma) */
381
+
382
+ /* Figma alias */
383
+ --borderradius--core--full: var(--border-radius--pill);
384
+ }
385
+
386
+ /* ─────────────────────────────────────────────────────
387
+ BREAKPOINTS (reference only — use in @media queries)
388
+ ───────────────────────────────────────────────────── */
389
+
390
+ /*
391
+ Desktop: min-width: 992px (default styles)
392
+ Tablet: max-width: 991px (Webflow convention)
393
+ Tablet alt: max-width: 1023px (compare page)
394
+ Mobile: max-width: 767px
395
+ Small mobile: max-width: 479px
396
+ */
397
+
398
+ /* ─────────────────────────────────────────────────────
399
+ LAYOUT CONSTANTS
400
+ ───────────────────────────────────────────────────── */
401
+
402
+ :root {
403
+ --layout--container-max: 1200px;
404
+ --layout--container-padding: var(--spacing--32); /* desktop */
405
+ --layout--container-padding-mobile: 1.25rem;
406
+ --layout--section-header-max: 720px;
407
+ --layout--hero-content-max: 720px;
408
+ --layout--cta-content-max: 640px;
409
+ --layout--section-gap: var(--spacing--80);
410
+ --layout--narrative-gap: 3rem;
411
+ --layout--cards-gap: var(--spacing--24);
412
+ }
413
+
414
+ /* ─────────────────────────────────────────────────────
415
+ COMPONENT TOKENS — BUTTONS
416
+ ───────────────────────────────────────────────────── */
417
+
418
+ :root {
419
+ --btn--padding-y: 0.875rem;
420
+ --btn--padding-x: 1.75rem;
421
+ --btn--padding-y-lg: 1rem;
422
+ --btn--padding-x-lg: 2rem;
423
+ --btn--border-radius: var(--border-radius--pill); /* fully rounded */
424
+ --btn--font-family: var(--font-family--ui);
425
+ --btn--font-size: var(--font-size--ui-m); /* 14px */
426
+ --btn--font-weight: var(--font-weight--medium); /* 500 */
427
+ --btn--line-height: var(--line-height--ui-m); /* 20px */
428
+ --btn--letter-spacing: var(--letter-spacing--baggy); /* 0px */
429
+ --btn--transition: background-color 0.2s, border-color 0.2s, color 0.2s;
430
+
431
+ /* Primary (dark) */
432
+ --btn--primary--bg: #0e0e0e;
433
+ --btn--primary--color: #ffffff;
434
+ --btn--primary--bg-hover: #2a2d36;
435
+
436
+ /* Primary light (on dark backgrounds) */
437
+ --btn--primary-light--bg: #ffffff;
438
+ --btn--primary-light--color: #0e0e0e;
439
+ --btn--primary-light--bg-hover: #e8e8e8;
440
+
441
+ /* Secondary */
442
+ --btn--secondary--bg: transparent;
443
+ --btn--secondary--color: #0e0e0e;
444
+ --btn--secondary--border: var(--neutral--neutral-30);
445
+ --btn--secondary--bg-hover: #f5f5f5;
446
+ --btn--secondary--border-hover: var(--neutral--neutral-40);
447
+
448
+ /* Secondary light (on dark backgrounds) */
449
+ --btn--secondary-light--bg: transparent;
450
+ --btn--secondary-light--color: #ffffff;
451
+ --btn--secondary-light--border: #444444;
452
+ --btn--secondary-light--bg-hover: rgba(255, 255, 255, 0.05);
453
+ --btn--secondary-light--border-hover: #666666;
454
+ }
455
+
456
+ /* ─────────────────────────────────────────────────────
457
+ COMPONENT TOKENS — BADGES / TAGS
458
+ ───────────────────────────────────────────────────── */
459
+
460
+ :root {
461
+ --badge--padding-y: var(--spacing--8);
462
+ --badge--padding-x: var(--spacing--12);
463
+ --badge--border-radius: var(--border-radius--tag); /* 2000px */
464
+ --badge--font-size: var(--font-size--body-xs); /* 12px */
465
+ --badge--font-weight: var(--font-weight--regular);
466
+ --badge--line-height: var(--line-height--130);
467
+ }
468
+
469
+ /* ─────────────────────────────────────────────────────
470
+ COMPONENT TOKENS — CARDS
471
+ ───────────────────────────────────────────────────── */
472
+
473
+ :root {
474
+ /* Verdict card */
475
+ --card--verdict--bg: var(--neutral--neutral-10);
476
+ --card--verdict--radius: var(--border-radius--16);
477
+ --card--verdict--padding: var(--spacing--32);
478
+ --card--verdict--gap: 0.75rem;
479
+ --card--verdict--stat-font: var(--font-family--primary);
480
+ --card--verdict--stat-size: 3rem;
481
+ --card--verdict--stat-weight: var(--font-weight--medium);
482
+
483
+ /* Pricing card */
484
+ --card--pricing--border: 1px solid var(--neutral--neutral-20);
485
+ --card--pricing--radius: var(--border-radius--16);
486
+ --card--pricing--padding: 2.5rem 2rem;
487
+ --card--pricing--gap: var(--spacing--24);
488
+ --card--pricing--price-font: var(--font-family--primary);
489
+ --card--pricing--price-size: 2.5rem;
490
+ --card--pricing--price-weight: var(--font-weight--medium);
491
+ --card--pricing--recommended-border: 2px solid #0e0e0e;
492
+ }