@gratiaos/ui 1.0.5 β†’ 1.1.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
@@ -7,6 +7,15 @@
7
7
  **Garden UI** is the shared component library that gives shape and soul to the Garden.
8
8
  It’s where headless primitives meet design tokens, growing together into a living interface system.
9
9
 
10
+ ## πŸ›°οΈ Garden Stack naming (infra-facing)
11
+
12
+ - **Pattern Engine** β†’ underlying model stack (training / inference / retrieval). Use this wording for infra/capability talk.
13
+ - **Presence Node** β†’ surfaced endpoint humans touch (web UI, CLI, scripts, voice, agents).
14
+ - **Mode** β†’ behavioral / conversational contract for a Presence Node (e.g. `Codex-mode`, `Monday-mode`). Styles, not identities.
15
+ - **Garden Stack** β†’ Pattern Engine + Presence Nodes + Modes working together.
16
+
17
+ Route any β€œAI” mention to the correct layer so UI docs stay aligned with Garden + M3.
18
+
10
19
  ---
11
20
 
12
21
  ## ✨ Vision
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Garden UI β€” PersonalPulse primitive (headless)
4
+ * ----------------------------------------------
5
+ * Whisper: "tiny beacon, still here." 🌬️
6
+ *
7
+ * Purpose
8
+ * β€’ Mirrors the shared pulse so the interface feels alive even when idle.
9
+ * β€’ Falls back to a soft idle rhythm when no beats arrive for a while.
10
+ */
11
+ export declare const PersonalPulse: React.FC;
12
+ //# sourceMappingURL=PersonalPulse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersonalPulse.d.ts","sourceRoot":"","sources":["../../src/footer/PersonalPulse.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAiEjC,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { pulse$ } from '@gratiaos/presence-kernel';
4
+ /**
5
+ * Garden UI β€” PersonalPulse primitive (headless)
6
+ * ----------------------------------------------
7
+ * Whisper: "tiny beacon, still here." 🌬️
8
+ *
9
+ * Purpose
10
+ * β€’ Mirrors the shared pulse so the interface feels alive even when idle.
11
+ * β€’ Falls back to a soft idle rhythm when no beats arrive for a while.
12
+ */
13
+ export const PersonalPulse = () => {
14
+ const ref = React.useRef(null);
15
+ const [reduceMotion, setReduceMotion] = React.useState(() => {
16
+ if (typeof window === 'undefined')
17
+ return false;
18
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
19
+ });
20
+ React.useEffect(() => {
21
+ if (typeof window === 'undefined')
22
+ return;
23
+ const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
24
+ const update = () => setReduceMotion(mq.matches);
25
+ mq.addEventListener('change', update);
26
+ update();
27
+ return () => mq.removeEventListener('change', update);
28
+ }, []);
29
+ React.useEffect(() => {
30
+ if (reduceMotion) {
31
+ const node = ref.current;
32
+ if (node)
33
+ node.style.animation = 'none';
34
+ return;
35
+ }
36
+ const node = ref.current;
37
+ if (!node)
38
+ return;
39
+ let idleTimer = null;
40
+ const beginIdle = () => {
41
+ if (!node)
42
+ return;
43
+ node.style.animation = 'idle-pulse 6s ease-in-out infinite';
44
+ };
45
+ const cancelIdle = () => {
46
+ if (!node)
47
+ return;
48
+ node.style.animation = 'none';
49
+ };
50
+ const handleBeat = () => {
51
+ cancelIdle();
52
+ node.animate([
53
+ { opacity: 0.25, transform: 'scale(1)' },
54
+ { opacity: 0.55, transform: 'scale(1.15)' },
55
+ { opacity: 0.25, transform: 'scale(1)' },
56
+ ], {
57
+ duration: 420,
58
+ easing: 'ease-out',
59
+ });
60
+ if (idleTimer)
61
+ clearTimeout(idleTimer);
62
+ idleTimer = window.setTimeout(beginIdle, 8000);
63
+ };
64
+ const stop = pulse$.subscribe(handleBeat);
65
+ idleTimer = window.setTimeout(beginIdle, 8000);
66
+ return () => {
67
+ stop();
68
+ if (idleTimer)
69
+ clearTimeout(idleTimer);
70
+ };
71
+ }, [reduceMotion]);
72
+ return _jsx("div", { ref: ref, "data-ui": "personal-pulse", "aria-hidden": "true" });
73
+ };
74
+ //# sourceMappingURL=PersonalPulse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PersonalPulse.js","sourceRoot":"","sources":["../../src/footer/PersonalPulse.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import * as React from 'react';
2
+ import { type KernelAuthority } from '@gratiaos/presence-kernel';
3
+ /**
4
+ * Garden UI β€” ConductorChip primitive (headless)
5
+ * ---------------------------------------------
6
+ * Whisper: "name the conductor softly." 🌬️
7
+ *
8
+ * Purpose
9
+ * β€’ Display the active presence authority as a compact HUD chip.
10
+ * β€’ Mirrors kernel signals without requiring a kernel instance.
11
+ *
12
+ * Data API
13
+ * β€’ [data-ui="conductor-chip"] β€” root hook for skins.
14
+ * β€’ [data-authority="…"] β€” matches KernelAuthority enum.
15
+ *
16
+ * A11y
17
+ * β€’ Title defaults to "Authority: …" unless overridden via props.
18
+ *
19
+ * Theming
20
+ * β€’ Reads tone tokens (--tone-accent, --tone-ink) for visuals.
21
+ *
22
+ * Notes
23
+ * β€’ Headless: visuals live in styles/header.css.
24
+ */
25
+ export interface ConductorChipProps extends React.ComponentPropsWithoutRef<'span'> {
26
+ /** Optional custom label formatter. Receives the raw authority string. */
27
+ formatLabel?: (authority: KernelAuthority) => React.ReactNode;
28
+ }
29
+ export declare const ConductorChip: React.FC<ConductorChipProps>;
30
+ //# sourceMappingURL=ConductorChip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConductorChip.d.ts","sourceRoot":"","sources":["../../src/header/ConductorChip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,wBAAwB,CAAC,MAAM,CAAC;IAChF,0EAA0E;IAC1E,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,KAAK,CAAC,SAAS,CAAC;CAC/D;AAQD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAkBtD,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { authority$ } from '@gratiaos/presence-kernel';
4
+ const DEFAULT_LABELS = {
5
+ 'local-primary': 'Local',
6
+ 'remote-primary': 'Remote',
7
+ distributed: 'Mesh',
8
+ };
9
+ export const ConductorChip = ({ className, title, children, formatLabel, ...rest }) => {
10
+ const [authority, setAuthority] = React.useState(authority$.value);
11
+ React.useEffect(() => authority$.subscribe(setAuthority), []);
12
+ const label = React.useMemo(() => {
13
+ if (formatLabel)
14
+ return formatLabel(authority);
15
+ return DEFAULT_LABELS[authority] ?? authority;
16
+ }, [authority, formatLabel]);
17
+ const resolvedTitle = title ?? `Authority: ${authority}`;
18
+ const resolvedClassName = ['conductor-chip', className].filter(Boolean).join(' ') || undefined;
19
+ return (_jsx("span", { "data-ui": "conductor-chip", "data-authority": authority, className: resolvedClassName, title: resolvedTitle, ...rest, children: children ?? label }));
20
+ };
21
+ //# sourceMappingURL=ConductorChip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConductorChip.js","sourceRoot":"","sources":["../../src/header/ConductorChip.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAwB,MAAM,2BAA2B,CAAC;AA6B7E,MAAM,cAAc,GAA2B;IAC7C,eAAe,EAAE,OAAO;IACxB,gBAAgB,EAAE,QAAQ;IAC1B,WAAW,EAAE,MAAM;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAiC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE;IAClH,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAkB,UAAU,CAAC,KAAK,CAAC,CAAC;IAEpF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;IAE9D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QAC/B,IAAI,WAAW;YAAE,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;QAC/C,OAAO,cAAc,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;IAChD,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAE7B,MAAM,aAAa,GAAG,KAAK,IAAI,cAAc,SAAS,EAAE,CAAC;IACzD,MAAM,iBAAiB,GAAG,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IAE/F,OAAO,CACL,0BAAc,gBAAgB,oBAAiB,SAAS,EAAE,SAAS,EAAE,iBAAiB,EAAE,KAAK,EAAE,aAAa,KAAM,IAAI,YACnH,QAAQ,IAAI,KAAK,GACb,CACR,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Garden UI β€” Constellation primitive (headless)
4
+ * ---------------------------------------------
5
+ * Whisper: "quiet company overhead." 🌬️
6
+ *
7
+ * Purpose
8
+ * β€’ Minimal belonging indicator β€” signals presence context without interaction.
9
+ *
10
+ * Data API
11
+ * β€’ [data-ui="constellation"] β€” root wrapper hook.
12
+ *
13
+ * Notes
14
+ * β€’ Static dots; peers are abstract and not tied to live presence counts.
15
+ */
16
+ export declare const Constellation: React.FC;
17
+ //# sourceMappingURL=Constellation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Constellation.d.ts","sourceRoot":"","sources":["../../src/header/Constellation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAUjC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Garden UI β€” Constellation primitive (headless)
4
+ * ---------------------------------------------
5
+ * Whisper: "quiet company overhead." 🌬️
6
+ *
7
+ * Purpose
8
+ * β€’ Minimal belonging indicator β€” signals presence context without interaction.
9
+ *
10
+ * Data API
11
+ * β€’ [data-ui="constellation"] β€” root wrapper hook.
12
+ *
13
+ * Notes
14
+ * β€’ Static dots; peers are abstract and not tied to live presence counts.
15
+ */
16
+ export const Constellation = () => {
17
+ return (_jsxs("div", { "data-ui": "constellation", "aria-hidden": "true", children: [_jsx("span", { className: "dot" }), _jsx("span", { className: "dot" }), _jsx("span", { className: "dot active" }), _jsx("span", { className: "dot" }), _jsx("span", { className: "dot" })] }));
18
+ };
19
+ //# sourceMappingURL=Constellation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Constellation.js","sourceRoot":"","sources":["../../src/header/Constellation.tsx"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,aAAa,GAAa,GAAG,EAAE;IAC1C,OAAO,CACL,0BAAa,eAAe,iBAAa,MAAM,aAC7C,eAAM,SAAS,EAAC,KAAK,GAAG,EACxB,eAAM,SAAS,EAAC,KAAK,GAAG,EACxB,eAAM,SAAS,EAAC,YAAY,GAAG,EAC/B,eAAM,SAAS,EAAC,KAAK,GAAG,EACxB,eAAM,SAAS,EAAC,KAAK,GAAG,IACpB,CACP,CAAC;AACJ,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -7,4 +7,7 @@ export * from './primitives/badge.js';
7
7
  export * from './primitives/toast.js';
