@tangle-network/brand 1.9.0 → 1.10.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.
@@ -5,35 +5,43 @@
5
5
  * is the neutral "tangle" theme — also selectable by name as "tangle-dark";
6
6
  * "<name>-light" scopes are the light variants. */
7
7
 
8
- /* Bridge — the actual re-skin mechanism. Tailwind utilities read the --color-*
9
- * layer (theme.css @theme: `bg-card` → var(--color-card) = hsl(var(--card))).
10
- * Both --color-* and its --card/--hsl-card source are declared only at :root, so
11
- * a descendant [data-theme] that changes --hsl-card never re-substitutes the
12
- * :root-computed --color-card the utility consumes — the value is frozen at the
13
- * root color (double-indirection inheritance trap). Redeclaring the --color-*
14
- * layer directly on any themed element forces each one to recompute from that
15
- * element's own --hsl-*. Tokens a theme doesn't override fall back to the
16
- * inherited neutral --hsl-* (all defined at :root), so this is always valid. */
8
+ /* Compatibility for consumers compiled to var(--color-*). Tailwind's inline
9
+ * theme mapping handles newly compiled utilities, but precompiled consumers
10
+ * must also re-resolve their aliases on every theme boundary, not only root. */
11
+ :root,
12
+ .dark,
13
+ .light,
14
+ [data-sandbox-ui],
15
+ [data-sandbox-theme],
17
16
  [data-theme] {
18
- --color-background: hsl(var(--hsl-background));
19
- --color-foreground: hsl(var(--hsl-foreground));
20
- --color-card: hsl(var(--hsl-card));
21
- --color-card-foreground: hsl(var(--hsl-card-foreground));
22
- --color-popover: hsl(var(--hsl-popover));
23
- --color-popover-foreground: hsl(var(--hsl-popover-foreground));
24
- --color-primary: hsl(var(--hsl-primary));
25
- --color-primary-foreground: hsl(var(--hsl-primary-foreground));
26
- --color-secondary: hsl(var(--hsl-secondary));
27
- --color-secondary-foreground: hsl(var(--hsl-secondary-foreground));
28
- --color-muted: hsl(var(--hsl-muted));
29
- --color-muted-foreground: hsl(var(--hsl-muted-foreground));
30
- --color-accent: hsl(var(--hsl-accent));
31
- --color-accent-foreground: hsl(var(--hsl-accent-foreground));
32
- --color-destructive: hsl(var(--hsl-destructive));
33
- --color-destructive-foreground: hsl(var(--hsl-destructive-foreground));
34
- --color-border: hsl(var(--hsl-border));
35
- --color-input: hsl(var(--hsl-muted-foreground));
36
- --color-ring: hsl(var(--hsl-ring));
17
+ --text-display: var(--font-size-display);
18
+ --text-hero: var(--font-size-hero);
19
+ --text-page: var(--font-size-3xl);
20
+ --text-section: var(--font-size-xl);
21
+ --text-eyebrow: var(--font-size-sm);
22
+ --color-depth-1: var(--depth-1);
23
+ --color-depth-2: var(--depth-2);
24
+ --color-depth-3: var(--depth-3);
25
+ --color-depth-4: var(--depth-4);
26
+ --color-background: hsl(var(--background));
27
+ --color-foreground: hsl(var(--foreground));
28
+ --color-card: hsl(var(--card));
29
+ --color-card-foreground: hsl(var(--card-foreground));
30
+ --color-popover: hsl(var(--popover));
31
+ --color-popover-foreground: hsl(var(--popover-foreground));
32
+ --color-primary: hsl(var(--primary));
33
+ --color-primary-foreground: hsl(var(--primary-foreground));
34
+ --color-secondary: hsl(var(--secondary));
35
+ --color-secondary-foreground: hsl(var(--secondary-foreground));
36
+ --color-muted: hsl(var(--muted));
37
+ --color-muted-foreground: hsl(var(--muted-foreground));
38
+ --color-accent: hsl(var(--accent));
39
+ --color-accent-foreground: hsl(var(--accent-foreground));
40
+ --color-destructive: hsl(var(--destructive));
41
+ --color-destructive-foreground: hsl(var(--destructive-foreground));
42
+ --color-border: hsl(var(--border));
43
+ --color-input: hsl(var(--input));
44
+ --color-ring: hsl(var(--ring));
37
45
  --color-surface-container-lowest: var(--md3-surface-container-lowest);
38
46
  --color-surface-container-low: var(--md3-surface-container-low);
39
47
  --color-surface-container: var(--md3-surface-container);
@@ -44,47 +52,15 @@
44
52
  --color-fg-dim: var(--text-dim);
45
53
  }
