@drip-apex/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -0
  3. package/dist/_headers +3 -0
  4. package/dist/bundle-report.json +564 -0
  5. package/dist/drip.debug.js +2 -0
  6. package/dist/drip.debug.js.map +1 -0
  7. package/dist/drip.heatmap.js +2 -0
  8. package/dist/drip.heatmap.js.map +1 -0
  9. package/dist/drip.js +2 -0
  10. package/dist/drip.js.map +1 -0
  11. package/dist/drip.live.js +2 -0
  12. package/dist/drip.live.js.map +1 -0
  13. package/dist/editor.js +480 -0
  14. package/dist/editor.js.map +7 -0
  15. package/dist/index.mjs +645 -0
  16. package/dist/index.mjs.map +7 -0
  17. package/dist/metafiles/drip.debug.meta.json +973 -0
  18. package/dist/metafiles/drip.heatmap.meta.json +918 -0
  19. package/dist/metafiles/drip.live.meta.json +918 -0
  20. package/dist/metafiles/drip.meta.json +973 -0
  21. package/dist/metafiles/editor.meta.json +321 -0
  22. package/dist/metafiles/index.meta.json +1039 -0
  23. package/dist/metafiles/index.mjs.meta.json +78 -0
  24. package/dist/react/index.js +16973 -0
  25. package/dist/react/index.js.map +7 -0
  26. package/dist/sri.json +27 -0
  27. package/dist/types/analytics.d.ts +15 -0
  28. package/dist/types/antiflicker.d.ts +14 -0
  29. package/dist/types/assignment-store.d.ts +30 -0
  30. package/dist/types/audit.d.ts +9 -0
  31. package/dist/types/bucket.d.ts +2 -0
  32. package/dist/types/bucketing-cleanup.d.ts +5 -0
  33. package/dist/types/commerce-gift.d.ts +41 -0
  34. package/dist/types/commerce-price.d.ts +22 -0
  35. package/dist/types/commerce-shipping.d.ts +28 -0
  36. package/dist/types/css.d.ts +5 -0
  37. package/dist/types/cwv.d.ts +10 -0
  38. package/dist/types/data-layer-normalize.d.ts +1 -0
  39. package/dist/types/debug.d.ts +23 -0
  40. package/dist/types/define.d.ts +87 -0
  41. package/dist/types/devtools.d.ts +32 -0
  42. package/dist/types/dom-trigger.d.ts +3 -0
  43. package/dist/types/editor/api.d.ts +37 -0
  44. package/dist/types/editor/artifacts.d.ts +15 -0
  45. package/dist/types/editor/command-runtime.d.ts +48 -0
  46. package/dist/types/editor/controller.d.ts +97 -0
  47. package/dist/types/editor/device-preview.d.ts +23 -0
  48. package/dist/types/editor/index.d.ts +9 -0
  49. package/dist/types/editor/operator.d.ts +39 -0
  50. package/dist/types/editor/picker.d.ts +23 -0
  51. package/dist/types/editor/selector.d.ts +2 -0
  52. package/dist/types/editor/types.d.ts +55 -0
  53. package/dist/types/editor/view-kit.d.ts +33 -0
  54. package/dist/types/editor/view.d.ts +5 -0
  55. package/dist/types/editor-bootstrap.d.ts +37 -0
  56. package/dist/types/exclusion-groups.d.ts +59 -0
  57. package/dist/types/exposure-signals.d.ts +7 -0
  58. package/dist/types/flags.d.ts +65 -0
  59. package/dist/types/goals.d.ts +16 -0
  60. package/dist/types/guards.d.ts +39 -0
  61. package/dist/types/handover.d.ts +10 -0
  62. package/dist/types/hash.d.ts +19 -0
  63. package/dist/types/heatmap.d.ts +8 -0
  64. package/dist/types/hideflicker.d.ts +15 -0
  65. package/dist/types/hydration.d.ts +11 -0
  66. package/dist/types/index.d.ts +144 -0
  67. package/dist/types/js.d.ts +6 -0
  68. package/dist/types/module.d.ts +4 -0
  69. package/dist/types/money.d.ts +14 -0
  70. package/dist/types/mutate.d.ts +34 -0
  71. package/dist/types/observer-mute.d.ts +3 -0
  72. package/dist/types/pii-keys.d.ts +1 -0
  73. package/dist/types/prerequisites.d.ts +12 -0
  74. package/dist/types/qa-assistant-state.d.ts +68 -0
  75. package/dist/types/qa-assistant-view.d.ts +6 -0
  76. package/dist/types/qa-assistant.d.ts +9 -0
  77. package/dist/types/qa-toolbar.d.ts +19 -0
  78. package/dist/types/react/index.d.ts +84 -0
  79. package/dist/types/reassert-sentinel.d.ts +6 -0
  80. package/dist/types/router.d.ts +9 -0
  81. package/dist/types/runtime-tools.d.ts +50 -0
  82. package/dist/types/runtime.d.ts +22 -0
  83. package/dist/types/safe-regex.d.ts +6 -0
  84. package/dist/types/sanitize.d.ts +5 -0
  85. package/dist/types/semantic.d.ts +7 -0
  86. package/dist/types/shopify-cart-events.d.ts +7 -0
  87. package/dist/types/shopify-cart.d.ts +62 -0
  88. package/dist/types/signals.d.ts +31 -0
  89. package/dist/types/surface-signals.d.ts +6 -0
  90. package/dist/types/targeting-diagnostics.d.ts +5 -0
  91. package/dist/types/targeting.d.ts +50 -0
  92. package/dist/types/test-fixtures/commerce.d.ts +12 -0
  93. package/dist/types/track.d.ts +79 -0
  94. package/dist/types/types.d.ts +859 -0
  95. package/dist/types/wait.d.ts +7 -0
  96. package/package.json +74 -0
  97. package/src/analytics.ts +146 -0
  98. package/src/antiflicker.test.ts +127 -0
  99. package/src/antiflicker.ts +147 -0
  100. package/src/assignment-store.test.ts +171 -0
  101. package/src/assignment-store.ts +208 -0
  102. package/src/audit.test.ts +17 -0
  103. package/src/audit.ts +362 -0
  104. package/src/bucket.test.ts +65 -0
  105. package/src/bucket.ts +18 -0
  106. package/src/bucketing-cleanup.test.ts +30 -0
  107. package/src/bucketing-cleanup.ts +72 -0
  108. package/src/bucketing-parity.test.ts +41 -0
  109. package/src/commerce-analytics-lifecycle.test.ts +1416 -0
  110. package/src/commerce-config-lifecycle.test.ts +274 -0
  111. package/src/commerce-epoch-lifecycle.test.ts +62 -0
  112. package/src/commerce-gift.test.ts +1293 -0
  113. package/src/commerce-gift.ts +979 -0
  114. package/src/commerce-offers-display.test.ts +154 -0
  115. package/src/commerce-price.test.ts +1145 -0
  116. package/src/commerce-price.ts +941 -0
  117. package/src/commerce-revocation-lifecycle.test.ts +78 -0
  118. package/src/commerce-shipping.test.ts +630 -0
  119. package/src/commerce-shipping.ts +447 -0
  120. package/src/config-fetch.test.ts +325 -0
  121. package/src/css.ts +54 -0
  122. package/src/cwv.test.ts +95 -0
  123. package/src/cwv.ts +129 -0
  124. package/src/data-layer-normalize.ts +21 -0
  125. package/src/debug.test.ts +83 -0
  126. package/src/debug.ts +138 -0
  127. package/src/define.test.ts +327 -0
  128. package/src/define.ts +208 -0
  129. package/src/devtools.ts +582 -0
  130. package/src/dom-trigger.test.ts +70 -0
  131. package/src/dom-trigger.ts +55 -0
  132. package/src/editor/api.test.ts +154 -0
  133. package/src/editor/api.ts +185 -0
  134. package/src/editor/artifacts.test.ts +57 -0
  135. package/src/editor/artifacts.ts +115 -0
  136. package/src/editor/command-runtime.test.ts +225 -0
  137. package/src/editor/command-runtime.ts +572 -0
  138. package/src/editor/controller.test.ts +371 -0
  139. package/src/editor/controller.ts +596 -0
  140. package/src/editor/device-preview.test.ts +60 -0
  141. package/src/editor/device-preview.ts +120 -0
  142. package/src/editor/index.test.ts +161 -0
  143. package/src/editor/index.ts +169 -0
  144. package/src/editor/operator.test.ts +148 -0
  145. package/src/editor/operator.ts +256 -0
  146. package/src/editor/picker.test.ts +58 -0
  147. package/src/editor/picker.ts +152 -0
  148. package/src/editor/selector.test.ts +44 -0
  149. package/src/editor/selector.ts +110 -0
  150. package/src/editor/types.ts +92 -0
  151. package/src/editor/view-kit.ts +162 -0
  152. package/src/editor/view.test.ts +535 -0
  153. package/src/editor/view.ts +1395 -0
  154. package/src/editor-bootstrap.test.ts +116 -0
  155. package/src/editor-bootstrap.ts +213 -0
  156. package/src/event-schema-contract.test.ts +35 -0
  157. package/src/exclusion-groups.test.ts +383 -0
  158. package/src/exclusion-groups.ts +270 -0
  159. package/src/exposure-signals.test.ts +182 -0
  160. package/src/exposure-signals.ts +110 -0
  161. package/src/flags.test.ts +322 -0
  162. package/src/flags.ts +201 -0
  163. package/src/goals.test.ts +42 -0
  164. package/src/goals.ts +200 -0
  165. package/src/guards.test.ts +249 -0
  166. package/src/guards.ts +250 -0
  167. package/src/handover-cache-order.test.ts +32 -0
  168. package/src/handover.test.ts +349 -0
  169. package/src/handover.ts +309 -0
  170. package/src/hash.ts +214 -0
  171. package/src/heatmap.test.ts +305 -0
  172. package/src/heatmap.ts +373 -0
  173. package/src/hideflicker.ts +21 -0
  174. package/src/hydration.test.ts +252 -0
  175. package/src/hydration.ts +203 -0
  176. package/src/index.ts +7513 -0
  177. package/src/init-empty.test.ts +5572 -0
  178. package/src/js.test.ts +26 -0
  179. package/src/js.ts +61 -0
  180. package/src/module.ts +50 -0
  181. package/src/money.test.ts +35 -0
  182. package/src/money.ts +53 -0
  183. package/src/mutate.test.ts +304 -0
  184. package/src/mutate.ts +469 -0
  185. package/src/observer-mute.test.ts +88 -0
  186. package/src/observer-mute.ts +45 -0
  187. package/src/page-trigger.test.ts +84 -0
  188. package/src/personalization.test.ts +68 -0
  189. package/src/pii-keys.ts +17 -0
  190. package/src/prerequisites.test.ts +39 -0
  191. package/src/prerequisites.ts +94 -0
  192. package/src/qa-assistant-state.test.ts +471 -0
  193. package/src/qa-assistant-state.ts +505 -0
  194. package/src/qa-assistant-view.test.ts +185 -0
  195. package/src/qa-assistant-view.ts +768 -0
  196. package/src/qa-assistant.ts +40 -0
  197. package/src/qa-toolbar.ts +444 -0
  198. package/src/react/index.test.tsx +177 -0
  199. package/src/react/index.tsx +252 -0
  200. package/src/reassert-sentinel.test.ts +314 -0
  201. package/src/reassert-sentinel.ts +191 -0
  202. package/src/router.test.ts +78 -0
  203. package/src/router.ts +92 -0
  204. package/src/runtime-tools.test.ts +112 -0
  205. package/src/runtime-tools.ts +403 -0
  206. package/src/runtime.test.ts +217 -0
  207. package/src/runtime.ts +268 -0
  208. package/src/safe-regex.ts +35 -0
  209. package/src/sanitize.ts +34 -0
  210. package/src/semantic.ts +245 -0
  211. package/src/shopify-cart-events.test.ts +76 -0
  212. package/src/shopify-cart-events.ts +115 -0
  213. package/src/shopify-cart.test.ts +2823 -0
  214. package/src/shopify-cart.ts +1256 -0
  215. package/src/signals.ts +226 -0
  216. package/src/surface-signals.test.ts +83 -0
  217. package/src/surface-signals.ts +165 -0
  218. package/src/targeting-diagnostics.ts +560 -0
  219. package/src/targeting.detailed.test.ts +443 -0
  220. package/src/targeting.test.ts +1054 -0
  221. package/src/targeting.ts +1024 -0
  222. package/src/test-fixtures/commerce.ts +65 -0
  223. package/src/track.test.ts +817 -0
  224. package/src/track.ts +519 -0
  225. package/src/types.ts +991 -0
  226. package/src/wait.test.ts +96 -0
  227. package/src/wait.ts +238 -0