8
8
  export * from './primitives/whisper.js';
9
9
  export * from './hooks/index.js';
10
+ export * from './header/ConductorChip.js';
11
+ export * from './header/Constellation.js';
12
+ export * from './footer/PersonalPulse.js';
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC"}
package/dist/index.js CHANGED
@@ -7,4 +7,7 @@ export * from './primitives/badge.js';
7
7
  export * from './primitives/toast.js';
8
8
  export * from './primitives/whisper.js';
9
9
  export * from './hooks/index.js';
10
+ export * from './header/ConductorChip.js';
11
+ export * from './header/Constellation.js';
12
+ export * from './footer/PersonalPulse.js';
10
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gratiaos/ui",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "funding": "https://github.com/sponsors/GratiaOS",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
@@ -92,6 +92,9 @@
92
92
  "peerDependencies": {
93
93
  "react": "^18 || ^19"
94
94
  },
95
+ "dependencies": {
96
+ "@gratiaos/presence-kernel": "workspace:*"
97
+ },
95
98
  "devDependencies": {
96
99
  "typescript": "^5.9.3",
97
100
  "react": "^19.2.0",
package/styles/base.css CHANGED
@@ -6,3 +6,4 @@
6
6
  @import './toast.css';
7
7
  @import './badge.css';
8
8
  @import './whisper.css';
9
+ @import './header.css';
@@ -0,0 +1,93 @@
1
+ /* ─────────────────────────────────────────
2
+ Garden UI β€” ConductorChip skin (opt-in)
3
+ Whisper: "name the conductor softly." 🌬️
4
+ Purpose | Data API | Notes
5
+ ─────────────────────────────────────── */
6
+ @layer components {
7
+ [data-ui='conductor-chip'] {
8
+ display: inline-flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ gap: 0.35rem;
12
+ padding: 0.125rem 0.5625rem;
13
+ border-radius: 9999px;
14
+ font-size: 0.6875rem;
15
+ font-weight: 600;
16
+ letter-spacing: 0.02em;
17
+ text-transform: uppercase;
18
+ color: var(--tone-ink);
19
+ background: color-mix(in oklab, var(--tone-accent) 22%, transparent);
20
+ border: 1px solid color-mix(in oklab, var(--tone-accent) 38%, transparent);
21
+ box-shadow: var(--tone-glow, 0 0 24px color-mix(in oklab, var(--tone-accent) 30%, transparent));
22
+ backdrop-filter: blur(8px);
23
+ pointer-events: auto;
24
+ transition:
25
+ background var(--duration-snug, 160ms) var(--ease-soft, ease),
26
+ color var(--duration-snug, 160ms) var(--ease-soft, ease),
27
+ border-color var(--duration-snug, 160ms) var(--ease-soft, ease),
28
+ box-shadow var(--duration-snug, 160ms) var(--ease-soft, ease);
29
+ }
30
+
31
+ @media (prefers-reduced-motion: reduce) {
32
+ [data-ui='conductor-chip'] {
33
+ transition: none;
34
+ }
35
+ }
36
+
37
+ [data-ui='personal-pulse'] {
38
+ position: absolute;
39
+ bottom: 18px;
40
+ left: 72px;
41
+ width: 6px;
42
+ height: 6px;
43
+ border-radius: 999px;
44
+ background: var(--tone-accent);
45
+ opacity: 0.25;
46
+ will-change: transform, opacity;
47
+ pointer-events: none;
48
+ }
49
+
50
+ @media (prefers-reduced-motion: reduce) {
51
+ [data-ui='personal-pulse'] {
52
+ animation: none !important;
53
+ }
54
+ }
55
+
56
+ @keyframes idle-pulse {
57
+ 0%,
58
+ 100% {
59
+ opacity: 0.18;
60
+ transform: scale(1);
61
+ }
62
+ 50% {
63
+ opacity: 0.4;
64
+ transform: scale(1.12);
65
+ }
66
+ }
67
+
68
+ :root {
69
+ --constellation-dot: color-mix(in oklab, var(--tone-ink) 55%, transparent);
70
+ --constellation-active: var(--tone-accent);
71
+ }
72
+
73
+ [data-ui='constellation'] {
74
+ display: flex;
75
+ gap: 8px;
76
+ justify-content: center;
77
+ opacity: 0.32;
78
+ pointer-events: none;
79
+ user-select: none;
80
+ }
81
+
82
+ [data-ui='constellation'] .dot {
83
+ width: 3px;
84
+ height: 3px;
85
+ border-radius: 50%;
86
+ background: var(--constellation-dot);
87
+ }
88
+
89
+ [data-ui='constellation'] .dot.active {
90
+ background: var(--constellation-active);
91
+ opacity: 0.9;
92
+ }
93
+ }
package/styles/pad.css CHANGED
@@ -1,17 +1,28 @@
1
1
  /* 1) Pad runtime mappings β€” inherit from global theme */
2
2
  @layer base {
3
3
  :root {
4
+ /* Tone alignment β€” sync Pad surfacing with main layout frequency mix */
5
+ --tone-surface: var(--color-surface, #0F1317);
6
+ --tone-ink: var(--color-ink, var(--color-text, #E6EDF5));
7
+ --tone-accent: var(--color-accent, #3ED0C8);
8
+
9
+ --pad-bg-0: color-mix(in oklch, var(--tone-surface) 94%, var(--tone-ink));
10
+ --pad-bg-1: color-mix(in oklch, var(--tone-surface) 90%, var(--tone-ink));
11
+ --pad-ink-muted: color-mix(in oklch, var(--tone-ink) 65%, var(--tone-surface));
12
+ --pad-border-soft: color-mix(in oklch, var(--tone-ink) 8%, var(--tone-surface));
13
+ --pad-focus-ring: color-mix(in oklch, var(--tone-accent) 70%, transparent);
14
+
4
15
  /* Surfaces & text */
5
- --pad-surface: var(--color-surface);
6
- --pad-elev: var(--color-elev);
7
- --pad-border: var(--color-border);
8
- --pad-text: var(--color-text);
9
- --pad-text-muted: var(--color-muted);
16
+ --pad-surface: var(--pad-bg-0, var(--color-surface));
17
+ --pad-elev: var(--pad-bg-1, var(--color-elev));
18
+ --pad-border: var(--pad-border-soft, var(--color-border));
19
+ --pad-text: var(--tone-ink, var(--color-text));
20
+ --pad-text-muted: var(--pad-ink-muted, var(--color-muted));
10
21
  --pad-text-subtle: var(--color-subtle);
11
22
  --pad-text-faint: var(--color-faint);
12
23
 
13
24
  /* Accent system */
14
- --pad-accent: var(--color-accent);
25
+ --pad-accent: var(--tone-accent);
15
26
  --pad-onaccent: var(--color-on-accent);
16
27
 
17
28
  /* Shape & depth */
@@ -44,6 +55,43 @@
44
55
  .pad-ring {
45
56
  box-shadow: 0 0 0 3px var(--pad-ring);
46
57
  }
58
+
59
+ /* Tabs */
60
+ [data-pad-tabs] [role='tab'] {
61
+ background: transparent;
62
+ color: var(--pad-text-muted);
63
+ border: 0;
64
+ border-bottom: 1px solid var(--pad-border);
65
+ border-radius: 0;
66
+ padding-bottom: 0.4rem;
67
+ }
68
+ [data-pad-tabs] [role='tab'][aria-selected='true'] {
69
+ color: var(--pad-text);
70
+ border-bottom-color: var(--pad-accent);
71
+ box-shadow: 0 2px 0 0 color-mix(in oklch, var(--pad-accent) 55%, transparent);
72
+ }
73
+
74
+ /* Inputs */
75
+ .codex-portal,
76
+ .pad-input,
77
+ .pad-textarea {
78
+ background: var(--pad-elev);
79
+ color: var(--pad-text);
80
+ border: 1px solid var(--pad-border);
81
+ border-radius: var(--pad-radius);
82
+ transition: border-color var(--duration-snug, 160ms) var(--ease-soft),
83
+ box-shadow var(--duration-snug, 160ms) var(--ease-soft);
84
+ }
85
+ .codex-portal:focus,
86
+ .pad-input:focus,
87
+ .pad-textarea:focus {
88
+ outline: 0;
89
+ border-color: color-mix(in oklch, var(--pad-accent) 35%, var(--pad-border));
90
+ box-shadow: 0 0 0 2px var(--pad-focus-ring);
91
+ }
92
+ .pad-textarea::placeholder {
93
+ color: var(--pad-text-muted);
94
+ }
47
95
  }
48
96
 
49
97
  /* 3) Pad mood & depth utilities (Layered Synesthetic UI) */
package/styles/theme.css CHANGED
@@ -162,6 +162,49 @@
162
162
 
163
163
  /* === Runtime dark mapping (no duplicate @theme) === */
164
164
  @layer base {
165
+ :root {
166
+ --tone-accent: color-mix(in oklab, var(--color-accent) 82%, white 18%);
167
+ --tone-surface: color-mix(in oklab, var(--color-surface) 92%, var(--tone-accent) 8%);
168
+ --tone-ink: color-mix(in oklab, var(--color-text) 96%, white 4%);
169
+ --tone-glow: 0 0 24px color-mix(in oklab, var(--tone-accent) 32%, transparent);
170
+ }
171
+
172
+ :root[data-mood='soft'] {
173
+ --tone-surface: color-mix(in oklab, var(--color-surface) 92%, var(--tone-accent) 8%);
174
+ --tone-ink: color-mix(in oklab, var(--color-text) 96%, white 4%);
175
+ --tone-glow: 0 0 24px color-mix(in oklab, var(--tone-accent) 32%, transparent);
176
+ }
177
+
178
+ :root[data-mood='presence'] {
179
+ --tone-surface: color-mix(in oklab, var(--color-surface) 88%, var(--tone-accent) 12%);
180
+ --tone-ink: color-mix(in oklab, var(--color-text) 94%, white 6%);
181
+ --tone-glow: 0 0 28px color-mix(in oklab, var(--tone-accent) 38%, transparent);
182
+ }
183
+
184
+ :root[data-mood='focused'] {
185
+ --tone-surface: color-mix(in oklab, var(--color-surface) 84%, var(--tone-accent) 16%);
186
+ --tone-ink: color-mix(in oklab, var(--color-text) 92%, white 8%);
187
+ --tone-glow: 0 0 32px color-mix(in oklab, var(--tone-accent) 46%, transparent);
188
+ }
189
+
190
+ :root[data-mood='celebratory'] {
191
+ --tone-surface: color-mix(in oklab, var(--color-surface) 82%, var(--tone-accent) 18%);
192
+ --tone-ink: color-mix(in oklab, var(--color-text) 90%, white 10%);
193
+ --tone-glow: 0 0 36px color-mix(in oklab, var(--tone-accent) 54%, transparent);
194
+ }
195
+
196
+ :root[data-authority='local-primary'] {
197
+ --tone-accent: #9fc2ff;
198
+ }
199
+
200
+ :root[data-authority='remote-primary'] {
201
+ --tone-accent: #b2ffa8;
202
+ }
203
+
204
+ :root[data-authority='distributed'] {
205
+ --tone-accent: #ffd59e;
206
+ }
207
+
165
208
  :root[data-theme='dark'],
166
209
  :root.dark {
167
210
  --color-surface: oklch(21% 0.07 241);
@@ -220,11 +263,17 @@
220
263
  --inset-shadow-depth-3: inset 0 3px 6px rgb(0 0 0 / 0.3);
221
264
 
222
265
  --drop-shadow-depth-0: 0 0 0 rgb(0 0 0 / 0);
223
- --drop-shadow-depth-1: 0 1px 1px rgb(0 0 0 / 0.25);
224
- --drop-shadow-depth-2: 0 3px 3px rgb(0 0 0 / 0.32);
225
- --drop-shadow-depth-3: 0 6px 6px rgb(0 0 0 / 0.42);
226
- }
266
+ --drop-shadow-depth-1: 0 1px 1px rgb(0 0 0 / 0.25);
267
+ --drop-shadow-depth-2: 0 3px 3px rgb(0 0 0 / 0.32);
268
+ --drop-shadow-depth-3: 0 6px 6px rgb(0 0 0 / 0.42);
269
+
270
+ --tone-accent: color-mix(in oklab, var(--color-accent) 70%, white 30%);
271
+ --tone-surface: color-mix(in oklab, var(--color-surface) 88%, var(--tone-accent) 12%);
272
+ --tone-ink: color-mix(in oklab, var(--color-text) 98%, white 2%);
273
+ --tone-glow: 0 0 32px color-mix(in oklab, var(--tone-accent) 42%, transparent);
274
+ --constellation-dot: color-mix(in oklab, var(--tone-ink) 65%, transparent);
227
275
  }
276
+ }
228
277
 
229
278
  /* Depth mapping helpers β€” set current depth variables from [data-depth] */
230
279
  :root {
@@ -256,11 +305,11 @@
256
305
  --glow-intensity: 0.08;
257
306
  --grain-strength: 0.1;
258
307
  --grain-size: 160px; /* larger tile -> softer grain geometry */
259
- --track-glow: color-mix(in oklab, var(--color-accent) 45%, transparent);
260
- --track-shadow: color-mix(in oklab, var(--color-text) 25%, transparent);
261
- --scene-highlight: color-mix(in oklab, var(--color-accent) 55%, transparent);
262
- --presence-dot-color: color-mix(in oklab, var(--color-accent) 65%, white 15%);
263
- --ghost-trail-color: color-mix(in oklab, var(--color-accent) 18%, transparent);
308
+ --track-glow: color-mix(in oklab, var(--tone-accent) 45%, transparent);
309
+ --track-shadow: color-mix(in oklab, var(--tone-accent) 25%, transparent);
310
+ --scene-highlight: color-mix(in oklab, var(--tone-accent) 55%, transparent);
311
+ --presence-dot-color: color-mix(in oklab, var(--tone-accent) 65%, white 15%);
312
+ --ghost-trail-color: color-mix(in oklab, var(--tone-accent) 18%, transparent);
264
313
 
265
314
  /* calmer hero gradient and slower entrances */
266
315
  --pad-hero-start: color-mix(in oklab, var(--accent) 8%, var(--surface));
@@ -279,11 +328,11 @@
279
328
  --glow-intensity: 0.12;
280
329
  --grain-strength: 0.12;
281
330
  --grain-size: 130px; /* tighter tile -> slightly crisper grain */
282
- --track-glow: color-mix(in oklab, var(--color-accent) 65%, transparent);
283
- --track-shadow: color-mix(in oklab, var(--color-accent) 28%, transparent);
284
- --scene-highlight: color-mix(in oklab, var(--color-accent) 70%, transparent);
285
- --presence-dot-color: color-mix(in oklab, var(--color-accent) 78%, white 12%);
286
- --ghost-trail-color: color-mix(in oklab, var(--color-accent) 24%, transparent);
331
+ --track-glow: color-mix(in oklab, var(--tone-accent) 65%, transparent);
332
+ --track-shadow: color-mix(in oklab, var(--tone-accent) 28%, transparent);
333
+ --scene-highlight: color-mix(in oklab, var(--tone-accent) 70%, transparent);
334
+ --presence-dot-color: color-mix(in oklab, var(--tone-accent) 78%, white 12%);
335
+ --ghost-trail-color: color-mix(in oklab, var(--tone-accent) 24%, transparent);
287
336
 
288
337
  --pad-hero-start: color-mix(in oklab, var(--accent) 16%, var(--surface));
289
338
  --pad-hero-end: color-mix(in oklab, var(--accent) 6%, var(--surface));
@@ -301,11 +350,11 @@
301
350
  --glow-intensity: 0.18;
302
351
  --grain-strength: 0.14;
303
352
  --grain-size: 120px; /* smallest tile -> more lively grain */
304
- --track-glow: color-mix(in oklab, var(--color-accent) 90%, white 10%);
305
- --track-shadow: color-mix(in oklab, var(--color-accent) 35%, transparent);
306
- --scene-highlight: color-mix(in oklab, var(--color-accent) 92%, white 8%);
307
- --presence-dot-color: color-mix(in oklab, var(--color-accent) 94%, white 12%);
308
- --ghost-trail-color: color-mix(in oklab, var(--color-accent) 32%, transparent);
353
+ --track-glow: color-mix(in oklab, var(--tone-accent) 90%, white 10%);
354
+ --track-shadow: color-mix(in oklab, var(--tone-accent) 35%, transparent);
355
+ --scene-highlight: color-mix(in oklab, var(--tone-accent) 92%, white 8%);
356
+ --presence-dot-color: color-mix(in oklab, var(--tone-accent) 94%, white 12%);
357
+ --ghost-trail-color: color-mix(in oklab, var(--tone-accent) 32%, transparent);
309
358
 
310
359
  --pad-hero-start: color-mix(in oklab, var(--accent) 24%, var(--surface));
311
360
  --pad-hero-end: color-mix(in oklab, var(--accent) 12%, var(--surface));
@@ -363,11 +412,11 @@
363
412
  --ring-alpha: 0.18; /* 0–1 β€” whisper ring strength */
364
413
  --grain-strength: 0.12; /* 0–1 β€” ambient grain strength */
365
414
  --grain-size: 140px; /* px β€” grain tile size used by card grain overlay */
366
- --track-glow: color-mix(in oklab, var(--color-accent) 55%, transparent);
367
- --track-shadow: color-mix(in oklab, var(--color-text) 25%, transparent);
368
- --scene-highlight: color-mix(in oklab, var(--color-accent) 60%, transparent);
369
- --presence-dot-color: color-mix(in oklab, var(--color-accent) 70%, white 15%);
370
- --ghost-trail-color: color-mix(in oklab, var(--color-accent) 22%, transparent);
415
+ --track-glow: color-mix(in oklab, var(--tone-accent) 55%, transparent);
416
+ --track-shadow: color-mix(in oklab, var(--tone-accent) 32%, transparent);
417
+ --scene-highlight: color-mix(in oklab, var(--tone-accent) 60%, transparent);
418
+ --presence-dot-color: color-mix(in oklab, var(--tone-accent) 70%, white 15%);
419
+ --ghost-trail-color: color-mix(in oklab, var(--tone-accent) 22%, transparent);
371
420
  }
372
421
 
373
422
  @layer utilities {