@carbonid1/design-system 5.2.3 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -64,20 +64,20 @@ export default function RootLayout({ children }: { children: React.ReactNode })
64
64
 
65
65
  ## Components
66
66
 
67
- | Component | Use for |
68
- | --- | --- |
69
- | `Badge` | Compact status/label chip with variants |
70
- | `Button` | Standard button primitive with variants (`ghost`, `primary`, `outline`, `destructive`, `attention`, `subtle`, `danger`, `link`) |
71
- | `Kbd` | Keyboard key display (`⌘K`, `⇧B`) |
72
- | `ProgressRing` | Circular progress indicator |
73
- | `Slider` | Range slider |
74
- | `ContextMenu` | Right-click / long-press menu (compound API) |
75
- | `Select` | Custom dropdown — never use native `<select>` |
76
- | `Tooltip` | Hover/focus tooltip (wraps a single child) |
77
- | `Toaster` | Toast notification root (renders once in layout) |
78
- | `toast` | Imperative toast trigger (re-export from `sonner`) |
79
- | `ThemeProvider` | Wraps `next-themes` — provides dark/light mode |
80
- | `ThemeCycler` | `shift+t` hotkey cycles `system → light → dark` with toast |
67
+ | Component | Use for |
68
+ | --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
69
+ | `Badge` | Compact status/label chip with variants |
70
+ | `Button` | Standard button primitive with variants (`ghost`, `primary`, `outline`, `destructive`, `attention`, `subtle`, `danger`, `link`) |
71
+ | `Kbd` | Keyboard key display (`⌘K`, `⇧B`) |
72
+ | `ProgressRing` | Circular progress indicator |
73
+ | `Slider` | Range slider |
74
+ | `ContextMenu` | Right-click / long-press menu (compound API) |
75
+ | `Select` | Custom dropdown — never use native `<select>` |
76
+ | `Tooltip` | Hover/focus tooltip (wraps a single child) |
77
+ | `Toaster` | Toast notification root (renders once in layout) |
78
+ | `toast` | Imperative toast trigger (re-export from `sonner`) |
79
+ | `ThemeProvider` | Wraps `next-themes` — provides dark/light mode |
80
+ | `ThemeCycler` | `shift+t` hotkey cycles `system → light → dark` with toast |
81
81
 
82
82
  ## Helpers
83
83
 
