@volter/twin-stripe 0.1.1 → 2.0.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 (219) hide show
  1. package/README.md +64 -27
  2. package/client/dashboard-api.ts +286 -0
  3. package/client/stripe-mirror.css +272 -159
  4. package/client/stripe-mirror.tsx +1384 -541
  5. package/dist/client/dashboard-api.d.ts +107 -0
  6. package/dist/client/dashboard-api.js +238 -0
  7. package/dist/client/dashboard-api.ts +286 -0
  8. package/dist/client/stripe-mirror.bundle.js +236 -0
  9. package/dist/client/stripe-mirror.css +275 -0
  10. package/dist/client/stripe-mirror.d.ts +134 -0
  11. package/dist/client/stripe-mirror.js +823 -0
  12. package/dist/client/stripe-mirror.tsx +1534 -0
  13. package/dist/src/cli.d.ts +2 -0
  14. package/dist/src/cli.js +39 -0
  15. package/dist/src/generated/events.gen.json +1 -0
  16. package/dist/src/generated/surface.gen.json +1 -0
  17. package/dist/src/generated/ui.gen.json +1 -0
  18. package/dist/src/index.d.ts +14 -0
  19. package/dist/src/index.js +73 -0
  20. package/dist/src/manifest.d.ts +2 -0
  21. package/dist/src/manifest.js +1065 -0
  22. package/dist/src/screens/checkout.d.ts +31 -0
  23. package/dist/src/screens/checkout.js +241 -0
  24. package/dist/src/screens/consent-skin.d.ts +4 -0
  25. package/dist/src/screens/consent-skin.js +18 -0
  26. package/dist/src/screens/financial-connections.d.ts +5 -0
  27. package/dist/src/screens/financial-connections.js +90 -0
  28. package/dist/src/screens/identity.d.ts +5 -0
  29. package/dist/src/screens/identity.js +86 -0
  30. package/dist/src/screens/industries.d.ts +1 -0
  31. package/dist/src/screens/industries.js +267 -0
  32. package/dist/src/screens/onboarding.d.ts +13 -0
  33. package/dist/src/screens/onboarding.js +225 -0
  34. package/dist/src/screens/portal.d.ts +5 -0
  35. package/dist/src/screens/portal.js +214 -0
  36. package/dist/src/screens/public-details.d.ts +5 -0
  37. package/dist/src/screens/public-details.js +90 -0
  38. package/dist/src/semantics/after-payment.d.ts +22 -0
  39. package/dist/src/semantics/after-payment.js +93 -0
  40. package/dist/src/semantics/apps-secrets.d.ts +2 -0
  41. package/dist/src/semantics/apps-secrets.js +54 -0
  42. package/dist/src/semantics/balance.d.ts +11 -0
  43. package/dist/src/semantics/balance.js +195 -0
  44. package/dist/src/semantics/billing.d.ts +2 -0
  45. package/dist/src/semantics/billing.js +220 -0
  46. package/dist/src/semantics/charges.d.ts +28 -0
  47. package/dist/src/semantics/charges.js +201 -0
  48. package/dist/src/semantics/checkout.d.ts +15 -0
  49. package/dist/src/semantics/checkout.js +303 -0
  50. package/dist/src/semantics/connect.d.ts +5 -0
  51. package/dist/src/semantics/connect.js +476 -0
  52. package/dist/src/semantics/coupons.d.ts +6 -0
  53. package/dist/src/semantics/coupons.js +92 -0
  54. package/dist/src/semantics/credit-notes.d.ts +2 -0
  55. package/dist/src/semantics/credit-notes.js +172 -0
  56. package/dist/src/semantics/customers.d.ts +6 -0
  57. package/dist/src/semantics/customers.js +429 -0
  58. package/dist/src/semantics/disputes.d.ts +2 -0
  59. package/dist/src/semantics/disputes.js +51 -0
  60. package/dist/src/semantics/entitlements.d.ts +2 -0
  61. package/dist/src/semantics/entitlements.js +95 -0
  62. package/dist/src/semantics/ephemeral-keys.d.ts +2 -0
  63. package/dist/src/semantics/ephemeral-keys.js +34 -0
  64. package/dist/src/semantics/files.d.ts +2 -0
  65. package/dist/src/semantics/files.js +125 -0
  66. package/dist/src/semantics/invoices.d.ts +18 -0
  67. package/dist/src/semantics/invoices.js +541 -0
  68. package/dist/src/semantics/issuing.d.ts +13 -0
  69. package/dist/src/semantics/issuing.js +570 -0
  70. package/dist/src/semantics/ledger.d.ts +54 -0
  71. package/dist/src/semantics/ledger.js +181 -0
  72. package/dist/src/semantics/payment-intents.d.ts +18 -0
  73. package/dist/src/semantics/payment-intents.js +404 -0
  74. package/dist/src/semantics/payment-links.d.ts +2 -0
  75. package/dist/src/semantics/payment-links.js +133 -0
  76. package/dist/src/semantics/payment-methods.d.ts +20 -0
  77. package/dist/src/semantics/payment-methods.js +138 -0
  78. package/dist/src/semantics/plans.d.ts +5 -0
  79. package/dist/src/semantics/plans.js +121 -0
  80. package/dist/src/semantics/platform.d.ts +9 -0
  81. package/dist/src/semantics/platform.js +206 -0
  82. package/dist/src/semantics/products.d.ts +2 -0
  83. package/dist/src/semantics/products.js +140 -0
  84. package/dist/src/semantics/radar.d.ts +2 -0
  85. package/dist/src/semantics/radar.js +83 -0
  86. package/dist/src/semantics/refunds.d.ts +9 -0
  87. package/dist/src/semantics/refunds.js +195 -0
  88. package/dist/src/semantics/renewals.d.ts +47 -0
  89. package/dist/src/semantics/renewals.js +251 -0
  90. package/dist/src/semantics/setup-intents.d.ts +2 -0
  91. package/dist/src/semantics/setup-intents.js +84 -0
  92. package/dist/src/semantics/shared.d.ts +78 -0
  93. package/dist/src/semantics/shared.js +192 -0
  94. package/dist/src/semantics/subscription-schedules.d.ts +2 -0
  95. package/dist/src/semantics/subscription-schedules.js +119 -0
  96. package/dist/src/semantics/subscriptions.d.ts +11 -0
  97. package/dist/src/semantics/subscriptions.js +605 -0
  98. package/dist/src/semantics/tax.d.ts +2 -0
  99. package/dist/src/semantics/tax.js +197 -0
  100. package/dist/src/semantics/terminal.d.ts +5 -0
  101. package/dist/src/semantics/terminal.js +182 -0
  102. package/dist/src/semantics/test-clocks.d.ts +6 -0
  103. package/dist/src/semantics/test-clocks.js +73 -0
  104. package/dist/src/semantics/tokens.d.ts +4 -0
  105. package/dist/src/semantics/tokens.js +44 -0
  106. package/dist/src/semantics/transfers.d.ts +2 -0
  107. package/dist/src/semantics/transfers.js +154 -0
  108. package/dist/src/semantics/treasury.d.ts +2 -0
  109. package/dist/src/semantics/treasury.js +377 -0
  110. package/dist/src/semantics/webhook-endpoints.d.ts +3 -0
  111. package/dist/src/semantics/webhook-endpoints.js +85 -0
  112. package/dist/src/stripe-budget.d.ts +55 -0
  113. package/dist/src/stripe-budget.js +155 -0
  114. package/dist/src/stripe-capabilities.d.ts +3 -0
  115. package/dist/src/stripe-capabilities.js +5052 -0
  116. package/dist/src/stripe-conformance.d.ts +41 -0
  117. package/dist/src/stripe-conformance.js +96 -0
  118. package/dist/src/stripe-connector.d.ts +161 -0
  119. package/dist/src/stripe-connector.js +414 -0
  120. package/dist/src/stripe-emit.d.ts +2 -0
  121. package/dist/src/stripe-emit.js +145 -0
  122. package/dist/src/stripe-events.d.ts +93 -0
  123. package/dist/src/stripe-events.js +388 -0
  124. package/dist/src/stripe-js.d.ts +4 -0
  125. package/dist/src/stripe-js.js +70 -0
  126. package/dist/src/stripe-mirror-ui.d.ts +15 -0
  127. package/dist/src/stripe-mirror-ui.js +87 -0
  128. package/dist/src/stripe-params.d.ts +3 -0
  129. package/dist/src/stripe-params.js +43 -0
  130. package/dist/src/stripe-perform-harness.d.ts +9 -0
  131. package/dist/src/stripe-perform-harness.js +26 -0
  132. package/dist/src/stripe-server.d.ts +33 -0
  133. package/dist/src/stripe-server.js +326 -0
  134. package/dist/src/stripe-shared.d.ts +106 -0
  135. package/dist/src/stripe-shared.js +273 -0
  136. package/dist/src/stripe-twin.d.ts +155 -0
  137. package/dist/src/stripe-twin.js +1226 -0
  138. package/dist/src/stripe-ui-conformance.d.ts +5 -0
  139. package/dist/src/stripe-ui-conformance.js +79 -0
  140. package/dist/src/stripe-ui-structure.d.ts +3 -0
  141. package/dist/src/stripe-ui-structure.js +168 -0
  142. package/dist/src/stripe-version.d.ts +10 -0
  143. package/dist/src/stripe-version.js +285 -0
  144. package/dist/test-fixtures/stripe-known-deviations.json +105 -0
  145. package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +14 -0
  146. package/dist/test-fixtures/stripe-openapi-operations.json +4717 -0
  147. package/dist/test-fixtures/stripe-schemas.SOURCE.md +35 -0
  148. package/dist/test-fixtures/stripe-schemas.json +3740 -0
  149. package/package.json +18 -10
  150. package/src/cli.ts +7 -7
  151. package/src/generated/events.gen.json +1 -0
  152. package/src/generated/surface.gen.json +1 -0
  153. package/src/generated/ui.gen.json +1 -0
  154. package/src/index.ts +31 -9
  155. package/src/manifest.ts +1097 -0
  156. package/src/screens/checkout.tsx +252 -0
  157. package/src/screens/consent-skin.ts +20 -0
  158. package/src/screens/financial-connections.tsx +101 -0
  159. package/src/screens/identity.tsx +96 -0
  160. package/src/screens/industries.ts +267 -0
  161. package/src/screens/onboarding.tsx +243 -0
  162. package/src/screens/portal.tsx +218 -0
  163. package/src/screens/public-details.tsx +105 -0
  164. package/src/semantics/after-payment.ts +113 -0
  165. package/src/semantics/apps-secrets.ts +58 -0
  166. package/src/semantics/balance.ts +209 -0
  167. package/src/semantics/billing.ts +216 -0
  168. package/src/semantics/charges.ts +211 -0
  169. package/src/semantics/checkout.ts +297 -0
  170. package/src/semantics/connect.ts +471 -0
  171. package/src/semantics/coupons.ts +97 -0
  172. package/src/semantics/credit-notes.ts +168 -0
  173. package/src/semantics/customers.ts +432 -0
  174. package/src/semantics/disputes.ts +62 -0
  175. package/src/semantics/entitlements.ts +94 -0
  176. package/src/semantics/ephemeral-keys.ts +34 -0
  177. package/src/semantics/files.ts +143 -0
  178. package/src/semantics/invoices.ts +541 -0
  179. package/src/semantics/issuing.ts +585 -0
  180. package/src/semantics/ledger.ts +216 -0
  181. package/src/semantics/payment-intents.ts +420 -0
  182. package/src/semantics/payment-links.ts +148 -0
  183. package/src/semantics/payment-methods.ts +143 -0
  184. package/src/semantics/plans.ts +131 -0
  185. package/src/semantics/platform.ts +220 -0
  186. package/src/semantics/products.ts +154 -0
  187. package/src/semantics/radar.ts +85 -0
  188. package/src/semantics/refunds.ts +218 -0
  189. package/src/semantics/renewals.ts +274 -0
  190. package/src/semantics/setup-intents.ts +87 -0
  191. package/src/semantics/shared.ts +215 -0
  192. package/src/semantics/subscription-schedules.ts +129 -0
  193. package/src/semantics/subscriptions.ts +610 -0
  194. package/src/semantics/tax.ts +220 -0
  195. package/src/semantics/terminal.ts +195 -0
  196. package/src/semantics/test-clocks.ts +77 -0
  197. package/src/semantics/tokens.ts +52 -0
  198. package/src/semantics/transfers.ts +174 -0
  199. package/src/semantics/treasury.ts +383 -0
  200. package/src/semantics/webhook-endpoints.ts +87 -0
  201. package/src/stripe-budget.ts +4 -4
  202. package/src/stripe-capabilities.ts +1456 -222
  203. package/src/stripe-conformance.ts +6 -5
  204. package/src/stripe-connector.ts +68 -40
  205. package/src/stripe-emit.ts +14 -7
  206. package/src/stripe-events.ts +94 -36
  207. package/src/stripe-js.ts +70 -0
  208. package/src/stripe-mirror-ui.ts +28 -298
  209. package/src/stripe-params.ts +44 -0
  210. package/src/stripe-perform-harness.ts +29 -0
  211. package/src/stripe-server.ts +263 -38
  212. package/src/stripe-shared.ts +294 -0
  213. package/src/stripe-twin.ts +429 -5325
  214. package/src/stripe-ui-conformance.ts +70 -107
  215. package/src/stripe-ui-structure.ts +124 -348
  216. package/src/stripe-version.ts +278 -0
  217. package/test-fixtures/stripe-known-deviations.json +2 -7
  218. package/test-fixtures/stripe-openapi-operations.json +1188 -2855
  219. package/src/stripe-form.ts +0 -35