@@ -0,0 +1,92 @@
1
+ import type { Mutation } from "../types";
2
+
3
+ export type ActiveEditorSession = {
4
+ sid: string;
5
+ bearer: string;
6
+ expiresAt: string;
7
+ shopId: string;
8
+ experimentId: string;
9
+ experimentName?: string | null;
10
+ initialVariationId: string;
11
+ targetUrl: string;
12
+ targetOrigin: string;
13
+ variations: Array<{ id: string; name?: string | null; slug?: string | null }>;
14
+ };
15
+
16
+ export type EditorArtifacts = {
17
+ mutations: Mutation[];
18
+ customCss: string;
19
+ customJs: string;
20
+ };
21
+
22
+ export type EditorVariation = {
23
+ id: string;
24
+ name: string;
25
+ artifactHash: string;
26
+ reviewStatus: string | null;
27
+ };
28
+
29
+ export type EditorBrowserCommand =
30
+ | "navigate"
31
+ | "reload"
32
+ | "back"
33
+ | "forward"
34
+ | "click"
35
+ | "type"
36
+ | "wait_for"
37
+ | "snapshot"
38
+ | "screenshot"
39
+ | "eval_readonly"
40
+ | "console_logs"
41
+ | "network_logs"
42
+ | "network_probe"
43
+ | "current_url"
44
+ | "select_element"
45
+ | "apply_artifacts";
46
+
47
+ export type ClaimedEditorCommand = {
48
+ commandId: string;
49
+ command: EditorBrowserCommand;
50
+ args: Record<string, unknown>;
51
+ expiresAt: string | null;
52
+ };
53
+
54
+ export type EditorSaveState = "idle" | "saving" | "saved" | "conflict" | "error";
55
+
56
+ export type EditorDeviceState = "closed" | "loading" | "active" | "blocked";
57
+
58
+ export type EditorState = {
59
+ variation: EditorVariation | null;
60
+ artifacts: EditorArtifacts;
61
+ artifactsEnabled: boolean;
62
+ pickerActive: boolean;
63
+ selectedElement: Element | null;
64
+ selectedSelector: string | null;
65
+ saveState: EditorSaveState;
66
+ saveMessage: string | null;
67
+ dock: "top" | "bottom";
68
+ canUndo: boolean;
69
+ canRedo: boolean;
70
+ jsApplied: boolean;
71
+ reloadRequired: boolean;
72
+ deviceState: EditorDeviceState;
73
+ };
74
+
75
+ export const EMPTY_EDITOR_ARTIFACTS: EditorArtifacts = {
76
+ mutations: [],
77
+ customCss: "",
78
+ customJs: "",
79
+ };
80
+
81
+ export function cloneArtifacts(artifacts: EditorArtifacts): EditorArtifacts {
82
+ return {
83
+ mutations: artifacts.mutations.map((mutation) => ({
84
+ ...mutation,
85
+ attribute: mutation.attribute ? { ...mutation.attribute } : undefined,
86
+ attributes: mutation.attributes ? { ...mutation.attributes } : undefined,
87
+ styles: mutation.styles ? { ...mutation.styles } : undefined,
88
+ })),
89
+ customCss: artifacts.customCss,
90
+ customJs: artifacts.customJs,
91
+ };
92
+ }
@@ -0,0 +1,162 @@
1
+ // Shared visual kit for the on-site editor chrome. Values are the canonical
2
+ // Apex Design System dark tokens (docs/design-system/tokens) redeclared on
3
+ // :host because the shadow root resets inheritance with all:initial.
4
+
5
+ export const ICONS = {
6
+ pointer: "M4 3l7.6 18 2.3-7.4L21 11.5zM13.9 13.9L19 19",
7
+ undo: "M9 14L4 9l5-5M4 9h10.5a5.5 5.5 0 015.5 5.5v0a5.5 5.5 0 01-5.5 5.5H11",
8
+ redo: "M15 14l5-5-5-5M20 9H9.5A5.5 5.5 0 004 14.5v0A5.5 5.5 0 009.5 20H13",
9
+ monitor: "M3 4h18a1 1 0 011 1v11a1 1 0 01-1 1H3a1 1 0 01-1-1V5a1 1 0 011-1zM8 21h8M12 17v4",
10
+ tablet: "M6 2h12a2 2 0 012 2v16a2 2 0 01-2 2H6a2 2 0 01-2-2V4a2 2 0 012-2zM12 18h.01",
11
+ phone: "M8 2h8a2 2 0 012 2v16a2 2 0 01-2 2H8a2 2 0 01-2-2V4a2 2 0 012-2zM11 18h2",
12
+ wifiOff: "M2 2l20 20M8.5 16.5a5 5 0 015.6-1M5 12.5a10 10 0 015.2-2.7M2 8.8a15 15 0 014.2-2.5M16.6 6.6A15 15 0 0122 8.8M12 20h.01",
13
+ braces: "M8 3H7a2 2 0 00-2 2v4a2 2 0 01-2 2 2 2 0 012 2v4a2 2 0 002 2h1M16 3h1a2 2 0 012 2v4a2 2 0 002 2 2 2 0 00-2 2v4a2 2 0 01-2 2h-1",
14
+ collapse: "M9 3v18M3 5a2 2 0 012-2h14a2 2 0 012 2v14a2 2 0 01-2 2H5a2 2 0 01-2-2zM13 10l3 2-3 2",
15
+ history: "M3 12a9 9 0 113 6.7M3 12H1.5M3 12l-1.8 2M12 7v5l3.5 2",
16
+ send: "M22 2L11 13M22 2l-7 20-4-9-9-4z",
17
+ stop: "M6 6h12v12H6z",
18
+ cursorBox: "M3 3h8M3 3v8M21 13v8h-8M9 9l7 7M16 9v7h-7",
19
+ check: "M5 13l4 4L19 7",
20
+ x: "M18 6L6 18M6 6l12 12",
21
+ chevD: "M6 9l6 6 6-6",
22
+ chevR: "M9 6l6 6-6 6",
23
+ refresh: "M3 12a9 9 0 0114.5-7L21 8M21 3v5h-5M21 12a9 9 0 01-14.5 7L3 16M3 21v-5h5",
24
+ external: "M15 3h6v6M21 3l-9 9M10 5H5a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2v-5",
25
+ code: "M16 18l6-6-6-6M8 6l-6 6 6 6",
26
+ clock: "M12 22a10 10 0 100-20 10 10 0 000 20zM12 7v5l3 2",
27
+ eye: "M2 12s4-7 10-7 10 7 10 7-4 7-10 7-10-7-10-7zM12 15a3 3 0 100-6 3 3 0 000 6z",
28
+ alert: "M10.3 3.9L1.8 18a2 2 0 001.7 3h17a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0zM12 9v4M12 17h.01",
29
+ globe: "M12 2a10 10 0 100 20 10 10 0 000-20zM2 12h20M12 2a15 15 0 010 20M12 2a15 15 0 000 20",
30
+ play: "M6 4l14 8-14 8z",
31
+ dot: "M12 12h.01",
32
+ } as const;
33
+
34
+ export type IconName = keyof typeof ICONS;
35
+
36
+ export function icon(name: IconName, size = 14, extra = ""): string {
37
+ return `<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" ${extra}><path d="${ICONS[name]}"/></svg>`;
38
+ }
39
+
40
+ let operatorMarkId = 0;
41
+
42
+ // The Apex Operator "O." monogram — stencil-cut O with a purple accent chip.
43
+ export function operatorMark(size = 16, color = "#fff"): string {
44
+ const id = `apex-op-mark-${++operatorMarkId}`;
45
+ return `<svg width="${size}" height="${size}" viewBox="0 0 120 120" fill="none" aria-hidden="true" style="flex-shrink:0">
46
+ <defs><mask id="${id}"><rect width="120" height="120" fill="#fff"/><rect x="0" y="68" width="120" height="6" fill="#000"/></mask></defs>
47
+ <path d="M60 14 C92 14 106 36 106 60 C106 84 92 106 60 106 C28 106 14 84 14 60 C14 36 28 14 60 14 Z M60 38 C46 38 38 48 38 60 C38 72 46 82 60 82 C74 82 82 72 82 60 C82 48 74 38 60 38 Z" fill="${color}" fill-rule="evenodd" mask="url(#${id})"/>
48
+ <rect x="92" y="92" width="14" height="14" rx="2" fill="#5B29FF"/>
49
+ </svg>`;
50
+ }
51
+
52
+ export function esc(value: string): string {
53
+ return value
54
+ .replace(/&/g, "&amp;")
55
+ .replace(/</g, "&lt;")
56
+ .replace(/>/g, "&gt;")
57
+ .replace(/"/g, "&quot;");
58
+ }
59
+
60
+ export const KIT_CSS = `
61
+ :host {
62
+ --bg0:#08080A;--bg1:#0A0A0C;--raised:#141419;--raised-hi:#1A1A21;--inset:#0B0B0E;
63
+ --border:rgba(255,255,255,0.06);--border-hi:rgba(255,255,255,0.10);--border-px:rgba(255,255,255,0.14);
64
+ --text1:#FAFAFA;--text2:rgba(255,255,255,0.66);--text3:rgba(255,255,255,0.42);--text4:rgba(255,255,255,0.26);
65
+ --purple500:#5B29FF;--purple400:#7C54FF;--purple300:#9B6FFF;--purple200:#C8B4FF;
66
+ --purple-soft:rgba(91,41,255,0.14);--purple-bd:rgba(124,84,255,0.34);
67
+ --positive:#3DD68C;--warning:#FACC15;--negative:#EB5252;--negative-soft:#F39797;
68
+ all:initial;font-family:Inter,system-ui,sans-serif;color:var(--text1);letter-spacing:0;
69
+ position:fixed;inset:0;z-index:2147483647;pointer-events:none;font-size:12.5px;line-height:1.5;
70
+ }
71
+ *{box-sizing:border-box;letter-spacing:0;margin:0;padding:0}
72
+ button,input,select,textarea{font:inherit;color:inherit;font-family:inherit}
73
+ button{cursor:pointer;background:none;border:none}
74
+ button:disabled{cursor:not-allowed}
75
+ :is(button,textarea,input,a):focus-visible{outline:2px solid var(--purple400);outline-offset:2px}
76
+ @keyframes ee-spin{to{transform:rotate(360deg)}}
77
+ @keyframes ee-pulse{0%{transform:scale(0.7);opacity:0.9}100%{transform:scale(1.6);opacity:0}}
78
+ @keyframes ee-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
79
+ .ee-in{animation:ee-in 160ms ease-out}
80
+ .spin{animation:ee-spin 1s linear infinite}
81
+ @media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:0.01ms!important;animation-iteration-count:1!important;transition-duration:0.01ms!important}}
82
+
83
+ /* Buttons */
84
+ .btn{display:inline-flex;align-items:center;gap:7px;justify-content:center;padding:7px 12px;font-size:13px;font-weight:550;border-radius:8px;border:1px solid transparent;line-height:1.2;white-space:nowrap;transition:background 120ms,border-color 120ms,color 120ms;pointer-events:auto}
85
+ .btn.sm{padding:5px 10px;font-size:12px}
86
+ .btn:disabled{opacity:0.45}
87
+ .btn.primary{background:var(--purple500);color:#fff;border-color:rgba(255,255,255,0.14)}
88
+ .btn.soft{background:var(--purple-soft);color:var(--purple200);border-color:var(--purple-bd)}
89
+ .btn.ghost{background:transparent;color:var(--text2);border-color:var(--border)}
90
+ .btn.ghost:hover{background:var(--raised-hi);color:var(--text1)}
91
+ .btn.bare{background:transparent;color:var(--text2);border-color:transparent}
92
+ .btn.danger{background:rgba(235,82,82,0.14);color:var(--negative-soft);border-color:rgba(235,82,82,0.3)}
93
+ .iconbtn{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border-radius:8px;border:1px solid transparent;background:transparent;color:var(--text2);flex-shrink:0;transition:background 120ms,color 120ms;pointer-events:auto}
94
+ .iconbtn:hover{background:var(--raised-hi);color:var(--text1)}
95
+ .iconbtn.active{background:var(--purple-soft);color:var(--purple200);border-color:var(--purple-bd)}
96
+ .iconbtn:disabled{opacity:0.4}
97
+ .iconbtn.xs{width:22px;height:22px}
98
+
99
+ /* Status dot */
100
+ .dot{position:relative;width:7px;height:7px;flex-shrink:0;display:inline-block}
101
+ .dot i{position:absolute;inset:0;border-radius:50%}
102
+ .dot.ok i{background:var(--positive)}.dot.warn i{background:var(--warning)}.dot.err i{background:var(--negative)}.dot.purple i{background:var(--purple300)}
103
+ .dot b{position:absolute;inset:-3px;border-radius:50%;border:1px solid currentColor}
104
+ .dot.ok b{color:var(--positive)}.dot.warn b{color:var(--warning)}.dot.err b{color:var(--negative)}.dot.purple b{color:var(--purple300)}
105
+ .dot b{animation:ee-pulse 1.4s ease-out infinite}
106
+
107
+ /* Save chip */
108
+ .save-chip{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:550;padding:4px 9px;border-radius:7px;background:rgba(255,255,255,0.04);border:1px solid var(--border);white-space:nowrap}
109
+ .save-chip.unsaved{color:var(--warning)}
110
+ .save-chip.saving{color:var(--purple200)}
111
+ .save-chip.saved{color:var(--positive)}
112
+ .save-chip.failed,.save-chip.conflict{color:var(--negative-soft);background:rgba(235,82,82,0.10);border-color:rgba(235,82,82,0.25)}
113
+ .save-chip .retry{border:none;background:rgba(255,255,255,0.1);color:#fff;font-size:11.5px;font-weight:600;border-radius:5px;padding:2px 7px;margin-left:2px;pointer-events:auto}
114
+
115
+ /* Segmented control */
116
+ .seg{display:inline-flex;background:var(--inset);border-radius:8px;padding:2px;gap:2px;border:1px solid var(--border);pointer-events:auto}
117
+ .seg button{display:inline-flex;align-items:center;gap:6px;justify-content:center;padding:5px 11px;border-radius:6px;border:none;background:transparent;color:var(--text3);font-size:12px;font-weight:550;transition:background 120ms,color 120ms}
118
+ .seg button.sm{padding:4px 8px}
119
+ .seg button[aria-checked="true"]{background:var(--raised-hi);color:var(--text1);box-shadow:inset 0 0 0 1px var(--border-px)}
120
+
121
+ /* Pills & chips */
122
+ .draft-pill{display:inline-flex;align-items:center;gap:6px;padding:2px 8px;border-radius:999px;background:rgba(250,204,21,0.10);border:1px solid rgba(250,204,21,0.3);font-size:11px;font-weight:600;color:var(--warning);white-space:nowrap}
123
+ .session-chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:550;color:var(--warning);padding:4px 9px;border-radius:7px;border:1px solid rgba(250,204,21,0.35);background:rgba(250,204,21,0.08);white-space:nowrap;font-variant-numeric:tabular-nums}
124
+ .session-chip .extend{border:none;background:rgba(250,204,21,0.16);color:var(--warning);font-size:11.5px;font-weight:600;border-radius:5px;padding:2px 7px;pointer-events:auto}
125
+ .session-note{font-size:11px;color:var(--text4);white-space:nowrap}
126
+ .conn-chip{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:550;white-space:nowrap;color:var(--text3)}
127
+ .conn-chip.offline{color:var(--negative-soft)}
128
+ .conn-chip.connecting{color:var(--warning)}
129
+ .ctx-chip{display:inline-flex;align-items:center;gap:7px;max-width:100%;background:var(--purple-soft);border:1px solid var(--purple-bd);border-radius:8px;padding:5px 8px;font-size:11.5px;color:var(--purple200);font-weight:550}
130
+ .ctx-chip .name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
131
+ .ctx-chip .replace{border:none;background:rgba(255,255,255,0.08);color:var(--text2);font-size:10.5px;font-weight:600;border-radius:5px;padding:2px 7px;pointer-events:auto}
132
+ .ctx-chip .clear{border:none;background:none;color:var(--text3);padding:2px;display:inline-flex;pointer-events:auto}
133
+
134
+ /* Fields */
135
+ .field{width:100%;background:var(--inset);color:var(--text1);border:1px solid var(--border-hi);border-radius:8px;padding:8px 10px;font-size:12.5px;line-height:1.5;outline:none;resize:vertical;pointer-events:auto}
136
+ .field::placeholder{color:rgba(255,255,255,0.28)}
137
+ .field.code{white-space:pre;font-variant-numeric:tabular-nums;min-height:150px}
138
+ .flabel{display:block;font-size:11.5px;font-weight:550;color:var(--text3);margin-bottom:5px}
139
+ .fhint{display:block;font-size:11px;color:var(--text4);margin-top:4px}
140
+
141
+ /* Banners */
142
+ .banner{display:flex;align-items:center;gap:9px;padding:8px 12px;border-radius:10px;color:var(--text1);font-size:12.5px;box-shadow:0 12px 32px rgba(0,0,0,0.4);pointer-events:auto;max-width:560px}
143
+ .banner .body{flex:1;min-width:0}
144
+ .banner.info{background:linear-gradient(0deg,rgba(91,41,255,0.16),rgba(91,41,255,0.16)),var(--bg1);border:1px solid var(--purple-bd)}
145
+ .banner.info svg{color:var(--purple200)}
146
+ .banner.warn{background:linear-gradient(0deg,rgba(250,204,21,0.10),rgba(250,204,21,0.10)),var(--bg1);border:1px solid rgba(250,204,21,0.35)}
147
+ .banner.warn svg{color:var(--warning)}
148
+ .banner.error{background:linear-gradient(0deg,rgba(235,82,82,0.12),rgba(235,82,82,0.12)),var(--bg1);border:1px solid rgba(235,82,82,0.35)}
149
+ .banner.error svg{color:var(--negative-soft)}
150
+
151
+ /* Modal */
152
+ .modal-backdrop{position:fixed;inset:0;z-index:300;display:flex;align-items:center;justify-content:center;background:rgba(5,5,8,0.55);backdrop-filter:blur(3px);pointer-events:auto}
153
+ .modal{width:430px;max-width:calc(100vw - 40px);background:var(--bg1);border:1px solid var(--border-px);border-radius:14px;box-shadow:0 32px 80px rgba(0,0,0,0.55);overflow:hidden;color:var(--text1)}
154
+ .modal .m-head{display:flex;gap:10px;align-items:flex-start;padding:18px 18px 0}
155
+ .modal .m-icon{width:30px;height:30px;border-radius:8px;background:rgba(255,255,255,0.05);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;flex-shrink:0}
156
+ .modal .m-icon.warn{color:var(--warning)}.modal .m-icon.purple{color:var(--purple300)}.modal .m-icon.ok{color:var(--positive)}
157
+ .modal .m-title{font-size:15px;font-weight:600;letter-spacing:-0.015em;padding-top:4px}
158
+ .modal .m-body{padding:12px 18px 4px;font-size:13px;line-height:1.6;color:var(--text2)}
159
+ .modal .m-body p{margin:0}
160
+ .modal .m-body p+p{margin-top:10px}
161
+ .modal .m-actions{display:flex;justify-content:flex-end;gap:8px;padding:14px 18px 18px}
162
+ `;