@jjlmoya/utils-travel 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +60 -0
  2. package/src/category/i18n/en.ts +185 -0
  3. package/src/category/i18n/es.ts +187 -0
  4. package/src/category/i18n/fr.ts +100 -0
  5. package/src/category/index.ts +12 -0
  6. package/src/category/seo.astro +15 -0
  7. package/src/components/PreviewNavSidebar.astro +116 -0
  8. package/src/components/PreviewToolbar.astro +143 -0
  9. package/src/data.ts +15 -0
  10. package/src/env.d.ts +5 -0
  11. package/src/index.ts +22 -0
  12. package/src/layouts/PreviewLayout.astro +117 -0
  13. package/src/pages/[locale]/[slug].astro +146 -0
  14. package/src/pages/[locale].astro +278 -0
  15. package/src/pages/index.astro +4 -0
  16. package/src/tests/faq_count.test.ts +8 -0
  17. package/src/tests/locale_completeness.test.ts +21 -0
  18. package/src/tests/mocks/astro_mock.js +2 -0
  19. package/src/tests/no_h1_in_components.test.ts +8 -0
  20. package/src/tests/seo_length.test.ts +8 -0
  21. package/src/tests/tool_validation.test.ts +17 -0
  22. package/src/tool/luggage-calculator/bibliography.astro +14 -0
  23. package/src/tool/luggage-calculator/component.astro +560 -0
  24. package/src/tool/luggage-calculator/i18n/en.ts +617 -0
  25. package/src/tool/luggage-calculator/i18n/es.ts +617 -0
  26. package/src/tool/luggage-calculator/i18n/fr.ts +549 -0
  27. package/src/tool/luggage-calculator/index.ts +53 -0
  28. package/src/tool/luggage-calculator/seo.astro +14 -0
  29. package/src/tool/mini-adventures/bibliography.astro +14 -0
  30. package/src/tool/mini-adventures/component.astro +665 -0
  31. package/src/tool/mini-adventures/i18n/en.ts +161 -0
  32. package/src/tool/mini-adventures/i18n/es.ts +286 -0
  33. package/src/tool/mini-adventures/i18n/fr.ts +144 -0
  34. package/src/tool/mini-adventures/index.ts +70 -0
  35. package/src/tool/mini-adventures/seo.astro +14 -0
  36. package/src/tool/optimal-routes/bibliography.astro +14 -0
  37. package/src/tool/optimal-routes/component.astro +439 -0
  38. package/src/tool/optimal-routes/i18n/en.ts +42 -0
  39. package/src/tool/optimal-routes/i18n/es.ts +52 -0
  40. package/src/tool/optimal-routes/index.ts +63 -0
  41. package/src/tool/optimal-routes/lib/RouteManager.ts +181 -0
  42. package/src/tool/optimal-routes/seo.astro +14 -0
  43. package/src/tool/suitcase-checklist/bibliography.astro +14 -0
  44. package/src/tool/suitcase-checklist/component.astro +710 -0
  45. package/src/tool/suitcase-checklist/i18n/en.ts +261 -0
  46. package/src/tool/suitcase-checklist/i18n/es.ts +261 -0
  47. package/src/tool/suitcase-checklist/i18n/fr.ts +259 -0
  48. package/src/tool/suitcase-checklist/index.ts +75 -0
  49. package/src/tool/suitcase-checklist/seo.astro +14 -0
  50. package/src/tool/tip-calculator/bibliography.astro +14 -0
  51. package/src/tool/tip-calculator/component.astro +683 -0
  52. package/src/tool/tip-calculator/i18n/en.ts +264 -0
  53. package/src/tool/tip-calculator/i18n/es.ts +264 -0
  54. package/src/tool/tip-calculator/i18n/fr.ts +264 -0
  55. package/src/tool/tip-calculator/index.ts +53 -0
  56. package/src/tool/tip-calculator/seo.astro +14 -0
  57. package/src/tools.ts +13 -0
  58. package/src/types.ts +73 -0