@@ -0,0 +1,16 @@
1
+ import type { ElementType } from 'react';
2
+ import type { TextProps } from './Text.types';
3
+ /**
4
+ * `variant` owns the type *scale* only (size + weight + line-height + tracking).
5
+ * Font family (`font`) and `color` are kept orthogonal to it, so a single scale
6
+ * composes with any font family or color context.
7
+ */
8
+ declare const textVariants: (props?: ({
9
+ variant?: "title" | "heading" | "display" | "body" | "caption" | "label" | "subheading" | "bodyLg" | "overline" | null | undefined;
10
+ color?: "default" | "primary" | "success" | "attention" | "destructive" | "highlight" | "muted" | null | undefined;
11
+ font?: "sans" | "serif" | "mono" | null | undefined;
12
+ weight?: "bold" | "regular" | "medium" | "semibold" | null | undefined;
13
+ align?: "end" | "center" | "start" | null | undefined;
14
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
15
+ declare const Text: <E extends ElementType = "p">({ as, variant, color, font, weight, align, numeric, truncate, className, ...props }: TextProps<E>) => import("react/jsx-runtime").JSX.Element;
16
+ export { Text, textVariants };
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from '../helpers/cn/cn';
3
+ import { cva } from 'class-variance-authority';
4
+ /**
5
+ * `variant` owns the type *scale* only (size + weight + line-height + tracking).
6
+ * Font family (`font`) and `color` are kept orthogonal to it, so a single scale
7
+ * composes with any font family or color context.
8
+ */
9
+ const textVariants = cva('', {
10
+ variants: {
11
+ variant: {
12
+ display: 'text-2xl font-semibold tracking-tight leading-tight',
13
+ title: 'text-xl font-semibold tracking-tight leading-tight',
14
+ heading: 'text-lg font-semibold leading-snug',
15
+ subheading: 'text-base font-medium leading-snug',
16
+ body: 'text-sm leading-normal',
17
+ bodyLg: 'text-base leading-relaxed',
18
+ label: 'text-sm font-medium leading-normal',
19
+ caption: 'text-xs leading-normal',
20
+ overline: 'text-xs font-medium uppercase tracking-wide leading-normal',
21
+ },
22
+ // Semantic tokens only. `destructive` has no `-foreground` token; the others do.
23
+ color: {
24
+ default: 'text-foreground',
25
+ muted: 'text-muted-foreground',
26
+ primary: 'text-primary',
27
+ destructive: 'text-destructive',
28
+ success: 'text-success-foreground',
29
+ attention: 'text-attention-foreground',
30
+ highlight: 'text-highlight-foreground',
31
+ },
32
+ // Left unset by default so an ancestor font-family cascades.
33
+ font: {
34
+ sans: 'font-sans',
35
+ serif: 'font-serif',
36
+ mono: 'font-mono',
37
+ },
38
+ // Optional override of the weight baked into `variant`.
39
+ weight: {
40
+ regular: 'font-normal',
41
+ medium: 'font-medium',
42
+ semibold: 'font-semibold',
43
+ bold: 'font-bold',
44
+ },
45
+ align: {
46
+ start: 'text-start',
47
+ center: 'text-center',
48
+ end: 'text-end',
49
+ },
50
+ },
51
+ // No default `color`/`font` — color is resolved per-variant below, font is inherited.
52
+ defaultVariants: { variant: 'body' },
53
+ });
54
+ /** Variants that read as secondary chrome and default to the muted token. */
55
+ const MUTED_VARIANTS = new Set(['caption', 'overline']);
56
+ const Text = ({ as, variant = 'body', color, font, weight, align, numeric, truncate, className, ...props }) => {
57
+ const Component = (as ?? 'p');
58
+ const resolvedColor = color ?? (variant && MUTED_VARIANTS.has(variant) ? 'muted' : 'default');
59
+ return (_jsx(Component, { className: cn(textVariants({ variant, color: resolvedColor, font, weight, align }), numeric && 'tabular-nums', truncate && 'truncate', className), ...props }));
60
+ };
61
+ export { Text, textVariants };
@@ -0,0 +1,20 @@
1
+ import type { ElementType, ComponentPropsWithoutRef } from 'react';
2
+ import type { VariantProps } from 'class-variance-authority';
3
+ import type { textVariants } from './Text';
4
+ type TextOwnProps<E extends ElementType = 'p'> = VariantProps<typeof textVariants> & {
5
+ /** Override the rendered element. Defaults to `p`. Decoupled from `variant` — pick `as` for semantics (`h1`–`h6`, `span`, `label`), `variant` for the look. Element-specific props follow (e.g. `href` when `as="a"`). */
6
+ as?: E;
7
+ /** Tabular (fixed-width) digits for numeric columns, timers, and metrics. */
8
+ numeric?: boolean;
9
+ /** Clamp to a single line with an ellipsis (Tailwind's `truncate`). */
10
+ truncate?: boolean;
11
+ className?: string;
12
+ };
13
+ /**
14
+ * Props for `<Text>`. Generic over the rendered element so element-specific
15
+ * attributes resolve correctly (e.g. `href` is available when `as="a"`).
16
+ */
17
+ type TextProps<E extends ElementType = 'p'> = TextOwnProps<E> & Omit<ComponentPropsWithoutRef<E>, keyof TextOwnProps<E>>;
18
+ /** Concrete, non-generic alias for contexts that need a fixed props type (e.g. Storybook args). */
19
+ type TextPropsDefault = TextProps<'p'>;
20
+ export type { TextProps, TextPropsDefault };
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@ export { Button, buttonVariants } from './Button/Button';
4
4
  export type { ButtonProps } from './Button/Button.types';
5
5
  export { Kbd, kbdVariants } from './Kbd/Kbd';
6
6
  export type { KbdProps } from './Kbd/Kbd.types';
7
+ export { Text, textVariants } from './Text/Text';
8
+ export type { TextProps, TextPropsDefault } from './Text/Text.types';
7
9
  export { ProgressRing } from './ProgressRing/ProgressRing';
8
10
  export { Slider } from './Slider/Slider';
9
11
  export { ContextMenu } from './ContextMenu/ContextMenu';
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export { Badge, badgeVariants } from './Badge/Badge';
2
2
  export { Button, buttonVariants } from './Button/Button';
3
3
  export { Kbd, kbdVariants } from './Kbd/Kbd';
4
+ export { Text, textVariants } from './Text/Text';
4
5
  export { ProgressRing } from './ProgressRing/ProgressRing';
5
6
  export { Slider } from './Slider/Slider';
6
7
  export { ContextMenu } from './ContextMenu/ContextMenu';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carbonid1/design-system",
3
- "version": "5.2.3",
3
+ "version": "5.3.0",
4
4
  "description": "Shared React UI primitives + design tokens (themes, postcss config)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -52,6 +52,7 @@
52
52
  "devDependencies": {
53
53
  "@base-ui/react": "^1.4.1",
54
54
  "@storybook/addon-docs": "^10.3.5",
55
+ "@storybook/addon-mcp": "^0.6.0",
55
56
  "@storybook/addon-themes": "^10.3.5",
56
57
  "@storybook/addon-vitest": "^10.3.5",
57
58
  "@storybook/react-vite": "^10.3.5",
@@ -76,7 +77,7 @@
76
77
  },
77
78
  "scripts": {
78
79
  "build": "tsc",
79
- "storybook": "storybook dev -p 6006",
80
+ "storybook": "storybook dev -p 7006",
80
81
  "build-storybook": "storybook build",
81
82
  "test": "vitest --run",
82
83
  "test:watch": "vitest",
@@ -6,7 +6,11 @@ import { fileURLToPath } from 'node:url'
6
6
  const PKG_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..')
7
7
  const SKILL_SRC = join(PKG_DIR, 'skills', 'design-system')
8
8
 
9
- if (!PKG_DIR.includes(`${process.platform === 'win32' ? '\\' : '/'}node_modules${process.platform === 'win32' ? '\\' : '/'}`)) {
9
+ if (
10
+ !PKG_DIR.includes(
11
+ `${process.platform === 'win32' ? '\\' : '/'}node_modules${process.platform === 'win32' ? '\\' : '/'}`,
12
+ )
13
+ ) {
10
14
  process.exit(0)
11
15
  }
12
16
 
@@ -9,17 +9,27 @@ Primitives live in `@carbonid1/design-system`. **Check the package's exports and
9
9
 
10
10
  ```ts
11
11
  import {
12
- Badge, Button, Kbd, ProgressRing, Slider,
13
- ContextMenu, Select, Tooltip,
14
- Toaster, toast,
15
- ThemeProvider, ThemeCycler, useTheme,
16
- cn, getModKey,
12
+ Badge,
13
+ Button,
14
+ Kbd,
15
+ ProgressRing,
16
+ Slider,
17
+ ContextMenu,
18
+ Select,
19
+ Tooltip,
20
+ Toaster,
21
+ toast,
22
+ ThemeProvider,
23
+ ThemeCycler,
24
+ useTheme,
25
+ cn,
26
+ getModKey,
17
27
  } from '@carbonid1/design-system'
18
28
  ```
19
29
 
20
30
  Palettes are chosen by importing one theme CSS per app: `@carbonid1/design-system/themes/reader` (InkVoice) or `/themes/dashboard` (CoI Calculator).
21
31
 
22
- If you're editing `@carbonid1/design-system` itself (adding a primitive, changing a token), read that package's `CLAUDE.md` — this file is for *using* the design system, not building it.
32
+ If you're editing `@carbonid1/design-system` itself (adding a primitive, changing a token), read that package's `CLAUDE.md` — this file is for _using_ the design system, not building it.
23
33
 
24
34
  ## Core rules
25
35
 
@@ -43,12 +53,12 @@ If you're editing `@carbonid1/design-system` itself (adding a primitive, changin
43
53
 
44
54
  Four-tier contract — every themed surface picks one of these tokens. Layering is recessed: cards are sheets on the desk, controls are carved INTO sheets, popovers lift OFF the desk.
45
55
 
46
- | Token | Role | Pair with |
47
- | ------------------ | ---------------------------------------- | ---------------------- |
48
- | `bg-background` | Page (the desk) | — |
49
- | `bg-card` | Raised paper on the desk — peak surface | `shadow-card` |
50
- | `bg-surface-inset` | Inset block carved into a card | `inset-shadow-surface` |
51
- | `bg-popover` | Floating layer above everything | `shadow-popover` |
56
+ | Token | Role | Pair with |
57
+ | ------------------ | --------------------------------------- | ---------------------- |
58
+ | `bg-background` | Page (the desk) | — |
59
+ | `bg-card` | Raised paper on the desk — peak surface | `shadow-card` |
60
+ | `bg-surface-inset` | Inset block carved into a card | `inset-shadow-surface` |
61
+ | `bg-popover` | Floating layer above everything | `shadow-popover` |
52
62
 
53
63
  `bg-surface-inset` covers form inputs, preview boxes, quote blocks, and language tabs. `bg-popover` covers drawers, menus, and command palettes.
54
64
 
@@ -60,10 +70,10 @@ Four-tier contract — every themed surface picks one of these tokens. Layering
60
70
 
61
71
  Two tiers. Pick by how hard the action is to redo, not how scary it feels.
62
72
 
63
- | Severity | Pattern | Example |
64
- | ---------------- | ----------------------------------- | ------------------------------------ |
65
- | **Hard to redo** | Undo toast (5s + Cmd/Ctrl+Z) | Delete a record, remove history item |
66
- | **Easy to redo** | No confirmation | Toggle flag, remove a tag |
73
+ | Severity | Pattern | Example |
74
+ | ---------------- | ---------------------------- | ------------------------------------ |
75
+ | **Hard to redo** | Undo toast (5s + Cmd/Ctrl+Z) | Delete a record, remove history item |
76
+ | **Easy to redo** | No confirmation | Toggle flag, remove a tag |
67
77
 
68
78
  **Undo toast:** action executes immediately → toast with description `${getModKey()}+Z to undo` + "Undo" action button (5s auto-dismiss) → store holds `lastDeleted` for restoration → global `mod+z` hotkey via `react-hotkeys-hook` → sequential deletes overwrite the buffer (only latest is undoable). Never add a modal confirmation for hard-to-redo actions — the undo toast is the confirmation.
69
79
 
@@ -31,41 +31,41 @@ Tokens are defined in `globals.css` (`:root` + `.dark`), bridged in `@theme inli
31
31
 
32
32
  ### Base tokens (from shadcn naming)
33
33
 
34
- | Token | Role | Sub-variants |
35
- | ------------------ | --------------------------------------------------------------- | ------------ |
36
- | `--background` | Page background (the desk) | — |
37
- | `--foreground` | Default text | — |
38
- | `--card` | Raised card surfaces | foreground |
39
- | `--popover` | Floating popover/drawer/menu surfaces | foreground |
40
- | `--surface-inset` | Inset blocks carved into a card (inputs, preview boxes) | — |
41
- | `--primary` | Interactive color (buttons, links, selections, focus, progress) | foreground |
42
- | `--secondary` | Supporting surfaces | foreground |
43
- | `--muted` | De-emphasized surfaces and text | foreground |
44
- | `--accent` | Hover/expanded tints | foreground |
45
- | `--destructive` | Errors, danger | — |
46
- | `--border` | Default borders | — |
47
- | `--input` | Input borders | — |
48
- | `--ring` | Focus rings | — |
34
+ | Token | Role | Sub-variants |
35
+ | ----------------- | --------------------------------------------------------------- | ------------ |
36
+ | `--background` | Page background (the desk) | — |
37
+ | `--foreground` | Default text | — |
38
+ | `--card` | Raised card surfaces | foreground |
39
+ | `--popover` | Floating popover/drawer/menu surfaces | foreground |
40
+ | `--surface-inset` | Inset blocks carved into a card (inputs, preview boxes) | — |
41
+ | `--primary` | Interactive color (buttons, links, selections, focus, progress) | foreground |
42
+ | `--secondary` | Supporting surfaces | foreground |
43
+ | `--muted` | De-emphasized surfaces and text | foreground |
44
+ | `--accent` | Hover/expanded tints | foreground |
45
+ | `--destructive` | Errors, danger | — |
46
+ | `--border` | Default borders | — |
47
+ | `--input` | Input borders | — |
48
+ | `--ring` | Focus rings | — |
49
49
 
50
50
  ### Elevation shadows
51
51
 
52
52
  Each elevated surface pairs with a tuned shadow. Tailwind utilities: `shadow-card`, `inset-shadow-surface`, `shadow-popover`.
53
53
 
54
- | Token | Pairs with | Notes |
55
- | ------------------------ | ------------------ | ---------------------------------------------------- |
56
- | `--card-shadow` | `bg-card` | Subtle drop, neutral or hue-tinted per theme |
57
- | `--surface-inset-shadow` | `bg-surface-inset` | Hairline inset top in light, `none` in dark |
58
- | `--popover-shadow` | `bg-popover` | Stronger drop with larger geometry in dark |
54
+ | Token | Pairs with | Notes |
55
+ | ------------------------ | ------------------ | -------------------------------------------- |
56
+ | `--card-shadow` | `bg-card` | Subtle drop, neutral or hue-tinted per theme |
57
+ | `--surface-inset-shadow` | `bg-surface-inset` | Hairline inset top in light, `none` in dark |
58
+ | `--popover-shadow` | `bg-popover` | Stronger drop with larger geometry in dark |
59
59
 
60
60
  Why dark mode skips the inset shadow: top-edge highlights fake a "light source from above" convention that reads as a sharp border artifact on dark surfaces, not as a soft recess. Tonal contrast (a wider inset-vs-card lightness delta) carries the elevation instead.
61
61
 
62
62
  ### Custom tokens
63
63
 
64
- | Token | Role | Sub-variants |
65
- | ------------- | --------------------------------------------- | ------------------------- |
64
+ | Token | Role | Sub-variants |
65
+ | ------------- | --------------------------------------------------------- | ------------------------- |
66
66
  | `--highlight` | Emphasis accent (e.g. live cursors, selection highlights) | foreground, muted |
67
67
  | `--attention` | Warnings, notices, saved-for-later — "look at this" | foreground, muted, border |
68
- | `--success` | Completion, positive outcomes | foreground |
68
+ | `--success` | Completion, positive outcomes | foreground |
69
69
 
70
70
  ## How to Add a New Semantic Token
71
71
 
@@ -99,7 +99,7 @@ Why dark mode skips the inset shadow: top-edge highlights fake a "light source f
99
99
 
100
100
  ## Surfaces & Elevation
101
101
 
102
- Four-tier contract that every themed surface picks from. Layering is *recessed* (cards are sheets on the desk; inputs are carved INTO sheets; popovers lift OFF the desk) — the inverse of Material's monotonic stack.
102
+ Four-tier contract that every themed surface picks from. Layering is _recessed_ (cards are sheets on the desk; inputs are carved INTO sheets; popovers lift OFF the desk) — the inverse of Material's monotonic stack.
103
103
 
104
104
  ```
105
105
  bg-background page (the desk)
@@ -112,7 +112,7 @@ bg-popover floats above everything → shadow-popover
112
112
 
113
113
  ### Empty-slot convention
114
114
 
115
- When a region is meant to be filled (`AddBookCard`, audio drop zone, preview slot before recording), render it as a *background-matched or transparent* surface with `border-dashed` and a foreground border token (`border-border` or similar). The slot reads as a missing piece on its parent surface — never as a recessed input or a card. Once filled, the dashed border switches to solid and the surface adopts its real elevation.
115
+ When a region is meant to be filled (`AddBookCard`, audio drop zone, preview slot before recording), render it as a _background-matched or transparent_ surface with `border-dashed` and a foreground border token (`border-border` or similar). The slot reads as a missing piece on its parent surface — never as a recessed input or a card. Once filled, the dashed border switches to solid and the surface adopts its real elevation.
116
116
 
117
117
  ```tsx
118
118
  // Empty slot on a card surface
@@ -21,7 +21,7 @@
21
21
  * Button/Kbd/etc. — Tailwind v4 skips node_modules by default. Point at the
22
22
  * shipped `dist/` (the only source that lands in installed `node_modules`),
23
23
  * not `src/` which isn't in the published `files`. */
24
- @source "../dist/**/*.js";
24
+ @source '../dist/**/*.js';
25
25
 
26
26
  @custom-variant dark (&:is(.dark *));
27
27
 
@@ -59,7 +59,38 @@
59
59
  --color-border: var(--border);
60
60
  --color-input: var(--input);
61
61
  --color-ring: var(--ring);
62
- --font-serif: var(--font-literata), Georgia, Cambria, 'Times New Roman', Times, serif;
62
+ /* Font families. Override a role by setting its `--font-*-custom` variable;
63
+ * each falls back to a system stack. */
64
+ --font-sans: var(
65
+ --font-sans-custom,
66
+ ui-sans-serif,
67
+ system-ui,
68
+ sans-serif,
69
+ 'Apple Color Emoji',
70
+ 'Segoe UI Emoji',
71
+ 'Segoe UI Symbol',
72
+ 'Noto Color Emoji'
73
+ );
74
+ --font-serif: var(
75
+ --font-serif-custom,
76
+ ui-serif,
77
+ Georgia,
78
+ Cambria,
79
+ 'Times New Roman',
80
+ Times,
81
+ serif
82
+ );
83
+ --font-mono: var(
84
+ --font-mono-custom,
85
+ ui-monospace,
86
+ SFMono-Regular,
87
+ Menlo,
88
+ Monaco,
89
+ Consolas,
90
+ 'Liberation Mono',
91
+ 'Courier New',
92
+ monospace
93
+ );
63
94
  --radius: 0.625rem;
64
95
  --animate-buffer-pulse: buffer-pulse 3s ease-in-out infinite;
65
96
  --animate-ring-spin: ring-spin 5s linear infinite;
@@ -76,8 +107,7 @@
76
107
  --popover-foreground: oklch(0.145 0 0);
77
108
  --surface-inset: oklch(0.965 0 0);
78
109
  --card-shadow: 0 1px 2px 0 oklch(0.2 0 0 / 0.06);
79
- --popover-shadow:
80
- 0 8px 24px -4px oklch(0.2 0 0 / 0.1), 0 4px 8px -2px oklch(0.2 0 0 / 0.06);
110
+ --popover-shadow: 0 8px 24px -4px oklch(0.2 0 0 / 0.1), 0 4px 8px -2px oklch(0.2 0 0 / 0.06);
81
111
  --surface-inset-shadow: inset 0 1px 1px 0 oklch(0.2 0 0 / 0.04);
82
112
  --primary: oklch(0.546 0.245 262.881);
83
113
  --primary-foreground: oklch(1 0 0);
package/themes/reader.css CHANGED
@@ -43,7 +43,7 @@
43
43
  * Button/Kbd/etc. — Tailwind v4 skips node_modules by default. Point at the
44
44
  * shipped `dist/` (the only source that lands in installed `node_modules`),
45
45
  * not `src/` which isn't in the published `files`. */
46
- @source "../dist/**/*.js";
46
+ @source '../dist/**/*.js';
47
47
 
48
48
  @custom-variant dark (&:is(.dark *));
49
49
 
@@ -81,7 +81,38 @@
81
81
  --color-border: var(--border);
82
82
  --color-input: var(--input);
83
83
  --color-ring: var(--ring);
84
- --font-serif: var(--font-literata), Georgia, Cambria, 'Times New Roman', Times, serif;
84
+ /* Font families. Override a role by setting its `--font-*-custom` variable;
85
+ * each falls back to a system stack. */
86
+ --font-sans: var(
87
+ --font-sans-custom,
88
+ ui-sans-serif,
89
+ system-ui,
90
+ sans-serif,
91
+ 'Apple Color Emoji',
92
+ 'Segoe UI Emoji',
93
+ 'Segoe UI Symbol',
94
+ 'Noto Color Emoji'
95
+ );
96
+ --font-serif: var(
97
+ --font-serif-custom,
98
+ var(--font-literata),
99
+ Georgia,
100
+ Cambria,
101
+ 'Times New Roman',
102
+ Times,
103
+ serif
104
+ );
105
+ --font-mono: var(
106
+ --font-mono-custom,
107
+ ui-monospace,
108
+ SFMono-Regular,
109
+ Menlo,
110
+ Monaco,
111
+ Consolas,
112
+ 'Liberation Mono',
113
+ 'Courier New',
114
+ monospace
115
+ );
85
116
  --radius: 0.625rem;
86
117
  --animate-buffer-pulse: buffer-pulse 3s ease-in-out infinite;
87
118
  --animate-ring-spin: ring-spin 5s linear infinite;