@orangecheck/design 0.24.0 → 0.26.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.
@@ -225,9 +225,36 @@
225
225
  }
226
226
  }
227
227
 
228
+ /* Grain — the 2026 texture pass. A tiny repeating feTurbulence tile (160px,
229
+ luminance-only so it is skin-agnostic) riding inside the aurora slot, so it
230
+ inherits the radial edge fade and the intensity/mode dampening for free.
231
+ Static — unaffected by reduced-motion. Dial with --oc-grain-op; zero it
232
+ per-site with one CSS line. */
233
+ .oc-aurora__grain {
234
+ position: absolute;
235
+ inset: 0;
236
+ mix-blend-mode: overlay;
237
+ opacity: var(--oc-grain-op, 0.1);
238
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
239
+ background-repeat: repeat;
240
+ }
241
+ :root.dark .oc-aurora__grain {
242
+ opacity: calc(var(--oc-grain-op, 0.1) * 1.3);
243
+ }
244
+
228
245
  /* Motion-sensitive: hold the clouds still (they still recolour via tokens). */
229
246
  @media (prefers-reduced-motion: reduce) {
230
247
  .oc-aurora__blob {
231
248
  animation: none !important;
232
249
  }
233
250
  }
251
+
252
+ /* Ambient-motion switch (oc_motion cookie → data-oc-motion="off" on <html>,
253
+ applied pre-paint by getOcThemeInitScript). This is the WCAG 2.2.2
254
+ Pause/Stop/Hide mechanism — a user choice, distinct from the OS-level
255
+ prefers-reduced-motion above. `.oc-ambient` is the shared opt-in hook: any
256
+ decorative animation in the family adds the class and inherits the pause. */
257
+ :root[data-oc-motion='off'] .oc-aurora__blob,
258
+ :root[data-oc-motion='off'] .oc-ambient {
259
+ animation-play-state: paused !important;
260
+ }
@@ -311,6 +311,86 @@
311
311
  );
312
312
  background-size: 16px 16px;
313
313
  }
314
+ /* Guides — the quieter, 2026-register evolution of .bg-grid: a fainter
315
+ 56px lattice with plus-mark crosses at the intersections (crosses via a
316
+ masked ::before so their color stays token-reactive). Opt-in; .bg-grid
317
+ is untouched. */
318
+ .oc-guides {
319
+ position: relative;
320
+ background-image:
321
+ linear-gradient(
322
+ to right,
323
+ color-mix(in oklch, var(--foreground), transparent 96%) 1px,
324
+ transparent 1px
325
+ ),
326
+ linear-gradient(
327
+ to bottom,
328
+ color-mix(in oklch, var(--foreground), transparent 96%) 1px,
329
+ transparent 1px
330
+ );
331
+ background-size: 56px 56px;
332
+ }
333
+ .oc-guides::before {
334
+ content: '';
335
+ position: absolute;
336
+ inset: 0;
337
+ pointer-events: none;
338
+ background: color-mix(in oklch, var(--foreground), transparent 76%);
339
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='56'%20height='56'%3E%3Cpath%20d='M27.5,23h1v10h-1zM23,27.5h10v1h-10z'/%3E%3C/svg%3E");
340
+ mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='56'%20height='56'%3E%3Cpath%20d='M27.5,23h1v10h-1zM23,27.5h10v1h-10z'/%3E%3C/svg%3E");
341
+ -webkit-mask-size: 56px 56px;
342
+ mask-size: 56px 56px;
343
+ -webkit-mask-position: -28px -28px;
344
+ mask-position: -28px -28px;
345
+ }
346
+ /* .oc-halo — the glyph-shaped glow plate (the sanctioned "plinth"): the
347
+ normalized orangecheck mark as a soft token-tinted mask behind a hero
348
+ artifact card. Zero JS, one composited layer, no motion. Absorbs the
349
+ hand-rolled `bg-primary/10 -inset-6 blur-3xl` pattern. Override the mark
350
+ per-site via --oc-halo-mask (a url(...) to another normalized 0..1024
351
+ media-kit glyph); dial with --oc-halo-op / --oc-halo-blur /
352
+ --oc-halo-color. Mount inside a `relative` wrapper, before the card in
353
+ source order. The default mask is the normalized media-kit render of the
354
+ mark (centering/flip transform baked in) — never the raw font-space path. */
355
+ .oc-halo {
356
+ position: absolute;
357
+ inset: -18%;
358
+ pointer-events: none;
359
+ background: var(--oc-halo-color, var(--primary));
360
+ opacity: var(--oc-halo-op, 0.3);
361
+ filter: blur(var(--oc-halo-blur, 40px));
362
+ -webkit-mask-image: var(
363
+ --oc-halo-mask,
364
+ url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201024%201024'%3E%3Cpath%20d='M518,856Q463,820,438.5,785.5Q414,751,414,711Q414,657,462.5,613.0Q511,569,711,473Q766,509,790.5,543.5Q815,578,815,621Q815,702,550,840ZM930,1460V1235Q845,1265,779.0,1279.5Q713,1294,659,1294Q583,1294,540.5,1265.0Q498,1236,498,1184Q498,1109,701,1004Q720,994,729,989Q943,879,1002.0,808.5Q1061,738,1061,637Q1061,548,1013.5,484.0Q966,420,864,373Q934,323,966.5,261.5Q999,200,999,119Q999,-28,894.5,-111.5Q790,-195,604,-195Q515,-195,429.0,-180.5Q343,-166,258,-137V92Q343,62,424.0,46.5Q505,31,578,31Q655,31,696.0,59.5Q737,88,737,141Q737,211,523,326L512,332L486,346Q170,516,170,688Q170,782,222.0,851.5Q274,921,371,954Q300,1004,268.0,1064.0Q236,1124,236,1206Q236,1348,340.0,1434.0Q444,1520,616,1520Q690,1520,768.5,1505.0Q847,1490,930,1460Z'%20transform='translate(195.9452,852.1889),scale(0.513493,-0.513493)'/%3E%3C/svg%3E")
365
+ );
366
+ mask-image: var(
367
+ --oc-halo-mask,
368
+ url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201024%201024'%3E%3Cpath%20d='M518,856Q463,820,438.5,785.5Q414,751,414,711Q414,657,462.5,613.0Q511,569,711,473Q766,509,790.5,543.5Q815,578,815,621Q815,702,550,840ZM930,1460V1235Q845,1265,779.0,1279.5Q713,1294,659,1294Q583,1294,540.5,1265.0Q498,1236,498,1184Q498,1109,701,1004Q720,994,729,989Q943,879,1002.0,808.5Q1061,738,1061,637Q1061,548,1013.5,484.0Q966,420,864,373Q934,323,966.5,261.5Q999,200,999,119Q999,-28,894.5,-111.5Q790,-195,604,-195Q515,-195,429.0,-180.5Q343,-166,258,-137V92Q343,62,424.0,46.5Q505,31,578,31Q655,31,696.0,59.5Q737,88,737,141Q737,211,523,326L512,332L486,346Q170,516,170,688Q170,782,222.0,851.5Q274,921,371,954Q300,1004,268.0,1064.0Q236,1124,236,1206Q236,1348,340.0,1434.0Q444,1520,616,1520Q690,1520,768.5,1505.0Q847,1490,930,1460Z'%20transform='translate(195.9452,852.1889),scale(0.513493,-0.513493)'/%3E%3C/svg%3E")
369
+ );
370
+ -webkit-mask-repeat: no-repeat;
371
+ mask-repeat: no-repeat;
372
+ -webkit-mask-position: center;
373
+ mask-position: center;
374
+ -webkit-mask-size: contain;
375
+ mask-size: contain;
376
+ }
377
+ /* Cypherpunk skins: hard borders, no soft shadows — the halo tightens to a
378
+ crisp edge-glow instead of a warm bloom (skin-coherent, per charter). */
379
+ :root[data-oc-theme='orangecheck'] .oc-halo,
380
+ :root[data-oc-theme='phosphor'] .oc-halo,
381
+ :root[data-oc-theme='lightning'] .oc-halo,
382
+ :root[data-oc-theme='gold'] .oc-halo {
383
+ filter: blur(var(--oc-halo-blur, 10px));
384
+ opacity: calc(var(--oc-halo-op, 0.3) * 0.6);
385
+ }
386
+ /* Decorative rasters are NOT auto-stripped by forced colors the way
387
+ gradients are — hide them explicitly. */
388
+ @media (forced-colors: active) {
389
+ .oc-halo,
390
+ .oc-aurora__grain {
391
+ display: none;
392
+ }
393
+ }
314
394
  /* currentColor-based textures for brand/CTA bands. NOT prefixed `bg-`:
315
395
  tailwind-merge misclassifies any `bg-*` class as a background-color and
316
396
  would drop a real `bg-brand`/`bg-card` sitting next to it in the same
package/dist/tokens.d.mts CHANGED
@@ -18,16 +18,20 @@ type OcThemeId = (typeof OC_THEMES)[number]['id'] | (string & {});
18
18
  declare function isKnownTheme(id: string | null | undefined): id is OcThemeId;
19
19
  declare function resolveTheme(id: string | null | undefined): string;
20
20
  declare const OC_SKIN_COOKIE = "oc_skin";
21
+ declare const OC_MOTION_COOKIE = "oc_motion";
21
22
 
22
23
  declare global {
23
24
  interface Window {
24
25
  __ocApplySkinChrome?: (skin: string) => void;
25
26
  }
26
27
  }
28
+ type OcMotion = 'on' | 'off';
27
29
  interface OcSkinContextValue {
28
30
  skin: string;
29
31
  setSkin: (id: string) => void;
30
32
  themes: readonly OcTheme[];
33
+ motion: OcMotion;
34
+ setMotion: (value: OcMotion) => void;
31
35
  }
32
36
  interface OcThemeProviderProps {
33
37
  children: ReactNode;
@@ -38,6 +42,10 @@ interface OcThemeProviderProps {
38
42
  }
39
43
  declare function OcThemeProvider({ children, defaultSkin, aurora, }: OcThemeProviderProps): react_jsx_runtime.JSX.Element;
40
44
  declare function useOcSkin(): OcSkinContextValue;
45
+ declare function useOcMotion(): {
46
+ motion: OcMotion;
47
+ setMotion: (value: OcMotion) => void;
48
+ };
41
49
  declare function getOcThemeInitScript(defaultSkin?: string): string;
42
50
 
43
51
  declare function OcThemeBridge(): null;
@@ -65,4 +73,4 @@ interface OcAuroraProps {
65
73
  }
66
74
  declare function OcAurora({ intensity, className }: OcAuroraProps): react_jsx_runtime.JSX.Element;
67
75
 
68
- export { AppearanceControls, DEFAULT_OC_THEME, OC_DEFAULT_ACCENT, OC_SKIN_COOKIE, OC_THEMES, OcAppearanceMenu, type OcAppearanceMenuProps, OcAurora, type OcAuroraProps, type OcTheme, OcThemeBridge, type OcThemeId, OcThemePicker, type OcThemePickerProps, OcThemeProvider, type OcThemeProviderProps, accentFor, cn, getOcThemeInitScript, isKnownTheme, resolveTheme, useOcSkin };
76
+ export { AppearanceControls, DEFAULT_OC_THEME, OC_DEFAULT_ACCENT, OC_MOTION_COOKIE, OC_SKIN_COOKIE, OC_THEMES, OcAppearanceMenu, type OcAppearanceMenuProps, OcAurora, type OcAuroraProps, type OcMotion, type OcTheme, OcThemeBridge, type OcThemeId, OcThemePicker, type OcThemePickerProps, OcThemeProvider, type OcThemeProviderProps, accentFor, cn, getOcThemeInitScript, isKnownTheme, resolveTheme, useOcMotion, useOcSkin };
package/dist/tokens.d.ts CHANGED
@@ -18,16 +18,20 @@ type OcThemeId = (typeof OC_THEMES)[number]['id'] | (string & {});
18
18
  declare function isKnownTheme(id: string | null | undefined): id is OcThemeId;
19
19
  declare function resolveTheme(id: string | null | undefined): string;
20
20
  declare const OC_SKIN_COOKIE = "oc_skin";
21
+ declare const OC_MOTION_COOKIE = "oc_motion";
21
22
 
22
23
  declare global {
23
24
  interface Window {
24
25
  __ocApplySkinChrome?: (skin: string) => void;
25
26
  }
26
27
  }
28
+ type OcMotion = 'on' | 'off';
27
29
  interface OcSkinContextValue {
28
30
  skin: string;
29
31
  setSkin: (id: string) => void;
30
32
  themes: readonly OcTheme[];
33
+ motion: OcMotion;
34
+ setMotion: (value: OcMotion) => void;
31
35
  }
32
36
  interface OcThemeProviderProps {
33
37
  children: ReactNode;
@@ -38,6 +42,10 @@ interface OcThemeProviderProps {
38
42
  }
39
43
  declare function OcThemeProvider({ children, defaultSkin, aurora, }: OcThemeProviderProps): react_jsx_runtime.JSX.Element;
40
44
  declare function useOcSkin(): OcSkinContextValue;
45
+ declare function useOcMotion(): {
46
+ motion: OcMotion;
47
+ setMotion: (value: OcMotion) => void;
48
+ };
41
49
  declare function getOcThemeInitScript(defaultSkin?: string): string;
42
50
 
43
51
  declare function OcThemeBridge(): null;
@@ -65,4 +73,4 @@ interface OcAuroraProps {
65
73
  }
66
74
  declare function OcAurora({ intensity, className }: OcAuroraProps): react_jsx_runtime.JSX.Element;
67
75
 
68
- export { AppearanceControls, DEFAULT_OC_THEME, OC_DEFAULT_ACCENT, OC_SKIN_COOKIE, OC_THEMES, OcAppearanceMenu, type OcAppearanceMenuProps, OcAurora, type OcAuroraProps, type OcTheme, OcThemeBridge, type OcThemeId, OcThemePicker, type OcThemePickerProps, OcThemeProvider, type OcThemeProviderProps, accentFor, cn, getOcThemeInitScript, isKnownTheme, resolveTheme, useOcSkin };
76
+ export { AppearanceControls, DEFAULT_OC_THEME, OC_DEFAULT_ACCENT, OC_MOTION_COOKIE, OC_SKIN_COOKIE, OC_THEMES, OcAppearanceMenu, type OcAppearanceMenuProps, OcAurora, type OcAuroraProps, type OcMotion, type OcTheme, OcThemeBridge, type OcThemeId, OcThemePicker, type OcThemePickerProps, OcThemeProvider, type OcThemeProviderProps, accentFor, cn, getOcThemeInitScript, isKnownTheme, resolveTheme, useOcMotion, useOcSkin };
package/dist/tokens.js CHANGED
@@ -57,13 +57,18 @@ function resolveTheme(id) {
57
57
  return isKnownTheme(id) ? id : DEFAULT_OC_THEME;
58
58
  }
59
59
  var OC_SKIN_COOKIE = "oc_skin";
60
+ var OC_MOTION_COOKIE = "oc_motion";
60
61
  var BLOBS = [1, 2, 3, 4, 5];
61
62
  function OcAurora({ intensity, className }) {
62
63
  const style = intensity == null ? void 0 : { "--oc-aurora-intensity": String(intensity) };
63
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("oc-aurora", className), style, "aria-hidden": "true", children: BLOBS.map((n) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `oc-aurora__blob oc-aurora__blob-${n}` }, n)) });
64
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("oc-aurora", className), style, "aria-hidden": "true", children: [
65
+ BLOBS.map((n) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `oc-aurora__blob oc-aurora__blob-${n}` }, n)),
66
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "oc-aurora__grain" })
67
+ ] });
64
68
  }
65
69
  var ONE_YEAR = 60 * 60 * 24 * 365;
66
70
  var ATTR = "data-oc-theme";
71
+ var MOTION_ATTR = "data-oc-motion";
67
72
  function readSkinCookie() {
68
73
  if (typeof document === "undefined") return null;
69
74
  const prefix = `${OC_SKIN_COOKIE}=`;
@@ -95,6 +100,38 @@ function applyAttr(skin) {
95
100
  if (typeof document === "undefined") return;
96
101
  document.documentElement.setAttribute(ATTR, skin);
97
102
  }
103
+ function readMotionCookie() {
104
+ if (typeof document === "undefined") return null;
105
+ const prefix = `${OC_MOTION_COOKIE}=`;
106
+ for (const part of document.cookie.split(";")) {
107
+ const trimmed = part.trim();
108
+ if (trimmed.startsWith(prefix)) {
109
+ const v = decodeURIComponent(trimmed.slice(prefix.length));
110
+ return v === "off" ? "off" : v === "on" ? "on" : null;
111
+ }
112
+ }
113
+ return null;
114
+ }
115
+ function writeMotionCookie(value) {
116
+ if (typeof document === "undefined") return;
117
+ const isLocal = location.hostname === "localhost" || location.hostname === "127.0.0.1";
118
+ const parts = [
119
+ `${OC_MOTION_COOKIE}=${encodeURIComponent(value)}`,
120
+ "Path=/",
121
+ `Max-Age=${ONE_YEAR}`,
122
+ "SameSite=Lax"
123
+ ];
124
+ if (!isLocal) {
125
+ parts.push("Domain=.ochk.io");
126
+ parts.push("Secure");
127
+ }
128
+ document.cookie = parts.join("; ");
129
+ }
130
+ function applyMotionAttr(motion) {
131
+ if (typeof document === "undefined") return;
132
+ if (motion === "off") document.documentElement.setAttribute(MOTION_ATTR, "off");
133
+ else document.documentElement.removeAttribute(MOTION_ATTR);
134
+ }
98
135
  function applySkinChrome(skin) {
99
136
  if (typeof window === "undefined") return;
100
137
  if (typeof window.__ocApplySkinChrome === "function") {
@@ -111,6 +148,7 @@ function OcThemeProvider({
111
148
  aurora = true
112
149
  }) {
113
150
  const [skin, setSkinState] = react.useState(() => resolveTheme(defaultSkin));
151
+ const [motion, setMotionState] = react.useState("on");
114
152
  const hydratedRef = react.useRef(false);
115
153
  react.useEffect(() => {
116
154
  if (hydratedRef.current) return;
@@ -119,6 +157,9 @@ function OcThemeProvider({
119
157
  applyAttr(fromCookie);
120
158
  applySkinChrome(fromCookie);
121
159
  setSkinState(fromCookie);
160
+ const motionCookie = readMotionCookie() ?? "on";
161
+ applyMotionAttr(motionCookie);
162
+ setMotionState(motionCookie);
122
163
  }, [defaultSkin]);
123
164
  react.useEffect(() => {
124
165
  function sync() {
@@ -128,6 +169,11 @@ function OcThemeProvider({
128
169
  applySkinChrome(fromCookie);
129
170
  setSkinState(fromCookie);
130
171
  }
172
+ const motionCookie = readMotionCookie() ?? "on";
173
+ if (motionCookie !== motion) {
174
+ applyMotionAttr(motionCookie);
175
+ setMotionState(motionCookie);
176
+ }
131
177
  }
132
178
  window.addEventListener("focus", sync);
133
179
  document.addEventListener("visibilitychange", sync);
@@ -135,7 +181,7 @@ function OcThemeProvider({
135
181
  window.removeEventListener("focus", sync);
136
182
  document.removeEventListener("visibilitychange", sync);
137
183
  };
138
- }, [skin]);
184
+ }, [skin, motion]);
139
185
  const setSkin = react.useCallback((id) => {
140
186
  const next = resolveTheme(id);
141
187
  applyAttr(next);
@@ -143,9 +189,15 @@ function OcThemeProvider({
143
189
  writeSkinCookie(next);
144
190
  setSkinState(next);
145
191
  }, []);
192
+ const setMotion = react.useCallback((value2) => {
193
+ const next = value2 === "off" ? "off" : "on";
194
+ applyMotionAttr(next);
195
+ writeMotionCookie(next);
196
+ setMotionState(next);
197
+ }, []);
146
198
  const value = react.useMemo(
147
- () => ({ skin, setSkin, themes: OC_THEMES }),
148
- [skin, setSkin]
199
+ () => ({ skin, setSkin, themes: OC_THEMES, motion, setMotion }),
200
+ [skin, setSkin, motion, setMotion]
149
201
  );
150
202
  return /* @__PURE__ */ jsxRuntime.jsxs(OcSkinContext.Provider, { value, children: [
151
203
  aurora !== false && /* @__PURE__ */ jsxRuntime.jsx(OcAurora, { intensity: typeof aurora === "object" ? aurora.intensity : void 0 }),
@@ -159,9 +211,13 @@ function useOcSkin() {
159
211
  }
160
212
  return ctx;
161
213
  }
214
+ function useOcMotion() {
215
+ const { motion, setMotion } = useOcSkin();
216
+ return { motion, setMotion };
217
+ }
162
218
  function getOcThemeInitScript(defaultSkin = DEFAULT_OC_THEME) {
163
219
  const accents = Object.fromEntries(OC_THEMES.map((t) => [t.id, t.accent]));
164
- return `(function(){var ACC=${JSON.stringify(accents)},DEF=${JSON.stringify(defaultSkin)},ORIG=${JSON.stringify(OC_DEFAULT_ACCENT)},fav=null;function acc(s){return ACC[s]||ACC[DEF]||ORIG;}window.__ocApplySkinChrome=function(s){try{var a=acc(s);var meta=document.querySelector('meta[name="theme-color"]');if(meta){meta.setAttribute('content',a);}var link=document.querySelector('link[rel~="icon"][type="image/svg+xml"]');if(!link){return;}var paint=function(svg){link.setAttribute('href','data:image/svg+xml,'+encodeURIComponent(svg.split(ORIG).join(a)));};if(fav!=null){paint(fav);return;}var h=link.getAttribute('href');if(!h||h.indexOf('data:')===0){return;}fetch(h).then(function(r){return r.text();}).then(function(svg){fav=svg;paint(svg);}).catch(function(){});}catch(e){}};try{var m=document.cookie.match(/(?:^|; )${OC_SKIN_COOKIE}=([^;]*)/);var s=m?decodeURIComponent(m[1]):DEF;if(!s){s=DEF;}document.documentElement.setAttribute('${ATTR}',s);window.__ocApplySkinChrome(s);}catch(e){document.documentElement.setAttribute('${ATTR}',DEF);}})();`;
220
+ return `(function(){var ACC=${JSON.stringify(accents)},DEF=${JSON.stringify(defaultSkin)},ORIG=${JSON.stringify(OC_DEFAULT_ACCENT)},fav=null;function acc(s){return ACC[s]||ACC[DEF]||ORIG;}window.__ocApplySkinChrome=function(s){try{var a=acc(s);var meta=document.querySelector('meta[name="theme-color"]');if(meta){meta.setAttribute('content',a);}var link=document.querySelector('link[rel~="icon"][type="image/svg+xml"]');if(!link){return;}var paint=function(svg){link.setAttribute('href','data:image/svg+xml,'+encodeURIComponent(svg.split(ORIG).join(a)));};if(fav!=null){paint(fav);return;}var h=link.getAttribute('href');if(!h||h.indexOf('data:')===0){return;}fetch(h).then(function(r){return r.text();}).then(function(svg){fav=svg;paint(svg);}).catch(function(){});}catch(e){}};try{var m=document.cookie.match(/(?:^|; )${OC_SKIN_COOKIE}=([^;]*)/);var s=m?decodeURIComponent(m[1]):DEF;if(!s){s=DEF;}document.documentElement.setAttribute('${ATTR}',s);window.__ocApplySkinChrome(s);}catch(e){document.documentElement.setAttribute('${ATTR}',DEF);}try{var mm=document.cookie.match(/(?:^|; )${OC_MOTION_COOKIE}=([^;]*)/);if(mm&&decodeURIComponent(mm[1])==='off'){document.documentElement.setAttribute('${MOTION_ATTR}','off');}}catch(e){}})();`;
165
221
  }
166
222
  var COOKIE = "oc_theme";
167
223
  var ALLOWED = /* @__PURE__ */ new Set(["light", "dark", "system"]);
@@ -296,10 +352,12 @@ var MODES = [
296
352
  ];
297
353
  function AppearanceControls({ className }) {
298
354
  const { skin, setSkin, themes } = useOcSkin();
355
+ const { motion, setMotion } = useOcMotion();
299
356
  const { theme, setTheme } = nextThemes.useTheme();
300
357
  const [mounted, setMounted] = react.useState(false);
301
358
  react.useEffect(() => setMounted(true), []);
302
359
  const activeMode = mounted ? theme ?? "system" : null;
360
+ const activeMotion = mounted ? motion : null;
303
361
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
304
362
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-muted-foreground px-3 pt-3 pb-2", children: "mode" }),
305
363
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-1 px-2 pb-2", children: MODES.map(({ id, label, Icon }) => {
@@ -346,6 +404,32 @@ function AppearanceControls({ className }) {
346
404
  ]
347
405
  }
348
406
  ) }, t.id);