@@ -0,0 +1,683 @@
1
+ ---
2
+ import { Icon } from "astro-icon/components";
3
+ import type { TipCalculatorUI } from "./index";
4
+
5
+ interface Props {
6
+ ui: TipCalculatorUI;
7
+ }
8
+
9
+ const { ui } = Astro.props;
10
+ ---
11
+
12
+ <div class="tip-calculator">
13
+ <div class="tc-main-card">
14
+ <div class="tc-header">
15
+ <div class="tc-header-content">
16
+ <span class="tc-badge">{ui.badge}</span>
17
+ <h2>{ui.title}</h2>
18
+ </div>
19
+ <div class="tc-header-icon">
20
+ <Icon name="mdi:calculator-variant" />
21
+ </div>
22
+ </div>
23
+
24
+ <div class="tc-grid">
25
+ <div class="tc-inputs">
26
+ <div class="tc-input-field">
27
+ <label>{ui.billLabel}</label>
28
+ <div class="tc-input-control">
29
+ <Icon name="mdi:currency-eur" class="tc-control-icon" />
30
+ <input
31
+ type="number"
32
+ id="bill-amount"
33
+ placeholder={ui.placeholderAmount}
34
+ step="0.01"
35
+ />
36
+ </div>
37
+ </div>
38
+
39
+ <div class="tc-input-field">
40
+ <label>{ui.countryLabel}</label>
41
+ <div class="tc-dropdown" id="country-dropdown">
42
+ <div class="tc-dropdown-toggle" id="dropdown-toggle">
43
+ <Icon name="mdi:earth" class="tc-toggle-icon" />
44
+ <span id="selected-country-name" class="tc-selected-name">{ui.placeholderSelect}</span>
45
+ <Icon name="mdi:chevron-down" class="tc-chevron" />
46
+ </div>
47
+ <div class="tc-dropdown-menu" id="dropdown-menu">
48
+ <div class="tc-dropdown-search">
49
+ <Icon name="mdi:magnify" />
50
+ <input
51
+ type="text"
52
+ id="country-search"
53
+ placeholder={ui.placeholderFilter}
54
+ />
55
+ </div>
56
+ <div class="tc-dropdown-list" id="country-list">
57
+ {
58
+ ui.countries.map((c) => (
59
+ <div class="tc-dropdown-item" data-id={c.id}>
60
+ {c.name}
61
+ </div>
62
+ ))
63
+ }
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+
69
+ <div class="tc-input-field">
70
+ <div class="tc-label-with-value">
71
+ <label>{ui.tipLabel}</label>
72
+ <span class="tc-value-highlight"><span id="perc-label">10</span>%</span>
73
+ </div>
74
+ <div class="tc-percentage-pills">
75
+ <button class="tc-pill-btn" data-value="0">0%</button>
76
+ <button class="tc-pill-btn" data-value="5">5%</button>
77
+ <button class="tc-pill-btn active" data-value="10">10%</button>
78
+ <button class="tc-pill-btn" data-value="15">15%</button>
79
+ <button class="tc-pill-btn" data-value="20">20%</button>
80
+ </div>
81
+ </div>
82
+
83
+ <div class="tc-input-field">
84
+ <label>{ui.splitLabel}</label>
85
+ <div class="tc-split-control">
86
+ <button id="split-minus" class="tc-split-btn"
87
+ ><Icon name="mdi:minus" /></button
88
+ >
89
+ <div class="tc-split-display">
90
+ <Icon name="mdi:account-group" />
91
+ <span id="split-val">4</span>
92
+ </div>
93
+ <button id="split-plus" class="tc-split-btn"
94
+ ><Icon name="mdi:plus" /></button
95
+ >
96
+ </div>
97
+ </div>
98
+ </div>
99
+
100
+ <div class="tc-summary">
101
+ <div class="tc-summary-card">
102
+ <div class="tc-summary-details">
103
+ <div class="tc-summary-line">
104
+ <span>{ui.summaryTip}</span>
105
+ <strong id="tip-amount">0.00€</strong>
106
+ </div>
107
+ <div class="tc-summary-line">
108
+ <span>{ui.summarySubtotal}</span>
109
+ <strong id="bill-val">0.00€</strong>
110
+ </div>
111
+ </div>
112
+
113
+ <div class="tc-summary-total">
114
+ <span class="tc-total-label">{ui.summaryTotalPerson}</span>
115
+ <div class="tc-total-amount">
116
+ <span id="total-per-person">0.00</span><small>€</small>
117
+ </div>
118
+ </div>
119
+ </div>
120
+
121
+ <div id="culture-box" class="tc-culture-info" style="display: none;">
122
+ <div class="tc-culture-header">
123
+ <Icon name="mdi:information-variant" />
124
+ <span id="culture-title">{ui.protocolTitle}</span>
125
+ </div>
126
+ <p id="culture-text"></p>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </div>
131
+ </div>
132
+
133
+ <script is:inline define:vars={{ countries: ui.countries, content: ui }}>
134
+ const billInput = document.getElementById("bill-amount");
135
+ const percLabel = document.getElementById("perc-label");
136
+ const percBtns = document.querySelectorAll(".tc-pill-btn");
137
+
138
+ const dropdownToggle = document.getElementById("dropdown-toggle");
139
+ const dropdownMenu = document.getElementById("dropdown-menu");
140
+ const countrySearch = document.getElementById("country-search");
141
+ const dropdownItems = document.querySelectorAll(".tc-dropdown-item");
142
+ const selectedCountryName = document.getElementById("selected-country-name");
143
+
144
+ const splitMinus = document.getElementById("split-minus");
145
+ const splitPlus = document.getElementById("split-plus");
146
+ const splitDisplay = document.getElementById("split-val");
147
+
148
+ const tipAmountEl = document.getElementById("tip-amount");
149
+ const billValEl = document.getElementById("bill-val");
150
+ const totalPersonEl = document.getElementById("total-per-person");
151
+
152
+ const cultureBox = document.getElementById("culture-box");
153
+ const cultureTitle = document.getElementById("culture-title");
154
+ const cultureText = document.getElementById("culture-text");
155
+
156
+ let currentPerc = 10;
157
+ let currentSplit = 4;
158
+ let activeCountryId = null;
159
+
160
+ function saveState() {
161
+ const state = {
162
+ bill: billInput.value,
163
+ split: currentSplit,
164
+ percentage: currentPerc,
165
+ countryId: activeCountryId,
166
+ };
167
+ localStorage.setItem("tip_calculator_state", JSON.stringify(state));
168
+ }
169
+
170
+ function loadState() {
171
+ const saved = localStorage.getItem("tip_calculator_state");
172
+ if (!saved) { updateUI(); return; }
173
+ try {
174
+ const state = JSON.parse(saved);
175
+ billInput.value = state.bill || "";
176
+ currentSplit = typeof state.split === 'number' ? state.split : 4;
177
+ currentPerc = typeof state.percentage === 'number' ? state.percentage : 10;
178
+ activeCountryId = state.countryId;
179
+ splitDisplay.textContent = currentSplit;
180
+ percLabel.textContent = currentPerc;
181
+ percBtns.forEach((btn) => {
182
+ btn.classList.toggle("active", parseInt(btn.dataset.value) === currentPerc);
183
+ });
184
+ if (activeCountryId) {
185
+ const item = Array.from(dropdownItems).find((i) => i.dataset.id === activeCountryId);
186
+ if (item) updateCountry(item, false);
187
+ }
188
+ } catch {}
189
+ updateUI();
190
+ }
191
+
192
+ function updateUI() {
193
+ const bill = parseFloat(billInput.value) || 0;
194
+ const tipTotal = bill * (currentPerc / 100);
195
+ const grandTotal = bill + tipTotal;
196
+ const perPerson = grandTotal / currentSplit;
197
+
198
+ tipAmountEl.textContent = tipTotal.toFixed(2) + "€";
199
+ billValEl.textContent = bill.toFixed(2) + "€";
200
+ totalPersonEl.textContent = perPerson.toFixed(2);
201
+ saveState();
202
+ }
203
+
204
+ function updateCountry(item, updatePerc = true) {
205
+ if (!item) return;
206
+
207
+ dropdownItems.forEach((i) => i.classList.remove("active"));
208
+ item.classList.add("active");
209
+ selectedCountryName.textContent = item.textContent.trim();
210
+
211
+ activeCountryId = item.dataset.id;
212
+ const country = countries.find((c) => c.id === activeCountryId);
213
+
214
+ if (country) {
215
+ if (updatePerc) {
216
+ currentPerc = country.default;
217
+ percLabel.textContent = currentPerc;
218
+
219
+ percBtns.forEach((btn) => {
220
+ const btnVal = parseInt(btn.dataset.value);
221
+ if (btnVal === currentPerc) {
222
+ btn.classList.add("active");
223
+ } else {
224
+ btn.classList.remove("active");
225
+ }
226
+ });
227
+ }
228
+
229
+ cultureBox.style.display = "block";
230
+ cultureTitle.textContent = `${content.protocolTitle} en ${country.name}`;
231
+ cultureText.textContent = country.culture;
232
+ }
233
+ dropdownMenu.classList.remove("show");
234
+ updateUI();
235
+ }
236
+
237
+ billInput.addEventListener("input", updateUI);
238
+
239
+ percBtns.forEach((btn) => {
240
+ btn.addEventListener("click", () => {
241
+ percBtns.forEach((b) => b.classList.remove("active"));
242
+ btn.classList.add("active");
243
+ currentPerc = parseInt(btn.dataset.value);
244
+ percLabel.textContent = currentPerc;
245
+ updateUI();
246
+ });
247
+ });
248
+
249
+ dropdownToggle.addEventListener("click", (e) => {
250
+ e.stopPropagation();
251
+ dropdownMenu.classList.toggle("show");
252
+ if (dropdownMenu.classList.contains("show")) {
253
+ countrySearch.focus();
254
+ }
255
+ });
256
+
257
+ document.addEventListener("click", () => {
258
+ dropdownMenu.classList.remove("show");
259
+ });
260
+
261
+ dropdownMenu.addEventListener("click", (e) => e.stopPropagation());
262
+
263
+ dropdownItems.forEach((item) => {
264
+ item.addEventListener("click", () => updateCountry(item));
265
+ });
266
+
267
+ countrySearch.addEventListener("input", (e) => {
268
+ const query = e.target.value.toLowerCase();
269
+ dropdownItems.forEach((item) => {
270
+ const name = item.textContent.toLowerCase();
271
+ item.style.display = name.includes(query) ? "block" : "none";
272
+ });
273
+ });
274
+
275
+ splitMinus.addEventListener("click", () => {
276
+ if (currentSplit > 1) {
277
+ currentSplit--;
278
+ splitDisplay.textContent = currentSplit;
279
+ updateUI();
280
+ }
281
+ });
282
+
283
+ splitPlus.addEventListener("click", () => {
284
+ currentSplit++;
285
+ splitDisplay.textContent = currentSplit;
286
+ updateUI();
287
+ });
288
+
289
+ loadState();
290
+ </script>
291
+
292
+ <style>
293
+ .tip-calculator {
294
+ --tc-primary: #10b981;
295
+ --tc-primary-soft: rgba(16, 185, 129, 0.1);
296
+ --tc-bg: #fff;
297
+ --tc-border: #e2e8f0;
298
+ --tc-text: #1e293b;
299
+ --tc-text-muted: #64748b;
300
+ --tc-card-bg: #fff;
301
+ --tc-input-bg: #f8fafc;
302
+ --tc-item-bg: #f8fafc;
303
+ --tc-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
304
+ }
305
+
306
+ :global(.theme-dark) .tip-calculator {
307
+ --tc-bg: #0f172a;
308
+ --tc-border: #334155;
309
+ --tc-text: #f1f5f9;
310
+ --tc-text-muted: #94a3b8;
311
+ --tc-card-bg: #1e293b;
312
+ --tc-input-bg: #0f172a;
313
+ --tc-item-bg: #0f172a;
314
+ --tc-primary: #34d399;
315
+ --tc-primary-soft: rgba(52, 211, 153, 0.1);
316
+ --tc-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
317
+ }
318
+
319
+ .tc-main-card {
320
+ background: var(--tc-card-bg);
321
+ border: 1px solid var(--tc-border);
322
+ border-radius: 2rem;
323
+ padding: 2.5rem;
324
+ box-shadow: var(--tc-shadow);
325
+ backdrop-filter: blur(12px);
326
+ }
327
+
328
+ .tc-header {
329
+ display: flex;
330
+ justify-content: space-between;
331
+ align-items: flex-start;
332
+ margin-bottom: 2.5rem;
333
+ }
334
+
335
+ .tc-badge {
336
+ display: inline-block;
337
+ padding: 0.5rem 1rem;
338
+ background: var(--tc-primary-soft);
339
+ color: var(--tc-primary);
340
+ border-radius: 2rem;
341
+ font-size: 0.8rem;
342
+ font-weight: 800;
343
+ text-transform: uppercase;
344
+ margin-bottom: 0.75rem;
345
+ }
346
+
347
+ .tc-header h2 {
348
+ font-size: 2.25rem;
349
+ font-weight: 900;
350
+ margin: 0;
351
+ line-height: 1.1;
352
+ }
353
+
354
+ .tc-header-icon {
355
+ width: 64px;
356
+ height: 64px;
357
+ background: var(--tc-primary-soft);
358
+ color: var(--tc-primary);
359
+ border-radius: 1.5rem;
360
+ display: flex;
361
+ align-items: center;
362
+ justify-content: center;
363
+ }
364
+
365
+ .tc-header-icon svg {
366
+ width: 32px;
367
+ height: 32px;
368
+ }
369
+
370
+ .tc-grid {
371
+ display: grid;
372
+ grid-template-columns: 1.2fr 1fr;
373
+ gap: 3rem;
374
+ }
375
+
376
+ .tc-input-field {
377
+ margin-bottom: 2rem;
378
+ }
379
+
380
+ .tc-input-field label {
381
+ display: block;
382
+ font-size: 0.9rem;
383
+ font-weight: 700;
384
+ color: var(--tc-text-muted);
385
+ margin-bottom: 0.75rem;
386
+ text-transform: uppercase;
387
+ letter-spacing: 0.05em;
388
+ }
389
+
390
+ .tc-input-control {
391
+ position: relative;
392
+ display: flex;
393
+ align-items: center;
394
+ }
395
+
396
+ .tc-control-icon {
397
+ position: absolute;
398
+ left: 1.25rem;
399
+ color: var(--tc-primary);
400
+ width: 20px;
401
+ height: 20px;
402
+ }
403
+
404
+ .tc-input-control input {
405
+ width: 100%;
406
+ padding: 1.25rem 1.25rem 1.25rem 3.5rem;
407
+ background: var(--tc-input-bg);
408
+ border: 2px solid var(--tc-border);
409
+ border-radius: 1.25rem;
410
+ font-size: 1.25rem;
411
+ font-weight: 800;
412
+ color: var(--tc-text);
413
+ transition: all 0.2s;
414
+ outline: none;
415
+ }
416
+
417
+ .tc-input-control input:focus {
418
+ border-color: var(--tc-primary);
419
+ box-shadow: 0 0 0 4px var(--tc-primary-soft);
420
+ }
421
+
422
+ .tc-dropdown {
423
+ position: relative;
424
+ }
425
+
426
+ .tc-dropdown-toggle {
427
+ width: 100%;
428
+ padding: 1.25rem 1.5rem;
429
+ background: var(--tc-input-bg);
430
+ border: 2px solid var(--tc-border);
431
+ border-radius: 1.25rem;
432
+ display: flex;
433
+ align-items: center;
434
+ gap: 1rem;
435
+ cursor: pointer;
436
+ transition: all 0.2s;
437
+ }
438
+
439
+ .tc-toggle-icon {
440
+ color: var(--tc-primary);
441
+ width: 20px;
442
+ height: 20px;
443
+ }
444
+
445
+ .tc-selected-name {
446
+ flex: 1;
447
+ font-weight: 700;
448
+ }
449
+
450
+ .tc-chevron {
451
+ color: var(--tc-text-muted);
452
+ transition: transform 0.2s;
453
+ margin-left: auto;
454
+ }
455
+
456
+ .tc-dropdown-menu {
457
+ position: absolute;
458
+ top: calc(100% + 0.5rem);
459
+ left: 0;
460
+ width: 100%;
461
+ background: var(--tc-card-bg);
462
+ border: 1px solid var(--tc-border);
463
+ border-radius: 1.25rem;
464
+ box-shadow: var(--tc-shadow);
465
+ z-index: 100;
466
+ display: none;
467
+ overflow: hidden;
468
+ }
469
+
470
+ .tc-dropdown-menu.show {
471
+ display: block;
472
+ }
473
+
474
+ .tc-dropdown-search {
475
+ padding: 1rem;
476
+ border-bottom: 1px solid var(--tc-border);
477
+ display: flex;
478
+ align-items: center;
479
+ gap: 0.75rem;
480
+ background: var(--tc-input-bg);
481
+ }
482
+
483
+ .tc-dropdown-search input {
484
+ background: transparent;
485
+ border: none;
486
+ outline: none;
487
+ width: 100%;
488
+ color: var(--tc-text);
489
+ }
490
+
491
+ .tc-dropdown-list {
492
+ max-height: 250px;
493
+ overflow-y: auto;
494
+ background: var(--tc-card-bg);
495
+ }
496
+
497
+ .tc-dropdown-item {
498
+ padding: 1rem 1.5rem;
499
+ cursor: pointer;
500
+ transition: all 0.2s;
501
+ font-weight: 600;
502
+ color: var(--tc-text);
503
+ }
504
+
505
+ .tc-dropdown-item:hover {
506
+ background: var(--tc-primary-soft);
507
+ color: var(--tc-primary);
508
+ }
509
+
510
+ .tc-dropdown-item.active {
511
+ background: var(--tc-primary);
512
+ color: white;
513
+ }
514
+
515
+ .tc-label-with-value {
516
+ display: flex;
517
+ justify-content: space-between;
518
+ align-items: center;
519
+ margin-bottom: 0.75rem;
520
+ }
521
+
522
+ .tc-value-highlight {
523
+ font-weight: 900;
524
+ color: var(--tc-primary);
525
+ }
526
+
527
+ .tc-percentage-pills {
528
+ display: flex;
529
+ gap: 0.5rem;
530
+ }
531
+
532
+ .tc-pill-btn {
533
+ flex: 1;
534
+ padding: 1rem;
535
+ background: var(--tc-input-bg);
536
+ border: 2px solid var(--tc-border);
537
+ border-radius: 1rem;
538
+ font-weight: 800;
539
+ cursor: pointer;
540
+ transition: all 0.2s;
541
+ color: var(--tc-text);
542
+ }
543
+
544
+ .tc-pill-btn:hover {
545
+ border-color: var(--tc-primary);
546
+ }
547
+
548
+ .tc-pill-btn.active {
549
+ background: var(--tc-primary);
550
+ border-color: var(--tc-primary);
551
+ color: white;
552
+ }
553
+
554
+ .tc-split-control {
555
+ display: flex;
556
+ align-items: center;
557
+ gap: 1rem;
558
+ }
559
+
560
+ .tc-split-btn {
561
+ width: 54px;
562
+ height: 54px;
563
+ border-radius: 1rem;
564
+ border: 2px solid var(--tc-border);
565
+ background: var(--tc-input-bg);
566
+ display: flex;
567
+ align-items: center;
568
+ justify-content: center;
569
+ cursor: pointer;
570
+ transition: all 0.2s;
571
+ color: var(--tc-text);
572
+ }
573
+
574
+ .tc-split-btn:hover {
575
+ border-color: var(--tc-primary);
576
+ color: var(--tc-primary);
577
+ }
578
+
579
+ .tc-split-display {
580
+ flex: 1;
581
+ background: var(--tc-input-bg);
582
+ border: 2px solid var(--tc-border);
583
+ border-radius: 1rem;
584
+ height: 54px;
585
+ display: flex;
586
+ align-items: center;
587
+ justify-content: center;
588
+ gap: 0.75rem;
589
+ font-weight: 900;
590
+ font-size: 1.25rem;
591
+ }
592
+
593
+ .tc-split-display svg {
594
+ color: var(--tc-primary);
595
+ }
596
+
597
+ .tc-summary-card {
598
+ background: linear-gradient(135deg, var(--tc-primary) 0%, #059669 100%);
599
+ border-radius: 2rem;
600
+ padding: 2.5rem;
601
+ color: #fff;
602
+ box-shadow: 0 15px 30px rgba(16, 185, 129, 0.2);
603
+ }
604
+
605
+ .tc-summary-line {
606
+ display: flex;
607
+ justify-content: space-between;
608
+ margin-bottom: 1rem;
609
+ font-size: 1.1rem;
610
+ opacity: 0.9;
611
+ }
612
+
613
+ .tc-summary-line strong {
614
+ font-weight: 800;
615
+ }
616
+
617
+ .tc-summary-details {
618
+ padding-bottom: 1.5rem;
619
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
620
+ margin-bottom: 1.5rem;
621
+ }
622
+
623
+ .tc-total-label {
624
+ display: block;
625
+ text-align: center;
626
+ font-weight: 700;
627
+ text-transform: uppercase;
628
+ font-size: 0.8rem;
629
+ letter-spacing: 0.1em;
630
+ margin-bottom: 0.5rem;
631
+ }
632
+
633
+ .tc-total-amount {
634
+ text-align: center;
635
+ font-size: 4rem;
636
+ font-weight: 900;
637
+ line-height: 1;
638
+ }
639
+
640
+ .tc-total-amount small {
641
+ font-size: 1.5rem;
642
+ margin-left: 0.25rem;
643
+ }
644
+
645
+ .tc-culture-info {
646
+ margin-top: 2rem;
647
+ padding: 1.5rem;
648
+ background: var(--tc-item-bg);
649
+ border: 1px solid var(--tc-border);
650
+ border-radius: 1.5rem;
651
+ }
652
+
653
+ .tc-culture-header {
654
+ display: flex;
655
+ align-items: center;
656
+ gap: 0.75rem;
657
+ margin-bottom: 0.75rem;
658
+ font-weight: 800;
659
+ color: var(--tc-primary);
660
+ }
661
+
662
+ .tc-culture-info p {
663
+ font-size: 0.95rem;
664
+ line-height: 1.6;
665
+ margin: 0;
666
+ color: var(--tc-text-muted);
667
+ }
668
+
669
+ @media (max-width: 768px) {
670
+ .tc-grid {
671
+ grid-template-columns: 1fr;
672
+ gap: 2rem;
673
+ }
674
+
675
+ .tc-main-card {
676
+ padding: 1.5rem;
677
+ }
678
+
679
+ .tc-header h2 {
680
+ font-size: 1.75rem;
681
+ }
682
+ }
683
+ </style>