@solvapay/react 1.0.9-preview.1 → 1.0.9

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.
@@ -0,0 +1,1115 @@
1
+ /**
2
+ * @solvapay/react — golden-path default styles.
3
+ *
4
+ * Opt-in via `import '@solvapay/react/styles.css'`. Theme by overriding the
5
+ * CSS custom properties exposed on `:root`. Every rule targets either an
6
+ * opaque `data-solvapay-*` selector (works for consumer compositions of the
7
+ * primitives) or a `.solvapay-*` class seeded by the default-tree shims in
8
+ * `src/components/*`. No element styles; safe to layer.
9
+ */
10
+
11
+ :root {
12
+ --solvapay-accent: hsl(222 47% 11%);
13
+ --solvapay-accent-foreground: hsl(0 0% 98%);
14
+ --solvapay-accent-hover: hsl(222 47% 20%);
15
+ --solvapay-surface: hsl(0 0% 100%);
16
+ --solvapay-muted: hsl(210 40% 96%);
17
+ --solvapay-muted-foreground: hsl(215 16% 47%);
18
+ --solvapay-border: hsl(214 32% 91%);
19
+ --solvapay-destructive: hsl(0 72% 51%);
20
+ --solvapay-warning: hsl(38 92% 50%);
21
+ --solvapay-radius: 0.5rem;
22
+ --solvapay-font: inherit;
23
+ }
24
+
25
+ /* -----------------------------------------------------------------------------
26
+ * Spinner (shared across PaymentForm, TopupForm, StripePaymentFormWrapper)
27
+ * -------------------------------------------------------------------------- */
28
+
29
+ @keyframes solvapay-spin {
30
+ to {
31
+ transform: rotate(360deg);
32
+ }
33
+ }
34
+
35
+ [data-solvapay-spinner] {
36
+ animation: solvapay-spin 0.8s linear infinite;
37
+ flex-shrink: 0;
38
+ vertical-align: middle;
39
+ }
40
+
41
+ @media (prefers-reduced-motion: reduce) {
42
+ [data-solvapay-spinner] {
43
+ animation: none;
44
+ }
45
+ }
46
+
47
+ /* -----------------------------------------------------------------------------
48
+ * Checkout layout shell (drop-in)
49
+ * -------------------------------------------------------------------------- */
50
+
51
+ .solvapay-checkout-layout {
52
+ font-family: var(--solvapay-font);
53
+ color: var(--solvapay-accent);
54
+ display: grid;
55
+ gap: 1rem;
56
+ padding: 1rem;
57
+ font-size: 0.875rem;
58
+ line-height: 1.5;
59
+ }
60
+
61
+ [data-solvapay-checkout-layout='desktop'].solvapay-checkout-layout {
62
+ gap: 1.5rem;
63
+ padding: 1.5rem;
64
+ }
65
+
66
+ [data-solvapay-checkout-layout='desktop'][data-solvapay-step='pay'].solvapay-checkout-layout {
67
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
68
+ }
69
+
70
+ [data-solvapay-checkout-layout='mobile'].solvapay-checkout-layout {
71
+ font-size: 0.9375rem;
72
+ }
73
+
74
+ [data-solvapay-checkout-layout='chat'].solvapay-checkout-layout {
75
+ padding: 0.5rem;
76
+ gap: 0.75rem;
77
+ }
78
+
79
+ .solvapay-back {
80
+ align-self: flex-start;
81
+ background: transparent;
82
+ border: none;
83
+ color: var(--solvapay-muted-foreground);
84
+ cursor: pointer;
85
+ font: inherit;
86
+ padding: 0.25rem 0;
87
+ text-decoration: none;
88
+ transition: color 120ms ease;
89
+ }
90
+
91
+ .solvapay-back:hover {
92
+ color: var(--solvapay-accent);
93
+ }
94
+
95
+ .solvapay-back:focus-visible {
96
+ outline: 2px solid var(--solvapay-accent);
97
+ outline-offset: 2px;
98
+ border-radius: calc(var(--solvapay-radius) / 2);
99
+ }
100
+
101
+ .solvapay-continue {
102
+ align-self: stretch;
103
+ background: var(--solvapay-accent);
104
+ color: var(--solvapay-accent-foreground);
105
+ border: none;
106
+ border-radius: var(--solvapay-radius);
107
+ cursor: pointer;
108
+ font: inherit;
109
+ font-weight: 500;
110
+ padding: 0.75rem 1rem;
111
+ transition:
112
+ background-color 120ms ease,
113
+ opacity 120ms ease;
114
+ }
115
+
116
+ .solvapay-continue:hover:not(:disabled) {
117
+ background: var(--solvapay-accent-hover);
118
+ }
119
+
120
+ .solvapay-continue:disabled,
121
+ .solvapay-continue[data-state='disabled'] {
122
+ opacity: 0.5;
123
+ cursor: not-allowed;
124
+ }
125
+
126
+ .solvapay-continue:focus-visible {
127
+ outline: 2px solid var(--solvapay-accent);
128
+ outline-offset: 2px;
129
+ }
130
+
131
+ /* -----------------------------------------------------------------------------
132
+ * CheckoutSummary
133
+ * -------------------------------------------------------------------------- */
134
+
135
+ [data-solvapay-checkout-summary] {
136
+ display: flex;
137
+ flex-direction: column;
138
+ gap: 0.25rem;
139
+ background: var(--solvapay-muted);
140
+ border-radius: var(--solvapay-radius);
141
+ padding: 1rem;
142
+ }
143
+
144
+ [data-solvapay-checkout-summary-product],
145
+ .solvapay-checkout-summary-product {
146
+ font-weight: 600;
147
+ color: var(--solvapay-accent);
148
+ }
149
+
150
+ .solvapay-checkout-summary-row {
151
+ display: flex;
152
+ align-items: baseline;
153
+ justify-content: space-between;
154
+ gap: 0.5rem;
155
+ }
156
+
157
+ [data-solvapay-checkout-summary-plan],
158
+ .solvapay-checkout-summary-plan {
159
+ color: var(--solvapay-muted-foreground);
160
+ }
161
+
162
+ [data-solvapay-checkout-summary-price],
163
+ .solvapay-checkout-summary-price {
164
+ font-weight: 600;
165
+ color: var(--solvapay-accent);
166
+ font-variant-numeric: tabular-nums;
167
+ }
168
+
169
+ [data-solvapay-checkout-summary-trial],
170
+ .solvapay-checkout-summary-trial,
171
+ [data-solvapay-checkout-summary-tax-note],
172
+ .solvapay-checkout-summary-tax-note {
173
+ color: var(--solvapay-muted-foreground);
174
+ font-size: 0.8125rem;
175
+ }
176
+
177
+ /* -----------------------------------------------------------------------------
178
+ * PlanSelector
179
+ * -------------------------------------------------------------------------- */
180
+
181
+ [data-solvapay-plan-selector],
182
+ .solvapay-plan-selector {
183
+ display: flex;
184
+ flex-direction: column;
185
+ gap: 0.75rem;
186
+ }
187
+
188
+ [data-solvapay-plan-selector-heading],
189
+ .solvapay-plan-selector-heading {
190
+ font-size: 1rem;
191
+ font-weight: 600;
192
+ margin: 0;
193
+ color: var(--solvapay-accent);
194
+ }
195
+
196
+ [data-solvapay-plan-selector-grid],
197
+ .solvapay-plan-selector-grid {
198
+ display: grid;
199
+ gap: 0.75rem;
200
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
201
+ }
202
+
203
+ [data-solvapay-plan-selector-card] {
204
+ position: relative;
205
+ display: flex;
206
+ flex-direction: column;
207
+ gap: 0.25rem;
208
+ align-items: flex-start;
209
+ background: var(--solvapay-surface);
210
+ border: 1px solid var(--solvapay-border);
211
+ border-radius: var(--solvapay-radius);
212
+ padding: 1rem;
213
+ text-align: left;
214
+ cursor: pointer;
215
+ font: inherit;
216
+ color: inherit;
217
+ transition:
218
+ border-color 120ms ease,
219
+ box-shadow 120ms ease,
220
+ background-color 120ms ease;
221
+ }
222
+
223
+ [data-solvapay-plan-selector-card]:hover:not([data-state='disabled']) {
224
+ border-color: var(--solvapay-accent);
225
+ }
226
+
227
+ [data-solvapay-plan-selector-card]:focus-visible {
228
+ outline: none;
229
+ border-color: var(--solvapay-accent);
230
+ box-shadow: 0 0 0 2px var(--solvapay-accent);
231
+ }
232
+
233
+ [data-solvapay-plan-selector-card][data-state='selected'] {
234
+ border-color: var(--solvapay-accent);
235
+ box-shadow: 0 0 0 1px var(--solvapay-accent);
236
+ }
237
+
238
+ [data-solvapay-plan-selector-card][data-state='current'] {
239
+ background: var(--solvapay-muted);
240
+ border-color: var(--solvapay-border);
241
+ cursor: default;
242
+ }
243
+
244
+ [data-solvapay-plan-selector-card][data-state='disabled'] {
245
+ opacity: 0.6;
246
+ cursor: not-allowed;
247
+ }
248
+
249
+ [data-solvapay-plan-selector-card][data-popular] {
250
+ border-color: var(--solvapay-accent);
251
+ }
252
+
253
+ [data-solvapay-plan-selector-card-name],
254
+ .solvapay-plan-selector-card-name {
255
+ font-weight: 600;
256
+ color: var(--solvapay-accent);
257
+ }
258
+
259
+ [data-solvapay-plan-selector-card-price],
260
+ .solvapay-plan-selector-card-price {
261
+ font-size: 1.125rem;
262
+ font-weight: 600;
263
+ color: var(--solvapay-accent);
264
+ font-variant-numeric: tabular-nums;
265
+ }
266
+
267
+ [data-solvapay-plan-selector-card-interval],
268
+ .solvapay-plan-selector-card-interval {
269
+ color: var(--solvapay-muted-foreground);
270
+ font-size: 0.8125rem;
271
+ }
272
+
273
+ [data-solvapay-plan-selector-card-badge] {
274
+ position: absolute;
275
+ top: 0.5rem;
276
+ right: 0.5rem;
277
+ background: var(--solvapay-accent);
278
+ color: var(--solvapay-accent-foreground);
279
+ border-radius: 999px;
280
+ font-size: 0.6875rem;
281
+ font-weight: 600;
282
+ letter-spacing: 0.02em;
283
+ padding: 0.125rem 0.5rem;
284
+ text-transform: uppercase;
285
+ }
286
+
287
+ [data-solvapay-plan-selector-card-badge][data-variant='current'] {
288
+ background: var(--solvapay-muted-foreground);
289
+ }
290
+
291
+ [data-solvapay-plan-selector-loading],
292
+ .solvapay-plan-selector-loading {
293
+ color: var(--solvapay-muted-foreground);
294
+ font-size: 0.875rem;
295
+ padding: 1rem 0;
296
+ }
297
+
298
+ [data-solvapay-plan-selector-error],
299
+ .solvapay-plan-selector-error {
300
+ color: var(--solvapay-destructive);
301
+ font-size: 0.875rem;
302
+ padding: 0.75rem 1rem;
303
+ border: 1px solid var(--solvapay-destructive);
304
+ border-radius: var(--solvapay-radius);
305
+ background: color-mix(in srgb, var(--solvapay-destructive) 6%, transparent);
306
+ }
307
+
308
+ /* -----------------------------------------------------------------------------
309
+ * PaymentForm
310
+ * -------------------------------------------------------------------------- */
311
+
312
+ [data-solvapay-payment-form] {
313
+ display: flex;
314
+ flex-direction: column;
315
+ gap: 1rem;
316
+ }
317
+
318
+ [data-solvapay-payment-form-customer-fields] {
319
+ display: flex;
320
+ flex-direction: column;
321
+ gap: 0.5rem;
322
+ }
323
+
324
+ [data-solvapay-payment-form-customer-email] input,
325
+ [data-solvapay-payment-form-customer-name] input {
326
+ width: 100%;
327
+ background: var(--solvapay-surface);
328
+ border: 1px solid var(--solvapay-border);
329
+ border-radius: var(--solvapay-radius);
330
+ font: inherit;
331
+ padding: 0.625rem 0.75rem;
332
+ color: var(--solvapay-accent);
333
+ transition: border-color 120ms ease;
334
+ }
335
+
336
+ [data-solvapay-payment-form-customer-email] input:focus,
337
+ [data-solvapay-payment-form-customer-name] input:focus {
338
+ outline: none;
339
+ border-color: var(--solvapay-accent);
340
+ box-shadow: 0 0 0 1px var(--solvapay-accent);
341
+ }
342
+
343
+ [data-solvapay-payment-form-terms] {
344
+ display: flex;
345
+ align-items: flex-start;
346
+ gap: 0.5rem;
347
+ font-size: 0.8125rem;
348
+ color: var(--solvapay-muted-foreground);
349
+ }
350
+
351
+ [data-solvapay-payment-form-submit] {
352
+ display: inline-flex;
353
+ align-items: center;
354
+ justify-content: center;
355
+ gap: 0.5rem;
356
+ background: var(--solvapay-accent);
357
+ color: var(--solvapay-accent-foreground);
358
+ border: none;
359
+ border-radius: var(--solvapay-radius);
360
+ cursor: pointer;
361
+ font: inherit;
362
+ font-weight: 500;
363
+ padding: 0.75rem 1rem;
364
+ transition:
365
+ background-color 120ms ease,
366
+ opacity 120ms ease;
367
+ }
368
+
369
+ [data-solvapay-payment-form-submit]:hover:not(:disabled) {
370
+ background: var(--solvapay-accent-hover);
371
+ }
372
+
373
+ [data-solvapay-payment-form-submit]:focus-visible {
374
+ outline: 2px solid var(--solvapay-accent);
375
+ outline-offset: 2px;
376
+ }
377
+
378
+ [data-solvapay-payment-form-submit][data-state='processing'] {
379
+ opacity: 0.75;
380
+ cursor: wait;
381
+ }
382
+
383
+ [data-solvapay-payment-form-submit][data-state='disabled'],
384
+ [data-solvapay-payment-form-submit]:disabled {
385
+ opacity: 0.5;
386
+ cursor: not-allowed;
387
+ }
388
+
389
+ [data-solvapay-payment-form-loading] {
390
+ color: var(--solvapay-muted-foreground);
391
+ font-size: 0.875rem;
392
+ padding: 1rem 0;
393
+ }
394
+
395
+ [data-solvapay-payment-form-error] {
396
+ color: var(--solvapay-destructive);
397
+ font-size: 0.875rem;
398
+ padding: 0.75rem 1rem;
399
+ border: 1px solid var(--solvapay-destructive);
400
+ border-radius: var(--solvapay-radius);
401
+ background: color-mix(in srgb, var(--solvapay-destructive) 6%, transparent);
402
+ }
403
+
404
+ /* -----------------------------------------------------------------------------
405
+ * ActivationFlow
406
+ * -------------------------------------------------------------------------- */
407
+
408
+ [data-solvapay-activation-flow] {
409
+ display: flex;
410
+ flex-direction: column;
411
+ gap: 1rem;
412
+ }
413
+
414
+ [data-solvapay-activation-flow-summary],
415
+ .solvapay-activation-flow-summary {
416
+ display: flex;
417
+ flex-direction: column;
418
+ gap: 0.75rem;
419
+ background: var(--solvapay-muted);
420
+ border-radius: var(--solvapay-radius);
421
+ padding: 1rem;
422
+ }
423
+
424
+ .solvapay-activation-flow-heading,
425
+ .solvapay-activation-flow-topup-heading {
426
+ font-size: 1rem;
427
+ font-weight: 600;
428
+ margin: 0;
429
+ color: var(--solvapay-accent);
430
+ }
431
+
432
+ .solvapay-activation-flow-topup-subheading {
433
+ color: var(--solvapay-muted-foreground);
434
+ font-size: 0.875rem;
435
+ margin: 0;
436
+ }
437
+
438
+ [data-solvapay-activation-flow-activate],
439
+ [data-solvapay-activation-flow-continue],
440
+ .solvapay-activation-flow-activate,
441
+ .solvapay-activation-flow-continue {
442
+ align-self: stretch;
443
+ background: var(--solvapay-accent);
444
+ color: var(--solvapay-accent-foreground);
445
+ border: none;
446
+ border-radius: var(--solvapay-radius);
447
+ cursor: pointer;
448
+ font: inherit;
449
+ font-weight: 500;
450
+ padding: 0.75rem 1rem;
451
+ transition:
452
+ background-color 120ms ease,
453
+ opacity 120ms ease;
454
+ }
455
+
456
+ [data-solvapay-activation-flow-activate]:hover:not(:disabled),
457
+ [data-solvapay-activation-flow-continue]:hover:not(:disabled) {
458
+ background: var(--solvapay-accent-hover);
459
+ }
460
+
461
+ [data-solvapay-activation-flow-activate]:disabled,
462
+ [data-solvapay-activation-flow-continue]:disabled {
463
+ opacity: 0.5;
464
+ cursor: not-allowed;
465
+ }
466
+
467
+ [data-solvapay-activation-flow-activate]:focus-visible,
468
+ [data-solvapay-activation-flow-continue]:focus-visible {
469
+ outline: 2px solid var(--solvapay-accent);
470
+ outline-offset: 2px;
471
+ }
472
+
473
+ .solvapay-activation-flow-change-amount,
474
+ .solvapay-activation-flow-try-again,
475
+ .solvapay-activation-flow-back {
476
+ background: transparent;
477
+ border: 1px solid var(--solvapay-border);
478
+ border-radius: var(--solvapay-radius);
479
+ color: var(--solvapay-accent);
480
+ cursor: pointer;
481
+ font: inherit;
482
+ padding: 0.5rem 0.75rem;
483
+ transition:
484
+ background-color 120ms ease,
485
+ border-color 120ms ease;
486
+ }
487
+
488
+ .solvapay-activation-flow-change-amount:hover,
489
+ .solvapay-activation-flow-try-again:hover,
490
+ .solvapay-activation-flow-back:hover {
491
+ background: var(--solvapay-muted);
492
+ border-color: var(--solvapay-accent);
493
+ }
494
+
495
+ [data-solvapay-activation-flow-retrying],
496
+ .solvapay-activation-flow-retrying,
497
+ [data-solvapay-activation-flow-activated],
498
+ .solvapay-activation-flow-activated {
499
+ background: var(--solvapay-muted);
500
+ border-radius: var(--solvapay-radius);
501
+ padding: 1rem;
502
+ }
503
+
504
+ [data-solvapay-activation-flow-loading] {
505
+ color: var(--solvapay-muted-foreground);
506
+ font-size: 0.875rem;
507
+ padding: 1rem 0;
508
+ }
509
+
510
+ [data-solvapay-activation-flow-error],
511
+ .solvapay-activation-flow-error {
512
+ color: var(--solvapay-destructive);
513
+ font-size: 0.875rem;
514
+ padding: 0.75rem 1rem;
515
+ border: 1px solid var(--solvapay-destructive);
516
+ border-radius: var(--solvapay-radius);
517
+ background: color-mix(in srgb, var(--solvapay-destructive) 6%, transparent);
518
+ }
519
+
520
+ /* -----------------------------------------------------------------------------
521
+ * AmountPicker
522
+ * -------------------------------------------------------------------------- */
523
+
524
+ [data-solvapay-amount-picker],
525
+ .solvapay-amount-picker {
526
+ display: flex;
527
+ flex-direction: column;
528
+ gap: 0.75rem;
529
+ }
530
+
531
+ .solvapay-amount-picker-label,
532
+ .solvapay-amount-picker-custom-label {
533
+ font-size: 0.8125rem;
534
+ font-weight: 500;
535
+ color: var(--solvapay-muted-foreground);
536
+ margin: 0;
537
+ }
538
+
539
+ .solvapay-amount-picker-pills {
540
+ display: flex;
541
+ flex-wrap: wrap;
542
+ gap: 0.5rem;
543
+ }
544
+
545
+ [data-solvapay-amount-picker-option],
546
+ .solvapay-amount-picker-pill {
547
+ background: var(--solvapay-surface);
548
+ border: 1px solid var(--solvapay-border);
549
+ border-radius: 999px;
550
+ color: var(--solvapay-accent);
551
+ cursor: pointer;
552
+ font: inherit;
553
+ font-weight: 500;
554
+ padding: 0.375rem 0.875rem;
555
+ transition:
556
+ background-color 120ms ease,
557
+ border-color 120ms ease,
558
+ color 120ms ease;
559
+ }
560
+
561
+ [data-solvapay-amount-picker-option]:hover:not([data-state='disabled']),
562
+ .solvapay-amount-picker-pill:hover {
563
+ border-color: var(--solvapay-accent);
564
+ }
565
+
566
+ [data-solvapay-amount-picker-option][data-state='selected'] {
567
+ background: var(--solvapay-accent);
568
+ border-color: var(--solvapay-accent);
569
+ color: var(--solvapay-accent-foreground);
570
+ }
571
+
572
+ [data-solvapay-amount-picker-option][data-state='disabled'] {
573
+ opacity: 0.5;
574
+ cursor: not-allowed;
575
+ }
576
+
577
+ [data-solvapay-amount-picker-option]:focus-visible,
578
+ .solvapay-amount-picker-pill:focus-visible {
579
+ outline: 2px solid var(--solvapay-accent);
580
+ outline-offset: 2px;
581
+ }
582
+
583
+ .solvapay-amount-picker-custom-wrapper {
584
+ display: flex;
585
+ flex-direction: column;
586
+ gap: 0.25rem;
587
+ }
588
+
589
+ .solvapay-amount-picker-custom-row {
590
+ display: flex;
591
+ align-items: center;
592
+ gap: 0.5rem;
593
+ background: var(--solvapay-surface);
594
+ border: 1px solid var(--solvapay-border);
595
+ border-radius: var(--solvapay-radius);
596
+ padding: 0.5rem 0.75rem;
597
+ transition: border-color 120ms ease;
598
+ }
599
+
600
+ .solvapay-amount-picker-custom-row:focus-within {
601
+ border-color: var(--solvapay-accent);
602
+ box-shadow: 0 0 0 1px var(--solvapay-accent);
603
+ }
604
+
605
+ .solvapay-amount-picker-currency-symbol {
606
+ color: var(--solvapay-muted-foreground);
607
+ font-weight: 500;
608
+ }
609
+
610
+ [data-solvapay-amount-picker-custom],
611
+ .solvapay-amount-picker-custom-input {
612
+ background: transparent;
613
+ border: none;
614
+ color: var(--solvapay-accent);
615
+ flex: 1;
616
+ font: inherit;
617
+ min-width: 0;
618
+ outline: none;
619
+ padding: 0;
620
+ }
621
+
622
+ [data-solvapay-amount-picker-custom][data-state='active'] {
623
+ color: var(--solvapay-accent);
624
+ }
625
+
626
+ [data-solvapay-amount-picker-custom][data-state='dormant'] {
627
+ color: var(--solvapay-muted-foreground);
628
+ }
629
+
630
+ .solvapay-amount-picker-credit-estimate {
631
+ color: var(--solvapay-muted-foreground);
632
+ font-size: 0.75rem;
633
+ margin: 0;
634
+ }
635
+
636
+ .solvapay-amount-picker-error {
637
+ color: var(--solvapay-destructive);
638
+ font-size: 0.8125rem;
639
+ margin: 0;
640
+ }
641
+
642
+ /* -----------------------------------------------------------------------------
643
+ * BalanceBadge
644
+ * -------------------------------------------------------------------------- */
645
+
646
+ [data-solvapay-balance-badge] {
647
+ display: inline-flex;
648
+ align-items: baseline;
649
+ gap: 0.25rem;
650
+ font-variant-numeric: tabular-nums;
651
+ font-weight: 600;
652
+ color: var(--solvapay-accent);
653
+ }
654
+
655
+ [data-solvapay-balance-badge][data-state='loading'] {
656
+ color: var(--solvapay-muted-foreground);
657
+ }
658
+
659
+ [data-solvapay-balance-badge][data-state='zero'] {
660
+ color: var(--solvapay-destructive);
661
+ }
662
+
663
+ [data-solvapay-balance-badge][data-state='low'] {
664
+ color: var(--solvapay-warning);
665
+ }
666
+
667
+ /* -----------------------------------------------------------------------------
668
+ * CancelPlanButton
669
+ * -------------------------------------------------------------------------- */
670
+
671
+ [data-solvapay-cancel-plan] {
672
+ background: transparent;
673
+ border: 1px solid var(--solvapay-border);
674
+ border-radius: var(--solvapay-radius);
675
+ color: var(--solvapay-accent);
676
+ cursor: pointer;
677
+ font: inherit;
678
+ font-weight: 500;
679
+ padding: 0.5rem 0.875rem;
680
+ transition:
681
+ background-color 120ms ease,
682
+ border-color 120ms ease,
683
+ opacity 120ms ease;
684
+ }
685
+
686
+ [data-solvapay-cancel-plan]:hover:not(:disabled) {
687
+ background: var(--solvapay-muted);
688
+ border-color: var(--solvapay-destructive);
689
+ color: var(--solvapay-destructive);
690
+ }
691
+
692
+ [data-solvapay-cancel-plan]:focus-visible {
693
+ outline: 2px solid var(--solvapay-destructive);
694
+ outline-offset: 2px;
695
+ }
696
+
697
+ [data-solvapay-cancel-plan][data-state='cancelling'],
698
+ [data-solvapay-cancel-plan]:disabled {
699
+ opacity: 0.6;
700
+ cursor: wait;
701
+ }
702
+
703
+ /* -----------------------------------------------------------------------------
704
+ * CancelledPlanNotice
705
+ * -------------------------------------------------------------------------- */
706
+
707
+ [data-solvapay-cancelled-notice],
708
+ .solvapay-cancelled-notice {
709
+ display: flex;
710
+ flex-direction: column;
711
+ gap: 0.5rem;
712
+ background: var(--solvapay-muted);
713
+ border: 1px solid var(--solvapay-border);
714
+ border-radius: var(--solvapay-radius);
715
+ padding: 1rem;
716
+ }
717
+
718
+ [data-solvapay-cancelled-notice][data-state='expired'] {
719
+ border-color: var(--solvapay-destructive);
720
+ background: color-mix(in srgb, var(--solvapay-destructive) 6%, var(--solvapay-muted));
721
+ }
722
+
723
+ [data-solvapay-cancelled-notice-heading],
724
+ .solvapay-cancelled-notice-heading {
725
+ font-size: 0.9375rem;
726
+ font-weight: 600;
727
+ margin: 0;
728
+ color: var(--solvapay-accent);
729
+ }
730
+
731
+ .solvapay-cancelled-notice-details,
732
+ .solvapay-cancelled-notice-footer {
733
+ display: flex;
734
+ flex-direction: column;
735
+ gap: 0.25rem;
736
+ font-size: 0.8125rem;
737
+ color: var(--solvapay-muted-foreground);
738
+ }
739
+
740
+ [data-solvapay-cancelled-notice-days-remaining],
741
+ .solvapay-cancelled-notice-days-remaining {
742
+ color: var(--solvapay-accent);
743
+ font-weight: 500;
744
+ }
745
+
746
+ [data-solvapay-cancelled-notice-reactivate],
747
+ .solvapay-cancelled-notice-reactivate {
748
+ align-self: flex-start;
749
+ background: var(--solvapay-accent);
750
+ color: var(--solvapay-accent-foreground);
751
+ border: none;
752
+ border-radius: var(--solvapay-radius);
753
+ cursor: pointer;
754
+ font: inherit;
755
+ font-weight: 500;
756
+ padding: 0.5rem 0.875rem;
757
+ transition: background-color 120ms ease;
758
+ }
759
+
760
+ [data-solvapay-cancelled-notice-reactivate]:hover:not(:disabled) {
761
+ background: var(--solvapay-accent-hover);
762
+ }
763
+
764
+ [data-solvapay-cancelled-notice-reactivate]:focus-visible {
765
+ outline: 2px solid var(--solvapay-accent);
766
+ outline-offset: 2px;
767
+ }
768
+
769
+ /* -----------------------------------------------------------------------------
770
+ * CreditGate / PurchaseGate
771
+ * -------------------------------------------------------------------------- */
772
+
773
+ [data-solvapay-credit-gate],
774
+ [data-solvapay-purchase-gate],
775
+ .solvapay-credit-gate {
776
+ display: flex;
777
+ flex-direction: column;
778
+ gap: 0.75rem;
779
+ }
780
+
781
+ [data-solvapay-credit-gate-heading],
782
+ .solvapay-credit-gate-heading {
783
+ font-size: 1rem;
784
+ font-weight: 600;
785
+ margin: 0;
786
+ color: var(--solvapay-accent);
787
+ }
788
+
789
+ [data-solvapay-credit-gate-subheading],
790
+ .solvapay-credit-gate-subheading {
791
+ color: var(--solvapay-muted-foreground);
792
+ font-size: 0.875rem;
793
+ margin: 0;
794
+ }
795
+
796
+ [data-solvapay-credit-gate-loading],
797
+ [data-solvapay-purchase-gate-loading] {
798
+ color: var(--solvapay-muted-foreground);
799
+ font-size: 0.875rem;
800
+ }
801
+
802
+ [data-solvapay-credit-gate-error],
803
+ [data-solvapay-purchase-gate-error] {
804
+ color: var(--solvapay-destructive);
805
+ font-size: 0.875rem;
806
+ padding: 0.75rem 1rem;
807
+ border: 1px solid var(--solvapay-destructive);
808
+ border-radius: var(--solvapay-radius);
809
+ background: color-mix(in srgb, var(--solvapay-destructive) 6%, transparent);
810
+ }
811
+
812
+ /* -----------------------------------------------------------------------------
813
+ * TopupForm
814
+ * -------------------------------------------------------------------------- */
815
+
816
+ [data-solvapay-topup-form],
817
+ .solvapay-topup-form {
818
+ display: flex;
819
+ flex-direction: column;
820
+ gap: 1rem;
821
+ }
822
+
823
+ [data-solvapay-topup-form-submit],
824
+ .solvapay-topup-form-submit {
825
+ display: inline-flex;
826
+ align-items: center;
827
+ justify-content: center;
828
+ gap: 0.5rem;
829
+ align-self: stretch;
830
+ background: var(--solvapay-accent);
831
+ color: var(--solvapay-accent-foreground);
832
+ border: none;
833
+ border-radius: var(--solvapay-radius);
834
+ cursor: pointer;
835
+ font: inherit;
836
+ font-weight: 500;
837
+ padding: 0.75rem 1rem;
838
+ transition:
839
+ background-color 120ms ease,
840
+ opacity 120ms ease;
841
+ }
842
+
843
+ [data-solvapay-topup-form-submit]:hover:not(:disabled) {
844
+ background: var(--solvapay-accent-hover);
845
+ }
846
+
847
+ [data-solvapay-topup-form-submit]:disabled,
848
+ [data-solvapay-topup-form-submit][data-state='disabled'] {
849
+ opacity: 0.5;
850
+ cursor: not-allowed;
851
+ }
852
+
853
+ [data-solvapay-topup-form-submit][data-state='processing'] {
854
+ opacity: 0.75;
855
+ cursor: wait;
856
+ }
857
+
858
+ [data-solvapay-topup-form-submit]:focus-visible {
859
+ outline: 2px solid var(--solvapay-accent);
860
+ outline-offset: 2px;
861
+ }
862
+
863
+ [data-solvapay-topup-form-loading],
864
+ .solvapay-topup-form-loading {
865
+ color: var(--solvapay-muted-foreground);
866
+ font-size: 0.875rem;
867
+ }
868
+
869
+ [data-solvapay-topup-form-error],
870
+ .solvapay-topup-form-error {
871
+ color: var(--solvapay-destructive);
872
+ font-size: 0.875rem;
873
+ padding: 0.75rem 1rem;
874
+ border: 1px solid var(--solvapay-destructive);
875
+ border-radius: var(--solvapay-radius);
876
+ background: color-mix(in srgb, var(--solvapay-destructive) 6%, transparent);
877
+ }
878
+
879
+ /* -----------------------------------------------------------------------------
880
+ * Leaves: MandateText, ProductBadge, PlanBadge
881
+ * -------------------------------------------------------------------------- */
882
+
883
+ [data-solvapay-mandate-text] {
884
+ color: var(--solvapay-muted-foreground);
885
+ font-size: 0.75rem;
886
+ line-height: 1.5;
887
+ }
888
+
889
+ [data-solvapay-product-badge] {
890
+ display: inline-flex;
891
+ align-items: center;
892
+ gap: 0.375rem;
893
+ background: var(--solvapay-muted);
894
+ border-radius: 999px;
895
+ color: var(--solvapay-accent);
896
+ font-size: 0.8125rem;
897
+ font-weight: 500;
898
+ padding: 0.25rem 0.625rem;
899
+ }
900
+
901
+ /* -----------------------------------------------------------------------------
902
+ * CurrentPlanCard
903
+ * -------------------------------------------------------------------------- */
904
+
905
+ [data-solvapay-current-plan-card],
906
+ .solvapay-current-plan-card {
907
+ display: flex;
908
+ flex-direction: column;
909
+ gap: 0.5rem;
910
+ background: var(--solvapay-surface);
911
+ border: 1px solid var(--solvapay-border);
912
+ border-radius: var(--solvapay-radius);
913
+ padding: 1rem;
914
+ }
915
+
916
+ [data-solvapay-current-plan-heading],
917
+ .solvapay-current-plan-heading {
918
+ font-size: 1rem;
919
+ font-weight: 600;
920
+ margin: 0;
921
+ color: var(--solvapay-accent);
922
+ }
923
+
924
+ [data-solvapay-current-plan-name],
925
+ .solvapay-current-plan-name {
926
+ font-weight: 600;
927
+ color: var(--solvapay-accent);
928
+ }
929
+
930
+ [data-solvapay-current-plan-price],
931
+ .solvapay-current-plan-price {
932
+ font-size: 1.125rem;
933
+ font-weight: 600;
934
+ color: var(--solvapay-accent);
935
+ font-variant-numeric: tabular-nums;
936
+ }
937
+
938
+ [data-solvapay-current-plan-next-billing],
939
+ [data-solvapay-current-plan-expires],
940
+ .solvapay-current-plan-date-line {
941
+ display: block;
942
+ color: var(--solvapay-muted-foreground);
943
+ font-size: 0.8125rem;
944
+ }
945
+
946
+ [data-solvapay-current-plan-balance-line],
947
+ .solvapay-current-plan-balance-line {
948
+ display: flex;
949
+ align-items: baseline;
950
+ gap: 0.375rem;
951
+ font-size: 0.875rem;
952
+ }
953
+
954
+ [data-solvapay-current-plan-payment-method],
955
+ .solvapay-current-plan-payment-method {
956
+ display: block;
957
+ color: var(--solvapay-muted-foreground);
958
+ font-size: 0.8125rem;
959
+ }
960
+
961
+ [data-solvapay-current-plan-actions],
962
+ .solvapay-current-plan-actions {
963
+ display: flex;
964
+ flex-wrap: wrap;
965
+ gap: 0.5rem;
966
+ margin-top: 0.25rem;
967
+ }
968
+
969
+ /* -----------------------------------------------------------------------------
970
+ * LaunchCustomerPortalButton (also applies to UpdatePaymentMethodButton, which
971
+ * forwards `data-solvapay-update-payment-method` onto the same element).
972
+ *
973
+ * Ready state renders as <a target="_blank">; loading/error render as
974
+ * <button disabled>. The <a> rules explicitly reset `text-decoration` and
975
+ * align the label so the link doesn't fall back to the browser's default
976
+ * underlined styling inside the CurrentPlanCard actions row.
977
+ * -------------------------------------------------------------------------- */
978
+
979
+ [data-solvapay-launch-customer-portal] {
980
+ display: inline-flex;
981
+ align-items: center;
982
+ justify-content: center;
983
+ background: var(--solvapay-accent);
984
+ color: var(--solvapay-accent-foreground);
985
+ border: none;
986
+ border-radius: var(--solvapay-radius);
987
+ cursor: pointer;
988
+ font: inherit;
989
+ font-weight: 500;
990
+ padding: 0.5rem 0.875rem;
991
+ text-decoration: none;
992
+ transition:
993
+ background-color 120ms ease,
994
+ opacity 120ms ease;
995
+ }
996
+
997
+ [data-solvapay-launch-customer-portal][data-state='ready']:hover {
998
+ background: var(--solvapay-accent-hover);
999
+ }
1000
+
1001
+ [data-solvapay-launch-customer-portal]:focus-visible {
1002
+ outline: 2px solid var(--solvapay-accent);
1003
+ outline-offset: 2px;
1004
+ }
1005
+
1006
+ [data-solvapay-launch-customer-portal][data-state='loading'] {
1007
+ opacity: 0.75;
1008
+ cursor: wait;
1009
+ }
1010
+
1011
+ [data-solvapay-launch-customer-portal][data-state='error'] {
1012
+ opacity: 0.5;
1013
+ cursor: not-allowed;
1014
+ }
1015
+
1016
+ /* -----------------------------------------------------------------------------
1017
+ * UsageMeter (Phase 2.2)
1018
+ *
1019
+ * Horizontal progress bar with `data-state="safe|warning|critical|loading"`
1020
+ * on both the root and the bar itself. The fill width is driven by a CSS
1021
+ * custom property so the bar never needs inline styles.
1022
+ * -------------------------------------------------------------------------- */
1023
+
1024
+ :root {
1025
+ --solvapay-usage-safe: var(--solvapay-accent);
1026
+ --solvapay-usage-warning: var(--solvapay-warning);
1027
+ --solvapay-usage-critical: var(--solvapay-destructive);
1028
+ --solvapay-usage-meter-fill: 0%;
1029
+ }
1030
+
1031
+ [data-solvapay-usage-meter] {
1032
+ display: flex;
1033
+ flex-direction: column;
1034
+ gap: 0.375rem;
1035
+ font-size: 0.875rem;
1036
+ color: var(--solvapay-muted-foreground);
1037
+ }
1038
+
1039
+ [data-solvapay-usage-meter-bar] {
1040
+ position: relative;
1041
+ width: 100%;
1042
+ height: 0.5rem;
1043
+ background: var(--solvapay-muted);
1044
+ border-radius: 999px;
1045
+ overflow: hidden;
1046
+ }
1047
+
1048
+ [data-solvapay-usage-meter-bar]::after {
1049
+ content: '';
1050
+ display: block;
1051
+ height: 100%;
1052
+ width: var(--solvapay-usage-meter-fill, 0%);
1053
+ background: var(--solvapay-usage-safe);
1054
+ border-radius: inherit;
1055
+ transition: width 200ms ease;
1056
+ }
1057
+
1058
+ [data-solvapay-usage-meter-bar][data-state='warning']::after {
1059
+ background: var(--solvapay-usage-warning);
1060
+ }
1061
+
1062
+ [data-solvapay-usage-meter-bar][data-state='critical']::after {
1063
+ background: var(--solvapay-usage-critical);
1064
+ }
1065
+
1066
+ [data-solvapay-usage-meter-label] {
1067
+ color: var(--solvapay-accent);
1068
+ font-weight: 500;
1069
+ }
1070
+
1071
+ [data-solvapay-usage-meter-percentage],
1072
+ [data-solvapay-usage-meter-resets-in] {
1073
+ color: var(--solvapay-muted-foreground);
1074
+ }
1075
+
1076
+ [data-solvapay-usage-meter-empty] {
1077
+ color: var(--solvapay-muted-foreground);
1078
+ font-style: italic;
1079
+ }
1080
+
1081
+ /* -----------------------------------------------------------------------------
1082
+ * PaywallNotice (Phase 2.1)
1083
+ * -------------------------------------------------------------------------- */
1084
+
1085
+ [data-solvapay-paywall-notice] {
1086
+ display: flex;
1087
+ flex-direction: column;
1088
+ gap: 0.75rem;
1089
+ padding: 1rem;
1090
+ border: 1px solid var(--solvapay-border);
1091
+ border-radius: var(--solvapay-radius);
1092
+ background: var(--solvapay-surface);
1093
+ }
1094
+
1095
+ [data-solvapay-paywall-heading] {
1096
+ margin: 0;
1097
+ font-size: 1.125rem;
1098
+ font-weight: 600;
1099
+ color: var(--solvapay-accent);
1100
+ }
1101
+
1102
+ [data-solvapay-paywall-message] {
1103
+ margin: 0;
1104
+ color: var(--solvapay-muted-foreground);
1105
+ }
1106
+
1107
+ [data-solvapay-paywall-balance] {
1108
+ font-weight: 500;
1109
+ color: var(--solvapay-accent);
1110
+ }
1111
+
1112
+ [data-solvapay-paywall-retry][data-state='waiting'] {
1113
+ opacity: 0.5;
1114
+ cursor: wait;
1115
+ }