407
+ }) }),
408
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-muted-foreground border-t px-3 pt-3 pb-2", children: "ambient motion" }),
409
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-1 px-2 pb-3", children: [
410
+ { id: "on", label: "on", Icon: lucideReact.Waves },
411
+ { id: "off", label: "off", Icon: lucideReact.Pause }
412
+ ].map(({ id, label, Icon }) => {
413
+ const active = activeMotion === id;
414
+ return /* @__PURE__ */ jsxRuntime.jsxs(
415
+ "button",
416
+ {
417
+ type: "button",
418
+ role: "menuitemradio",
419
+ "aria-checked": active,
420
+ "aria-label": id === "off" ? "pause ambient motion" : "ambient motion on",
421
+ onClick: () => setMotion(id),
422
+ className: cn(
423
+ "flex flex-col items-center gap-1 rounded-md border py-2 text-[11px] transition-colors",
424
+ active ? "border-primary text-foreground bg-accent" : "border-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground"
425
+ ),
426
+ children: [
427
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-4", "aria-hidden": true }),
428
+ label
429
+ ]
430
+ },
431
+ id
432
+ );
349
433
  }) })
350
434
  ] });
351
435
  }
@@ -405,6 +489,7 @@ function OcAppearanceMenu({
405
489
  exports.AppearanceControls = AppearanceControls;
406
490
  exports.DEFAULT_OC_THEME = DEFAULT_OC_THEME;
407
491
  exports.OC_DEFAULT_ACCENT = OC_DEFAULT_ACCENT;
492
+ exports.OC_MOTION_COOKIE = OC_MOTION_COOKIE;
408
493
  exports.OC_SKIN_COOKIE = OC_SKIN_COOKIE;
409
494
  exports.OC_THEMES = OC_THEMES;
410
495
  exports.OcAppearanceMenu = OcAppearanceMenu;
@@ -417,6 +502,7 @@ exports.cn = cn;
417
502
  exports.getOcThemeInitScript = getOcThemeInitScript;
418
503
  exports.isKnownTheme = isKnownTheme;
419
504
  exports.resolveTheme = resolveTheme;
505
+ exports.useOcMotion = useOcMotion;
420
506
  exports.useOcSkin = useOcSkin;
421
507
  //# sourceMappingURL=tokens.js.map
422
508
  //# sourceMappingURL=tokens.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tokens/cn.ts","../src/tokens/themes.ts","../src/tokens/aurora.tsx","../src/tokens/provider.tsx","../src/tokens/theme-bridge.tsx","../src/tokens/theme-picker.tsx","../src/tokens/appearance-menu.tsx"],"names":["twMerge","clsx","jsx","createContext","useState","useRef","useEffect","useCallback","useMemo","jsxs","useContext","ONE_YEAR","useTheme","Palette","Check","Sun","Moon","Monitor"],"mappings":"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","file":"tokens.js","sourcesContent":["import type { ClassValue } from 'clsx';\n\nimport { clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Canonical class-name merge for the OrangeCheck family.\n * `clsx` for conditional composition, `tailwind-merge` to resolve\n * conflicting Tailwind utilities (last-wins by property).\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * The OrangeCheck theme (skin) registry.\n *\n * A *skin* is the named-theme axis, orthogonal to the light/dark *mode* axis\n * (which stays owned by `next-themes` via the `.dark` class). A skin is applied\n * as `data-oc-theme=\"<id>\"` on `<html>` and persisted in the `oc_skin` cookie at\n * `Domain=.ochk.io` so a choice on one family site carries to every other.\n *\n * Adding a skin = add a `themes/<id>.css` token block in this package and a\n * row here. Every site picks it up on the next `@orangecheck/design` bump; no\n * per-site edits.\n */\nexport interface OcTheme {\n /** Stable id — also the `data-oc-theme` attribute value and the CSS file stem. */\n readonly id: string;\n /** Human label for the picker (lowercase, house voice). */\n readonly label: string;\n /** One-line description shown in the picker / Storybook. */\n readonly description: string;\n /**\n * Accent hex (sRGB of the skin's dark-mode `--brand`). Used to swap the\n * browser chrome — `<meta name=\"theme-color\">` and the favicon (recolored\n * from the family `#f97316`) — when the skin changes. Mirrors the\n * `SKINS` palette in `oc-media-kit/build/brands.py` (same source of truth).\n */\n readonly accent: string;\n}\n\n// ember leads — the warm, human default. The other four are the Bitcoin-ethos\n// alternates (sharp, flat, cypherpunk), each carrying a meaning, not just a\n// colour: the chain, the node, the network, sound money. Order here is the\n// order shown in the appearance menu / picker (ember first).\nexport const OC_THEMES: readonly OcTheme[] = [\n {\n id: 'ember',\n label: 'ember',\n description:\n 'the warmth — burnt-sienna terracotta, soft 1rem corners, pill buttons, Hanken Grotesk · approachable, human',\n accent: '#da6736',\n },\n {\n id: 'orangecheck',\n label: 'orangecheck',\n description: 'the chain — Bitcoin orange, sharp 0.25rem corners, Inter + JetBrains Mono',\n accent: '#f97316',\n },\n {\n id: 'phosphor',\n label: 'phosphor',\n description: 'the node — CRT terminal green, hard 0.125rem, all-mono · sovereignty & verify',\n accent: '#55d671',\n },\n {\n id: 'lightning',\n label: 'lightning',\n description: 'the network — electric violet (L2), hardest 0rem edges, sans · instant',\n accent: '#c27dff',\n },\n {\n id: 'gold',\n label: 'gold',\n description: 'sound money — digital gold, hard 0.125rem milled edge, mono ledger · 21M',\n accent: '#e3b831',\n },\n] as const;\n\n/** The family default accent (orangecheck), and the hex every favicon ships\n * with — the swap recolors from this to the active skin's accent. */\nexport const OC_DEFAULT_ACCENT = '#f97316';\n\n/** Accent hex for a skin id, falling back to the default. */\nexport function accentFor(id: string | null | undefined): string {\n return OC_THEMES.find((t) => t.id === id)?.accent ?? OC_DEFAULT_ACCENT;\n}\n\n// ember is the family default — the skin a user with no `oc_skin` cookie gets.\n// (The favicon SVGs still ship baked with OC_DEFAULT_ACCENT below; the init\n// script recolors them from that to the active skin's accent on load.)\nexport const DEFAULT_OC_THEME = 'ember';\n\nexport type OcThemeId = (typeof OC_THEMES)[number]['id'] | (string & {});\n\nexport function isKnownTheme(id: string | null | undefined): id is OcThemeId {\n return !!id && OC_THEMES.some((t) => t.id === id);\n}\n\nexport function resolveTheme(id: string | null | undefined): string {\n return isKnownTheme(id) ? id : DEFAULT_OC_THEME;\n}\n\n/** Cookie name for the cross-subdomain skin choice. */\nexport const OC_SKIN_COOKIE = 'oc_skin';\n","import type { CSSProperties } from 'react';\n\nimport { cn } from './cn';\n\nexport interface OcAuroraProps {\n /**\n * Master intensity multiplier (default 1, from the theme CSS). Overrides\n * `--oc-aurora-intensity` for this mount — e.g. dial a reading-heavy site down.\n */\n intensity?: number;\n className?: string;\n}\n\nconst BLOBS = [1, 2, 3, 4, 5] as const;\n\n/**\n * The ambient \"bitcoin aurora\" background — soft, theme-reactive colour clouds\n * that slowly wander (styling in styles/aurora.css; recolours from --brand /\n * --success / --info / --primary across mode + skin). Pure markup, fixed behind\n * all content; `OcThemeProvider` mounts it by default. Mount manually only if a\n * site renders the aurora outside the provider.\n */\nexport function OcAurora({ intensity, className }: OcAuroraProps) {\n const style =\n intensity == null\n ? undefined\n : ({ '--oc-aurora-intensity': String(intensity) } as CSSProperties);\n return (\n <div className={cn('oc-aurora', className)} style={style} aria-hidden=\"true\">\n {BLOBS.map((n) => (\n <div key={n} className={`oc-aurora__blob oc-aurora__blob-${n}`} />\n ))}\n </div>\n );\n}\n","'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport {\n accentFor,\n DEFAULT_OC_THEME,\n OC_DEFAULT_ACCENT,\n OC_SKIN_COOKIE,\n OC_THEMES,\n resolveTheme,\n type OcTheme,\n} from './themes';\nimport { OcAurora } from './aurora';\n\ndeclare global {\n interface Window {\n /** Defined by `getOcThemeInitScript()`; recolors favicon + theme-color. */\n __ocApplySkinChrome?: (skin: string) => void;\n }\n}\n\n/**\n * OcThemeProvider — the skin (named-theme) axis.\n *\n * Orthogonal to `next-themes`, which owns light/dark via the `.dark` class.\n * This provider owns the `data-oc-theme` attribute on `<html>` and persists the\n * choice in the `oc_skin` cookie at `Domain=.ochk.io`, so a skin chosen on one\n * `*.ochk.io` site is honored on every other. It re-reads the cookie on focus /\n * visibility change so a fresh choice picks up when the user returns to a tab\n * (same cross-site pickup trick `OcAccountMenu` uses for sign-in).\n *\n * Mount once, inside (or beside) the `next-themes` `<ThemeProvider>`:\n *\n * <ThemeProvider attribute=\"class\" defaultTheme=\"system\" enableSystem>\n * <OcThemeProvider>\n * …app…\n * </OcThemeProvider>\n * </ThemeProvider>\n *\n * Pair with `getOcThemeInitScript()` in `_document` to avoid a flash before\n * hydration.\n */\n\nconst ONE_YEAR = 60 * 60 * 24 * 365;\nconst ATTR = 'data-oc-theme';\n\nfunction readSkinCookie(): string | null {\n if (typeof document === 'undefined') return null;\n const prefix = `${OC_SKIN_COOKIE}=`;\n for (const part of document.cookie.split(';')) {\n const trimmed = part.trim();\n if (trimmed.startsWith(prefix)) {\n const v = decodeURIComponent(trimmed.slice(prefix.length));\n return v.length > 0 ? v : null;\n }\n }\n return null;\n}\n\nfunction writeSkinCookie(value: string): void {\n if (typeof document === 'undefined') return;\n const isLocal =\n location.hostname === 'localhost' || location.hostname === '127.0.0.1';\n const parts = [\n `${OC_SKIN_COOKIE}=${encodeURIComponent(value)}`,\n 'Path=/',\n `Max-Age=${ONE_YEAR}`,\n 'SameSite=Lax',\n ];\n if (!isLocal) {\n parts.push('Domain=.ochk.io');\n parts.push('Secure');\n }\n document.cookie = parts.join('; ');\n}\n\nfunction applyAttr(skin: string): void {\n if (typeof document === 'undefined') return;\n document.documentElement.setAttribute(ATTR, skin);\n}\n\n/**\n * Swap the browser chrome (favicon + `<meta name=\"theme-color\">`) to the skin's\n * accent. The real work lives in the global installed by\n * `getOcThemeInitScript()` (so the favicon's original SVG is captured exactly\n * once, before the init script's own first recolor — avoids re-reading an\n * already-swapped data: URI). If the init script wasn't included, fall back to\n * the theme-color swap alone (favicon recolor needs the captured original).\n */\nfunction applySkinChrome(skin: string): void {\n if (typeof window === 'undefined') return;\n if (typeof window.__ocApplySkinChrome === 'function') {\n window.__ocApplySkinChrome(skin);\n return;\n }\n const meta = document.querySelector('meta[name=\"theme-color\"]');\n if (meta) meta.setAttribute('content', accentFor(skin));\n}\n\ninterface OcSkinContextValue {\n /** Current skin id (always resolved to a known theme). */\n skin: string;\n /** Set the skin: validates, applies the attribute, persists the cookie. */\n setSkin: (id: string) => void;\n /** The full registry, for rendering a picker. */\n themes: readonly OcTheme[];\n}\n\nconst OcSkinContext = createContext<OcSkinContextValue | null>(null);\n\nexport interface OcThemeProviderProps {\n children: ReactNode;\n /** Skin to assume before the cookie is read (defaults to `orangecheck`). */\n defaultSkin?: string;\n /**\n * The ambient bitcoin-aurora background. `true` (default) renders it behind\n * the app; `false` disables it; `{ intensity }` tunes its strength for this\n * site (e.g. `aurora={{ intensity: 0.5 }}` on a reading-heavy surface).\n */\n aurora?: boolean | { intensity?: number };\n}\n\nexport function OcThemeProvider({\n children,\n defaultSkin = DEFAULT_OC_THEME,\n aurora = true,\n}: OcThemeProviderProps) {\n const [skin, setSkinState] = useState<string>(() => resolveTheme(defaultSkin));\n const hydratedRef = useRef(false);\n\n // Hydrate from the cookie once on mount and align the attribute.\n useEffect(() => {\n if (hydratedRef.current) return;\n hydratedRef.current = true;\n const fromCookie = resolveTheme(readSkinCookie() ?? defaultSkin);\n applyAttr(fromCookie);\n applySkinChrome(fromCookie);\n setSkinState(fromCookie);\n }, [defaultSkin]);\n\n // Cross-site pickup: re-read the cookie when the tab regains focus.\n useEffect(() => {\n function sync() {\n const fromCookie = resolveTheme(readSkinCookie() ?? skin);\n if (fromCookie !== skin) {\n applyAttr(fromCookie);\n applySkinChrome(fromCookie);\n setSkinState(fromCookie);\n }\n }\n window.addEventListener('focus', sync);\n document.addEventListener('visibilitychange', sync);\n return () => {\n window.removeEventListener('focus', sync);\n document.removeEventListener('visibilitychange', sync);\n };\n }, [skin]);\n\n const setSkin = useCallback((id: string) => {\n const next = resolveTheme(id);\n applyAttr(next);\n applySkinChrome(next);\n writeSkinCookie(next);\n setSkinState(next);\n }, []);\n\n const value = useMemo<OcSkinContextValue>(\n () => ({ skin, setSkin, themes: OC_THEMES }),\n [skin, setSkin]\n );\n\n return (\n <OcSkinContext.Provider value={value}>\n {aurora !== false && (\n <OcAurora intensity={typeof aurora === 'object' ? aurora.intensity : undefined} />\n )}\n {children}\n </OcSkinContext.Provider>\n );\n}\n\n/** Read the current skin + setter. Throws if used outside `OcThemeProvider`. */\nexport function useOcSkin(): OcSkinContextValue {\n const ctx = useContext(OcSkinContext);\n if (!ctx) {\n throw new Error('useOcSkin must be used within <OcThemeProvider>');\n }\n return ctx;\n}\n\n/**\n * Blocking init script for `_document` (Pages Router) `<Head>`. Applies the\n * cookie's skin to `<html>` before first paint so there is no flash of the\n * default skin. Inject with:\n *\n * <script dangerouslySetInnerHTML={{ __html: getOcThemeInitScript() }} />\n */\nexport function getOcThemeInitScript(defaultSkin: string = DEFAULT_OC_THEME): string {\n // Self-contained IIFE — no imports available at parse time. Beyond applying\n // the skin attribute before first paint, it installs `window.__ocApplySkinChrome`\n // (the single owner of the favicon + theme-color swap) and runs it for the\n // saved skin. OcThemeProvider re-invokes the same global on later changes, so\n // the favicon's *original* SVG is captured exactly once (before any recolor)\n // and re-recolored from `#f97316` to the active skin's accent. The favicon\n // recolor is async (a fetch of the same-origin favicon.svg) — chrome updates\n // a beat after paint, which is fine; the skin attribute itself is synchronous.\n const accents = Object.fromEntries(OC_THEMES.map((t) => [t.id, t.accent]));\n return (\n `(function(){` +\n `var ACC=${JSON.stringify(accents)},DEF=${JSON.stringify(defaultSkin)},ORIG=${JSON.stringify(OC_DEFAULT_ACCENT)},fav=null;` +\n `function acc(s){return ACC[s]||ACC[DEF]||ORIG;}` +\n `window.__ocApplySkinChrome=function(s){try{` +\n `var a=acc(s);` +\n `var meta=document.querySelector('meta[name=\"theme-color\"]');if(meta){meta.setAttribute('content',a);}` +\n `var link=document.querySelector('link[rel~=\"icon\"][type=\"image/svg+xml\"]');if(!link){return;}` +\n `var paint=function(svg){link.setAttribute('href','data:image/svg+xml,'+encodeURIComponent(svg.split(ORIG).join(a)));};` +\n `if(fav!=null){paint(fav);return;}` +\n `var h=link.getAttribute('href');if(!h||h.indexOf('data:')===0){return;}` +\n `fetch(h).then(function(r){return r.text();}).then(function(svg){fav=svg;paint(svg);}).catch(function(){});` +\n `}catch(e){}};` +\n `try{var m=document.cookie.match(/(?:^|; )${OC_SKIN_COOKIE}=([^;]*)/);var s=m?decodeURIComponent(m[1]):DEF;if(!s){s=DEF;}` +\n `document.documentElement.setAttribute('${ATTR}',s);window.__ocApplySkinChrome(s);}` +\n `catch(e){document.documentElement.setAttribute('${ATTR}',DEF);}` +\n `})();`\n );\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useTheme } from 'next-themes';\n\n/**\n * OcThemeBridge — cross-subdomain persistence for the MODE axis (light/dark).\n *\n * `next-themes` defaults to origin-scoped `localStorage`, so a dark/light choice\n * on one `*.ochk.io` site won't carry to another. This layers an\n * `oc_theme` cookie at `Domain=.ochk.io` on top so the choice is visible\n * family-wide. (The SKIN axis has its own `oc_skin` bridge inside\n * `OcThemeProvider`; this is the mode counterpart, previously duplicated in\n * every consumer repo.)\n *\n * Mount once inside the next-themes `<ThemeProvider>`:\n *\n * <ThemeProvider attribute=\"class\" defaultTheme=\"system\" enableSystem>\n * <OcThemeBridge />\n * <OcThemeProvider>…</OcThemeProvider>\n * </ThemeProvider>\n *\n * The cookie is intentionally non-HttpOnly (next-themes JS reads/writes it) and\n * carries no auth value — a leak only reveals a theme preference.\n */\nconst COOKIE = 'oc_theme';\nconst ALLOWED = new Set(['light', 'dark', 'system']);\nconst ONE_YEAR = 60 * 60 * 24 * 365;\n\nfunction readCookie(name: string): string | null {\n if (typeof document === 'undefined') return null;\n const prefix = `${name}=`;\n for (const part of document.cookie.split(';')) {\n const trimmed = part.trim();\n if (trimmed.startsWith(prefix)) {\n const v = decodeURIComponent(trimmed.slice(prefix.length));\n return v.length > 0 ? v : null;\n }\n }\n return null;\n}\n\nfunction writeCookie(value: string): void {\n if (typeof document === 'undefined') return;\n if (!ALLOWED.has(value)) return;\n const isLocal = location.hostname === 'localhost' || location.hostname === '127.0.0.1';\n const parts = [\n `${COOKIE}=${encodeURIComponent(value)}`,\n 'Path=/',\n `Max-Age=${ONE_YEAR}`,\n 'SameSite=Lax',\n ];\n if (!isLocal) {\n parts.push('Domain=.ochk.io');\n parts.push('Secure');\n }\n document.cookie = parts.join('; ');\n}\n\nexport function OcThemeBridge() {\n const { theme, setTheme } = useTheme();\n const hydratedRef = useRef(false);\n\n useEffect(() => {\n if (hydratedRef.current) return;\n hydratedRef.current = true;\n const cookieValue = readCookie(COOKIE);\n if (cookieValue && ALLOWED.has(cookieValue) && cookieValue !== theme) {\n setTheme(cookieValue);\n }\n }, [theme, setTheme]);\n\n useEffect(() => {\n if (!hydratedRef.current) return;\n if (!theme) return;\n writeCookie(theme);\n }, [theme]);\n\n return null;\n}\n","'use client';\n\nimport { Check, Palette } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { cn } from './cn';\nimport { useOcSkin } from './provider';\n\n/**\n * OcThemePicker — the skin selector. Sits beside `ThemeToggle` in the header.\n * Self-contained dropdown (no Radix): outside-click + Escape to close. Mirrors\n * the ghost-icon affordance of `ThemeToggle`. Gate its mount behind\n * `NEXT_PUBLIC_OC_THEME_PICKER` during staged rollout.\n */\nexport interface OcThemePickerProps {\n className?: string;\n triggerClassName?: string;\n popoverClassName?: string;\n}\n\nexport function OcThemePicker({ className, triggerClassName, popoverClassName }: OcThemePickerProps) {\n const { skin, setSkin, themes } = useOcSkin();\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n function onDown(e: MouseEvent) {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDown);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDown);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn('relative', className)}>\n <button\n type=\"button\"\n aria-label=\"choose theme\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n title=\"choose theme\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'text-muted-foreground hover:text-foreground inline-flex size-9 items-center justify-center rounded-md transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n triggerClassName\n )}\n >\n <Palette className=\"size-4\" aria-hidden />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n className={cn(\n 'bg-popover text-popover-foreground absolute right-0 z-50 mt-2 w-64 overflow-hidden rounded-md border shadow-md',\n popoverClassName\n )}\n >\n <div className=\"label-mono text-muted-foreground px-3 pt-3 pb-1\">theme</div>\n <ul className=\"pb-1\">\n {themes.map((t) => {\n const active = t.id === skin;\n return (\n <li key={t.id}>\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n onClick={() => {\n setSkin(t.id);\n setOpen(false);\n }}\n className={cn(\n 'hover:bg-accent hover:text-accent-foreground flex w-full items-start gap-2 px-3 py-2 text-left transition-colors',\n active && 'text-foreground'\n )}\n >\n <span className=\"mt-0.5 size-4 shrink-0\">\n {active && <Check className=\"size-4 text-primary\" aria-hidden />}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-medium\">{t.label}</span>\n <span className=\"text-muted-foreground block text-xs leading-snug\">\n {t.description}\n </span>\n </span>\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { Check, Monitor, Moon, Palette, Sun } from 'lucide-react';\nimport { useTheme } from 'next-themes';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { cn } from './cn';\nimport { useOcSkin } from './provider';\n\n/**\n * OcAppearanceMenu — the single header control for ALL appearance settings.\n *\n * One icon button opens a dropdown with both axes:\n * • mode — light / dark / system (next-themes `.dark` class)\n * • theme — the registered skins (data-oc-theme, persisted .ochk.io)\n *\n * Replaces the separate `ThemeToggle` + `OcThemePicker` so every family site\n * carries exactly one appearance control. Self-contained dropdown (no Radix):\n * outside-click + Escape to close. Requires `<OcThemeProvider>` above it (skin\n * axis) and a next-themes `<ThemeProvider>` (mode axis) — both already mounted\n * on every family site.\n */\nexport interface OcAppearanceMenuProps {\n className?: string;\n triggerClassName?: string;\n popoverClassName?: string;\n}\n\nconst MODES = [\n { id: 'light', label: 'light', Icon: Sun },\n { id: 'dark', label: 'dark', Icon: Moon },\n { id: 'system', label: 'system', Icon: Monitor },\n] as const;\n\n/**\n * AppearanceControls — the mode segment + skin list, with no trigger/popover\n * chrome of its own. Embed it anywhere a surface wants to host appearance\n * settings inline (the standalone OcAppearanceMenu popover, the mobile account\n * menu, a site's Sheet drawer). Requires `<OcThemeProvider>` + next-themes\n * above it, like OcAppearanceMenu.\n */\nexport function AppearanceControls({ className }: { className?: string }) {\n const { skin, setSkin, themes } = useOcSkin();\n const { theme, setTheme } = useTheme();\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n const activeMode = mounted ? (theme ?? 'system') : null;\n\n return (\n <div className={className}>\n <div className=\"label-mono text-muted-foreground px-3 pt-3 pb-2\">mode</div>\n <div className=\"grid grid-cols-3 gap-1 px-2 pb-2\">\n {MODES.map(({ id, label, Icon }) => {\n const active = activeMode === id;\n return (\n <button\n key={id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n onClick={() => setTheme(id)}\n className={cn(\n 'flex flex-col items-center gap-1 rounded-md border py-2 text-[11px] transition-colors',\n active\n ? 'border-primary text-foreground bg-accent'\n : 'border-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground'\n )}\n >\n <Icon className=\"size-4\" aria-hidden />\n {label}\n </button>\n );\n })}\n </div>\n <div className=\"label-mono text-muted-foreground border-t px-3 pt-3 pb-1\">theme</div>\n <ul className=\"pb-1\">\n {themes.map((t) => {\n const active = t.id === skin;\n return (\n <li key={t.id}>\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n onClick={() => setSkin(t.id)}\n className={cn(\n 'hover:bg-accent hover:text-accent-foreground flex w-full items-start gap-2 px-3 py-2 text-left transition-colors',\n active && 'text-foreground'\n )}\n >\n <span className=\"mt-0.5 size-4 shrink-0\">\n {active && <Check className=\"text-primary size-4\" aria-hidden />}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-medium\">{t.label}</span>\n <span className=\"text-muted-foreground block text-xs leading-snug\">\n {t.description}\n </span>\n </span>\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\nexport function OcAppearanceMenu({\n className,\n triggerClassName,\n popoverClassName,\n}: OcAppearanceMenuProps) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n function onDown(e: MouseEvent) {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDown);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDown);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn('relative', className)}>\n <button\n type=\"button\"\n aria-label=\"appearance settings\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n title=\"appearance · mode + theme\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'text-muted-foreground hover:text-foreground inline-flex size-9 items-center justify-center rounded-md transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n triggerClassName\n )}\n >\n <Palette className=\"size-4\" aria-hidden />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n className={cn(\n 'bg-popover text-popover-foreground absolute right-0 z-50 mt-2 w-64 overflow-hidden rounded-md border shadow-md',\n popoverClassName\n )}\n >\n <AppearanceControls />\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/tokens/cn.ts","../src/tokens/themes.ts","../src/tokens/aurora.tsx","../src/tokens/provider.tsx","../src/tokens/theme-bridge.tsx","../src/tokens/theme-picker.tsx","../src/tokens/appearance-menu.tsx"],"names":["twMerge","clsx","jsxs","jsx","createContext","useState","useRef","useEffect","useCallback","value","useMemo","useContext","ONE_YEAR","useTheme","Palette","Check","Sun","Moon","Monitor","Waves","Pause"],"mappings":";;;;;;;;;;AAUO,SAAS,MAAM,MAAA,EAA8B;AAChD,EAAA,OAAOA,qBAAA,CAAQC,SAAA,CAAK,MAAM,CAAC,CAAA;AAC/B;;;ACoBO,IAAM,SAAA,GAAgC;AAAA,EACzC;AAAA,IACI,EAAA,EAAI,OAAA;AAAA,IACJ,KAAA,EAAO,OAAA;AAAA,IACP,WAAA,EACI,qHAAA;AAAA,IACJ,MAAA,EAAQ;AAAA,GACZ;AAAA,EACA;AAAA,IACI,EAAA,EAAI,aAAA;AAAA,IACJ,KAAA,EAAO,aAAA;AAAA,IACP,WAAA,EAAa,gFAAA;AAAA,IACb,MAAA,EAAQ;AAAA,GACZ;AAAA,EACA;AAAA,IACI,EAAA,EAAI,UAAA;AAAA,IACJ,KAAA,EAAO,UAAA;AAAA,IACP,WAAA,EAAa,uFAAA;AAAA,IACb,MAAA,EAAQ;AAAA,GACZ;AAAA,EACA;AAAA,IACI,EAAA,EAAI,WAAA;AAAA,IACJ,KAAA,EAAO,WAAA;AAAA,IACP,WAAA,EAAa,gFAAA;AAAA,IACb,MAAA,EAAQ;AAAA,GACZ;AAAA,EACA;AAAA,IACI,EAAA,EAAI,MAAA;AAAA,IACJ,KAAA,EAAO,MAAA;AAAA,IACP,WAAA,EAAa,kFAAA;AAAA,IACb,MAAA,EAAQ;AAAA;AAEhB;AAIO,IAAM,iBAAA,GAAoB;AAG1B,SAAS,UAAU,EAAA,EAAuC;AAC7D,EAAA,OAAO,SAAA,CAAU,KAAK,CAAC,CAAA,KAAM,EAAE,EAAA,KAAO,EAAE,GAAG,MAAA,IAAU,iBAAA;AACzD;AAKO,IAAM,gBAAA,GAAmB;AAIzB,SAAS,aAAa,EAAA,EAAgD;AACzE,EAAA,OAAO,CAAC,CAAC,EAAA,IAAM,SAAA,CAAU,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA;AACpD;AAEO,SAAS,aAAa,EAAA,EAAuC;AAChE,EAAA,OAAO,YAAA,CAAa,EAAE,CAAA,GAAI,EAAA,GAAK,gBAAA;AACnC;AAGO,IAAM,cAAA,GAAiB;AAQvB,IAAM,gBAAA,GAAmB;ACtFhC,IAAM,QAAQ,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA;AASrB,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,SAAA,EAAU,EAAkB;AAC9D,EAAA,MAAM,KAAA,GACF,aAAa,IAAA,GACP,MAAA,GACC,EAAE,uBAAA,EAAyB,MAAA,CAAO,SAAS,CAAA,EAAE;AACxD,EAAA,uBACIC,eAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,aAAa,SAAS,CAAA,EAAG,KAAA,EAAc,aAAA,EAAY,MAAA,EACjE,QAAA,EAAA;AAAA,IAAA,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,qBACRC,cAAA,CAAC,KAAA,EAAA,EAAY,WAAW,CAAA,gCAAA,EAAmC,CAAC,CAAA,CAAA,EAAA,EAAlD,CAAsD,CACnE,CAAA;AAAA,oBACDA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kBAAA,EAAmB;AAAA,GAAA,EACtC,CAAA;AAER;ACmBA,IAAM,QAAA,GAAW,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAChC,IAAM,IAAA,GAAO,eAAA;AACb,IAAM,WAAA,GAAc,gBAAA;AAKpB,SAAS,cAAA,GAAgC;AACrC,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,IAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,GAAG,cAAc,CAAA,CAAA,CAAA;AAChC,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AAC3C,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,EAAG;AAC5B,MAAA,MAAM,IAAI,kBAAA,CAAmB,OAAA,CAAQ,KAAA,CAAM,MAAA,CAAO,MAAM,CAAC,CAAA;AACzD,MAAA,OAAO,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,IAAA;AAAA,IAC9B;AAAA,EACJ;AACA,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,gBAAgB,KAAA,EAAqB;AAC1C,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACrC,EAAA,MAAM,OAAA,GACF,QAAA,CAAS,QAAA,KAAa,WAAA,IAAe,SAAS,QAAA,KAAa,WAAA;AAC/D,EAAA,MAAM,KAAA,GAAQ;AAAA,IACV,CAAA,EAAG,cAAc,CAAA,CAAA,EAAI,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAAA,IAC9C,QAAA;AAAA,IACA,WAAW,QAAQ,CAAA,CAAA;AAAA,IACnB;AAAA,GACJ;AACA,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,KAAA,CAAM,KAAK,iBAAiB,CAAA;AAC5B,IAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,EACvB;AACA,EAAA,QAAA,CAAS,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AACrC;AAEA,SAAS,UAAU,IAAA,EAAoB;AACnC,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACrC,EAAA,QAAA,CAAS,eAAA,CAAgB,YAAA,CAAa,IAAA,EAAM,IAAI,CAAA;AACpD;AAEA,SAAS,gBAAA,GAAoC;AACzC,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,IAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,GAAG,gBAAgB,CAAA,CAAA,CAAA;AAClC,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AAC3C,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,EAAG;AAC5B,MAAA,MAAM,IAAI,kBAAA,CAAmB,OAAA,CAAQ,KAAA,CAAM,MAAA,CAAO,MAAM,CAAC,CAAA;AACzD,MAAA,OAAO,CAAA,KAAM,KAAA,GAAQ,KAAA,GAAQ,CAAA,KAAM,OAAO,IAAA,GAAO,IAAA;AAAA,IACrD;AAAA,EACJ;AACA,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,kBAAkB,KAAA,EAAuB;AAC9C,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACrC,EAAA,MAAM,OAAA,GACF,QAAA,CAAS,QAAA,KAAa,WAAA,IAAe,SAAS,QAAA,KAAa,WAAA;AAC/D,EAAA,MAAM,KAAA,GAAQ;AAAA,IACV,CAAA,EAAG,gBAAgB,CAAA,CAAA,EAAI,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAAA,IAChD,QAAA;AAAA,IACA,WAAW,QAAQ,CAAA,CAAA;AAAA,IACnB;AAAA,GACJ;AACA,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,KAAA,CAAM,KAAK,iBAAiB,CAAA;AAC5B,IAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,EACvB;AACA,EAAA,QAAA,CAAS,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AACrC;AAGA,SAAS,gBAAgB,MAAA,EAAwB;AAC7C,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACrC,EAAA,IAAI,WAAW,KAAA,EAAO,QAAA,CAAS,eAAA,CAAgB,YAAA,CAAa,aAAa,KAAK,CAAA;AAAA,OACzE,QAAA,CAAS,eAAA,CAAgB,eAAA,CAAgB,WAAW,CAAA;AAC7D;AAUA,SAAS,gBAAgB,IAAA,EAAoB;AACzC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,EAAA,IAAI,OAAO,MAAA,CAAO,mBAAA,KAAwB,UAAA,EAAY;AAClD,IAAA,MAAA,CAAO,oBAAoB,IAAI,CAAA;AAC/B,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,0BAA0B,CAAA;AAC9D,EAAA,IAAI,MAAM,IAAA,CAAK,YAAA,CAAa,SAAA,EAAW,SAAA,CAAU,IAAI,CAAC,CAAA;AAC1D;AAeA,IAAM,aAAA,GAAgBC,oBAAyC,IAAI,CAAA;AAc5D,SAAS,eAAA,CAAgB;AAAA,EAC5B,QAAA;AAAA,EACA,WAAA,GAAc,gBAAA;AAAA,EACd,MAAA,GAAS;AACb,CAAA,EAAyB;AACrB,EAAA,MAAM,CAAC,MAAM,YAAY,CAAA,GAAIC,eAAiB,MAAM,YAAA,CAAa,WAAW,CAAC,CAAA;AAC7E,EAAA,MAAM,CAAC,MAAA,EAAQ,cAAc,CAAA,GAAIA,eAAmB,IAAI,CAAA;AACxD,EAAA,MAAM,WAAA,GAAcC,aAAO,KAAK,CAAA;AAGhC,EAAAC,eAAA,CAAU,MAAM;AACZ,IAAA,IAAI,YAAY,OAAA,EAAS;AACzB,IAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,IAAA,MAAM,UAAA,GAAa,YAAA,CAAa,cAAA,EAAe,IAAK,WAAW,CAAA;AAC/D,IAAA,SAAA,CAAU,UAAU,CAAA;AACpB,IAAA,eAAA,CAAgB,UAAU,CAAA;AAC1B,IAAA,YAAA,CAAa,UAAU,CAAA;AACvB,IAAA,MAAM,YAAA,GAAe,kBAAiB,IAAK,IAAA;AAC3C,IAAA,eAAA,CAAgB,YAAY,CAAA;AAC5B,IAAA,cAAA,CAAe,YAAY,CAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAGhB,EAAAA,eAAA,CAAU,MAAM;AACZ,IAAA,SAAS,IAAA,GAAO;AACZ,MAAA,MAAM,UAAA,GAAa,YAAA,CAAa,cAAA,EAAe,IAAK,IAAI,CAAA;AACxD,MAAA,IAAI,eAAe,IAAA,EAAM;AACrB,QAAA,SAAA,CAAU,UAAU,CAAA;AACpB,QAAA,eAAA,CAAgB,UAAU,CAAA;AAC1B,QAAA,YAAA,CAAa,UAAU,CAAA;AAAA,MAC3B;AACA,MAAA,MAAM,YAAA,GAAe,kBAAiB,IAAK,IAAA;AAC3C,MAAA,IAAI,iBAAiB,MAAA,EAAQ;AACzB,QAAA,eAAA,CAAgB,YAAY,CAAA;AAC5B,QAAA,cAAA,CAAe,YAAY,CAAA;AAAA,MAC/B;AAAA,IACJ;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,IAAI,CAAA;AACrC,IAAA,QAAA,CAAS,gBAAA,CAAiB,oBAAoB,IAAI,CAAA;AAClD,IAAA,OAAO,MAAM;AACT,MAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,IAAI,CAAA;AACxC,MAAA,QAAA,CAAS,mBAAA,CAAoB,oBAAoB,IAAI,CAAA;AAAA,IACzD,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,IAAA,EAAM,MAAM,CAAC,CAAA;AAEjB,EAAA,MAAM,OAAA,GAAUC,iBAAA,CAAY,CAAC,EAAA,KAAe;AACxC,IAAA,MAAM,IAAA,GAAO,aAAa,EAAE,CAAA;AAC5B,IAAA,SAAA,CAAU,IAAI,CAAA;AACd,IAAA,eAAA,CAAgB,IAAI,CAAA;AACpB,IAAA,eAAA,CAAgB,IAAI,CAAA;AACpB,IAAA,YAAA,CAAa,IAAI,CAAA;AAAA,EACrB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,SAAA,GAAYA,iBAAA,CAAY,CAACC,MAAAA,KAAoB;AAC/C,IAAA,MAAM,IAAA,GAAiBA,MAAAA,KAAU,KAAA,GAAQ,KAAA,GAAQ,IAAA;AACjD,IAAA,eAAA,CAAgB,IAAI,CAAA;AACpB,IAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,IAAA,cAAA,CAAe,IAAI,CAAA;AAAA,EACvB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,KAAA,GAAQC,aAAA;AAAA,IACV,OAAO,EAAE,IAAA,EAAM,SAAS,MAAA,EAAQ,SAAA,EAAW,QAAQ,SAAA,EAAU,CAAA;AAAA,IAC7D,CAAC,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,SAAS;AAAA,GACrC;AAEA,EAAA,uBACIR,eAAAA,CAAC,aAAA,CAAc,QAAA,EAAd,EAAuB,KAAA,EACnB,QAAA,EAAA;AAAA,IAAA,MAAA,KAAW,KAAA,oBACRC,cAAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAW,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,CAAO,SAAA,GAAY,MAAA,EAAW,CAAA;AAAA,IAEnF;AAAA,GAAA,EACL,CAAA;AAER;AAGO,SAAS,SAAA,GAAgC;AAC5C,EAAA,MAAM,GAAA,GAAMQ,iBAAW,aAAa,CAAA;AACpC,EAAA,IAAI,CAAC,GAAA,EAAK;AACN,IAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,EACrE;AACA,EAAA,OAAO,GAAA;AACX;AAQO,SAAS,WAAA,GAA0E;AACtF,EAAA,MAAM,EAAE,MAAA,EAAQ,SAAA,EAAU,GAAI,SAAA,EAAU;AACxC,EAAA,OAAO,EAAE,QAAQ,SAAA,EAAU;AAC/B;AASO,SAAS,oBAAA,CAAqB,cAAsB,gBAAA,EAA0B;AASjF,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,WAAA,CAAY,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,MAAM,CAAC,CAAC,CAAA;AACzE,EAAA,OACI,CAAA,oBAAA,EACW,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,QAAQ,IAAA,CAAK,SAAA,CAAU,WAAW,CAAC,CAAA,MAAA,EAAS,IAAA,CAAK,UAAU,iBAAiB,CAAC,CAAA,irBAAA,EAWnE,cAAc,CAAA,qGAAA,EAChB,IAAI,uFACK,IAAI,CAAA,kDAAA,EAGV,gBAAgB,CAAA,4FAAA,EACuB,WAAW,CAAA,0BAAA,CAAA;AAIvG;AChSA,IAAM,MAAA,GAAS,UAAA;AACf,IAAM,0BAAU,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,MAAA,EAAQ,QAAQ,CAAC,CAAA;AACnD,IAAMC,SAAAA,GAAW,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAEhC,SAAS,WAAW,IAAA,EAA6B;AAC7C,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,IAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,GAAG,IAAI,CAAA,CAAA,CAAA;AACtB,EAAA,KAAA,MAAW,IAAA,IAAQ,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AAC3C,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,EAAG;AAC5B,MAAA,MAAM,IAAI,kBAAA,CAAmB,OAAA,CAAQ,KAAA,CAAM,MAAA,CAAO,MAAM,CAAC,CAAA;AACzD,MAAA,OAAO,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,CAAA,GAAI,IAAA;AAAA,IAC9B;AAAA,EACJ;AACA,EAAA,OAAO,IAAA;AACX;AAEA,SAAS,YAAY,KAAA,EAAqB;AACtC,EAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACrC,EAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AACzB,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,QAAA,KAAa,WAAA,IAAe,SAAS,QAAA,KAAa,WAAA;AAC3E,EAAA,MAAM,KAAA,GAAQ;AAAA,IACV,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA;AAAA,IACtC,QAAA;AAAA,IACA,WAAWA,SAAQ,CAAA,CAAA;AAAA,IACnB;AAAA,GACJ;AACA,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,KAAA,CAAM,KAAK,iBAAiB,CAAA;AAC5B,IAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,EACvB;AACA,EAAA,QAAA,CAAS,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AACrC;AAEO,SAAS,aAAA,GAAgB;AAC5B,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAIC,mBAAA,EAAS;AACrC,EAAA,MAAM,WAAA,GAAcP,aAAO,KAAK,CAAA;AAEhC,EAAAC,gBAAU,MAAM;AACZ,IAAA,IAAI,YAAY,OAAA,EAAS;AACzB,IAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,IAAA,MAAM,WAAA,GAAc,WAAW,MAAM,CAAA;AACrC,IAAA,IAAI,eAAe,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAA,IAAK,gBAAgB,KAAA,EAAO;AAClE,MAAA,QAAA,CAAS,WAAW,CAAA;AAAA,IACxB;AAAA,EACJ,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEpB,EAAAA,gBAAU,MAAM;AACZ,IAAA,IAAI,CAAC,YAAY,OAAA,EAAS;AAC1B,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,WAAA,CAAY,KAAK,CAAA;AAAA,EACrB,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,IAAA;AACX;AC3DO,SAAS,aAAA,CAAc,EAAE,SAAA,EAAW,gBAAA,EAAkB,kBAAiB,EAAuB;AACjG,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,MAAA,KAAW,SAAA,EAAU;AAC5C,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIF,eAAS,KAAK,CAAA;AACtC,EAAA,MAAM,OAAA,GAAUC,aAAuB,IAAI,CAAA;AAE3C,EAAAC,gBAAU,MAAM;AACZ,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,SAAS,OAAO,CAAA,EAAe;AAC3B,MAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,CAAC,OAAA,CAAQ,OAAA,CAAQ,SAAS,CAAA,CAAE,MAAc,CAAA,EAAG,OAAA,CAAQ,KAAK,CAAA;AAAA,IACrF;AACA,IAAA,SAAS,MAAM,CAAA,EAAkB;AAC7B,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,QAAA,EAAU,OAAA,CAAQ,KAAK,CAAA;AAAA,IACzC;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,MAAM,CAAA;AAC7C,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,KAAK,CAAA;AAC1C,IAAA,OAAO,MAAM;AACT,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAa,MAAM,CAAA;AAChD,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,KAAK,CAAA;AAAA,IACjD,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,uBACIL,gBAAC,KAAA,EAAA,EAAI,GAAA,EAAK,SAAS,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAClD,QAAA,EAAA;AAAA,oBAAAC,cAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACG,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,cAAA;AAAA,QACX,eAAA,EAAc,MAAA;AAAA,QACd,eAAA,EAAe,IAAA;AAAA,QACf,KAAA,EAAM,cAAA;AAAA,QACN,SAAS,MAAM,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,QAChC,SAAA,EAAW,EAAA;AAAA,UACP,0LAAA;AAAA,UACA;AAAA,SACJ;AAAA,QAEA,0BAAAA,cAAAA,CAACW,mBAAA,EAAA,EAAQ,SAAA,EAAU,QAAA,EAAS,eAAW,IAAA,EAAC;AAAA;AAAA,KAC5C;AAAA,IAEC,wBACGZ,eAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACG,IAAA,EAAK,MAAA;AAAA,QACL,SAAA,EAAW,EAAA;AAAA,UACP,gHAAA;AAAA,UACA;AAAA,SACJ;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAAC,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iDAAA,EAAkD,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,0BACtEA,eAAC,IAAA,EAAA,EAAG,SAAA,EAAU,QACT,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM;AACf,YAAA,MAAM,MAAA,GAAS,EAAE,EAAA,KAAO,IAAA;AACxB,YAAA,uBACIA,cAAAA,CAAC,IAAA,EAAA,EACG,QAAA,kBAAAD,eAAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACG,IAAA,EAAK,QAAA;AAAA,gBACL,IAAA,EAAK,eAAA;AAAA,gBACL,cAAA,EAAc,MAAA;AAAA,gBACd,SAAS,MAAM;AACX,kBAAA,OAAA,CAAQ,EAAE,EAAE,CAAA;AACZ,kBAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,gBACjB,CAAA;AAAA,gBACA,SAAA,EAAW,EAAA;AAAA,kBACP,kHAAA;AAAA,kBACA,MAAA,IAAU;AAAA,iBACd;AAAA,gBAEA,QAAA,EAAA;AAAA,kCAAAC,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,wBAAA,EACX,QAAA,EAAA,MAAA,oBAAUA,cAAAA,CAACY,iBAAA,EAAA,EAAM,SAAA,EAAU,qBAAA,EAAsB,aAAA,EAAW,IAAA,EAAC,CAAA,EAClE,CAAA;AAAA,kCACAb,eAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EACZ,QAAA,EAAA;AAAA,oCAAAC,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2BAAA,EAA6B,YAAE,KAAA,EAAM,CAAA;AAAA,oCACrDA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kDAAA,EACX,YAAE,WAAA,EACP;AAAA,mBAAA,EACJ;AAAA;AAAA;AAAA,aACJ,EAAA,EAvBK,EAAE,EAwBX,CAAA;AAAA,UAER,CAAC,CAAA,EACL;AAAA;AAAA;AAAA;AACJ,GAAA,EAER,CAAA;AAER;AC3EA,IAAM,KAAA,GAAQ;AAAA,EACV,EAAE,EAAA,EAAI,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,MAAMa,eAAA,EAAI;AAAA,EACzC,EAAE,EAAA,EAAI,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,MAAMC,gBAAA,EAAK;AAAA,EACxC,EAAE,EAAA,EAAI,QAAA,EAAU,KAAA,EAAO,QAAA,EAAU,MAAMC,mBAAA;AAC3C,CAAA;AASO,SAAS,kBAAA,CAAmB,EAAE,SAAA,EAAU,EAA2B;AACtE,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,MAAA,KAAW,SAAA,EAAU;AAC5C,EAAA,MAAM,EAAE,MAAA,EAAQ,SAAA,EAAU,GAAI,WAAA,EAAY;AAC1C,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAIL,mBAAAA,EAAS;AACrC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIR,eAAS,KAAK,CAAA;AAC5C,EAAAE,gBAAU,MAAM,UAAA,CAAW,IAAI,CAAA,EAAG,EAAE,CAAA;AACpC,EAAA,MAAM,UAAA,GAAa,OAAA,GAAW,KAAA,IAAS,QAAA,GAAY,IAAA;AACnD,EAAA,MAAM,YAAA,GAAe,UAAU,MAAA,GAAS,IAAA;AAExC,EAAA,uBACIL,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EACD,QAAA,EAAA;AAAA,oBAAAC,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iDAAA,EAAkD,QAAA,EAAA,MAAA,EAAI,CAAA;AAAA,oBACrEA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kCAAA,EACV,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,EAAE,EAAA,EAAI,KAAA,EAAO,IAAA,EAAK,KAAM;AAChC,MAAA,MAAM,SAAS,UAAA,KAAe,EAAA;AAC9B,MAAA,uBACID,eAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEG,IAAA,EAAK,QAAA;AAAA,UACL,IAAA,EAAK,eAAA;AAAA,UACL,cAAA,EAAc,MAAA;AAAA,UACd,OAAA,EAAS,MAAM,QAAA,CAAS,EAAE,CAAA;AAAA,UAC1B,SAAA,EAAW,EAAA;AAAA,YACP,uFAAA;AAAA,YACA,SACM,0CAAA,GACA;AAAA,WACV;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAAC,cAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,QAAA,EAAS,eAAW,IAAA,EAAC,CAAA;AAAA,YACpC;AAAA;AAAA,SAAA;AAAA,QAbI;AAAA,OAcT;AAAA,IAER,CAAC,CAAA,EACL,CAAA;AAAA,oBACAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAA2D,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,oBAC/EA,eAAC,IAAA,EAAA,EAAG,SAAA,EAAU,QACT,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM;AACf,MAAA,MAAM,MAAA,GAAS,EAAE,EAAA,KAAO,IAAA;AACxB,MAAA,uBACIA,cAAAA,CAAC,IAAA,EAAA,EACG,QAAA,kBAAAD,eAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACG,IAAA,EAAK,QAAA;AAAA,UACL,IAAA,EAAK,eAAA;AAAA,UACL,cAAA,EAAc,MAAA;AAAA,UACd,OAAA,EAAS,MAAM,OAAA,CAAQ,CAAA,CAAE,EAAE,CAAA;AAAA,UAC3B,SAAA,EAAW,EAAA;AAAA,YACP,kHAAA;AAAA,YACA,MAAA,IAAU;AAAA,WACd;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAAC,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,wBAAA,EACX,QAAA,EAAA,MAAA,oBAAUA,cAAAA,CAACY,iBAAAA,EAAA,EAAM,SAAA,EAAU,qBAAA,EAAsB,aAAA,EAAW,MAAC,CAAA,EAClE,CAAA;AAAA,4BACAb,eAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EACZ,QAAA,EAAA;AAAA,8BAAAC,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2BAAA,EAA6B,YAAE,KAAA,EAAM,CAAA;AAAA,8BACrDA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kDAAA,EACX,YAAE,WAAA,EACP;AAAA,aAAA,EACJ;AAAA;AAAA;AAAA,OACJ,EAAA,EApBK,EAAE,EAqBX,CAAA;AAAA,IAER,CAAC,CAAA,EACL,CAAA;AAAA,oBACAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4DAA2D,QAAA,EAAA,gBAAA,EAE1E,CAAA;AAAA,oBACAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kCAAA,EAEP,QAAA,EAAA;AAAA,MACI,EAAE,EAAA,EAAI,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,MAAMgB,iBAAA,EAAM;AAAA,MACrC,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,MAAMC,iBAAA;AAAM,MAE7C,GAAA,CAAI,CAAC,EAAE,EAAA,EAAI,KAAA,EAAO,MAAK,KAAM;AAC3B,MAAA,MAAM,SAAS,YAAA,KAAiB,EAAA;AAChC,MAAA,uBACIlB,eAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEG,IAAA,EAAK,QAAA;AAAA,UACL,IAAA,EAAK,eAAA;AAAA,UACL,cAAA,EAAc,MAAA;AAAA,UACd,YAAA,EAAY,EAAA,KAAO,KAAA,GAAQ,sBAAA,GAAyB,mBAAA;AAAA,UACpD,OAAA,EAAS,MAAM,SAAA,CAAU,EAAE,CAAA;AAAA,UAC3B,SAAA,EAAW,EAAA;AAAA,YACP,uFAAA;AAAA,YACA,SACM,0CAAA,GACA;AAAA,WACV;AAAA,UAEA,QAAA,EAAA;AAAA,4BAAAC,cAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,QAAA,EAAS,eAAW,IAAA,EAAC,CAAA;AAAA,YACpC;AAAA;AAAA,SAAA;AAAA,QAdI;AAAA,OAeT;AAAA,IAER,CAAC,CAAA,EACL;AAAA,GAAA,EACJ,CAAA;AAER;AAEO,SAAS,gBAAA,CAAiB;AAAA,EAC7B,SAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACJ,CAAA,EAA0B;AACtB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIE,eAAS,KAAK,CAAA;AACtC,EAAA,MAAM,OAAA,GAAUC,aAAuB,IAAI,CAAA;AAE3C,EAAAC,gBAAU,MAAM;AACZ,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,SAAS,OAAO,CAAA,EAAe;AAC3B,MAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,CAAC,OAAA,CAAQ,OAAA,CAAQ,SAAS,CAAA,CAAE,MAAc,CAAA,EAAG,OAAA,CAAQ,KAAK,CAAA;AAAA,IACrF;AACA,IAAA,SAAS,MAAM,CAAA,EAAkB;AAC7B,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,QAAA,EAAU,OAAA,CAAQ,KAAK,CAAA;AAAA,IACzC;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,MAAM,CAAA;AAC7C,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,KAAK,CAAA;AAC1C,IAAA,OAAO,MAAM;AACT,MAAA,QAAA,CAAS,mBAAA,CAAoB,aAAa,MAAM,CAAA;AAChD,MAAA,QAAA,CAAS,mBAAA,CAAoB,WAAW,KAAK,CAAA;AAAA,IACjD,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,uBACIL,gBAAC,KAAA,EAAA,EAAI,GAAA,EAAK,SAAS,SAAA,EAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAClD,QAAA,EAAA;AAAA,oBAAAC,cAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACG,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,qBAAA;AAAA,QACX,eAAA,EAAc,MAAA;AAAA,QACd,eAAA,EAAe,IAAA;AAAA,QACf,KAAA,EAAM,8BAAA;AAAA,QACN,SAAS,MAAM,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,QAChC,SAAA,EAAW,EAAA;AAAA,UACP,0LAAA;AAAA,UACA;AAAA,SACJ;AAAA,QAEA,0BAAAA,cAAAA,CAACW,mBAAAA,EAAA,EAAQ,SAAA,EAAU,QAAA,EAAS,eAAW,IAAA,EAAC;AAAA;AAAA,KAC5C;AAAA,IAEC,wBACGX,cAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACG,IAAA,EAAK,MAAA;AAAA,QACL,SAAA,EAAW,EAAA;AAAA,UACP,gHAAA;AAAA,UACA;AAAA,SACJ;AAAA,QAEA,QAAA,kBAAAA,eAAC,kBAAA,EAAA,EAAmB;AAAA;AAAA;AACxB,GAAA,EAER,CAAA;AAER","file":"tokens.js","sourcesContent":["import type { ClassValue } from 'clsx';\n\nimport { clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Canonical class-name merge for the OrangeCheck family.\n * `clsx` for conditional composition, `tailwind-merge` to resolve\n * conflicting Tailwind utilities (last-wins by property).\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * The OrangeCheck theme (skin) registry.\n *\n * A *skin* is the named-theme axis, orthogonal to the light/dark *mode* axis\n * (which stays owned by `next-themes` via the `.dark` class). A skin is applied\n * as `data-oc-theme=\"<id>\"` on `<html>` and persisted in the `oc_skin` cookie at\n * `Domain=.ochk.io` so a choice on one family site carries to every other.\n *\n * Adding a skin = add a `themes/<id>.css` token block in this package and a\n * row here. Every site picks it up on the next `@orangecheck/design` bump; no\n * per-site edits.\n */\nexport interface OcTheme {\n /** Stable id — also the `data-oc-theme` attribute value and the CSS file stem. */\n readonly id: string;\n /** Human label for the picker (lowercase, house voice). */\n readonly label: string;\n /** One-line description shown in the picker / Storybook. */\n readonly description: string;\n /**\n * Accent hex (sRGB of the skin's dark-mode `--brand`). Used to swap the\n * browser chrome — `<meta name=\"theme-color\">` and the favicon (recolored\n * from the family `#f97316`) — when the skin changes. Mirrors the\n * `SKINS` palette in `oc-media-kit/build/brands.py` (same source of truth).\n */\n readonly accent: string;\n}\n\n// ember leads — the warm, human default. The other four are the Bitcoin-ethos\n// alternates (sharp, flat, cypherpunk), each carrying a meaning, not just a\n// colour: the chain, the node, the network, sound money. Order here is the\n// order shown in the appearance menu / picker (ember first).\nexport const OC_THEMES: readonly OcTheme[] = [\n {\n id: 'ember',\n label: 'ember',\n description:\n 'the warmth — burnt-sienna terracotta, soft 1rem corners, pill buttons, Hanken Grotesk · approachable, human',\n accent: '#da6736',\n },\n {\n id: 'orangecheck',\n label: 'orangecheck',\n description: 'the chain — Bitcoin orange, sharp 0.25rem corners, Inter + JetBrains Mono',\n accent: '#f97316',\n },\n {\n id: 'phosphor',\n label: 'phosphor',\n description: 'the node — CRT terminal green, hard 0.125rem, all-mono · sovereignty & verify',\n accent: '#55d671',\n },\n {\n id: 'lightning',\n label: 'lightning',\n description: 'the network — electric violet (L2), hardest 0rem edges, sans · instant',\n accent: '#c27dff',\n },\n {\n id: 'gold',\n label: 'gold',\n description: 'sound money — digital gold, hard 0.125rem milled edge, mono ledger · 21M',\n accent: '#e3b831',\n },\n] as const;\n\n/** The family default accent (orangecheck), and the hex every favicon ships\n * with — the swap recolors from this to the active skin's accent. */\nexport const OC_DEFAULT_ACCENT = '#f97316';\n\n/** Accent hex for a skin id, falling back to the default. */\nexport function accentFor(id: string | null | undefined): string {\n return OC_THEMES.find((t) => t.id === id)?.accent ?? OC_DEFAULT_ACCENT;\n}\n\n// ember is the family default — the skin a user with no `oc_skin` cookie gets.\n// (The favicon SVGs still ship baked with OC_DEFAULT_ACCENT below; the init\n// script recolors them from that to the active skin's accent on load.)\nexport const DEFAULT_OC_THEME = 'ember';\n\nexport type OcThemeId = (typeof OC_THEMES)[number]['id'] | (string & {});\n\nexport function isKnownTheme(id: string | null | undefined): id is OcThemeId {\n return !!id && OC_THEMES.some((t) => t.id === id);\n}\n\nexport function resolveTheme(id: string | null | undefined): string {\n return isKnownTheme(id) ? id : DEFAULT_OC_THEME;\n}\n\n/** Cookie name for the cross-subdomain skin choice. */\nexport const OC_SKIN_COOKIE = 'oc_skin';\n\n/**\n * Cookie name for the cross-subdomain ambient-motion choice ('off' pauses the\n * aurora + every `.oc-ambient` decoration family-wide). This is the WCAG 2.2.2\n * Pause/Stop/Hide mechanism — prefers-reduced-motion alone does not satisfy it\n * for >5s auto-playing decorative motion.\n */\nexport const OC_MOTION_COOKIE = 'oc_motion';\n","import type { CSSProperties } from 'react';\n\nimport { cn } from './cn';\n\nexport interface OcAuroraProps {\n /**\n * Master intensity multiplier (default 1, from the theme CSS). Overrides\n * `--oc-aurora-intensity` for this mount — e.g. dial a reading-heavy site down.\n */\n intensity?: number;\n className?: string;\n}\n\nconst BLOBS = [1, 2, 3, 4, 5] as const;\n\n/**\n * The ambient \"bitcoin aurora\" background — soft, theme-reactive colour clouds\n * that slowly wander (styling in styles/aurora.css; recolours from --brand /\n * --success / --info / --primary across mode + skin). Pure markup, fixed behind\n * all content; `OcThemeProvider` mounts it by default. Mount manually only if a\n * site renders the aurora outside the provider.\n */\nexport function OcAurora({ intensity, className }: OcAuroraProps) {\n const style =\n intensity == null\n ? undefined\n : ({ '--oc-aurora-intensity': String(intensity) } as CSSProperties);\n return (\n <div className={cn('oc-aurora', className)} style={style} aria-hidden=\"true\">\n {BLOBS.map((n) => (\n <div key={n} className={`oc-aurora__blob oc-aurora__blob-${n}`} />\n ))}\n <div className=\"oc-aurora__grain\" />\n </div>\n );\n}\n","'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\n\nimport {\n accentFor,\n DEFAULT_OC_THEME,\n OC_DEFAULT_ACCENT,\n OC_MOTION_COOKIE,\n OC_SKIN_COOKIE,\n OC_THEMES,\n resolveTheme,\n type OcTheme,\n} from './themes';\nimport { OcAurora } from './aurora';\n\ndeclare global {\n interface Window {\n /** Defined by `getOcThemeInitScript()`; recolors favicon + theme-color. */\n __ocApplySkinChrome?: (skin: string) => void;\n }\n}\n\n/**\n * OcThemeProvider — the skin (named-theme) axis.\n *\n * Orthogonal to `next-themes`, which owns light/dark via the `.dark` class.\n * This provider owns the `data-oc-theme` attribute on `<html>` and persists the\n * choice in the `oc_skin` cookie at `Domain=.ochk.io`, so a skin chosen on one\n * `*.ochk.io` site is honored on every other. It re-reads the cookie on focus /\n * visibility change so a fresh choice picks up when the user returns to a tab\n * (same cross-site pickup trick `OcAccountMenu` uses for sign-in).\n *\n * Mount once, inside (or beside) the `next-themes` `<ThemeProvider>`:\n *\n * <ThemeProvider attribute=\"class\" defaultTheme=\"system\" enableSystem>\n * <OcThemeProvider>\n * …app…\n * </OcThemeProvider>\n * </ThemeProvider>\n *\n * Pair with `getOcThemeInitScript()` in `_document` to avoid a flash before\n * hydration.\n */\n\nconst ONE_YEAR = 60 * 60 * 24 * 365;\nconst ATTR = 'data-oc-theme';\nconst MOTION_ATTR = 'data-oc-motion';\n\n/** Ambient-motion switch. `'off'` freezes the aurora and every `.oc-ambient`. */\nexport type OcMotion = 'on' | 'off';\n\nfunction readSkinCookie(): string | null {\n if (typeof document === 'undefined') return null;\n const prefix = `${OC_SKIN_COOKIE}=`;\n for (const part of document.cookie.split(';')) {\n const trimmed = part.trim();\n if (trimmed.startsWith(prefix)) {\n const v = decodeURIComponent(trimmed.slice(prefix.length));\n return v.length > 0 ? v : null;\n }\n }\n return null;\n}\n\nfunction writeSkinCookie(value: string): void {\n if (typeof document === 'undefined') return;\n const isLocal =\n location.hostname === 'localhost' || location.hostname === '127.0.0.1';\n const parts = [\n `${OC_SKIN_COOKIE}=${encodeURIComponent(value)}`,\n 'Path=/',\n `Max-Age=${ONE_YEAR}`,\n 'SameSite=Lax',\n ];\n if (!isLocal) {\n parts.push('Domain=.ochk.io');\n parts.push('Secure');\n }\n document.cookie = parts.join('; ');\n}\n\nfunction applyAttr(skin: string): void {\n if (typeof document === 'undefined') return;\n document.documentElement.setAttribute(ATTR, skin);\n}\n\nfunction readMotionCookie(): OcMotion | null {\n if (typeof document === 'undefined') return null;\n const prefix = `${OC_MOTION_COOKIE}=`;\n for (const part of document.cookie.split(';')) {\n const trimmed = part.trim();\n if (trimmed.startsWith(prefix)) {\n const v = decodeURIComponent(trimmed.slice(prefix.length));\n return v === 'off' ? 'off' : v === 'on' ? 'on' : null;\n }\n }\n return null;\n}\n\nfunction writeMotionCookie(value: OcMotion): void {\n if (typeof document === 'undefined') return;\n const isLocal =\n location.hostname === 'localhost' || location.hostname === '127.0.0.1';\n const parts = [\n `${OC_MOTION_COOKIE}=${encodeURIComponent(value)}`,\n 'Path=/',\n `Max-Age=${ONE_YEAR}`,\n 'SameSite=Lax',\n ];\n if (!isLocal) {\n parts.push('Domain=.ochk.io');\n parts.push('Secure');\n }\n document.cookie = parts.join('; ');\n}\n\n/** Attribute is only present when motion is off — absence means the default. */\nfunction applyMotionAttr(motion: OcMotion): void {\n if (typeof document === 'undefined') return;\n if (motion === 'off') document.documentElement.setAttribute(MOTION_ATTR, 'off');\n else document.documentElement.removeAttribute(MOTION_ATTR);\n}\n\n/**\n * Swap the browser chrome (favicon + `<meta name=\"theme-color\">`) to the skin's\n * accent. The real work lives in the global installed by\n * `getOcThemeInitScript()` (so the favicon's original SVG is captured exactly\n * once, before the init script's own first recolor — avoids re-reading an\n * already-swapped data: URI). If the init script wasn't included, fall back to\n * the theme-color swap alone (favicon recolor needs the captured original).\n */\nfunction applySkinChrome(skin: string): void {\n if (typeof window === 'undefined') return;\n if (typeof window.__ocApplySkinChrome === 'function') {\n window.__ocApplySkinChrome(skin);\n return;\n }\n const meta = document.querySelector('meta[name=\"theme-color\"]');\n if (meta) meta.setAttribute('content', accentFor(skin));\n}\n\ninterface OcSkinContextValue {\n /** Current skin id (always resolved to a known theme). */\n skin: string;\n /** Set the skin: validates, applies the attribute, persists the cookie. */\n setSkin: (id: string) => void;\n /** The full registry, for rendering a picker. */\n themes: readonly OcTheme[];\n /** Ambient-motion switch ('off' pauses aurora + every `.oc-ambient`). */\n motion: OcMotion;\n /** Set ambient motion: applies the attribute, persists the cookie. */\n setMotion: (value: OcMotion) => void;\n}\n\nconst OcSkinContext = createContext<OcSkinContextValue | null>(null);\n\nexport interface OcThemeProviderProps {\n children: ReactNode;\n /** Skin to assume before the cookie is read (defaults to `orangecheck`). */\n defaultSkin?: string;\n /**\n * The ambient bitcoin-aurora background. `true` (default) renders it behind\n * the app; `false` disables it; `{ intensity }` tunes its strength for this\n * site (e.g. `aurora={{ intensity: 0.5 }}` on a reading-heavy surface).\n */\n aurora?: boolean | { intensity?: number };\n}\n\nexport function OcThemeProvider({\n children,\n defaultSkin = DEFAULT_OC_THEME,\n aurora = true,\n}: OcThemeProviderProps) {\n const [skin, setSkinState] = useState<string>(() => resolveTheme(defaultSkin));\n const [motion, setMotionState] = useState<OcMotion>('on');\n const hydratedRef = useRef(false);\n\n // Hydrate from the cookies once on mount and align the attributes.\n useEffect(() => {\n if (hydratedRef.current) return;\n hydratedRef.current = true;\n const fromCookie = resolveTheme(readSkinCookie() ?? defaultSkin);\n applyAttr(fromCookie);\n applySkinChrome(fromCookie);\n setSkinState(fromCookie);\n const motionCookie = readMotionCookie() ?? 'on';\n applyMotionAttr(motionCookie);\n setMotionState(motionCookie);\n }, [defaultSkin]);\n\n // Cross-site pickup: re-read the cookies when the tab regains focus.\n useEffect(() => {\n function sync() {\n const fromCookie = resolveTheme(readSkinCookie() ?? skin);\n if (fromCookie !== skin) {\n applyAttr(fromCookie);\n applySkinChrome(fromCookie);\n setSkinState(fromCookie);\n }\n const motionCookie = readMotionCookie() ?? 'on';\n if (motionCookie !== motion) {\n applyMotionAttr(motionCookie);\n setMotionState(motionCookie);\n }\n }\n window.addEventListener('focus', sync);\n document.addEventListener('visibilitychange', sync);\n return () => {\n window.removeEventListener('focus', sync);\n document.removeEventListener('visibilitychange', sync);\n };\n }, [skin, motion]);\n\n const setSkin = useCallback((id: string) => {\n const next = resolveTheme(id);\n applyAttr(next);\n applySkinChrome(next);\n writeSkinCookie(next);\n setSkinState(next);\n }, []);\n\n const setMotion = useCallback((value: OcMotion) => {\n const next: OcMotion = value === 'off' ? 'off' : 'on';\n applyMotionAttr(next);\n writeMotionCookie(next);\n setMotionState(next);\n }, []);\n\n const value = useMemo<OcSkinContextValue>(\n () => ({ skin, setSkin, themes: OC_THEMES, motion, setMotion }),\n [skin, setSkin, motion, setMotion]\n );\n\n return (\n <OcSkinContext.Provider value={value}>\n {aurora !== false && (\n <OcAurora intensity={typeof aurora === 'object' ? aurora.intensity : undefined} />\n )}\n {children}\n </OcSkinContext.Provider>\n );\n}\n\n/** Read the current skin + setter. Throws if used outside `OcThemeProvider`. */\nexport function useOcSkin(): OcSkinContextValue {\n const ctx = useContext(OcSkinContext);\n if (!ctx) {\n throw new Error('useOcSkin must be used within <OcThemeProvider>');\n }\n return ctx;\n}\n\n/**\n * Read the ambient-motion switch + setter. The WCAG 2.2.2 pause mechanism:\n * `'off'` sets `data-oc-motion=\"off\"` on `<html>` (persisted family-wide in the\n * `oc_motion` cookie), which pauses the aurora and any `.oc-ambient` element.\n * Throws if used outside `OcThemeProvider`.\n */\nexport function useOcMotion(): { motion: OcMotion; setMotion: (value: OcMotion) => void } {\n const { motion, setMotion } = useOcSkin();\n return { motion, setMotion };\n}\n\n/**\n * Blocking init script for `_document` (Pages Router) `<Head>`. Applies the\n * cookie's skin to `<html>` before first paint so there is no flash of the\n * default skin. Inject with:\n *\n * <script dangerouslySetInnerHTML={{ __html: getOcThemeInitScript() }} />\n */\nexport function getOcThemeInitScript(defaultSkin: string = DEFAULT_OC_THEME): string {\n // Self-contained IIFE — no imports available at parse time. Beyond applying\n // the skin attribute before first paint, it installs `window.__ocApplySkinChrome`\n // (the single owner of the favicon + theme-color swap) and runs it for the\n // saved skin. OcThemeProvider re-invokes the same global on later changes, so\n // the favicon's *original* SVG is captured exactly once (before any recolor)\n // and re-recolored from `#f97316` to the active skin's accent. The favicon\n // recolor is async (a fetch of the same-origin favicon.svg) — chrome updates\n // a beat after paint, which is fine; the skin attribute itself is synchronous.\n const accents = Object.fromEntries(OC_THEMES.map((t) => [t.id, t.accent]));\n return (\n `(function(){` +\n `var ACC=${JSON.stringify(accents)},DEF=${JSON.stringify(defaultSkin)},ORIG=${JSON.stringify(OC_DEFAULT_ACCENT)},fav=null;` +\n `function acc(s){return ACC[s]||ACC[DEF]||ORIG;}` +\n `window.__ocApplySkinChrome=function(s){try{` +\n `var a=acc(s);` +\n `var meta=document.querySelector('meta[name=\"theme-color\"]');if(meta){meta.setAttribute('content',a);}` +\n `var link=document.querySelector('link[rel~=\"icon\"][type=\"image/svg+xml\"]');if(!link){return;}` +\n `var paint=function(svg){link.setAttribute('href','data:image/svg+xml,'+encodeURIComponent(svg.split(ORIG).join(a)));};` +\n `if(fav!=null){paint(fav);return;}` +\n `var h=link.getAttribute('href');if(!h||h.indexOf('data:')===0){return;}` +\n `fetch(h).then(function(r){return r.text();}).then(function(svg){fav=svg;paint(svg);}).catch(function(){});` +\n `}catch(e){}};` +\n `try{var m=document.cookie.match(/(?:^|; )${OC_SKIN_COOKIE}=([^;]*)/);var s=m?decodeURIComponent(m[1]):DEF;if(!s){s=DEF;}` +\n `document.documentElement.setAttribute('${ATTR}',s);window.__ocApplySkinChrome(s);}` +\n `catch(e){document.documentElement.setAttribute('${ATTR}',DEF);}` +\n // Ambient-motion pause (oc_motion cookie) applied before first paint so\n // a paused choice never flashes a moving frame. Absence = motion on.\n `try{var mm=document.cookie.match(/(?:^|; )${OC_MOTION_COOKIE}=([^;]*)/);` +\n `if(mm&&decodeURIComponent(mm[1])==='off'){document.documentElement.setAttribute('${MOTION_ATTR}','off');}}` +\n `catch(e){}` +\n `})();`\n );\n}\n","'use client';\n\nimport { useEffect, useRef } from 'react';\nimport { useTheme } from 'next-themes';\n\n/**\n * OcThemeBridge — cross-subdomain persistence for the MODE axis (light/dark).\n *\n * `next-themes` defaults to origin-scoped `localStorage`, so a dark/light choice\n * on one `*.ochk.io` site won't carry to another. This layers an\n * `oc_theme` cookie at `Domain=.ochk.io` on top so the choice is visible\n * family-wide. (The SKIN axis has its own `oc_skin` bridge inside\n * `OcThemeProvider`; this is the mode counterpart, previously duplicated in\n * every consumer repo.)\n *\n * Mount once inside the next-themes `<ThemeProvider>`:\n *\n * <ThemeProvider attribute=\"class\" defaultTheme=\"system\" enableSystem>\n * <OcThemeBridge />\n * <OcThemeProvider>…</OcThemeProvider>\n * </ThemeProvider>\n *\n * The cookie is intentionally non-HttpOnly (next-themes JS reads/writes it) and\n * carries no auth value — a leak only reveals a theme preference.\n */\nconst COOKIE = 'oc_theme';\nconst ALLOWED = new Set(['light', 'dark', 'system']);\nconst ONE_YEAR = 60 * 60 * 24 * 365;\n\nfunction readCookie(name: string): string | null {\n if (typeof document === 'undefined') return null;\n const prefix = `${name}=`;\n for (const part of document.cookie.split(';')) {\n const trimmed = part.trim();\n if (trimmed.startsWith(prefix)) {\n const v = decodeURIComponent(trimmed.slice(prefix.length));\n return v.length > 0 ? v : null;\n }\n }\n return null;\n}\n\nfunction writeCookie(value: string): void {\n if (typeof document === 'undefined') return;\n if (!ALLOWED.has(value)) return;\n const isLocal = location.hostname === 'localhost' || location.hostname === '127.0.0.1';\n const parts = [\n `${COOKIE}=${encodeURIComponent(value)}`,\n 'Path=/',\n `Max-Age=${ONE_YEAR}`,\n 'SameSite=Lax',\n ];\n if (!isLocal) {\n parts.push('Domain=.ochk.io');\n parts.push('Secure');\n }\n document.cookie = parts.join('; ');\n}\n\nexport function OcThemeBridge() {\n const { theme, setTheme } = useTheme();\n const hydratedRef = useRef(false);\n\n useEffect(() => {\n if (hydratedRef.current) return;\n hydratedRef.current = true;\n const cookieValue = readCookie(COOKIE);\n if (cookieValue && ALLOWED.has(cookieValue) && cookieValue !== theme) {\n setTheme(cookieValue);\n }\n }, [theme, setTheme]);\n\n useEffect(() => {\n if (!hydratedRef.current) return;\n if (!theme) return;\n writeCookie(theme);\n }, [theme]);\n\n return null;\n}\n","'use client';\n\nimport { Check, Palette } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { cn } from './cn';\nimport { useOcSkin } from './provider';\n\n/**\n * OcThemePicker — the skin selector. Sits beside `ThemeToggle` in the header.\n * Self-contained dropdown (no Radix): outside-click + Escape to close. Mirrors\n * the ghost-icon affordance of `ThemeToggle`. Gate its mount behind\n * `NEXT_PUBLIC_OC_THEME_PICKER` during staged rollout.\n */\nexport interface OcThemePickerProps {\n className?: string;\n triggerClassName?: string;\n popoverClassName?: string;\n}\n\nexport function OcThemePicker({ className, triggerClassName, popoverClassName }: OcThemePickerProps) {\n const { skin, setSkin, themes } = useOcSkin();\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n function onDown(e: MouseEvent) {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDown);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDown);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn('relative', className)}>\n <button\n type=\"button\"\n aria-label=\"choose theme\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n title=\"choose theme\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'text-muted-foreground hover:text-foreground inline-flex size-9 items-center justify-center rounded-md transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n triggerClassName\n )}\n >\n <Palette className=\"size-4\" aria-hidden />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n className={cn(\n 'bg-popover text-popover-foreground absolute right-0 z-50 mt-2 w-64 overflow-hidden rounded-md border shadow-md',\n popoverClassName\n )}\n >\n <div className=\"label-mono text-muted-foreground px-3 pt-3 pb-1\">theme</div>\n <ul className=\"pb-1\">\n {themes.map((t) => {\n const active = t.id === skin;\n return (\n <li key={t.id}>\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n onClick={() => {\n setSkin(t.id);\n setOpen(false);\n }}\n className={cn(\n 'hover:bg-accent hover:text-accent-foreground flex w-full items-start gap-2 px-3 py-2 text-left transition-colors',\n active && 'text-foreground'\n )}\n >\n <span className=\"mt-0.5 size-4 shrink-0\">\n {active && <Check className=\"size-4 text-primary\" aria-hidden />}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-medium\">{t.label}</span>\n <span className=\"text-muted-foreground block text-xs leading-snug\">\n {t.description}\n </span>\n </span>\n </button>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { Check, Monitor, Moon, Palette, Pause, Sun, Waves } from 'lucide-react';\nimport { useTheme } from 'next-themes';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { cn } from './cn';\nimport { useOcMotion, useOcSkin } from './provider';\n\n/**\n * OcAppearanceMenu — the single header control for ALL appearance settings.\n *\n * One icon button opens a dropdown with both axes:\n * • mode — light / dark / system (next-themes `.dark` class)\n * • theme — the registered skins (data-oc-theme, persisted .ochk.io)\n *\n * Replaces the separate `ThemeToggle` + `OcThemePicker` so every family site\n * carries exactly one appearance control. Self-contained dropdown (no Radix):\n * outside-click + Escape to close. Requires `<OcThemeProvider>` above it (skin\n * axis) and a next-themes `<ThemeProvider>` (mode axis) — both already mounted\n * on every family site.\n */\nexport interface OcAppearanceMenuProps {\n className?: string;\n triggerClassName?: string;\n popoverClassName?: string;\n}\n\nconst MODES = [\n { id: 'light', label: 'light', Icon: Sun },\n { id: 'dark', label: 'dark', Icon: Moon },\n { id: 'system', label: 'system', Icon: Monitor },\n] as const;\n\n/**\n * AppearanceControls — the mode segment + skin list, with no trigger/popover\n * chrome of its own. Embed it anywhere a surface wants to host appearance\n * settings inline (the standalone OcAppearanceMenu popover, the mobile account\n * menu, a site's Sheet drawer). Requires `<OcThemeProvider>` + next-themes\n * above it, like OcAppearanceMenu.\n */\nexport function AppearanceControls({ className }: { className?: string }) {\n const { skin, setSkin, themes } = useOcSkin();\n const { motion, setMotion } = useOcMotion();\n const { theme, setTheme } = useTheme();\n const [mounted, setMounted] = useState(false);\n useEffect(() => setMounted(true), []);\n const activeMode = mounted ? (theme ?? 'system') : null;\n const activeMotion = mounted ? motion : null;\n\n return (\n <div className={className}>\n <div className=\"label-mono text-muted-foreground px-3 pt-3 pb-2\">mode</div>\n <div className=\"grid grid-cols-3 gap-1 px-2 pb-2\">\n {MODES.map(({ id, label, Icon }) => {\n const active = activeMode === id;\n return (\n <button\n key={id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n onClick={() => setTheme(id)}\n className={cn(\n 'flex flex-col items-center gap-1 rounded-md border py-2 text-[11px] transition-colors',\n active\n ? 'border-primary text-foreground bg-accent'\n : 'border-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground'\n )}\n >\n <Icon className=\"size-4\" aria-hidden />\n {label}\n </button>\n );\n })}\n </div>\n <div className=\"label-mono text-muted-foreground border-t px-3 pt-3 pb-1\">theme</div>\n <ul className=\"pb-1\">\n {themes.map((t) => {\n const active = t.id === skin;\n return (\n <li key={t.id}>\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n onClick={() => setSkin(t.id)}\n className={cn(\n 'hover:bg-accent hover:text-accent-foreground flex w-full items-start gap-2 px-3 py-2 text-left transition-colors',\n active && 'text-foreground'\n )}\n >\n <span className=\"mt-0.5 size-4 shrink-0\">\n {active && <Check className=\"text-primary size-4\" aria-hidden />}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block text-sm font-medium\">{t.label}</span>\n <span className=\"text-muted-foreground block text-xs leading-snug\">\n {t.description}\n </span>\n </span>\n </button>\n </li>\n );\n })}\n </ul>\n <div className=\"label-mono text-muted-foreground border-t px-3 pt-3 pb-2\">\n ambient motion\n </div>\n <div className=\"grid grid-cols-2 gap-1 px-2 pb-3\">\n {(\n [\n { id: 'on', label: 'on', Icon: Waves },\n { id: 'off', label: 'off', Icon: Pause },\n ] as const\n ).map(({ id, label, Icon }) => {\n const active = activeMotion === id;\n return (\n <button\n key={id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={active}\n aria-label={id === 'off' ? 'pause ambient motion' : 'ambient motion on'}\n onClick={() => setMotion(id)}\n className={cn(\n 'flex flex-col items-center gap-1 rounded-md border py-2 text-[11px] transition-colors',\n active\n ? 'border-primary text-foreground bg-accent'\n : 'border-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground'\n )}\n >\n <Icon className=\"size-4\" aria-hidden />\n {label}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n\nexport function OcAppearanceMenu({\n className,\n triggerClassName,\n popoverClassName,\n}: OcAppearanceMenuProps) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n function onDown(e: MouseEvent) {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDown);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDown);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn('relative', className)}>\n <button\n type=\"button\"\n aria-label=\"appearance settings\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n title=\"appearance · mode + theme\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n 'text-muted-foreground hover:text-foreground inline-flex size-9 items-center justify-center rounded-md transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50',\n triggerClassName\n )}\n >\n <Palette className=\"size-4\" aria-hidden />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n className={cn(\n 'bg-popover text-popover-foreground absolute right-0 z-50 mt-2 w-64 overflow-hidden rounded-md border shadow-md',\n popoverClassName\n )}\n >\n <AppearanceControls />\n </div>\n )}\n </div>\n );\n}\n"]}