46
54
 
47
- /* Light-tuned status palette for the named light scopes. Without this they
48
- * inherit the dark :root status colors (bright #f87171/#34D399/…), which fail
49
- * WCAG on a light surface — status text + glyphs drop to ~2.5:1. These mirror
50
- * tokens.css `[data-theme="light"]` (dark-on-light status text that passes AA). */
55
+ /* Named-specific light ink. All shared status and syntax colors now come
56
+ * from the complete canonical light baseline in tokens.css. */
51
57
  [data-theme="aubergine-light"],
52
58
  [data-theme="arena-light"],
53
59
  [data-theme="tangle-light"] {
54
- --surface-success-bg: #ecfdf5; --surface-success-border: #a7f3d0; --surface-success-text: #047857;
55
- --surface-warning-bg: #fffbeb; --surface-warning-border: #fde68a; --surface-warning-text: #ab4f09;
56
- --surface-danger-bg: #fff1f2; --surface-danger-border: #fecdd3; --surface-danger-text: #b91c1c;
57
- --surface-info-bg: #f0f9ff; --surface-info-border: #bae6fd; --surface-info-text: #0369a1;
58
- /* Light-tuned interactive tokens — without these the named light scopes
59
- * inherit the dark :root values on a light surface: destructive white-on-red
60
- * fell to 3.67, and the secondary badge inherited near-white foreground (~1.05). */
61
- --hsl-destructive: 0 72% 41%;
62
- --hsl-destructive-foreground: 0 0% 100%;
63
60
  --hsl-secondary-foreground: 0 0% 10%;
64
- /* neutral status label inherited var(--text-muted) which was ~3.8:1 on the
65
- * light row surface; pin a darker slate that clears AA on light surfaces. */
66
61
  --surface-neutral-text: #4b5563;
67
62
  }
68
63
 
69
- /* Light-tuned syntax highlighting for ALL light scopes (incl. base light).
70
- * --syntax-* is defined only in the dark :root (near-white foreground), so on a
71
- * light code surface (bg-card ≈ white) code was ~1.2:1 — invisible. Dark-on-light
72
- * palette, all ≥4.5:1 on white. */
73
- [data-theme="light"],
74
- [data-theme="aubergine-light"],
75
- [data-theme="arena-light"],
76
- [data-theme="tangle-light"] {
77
- --syntax-foreground: #24292f;
78
- --syntax-comment: #57606a;
79
- --syntax-keyword: #6d28d9;
80
- --syntax-string: #047857;
81
- --syntax-function: #1d4ed8;
82
- --syntax-number: #92400e;
83
- --syntax-meta: #7c3aed;
84
- --syntax-variable: #24292f;
85
- --syntax-error: #b91c1c;
86
- }
87
-
88
64
  /* ───────────────────────── Aubergine (bazaar) — dark purple ──────────────── */
