@facturion/invoice-renderer 0.1.0 → 0.2.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.
- package/index.d.ts +1 -1
- package/package.json +6 -5
- package/src/document.js +6 -11
- package/src/render.js +4 -1
- package/src/styles.js +4 -0
- package/styles/invoice.css +509 -0
- package/styles/utilities.css +0 -227
- package/styles/variables.css +0 -89
- package/styles/view.css +0 -902
package/styles/view.css
DELETED
|
@@ -1,902 +0,0 @@
|
|
|
1
|
-
/* ── View page ──────────────────────────────────────────────────────────────── */
|
|
2
|
-
|
|
3
|
-
.view-layout {
|
|
4
|
-
max-width: 880px;
|
|
5
|
-
margin: 0 auto;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.view-drop-card {
|
|
9
|
-
margin-bottom: var(--space-5);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/* Modeled on .validate-tabs: the toolbar acts as the tab bar — the active
|
|
13
|
-
tab's underline overlaps the toolbar's border-bottom for a unified strip. */
|
|
14
|
-
.view-toolbar {
|
|
15
|
-
display: flex;
|
|
16
|
-
align-items: end;
|
|
17
|
-
gap: var(--space-3);
|
|
18
|
-
margin-bottom: var(--space-4);
|
|
19
|
-
border-bottom: 1px solid var(--border);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.view-toolbar .mode-tabs { margin-right: auto; }
|
|
23
|
-
|
|
24
|
-
/* Action buttons sit centered against the bar so they don't touch the
|
|
25
|
-
separator line — same treatment as .tab-download-btn in /validate. */
|
|
26
|
-
.view-toolbar .print-btn { align-self: center; }
|
|
27
|
-
|
|
28
|
-
/* ── Invoice paper ─────────────────────────────────────────────────────────── */
|
|
29
|
-
|
|
30
|
-
.invoice-paper {
|
|
31
|
-
background: #fdf8f0;
|
|
32
|
-
color: #111;
|
|
33
|
-
border-radius: var(--radius-md);
|
|
34
|
-
padding: var(--space-10);
|
|
35
|
-
box-shadow: var(--shadow-lg);
|
|
36
|
-
font-size: var(--text-sm);
|
|
37
|
-
line-height: 1.6;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/* ── Invoice header ────────────────────────────────────────────────────────── */
|
|
41
|
-
|
|
42
|
-
.inv-header {
|
|
43
|
-
display: flex;
|
|
44
|
-
justify-content: space-between;
|
|
45
|
-
align-items: flex-start;
|
|
46
|
-
margin-bottom: var(--space-8);
|
|
47
|
-
padding-bottom: var(--space-6);
|
|
48
|
-
border-bottom: 2px solid #e2e8f0;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.inv-type {
|
|
52
|
-
font-size: var(--text-xs);
|
|
53
|
-
font-weight: 700;
|
|
54
|
-
letter-spacing: 0.1em;
|
|
55
|
-
text-transform: uppercase;
|
|
56
|
-
color: #64748b;
|
|
57
|
-
margin-bottom: var(--space-1);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.inv-id {
|
|
61
|
-
font-size: var(--text-xl);
|
|
62
|
-
font-weight: 700;
|
|
63
|
-
color: #0f172a;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.inv-header-right {
|
|
67
|
-
text-align: right;
|
|
68
|
-
color: #475569;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.inv-header-right > div {
|
|
72
|
-
margin-bottom: var(--space-1);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* ── Parties ───────────────────────────────────────────────────────────────── */
|
|
76
|
-
|
|
77
|
-
.inv-parties {
|
|
78
|
-
display: grid;
|
|
79
|
-
grid-template-columns: 1fr 1fr;
|
|
80
|
-
gap: var(--space-8);
|
|
81
|
-
margin-bottom: var(--space-8);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.inv-party-label {
|
|
85
|
-
font-size: var(--text-xs);
|
|
86
|
-
font-weight: 700;
|
|
87
|
-
letter-spacing: 0.08em;
|
|
88
|
-
text-transform: uppercase;
|
|
89
|
-
color: #94a3b8;
|
|
90
|
-
margin-bottom: var(--space-2);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.inv-party-name {
|
|
94
|
-
font-weight: 600;
|
|
95
|
-
color: #0f172a;
|
|
96
|
-
margin-bottom: var(--space-1);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.inv-party > div {
|
|
100
|
-
color: #475569;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.inv-party-trading {
|
|
104
|
-
font-style: italic;
|
|
105
|
-
color: #64748b !important;
|
|
106
|
-
margin-bottom: var(--space-1);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.inv-party-legal {
|
|
110
|
-
margin-top: var(--space-2);
|
|
111
|
-
font-size: var(--text-xs);
|
|
112
|
-
color: #64748b !important;
|
|
113
|
-
line-height: 1.4;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.inv-party-contact {
|
|
117
|
-
margin-top: var(--space-2);
|
|
118
|
-
font-size: var(--text-xs);
|
|
119
|
-
color: #475569 !important;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.inv-parties-secondary {
|
|
123
|
-
display: grid;
|
|
124
|
-
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
|
125
|
-
gap: var(--space-6);
|
|
126
|
-
margin-bottom: var(--space-8);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/* ── References ────────────────────────────────────────────────────────────── */
|
|
130
|
-
|
|
131
|
-
.inv-references {
|
|
132
|
-
display: grid;
|
|
133
|
-
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
|
134
|
-
gap: var(--space-1) var(--space-6);
|
|
135
|
-
margin-bottom: var(--space-6);
|
|
136
|
-
padding: var(--space-3) var(--space-4);
|
|
137
|
-
background: #f5ede0;
|
|
138
|
-
border-radius: var(--radius-sm);
|
|
139
|
-
font-size: var(--text-xs);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.inv-ref {
|
|
143
|
-
display: flex;
|
|
144
|
-
gap: var(--space-2);
|
|
145
|
-
color: #475569;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.inv-ref-label {
|
|
149
|
-
font-weight: 600;
|
|
150
|
-
letter-spacing: 0.04em;
|
|
151
|
-
color: #64748b;
|
|
152
|
-
text-transform: uppercase;
|
|
153
|
-
flex-shrink: 0;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.inv-ref-value {
|
|
157
|
-
color: #0f172a;
|
|
158
|
-
word-break: break-all;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/* ── Period / delivery strip ───────────────────────────────────────────────── */
|
|
162
|
-
|
|
163
|
-
.inv-period {
|
|
164
|
-
margin-bottom: var(--space-6);
|
|
165
|
-
padding: var(--space-2) var(--space-4);
|
|
166
|
-
background: #f5ede0;
|
|
167
|
-
border-left: 3px solid #94a3b8;
|
|
168
|
-
border-radius: var(--radius-sm);
|
|
169
|
-
color: #334155;
|
|
170
|
-
font-size: var(--text-sm);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/* ── Notes / payment ───────────────────────────────────────────────────────── */
|
|
174
|
-
|
|
175
|
-
.inv-notes,
|
|
176
|
-
.inv-payment {
|
|
177
|
-
margin-bottom: var(--space-6);
|
|
178
|
-
padding: var(--space-4);
|
|
179
|
-
background: #f5ede0;
|
|
180
|
-
border-radius: var(--radius-sm);
|
|
181
|
-
color: #334155;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/* Keep coherent cards, the totals block, table rows, and short labels on a
|
|
185
|
-
* single page in PDF output — Chromium's paginator respects break-inside. */
|
|
186
|
-
.inv-references,
|
|
187
|
-
.inv-period,
|
|
188
|
-
.inv-notes,
|
|
189
|
-
.inv-payment,
|
|
190
|
-
.inv-payment-terms,
|
|
191
|
-
.inv-totals-wrap,
|
|
192
|
-
.inv-lines tr {
|
|
193
|
-
break-inside: avoid;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.inv-notes p {
|
|
197
|
-
margin: 0 0 var(--space-2) 0;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
.inv-notes p:last-child {
|
|
201
|
-
margin-bottom: 0;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
.inv-payment > div {
|
|
205
|
-
margin-bottom: var(--space-1);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
.inv-section-label {
|
|
209
|
-
font-size: var(--text-xs);
|
|
210
|
-
font-weight: 700;
|
|
211
|
-
letter-spacing: 0.08em;
|
|
212
|
-
text-transform: uppercase;
|
|
213
|
-
color: #64748b;
|
|
214
|
-
margin-bottom: var(--space-2);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.inv-label {
|
|
218
|
-
font-size: var(--text-xs);
|
|
219
|
-
font-weight: 600;
|
|
220
|
-
letter-spacing: 0.04em;
|
|
221
|
-
text-transform: uppercase;
|
|
222
|
-
color: #94a3b8;
|
|
223
|
-
margin-right: 0.3em;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/* ── Line items ────────────────────────────────────────────────────────────── */
|
|
227
|
-
|
|
228
|
-
.inv-lines-wrap {
|
|
229
|
-
margin-bottom: var(--space-6);
|
|
230
|
-
overflow-x: auto;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.inv-lines {
|
|
234
|
-
color: #1e293b;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
.inv-lines thead th {
|
|
238
|
-
background: #f5ede0;
|
|
239
|
-
color: #64748b;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
.inv-col-id {
|
|
243
|
-
width: 3rem;
|
|
244
|
-
color: #94a3b8;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
.inv-col-desc {
|
|
248
|
-
/* takes remaining space */
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.inv-col-num {
|
|
252
|
-
text-align: right;
|
|
253
|
-
white-space: nowrap;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/* ── Line cell internals ───────────────────────────────────────────────────── */
|
|
257
|
-
|
|
258
|
-
.inv-line-name {
|
|
259
|
-
font-weight: 500;
|
|
260
|
-
color: #0f172a;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
.inv-line-desc,
|
|
264
|
-
.inv-line-meta,
|
|
265
|
-
.inv-line-allowance,
|
|
266
|
-
.inv-line-charge {
|
|
267
|
-
font-size: var(--text-xs);
|
|
268
|
-
color: #64748b;
|
|
269
|
-
line-height: 1.4;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
.inv-line-meta {
|
|
273
|
-
margin-top: var(--space-1);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
.inv-line-allowance {
|
|
277
|
-
color: #b45309; /* amber-700 */
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
.inv-line-charge {
|
|
281
|
-
color: #475569;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
.inv-line-price-gross {
|
|
285
|
-
font-size: var(--text-xs);
|
|
286
|
-
color: #94a3b8;
|
|
287
|
-
text-decoration: line-through;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/* ── VAT breakdown sub-rows in the totals table ───────────────────────────── */
|
|
291
|
-
|
|
292
|
-
.inv-vat-base {
|
|
293
|
-
font-size: var(--text-xs);
|
|
294
|
-
color: #94a3b8;
|
|
295
|
-
font-weight: 400;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.inv-vat-reason td {
|
|
299
|
-
padding-top: 0 !important;
|
|
300
|
-
padding-bottom: var(--space-2) !important;
|
|
301
|
-
font-size: var(--text-xs);
|
|
302
|
-
font-style: italic;
|
|
303
|
-
color: #64748b;
|
|
304
|
-
line-height: 1.3;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/* ── Totals ────────────────────────────────────────────────────────────────── */
|
|
308
|
-
|
|
309
|
-
.inv-totals-wrap {
|
|
310
|
-
display: flex;
|
|
311
|
-
justify-content: flex-end;
|
|
312
|
-
margin-bottom: var(--space-6);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
.inv-totals {
|
|
316
|
-
min-width: 280px;
|
|
317
|
-
border-collapse: collapse;
|
|
318
|
-
color: #1e293b;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
.inv-totals td {
|
|
322
|
-
padding: var(--space-1) var(--space-3);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
.inv-totals td:first-child {
|
|
326
|
-
color: #475569;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
.inv-totals td.inv-col-num {
|
|
330
|
-
font-variant-numeric: tabular-nums;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
.inv-totals tr:first-child td {
|
|
334
|
-
padding-top: var(--space-3);
|
|
335
|
-
border-top: 1px solid #e2e8f0;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.inv-totals-payable td {
|
|
339
|
-
padding-top: var(--space-3);
|
|
340
|
-
border-top: 2px solid #e2e8f0;
|
|
341
|
-
font-weight: 700;
|
|
342
|
-
font-size: var(--text-base);
|
|
343
|
-
color: #0f172a;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/* ── Invoice paper dark mode ────────────────────────────────────────────────── */
|
|
347
|
-
|
|
348
|
-
.invoice-paper--dark {
|
|
349
|
-
background: var(--bg-elevated);
|
|
350
|
-
color: var(--text);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/* Header */
|
|
354
|
-
.invoice-paper--dark .inv-header {
|
|
355
|
-
border-bottom-color: var(--border);
|
|
356
|
-
}
|
|
357
|
-
.invoice-paper--dark .inv-type {
|
|
358
|
-
color: var(--text-secondary);
|
|
359
|
-
}
|
|
360
|
-
.invoice-paper--dark .inv-id {
|
|
361
|
-
color: var(--text);
|
|
362
|
-
}
|
|
363
|
-
.invoice-paper--dark .inv-header-right {
|
|
364
|
-
color: var(--text-secondary);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/* Parties */
|
|
368
|
-
.invoice-paper--dark .inv-party-name {
|
|
369
|
-
color: var(--text);
|
|
370
|
-
}
|
|
371
|
-
.invoice-paper--dark .inv-party > div {
|
|
372
|
-
color: var(--text-secondary);
|
|
373
|
-
}
|
|
374
|
-
.invoice-paper--dark .inv-party-label,
|
|
375
|
-
.invoice-paper--dark .inv-label {
|
|
376
|
-
color: var(--text-secondary);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/* Lines */
|
|
380
|
-
.invoice-paper--dark .inv-lines {
|
|
381
|
-
color: var(--text);
|
|
382
|
-
}
|
|
383
|
-
.invoice-paper--dark .inv-lines thead th {
|
|
384
|
-
background: var(--bg-card);
|
|
385
|
-
color: var(--text-secondary);
|
|
386
|
-
}
|
|
387
|
-
.invoice-paper--dark .data-table td {
|
|
388
|
-
color: var(--text-secondary);
|
|
389
|
-
}
|
|
390
|
-
.invoice-paper--dark .inv-col-id {
|
|
391
|
-
color: var(--text-muted);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/* Totals */
|
|
395
|
-
.invoice-paper--dark .inv-totals {
|
|
396
|
-
color: var(--text);
|
|
397
|
-
}
|
|
398
|
-
.invoice-paper--dark .inv-totals td:first-child {
|
|
399
|
-
color: var(--text-secondary);
|
|
400
|
-
}
|
|
401
|
-
.invoice-paper--dark .inv-totals tr:first-child td {
|
|
402
|
-
border-top-color: var(--border);
|
|
403
|
-
}
|
|
404
|
-
.invoice-paper--dark .inv-totals-payable td {
|
|
405
|
-
border-top-color: var(--border-light);
|
|
406
|
-
color: var(--text);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/* Payment terms */
|
|
410
|
-
.invoice-paper--dark .inv-payment-terms {
|
|
411
|
-
color: var(--text-secondary);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/* Secondary party cards + labels */
|
|
415
|
-
.invoice-paper--dark .inv-party-trading,
|
|
416
|
-
.invoice-paper--dark .inv-party-legal,
|
|
417
|
-
.invoice-paper--dark .inv-party-contact {
|
|
418
|
-
color: var(--text-secondary) !important;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/* References / period / notes / payment — neutral info cards */
|
|
422
|
-
.invoice-paper--dark .inv-references,
|
|
423
|
-
.invoice-paper--dark .inv-period,
|
|
424
|
-
.invoice-paper--dark .inv-notes,
|
|
425
|
-
.invoice-paper--dark .inv-payment {
|
|
426
|
-
background: var(--bg-card);
|
|
427
|
-
color: var(--text-secondary);
|
|
428
|
-
}
|
|
429
|
-
.invoice-paper--dark .inv-ref {
|
|
430
|
-
color: var(--text-secondary);
|
|
431
|
-
}
|
|
432
|
-
.invoice-paper--dark .inv-ref-label,
|
|
433
|
-
.invoice-paper--dark .inv-section-label {
|
|
434
|
-
color: var(--text-secondary);
|
|
435
|
-
}
|
|
436
|
-
.invoice-paper--dark .inv-ref-value {
|
|
437
|
-
color: var(--text);
|
|
438
|
-
}
|
|
439
|
-
.invoice-paper--dark .inv-period {
|
|
440
|
-
border-left-color: var(--border-light);
|
|
441
|
-
color: var(--text-secondary);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/* Line cell internals */
|
|
445
|
-
.invoice-paper--dark .inv-line-name {
|
|
446
|
-
color: var(--text);
|
|
447
|
-
}
|
|
448
|
-
.invoice-paper--dark .inv-line-desc,
|
|
449
|
-
.invoice-paper--dark .inv-line-meta,
|
|
450
|
-
.invoice-paper--dark .inv-line-charge {
|
|
451
|
-
color: var(--text-secondary);
|
|
452
|
-
}
|
|
453
|
-
.invoice-paper--dark .inv-line-price-gross {
|
|
454
|
-
color: var(--text-secondary);
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/* VAT breakdown sub-rows */
|
|
458
|
-
.invoice-paper--dark .inv-vat-base,
|
|
459
|
-
.invoice-paper--dark .inv-vat-reason td {
|
|
460
|
-
color: var(--text-secondary);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/* ── Detailed view ─────────────────────────────────────────────────────────── */
|
|
464
|
-
|
|
465
|
-
/* Power-user / educational rendering: every populated EN 16931 field beside
|
|
466
|
-
its BT/BG code + DE/EN human label. Grouped by BG group. Styled with the
|
|
467
|
-
site's dark theme tokens — deliberately not document-shaped. */
|
|
468
|
-
|
|
469
|
-
.inv-detailed {
|
|
470
|
-
display: flex;
|
|
471
|
-
flex-direction: column;
|
|
472
|
-
gap: var(--space-5);
|
|
473
|
-
color: var(--text);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
.inv-d-group {
|
|
477
|
-
background: var(--bg-card);
|
|
478
|
-
border: 1px solid var(--border);
|
|
479
|
-
border-radius: var(--radius-lg);
|
|
480
|
-
overflow: hidden;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
.inv-d-group-title {
|
|
484
|
-
display: flex;
|
|
485
|
-
align-items: baseline;
|
|
486
|
-
gap: var(--space-3);
|
|
487
|
-
flex-wrap: wrap;
|
|
488
|
-
margin: 0;
|
|
489
|
-
padding: var(--space-3) var(--space-4);
|
|
490
|
-
background: var(--bg-elevated);
|
|
491
|
-
border-bottom: 1px solid var(--border);
|
|
492
|
-
font-size: var(--text-base);
|
|
493
|
-
font-weight: 600;
|
|
494
|
-
color: var(--text);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/* Two-column auto-flow: rows pair up side-by-side once there's enough room
|
|
498
|
-
(>= ~720px container), otherwise collapse to a single column. The 360px
|
|
499
|
-
minimum is tuned so the create-view's narrower preview pane stays single
|
|
500
|
-
column. */
|
|
501
|
-
.inv-d-grid {
|
|
502
|
-
display: grid;
|
|
503
|
-
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
|
|
504
|
-
column-gap: 1px; /* hairline divider between columns via background */
|
|
505
|
-
background: var(--border);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
.inv-d-row {
|
|
509
|
-
display: grid;
|
|
510
|
-
grid-template-columns: minmax(11rem, max-content) 1fr;
|
|
511
|
-
column-gap: var(--space-4);
|
|
512
|
-
align-items: center;
|
|
513
|
-
padding: var(--space-2) var(--space-4);
|
|
514
|
-
background: var(--bg-card);
|
|
515
|
-
font-size: var(--text-sm);
|
|
516
|
-
border-bottom: 1px solid var(--border);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
.inv-d-key {
|
|
520
|
-
display: flex;
|
|
521
|
-
flex-direction: column;
|
|
522
|
-
gap: 2px;
|
|
523
|
-
word-break: break-word;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
.inv-d-code {
|
|
527
|
-
font-family: var(--font-mono);
|
|
528
|
-
font-size: var(--text-xs);
|
|
529
|
-
color: var(--primary-light);
|
|
530
|
-
letter-spacing: 0.04em;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
.inv-d-name {
|
|
534
|
-
font-size: var(--text-sm);
|
|
535
|
-
color: var(--text);
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
.inv-d-value {
|
|
539
|
-
color: var(--text-secondary);
|
|
540
|
-
text-align: left;
|
|
541
|
-
word-break: break-word;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
/* Empty rows: muted, italic placeholder. Used when "Show empty fields" is
|
|
545
|
-
on so users debugging or building an invoice can see the full structure. */
|
|
546
|
-
.inv-d-row--empty .inv-d-name,
|
|
547
|
-
.inv-d-row--empty .inv-d-code {
|
|
548
|
-
color: var(--text-muted);
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
.inv-d-row--empty .inv-d-value {
|
|
552
|
-
color: var(--text-muted);
|
|
553
|
-
font-style: italic;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
/* "Show empty fields" toggle — embedded as a checkbox label in the first
|
|
557
|
-
section header. Sits flush right via margin-left: auto. */
|
|
558
|
-
.inv-d-show-empty {
|
|
559
|
-
margin-left: auto;
|
|
560
|
-
display: inline-flex;
|
|
561
|
-
align-items: center;
|
|
562
|
-
gap: var(--space-2);
|
|
563
|
-
font-size: var(--text-xs);
|
|
564
|
-
font-weight: 400;
|
|
565
|
-
color: var(--text-secondary);
|
|
566
|
-
text-transform: none;
|
|
567
|
-
letter-spacing: normal;
|
|
568
|
-
cursor: pointer;
|
|
569
|
-
user-select: none;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
.inv-d-show-empty input {
|
|
573
|
-
accent-color: var(--primary);
|
|
574
|
-
cursor: pointer;
|
|
575
|
-
margin: 0;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
.inv-d-hint {
|
|
579
|
-
color: var(--text-secondary);
|
|
580
|
-
font-size: var(--text-xs);
|
|
581
|
-
margin-left: var(--space-1);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
.inv-d-scheme {
|
|
585
|
-
color: var(--text-muted);
|
|
586
|
-
font-size: var(--text-xs);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
.inv-d-line {
|
|
590
|
-
background: var(--bg-card);
|
|
591
|
-
border: 1px solid var(--border);
|
|
592
|
-
border-left: 3px solid var(--text-muted);
|
|
593
|
-
border-radius: var(--radius-md);
|
|
594
|
-
padding: 0;
|
|
595
|
-
margin-bottom: var(--space-3);
|
|
596
|
-
overflow: hidden;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
.inv-d-lines .inv-d-line {
|
|
600
|
-
border-radius: var(--radius-md);
|
|
601
|
-
margin: var(--space-3) var(--space-4);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
.inv-d-line summary {
|
|
605
|
-
cursor: pointer;
|
|
606
|
-
display: flex;
|
|
607
|
-
align-items: baseline;
|
|
608
|
-
gap: var(--space-3);
|
|
609
|
-
padding: var(--space-3) var(--space-4);
|
|
610
|
-
background: var(--bg-elevated);
|
|
611
|
-
border-bottom: 1px solid var(--border);
|
|
612
|
-
list-style: none;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
.inv-d-line summary::-webkit-details-marker { display: none; }
|
|
616
|
-
|
|
617
|
-
.inv-d-line summary::before {
|
|
618
|
-
content: "▸";
|
|
619
|
-
color: var(--text-muted);
|
|
620
|
-
transition: transform var(--duration) var(--ease-out);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
.inv-d-line[open] summary::before {
|
|
624
|
-
transform: rotate(90deg);
|
|
625
|
-
display: inline-block;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
.inv-d-line > .inv-d-grid {
|
|
629
|
-
margin: var(--space-3) var(--space-4);
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
.inv-d-line > .inv-d-subgroup {
|
|
633
|
-
margin: var(--space-3) 0 0;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
/* Subgroup separation: matches the top-level array-item pattern — only the
|
|
637
|
-
title strip is tonally elevated; the body inherits the line card's tone.
|
|
638
|
-
A top border above each subgroup gives a clean structural break without
|
|
639
|
-
the body re-shading that previously felt visually busy on deep nests. */
|
|
640
|
-
.inv-d-subgroup {
|
|
641
|
-
border-top: 1px solid var(--border);
|
|
642
|
-
padding-top: var(--space-3);
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
.inv-d-subgroup-title {
|
|
646
|
-
display: flex;
|
|
647
|
-
align-items: baseline;
|
|
648
|
-
gap: var(--space-2);
|
|
649
|
-
margin: 0 0 var(--space-2);
|
|
650
|
-
padding: var(--space-2) var(--space-4);
|
|
651
|
-
background: var(--bg-elevated);
|
|
652
|
-
font-size: var(--text-xs);
|
|
653
|
-
font-weight: 600;
|
|
654
|
-
color: var(--text-secondary);
|
|
655
|
-
text-transform: uppercase;
|
|
656
|
-
letter-spacing: 0.04em;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
.inv-d-subgroup .inv-d-row:last-child {
|
|
660
|
-
border-bottom: 0;
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
/* Mode tabs — reuse .tab-btn from validate.css. The natural margin-bottom:
|
|
664
|
-
-1px on .tab-btn lets the active 2px underline overlap the parent's 1px
|
|
665
|
-
border-bottom for a unified tab-bar look. */
|
|
666
|
-
.mode-tabs {
|
|
667
|
-
display: inline-flex;
|
|
668
|
-
gap: var(--space-1);
|
|
669
|
-
align-items: end;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
.mode-tabs .tab-btn {
|
|
673
|
-
padding: var(--space-2) var(--space-3);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
/* ── Print ─────────────────────────────────────────────────────────────────── */
|
|
677
|
-
|
|
678
|
-
@media print {
|
|
679
|
-
@page {
|
|
680
|
-
margin: 1.5cm;
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
nav,
|
|
684
|
-
.site-footer,
|
|
685
|
-
.view-drop-card,
|
|
686
|
-
.view-toolbar,
|
|
687
|
-
#view-error,
|
|
688
|
-
.mode-tabs,
|
|
689
|
-
.inv-detailed {
|
|
690
|
-
display: none !important;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
body {
|
|
694
|
-
background: white;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
.view-layout {
|
|
698
|
-
max-width: 100%;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
.invoice-paper {
|
|
702
|
-
box-shadow: none;
|
|
703
|
-
border-radius: 0;
|
|
704
|
-
padding: 0;
|
|
705
|
-
background: #fff;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
/* ── Editor (editable detailed view) ─────────────────────────────────────── */
|
|
710
|
-
/* The detailed renderer's editable mode replaces value cells with inputs.
|
|
711
|
-
Styling keeps the inputs visually flush with the read-only mode — same
|
|
712
|
-
typography, no chrome — so the BT-code / label / value alignment stays
|
|
713
|
-
intact. The whole row is a <label>, so clicking anywhere in the row
|
|
714
|
-
focuses the input. */
|
|
715
|
-
|
|
716
|
-
.inv-detailed--editable label.inv-d-row {
|
|
717
|
-
cursor: text;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
.inv-detailed--editable .inv-d-value input,
|
|
721
|
-
.inv-detailed--editable .inv-d-value select {
|
|
722
|
-
font: inherit;
|
|
723
|
-
color: var(--text);
|
|
724
|
-
background: transparent;
|
|
725
|
-
border: 1px solid transparent;
|
|
726
|
-
border-radius: var(--radius-sm);
|
|
727
|
-
padding: 2px 4px;
|
|
728
|
-
margin: -3px -4px; /* keep baseline alignment with surrounding rows */
|
|
729
|
-
width: 100%;
|
|
730
|
-
min-width: 0;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
/* Vacant style: muted text for empty fields so populated content stands
|
|
734
|
-
out at scanning distance. Driven by `.inv-d-row--vacant`, which the
|
|
735
|
-
state listener keeps in sync as the user edits. */
|
|
736
|
-
.inv-detailed--editable .inv-d-row--vacant .inv-d-name,
|
|
737
|
-
.inv-detailed--editable .inv-d-row--vacant .inv-d-code {
|
|
738
|
-
color: var(--text-muted);
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
.inv-detailed--editable .inv-d-row--vacant .inv-d-value input,
|
|
742
|
-
.inv-detailed--editable .inv-d-row--vacant .inv-d-value select {
|
|
743
|
-
color: var(--text-muted);
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
.inv-detailed--editable .inv-d-value input:hover,
|
|
747
|
-
.inv-detailed--editable .inv-d-value select:hover {
|
|
748
|
-
border-color: var(--border);
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
.inv-detailed--editable .inv-d-value input:focus,
|
|
752
|
-
.inv-detailed--editable .inv-d-value select:focus {
|
|
753
|
-
outline: none;
|
|
754
|
-
border-color: var(--primary);
|
|
755
|
-
background: var(--bg-card);
|
|
756
|
-
color: var(--text);
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
.inv-detailed--editable .inv-d-row--derived .inv-d-value input,
|
|
760
|
-
.inv-detailed--editable .inv-d-row--derived .inv-d-value select {
|
|
761
|
-
color: var(--text-muted);
|
|
762
|
-
cursor: not-allowed;
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
/* Array item subcards (top-level array members: notes, allowances, credit
|
|
766
|
-
transfers, VAT breakdown rows, …). Mirror the line-item card treatment:
|
|
767
|
-
each item gets its own bordered card with a 3px neutral left accent so
|
|
768
|
-
it reads as a discrete unit within the section. */
|
|
769
|
-
.inv-d-arr-items {
|
|
770
|
-
display: flex;
|
|
771
|
-
flex-direction: column;
|
|
772
|
-
gap: var(--space-3);
|
|
773
|
-
padding: var(--space-3) var(--space-4);
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
.inv-d-arr-item {
|
|
777
|
-
background: var(--bg-card);
|
|
778
|
-
border: 1px solid var(--border);
|
|
779
|
-
border-left: 3px solid var(--text-muted);
|
|
780
|
-
border-radius: var(--radius-md);
|
|
781
|
-
overflow: hidden;
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
/* Title strip uses the elevated tone so it visually mirrors a line item's
|
|
785
|
-
summary header. Body rows below stay on the card tone. */
|
|
786
|
-
.inv-d-arr-item-title {
|
|
787
|
-
display: flex;
|
|
788
|
-
align-items: baseline;
|
|
789
|
-
gap: var(--space-2);
|
|
790
|
-
padding: var(--space-2) var(--space-4);
|
|
791
|
-
background: var(--bg-elevated);
|
|
792
|
-
border-bottom: 1px solid var(--border);
|
|
793
|
-
font-size: var(--text-xs);
|
|
794
|
-
font-weight: 600;
|
|
795
|
-
color: var(--text-secondary);
|
|
796
|
-
text-transform: uppercase;
|
|
797
|
-
letter-spacing: 0.04em;
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
/* Drop the divider line on the last row of a card (the card's own bottom
|
|
801
|
-
border already terminates the stack — the row border would just create
|
|
802
|
-
a doubled line). Field-row padding is preserved; the trailing-gap
|
|
803
|
-
tightening happens at the container level below. */
|
|
804
|
-
.inv-d-arr-item > .inv-d-grid > .inv-d-row:last-child,
|
|
805
|
-
.inv-d-group > .inv-d-grid:last-child > .inv-d-row:last-child,
|
|
806
|
-
.inv-d-line > .inv-d-grid:last-child > .inv-d-row:last-child {
|
|
807
|
-
border-bottom: 0;
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
/* Standalone + Add row used after a line's per-item subgroups (allowances,
|
|
811
|
-
charges, attributes), where there's no enclosing _group to host the
|
|
812
|
-
button. */
|
|
813
|
-
.inv-d-subgroup-add {
|
|
814
|
-
padding: var(--space-2) var(--space-4);
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
/* When the +Add button trails an .inv-d-arr-items list (e.g. credit
|
|
818
|
-
transfers), the parent already supplies horizontal padding — strip the
|
|
819
|
-
inner padding so the button aligns flush with the cards above. */
|
|
820
|
-
.inv-d-arr-items > .inv-d-subgroup-add {
|
|
821
|
-
padding: 0;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
/* Suggestion popup for codelist-driven inputs (BT-130 unit, country,
|
|
825
|
-
VAT category, …). Reuses the .listbox-panel / .listbox-option visual
|
|
826
|
-
styles from create.css; this block only adds combobox-specific bits:
|
|
827
|
-
a scrollable max-height for long lists and a monospace "code" column
|
|
828
|
-
so cryptic UN/CEFACT codes line up next to their friendly labels. */
|
|
829
|
-
.bt-suggest-panel {
|
|
830
|
-
max-height: 280px;
|
|
831
|
-
overflow-y: auto;
|
|
832
|
-
min-width: 240px;
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
.bt-suggest-panel:hover .listbox-option:not(:hover) {
|
|
836
|
-
background: transparent;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
.bt-suggest-panel .listbox-option:hover {
|
|
840
|
-
background: var(--bg-elevated);
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
.bt-suggest-code {
|
|
844
|
-
font-family: var(--font-mono);
|
|
845
|
-
font-size: var(--text-xs);
|
|
846
|
-
color: var(--text-secondary);
|
|
847
|
-
flex-shrink: 0;
|
|
848
|
-
min-width: 4em;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
/* + Add / × Remove buttons. Small, secondary visual weight — they live
|
|
852
|
-
alongside group titles and item headers, so they should fade into the
|
|
853
|
-
structure when not hovered. */
|
|
854
|
-
.inv-d-group-add,
|
|
855
|
-
.inv-d-row-remove {
|
|
856
|
-
appearance: none;
|
|
857
|
-
background: transparent;
|
|
858
|
-
border: 1px solid var(--border);
|
|
859
|
-
border-radius: var(--radius-sm);
|
|
860
|
-
color: var(--text-secondary);
|
|
861
|
-
font: inherit;
|
|
862
|
-
font-size: var(--text-xs);
|
|
863
|
-
padding: 2px 8px;
|
|
864
|
-
cursor: pointer;
|
|
865
|
-
margin-left: auto;
|
|
866
|
-
text-transform: none;
|
|
867
|
-
letter-spacing: normal;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
.inv-d-group-add:hover {
|
|
871
|
-
background: var(--bg-elevated);
|
|
872
|
-
color: var(--text);
|
|
873
|
-
border-color: var(--text-secondary);
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
.inv-d-row-remove {
|
|
877
|
-
padding: 0 6px;
|
|
878
|
-
line-height: 1.6;
|
|
879
|
-
}
|
|
880
|
-
|
|
881
|
-
.inv-d-row-remove:hover {
|
|
882
|
-
background: var(--error-dim, rgba(220, 53, 53, 0.08));
|
|
883
|
-
color: var(--error);
|
|
884
|
-
border-color: var(--error);
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
/* ── Mobile ────────────────────────────────────────────────────────────────── */
|
|
888
|
-
|
|
889
|
-
@media (max-width: 600px) {
|
|
890
|
-
.inv-parties {
|
|
891
|
-
grid-template-columns: 1fr;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
.inv-header {
|
|
895
|
-
flex-direction: column;
|
|
896
|
-
gap: var(--space-3);
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
.inv-header-right {
|
|
900
|
-
text-align: left;
|
|
901
|
-
}
|
|
902
|
-
}
|