@@ -1,162 +1,275 @@
1
+ /* The Stripe Dashboard in test mode: white frame, left navigation, top search, list tables and detail pages. */
1
2
  :root {
2
- --bg: #f6f8fa; --panel: #fff; --ink: #1a1f36; --muted: #697386;
3
- --line: #e3e8ee; --brand: #635bff; --ok-bg: #e3f6ec; --ok: #138c50;
4
- --warn-bg: #fcf0e4; --warn: #b25e09; --bad-bg: #fce4e4; --bad: #c0392b;
3
+ --text: #414552;
4
+ --heading: #353a44;
5
+ --muted: #687385;
6
+ --faint: #87909f;
7
+ --border: #ebeef1;
8
+ --border-strong: #d5dbe1;
9
+ --hover: #f6f8fa;
10
+ --brand: #635bff;
11
+ --brand-dark: #5851ea;
12
+ --test: #f68a2f;
13
+ --danger: #df1b41;
14
+ --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Ubuntu, sans-serif;
15
+ --mono: "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
5
16
  }
6
17
  * { box-sizing: border-box; }
7
- body { margin: 0; font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; color: var(--ink); background: var(--bg); }
8
- .dash { height: 100vh; display: flex; flex-direction: column; }
9
-
10
- .topbar { display: flex; align-items: center; gap: 16px; padding: 0 20px; height: 56px; background: #0a2540; color: #fff; }
11
- .brand { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 16px; }
12
- .brand .dot { width: 14px; height: 14px; border-radius: 4px; background: var(--brand); }
13
- .brand .tag { font-size: 11px; font-weight: 600; background: rgba(255,255,255,.15); padding: 2px 8px; border-radius: 999px; }
14
- .topbar .search { flex: 1; max-width: 520px; background: rgba(255,255,255,.12); border: 0; color: #cdd6e4; padding: 7px 12px; border-radius: 7px; }
15
- .topbar .mode { margin-left: auto; font-size: 12px; font-weight: 600; color: #f6b73c; background: rgba(246,183,60,.15); padding: 4px 10px; border-radius: 999px; }
16
-
17
- .body { flex: 1; display: flex; min-height: 0; }
18
- .side { width: 220px; background: var(--panel); border-right: 1px solid var(--line); padding: 14px 10px; display: flex; flex-direction: column; gap: 2px; }
19
- .side button { text-align: left; border: 0; background: none; padding: 8px 12px; border-radius: 7px; color: var(--ink); cursor: pointer; font-size: 14px; }
20
- .side button:hover { background: var(--bg); }
21
- .side button.active { background: #ecebff; color: var(--brand); font-weight: 600; }
22
- .side button { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
23
- .side .nav-count { font-size: 11px; font-weight: 600; color: var(--muted); background: var(--bg); padding: 1px 7px; border-radius: 999px; }
24
- .side button.active .nav-count { background: #fff; color: var(--brand); }
25
-
26
- .content { flex: 1; min-width: 0; padding: 22px 26px; overflow: auto; }
27
- .content-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 16px; }
28
- .content-head h2 { margin: 0; font-size: 22px; }
29
- .content-head .count { color: var(--muted); font-weight: 600; }
30
- .error { background: var(--warn-bg); color: var(--warn); padding: 10px 14px; border-radius: 8px; margin-bottom: 14px; }
31
-
32
- .split { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 18px; align-items: start; }
33
- .list { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
34
- .list-row { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; border: 0; border-bottom: 1px solid var(--line); background: none; cursor: pointer; text-align: left; }
35
- .list-row:last-child { border-bottom: 0; }
36
- .list-row:hover { background: var(--bg); }
37
- .list-row.active { background: #f5f4ff; box-shadow: inset 3px 0 0 var(--brand); }
38
- .row-main { display: flex; flex-direction: column; min-width: 0; }
39
- .row-title { font-weight: 600; }
40
- .row-sub { color: var(--muted); font-size: 12px; }
41
- .empty { padding: 28px; text-align: center; color: var(--muted); }
42
-
43
- .detail { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 16px; position: sticky; top: 0; }
44
- .detail.empty { color: var(--muted); }
45
- .detail-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-bottom: 12px; border-bottom: 1px solid var(--line); margin-bottom: 12px; }
46
- .detail dl { margin: 0; display: flex; flex-direction: column; gap: 8px; }
47
- .detail .kv { display: grid; grid-template-columns: 130px 1fr; gap: 10px; }
48
- .detail dt { color: var(--muted); }
49
- .detail dd { margin: 0; word-break: break-word; }
50
-
51
- .pill { font-size: 12px; font-weight: 600; padding: 2px 9px; border-radius: 999px; background: #eef1f6; color: var(--muted); white-space: nowrap; text-transform: capitalize; }
52
- .pill.ok { background: var(--ok-bg); color: var(--ok); }
53
- .pill.warn { background: var(--warn-bg); color: var(--warn); }
54
- .pill.bad { background: var(--bad-bg); color: var(--bad); }
55
- .mono { font-family: "SF Mono", ui-monospace, Menlo, monospace; font-size: 12px; }
56
-
57
- /* Nested-object rendering — replaces the old "[object Object]" */
58
- .detail-block { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line); }
59
- .detail-block h4 { margin: 0 0 8px; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
60
- .nested { display: flex; flex-direction: column; gap: 3px; font-size: 13px; }
61
- .nested-line { display: flex; gap: 8px; align-items: baseline; }
62
- .nested-label { color: var(--muted); flex-shrink: 0; }
63
- .nested-label::after { content: ":"; }
64
- .nested-value { word-break: break-word; }
65
-
66
- /* Cross-reference links */
67
- .ref-inline { border: 0; background: none; padding: 0; color: var(--brand); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
68
- .ref-inline:hover { color: #4b45cc; }
69
- .ref-group { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 8px; }
70
- .ref-group:last-child { margin-bottom: 0; }
71
- .ref-group-label { font-size: 11px; font-weight: 600; color: var(--muted); width: 100%; }
72
- .ref-chip { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 1px; border: 1px solid var(--line); background: var(--bg); border-radius: 8px; padding: 5px 10px; cursor: pointer; text-align: left; max-width: 100%; }
73
- .ref-chip:hover { border-color: var(--brand); background: #f5f4ff; }
74
- .ref-chip .ref-label { font-size: 12px; font-weight: 600; color: var(--ink); }
75
- .ref-chip .ref-id { color: var(--muted); }
76
-
77
- /* Test-card decline state — last_payment_error rendered as a prominent banner */
78
- .pay-error { display: flex; flex-direction: column; gap: 2px; background: var(--bad-bg); color: var(--bad); border: 1px solid #f3c2c2; border-radius: 8px; padding: 10px 12px; margin-bottom: 12px; }
79
- .pay-error-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
80
- .pay-error-text { font-size: 13px; }
81
-
82
- /* Account balance summary — available / pending buckets */
83
- .balance-summary { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
84
- .balance-bucket { flex: 1; min-width: 120px; border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; background: var(--bg); display: flex; flex-direction: column; gap: 2px; }
85
- .balance-bucket.available { background: var(--ok-bg); border-color: #bfe6cf; }
86
- .balance-bucket-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
87
- .balance-bucket.available .balance-bucket-label { color: var(--ok); }
88
- .balance-bucket-amount { font-size: 16px; font-weight: 700; }
89
-
90
- /* Connect — connected-account enablement flags + outstanding requirements */
91
- .connect-panel { display: flex; flex-direction: column; gap: 12px; margin-bottom: 12px; }
92
- .connect-flags { display: flex; gap: 10px; flex-wrap: wrap; }
93
- .connect-flag { flex: 1; min-width: 110px; border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; display: flex; flex-direction: column; gap: 2px; background: var(--bg); }
94
- .connect-flag.ok { background: var(--ok-bg); border-color: #bfe6cf; }
95
- .connect-flag.warn { background: var(--warn-bg); border-color: #f0dca6; }
96
- .connect-flag-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
97
- .connect-flag.ok .connect-flag-label { color: var(--ok); }
98
- .connect-flag-state { font-size: 14px; font-weight: 700; }
99
- .connect-requirements { border: 1px solid #f0dca6; background: var(--warn-bg); border-radius: 8px; padding: 10px 12px; }
100
- .connect-req-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--warn); }
101
- .connect-req-list { margin: 6px 0 0; padding-left: 18px; }
102
- .connect-req-item { font-size: 12px; }
103
-
104
- /* Product image thumbnails — actual <img> previews, not URL text */
105
- .thumbs { display: flex; flex-wrap: wrap; gap: 8px; }
106
- .thumb { display: block; width: 64px; height: 64px; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: var(--bg); }
107
- .thumb:hover { border-color: var(--brand); }
108
- .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
109
-
110
- /* Detail action bar — lifecycle verbs (Capture / Cancel) on a resource detail */
111
- .detail-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
112
- .action-btn { border: 1px solid var(--line); border-radius: 8px; padding: 6px 14px; font-size: 13px; font-weight: 600; cursor: pointer; background: var(--bg); }
113
- .action-btn:hover:not(:disabled) { border-color: var(--brand); }
114
- .action-btn:disabled { opacity: .5; cursor: default; }
115
- .action-capture { background: var(--brand); color: #fff; border-color: var(--brand); }
116
- .action-cancel { color: var(--bad, #c0392b); }
117
- .action-error { font-size: 12px; color: var(--bad, #c0392b); }
118
-
119
- /* Home / overview screen — top-line metric cards + recent payments */
120
- .home-screen { display: flex; flex-direction: column; gap: 24px; }
121
- .home-metrics { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
122
- .metric-card { border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px; background: var(--bg); display: flex; flex-direction: column; gap: 6px; }
123
- .metric-label { font-size: 12px; color: var(--muted, #687385); text-transform: uppercase; letter-spacing: .04em; }
124
- .metric-value { font-size: 22px; font-weight: 700; }
125
- .home-recent { display: flex; flex-direction: column; gap: 4px; }
126
- .home-recent h3 { margin: 0 0 8px; font-size: 14px; }
127
- .home-recent-row { display: flex; gap: 12px; align-items: center; border: none; background: transparent; padding: 8px 4px; cursor: pointer; text-align: left; border-bottom: 1px solid var(--line); }
128
- .home-recent-row:hover { background: var(--hover, #f6f8fa); }
129
-
130
- /* Command bar (Cmd-K global search) */
131
- .cmdk-overlay { position: fixed; inset: 0; background: rgba(20,25,35,.4); display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; z-index: 50; }
132
- .cmdk { width: min(560px, 92vw); background: var(--bg); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 20px 60px rgba(0,0,0,.25); overflow: hidden; }
133
- .cmdk-input { width: 100%; box-sizing: border-box; border: none; border-bottom: 1px solid var(--line); padding: 16px 18px; font-size: 16px; outline: none; }
134
- .cmdk-results { max-height: 50vh; overflow-y: auto; }
135
- .cmdk-hit { display: flex; flex-direction: column; gap: 2px; width: 100%; text-align: left; border: none; background: transparent; padding: 10px 18px; cursor: pointer; border-bottom: 1px solid var(--line); }
136
- .cmdk-hit:hover { background: var(--hover, #f6f8fa); }
137
- .cmdk-hit-label { font-weight: 600; font-size: 14px; }
138
- .cmdk-hit-sub { font-size: 12px; color: var(--muted, #687385); }
139
- .cmdk-empty { padding: 18px; color: var(--muted, #687385); font-size: 14px; }
140
- .search-trigger { text-align: left; color: var(--muted, #687385); cursor: pointer; }
141
- .kbd { border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; font-size: 11px; }
142
-
143
- /* Settings screen */
144
- .settings-screen { display: flex; flex-direction: column; gap: 24px; max-width: 640px; }
145
- .settings-block { border: 1px solid var(--line); border-radius: 10px; padding: 16px 18px; }
146
- .settings-block h3 { margin: 0 0 12px; font-size: 15px; }
147
- .api-key-row, .webhook-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--line); }
148
- .api-key-label, .webhook-url { font-size: 13px; }
149
- .settings-payout-schedule { font-weight: 600; }
150
-
151
- /* Create / edit modal (write forms) */
152
- .create-overlay { position: fixed; inset: 0; background: rgba(20,25,35,.4); display: flex; align-items: center; justify-content: center; z-index: 50; }
153
- .create-modal { width: min(440px, 92vw); background: var(--bg); border: 1px solid var(--line); border-radius: 12px; padding: 20px; box-shadow: 0 20px 60px rgba(0,0,0,.25); display: flex; flex-direction: column; gap: 12px; }
154
- .create-title { margin: 0; font-size: 16px; }
155
- .create-field { display: flex; flex-direction: column; gap: 4px; }
156
- .create-field-label { font-size: 12px; color: var(--muted, #687385); }
157
- .create-field-input { border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; font-size: 14px; }
158
- .create-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
159
- .create-cancel, .create-submit { border: 1px solid var(--line); border-radius: 8px; padding: 7px 16px; font-size: 13px; font-weight: 600; cursor: pointer; background: var(--bg); }
160
- .create-submit { background: var(--brand); color: #fff; border-color: var(--brand); }
161
- .create-error { font-size: 12px; color: var(--bad, #c0392b); }
162
- .create-trigger { margin-left: auto; border: 1px solid var(--brand); color: var(--brand); border-radius: 8px; padding: 5px 12px; font-size: 13px; font-weight: 600; cursor: pointer; background: var(--bg); }
18
+ html, body { margin: 0; background: #fff; color: var(--text); font: 14px/20px var(--font); -webkit-font-smoothing: antialiased; }
19
+ a { color: inherit; text-decoration: none; }
20
+ button { font: inherit; color: inherit; }
21
+ h1, h2, h3 { margin: 0; color: var(--heading); }
22
+ .mono { font-family: var(--mono); font-size: 12.5px; }
23
+ .muted { color: var(--muted); }
24
+ .small { font-size: 13px; line-height: 18px; }
25
+ .strong { font-weight: 600; color: var(--heading); }
26
+ .nowrap { white-space: nowrap; }
27
+ .right { text-align: right; }
28
+ .truncate { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
29
+ .icon { flex: none; }
30
+ .link { color: var(--brand); font-weight: 500; }
31
+ .link:hover { color: #0a2540; }
32
+
33
+ /* test mode */
34
+ .test-band { position: sticky; top: 0; z-index: 30; height: 28px; display: flex; align-items: center; justify-content: center; gap: 10px; background: var(--test); color: #fff; font-size: 13px; }
35
+ .test-band-tag { font-weight: 700; text-transform: uppercase; letter-spacing: .04em; font-size: 12px; background: rgba(255,255,255,.22); padding: 0 8px; border-radius: 4px; line-height: 20px; }
36
+ .test-band-text { font-weight: 500; }
37
+
38
+ /* frame */
39
+ .frame { display: flex; min-height: calc(100vh - 28px); }
40
+ .side { position: sticky; top: 28px; height: calc(100vh - 28px); width: 248px; flex: none; border-right: 1px solid var(--border); padding: 12px 12px 16px; display: flex; flex-direction: column; overflow-y: auto; background: #fff; }
41
+ .account-switcher { display: flex; align-items: center; gap: 10px; width: 100%; border: 0; background: none; padding: 8px 8px; border-radius: 6px; cursor: pointer; margin-bottom: 12px; text-align: left; }
42
+ .account-switcher:hover { background: var(--hover); }
43
+ .account-mark { width: 24px; height: 24px; border-radius: 6px; background: #0a2540; color: #fff; font-weight: 700; font-size: 13px; display: grid; place-items: center; }
44
+ .account-name { flex: 1; font-weight: 600; color: var(--heading); }
45
+ .nav-group { display: flex; flex-direction: column; gap: 1px; }
46
+ .nav-heading { margin: 20px 8px 6px; font-size: 13px; font-weight: 600; color: var(--muted); }
47
+ .nav-item { display: flex; align-items: center; gap: 10px; width: 100%; height: 32px; padding: 0 8px; border: 0; background: none; border-radius: 6px; cursor: pointer; font-weight: 500; color: var(--text); text-align: left; }
48
+ .nav-item .icon { color: var(--muted); }
49
+ .nav-item:hover { background: var(--hover); color: var(--heading); }
50
+ .nav-item.active { color: var(--brand); font-weight: 600; }
51
+ .nav-item.active .icon { color: var(--brand); }
52
+ .nav-item span { flex: 1; }
53
+ .nav-caret { margin-left: auto; opacity: .7; }
54
+ .nav-sub { padding-left: 34px; height: 30px; font-weight: 400; }
55
+ .nav-foot { margin-top: auto; padding-top: 12px; }
56
+
57
+ .main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
58
+ .topbar { position: sticky; top: 28px; z-index: 20; height: 60px; display: flex; align-items: center; gap: 16px; padding: 0 32px; background: #fff; }
59
+ .search { position: relative; flex: 1; max-width: 520px; }
60
+ .search-icon { position: absolute; left: 10px; top: 8px; color: var(--muted); }
61
+ .search-input { width: 100%; height: 32px; border: 0; border-radius: 6px; background: var(--hover); padding: 0 12px 0 34px; font: inherit; color: var(--heading); outline: none; }
62
+ .search-input:focus { background: #fff; box-shadow: 0 0 0 1px var(--border-strong), 0 0 0 4px rgba(99,91,255,.18); }
63
+ .search-input::placeholder { color: var(--muted); }
64
+ .cmdk { position: absolute; top: 38px; left: 0; right: 0; background: #fff; border-radius: 8px; box-shadow: 0 0 0 1px rgba(64,68,82,.08), 0 8px 24px rgba(64,68,82,.18); padding: 6px 0; max-height: 420px; overflow-y: auto; }
65
+ .cmdk-group { padding: 8px 14px 4px; font-size: 12px; font-weight: 600; color: var(--muted); }
66
+ .cmdk-hit { display: flex; flex-direction: column; width: 100%; border: 0; background: none; text-align: left; padding: 6px 14px; cursor: pointer; }
67
+ .cmdk-hit:hover { background: var(--hover); }
68
+ .cmdk-hit-label { color: var(--heading); font-weight: 500; }
69
+ .cmdk-hit-sub { color: var(--muted); font-size: 13px; }
70
+ .cmdk-empty { padding: 10px 14px; color: var(--muted); }
71
+ .topbar-actions { margin-left: auto; display: flex; align-items: center; gap: 4px; }
72
+ .icon-btn { width: 32px; height: 32px; border: 0; background: none; border-radius: 6px; display: grid; place-items: center; cursor: pointer; color: var(--muted); }
73
+ .icon-btn:hover { background: var(--hover); color: var(--heading); }
74
+ .icon-btn.create { background: var(--brand); color: #fff; width: 28px; height: 28px; border-radius: 50%; margin-left: 6px; }
75
+ .icon-btn.create:hover { background: var(--brand-dark); color: #fff; }
76
+
77
+ .content { padding: 8px 32px 64px; max-width: 1360px; width: 100%; }
78
+ .loading { padding: 40px 0; color: var(--muted); }
79
+ .page-error { margin: 24px 0; padding: 12px 16px; border-radius: 6px; background: #fff1f3; color: #b3093c; }
80
+
81
+ /* page heads */
82
+ .page-head { margin: 12px 0 20px; }
83
+ .kicker { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); font-weight: 500; margin-bottom: 6px; }
84
+ .page-head-row { display: flex; align-items: center; gap: 16px; }
85
+ .page-head h1 { font-size: 28px; line-height: 36px; font-weight: 700; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
86
+ .page-actions { margin-left: auto; display: flex; gap: 8px; }
87
+ .subtitle { color: var(--muted); margin-top: 4px; }
88
+ .tabs { display: flex; gap: 24px; border-bottom: 1px solid var(--border); margin-top: 16px; }
89
+ .tab { padding: 8px 0 10px; color: var(--muted); font-weight: 500; border-bottom: 2px solid transparent; margin-bottom: -1px; }
90
+ .tab:hover { color: var(--heading); }
91
+ .tab.active { color: var(--brand); border-bottom-color: var(--brand); font-weight: 600; }
92
+ .summary { display: flex; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
93
+ .summary-item { padding: 0 24px; border-left: 1px solid var(--border); min-width: 120px; }
94
+ .summary-item:first-child { padding-left: 0; border-left: 0; }
95
+ .summary-label { color: var(--muted); font-size: 13px; margin-bottom: 2px; }
96
+
97
+ /* amounts, pills, cards */
98
+ .amount-value { font-weight: 600; color: var(--heading); }
99
+ .amount-ccy { color: var(--muted); font-weight: 400; }
100
+ h1 .amount-value { font-weight: 700; }
101
+ h1 .amount-ccy { font-size: 28px; font-weight: 400; color: var(--faint); }
102
+ .pill { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 6px; border-radius: 4px; font-size: 12px; font-weight: 500; line-height: 18px; white-space: nowrap; border: 1px solid transparent; vertical-align: middle; }
103
+ h1 .pill { font-size: 13px; height: 22px; }
104
+ .pill-green { background: #d7f7c2; color: #05690d; border-color: #a6eb84; }
105
+ .pill-grey { background: #ebeef1; color: #545969; border-color: #d5dbe1; }
106
+ .pill-red { background: #ffe7f2; color: #b3093c; border-color: #ffccdf; }
107
+ .pill-blue { background: #cff5f6; color: #0055bc; border-color: #a2e5ef; }
108
+ .pill-orange { background: #fcedb9; color: #a82c00; border-color: #fcd579; }
109
+ .pill-purple { background: #f2ebff; color: #533afd; border-color: #d8cbff; }
110
+ .card-label { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
111
+ .dots { color: var(--muted); letter-spacing: 1px; }
112
+ .brand { display: inline-grid; place-items: center; width: 28px; height: 18px; border-radius: 3px; border: 1px solid var(--border-strong); background: #fff; font-size: 9px; font-weight: 800; font-style: italic; letter-spacing: .02em; }
113
+ .brand-visa { color: #1a1f71; }
114
+ .brand-amex { background: #1f72cd; border-color: #1f72cd; color: #fff; font-style: normal; font-size: 8px; }
115
+ .brand-generic { color: var(--muted); }
116
+ .check-pass { display: inline-flex; align-items: center; gap: 4px; color: #05690d; }
117
+
118
+ /* filter cards */
119
+ .filter-cards { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
120
+ .filter-card { min-width: 140px; flex: 0 1 180px; text-align: left; background: #fff; border: 1px solid var(--border-strong); border-radius: 8px; padding: 8px 12px; cursor: pointer; display: flex; flex-direction: column; box-shadow: 0 1px 1px rgba(0,0,0,.03); }
121
+ .filter-card:hover { border-color: #a3acba; }
122
+ .filter-card.selected { border: 2px solid var(--brand); padding: 7px 11px; }
123
+ .filter-card-label { font-size: 13px; color: var(--muted); font-weight: 500; }
124
+ .filter-card.selected .filter-card-label { color: var(--brand); }
125
+ .filter-card-count { font-size: 18px; line-height: 26px; font-weight: 600; color: var(--heading); }
126
+ .filter-card.selected .filter-card-count { color: var(--brand); }
127
+
128
+ /* tables */
129
+ .table { width: 100%; border-collapse: collapse; }
130
+ .table th { text-align: left; font-size: 13px; font-weight: 600; color: var(--heading); padding: 8px 12px 8px 0; border-bottom: 1px solid var(--border); white-space: nowrap; }
131
+ .table td { padding: 9px 12px 9px 0; border-bottom: 1px solid var(--border); vertical-align: middle; }
132
+ .table th.right, .table td.right { padding-right: 0; padding-left: 12px; text-align: right; }
133
+ .table tr.list-row { cursor: pointer; }
134
+ .table tr.list-row:hover td { background: var(--hover); }
135
+ .table tr.table-total td { border-bottom: 0; }
136
+ .table .empty-row td { border-bottom: 0; }
137
+ .table-foot { display: flex; align-items: center; justify-content: space-between; padding: 12px 0; color: var(--muted); font-size: 13px; }
138
+ .pager { display: flex; gap: 8px; }
139
+ .empty { padding: 28px 0; text-align: center; }
140
+ .empty-title { font-weight: 600; color: var(--heading); }
141
+ .empty-body { color: var(--muted); margin-top: 4px; }
142
+
143
+ /* buttons */
144
+ .btn { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 6px; border: 1px solid var(--border-strong); background: #fff; font-weight: 500; color: var(--heading); cursor: pointer; box-shadow: 0 1px 1px rgba(0,0,0,.05); white-space: nowrap; }
145
+ .btn:hover { border-color: #a3acba; }
146
+ .btn:disabled { color: #a3acba; cursor: default; box-shadow: none; }
147
+ .btn:disabled:hover { border-color: var(--border-strong); }
148
+ .btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; box-shadow: 0 1px 1px rgba(0,0,0,.08); }
149
+ .btn-primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
150
+ .btn-primary:disabled { background: #a4a1ff; border-color: #a4a1ff; color: #fff; }
151
+ .btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
152
+ .btn-danger:hover { background: #c0123c; border-color: #c0123c; }
153
+
154
+ /* sections */
155
+ .section { margin-top: 32px; }
156
+ .section-head { display: flex; align-items: center; justify-content: space-between; padding-bottom: 10px; border-bottom: 1px solid var(--border); margin-bottom: 4px; }
157
+ .section-head h2 { font-size: 18px; line-height: 28px; font-weight: 700; }
158
+ .section .table th { border-top: 0; }
159
+ .props { margin: 0; display: grid; grid-template-columns: 1fr; }
160
+ .prop { display: grid; grid-template-columns: 200px 1fr; padding: 6px 0; }
161
+ .prop dt { color: var(--muted); }
162
+ .prop dd { margin: 0; color: var(--heading); word-break: break-word; }
163
+ .detail-side .prop { grid-template-columns: 1fr; padding: 5px 0; }
164
+ .detail-side .prop dt { font-size: 13px; }
165
+ .detail-columns { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 48px; }
166
+ .detail-side .section:first-child, .detail-main .section:first-child { margin-top: 8px; }
167
+ .breakdown { margin: 8px 0 0; max-width: 480px; }
168
+ .breakdown > div { display: flex; justify-content: space-between; padding: 5px 0; }
169
+ .breakdown dt { color: var(--muted); }
170
+ .breakdown dd { margin: 0; color: var(--heading); }
171
+ .breakdown .total { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 8px; font-weight: 600; }
172
+ .breakdown .total dt { color: var(--heading); }
173
+
174
+ /* timeline */
175
+ .timeline { list-style: none; margin: 8px 0 0; padding: 0; }
176
+ .timeline-item { position: relative; display: flex; gap: 12px; padding: 0 0 16px; }
177
+ .timeline-item:not(:last-child)::before { content: ""; position: absolute; left: 5px; top: 16px; bottom: 0; width: 1px; background: var(--border-strong); }
178
+ .timeline-dot { flex: none; width: 11px; height: 11px; border-radius: 50%; margin-top: 4px; border: 2px solid #fff; box-shadow: 0 0 0 1px var(--border-strong); }
179
+ .dot-green { background: #30b130; }
180
+ .dot-red { background: var(--danger); }
181
+ .dot-blue { background: var(--brand); }
182
+ .dot-grey { background: #a3acba; }
183
+ .timeline-text { color: var(--heading); font-weight: 500; }
184
+ .timeline-time { color: var(--muted); font-size: 13px; }
185
+
186
+ /* payment error */
187
+ .pay-error { display: flex; gap: 10px; align-items: flex-start; margin: 8px 0 0; padding: 12px 14px; border-radius: 6px; background: #fff1f3; border: 1px solid #ffccdf; color: #b3093c; }
188
+ .pay-error-label { font-weight: 600; }
189
+ .pay-error-text { color: var(--heading); }
190
+
191
+ /* subscriptions on a customer */
192
+ .sub-list { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
193
+ .sub-card { display: block; border: 1px solid var(--border-strong); border-radius: 8px; padding: 10px 14px; }
194
+ .sub-card:hover { background: var(--hover); }
195
+ .sub-card-main { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
196
+
197
+ /* products */
198
+ .product-cell { display: flex; align-items: center; gap: 12px; }
199
+ .product-thumb { width: 36px; height: 36px; border-radius: 6px; background: var(--hover); border: 1px solid var(--border); display: grid; place-items: center; color: var(--faint); overflow: hidden; }
200
+ .product-thumb img { width: 100%; height: 100%; object-fit: cover; }
201
+
202
+ /* home */
203
+ .today { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 32px; padding-bottom: 28px; border-bottom: 1px solid var(--border); }
204
+ .today-label { color: var(--muted); font-weight: 500; display: flex; align-items: center; gap: 4px; }
205
+ .today-value { font-size: 20px; line-height: 28px; font-weight: 600; color: var(--heading); margin: 2px 0 10px; }
206
+ .spark { width: 100%; height: 120px; display: block; }
207
+ .today-axis { display: flex; justify-content: space-between; color: var(--faint); font-size: 12px; margin-top: 4px; }
208
+ .today-side { display: flex; flex-direction: column; }
209
+ .today-side-block { padding: 12px 0; border-bottom: 1px solid var(--border); }
210
+ .today-side-block:first-child { padding-top: 0; }
211
+ .today-side-value { font-size: 20px; line-height: 28px; font-weight: 600; color: var(--heading); margin: 2px 0; }
212
+ .overview-title { font-size: 20px; line-height: 28px; font-weight: 700; margin: 28px 0 16px; }
213
+ .home-metrics { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; border-top: 1px solid var(--border); }
214
+ .metric-card { display: flex; flex-direction: column; padding: 16px 24px 20px 0; border-bottom: 1px solid var(--border); }
215
+ .metric-label { color: var(--muted); font-weight: 500; }
216
+ .metric-value { font-size: 20px; line-height: 28px; font-weight: 600; color: var(--heading); margin-top: 4px; }
217
+
218
+ /* balances */
219
+ .balance-summary { display: flex; gap: 48px; padding: 12px 0 16px; }
220
+ .balance-bucket { display: flex; flex-direction: column; }
221
+ .balance-bucket-label { color: var(--muted); font-weight: 500; }
222
+ .balance-bucket-amount { font-size: 20px; line-height: 28px; font-weight: 600; color: var(--heading); }
223
+
224
+ /* connect */
225
+ .connect-panel { border: 1px solid var(--border-strong); border-radius: 8px; padding: 12px 16px; margin-bottom: 16px; }
226
+ .connect-flags { display: flex; gap: 32px; }
227
+ .connect-flag { display: flex; gap: 8px; align-items: center; }
228
+ .connect-flag-label { color: var(--muted); }
229
+ .connect-requirements { margin-top: 10px; }
230
+ .connect-req-label { font-weight: 600; color: var(--heading); }
231
+ .connect-req-list { margin: 4px 0 0; padding-left: 18px; }
232
+
233
+ /* dialogs */
234
+ .overlay { position: fixed; inset: 0; z-index: 50; background: rgba(48, 61, 82, .45); display: grid; place-items: start center; padding-top: 12vh; }
235
+ .dialog { width: 480px; max-width: calc(100vw - 32px); background: #fff; border-radius: 10px; box-shadow: 0 0 0 1px rgba(64,68,82,.08), 0 16px 48px rgba(48,49,61,.3); overflow: hidden; }
236
+ .dialog-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 20px; border-bottom: 1px solid var(--border); }
237
+ .dialog-head h2 { font-size: 18px; line-height: 26px; font-weight: 700; }
238
+ .dialog-body { padding: 16px 20px 20px; display: flex; flex-direction: column; gap: 16px; }
239
+ .dialog-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 20px; border-top: 1px solid var(--border); background: #fff; }
240
+ .dialog-note { margin: 0; color: var(--muted); }
241
+ .dialog-subhead { font-weight: 600; color: var(--heading); }
242
+ .field { display: flex; flex-direction: column; gap: 6px; }
243
+ .field-label { font-weight: 500; color: var(--heading); }
244
+ .optional { color: var(--muted); font-weight: 400; }
245
+ .field-hint { color: var(--muted); font-size: 13px; }
246
+ .field input, .field select { height: 32px; border: 1px solid var(--border-strong); border-radius: 6px; padding: 0 10px; font: inherit; color: var(--heading); background: #fff; outline: none; box-shadow: 0 1px 1px rgba(0,0,0,.03); }
247
+ .field input:focus, .field select:focus, .money-input:focus-within { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(99,91,255,.2); }
248
+ .money-input { display: flex; align-items: center; height: 32px; border: 1px solid var(--border-strong); border-radius: 6px; padding: 0 10px; max-width: 220px; }
249
+ .money-input input { flex: 1; min-width: 0; border: 0; height: 30px; padding: 0 4px; box-shadow: none; }
250
+ .money-input input:focus { box-shadow: none; }
251
+ .money-prefix, .money-suffix { color: var(--muted); }
252
+ .radio-group { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
253
+ .radio-group legend { margin-bottom: 8px; }
254
+ .radio { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; color: var(--heading); }
255
+ .radio input { margin-top: 3px; accent-color: var(--brand); }
256
+ .radio-hint { display: block; color: var(--muted); font-size: 13px; }
257
+ .form-error { color: #b3093c; background: #fff1f3; border-radius: 6px; padding: 8px 10px; }
258
+
259
+ /* list toolbar: filter chips and Export */
260
+ .toolbar { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; }
261
+ .toolbar-right { margin-left: auto; display: flex; gap: 8px; }
262
+ .chip-wrap { position: relative; }
263
+ .chip { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 10px 0 4px; border-radius: 12px; border: 1px dashed #a3acba; background: #fff; color: var(--text); font-size: 13px; font-weight: 500; cursor: pointer; }
264
+ .chip:hover { border-color: var(--muted); }
265
+ .chip-set { border-style: solid; border-color: var(--border-strong); }
266
+ .chip-plus { width: 16px; height: 16px; border-radius: 50%; display: grid; place-items: center; color: var(--muted); border: 1px solid #a3acba; }
267
+ .chip-set .chip-plus { border: 0; background: var(--hover); }
268
+ .chip-sep { color: var(--border-strong); }
269
+ .chip-value { color: var(--brand); }
270
+ .popover { position: absolute; z-index: 40; top: 30px; left: 0; min-width: 220px; background: #fff; border-radius: 8px; box-shadow: 0 0 0 1px rgba(64,68,82,.08), 0 8px 24px rgba(64,68,82,.18); padding: 8px 0; }
271
+ .popover-title { padding: 4px 14px 8px; font-weight: 600; color: var(--heading); font-size: 13px; }
272
+ .popover-item { display: flex; align-items: center; gap: 8px; width: 100%; border: 0; background: none; padding: 6px 14px; text-align: left; cursor: pointer; font-size: 13px; }
273
+ .popover-item:hover { background: var(--hover); }
274
+ .popover-radio { width: 14px; height: 14px; border-radius: 50%; border: 1px solid #a3acba; flex: none; }
275
+ .popover-item.checked .popover-radio { border: 4px solid var(--brand); }