89
65
  [data-theme="aubergine"] {
90
66
  /* Base lifted off near-black: at ~7% L the 258 hue read black; ~13-20% L with
@@ -1,69 +1,70 @@
1
- /* Tangle brand — Tailwind v4 @theme block.
2
- Maps brand CSS custom properties into Tailwind's color/font/radius system
3
- so utilities like `bg-brand-primary`, `text-text-muted`, `rounded-md`,
4
- `font-display` work out of the box.
5
-
6
- Consumers include this AFTER `@import "tailwindcss"` and
7
- BEFORE their own project-local @theme overrides. */
8
-
1
+ /* Tangle brand — Tailwind v4 registration.
2
+ * Import after tailwindcss. tokens.css owns the runtime theme; literal
3
+ * registrations below preserve the public font/radius utility names and are
4
+ * checked against that source. Do not inline those registrations: callers can
5
+ * override --font-* / --radius-* on a subtree.
6
+ */
9
7
  @theme {
10
- /* Typography — unified on Inter */
11
8
  --font-sans: "Inter", "Geist", ui-sans-serif, system-ui, -apple-system, sans-serif;
12
9
  --font-display: "Inter", "Geist", sans-serif;
13
10
  --font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;
14
11
 
15
- /* Canonical type roles — additive semantic sizes (do not shadow Tailwind's
16
- numeric text-* scale). Pair size + leading + tracking + weight so a
17
- `text-display` / `text-page` utility carries the whole role. Prefer the
18
- Heading / PageHeader primitives in @tangle-network/sandbox-ui over raw
19
- utilities so titles stay consistent across every app. */
20
- --text-display: var(--font-size-display);
21
12
  --text-display--line-height: 1.05;
22
13
  --text-display--letter-spacing: -0.02em;
23
14
  --text-display--font-weight: 700;
24
- --text-hero: var(--font-size-hero);
25
15
  --text-hero--line-height: 1.1;
26
16
  --text-hero--letter-spacing: -0.02em;
27
17
  --text-hero--font-weight: 700;
28
- --text-page: var(--font-size-3xl);
29
18
  --text-page--line-height: 1.15;
30
19
  --text-page--letter-spacing: -0.02em;
31
20
  --text-page--font-weight: 600;
32
- --text-section: var(--font-size-xl);
33
21
  --text-section--line-height: 1.3;
34
22
  --text-section--letter-spacing: -0.01em;
35
23
  --text-section--font-weight: 600;
36
- --text-eyebrow: var(--font-size-sm);
37
24
  --text-eyebrow--line-height: 1;
38
25
  --text-eyebrow--letter-spacing: 0.08em;
39
26
  --text-eyebrow--font-weight: 600;
40
27
 
41
- /* Radii — tight chrome scale */
42
28
  --radius-sm: 6px;
43
29
  --radius-md: 8px;
44
30
  --radius-lg: 10px;
45
31
  --radius-xl: 12px;
46
32
  --radius-full: 999px;
47
33
 
48
- /* Core brand accent (indigo) — use as `bg-brand`, `text-brand`, `ring-brand` */
49
34
  --color-brand: #6366F1;
50
35
  --color-brand-dim: #4F46E5;
51
36
  --color-brand-cool: #818CF8;
52
37
  --color-brand-glow: #A5AAFC;
53
38
  --color-brand-emerald: #10B981;
39
+ --color-status-running: #10B981;
40
+ --color-status-creating: #9B93F0;
41
+ --color-status-stopped: #FFB800;
42
+ --color-status-error: #FF4D6D;
43
+
44
+ --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
45
+ --shadow-dropdown: 0 8px 30px rgba(0, 0, 0, 0.45);
46
+ --shadow-glow: none;
47
+ --shadow-overlay:
48
+ 0 2px 6px hsl(var(--hsl-foreground) / 0.1),
49
+ 0 16px 40px hsl(var(--hsl-foreground) / 0.16);
50
+ }
51
+
52
+ /* Inline variable-dependent utilities so their source is resolved on the
53
+ * element using the utility, not frozen where @theme was declared. The
54
+ * named-themes.css bridge retains the --color-* API for precompiled consumers.
55
+ * Public HSL aliases remain HSL channel triples, never full CSS colors.
56
+ */
57
+ @theme inline {
58
+ --text-display: var(--font-size-display);
59
+ --text-hero: var(--font-size-hero);
60
+ --text-page: var(--font-size-3xl);
61
+ --text-section: var(--font-size-xl);
62
+ --text-eyebrow: var(--font-size-sm);
54
63
 
55
- /* Depth stack — REFERENCE the spine in tokens.css (single source; was a stale
56
- hardcoded copy that drifted from --depth-* and broke theme retunes). */
57
64
  --color-depth-1: var(--depth-1);
58
65
  --color-depth-2: var(--depth-2);
59
66
  --color-depth-3: var(--depth-3);
60
67
  --color-depth-4: var(--depth-4);
61
-
62
- /* Semantic surface + text roles — map the shadcn/MD3 utility names onto the
63
- tokens.css spine so `bg-card` / `border-border` / `bg-muted` /
64
- `bg-surface-container*` / `text-muted-foreground` resolve from ONE source
65
- here, instead of every consuming app re-defining them (the drift you hit).
66
- Apps may still override locally; absent an override these are the defaults. */
67
68
  --color-background: hsl(var(--background));
68
69
  --color-foreground: hsl(var(--foreground));
69
70
  --color-card: hsl(var(--card));
@@ -88,26 +89,7 @@
88
89
  --color-surface-container: var(--md3-surface-container);
89
90
  --color-surface-container-high: var(--md3-surface-container-high);
90
91
  --color-surface-container-highest: var(--md3-surface-container-highest);
91
-
92
- /* Semantic text — use as `text-fg`, `text-fg-muted`, `text-fg-dim` */
93
92
  --color-fg: var(--text-primary);
94
93
  --color-fg-muted: var(--text-muted);
95
94
  --color-fg-dim: var(--text-dim);
96
-
97
- /* Status — use as `text-status-running`, `bg-status-stopped` */
98
- --color-status-running: #10B981;
99
- --color-status-creating: #9B93F0;
100
- --color-status-stopped: #FFB800;
101
- --color-status-error: #FF4D6D;
102
-
103
- /* Shadows — flat, no inner ring, no indigo glow */
104
- --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3);
105
- --shadow-dropdown: 0 8px 30px rgba(0, 0, 0, 0.45);
106
- --shadow-glow: none;
107
- /* Theme-derived, so it inverts — see tokens.css. Declared here as well so
108
- Tailwind emits the `shadow-overlay` utility, which is how a consumer
109
- reaches it without writing `shadow-[var(--shadow-overlay)]`. */
110
- --shadow-overlay:
111
- 0 2px 6px hsl(var(--hsl-foreground) / 0.1),
112
- 0 16px 40px hsl(var(--hsl-foreground) / 0.16);
113
95
  }
