@clinia/tailwindcss 0.3.0 → 2.0.0-rc.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Clinia Health Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # @clinia/tailwindcss
2
+
3
+ Clinia's brand tokens for Tailwind CSS v4: the colour palette, the light and dark theme as semantic tokens (`bg-primary`, `text-muted-foreground`, `border-emphasis`), the type scale, the radius scale, and the brand font faces.
4
+
5
+ Components come from the `@clinia` shadcn registry, not from this package. Documentation, rules, and components: [ui.clinia.dev](https://ui.clinia.dev).
6
+
7
+ ## Install
8
+
9
+ The theme registry item installs this package and writes the imports for you:
10
+
11
+ ```bash
12
+ pnpm dlx shadcn@latest add @clinia/theme # product apps
13
+ pnpm dlx shadcn@latest add @clinia/theme-marketing # marketing sites
14
+ ```
15
+
16
+ To install it by hand:
17
+
18
+ ```bash
19
+ pnpm add @clinia/tailwindcss
20
+ ```
21
+
22
+ ```css
23
+ @import "@clinia/tailwindcss/fonts";
24
+ @import "@clinia/tailwindcss";
25
+ ```
26
+
27
+ ## Entry points
28
+
29
+ | Import | What it adds |
30
+ |---|---|
31
+ | `@clinia/tailwindcss` | The theme: semantic tokens for light and dark, exposed to Tailwind |
32
+ | `@clinia/tailwindcss/tokens` | The raw brand palette and font stacks only |
33
+ | `@clinia/tailwindcss/fonts` | The `@font-face` declarations for the seven licensed faces |
34
+ | `@clinia/tailwindcss/marketing` | The illustration roles for marketing scenes. Marketing sites only |
35
+
36
+ Dark mode follows a `dark` class on `<html>` or any ancestor; `light` pins a subtree back to light.
37
+
38
+ ## Fonts
39
+
40
+ The package declares the brand faces but ships no font files: CircularXX and NaN Serf B are licensed per property and can't be redistributed. Put the seven `.woff2` files in your app's `public/fonts/`: [App getting started](https://ui.clinia.dev/docs/app/getting-started#3-host-the-brand-fonts) lists them and where to get them.
41
+
42
+ ## Licence
43
+
44
+ MIT. The brand fonts are not part of this licence.
package/fonts.css CHANGED
@@ -1,38 +1,14 @@
1
- /* ============================================================================
2
- * Clinia – Font loading
3
- *
4
- * Drop this file into your app's global CSS *once* and place the licensed
5
- * woff2 files at the paths declared below. The package itself does not ship
6
- * the font binaries — Lineto (CircularXX) and Sharp Type (Gothia Serif)
7
- * licenses are non-redistributable.
8
- *
9
- * Usage in a Next.js or Vite app:
10
- * 1. Drop the woff2 files in `public/fonts/` (paths must match the URLs below).
11
- * 2. Import this file from your app's globals.css *before* @clinia/ui's theme:
12
- * @import "@clinia/ui/fonts";
13
- * @import "@clinia/ui/styles";
14
- * 3. Preload the two faces above the fold in your HTML <head>:
15
- * <link rel="preload" href="/fonts/CircularXX-Book.woff2"
16
- * as="font" type="font/woff2" crossorigin />
17
- * <link rel="preload" href="/fonts/CircularXX-Medium.woff2"
18
- * as="font" type="font/woff2" crossorigin />
19
- *
20
- * Why these specific weights:
21
- * - Pulled directly from the Clinia – Brand Guidelines Figma text styles.
22
- * - CircularXX: Book (most body), Regular (titles), Medium (labels, eyebrows).
23
- * - Gothia Serif: Book (Display XL/L), Regular (Huge, Display M/S).
24
- * - CircularXX Mono: Regular (Eyebrow L/S, Dev Body).
25
- *
26
- * Performance:
27
- * - `font-display: swap` paints fallback first, swaps when the file lands.
28
- * Avoids invisible text (FOIT). Pairs with the fallback stack tuned in
29
- * tokens.css.
30
- * - `unicode-range: U+0000-00FF, U+0131, ...` requests the latin subset only.
31
- * Cuts ~40% off file size. Drop or extend if you serve other scripts.
32
- * - Subset your woff2 with `pyftsubset` or `glyphhanger` before deploying.
33
- * ========================================================================== */
1
+ /* Clinia font loading.
2
+ * Import once, before the theme:
3
+ * @import "@clinia/tailwindcss/fonts";
4
+ * @import "@clinia/tailwindcss";
5
+ * Place the seven licensed woff2 files at the /fonts/ paths below. The package does not ship them: the Lineto (CircularXX) and NaN (NaN Serf B) licenses forbid redistributing the binaries.
6
+ * Faces: CircularXX Book 400, Regular 450, Medium 500, Book Italic 400, Medium Italic 500; CircularXX Mono Regular 400; NaN Serf B Book 400.
7
+ * Each face requests the latin subset only through unicode-range. Extend it if you serve other scripts.
8
+ * Preload the above-the-fold faces (CircularXXWeb-Book and CircularXXWeb-Medium) with <link rel="preload" as="font" type="font/woff2" crossorigin>.
9
+ */
34
10
 
35
- /* ---------- CircularXX (UI Sans) ---------------------------------------- */
11
+ /* CircularXX, the UI sans. */
36
12
  @font-face {
37
13
  font-family: "CircularXX";
38
14
  src: url("/fonts/CircularXXWeb-Book.woff2") format("woff2");
@@ -44,6 +20,17 @@
44
20
  U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
45
21
  }
46
22
 
23
+ @font-face {
24
+ font-family: "CircularXX";
25
+ src: url("/fonts/CircularXXWeb-BookItalic.woff2") format("woff2");
26
+ font-weight: 400;
27
+ font-style: italic;
28
+ font-display: swap;
29
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
30
+ U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
31
+ U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
32
+ }
33
+
47
34
  @font-face {
48
35
  font-family: "CircularXX";
49
36
  src: url("/fonts/CircularXXWeb-Regular.woff2") format("woff2");
@@ -66,7 +53,18 @@
66
53
  U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
67
54
  }
68
55
 
69
- /* ---------- CircularXX Mono --------------------------------------------- */
56
+ @font-face {
57
+ font-family: "CircularXX";
58
+ src: url("/fonts/CircularXXWeb-MediumItalic.woff2") format("woff2");
59
+ font-weight: 500;
60
+ font-style: italic;
61
+ font-display: swap;
62
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
63
+ U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
64
+ U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
65
+ }
66
+
67
+ /* CircularXX Mono. */
70
68
  @font-face {
71
69
  font-family: "CircularXX Mono";
72
70
  src: url("/fonts/CircularXXMonoWeb-Regular.woff2") format("woff2");
@@ -77,23 +75,13 @@
77
75
  U+20AC, U+2122, U+FEFF, U+FFFD;
78
76
  }
79
77
 
80
- /* ---------- Gothia Serif (Display) -------------------------------------- */
78
+ /* NaN Serf B, the display face. Book 400 only; no italic. */
81
79
  @font-face {
82
- font-family: "Gothia Serif";
83
- src: url("/fonts/GothiaSerif-Book.woff2") format("woff2");
80
+ font-family: "NaN Serf B";
81
+ src: url("/fonts/NaNSerfBText-Book.woff2") format("woff2");
84
82
  font-weight: 400;
85
83
  font-style: normal;
86
84
  font-display: swap;
87
85
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
88
86
  U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+FEFF, U+FFFD;
89
87
  }
90
-
91
- @font-face {
92
- font-family: "Gothia Serif";
93
- src: url("/fonts/GothiaSerif-Regular.woff2") format("woff2");
94
- font-weight: 500;
95
- font-style: normal;
96
- font-display: swap;
97
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
98
- U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+FEFF, U+FFFD;
99
- }
package/marketing.css ADDED
@@ -0,0 +1,29 @@
1
+ /* @clinia/tailwindcss/marketing, for marketing surfaces only.
2
+ *
3
+ * Illustration roles for the scenes on Clinia's marketing sites (the patient
4
+ * graphs on clinia.com): one colour per entity type, for its dot and the tint
5
+ * and outline of the tags that point to it. Every value is a brand swatch, the
6
+ * same in both themes.
7
+ *
8
+ * Use them in illustrations only, not for UI controls, text or states. Product
9
+ * (base-luma) apps do not import this file. Import it after the theme:
10
+ * @import "@clinia/tailwindcss";
11
+ * @import "@clinia/tailwindcss/marketing";
12
+ */
13
+
14
+ :root {
15
+ /* Conditions: T2 diabetes, retinopathy. Vital #ff5c00, for illustration only. */
16
+ --scene-condition: var(--clinia-vital);
17
+
18
+ /* Labs and measures: HbA1c. */
19
+ --scene-lab: var(--clinia-trust);
20
+
21
+ /* Medications and treatments: metformin, lisinopril. */
22
+ --scene-medication: var(--clinia-purple-5);
23
+ }
24
+
25
+ @theme inline {
26
+ --color-scene-condition: var(--scene-condition);
27
+ --color-scene-lab: var(--scene-lab);
28
+ --color-scene-medication: var(--scene-medication);
29
+ }
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "@clinia/tailwindcss",
3
- "version": "0.3.0",
4
- "description": "Clinia design-system: Tailwind v4 tokens, theme, and style layers.",
3
+ "version": "2.0.0-rc.2",
4
+ "description": "Clinia design-system: Tailwind v4 tokens, theme, and fonts.",
5
5
  "license": "MIT",
6
+ "homepage": "https://ui.clinia.dev",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/clinia/ui.git",
10
+ "directory": "packages/tailwindcss"
11
+ },
6
12
  "type": "module",
7
13
  "sideEffects": [
8
14
  "**/*.css"
@@ -12,11 +18,12 @@
12
18
  "./tokens": "./tokens.css",
13
19
  "./theme": "./theme.css",
14
20
  "./fonts": "./fonts.css",
15
- "./style-sera": "./style-sera.css",
16
- "./style-luma": "./style-luma.css"
21
+ "./marketing": "./marketing.css"
17
22
  },
18
23
  "files": [
19
- "*.css"
24
+ "*.css",
25
+ "README.md",
26
+ "LICENSE"
20
27
  ],
21
28
  "peerDependencies": {
22
29
  "tailwindcss": ">=4.0.0"
package/theme.css CHANGED
@@ -1,44 +1,27 @@
1
- /* ============================================================================
2
- * Clinia Theme — Tailwind v4
3
- *
4
- * Architecture (modern shadcn + Tailwind v4 pattern, with style layering):
5
- * 1. Raw brand palette + fonts live in `tokens.css` (the brand truth).
6
- * 2. Semantic *color* tokens (background, foreground, primary, …) are declared
7
- * here on `:root` (light) and `.dark` (dark) — one shared color truth
8
- * across every Clinia surface.
9
- * 3. *Shape* tokens (radii, shadows, spacing density, control treatment) are
10
- * declared in style layers — `style-sera.css` and `style-luma.css` —
11
- * and gated by `[data-style="sera"|"luma"]` on the root. Apps pick one;
12
- * brand sites typically pick Sera, product surfaces pick Luma.
13
- * 4. `@theme inline` re-exposes the semantic variables to Tailwind so
14
- * utilities like `bg-primary`, `rounded-md`, etc. resolve correctly and
15
- * switch with both theme (light/dark) and style (sera/luma).
16
- *
17
- * Accessibility:
18
- * - All text-on-surface pairs target WCAG AA at minimum.
19
- * - Brand orange (Vital) is paired with deep Infinite text — never white —
20
- * because white-on-Vital fails AA for normal text (≈3.1:1).
21
- * - Focus ring uses Vital at 2px to remain visible on any surface.
22
- *
23
- * Dark mode: add `class="dark"` to <html> (or any ancestor).
24
- * Style choice: add `data-style="sera"` or `data-style="luma"` to <html>.
25
- * No attribute = the neutral default (radius 0.5rem, light shadow).
26
- * ========================================================================== */
1
+ /* Clinia theme for Tailwind v4.
2
+ * Maps the brand swatches in tokens.css to semantic tokens on :root and .light (light) and .dark (dark), plus one set of shape tokens, and exposes them to Tailwind through @theme inline.
3
+ * Dark mode: add class="dark" to <html> or any ancestor.
4
+ * Accessibility: every text pair meets WCAG AA in both themes. accent (Trust) is a 3:1 color: borders, icons, selected states, and text from 24px or 18.66px bold. Never body or label text, never a fill behind small text.
5
+ * ring is Trust in both themes.
6
+ */
27
7
 
28
8
  @import "tailwindcss";
29
9
  @import "./tokens.css";
30
10
 
31
11
  @custom-variant dark (&:is(.dark *));
32
12
 
33
- /* ---------- Light theme (default) ---------------------------------------- */
34
- :root {
35
- /* Shape defaults — overridden by style layers when [data-style] is set. */
36
- --radius: 0.5rem;
13
+ /* Maps `data-horizontal:` and `data-vertical:` (slider, tabs, separator) onto the `data-orientation` attribute Base UI emits. */
14
+ @custom-variant data-horizontal (&[data-orientation="horizontal"]);
15
+ @custom-variant data-vertical (&[data-orientation="vertical"]);
16
+
17
+ /* Light theme, the default. .light redeclares every token, so a light island inside .dark gets light values. */
18
+ :root,
19
+ .light {
20
+ /* Shape. 0.625rem is the shadcn Luma default; a surface may override --radius locally. */
21
+ --radius: 0.625rem;
37
22
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.04);
38
23
  --shadow-md: 0 1px 3px 0 rgb(0 0 0 / 0.06), 0 1px 2px -1px rgb(0 0 0 / 0.04);
39
24
  --shadow-lg: 0 8px 24px -8px rgb(0 0 0 / 0.10);
40
- --tracking-display: -0.01em;
41
- --tracking-eyebrow: 0.1em;
42
25
  --button-text-transform: none;
43
26
  --button-letter-spacing: normal;
44
27
 
@@ -51,19 +34,20 @@
51
34
  --popover: #ffffff;
52
35
  --popover-foreground: var(--clinia-infinite);
53
36
 
54
- /* Primary = Infinite (deep brand black) — high-contrast default action. */
37
+ /* Primary: Infinite #1a1a1e, the default action. */
55
38
  --primary: var(--clinia-infinite);
56
39
  --primary-foreground: var(--clinia-serene);
57
40
 
58
- /* Secondary = Remedy (warm cream) — low-emphasis surfaces. */
41
+ /* Secondary: Remedy #fcf8ef, low-emphasis surfaces. */
59
42
  --secondary: var(--clinia-remedy);
60
43
  --secondary-foreground: var(--clinia-infinite);
61
44
 
62
45
  --muted: var(--clinia-remedy);
63
46
  --muted-foreground: var(--clinia-infinite-4);
64
47
 
65
- /* Accent = Vital orange — brand emphasis, always paired with dark text. */
66
- --accent: var(--clinia-vital);
48
+ /* Accent: Trust #95795c, brand emphasis. 3:1 color: 4.00:1 on the background (Serene #fffdf9), 4.27:1 on Infinite #1a1a1e.
49
+ * --accent-foreground (Infinite) is valid on a Trust fill from 24px, never at label size. */
50
+ --accent: var(--clinia-trust);
67
51
  --accent-foreground: var(--clinia-infinite);
68
52
 
69
53
  --destructive: #b91c1c;
@@ -76,15 +60,18 @@
76
60
  --warning-foreground: var(--clinia-infinite);
77
61
 
78
62
  --border: var(--clinia-infinite-1);
79
- --input: var(--clinia-infinite-1);
80
- --ring: var(--clinia-vital);
63
+ --input: #8c8c8c; /* derived neutral, boundary use only */
64
+ --ring: var(--clinia-trust);
81
65
 
82
- /* Chart palette drawn from across the brand families. */
83
- --chart-1: var(--clinia-vital);
66
+ /* Selected/hover outlines, section rules, the one emphasis moment per view. */
67
+ --border-emphasis: var(--clinia-trust);
68
+
69
+ /* Chart palette led by Trust, drawn from across the brand families. */
70
+ --chart-1: var(--clinia-trust);
84
71
  --chart-2: var(--clinia-thistle);
85
72
  --chart-3: var(--clinia-noble);
86
- --chart-4: var(--clinia-trust);
87
- --chart-5: var(--clinia-purple-5);
73
+ --chart-4: var(--clinia-purple-5);
74
+ --chart-5: var(--clinia-peach-4);
88
75
 
89
76
  /* Sidebar tokens alias the base semantic tokens. */
90
77
  --sidebar: var(--background);
@@ -97,12 +84,13 @@
97
84
  --sidebar-ring: var(--ring);
98
85
  }
99
86
 
100
- /* ---------- Dark theme ---------------------------------------------------- */
87
+ /* Dark theme, under class="dark". */
101
88
  .dark {
102
89
  --background: var(--clinia-infinite);
103
90
  --foreground: var(--clinia-serene);
104
91
 
105
- --card: #232327; /* one stop above --background for surface lift */
92
+ /* One step above --background, so cards lift off the page. */
93
+ --card: #232327;
106
94
  --card-foreground: var(--clinia-serene);
107
95
 
108
96
  --popover: #232327;
@@ -118,7 +106,7 @@
118
106
  --muted: var(--clinia-infinite-5);
119
107
  --muted-foreground: var(--clinia-infinite-2);
120
108
 
121
- --accent: var(--clinia-vital);
109
+ --accent: var(--clinia-trust);
122
110
  --accent-foreground: var(--clinia-infinite);
123
111
 
124
112
  --destructive: #ef6b5c;
@@ -131,10 +119,12 @@
131
119
  --warning-foreground: var(--clinia-infinite);
132
120
 
133
121
  --border: var(--clinia-infinite-5);
134
- --input: var(--clinia-infinite-5);
135
- --ring: var(--clinia-vital);
122
+ --input: #777777; /* derived neutral, boundary use only */
123
+ --ring: var(--clinia-trust);
124
+
125
+ --border-emphasis: var(--clinia-trust);
136
126
 
137
- --chart-1: var(--clinia-peach-2);
127
+ --chart-1: var(--clinia-trust);
138
128
  --chart-2: var(--clinia-purple-5);
139
129
  --chart-3: var(--clinia-beige-5);
140
130
  --chart-4: var(--clinia-purple-3);
@@ -146,13 +136,19 @@
146
136
  --sidebar-primary-foreground: var(--primary-foreground);
147
137
  --sidebar-accent: var(--accent);
148
138
  --sidebar-accent-foreground: var(--accent-foreground);
149
- --sidebar-border: oklch(1 0 0 / 10%);
139
+ --sidebar-border: var(--border);
150
140
  --sidebar-ring: var(--ring);
151
141
  }
152
142
 
153
- /* ---------- Tailwind theme bridge ---------------------------------------- */
143
+ /* Exposes the semantic tokens as Tailwind utilities. */
144
+ /* Letter spacing for display headlines and eyebrows, exposed as `tracking-display` and `tracking-eyebrow`. */
145
+ @theme {
146
+ --tracking-display: -0.01em;
147
+ --tracking-eyebrow: 0.1em;
148
+ }
149
+
154
150
  @theme inline {
155
- /* Surface + intent colors */
151
+ /* Surface + intent colours */
156
152
  --color-background: var(--background);
157
153
  --color-foreground: var(--foreground);
158
154
 
@@ -184,6 +180,8 @@
184
180
  --color-warning-foreground: var(--warning-foreground);
185
181
 
186
182
  --color-border: var(--border);
183
+ /* Tailwind builds colour utilities from --color-*, so this name yields `border-emphasis`, `ring-emphasis`, `bg-emphasis` and `text-emphasis`. */
184
+ --color-emphasis: var(--border-emphasis);
187
185
  --color-input: var(--input);
188
186
  --color-ring: var(--ring);
189
187
 
@@ -202,7 +200,7 @@
202
200
  --color-sidebar-border: var(--sidebar-border);
203
201
  --color-sidebar-ring: var(--sidebar-ring);
204
202
 
205
- /* Direct access to raw brand swatches when explicitly needed. */
203
+ /* Raw brand swatches as `brand-*` utilities, for marketing surfaces only. Product UI uses the semantic tokens. */
206
204
  --color-brand-vital: var(--clinia-vital);
207
205
  --color-brand-infinite: var(--clinia-infinite);
208
206
  --color-brand-serene: var(--clinia-serene);
@@ -211,16 +209,16 @@
211
209
  --color-brand-mend: var(--clinia-mend);
212
210
  --color-brand-trust: var(--clinia-trust);
213
211
 
214
- /* Radius scale derived from a single base. */
215
- --radius-sm: calc(var(--radius) - 4px);
216
- --radius-md: calc(var(--radius) - 2px);
212
+ /* Radius scale as multiples of --radius, matching shadcn, so it follows when Luma re-bases --radius inside the sidebar. */
213
+ --radius-sm: calc(var(--radius) * 0.6);
214
+ --radius-md: calc(var(--radius) * 0.8);
217
215
  --radius-lg: var(--radius);
218
- --radius-xl: calc(var(--radius) + 4px);
216
+ --radius-xl: calc(var(--radius) * 1.4);
219
217
  --radius-2xl: calc(var(--radius) * 1.8);
220
218
  --radius-3xl: calc(var(--radius) * 2.2);
221
219
  --radius-4xl: calc(var(--radius) * 2.6);
222
220
 
223
- /* Type scale — names mirror the Figma styles for traceability. */
221
+ /* Type scale. Names match the Figma text styles. */
224
222
  --font-display: var(--clinia-font-display);
225
223
  --font-sans: var(--clinia-font-sans);
226
224
  --font-mono: var(--clinia-font-mono);
@@ -243,7 +241,7 @@
243
241
  --text-eyebrow-s: 0.625rem; /* 10 / Eyebrow S */
244
242
  }
245
243
 
246
- /* ---------- Base reset --------------------------------------------------- */
244
+ /* Base styles. */
247
245
  @layer base {
248
246
  * {
249
247
  border-color: var(--border);
@@ -252,6 +250,8 @@
252
250
  html {
253
251
  color-scheme: light;
254
252
  font-family: var(--clinia-font-sans);
253
+ /* Missing weights and italics fall back instead of being faked. */
254
+ font-synthesis: none;
255
255
  }
256
256
 
257
257
  html.dark {
@@ -272,14 +272,17 @@
272
272
  border-radius: 2px;
273
273
  }
274
274
 
275
- /* Honor reduced-motion preference everywhere by default. */
275
+ /* Honour reduced-motion preference everywhere by default. */
276
276
  @media (prefers-reduced-motion: reduce) {
277
277
  *,
278
278
  *::before,
279
279
  *::after {
280
280
  animation-duration: 0.01ms !important;
281
+ animation-delay: 0s !important;
281
282
  animation-iteration-count: 1 !important;
282
283
  transition-duration: 0.01ms !important;
284
+ /* A staggered build would otherwise still wait its turn. */
285
+ transition-delay: 0s !important;
283
286
  scroll-behavior: auto !important;
284
287
  }
285
288
  }
package/tokens.css CHANGED
@@ -1,33 +1,26 @@
1
- /* ============================================================================
2
- * Clinia Brand Tokens
3
- * Source: Clinia – Brand Guidelines (Figma)
4
- * https://www.figma.com/design/aF7fTYG31l7DcKdySyk6yH
5
- *
6
- * These are the raw brand values pulled from the Figma paint + text styles.
7
- * Do NOT use these directly in components — consume the semantic tokens in
8
- * `theme.css` (e.g., `--color-primary`, `--color-accent`) so light/dark
9
- * theming and accessibility guarantees remain intact.
10
- * ========================================================================== */
1
+ /* Clinia brand tokens: the raw swatches and font stacks from the brand guidelines' Figma paint and text styles.
2
+ * Components use the semantic tokens in theme.css (`--color-primary`, `--color-accent`), which carry the light and dark themes and the contrast guarantees. Never use these directly.
3
+ */
11
4
 
12
5
  @layer base {
13
6
  :root {
14
- /* --- Foundation ------------------------------------------------------ */
15
- --clinia-infinite: #1a1a1e; /* Brand black — anchors the system */
7
+ /* Foundation. Infinite is the brand black that anchors the system. */
8
+ --clinia-infinite: #1a1a1e;
16
9
  --clinia-infinite-5: #333333;
17
10
  --clinia-infinite-4: #666666;
18
11
  --clinia-infinite-3: #999999;
19
12
  --clinia-infinite-2: #cdcdcd;
20
13
  --clinia-infinite-1: #e2e2e2;
21
14
 
22
- /* --- Beige / Tan (warm neutrals) ------------------------------------ */
23
- --clinia-serene: #fffdf9; /* Brand cream — page background */
15
+ /* Beige and tan, the warm neutrals. Serene is the brand cream page background. */
16
+ --clinia-serene: #fffdf9;
24
17
  --clinia-remedy: #fcf8ef;
25
18
  --clinia-beige-3: #f1e3cb;
26
19
  --clinia-remedy-dark: #ecd9b9;
27
20
  --clinia-beige-5: #dbbe87;
28
21
  --clinia-noble: #cca44f;
29
22
 
30
- /* --- Purple (cool accent family) ------------------------------------ */
23
+ /* Purple, the cool accent family. */
31
24
  --clinia-purple-1: #faf7ff;
32
25
  --clinia-aura: #f8f1ff;
33
26
  --clinia-purple-3: #ede5f6;
@@ -35,21 +28,18 @@
35
28
  --clinia-purple-5: #cabbdb;
36
29
  --clinia-purple-6: #b3a0ae;
37
30
 
38
- /* --- Peach / Orange (warm accent family) ---------------------------- */
31
+ /* Peach and orange, the warm accent family. */
39
32
  --clinia-mend: #ffccaf;
40
33
  --clinia-peach-2: #fd945f;
41
- --clinia-vital: #ff5c00; /* Brand orange — flagship accent */
34
+ /* Approved marketing highlights only. */
35
+ --clinia-vital: #ff5c00;
42
36
  --clinia-peach-4: #cb6a3d;
43
37
  --clinia-peach-5: #b3724c;
38
+ /* Flagship accent, a 3:1 colour. */
44
39
  --clinia-trust: #95795c;
45
40
 
46
- /* --- Typography ------------------------------------------------------
47
- * Gothia Serif and CircularXX are licensed fonts. Self-host the .woff2
48
- * files via @font-face in your app's CSS or use a hosting provider.
49
- * Fallbacks are tuned to keep editorial vs. UI character distinct.
50
- * ----------------------------------------------------------------- */
51
- --clinia-font-display: "Gothia Serif", "GT Sectra", "Tiempos Headline",
52
- Georgia, "Times New Roman", serif;
41
+ /* Typography. NaN Serf B and CircularXX are licensed: import @clinia/tailwindcss/fonts and self-host the woff2 files. */
42
+ --clinia-font-display: "NaN Serf B", "Source Serif 4", Georgia, serif;
53
43
  --clinia-font-sans: "CircularXX", "Inter", -apple-system, BlinkMacSystemFont,
54
44
  "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
55
45
  --clinia-font-mono: "CircularXX Mono", "JetBrains Mono", ui-monospace,
package/style-luma.css DELETED
@@ -1,80 +0,0 @@
1
- /* ============================================================================
2
- * Luma — shape layer
3
- *
4
- * Rounded geometry. Soft elevation. Breathable layouts. The shape system for
5
- * Clinia's product surfaces — clinical workflows, search consoles, login,
6
- * settings. Calmer than Sera, with enough lift to guide the eye through
7
- * dense interfaces without shouting.
8
- *
9
- * Activate by adding `data-style="luma"` to <html> (or any ancestor).
10
- *
11
- * Design notes:
12
- * - radius bumps to 0.875rem — soft but not pill-y.
13
- * - shadows are subtle but real. Cards earn the lift; popovers earn more.
14
- * - typography stays sans (no uppercase tracking on buttons). The voice
15
- * here is calm-and-competent, not editorial.
16
- * - transitions soften slightly (180ms ease-out) so hover states feel
17
- * considered, not snappy.
18
- * ========================================================================== */
19
-
20
- [data-style="luma"] {
21
- --radius: 0.875rem;
22
-
23
- --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.04),
24
- 0 1px 1px 0 rgb(0 0 0 / 0.03);
25
- --shadow-md: 0 2px 4px -1px rgb(0 0 0 / 0.06),
26
- 0 4px 12px -4px rgb(0 0 0 / 0.08);
27
- --shadow-lg: 0 8px 24px -8px rgb(0 0 0 / 0.12),
28
- 0 16px 48px -16px rgb(0 0 0 / 0.10);
29
-
30
- --tracking-display: -0.015em;
31
- --tracking-eyebrow: 0.08em;
32
-
33
- --button-text-transform: none;
34
- --button-letter-spacing: -0.005em;
35
- }
36
-
37
- /* Dark mode shadow tuning — increase opacity slightly so elevation reads. */
38
- .dark[data-style="luma"],
39
- [data-style="luma"] .dark,
40
- .dark [data-style="luma"] {
41
- --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.30),
42
- 0 1px 1px 0 rgb(0 0 0 / 0.20);
43
- --shadow-md: 0 2px 4px -1px rgb(0 0 0 / 0.35),
44
- 0 4px 12px -4px rgb(0 0 0 / 0.25);
45
- --shadow-lg: 0 8px 24px -8px rgb(0 0 0 / 0.40),
46
- 0 16px 48px -16px rgb(0 0 0 / 0.30);
47
- }
48
-
49
- /* ---------- Component-level expression ---------------------------------- */
50
- @layer components {
51
- /* Buttons: subtle hover lift. Pairs with the soft shadow on press. */
52
- [data-style="luma"] :where(button, [role="button"], a[role="button"]) {
53
- transition-duration: 180ms;
54
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
55
- }
56
-
57
- /* Cards: visible elevation, generous radius. */
58
- [data-style="luma"] :where(.shadow-sm) {
59
- box-shadow: var(--shadow-sm);
60
- }
61
- [data-style="luma"] :where(.shadow, .shadow-md) {
62
- box-shadow: var(--shadow-md);
63
- }
64
- [data-style="luma"] :where(.shadow-lg) {
65
- box-shadow: var(--shadow-lg);
66
- }
67
-
68
- /* Inputs: softer borders, slight inner shadow for depth. */
69
- [data-style="luma"] :where(input, textarea, select) {
70
- transition: border-color 160ms ease, box-shadow 160ms ease;
71
- }
72
- [data-style="luma"] :where(input, textarea, select):not(:focus) {
73
- box-shadow: inset 0 1px 0 0 rgb(0 0 0 / 0.02);
74
- }
75
-
76
- /* Headings: confident negative tracking for tighter rhythm. */
77
- [data-style="luma"] :where(h1, h2, h3) {
78
- letter-spacing: var(--tracking-display);
79
- }
80
- }
package/style-sera.css DELETED
@@ -1,75 +0,0 @@
1
- /* ============================================================================
2
- * Sera — shape layer
3
- *
4
- * Typography-first, print-inspired. Square corners, uppercase tracking,
5
- * underlined controls. Built for Clinia's brand surfaces (marketing site,
6
- * editorial content) where the Gothia Serif + CircularXX + CircularXX Mono
7
- * pairing carries the visual weight.
8
- *
9
- * Activate by adding `data-style="sera"` to <html> (or any ancestor).
10
- *
11
- * Design notes:
12
- * - radius collapses to 0 — every edge is a hairline.
13
- * - shadows go away. Cards/popovers separate via 1px borders only.
14
- * - body text inherits sans (CircularXX); headings should set
15
- * `font-display` (Gothia Serif) at the consumer level.
16
- * - buttons get tracked, slightly uppercase typography to match the
17
- * editorial register without committing to ALL CAPS everywhere.
18
- * - links and ghost buttons receive an offset underline for
19
- * "underlined controls".
20
- * ========================================================================== */
21
-
22
- [data-style="sera"] {
23
- --radius: 0;
24
-
25
- --shadow-sm: 0 0 0 1px var(--border);
26
- --shadow-md: 0 0 0 1px var(--border);
27
- --shadow-lg: 0 0 0 1px var(--border);
28
-
29
- --tracking-display: 0;
30
- --tracking-eyebrow: 0.18em;
31
-
32
- --button-text-transform: uppercase;
33
- --button-letter-spacing: 0.08em;
34
- }
35
-
36
- /* ---------- Component-level expression ---------------------------------- */
37
- @layer components {
38
- /* Buttons: editorial chrome. Default fill keeps the Confident voice;
39
- uppercase + tracking adds the print-inspired register. */
40
- [data-style="sera"] :where(button, [role="button"], a[role="button"]) {
41
- text-transform: var(--button-text-transform);
42
- letter-spacing: var(--button-letter-spacing);
43
- font-weight: 500;
44
- }
45
-
46
- /* Link variant gets the explicit underline. */
47
- [data-style="sera"] :where(a:not([role="button"])) {
48
- text-underline-offset: 4px;
49
- text-decoration-thickness: 1px;
50
- }
51
-
52
- /* Cards: hairline only, no shadow lift. The border and the negative
53
- space carry the structure. */
54
- [data-style="sera"] :where(.shadow-sm, .shadow, .shadow-md, .shadow-lg) {
55
- box-shadow: 0 0 0 1px var(--border);
56
- }
57
-
58
- /* Headings: editorial spacing. Tighter line-height, slight tracking. */
59
- [data-style="sera"] :where(h1, h2, h3) {
60
- letter-spacing: var(--tracking-display);
61
- line-height: 1.05;
62
- }
63
-
64
- /* Eyebrows already exist as a brand pattern. Sera amps the tracking. */
65
- [data-style="sera"] :where(.eyebrow, [data-eyebrow]) {
66
- text-transform: uppercase;
67
- letter-spacing: var(--tracking-eyebrow);
68
- font-family: var(--clinia-font-mono);
69
- }
70
-
71
- /* Inputs: square, hairline border, no inner shadow. */
72
- [data-style="sera"] :where(input, textarea, select) {
73
- box-shadow: none;
74
- }
75
- }