@usefillo/react 0.5.3 → 0.6.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.
@@ -0,0 +1,700 @@
1
+ /**
2
+ * @usefillo/react default theme.
3
+ * Entirely optional — everything is driven by fillo-* classes and CSS variables,
4
+ * so you can theme with variables, override classes, or skip this file and
5
+ * style from scratch.
6
+ */
7
+
8
+ /* Specificity contract: every rule stays at single-class specificity —
9
+ * qualifiers are wrapped in :where() so one consumer class always wins.
10
+ * A lint test (packages/react/test) fails the build on regressions. */
11
+ /* Cascade layers: these defaults live in the `components` layer so that, in
12
+ * apps using Tailwind (or any utility CSS in the `utilities` layer), YOUR
13
+ * classes always win over ours — className="bg-red-50" on an option just
14
+ * works. Without Tailwind the layer has no competition and nothing changes. */
15
+ /* (unlayered variant) */
16
+
17
+
18
+ .fillo-form {
19
+ --fillo-primary: #18181b;
20
+ --fillo-primary-contrast: #ffffff;
21
+ --fillo-bg: transparent;
22
+ --fillo-text: #18181b;
23
+ --fillo-muted: #71717a;
24
+ --fillo-border: #e4e4e7;
25
+ --fillo-error: #dc2626;
26
+ --fillo-radius: 10px;
27
+ --fillo-font: inherit;
28
+ --fillo-control-bg: #ffffff;
29
+
30
+ color-scheme: light;
31
+ font-family: var(--fillo-font);
32
+ color: var(--fillo-text);
33
+ background: var(--fillo-bg);
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: 1.75rem;
37
+ max-width: 100%;
38
+ }
39
+
40
+ .fillo-form[data-fillo-color-scheme="light"] {
41
+ color-scheme: light;
42
+ }
43
+
44
+ .fillo-form[data-fillo-color-scheme="dark"] {
45
+ --fillo-primary: #fafafa;
46
+ --fillo-primary-contrast: #18181b;
47
+ --fillo-text: #f4f4f5;
48
+ --fillo-muted: #a1a1aa;
49
+ --fillo-border: #3f3f46;
50
+ --fillo-error: #f87171;
51
+ --fillo-control-bg: #18181b;
52
+
53
+ color-scheme: dark;
54
+ }
55
+
56
+ @media (prefers-color-scheme: dark) {
57
+ .fillo-form:not([data-fillo-color-scheme="light"]):not([data-fillo-has-color-theme]) {
58
+ --fillo-primary: #fafafa;
59
+ --fillo-primary-contrast: #18181b;
60
+ --fillo-text: #f4f4f5;
61
+ --fillo-muted: #a1a1aa;
62
+ --fillo-border: #3f3f46;
63
+ --fillo-error: #f87171;
64
+ --fillo-control-bg: #18181b;
65
+
66
+ color-scheme: dark;
67
+ }
68
+ }
69
+
70
+ .fillo-header { display: flex; flex-direction: column; gap: 0.5rem; }
71
+ .fillo-title { font-size: 1.6rem; font-weight: 650; letter-spacing: 0; margin: 0; }
72
+ .fillo-form-description { color: var(--fillo-muted); margin: 0; line-height: 1.55; }
73
+ .fillo-page-title { font-size: 1.2rem; font-weight: 600; margin: 0; }
74
+
75
+ .fillo-blocks { display: flex; flex-direction: column; gap: 1.5rem; }
76
+
77
+ /* ---------- Field chrome ---------- */
78
+ .fillo-field { display: flex; flex-direction: column; gap: 0.45rem; }
79
+ .fillo-label { font-weight: 550; font-size: 0.95rem; }
80
+ /* Fillo marks the few optional fields rather than starring the many required
81
+ ones — so a clean label reads as required by default. */
82
+ .fillo-optional { color: var(--fillo-muted); font-weight: 400; font-size: 0.85em; }
83
+ .fillo-description { color: var(--fillo-muted); font-size: 0.85rem; margin: 0; line-height: 1.5; }
84
+ .fillo-error { color: var(--fillo-error); font-size: 0.85rem; margin: 0; }
85
+ .fillo-submit-error { color: var(--fillo-error); font-size: 0.85rem; font-weight: 500; margin: 0; }
86
+
87
+ /* ---------- Inputs ---------- */
88
+ .fillo-input {
89
+ appearance: none;
90
+ font: inherit;
91
+ color: var(--fillo-text);
92
+ background: var(--fillo-control-bg);
93
+ border: 1px solid var(--fillo-border);
94
+ border-radius: var(--fillo-radius);
95
+ min-height: 2.5rem;
96
+ padding: 0.6rem 0.8rem;
97
+ transition: border-color 120ms ease, box-shadow 120ms ease;
98
+ width: 100%;
99
+ box-sizing: border-box;
100
+ }
101
+ .fillo-input:focus-visible {
102
+ outline: none;
103
+ border-color: var(--fillo-primary);
104
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
105
+ }
106
+ :where(.fillo-field--error) .fillo-input { border-color: var(--fillo-error); }
107
+ .fillo-textarea { resize: vertical; min-height: 6rem; }
108
+
109
+ /* Phone field: country picker + national input */
110
+ .fillo-phone { position: relative; display: flex; align-items: stretch; gap: 0.4rem; }
111
+ .fillo-phone-country { position: relative; flex: 0 0 auto; }
112
+ .fillo-phone-flag {
113
+ display: inline-flex; align-items: center; gap: 0.35rem;
114
+ height: 100%; min-height: 2.5rem; padding: 0 0.6rem;
115
+ font: inherit; color: var(--fillo-text);
116
+ background: var(--fillo-control-bg);
117
+ border: 1px solid var(--fillo-border); border-radius: var(--fillo-radius);
118
+ cursor: pointer; white-space: nowrap;
119
+ transition: border-color 120ms ease, box-shadow 120ms ease;
120
+ }
121
+ .fillo-phone-flag:focus-visible {
122
+ outline: none; border-color: var(--fillo-primary);
123
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
124
+ }
125
+ .fillo-phone-flag-emoji { font-size: 1.15em; line-height: 1; }
126
+ .fillo-phone-dial { font-variant-numeric: tabular-nums; color: var(--fillo-muted); }
127
+ .fillo-phone-caret { font-size: 0.65em; color: var(--fillo-muted); }
128
+ .fillo-phone-input { flex: 1 1 auto; min-width: 0; }
129
+ :where(.fillo-field--error) .fillo-phone-flag { border-color: var(--fillo-error); }
130
+ .fillo-phone-popover {
131
+ position: absolute; z-index: 30; top: calc(100% + 0.3rem); left: 0;
132
+ width: min(18rem, calc(100vw - 1rem));
133
+ max-width: var(--fillo-phone-popover-max-width, 84vw);
134
+ max-height: min(var(--fillo-phone-popover-max-height, 20rem), calc(100vh - 1rem));
135
+ padding: 0.4rem;
136
+ box-sizing: border-box; overflow: hidden;
137
+ transform: translateX(var(--fillo-phone-popover-offset-x, 0px));
138
+ display: flex; flex-direction: column; gap: 0.35rem;
139
+ background: var(--fillo-control-bg);
140
+ border: 1px solid var(--fillo-border); border-radius: var(--fillo-radius);
141
+ box-shadow: 0 12px 32px -14px rgba(0, 0, 0, 0.35);
142
+ }
143
+ .fillo-phone-popover--above { top: auto; bottom: calc(100% + 0.3rem); }
144
+ .fillo-phone-search {
145
+ appearance: none; font: inherit; width: 100%; box-sizing: border-box;
146
+ color: var(--fillo-text); background: var(--fillo-bg);
147
+ border: 1px solid var(--fillo-border);
148
+ border-radius: calc(var(--fillo-radius) - 3px); padding: 0.45rem 0.6rem;
149
+ }
150
+ .fillo-phone-search:focus-visible { outline: none; border-color: var(--fillo-primary); }
151
+ .fillo-phone-list {
152
+ flex: 1 1 auto; min-height: 0;
153
+ list-style: none; margin: 0; padding: 0; max-height: 14rem; overflow-y: auto;
154
+ }
155
+ .fillo-phone-option {
156
+ display: flex; align-items: center; gap: 0.5rem;
157
+ padding: 0.45rem 0.5rem; border-radius: calc(var(--fillo-radius) - 3px);
158
+ cursor: pointer; color: var(--fillo-text);
159
+ }
160
+ .fillo-phone-option--active { background: color-mix(in srgb, var(--fillo-primary) 10%, transparent); }
161
+ .fillo-phone-option-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
162
+ .fillo-phone-option-dial { color: var(--fillo-muted); font-variant-numeric: tabular-nums; }
163
+ .fillo-phone-empty { padding: 0.6rem 0.5rem; color: var(--fillo-muted); }
164
+ .fillo-select-wrap {
165
+ position: relative;
166
+ display: block;
167
+ }
168
+ .fillo-select {
169
+ cursor: pointer;
170
+ padding-right: 2.45rem;
171
+ }
172
+ .fillo-select-icon {
173
+ pointer-events: none;
174
+ position: absolute;
175
+ top: 50%;
176
+ right: 0.9rem;
177
+ width: 0.62rem;
178
+ height: 0.62rem;
179
+ border-right: 1.5px solid currentColor;
180
+ border-bottom: 1.5px solid currentColor;
181
+ color: var(--fillo-muted);
182
+ transform: translateY(-65%) rotate(45deg);
183
+ transition: color 120ms ease;
184
+ }
185
+ :where(.fillo-select-wrap:focus-within) .fillo-select-icon { color: var(--fillo-primary); }
186
+
187
+ /* ---------- Choices ---------- */
188
+ .fillo-options { display: flex; flex-direction: column; gap: 0.5rem; }
189
+ .fillo-option {
190
+ position: relative;
191
+ display: flex;
192
+ align-items: center;
193
+ gap: 0.6rem;
194
+ border: 1px solid var(--fillo-border);
195
+ border-radius: var(--fillo-radius);
196
+ background: var(--fillo-control-bg);
197
+ padding: 0.55rem 0.8rem;
198
+ cursor: pointer;
199
+ transition: border-color 120ms ease, background 120ms ease;
200
+ }
201
+ .fillo-option:hover { border-color: color-mix(in srgb, var(--fillo-primary) 45%, var(--fillo-border)); }
202
+ .fillo-option:focus-within {
203
+ border-color: var(--fillo-primary);
204
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 14%, transparent);
205
+ }
206
+ .fillo-option--selected {
207
+ border-color: var(--fillo-primary);
208
+ background: color-mix(in srgb, var(--fillo-primary) 6%, var(--fillo-control-bg));
209
+ }
210
+ .fillo-option-input {
211
+ accent-color: var(--fillo-primary);
212
+ flex: 0 0 auto;
213
+ width: 1rem;
214
+ height: 1rem;
215
+ margin: 0;
216
+ }
217
+ .fillo-option-input:focus-visible { outline: none; }
218
+ :where(.fillo-option--has-icon) .fillo-option-input {
219
+ position: absolute;
220
+ width: 1px;
221
+ height: 1px;
222
+ overflow: hidden;
223
+ opacity: 0;
224
+ pointer-events: none;
225
+ }
226
+ .fillo-option-icon {
227
+ width: 1.05rem;
228
+ height: 1.05rem;
229
+ flex: 0 0 auto;
230
+ color: var(--fillo-muted);
231
+ transition: color 120ms ease;
232
+ }
233
+ :where(.fillo-option--selected) .fillo-option-icon { color: var(--fillo-primary); }
234
+ .fillo-option-label { font-size: 0.95rem; }
235
+
236
+ .fillo-option-main {
237
+ display: flex;
238
+ align-items: center;
239
+ gap: 0.6rem;
240
+ min-width: 0;
241
+ }
242
+ .fillo-option--with-other {
243
+ align-items: stretch;
244
+ flex-direction: column;
245
+ gap: 0.55rem;
246
+ }
247
+ :where(.fillo-option--with-other) .fillo-option-label {
248
+ font-weight: 550;
249
+ }
250
+
251
+ /* ---------- Toggle checkbox ---------- */
252
+ .fillo-toggle {
253
+ position: relative;
254
+ display: flex;
255
+ align-items: center;
256
+ justify-content: space-between;
257
+ gap: 1rem;
258
+ border: 1px solid var(--fillo-border);
259
+ border-radius: var(--fillo-radius);
260
+ background: var(--fillo-control-bg);
261
+ padding: 0.65rem 0.8rem;
262
+ cursor: pointer;
263
+ transition: border-color 120ms ease, background 120ms ease, box-shadow 120ms ease;
264
+ }
265
+ .fillo-toggle:hover { border-color: color-mix(in srgb, var(--fillo-primary) 45%, var(--fillo-border)); }
266
+ .fillo-toggle-copy { min-width: 0; }
267
+ .fillo-toggle-input {
268
+ position: absolute;
269
+ width: 1px;
270
+ height: 1px;
271
+ overflow: hidden;
272
+ clip: rect(0 0 0 0);
273
+ clip-path: inset(50%);
274
+ white-space: nowrap;
275
+ }
276
+ .fillo-toggle-track {
277
+ position: relative;
278
+ display: inline-flex;
279
+ width: 2.35rem;
280
+ height: 1.35rem;
281
+ flex: 0 0 auto;
282
+ align-items: center;
283
+ border-radius: 999px;
284
+ background: color-mix(in srgb, var(--fillo-muted) 18%, var(--fillo-control-bg));
285
+ box-shadow: inset 0 0 0 1px var(--fillo-border);
286
+ transition: background 160ms ease, box-shadow 160ms ease;
287
+ }
288
+ .fillo-toggle-thumb {
289
+ width: 1rem;
290
+ height: 1rem;
291
+ margin-left: 0.18rem;
292
+ border-radius: 999px;
293
+ background: var(--fillo-control-bg);
294
+ box-shadow: 0 1px 2px color-mix(in srgb, var(--fillo-text) 18%, transparent);
295
+ transition: transform 160ms ease, background 160ms ease;
296
+ }
297
+ :where(.fillo-toggle-input:checked) + .fillo-toggle-track {
298
+ background: var(--fillo-primary);
299
+ box-shadow: inset 0 0 0 1px var(--fillo-primary);
300
+ }
301
+ :where(.fillo-toggle-input:checked) + :where(.fillo-toggle-track) .fillo-toggle-thumb {
302
+ transform: translateX(1rem);
303
+ background: var(--fillo-primary-contrast);
304
+ }
305
+ :where(.fillo-toggle-input:focus-visible) + .fillo-toggle-track {
306
+ box-shadow:
307
+ inset 0 0 0 1px var(--fillo-primary),
308
+ 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
309
+ }
310
+ .fillo-toggle:where(:has(.fillo-toggle-input:checked)) {
311
+ border-color: var(--fillo-primary);
312
+ background: color-mix(in srgb, var(--fillo-primary) 5%, var(--fillo-control-bg));
313
+ }
314
+
315
+ /* "Other" free-text input — nested inside choice rows, block under dropdowns. */
316
+ .fillo-other-input {
317
+ width: 100%;
318
+ min-width: 0;
319
+ margin-left: 0;
320
+ padding: 0.5rem 0.7rem;
321
+ font-size: 0.92rem;
322
+ background: color-mix(in srgb, var(--fillo-primary) 3%, var(--fillo-control-bg));
323
+ }
324
+ .fillo-other-input--block {
325
+ margin-top: 0.45rem;
326
+ padding: 0.55rem 0.8rem;
327
+ }
328
+
329
+ /* ---------- Rating ---------- */
330
+ .fillo-rating { display: flex; gap: 0.25rem; }
331
+ .fillo-star {
332
+ font-size: 1.6rem;
333
+ line-height: 1;
334
+ background: none;
335
+ border: none;
336
+ cursor: pointer;
337
+ color: var(--fillo-border);
338
+ padding: 0.1rem;
339
+ transition: color 100ms ease, transform 100ms ease;
340
+ }
341
+ .fillo-star:hover { transform: scale(1.15); }
342
+ .fillo-star--active { color: var(--fillo-primary); }
343
+ .fillo-star:focus-visible {
344
+ outline: none;
345
+ border-radius: calc(var(--fillo-radius) * 0.5);
346
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 30%, transparent);
347
+ }
348
+
349
+ /* ---------- Linear scale ---------- */
350
+ /* Steps share one row and shrink to fit — an 11-step NPS scale must never
351
+ wrap onto a second line, even in narrow embeds. */
352
+ .fillo-scale { display: flex; gap: 0.35rem; }
353
+ .fillo-scale-step {
354
+ flex: 1 1 0;
355
+ min-width: 0;
356
+ padding: 0.5rem 0.15rem;
357
+ font: inherit;
358
+ font-size: 0.92em;
359
+ font-variant-numeric: tabular-nums;
360
+ text-align: center;
361
+ border: 1px solid var(--fillo-border);
362
+ border-radius: var(--fillo-radius);
363
+ background: var(--fillo-control-bg);
364
+ cursor: pointer;
365
+ transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
366
+ }
367
+ .fillo-scale-step:hover { border-color: var(--fillo-primary); }
368
+ .fillo-scale-step:focus-visible {
369
+ outline: none;
370
+ border-color: var(--fillo-primary);
371
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
372
+ }
373
+ .fillo-scale-step--active {
374
+ background: var(--fillo-primary);
375
+ border-color: var(--fillo-primary);
376
+ color: var(--fillo-primary-contrast);
377
+ }
378
+ .fillo-scale-labels {
379
+ display: flex;
380
+ justify-content: space-between;
381
+ color: var(--fillo-muted);
382
+ font-size: 0.78rem;
383
+ margin-top: 0.35rem;
384
+ }
385
+
386
+ /* ---------- Ranking ---------- */
387
+ .fillo-ranking { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.45rem; }
388
+ .fillo-ranking-item {
389
+ display: flex;
390
+ align-items: center;
391
+ gap: 0.7rem;
392
+ border: 1px solid var(--fillo-border);
393
+ border-radius: var(--fillo-radius);
394
+ background: var(--fillo-control-bg);
395
+ padding: 0.5rem 0.7rem;
396
+ }
397
+ .fillo-ranking-index {
398
+ display: grid;
399
+ place-items: center;
400
+ width: 1.5rem;
401
+ height: 1.5rem;
402
+ border-radius: 999px;
403
+ background: color-mix(in srgb, var(--fillo-primary) 10%, transparent);
404
+ color: var(--fillo-primary);
405
+ font-size: 0.78rem;
406
+ font-weight: 650;
407
+ font-variant-numeric: tabular-nums;
408
+ }
409
+ .fillo-ranking-label { flex: 1; font-size: 0.95rem; }
410
+ .fillo-ranking-controls { display: flex; gap: 0.2rem; }
411
+ .fillo-ranking-move {
412
+ font: inherit;
413
+ border: 1px solid var(--fillo-border);
414
+ background: transparent;
415
+ border-radius: calc(var(--fillo-radius) * 0.6);
416
+ cursor: pointer;
417
+ padding: 0.15rem 0.45rem;
418
+ color: var(--fillo-muted);
419
+ transition: color 120ms ease, border-color 120ms ease;
420
+ }
421
+ .fillo-ranking-move:hover:not(:disabled) { color: var(--fillo-primary); border-color: var(--fillo-primary); }
422
+ .fillo-ranking-move:disabled { opacity: 0.35; cursor: default; }
423
+
424
+ /* ---------- Matrix ---------- */
425
+ .fillo-matrix-wrap { overflow-x: auto; }
426
+ .fillo-matrix { border-collapse: collapse; width: 100%; font-size: 0.9rem; }
427
+ :where(.fillo-matrix) th, :where(.fillo-matrix) td {
428
+ padding: 0.55rem 0.7rem;
429
+ text-align: center;
430
+ border-bottom: 1px solid var(--fillo-border);
431
+ }
432
+ .fillo-matrix thead th { color: var(--fillo-muted); font-weight: 500; font-size: 0.8rem; }
433
+ .fillo-matrix tbody th { text-align: left; font-weight: 500; }
434
+ .fillo-matrix tbody tr:last-child th, .fillo-matrix tbody tr:last-child td { border-bottom: none; }
435
+
436
+ /* ---------- Signature ---------- */
437
+ .fillo-signature {
438
+ position: relative;
439
+ border: 1.5px dashed var(--fillo-border);
440
+ border-radius: var(--fillo-radius);
441
+ background: var(--fillo-control-bg);
442
+ }
443
+ .fillo-signature-canvas {
444
+ display: block;
445
+ width: 100%;
446
+ height: 9rem;
447
+ color: var(--fillo-text);
448
+ touch-action: none;
449
+ cursor: crosshair;
450
+ }
451
+ .fillo-signature-hint {
452
+ position: absolute;
453
+ inset: 0;
454
+ display: grid;
455
+ place-items: center;
456
+ color: var(--fillo-muted);
457
+ font-size: 0.85rem;
458
+ pointer-events: none;
459
+ }
460
+ .fillo-signature-clear {
461
+ position: absolute;
462
+ top: 0.4rem;
463
+ right: 0.4rem;
464
+ font: inherit;
465
+ font-size: 0.75rem;
466
+ border: 1px solid var(--fillo-border);
467
+ border-radius: calc(var(--fillo-radius) * 0.6);
468
+ background: var(--fillo-control-bg);
469
+ color: var(--fillo-muted);
470
+ padding: 0.15rem 0.5rem;
471
+ cursor: pointer;
472
+ }
473
+ .fillo-signature-clear:hover { color: var(--fillo-error); border-color: var(--fillo-error); }
474
+
475
+ /* Type-to-sign: the keyboard/screen-reader path under the canvas. */
476
+ .fillo-signature-type {
477
+ display: flex;
478
+ flex-direction: column;
479
+ gap: 0.35rem;
480
+ margin-top: 0.55rem;
481
+ }
482
+ .fillo-signature-type-label {
483
+ color: var(--fillo-muted);
484
+ font-size: 0.8rem;
485
+ }
486
+ .fillo-signature-type-input {
487
+ margin-top: 0;
488
+ }
489
+
490
+ /* ---------- File upload ---------- */
491
+ .fillo-dropzone {
492
+ display: flex;
493
+ flex-direction: column;
494
+ align-items: center;
495
+ gap: 0.25rem;
496
+ border: 1.5px dashed var(--fillo-border);
497
+ border-radius: var(--fillo-radius);
498
+ padding: 1.6rem 1rem;
499
+ text-align: center;
500
+ cursor: pointer;
501
+ background: color-mix(in srgb, var(--fillo-control-bg) 60%, transparent);
502
+ transition: border-color 120ms ease, background 120ms ease;
503
+ }
504
+ .fillo-dropzone:hover,
505
+ .fillo-dropzone--over {
506
+ border-color: var(--fillo-primary);
507
+ background: color-mix(in srgb, var(--fillo-primary) 4%, var(--fillo-control-bg));
508
+ }
509
+ .fillo-dropzone:focus-visible {
510
+ outline: none;
511
+ border-color: var(--fillo-primary);
512
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 15%, transparent);
513
+ }
514
+ .fillo-dropzone--disabled { cursor: not-allowed; opacity: 0.6; }
515
+ .fillo-dropzone-title { font-weight: 550; font-size: 0.95rem; }
516
+ .fillo-dropzone-hint { color: var(--fillo-muted); font-size: 0.82rem; }
517
+
518
+ .fillo-files { list-style: none; display: flex; flex-direction: column; gap: 0.45rem; margin: 0; padding: 0; }
519
+ .fillo-file {
520
+ display: grid;
521
+ grid-template-columns: 1fr auto auto;
522
+ align-items: center;
523
+ gap: 0.3rem 0.8rem;
524
+ border: 1px solid var(--fillo-border);
525
+ border-radius: var(--fillo-radius);
526
+ padding: 0.5rem 0.75rem;
527
+ font-size: 0.88rem;
528
+ background: var(--fillo-control-bg);
529
+ }
530
+ .fillo-file--failed { border-color: var(--fillo-error); }
531
+ .fillo-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
532
+ .fillo-file-meta { color: var(--fillo-muted); font-variant-numeric: tabular-nums; }
533
+ .fillo-file-remove {
534
+ background: none; border: none; cursor: pointer;
535
+ color: var(--fillo-muted); font-size: 1.1rem; line-height: 1; padding: 0 0.2rem;
536
+ }
537
+ .fillo-file-remove:hover { color: var(--fillo-error); }
538
+ .fillo-progress {
539
+ grid-column: 1 / -1;
540
+ height: 4px;
541
+ border-radius: 999px;
542
+ background: var(--fillo-border);
543
+ overflow: hidden;
544
+ }
545
+ .fillo-progress-bar {
546
+ display: block;
547
+ height: 100%;
548
+ background: var(--fillo-primary);
549
+ border-radius: inherit;
550
+ transition: width 200ms ease;
551
+ }
552
+
553
+ /* ---------- Content blocks ---------- */
554
+ .fillo-heading { font-size: 1.15rem; font-weight: 600; margin: 0.5rem 0 0; }
555
+ .fillo-paragraph { color: var(--fillo-muted); line-height: 1.6; margin: 0; }
556
+ .fillo-divider { border: none; border-top: 1px solid var(--fillo-border); margin: 0.25rem 0; }
557
+
558
+ /* ---------- Footer / buttons ---------- */
559
+ .fillo-footer { display: flex; justify-content: flex-end; gap: 0.6rem; }
560
+ .fillo-button {
561
+ font: inherit;
562
+ font-weight: 550;
563
+ border-radius: var(--fillo-radius);
564
+ padding: 0.6rem 1.4rem;
565
+ cursor: pointer;
566
+ border: 1px solid transparent;
567
+ transition: opacity 120ms ease, transform 60ms ease;
568
+ }
569
+ .fillo-button:active { transform: translateY(1px); }
570
+ .fillo-button:disabled { opacity: 0.55; cursor: not-allowed; }
571
+ .fillo-button:focus-visible {
572
+ outline: none;
573
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fillo-primary) 30%, transparent);
574
+ }
575
+ .fillo-button--primary { background: var(--fillo-primary); color: var(--fillo-primary-contrast); }
576
+ .fillo-button--ghost { background: transparent; color: var(--fillo-text); border-color: var(--fillo-border); }
577
+
578
+ /* ---------- Progress (multi-page) ---------- */
579
+ .fillo-progress-track {
580
+ height: 4px;
581
+ border-radius: 999px;
582
+ background: var(--fillo-border);
583
+ overflow: hidden;
584
+ }
585
+ .fillo-progress-fill {
586
+ width: var(--fillo-progress-value, 0%);
587
+ height: 100%;
588
+ background: var(--fillo-primary);
589
+ border-radius: inherit;
590
+ transition: width 300ms ease;
591
+ }
592
+
593
+ /* ---------- Closed ---------- */
594
+ .fillo-closed {
595
+ text-align: center;
596
+ color: var(--fillo-muted);
597
+ padding: 2rem 1rem;
598
+ margin: 0;
599
+ }
600
+
601
+ /* ---------- Success ---------- */
602
+ .fillo-success { display: flex; flex-direction: column; align-items: center; gap: 0.4rem; text-align: center; padding: 1.4rem 1rem; }
603
+ .fillo-success-mark {
604
+ width: 2rem; height: 2rem;
605
+ display: grid; place-items: center;
606
+ border-radius: 999px;
607
+ background: color-mix(in srgb, var(--fillo-primary) 10%, transparent);
608
+ color: var(--fillo-primary);
609
+ font-size: 0.95rem; font-weight: 700;
610
+ }
611
+ .fillo-success-title { margin: 0; font-size: 1.05rem; letter-spacing: 0; }
612
+ .fillo-success-message { margin: 0; font-size: 0.875rem; color: var(--fillo-muted); }
613
+
614
+ /* Honeypot — off-screen, never display:none (bots check that) */
615
+ .fillo-hp {
616
+ position: absolute;
617
+ left: -9999px;
618
+ width: 1px;
619
+ height: 1px;
620
+ opacity: 0;
621
+ pointer-events: none;
622
+ }
623
+
624
+ /* Visually hidden but exposed to assistive tech — for aria-live narration. */
625
+ .fillo-sr-only {
626
+ position: absolute;
627
+ width: 1px;
628
+ height: 1px;
629
+ margin: -1px;
630
+ padding: 0;
631
+ overflow: hidden;
632
+ clip: rect(0 0 0 0);
633
+ clip-path: inset(50%);
634
+ white-space: nowrap;
635
+ border: 0;
636
+ }
637
+
638
+ /* ---------- Loading skeleton ---------- */
639
+ .fillo-form--loading { gap: 0.9rem; }
640
+ .fillo-skeleton {
641
+ height: 2.4rem;
642
+ border-radius: var(--fillo-radius);
643
+ background: linear-gradient(90deg, var(--fillo-border) 25%, color-mix(in srgb, var(--fillo-border) 40%, transparent) 50%, var(--fillo-border) 75%);
644
+ background-size: 200% 100%;
645
+ animation: fillo-shimmer 1.4s infinite;
646
+ }
647
+ .fillo-skeleton--short { width: 40%; }
648
+ @keyframes fillo-shimmer {
649
+ to { background-position: -200% 0; }
650
+ }
651
+
652
+ /* Respect a reduced-motion preference: drop transitions, the press nudge,
653
+ the rating hover scale, and the skeleton shimmer. */
654
+ @media (prefers-reduced-motion: reduce) {
655
+ .fillo-form *,
656
+ .fillo-form *::before,
657
+ .fillo-form *::after {
658
+ animation-duration: 0.001ms !important;
659
+ animation-iteration-count: 1 !important;
660
+ transition-duration: 0.001ms !important;
661
+ scroll-behavior: auto !important;
662
+ }
663
+ .fillo-button:active { transform: none; }
664
+ .fillo-star:hover { transform: none; }
665
+ .fillo-skeleton { animation: none; }
666
+ }
667
+
668
+ /* ---------- "Powered by Fillo" badge ---------- */
669
+ .fillo-powered {
670
+ display: block;
671
+ margin-top: 1.25rem;
672
+ text-align: center;
673
+ font-size: 0.75rem;
674
+ font-weight: 500;
675
+ letter-spacing: 0;
676
+ color: var(--fillo-muted);
677
+ text-decoration: none;
678
+ opacity: 0.75;
679
+ transition: opacity 120ms ease;
680
+ }
681
+ .fillo-powered:hover { opacity: 1; }
682
+
683
+ /* ---------- Dev-only "no client" notice (stripped in production builds) ---------- */
684
+ .fillo-devwarning {
685
+ margin-bottom: 1rem;
686
+ padding: 0.75rem 0.9rem;
687
+ border: 1px solid #f59e0b;
688
+ border-radius: var(--fillo-radius);
689
+ background: #fffbeb;
690
+ color: #92400e;
691
+ font-size: 0.82rem;
692
+ line-height: 1.45;
693
+ }
694
+ .fillo-devwarning code {
695
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
696
+ font-size: 0.92em;
697
+ background: #fef3c7;
698
+ padding: 0.05em 0.3em;
699
+ border-radius: 4px;
700
+ }