@@ -30,10 +30,26 @@
30
30
  * work here. The hairline is about 1.5:1 against the resting card — quiet by design,
31
31
  * enough to state an edge without drawing a box around every panel.
32
32
  */
33
+ /* Seed a complete baseline on every supported boundary BEFORE mode overrides.
34
+ * Inherited var() aliases are already substituted at their parent; declaring
35
+ * them here lets a nested light/dark/named scope resolve its own palette.
36
+ * Light scopes are deliberately included in this baseline, then override it
37
+ * below. Named themes only author their product-specific differences. */
33
38
  :root,
34
39
  [data-sandbox-ui],
40
+ [data-sandbox-theme="vault"],
41
+ [data-sandbox-theme="dawn"],
35
42
  [data-theme="dark"],
43
+ [data-theme="light"],
44
+ [data-theme="aubergine"],
45
+ [data-theme="aubergine-light"],
46
+ [data-theme="arena"],
47
+ [data-theme="arena-light"],
48
+ [data-theme="tangle-dark"],
49
+ [data-theme="tangle-light"],
50
+ .light,
36
51
  .dark {
52
+ color-scheme: dark;
37
53
  --md3-surface: #161616; /* L0 page canvas */
38
54
  --md3-surface-dim: #101010; /* recessed page */
39
55
  --md3-surface-bright: #3b3b3b;
@@ -66,6 +82,7 @@
66
82
  --md3-on-secondary-container: #E8E5FF;
67
83
 
68
84
  --md3-tertiary: #10B981;
85
+ --md3-tertiary-container: var(--surface-success-bg);
69
86
  --md3-outline: #8e8e8e;
70
87
  --md3-outline-variant: #4c4c4c;
71
88
 
@@ -390,7 +407,8 @@
390
407
  --tool-card-py: 0.5rem;
391
408
  --tool-icon-size: 1.75rem;
392
409
 
393
- /* Syntax highlighting — override per-theme in vault section */
410
+ /* Syntax highlighting — the light palette is authored below. */
411
+ --code-header-bg: hsl(var(--hsl-background));
394
412
  --syntax-comment: #8b8fbc;
395
413
  --syntax-keyword: #A78FFF;
396
414
  --syntax-string: #10b981;
@@ -401,7 +419,29 @@
401
419
  --syntax-variable: #C4C0D8;
402
420
  --syntax-foreground: #E8E6F6;
403
421
 
404
- /* Transitions */
422
+ /* Shared motion vocabulary, previously authored by the light-default Agent
423
+ * App consumer. These are tokens only, not automatic animation classes. */
424
+ --duration-instant: 90ms;
425
+ --duration-fast: 150ms;
426
+ --duration-base: 240ms;
427
+ --duration-slow: 360ms;
428
+ --duration-stream: 420ms;
429
+ --duration-arrive: 600ms;
430
+ --ease-standard: cubic-bezier(0.2, 0.8, 0.2, 1);
431
+ --ease-entrance: cubic-bezier(0.22, 1, 0.36, 1);
432
+ --ease-exit: cubic-bezier(0.4, 0, 1, 1);
433
+ --ease-expo: cubic-bezier(0.23, 1, 0.32, 1);
434
+ --motion-control: var(--duration-fast) var(--ease-standard);
435
+ --motion-surface: var(--duration-base) var(--ease-entrance);
436
+ --motion-dismiss: var(--duration-instant) var(--ease-exit);
437
+ --motion-stream: var(--duration-stream) var(--ease-expo);
438
+ --motion-arrive: var(--duration-arrive) var(--ease-expo);
439
+ --stagger-step: 50ms;
440
+ --stagger-index: 0;
441
+ --arrive-distance: 8px;
442
+ --stream-blur: 4px;
443
+
444
+ /* Transitions — retain the existing Brand timings. */
405
445
  --transition-fast: 0.1s ease;
406
446
  --transition-default: 0.16s ease;
407
447
  --transition-medium: 0.24s ease;
@@ -416,10 +456,25 @@
416
456
  * `[data-theme="light"]` / `.light` switch. Both blocks are single-attribute/
417
457
  * class selectors, and this one is later in source order, so when an element
418
458
  * carries both `data-sandbox-ui` (dark) and `data-theme="light"`, light wins. */
419
- [data-sandbox-theme="vault"],
459
+ [data-sandbox-theme="vault"]:where(:not(.dark)),
460
+ [data-sandbox-theme="dawn"]:where(:not(.dark)),
420
461
  [data-theme="light"],
462
+ [data-theme="aubergine-light"],
463
+ [data-theme="arena-light"],
464
+ [data-theme="tangle-light"],
421
465
  .light {
466
+ color-scheme: light;
422
467
  /* Light theme — neutral surfaces with purple accents */
468
+ --code-header-bg: color-mix(in srgb, hsl(var(--hsl-muted)) 50%, transparent);
469
+ --syntax-foreground: #24292f;
470
+ --syntax-comment: #57606a;
471
+ --syntax-keyword: #6d28d9;
472
+ --syntax-string: #047857;
473
+ --syntax-function: #1d4ed8;
474
+ --syntax-number: #92400e;
475
+ --syntax-meta: #7c3aed;
476
+ --syntax-variable: #24292f;
477
+ --syntax-error: #b91c1c;
423
478
 
424
479
  /* MD3 surface hierarchy */
425
480
  /* The light ladder ALTERNATES; it is not monotonic, and that is deliberate.
@@ -752,7 +807,8 @@
752
807
  /* Light: the accent is the indigo fill (#4c3fc6, 7.41:1 on white) and the tier
753
808
  * ramp runs light to dark. `[data-theme$="-light"]` covers the named light
754
809
  * themes, which would otherwise inherit the dark ramp from :root. */
755
- [data-sandbox-theme="vault"],
810
+ [data-sandbox-theme="vault"]:where(:not(.dark)),
811
+ [data-sandbox-theme="dawn"]:where(:not(.dark)),
756
812
  [data-theme="light"],
757
813
  .light,
758
814
  [data-theme$="-light"] {
@@ -762,3 +818,28 @@
762
818
  --chart-tier-a: #5b5bd6;
763
819
  --chart-tier-s: #272962;
764
820
  }
821
+
822
+
823
+ /* Motion is opt-in at the component, but its reduced-motion preference is
824
+ * shared. Re-declare composites at the same boundary as their durations. */
825
+ @media (prefers-reduced-motion: reduce) {
826
+ :root,
827
+ .dark,
828
+ .light,
829
+ [data-sandbox-ui],
830
+ [data-sandbox-theme],
831
+ [data-theme] {
832
+ --duration-instant: 0ms;
833
+ --duration-fast: 0ms;
834
+ --duration-base: 0ms;
835
+ --duration-slow: 0ms;
836
+ --duration-stream: 0ms;
837
+ --duration-arrive: 0ms;
838
+ --stagger-step: 0ms;
839
+ --motion-control: var(--duration-fast) var(--ease-standard);
840
+ --motion-surface: var(--duration-base) var(--ease-entrance);
841
+ --motion-dismiss: var(--duration-instant) var(--ease-exit);
842
+ --motion-stream: var(--duration-stream) var(--ease-expo);
843
+ --motion-arrive: var(--duration-arrive) var(--ease-expo);
844
+ }
845
+ }