@invisibleloop/pulse 0.20.5 → 0.20.6

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 (79) hide show
  1. package/.claude/pulse-checklist.md +1 -2
  2. package/CLAUDE.md +1 -2
  3. package/docs/.claude/pulse-checklist.md +1 -2
  4. package/docs/public/coutumes.css +21 -44
  5. package/docs/public/docs.css +67 -0
  6. package/docs/public/pulse-ui.css +8 -1037
  7. package/docs/public/retrowheels.css +23 -0
  8. package/docs/public/shop.css +35 -1
  9. package/docs/public/sparkys.css +56 -23
  10. package/docs/server.js +0 -11
  11. package/docs/src/lib/nav.js +0 -11
  12. package/docs/src/pages/components/charts.js +2 -1
  13. package/docs/src/pages/components/grid.js +9 -5
  14. package/docs/src/pages/components.js +0 -4
  15. package/docs/src/pages/home.js +16 -1
  16. package/docs/src/pages/how-it-works.js +20 -14
  17. package/docs/src/pages/templates/coutumes.js +83 -72
  18. package/docs/src/pages/templates/mobile-app.js +36 -9
  19. package/docs/src/pages/templates/retrowheels.js +17 -4
  20. package/docs/src/pages/templates/shop.js +21 -10
  21. package/docs/src/pages/templates/sparkys.js +35 -20
  22. package/examples/.claude/pulse-checklist.md +1 -2
  23. package/examples/examples.test.js +4 -4
  24. package/examples/pricing.js +21 -3
  25. package/examples/public/pulse-ui.css +8 -1037
  26. package/examples/retrowheels.css +23 -0
  27. package/examples/retrowheels.js +17 -4
  28. package/package.json +5 -1
  29. package/public/.pulse-ui-version +1 -1
  30. package/public/pulse-ui.css +8 -1037
  31. package/src/agent/checklist.md +1 -2
  32. package/src/agent/guide-components.md +43 -67
  33. package/src/agent/guide-design-gallery.md +14 -14
  34. package/src/agent/guide-design-references.md +21 -21
  35. package/src/agent/guide-styles.md +2 -2
  36. package/src/agent/guide-templates.md +6 -6
  37. package/src/agent/identity.md +1 -1
  38. package/src/agent/workflow.md +1 -2
  39. package/src/mcp/server.js +31 -24
  40. package/src/ui/index.js +0 -27
  41. package/src/ui/ui.test.js +0 -137
  42. package/types/charts.d.ts +61 -0
  43. package/types/ui.d.ts +1 -129
  44. package/docs/src/pages/components/banner.js +0 -44
  45. package/docs/src/pages/components/carousel.js +0 -71
  46. package/docs/src/pages/components/code-window.js +0 -56
  47. package/docs/src/pages/components/decorate.js +0 -74
  48. package/docs/src/pages/components/gallery.js +0 -102
  49. package/docs/src/pages/components/list.js +0 -111
  50. package/docs/src/pages/components/marquee.js +0 -76
  51. package/docs/src/pages/components/photo-card.js +0 -74
  52. package/docs/src/pages/components/pricing.js +0 -67
  53. package/docs/src/pages/components/testimonial.js +0 -48
  54. package/docs/src/pages/components/timeline.js +0 -226
  55. package/src/ui/banner.js +0 -41
  56. package/src/ui/brand-statement.js +0 -58
  57. package/src/ui/carousel.js +0 -59
  58. package/src/ui/code-window.js +0 -39
  59. package/src/ui/colophon.js +0 -29
  60. package/src/ui/contact-row.js +0 -41
  61. package/src/ui/decorate.js +0 -55
  62. package/src/ui/display-heading.js +0 -44
  63. package/src/ui/drop-cap.js +0 -29
  64. package/src/ui/editorial-hero.js +0 -63
  65. package/src/ui/entry-list.js +0 -36
  66. package/src/ui/gallery.js +0 -60
  67. package/src/ui/image-pair.js +0 -72
  68. package/src/ui/list.js +0 -36
  69. package/src/ui/marquee.js +0 -48
  70. package/src/ui/photo-card.js +0 -44
  71. package/src/ui/pricing.js +0 -56
  72. package/src/ui/product-card.js +0 -65
  73. package/src/ui/section-label.js +0 -38
  74. package/src/ui/service-card.js +0 -47
  75. package/src/ui/stat-grid.js +0 -40
  76. package/src/ui/testimonial.js +0 -59
  77. package/src/ui/timeline.js +0 -72
  78. package/src/ui/top-strip.js +0 -47
  79. package/src/ui/trust-list.js +0 -46
@@ -822,59 +822,6 @@ hr.ui-divider {
822
822
  flex-shrink: 0;
823
823
  }
824
824
 
825
- /* ─── Banner ─────────────────────────────────────────────────────────────── */
826
- .ui-banner {
827
- padding: .625rem 1.5rem;
828
- text-align: center;
829
- font-size: .875rem;
830
- font-weight: 500;
831
- line-height: 1.5;
832
- }
833
-
834
- .ui-banner--info {
835
- background: var(--ui-accent-dim, rgba(155,141,255,.12));
836
- color: var(--ui-accent, var(--accent, #9b8dff));
837
- }
838
-
839
- .ui-banner--promo {
840
- background: var(--ui-accent, var(--accent, #9b8dff));
841
- color: #fff;
842
- }
843
-
844
- .ui-banner--warning {
845
- background: rgba(255, 193, 7, .12);
846
- color: #ffc107;
847
- }
848
-
849
- .ui-banner--bottom {
850
- position: fixed;
851
- bottom: 0;
852
- left: 0;
853
- right: 0;
854
- z-index: 200;
855
- display: flex;
856
- align-items: center;
857
- justify-content: center;
858
- gap: 1rem;
859
- }
860
-
861
- .ui-banner-close {
862
- position: absolute;
863
- right: 1rem;
864
- top: 50%;
865
- transform: translateY(-50%);
866
- background: none;
867
- border: none;
868
- cursor: pointer;
869
- color: inherit;
870
- font-size: 1.1rem;
871
- line-height: 1;
872
- padding: 0.25rem 0.5rem;
873
- opacity: 0.7;
874
- transition: opacity 0.15s;
875
- }
876
- .ui-banner-close:hover { opacity: 1; }
877
-
878
825
  /* ─── Media ──────────────────────────────────────────────────────────────── */
879
826
  .ui-media {
880
827
  display: grid;
@@ -1045,55 +992,6 @@ hr.ui-divider {
1045
992
  .ui-hero--overlap .ui-hero-subtitle{ color: rgba(255,255,255,.8); }
1046
993
  .ui-hero--overlap .ui-hero-actions { justify-content: flex-start; }
1047
994
 
1048
- /* ─── Testimonial ────────────────────────────────────────────────────────── */
1049
- .ui-testimonial {
1050
- background: var(--ui-surface, var(--surface, #111116));
1051
- border: 1px solid var(--ui-border, var(--border, #222228));
1052
- border-radius: var(--ui-radius, 8px);
1053
- padding: 1.5rem;
1054
- margin: 0;
1055
- }
1056
-
1057
- .ui-testimonial-rating {
1058
- color: #f5a623;
1059
- font-size: 1rem;
1060
- letter-spacing: .1em;
1061
- margin: 0 0 .75rem;
1062
- }
1063
-
1064
- .ui-testimonial-quote { margin: 0 0 1.25rem; }
1065
- .ui-testimonial-quote p {
1066
- font-size: .95rem;
1067
- line-height: 1.65;
1068
- color: var(--ui-text, var(--text, #e2e2ea));
1069
- font-style: italic;
1070
- margin: 0;
1071
- }
1072
-
1073
- .ui-testimonial-author { display: flex; align-items: center; gap: .75rem; }
1074
-
1075
- .ui-testimonial-avatar {
1076
- width: 40px;
1077
- height: 40px;
1078
- border-radius: 50%;
1079
- object-fit: cover;
1080
- flex-shrink: 0;
1081
- }
1082
-
1083
- .ui-testimonial-avatar--initials {
1084
- background: var(--ui-muted-bg, rgba(128,128,128,.2));
1085
- color: var(--ui-text, var(--text, #e2e2ea));
1086
- font-size: .8rem;
1087
- font-weight: 700;
1088
- display: flex;
1089
- align-items: center;
1090
- justify-content: center;
1091
- }
1092
-
1093
- .ui-testimonial-meta { display: flex; flex-direction: column; gap: .1rem; }
1094
- .ui-testimonial-name { font-size: .875rem; font-weight: 600; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
1095
- .ui-testimonial-role { font-size: .78rem; color: var(--ui-muted, var(--muted, #9090a0)); margin: 0; }
1096
-
1097
995
  /* ─── Feature ────────────────────────────────────────────────────────────── */
1098
996
  .ui-feature { display: flex; flex-direction: column; gap: .75rem; }
1099
997
  .ui-feature-image { width: 100%; border-radius: var(--ui-radius-sm); overflow: hidden; }
@@ -1110,68 +1008,6 @@ hr.ui-divider {
1110
1008
 
1111
1009
  .ui-feature--center { align-items: center; text-align: center; }
1112
1010
 
1113
- /* ─── Pricing ────────────────────────────────────────────────────────────── */
1114
- .ui-pricing {
1115
- box-sizing: border-box;
1116
- background: var(--ui-surface, var(--surface, #111116));
1117
- border: 1px solid var(--ui-border, var(--border, #222228));
1118
- border-radius: var(--ui-radius, 8px);
1119
- padding: 2rem;
1120
- display: flex;
1121
- flex-direction: column;
1122
- gap: 1.25rem;
1123
- position: relative;
1124
- width: 100%;
1125
- }
1126
-
1127
- .ui-pricing--highlighted {
1128
- border-color: var(--ui-accent, var(--accent, #9b8dff));
1129
- box-shadow: 0 0 0 1px var(--ui-accent, var(--accent, #9b8dff));
1130
- }
1131
-
1132
- .ui-pricing-badge {
1133
- position: absolute;
1134
- top: -12px;
1135
- left: 50%;
1136
- transform: translateX(-50%);
1137
- background: var(--ui-accent, var(--accent, #9b8dff));
1138
- color: var(--ui-accent-text, #0d0a20);
1139
- font-size: .72rem;
1140
- font-weight: 700;
1141
- letter-spacing: .05em;
1142
- text-transform: uppercase;
1143
- padding: .25rem .75rem;
1144
- border-radius: 99px;
1145
- margin: 0;
1146
- white-space: nowrap;
1147
- }
1148
-
1149
- .ui-pricing-header { display: flex; flex-direction: column; gap: .25rem; }
1150
- .ui-pricing-name { font-size: 1.1rem; font-weight: 700; color: var(--ui-text, var(--text, #e2e2ea)); margin: 0; }
1151
- .ui-pricing-desc { font-size: .875rem; color: var(--ui-muted, var(--muted, #9090a0)); margin: 0; }
1152
-
1153
- .ui-pricing-price { display: flex; align-items: baseline; gap: .3rem; }
1154
- .ui-pricing-amount { font-size: 2.25rem; font-weight: 800; color: var(--ui-text, var(--text, #e2e2ea)); line-height: 1; letter-spacing: -.02em; }
1155
- .ui-pricing-period { font-size: .875rem; color: var(--ui-muted, var(--muted, #9090a0)); }
1156
-
1157
- .ui-pricing-features { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: .6rem; }
1158
- .ui-pricing-feature { font-size: .875rem; color: var(--ui-text, var(--text, #e2e2ea)); display: flex; align-items: flex-start; gap: .5rem; width: 100%; }
1159
- .ui-pricing-check { color: var(--ui-green, var(--green, #3dd68c)); font-weight: 700; flex-shrink: 0; }
1160
-
1161
- /* ─── Pricing grid (responsive) ─────────────────────────────────────────── */
1162
- .ui-pricing-grid {
1163
- display: grid;
1164
- gap: 1.5rem;
1165
- align-items: start;
1166
- grid-template-columns: 1fr;
1167
- width: 100%;
1168
- }
1169
- @media (min-width: 640px) {
1170
- .ui-pricing-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
1171
- .ui-pricing-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
1172
- }
1173
- .ui-pricing-action { margin-top: auto; }
1174
-
1175
1011
  /* ─── Accordion ──────────────────────────────────────────────────────────── */
1176
1012
  .ui-accordion { display: flex; flex-direction: column; gap: .5rem; width: 100%; }
1177
1013
 
@@ -1374,73 +1210,6 @@ hr.ui-divider {
1374
1210
  flex-shrink: 0;
1375
1211
  }
1376
1212
 
1377
- /* ─── Carousel ───────────────────────────────────────────────────────────── */
1378
- .ui-carousel {
1379
- position: relative;
1380
- width: 100%;
1381
- border-radius: var(--ui-radius, 12px);
1382
- overflow: hidden;
1383
- }
1384
-
1385
- .ui-carousel-track {
1386
- display: flex;
1387
- overflow-x: auto;
1388
- scroll-snap-type: x mandatory;
1389
- scroll-behavior: smooth;
1390
- -webkit-overflow-scrolling: touch;
1391
- scrollbar-width: none;
1392
- }
1393
- .ui-carousel-track::-webkit-scrollbar { display: none; }
1394
-
1395
- .ui-carousel-slide {
1396
- flex: 0 0 100%;
1397
- scroll-snap-align: start;
1398
- }
1399
-
1400
- .ui-carousel-btn {
1401
- position: absolute;
1402
- top: 50%;
1403
- transform: translateY(-50%);
1404
- z-index: 2;
1405
- display: flex;
1406
- align-items: center;
1407
- justify-content: center;
1408
- width: 40px;
1409
- height: 40px;
1410
- padding: 0;
1411
- background: var(--ui-surface, var(--surface, #13131e));
1412
- border: 1px solid var(--ui-border, var(--border, #2a2a38));
1413
- border-radius: 50%;
1414
- color: var(--ui-text, var(--text, #e2e2ea));
1415
- cursor: pointer;
1416
- transition: background .15s, opacity .15s;
1417
- }
1418
- .ui-carousel-btn:hover { background: var(--ui-surface-2, var(--surface-2, #1a1a26)); }
1419
- .ui-carousel-btn[hidden] { display: none; }
1420
- .ui-carousel-prev { left: .75rem; }
1421
- .ui-carousel-next { right: .75rem; }
1422
-
1423
- .ui-carousel-dots {
1424
- display: flex;
1425
- justify-content: center;
1426
- gap: .5rem;
1427
- padding: .75rem 0 .5rem;
1428
- }
1429
-
1430
- .ui-carousel-dot {
1431
- width: 8px;
1432
- height: 8px;
1433
- padding: 0;
1434
- background: var(--ui-border, var(--border, #2a2a38));
1435
- border: none;
1436
- border-radius: 50%;
1437
- cursor: pointer;
1438
- transition: background .15s, transform .15s;
1439
- }
1440
- .ui-carousel-dot.active,
1441
- .ui-carousel-dot:hover { background: var(--ui-accent, var(--accent, #9b8dff)); }
1442
- .ui-carousel-dot.active { transform: scale(1.35); }
1443
-
1444
1213
  /* ─── Nav ────────────────────────────────────────────────────────────────── */
1445
1214
  .ui-nav {
1446
1215
  position: relative;
@@ -2291,141 +2060,6 @@ hr.ui-divider {
2291
2060
  .ui-icon-wrap--error { background: var(--ui-red-dim); color: var(--ui-red); }
2292
2061
  .ui-icon-wrap--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
2293
2062
 
2294
- /* ─── Timeline ───────────────────────────────────────────────────────────────
2295
- Shared rules (dot, label, body) apply to both orientations. */
2296
-
2297
- /* Shared base */
2298
- .ui-timeline {
2299
- list-style: none;
2300
- padding: 0;
2301
- margin: 0;
2302
- }
2303
-
2304
- .ui-timeline-dot {
2305
- width: 10px;
2306
- height: 10px;
2307
- border-radius: 50%;
2308
- flex-shrink: 0;
2309
- display: flex;
2310
- align-items: center;
2311
- justify-content: center;
2312
- position: relative;
2313
- z-index: 1;
2314
- }
2315
-
2316
- /* Icon dot — larger, with dim background */
2317
- .ui-timeline-dot--icon {
2318
- width: 2rem;
2319
- height: 2rem;
2320
- border-radius: 50%;
2321
- font-size: 1rem;
2322
- }
2323
-
2324
- /* Dot colour variants */
2325
- .ui-timeline-dot--accent { background: var(--ui-accent); }
2326
- .ui-timeline-dot--success { background: var(--ui-green); }
2327
- .ui-timeline-dot--warning { background: var(--ui-yellow); }
2328
- .ui-timeline-dot--error { background: var(--ui-red); }
2329
- .ui-timeline-dot--muted { background: var(--ui-surface-2); outline: 2px solid var(--ui-border); outline-offset: 0; }
2330
-
2331
- /* Icon dot: dim background + coloured icon */
2332
- .ui-timeline-dot--icon.ui-timeline-dot--accent { background: var(--ui-accent-dim); color: var(--ui-accent); }
2333
- .ui-timeline-dot--icon.ui-timeline-dot--success { background: var(--ui-green-dim); color: var(--ui-green); }
2334
- .ui-timeline-dot--icon.ui-timeline-dot--warning { background: var(--ui-yellow-dim); color: var(--ui-yellow); }
2335
- .ui-timeline-dot--icon.ui-timeline-dot--error { background: var(--ui-red-dim); color: var(--ui-red); }
2336
- .ui-timeline-dot--icon.ui-timeline-dot--muted { background: var(--ui-surface-2); color: var(--ui-muted); }
2337
-
2338
- .ui-timeline-label {
2339
- display: block;
2340
- font-size: .72rem;
2341
- font-weight: 600;
2342
- color: var(--ui-muted);
2343
- letter-spacing: .05em;
2344
- text-transform: uppercase;
2345
- margin-bottom: .35rem;
2346
- }
2347
-
2348
- /* ── Vertical ── */
2349
- .ui-timeline--vertical {
2350
- display: flex;
2351
- flex-direction: column;
2352
- }
2353
-
2354
- .ui-timeline--vertical .ui-timeline-item {
2355
- display: flex;
2356
- gap: 1rem;
2357
- }
2358
-
2359
- .ui-timeline--vertical .ui-timeline-side {
2360
- display: flex;
2361
- flex-direction: column;
2362
- align-items: center;
2363
- flex-shrink: 0;
2364
- }
2365
-
2366
- /* Connecting line segments run above and below the dot */
2367
- .ui-timeline--vertical .ui-timeline-connector {
2368
- width: 2px;
2369
- background: var(--ui-border);
2370
- flex: 1;
2371
- min-height: .75rem;
2372
- }
2373
-
2374
- /* No line above the first item or below the last */
2375
- .ui-timeline--vertical .ui-timeline-item:first-child .ui-timeline-connector--before,
2376
- .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-connector--after {
2377
- visibility: hidden;
2378
- }
2379
-
2380
- .ui-timeline--vertical .ui-timeline-main {
2381
- flex: 1;
2382
- padding-bottom: 1.75rem;
2383
- }
2384
-
2385
- .ui-timeline--vertical .ui-timeline-item:last-child .ui-timeline-main {
2386
- padding-bottom: 0;
2387
- }
2388
-
2389
- /* ── Horizontal ── */
2390
- .ui-timeline--horizontal {
2391
- display: flex;
2392
- align-items: flex-start;
2393
- overflow-x: auto;
2394
- }
2395
-
2396
- .ui-timeline--horizontal .ui-timeline-item {
2397
- flex: 1;
2398
- min-width: 0;
2399
- display: flex;
2400
- flex-direction: column;
2401
- align-items: center;
2402
- }
2403
-
2404
- .ui-timeline--horizontal .ui-timeline-side {
2405
- display: flex;
2406
- align-items: center;
2407
- width: 100%;
2408
- margin-bottom: .75rem;
2409
- }
2410
-
2411
- .ui-timeline--horizontal .ui-timeline-connector {
2412
- flex: 1;
2413
- height: 2px;
2414
- background: var(--ui-border);
2415
- }
2416
-
2417
- /* No line before the first item or after the last */
2418
- .ui-timeline--horizontal .ui-timeline-item:first-child .ui-timeline-connector--before,
2419
- .ui-timeline--horizontal .ui-timeline-item:last-child .ui-timeline-connector--after {
2420
- visibility: hidden;
2421
- }
2422
-
2423
- .ui-timeline--horizontal .ui-timeline-main {
2424
- text-align: center;
2425
- padding: 0 .5rem;
2426
- width: 100%;
2427
- }
2428
-
2429
2063
  /* ─── Switch ─────────────────────────────────────────────────────────────── */
2430
2064
  .ui-switch-input {
2431
2065
  position: absolute;
@@ -3149,18 +2783,6 @@ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { co
3149
2783
  font-size: 0.9375rem;
3150
2784
  }
3151
2785
 
3152
- /* ─── List ───────────────────────────────────────────────────────────────────
3153
- Styled list component. Use instead of raw <ul>/<ol>. */
3154
- .ui-list {
3155
- display: flex;
3156
- flex-direction: column;
3157
- padding-left: 1.5em;
3158
- color: var(--ui-text);
3159
- }
3160
- .ui-list--unordered { list-style-type: disc; }
3161
- .ui-list--ordered { list-style-type: decimal; }
3162
- .ui-list-item { line-height: 1.6; }
3163
-
3164
2786
  /* ─── Prose ──────────────────────────────────────────────────────────────────
3165
2787
  Typography wrapper for rich text: CMS output, markdown-rendered HTML,
3166
2788
  blog/article bodies. Styles all descendant elements without class names. */
@@ -3430,664 +3052,13 @@ fieldset[disabled] .ui-rating-stars .ui-rating-star:hover ~ .ui-rating-star { co
3430
3052
  --ui-letter-spacing-display: -0.02em;
3431
3053
  }
3432
3054
 
3433
- /* ─── Gallery ────────────────────────────────────────────────────────────── */
3434
- .ui-gallery { display: grid; gap: 1rem; }
3435
- .ui-gallery--cols-1 { grid-template-columns: 1fr; }
3436
- .ui-gallery--cols-2 { grid-template-columns: repeat(2, 1fr); }
3437
- .ui-gallery--cols-3 { grid-template-columns: repeat(3, 1fr); }
3438
- .ui-gallery--cols-4 { grid-template-columns: repeat(4, 1fr); }
3439
- .ui-gallery--gap-sm { gap: .5rem; }
3440
- .ui-gallery--gap-lg { gap: 1.5rem; }
3441
- .ui-gallery-item { margin: 0; }
3442
- .ui-gallery-crop { overflow: hidden; }
3443
- .ui-gallery-img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .3s ease; }
3444
- .ui-gallery--rounded .ui-gallery-crop { border-radius: var(--ui-radius); }
3445
- .ui-gallery-item:hover .ui-gallery-img { transform: scale(1.03); }
3446
- .ui-gallery-link { display: block; }
3447
- .ui-gallery-caption { font-size: .8125rem; color: var(--ui-muted); padding: .5rem 0 0; }
3448
-
3449
- /* strip: horizontal scroll row */
3450
- .ui-gallery--strip { grid-template-columns: none; display: flex; overflow-x: auto; gap: 1rem; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; }
3451
- .ui-gallery--strip .ui-gallery-item { flex: 0 0 auto; width: 280px; scroll-snap-align: start; }
3452
- .ui-gallery--strip .ui-gallery-crop { aspect-ratio: 3/4; }
3453
-
3454
- /* masonry: CSS column layout */
3455
- .ui-gallery--masonry { display: block; columns: 3; column-gap: 1rem; }
3456
- .ui-gallery--masonry.ui-gallery--cols-2 { columns: 2; }
3457
- .ui-gallery--masonry.ui-gallery--cols-4 { columns: 4; }
3458
- .ui-gallery--masonry .ui-gallery-item { break-inside: avoid; margin-bottom: 1rem; }
3459
- .ui-gallery--masonry .ui-gallery-crop { aspect-ratio: unset; }
3460
- .ui-gallery--masonry .ui-gallery-img { height: auto; }
3461
-
3462
- @media (max-width: 640px) {
3463
- .ui-gallery--cols-3,
3464
- .ui-gallery--cols-4 { grid-template-columns: repeat(2, 1fr); }
3465
- .ui-gallery--masonry.ui-gallery--cols-3,
3466
- .ui-gallery--masonry.ui-gallery--cols-4 { columns: 2; }
3467
- }
3468
-
3469
- /* ─── PhotoCard ──────────────────────────────────────────────────────────── */
3470
- .ui-photo-card {
3471
- margin: 0;
3472
- display: inline-flex;
3473
- flex-direction: column;
3474
- background: var(--ui-surface);
3475
- padding: .75rem .75rem .5rem;
3476
- border: 1px solid var(--ui-border);
3477
- box-shadow: 0 4px 12px rgba(0,0,0,.25);
3478
- rotate: var(--photo-tilt, 0deg);
3479
- transition: rotate .2s ease, box-shadow .2s ease;
3480
- }
3481
- .ui-photo-card:hover { box-shadow: 0 8px 24px rgba(0,0,0,.35); }
3482
- .ui-photo-card--rounded .ui-photo-card-crop { border-radius: var(--ui-radius); overflow: hidden; }
3483
- .ui-photo-card-crop { overflow: hidden; }
3484
- .ui-photo-card-img { width: 100%; height: 100%; object-fit: cover; display: block; }
3485
- .ui-photo-card-caption {
3486
- font-size: .8125rem;
3487
- color: var(--ui-muted);
3488
- padding: .5rem .25rem .25rem;
3489
- text-align: center;
3490
- font-family: var(--ui-mono);
3491
- }
3492
-
3493
- /* ─── Marquee ────────────────────────────────────────────────────────────── */
3494
- @keyframes ui-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
3495
-
3496
- .ui-marquee { overflow: hidden; }
3497
- .ui-marquee--fade {
3498
- mask-image: linear-gradient(to right, transparent 0%, #000 10%, #000 90%, transparent 100%);
3499
- -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 10%, #000 90%, transparent 100%);
3500
- }
3501
- .ui-marquee-track {
3502
- display: flex;
3503
- width: max-content;
3504
- animation: ui-marquee var(--marquee-speed, 30s) linear infinite;
3505
- animation-direction: var(--marquee-dir, normal);
3506
- list-style: none;
3507
- margin: 0;
3508
- padding: 0;
3509
- gap: 3rem;
3510
- }
3511
- .ui-marquee--gap-sm .ui-marquee-track { gap: 1rem; }
3512
- .ui-marquee--gap-md .ui-marquee-track { gap: 2rem; }
3513
- .ui-marquee--pause:hover .ui-marquee-track { animation-play-state: paused; }
3514
- .ui-marquee-item { flex: 0 0 auto; display: flex; align-items: center; }
3515
-
3516
- @media (prefers-reduced-motion: reduce) {
3517
- .ui-marquee-track { animation: none; }
3518
- .ui-marquee { overflow-x: auto; }
3519
- }
3520
-
3521
- /* ─── Decorate (SVG pattern overlay) ────────────────────────────────────── */
3522
- .ui-decorate { pointer-events: none; }
3523
-
3524
- /* ─── Product Card ───────────────────────────────────────────────────────── */
3525
- .ui-product-card {
3526
- position: relative;
3527
- display: block;
3528
- overflow: hidden;
3529
- text-decoration: none;
3530
- color: inherit;
3531
- }
3532
- .ui-product-card-crop {
3533
- overflow: hidden;
3534
- }
3535
- .ui-product-card-img {
3536
- width: 100%;
3537
- height: 100%;
3538
- object-fit: cover;
3539
- display: block;
3540
- transition: transform 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94);
3541
- }
3542
- .ui-product-card:hover .ui-product-card-img { transform: scale(1.04); }
3543
- .ui-product-card:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; }
3544
-
3545
- .ui-product-card-overlay {
3546
- position: absolute;
3547
- inset: 0;
3548
- display: flex;
3549
- flex-direction: column;
3550
- justify-content: flex-end;
3551
- padding: 1.25rem;
3552
- background: linear-gradient(to top, rgba(0,0,0,0.55) 0%, transparent 55%);
3553
- opacity: 0;
3554
- transition: opacity 0.3s ease;
3555
- }
3556
- .ui-product-card:hover .ui-product-card-overlay { opacity: 1; }
3557
-
3558
- /* Always-visible overlay for reduced-motion users */
3559
- @media (prefers-reduced-motion: reduce) {
3560
- .ui-product-card-img { transition: none; }
3561
- .ui-product-card-overlay { opacity: 1; }
3562
- }
3563
-
3564
- .ui-product-card-name {
3565
- font-size: 1rem;
3566
- font-weight: 500;
3567
- color: #fff;
3568
- margin: 0;
3569
- letter-spacing: 0.02em;
3570
- }
3571
- .ui-product-card-price {
3572
- font-size: 0.875rem;
3573
- color: rgba(255,255,255,0.75);
3574
- margin: 0.3rem 0 0;
3575
- }
3576
-
3577
- .ui-product-card-badge {
3578
- position: absolute;
3579
- top: 1rem;
3580
- left: 1rem;
3581
- background: var(--ui-text);
3582
- color: var(--ui-bg);
3583
- font-size: 0.6875rem;
3584
- font-weight: 600;
3585
- letter-spacing: 0.08em;
3586
- text-transform: uppercase;
3587
- padding: 0.2em 0.6em;
3588
- z-index: 1;
3055
+ /* Stat suffix — icon/rating appended to the value */
3056
+ .ui-stat-suffix {
3057
+ display: inline-flex;
3058
+ align-items: center;
3059
+ margin-left: 0.2em;
3060
+ font-size: 0.6em;
3061
+ vertical-align: middle;
3062
+ line-height: 0;
3589
3063
  }
3590
- .ui-product-card--badge-right .ui-product-card-badge { left: auto; right: 1rem; }
3591
3064
 
3592
- /* Below layout — caption sits under the image, always visible */
3593
- .ui-product-card--below {
3594
- overflow: visible;
3595
- }
3596
- .ui-product-card-caption {
3597
- text-align: center;
3598
- padding: 0.75rem 0.5rem 0.25rem;
3599
- background: var(--ui-surface);
3600
- }
3601
- .ui-product-card--below .ui-product-card-name {
3602
- font-size: 1rem;
3603
- font-weight: 400;
3604
- color: var(--ui-text);
3605
- margin: 0 0 0.25rem;
3606
- font-style: normal;
3607
- }
3608
- .ui-product-card--below .ui-product-card-price {
3609
- font-size: 0.875rem;
3610
- color: var(--ui-muted);
3611
- margin: 0;
3612
- }
3613
-
3614
- /* ─── Editorial Hero ─────────────────────────────────────────────────────── */
3615
- .ui-editorial-hero {
3616
- position: relative;
3617
- overflow: hidden;
3618
- }
3619
-
3620
- .ui-editorial-hero-heading {
3621
- position: absolute;
3622
- width: 1px;
3623
- height: 1px;
3624
- overflow: hidden;
3625
- clip: rect(0,0,0,0);
3626
- margin: -1px;
3627
- padding: 0;
3628
- border: 0;
3629
- }
3630
-
3631
- .ui-editorial-hero-images {
3632
- display: grid;
3633
- grid-template-columns: 1fr 1fr;
3634
- width: 100%;
3635
- }
3636
- .ui-editorial-hero-img {
3637
- overflow: hidden;
3638
- }
3639
- .ui-editorial-hero-img img {
3640
- width: 100%;
3641
- height: 100%;
3642
- object-fit: cover;
3643
- display: block;
3644
- }
3645
-
3646
- .ui-editorial-hero-overlay {
3647
- position: absolute;
3648
- inset: 0;
3649
- display: flex;
3650
- flex-direction: column;
3651
- justify-content: center;
3652
- align-items: center;
3653
- pointer-events: none;
3654
- color: var(--ui-accent);
3655
- mix-blend-mode: multiply;
3656
- }
3657
- .ui-editorial-hero-overlay span {
3658
- display: block;
3659
- font-size: clamp(3rem, 12vw, 11rem);
3660
- font-weight: 700;
3661
- letter-spacing: -0.04em;
3662
- line-height: 0.9;
3663
- text-transform: uppercase;
3664
- white-space: nowrap;
3665
- }
3666
-
3667
- .ui-editorial-hero-cta {
3668
- position: absolute;
3669
- bottom: 1.5rem;
3670
- left: 50%;
3671
- transform: translateX(-50%);
3672
- font-size: 0.75rem;
3673
- letter-spacing: 0.1em;
3674
- text-transform: uppercase;
3675
- text-decoration: none;
3676
- color: var(--ui-text);
3677
- white-space: nowrap;
3678
- }
3679
-
3680
- @media (max-width: 640px) {
3681
- .ui-editorial-hero-overlay span { font-size: clamp(2rem, 10vw, 4rem); }
3682
- }
3683
-
3684
- /* ─── Image Pair ─────────────────────────────────────────────────────────── */
3685
- .ui-image-pair {
3686
- display: grid;
3687
- grid-template-columns: 1fr 1fr;
3688
- width: 100%;
3689
- }
3690
- .ui-image-pair--gap-sm { gap: 0.5rem; }
3691
- .ui-image-pair--gap-md { gap: 1.5rem; }
3692
-
3693
- .ui-image-pair-col { overflow: hidden; }
3694
- .ui-image-pair-img { overflow: hidden; }
3695
- .ui-image-pair-crop { overflow: hidden; }
3696
- .ui-image-pair-crop img {
3697
- width: 100%;
3698
- height: 100%;
3699
- object-fit: cover;
3700
- display: block;
3701
- }
3702
- .ui-image-pair--captioned .ui-image-pair-col { overflow: visible; }
3703
-
3704
- .ui-image-pair-link {
3705
- display: inline-block;
3706
- margin-top: 0.75rem;
3707
- font-size: 0.9375rem;
3708
- text-decoration: none;
3709
- color: var(--ui-text);
3710
- }
3711
- .ui-image-pair-link:hover { opacity: 0.6; }
3712
-
3713
- @media (max-width: 480px) {
3714
- .ui-image-pair { grid-template-columns: 1fr; }
3715
- }
3716
-
3717
- /* ─── Brand Statement ────────────────────────────────────────────────────── */
3718
- .ui-brand-statement {
3719
- padding: 5rem 1.5rem;
3720
- text-align: center;
3721
- }
3722
- .ui-brand-statement--left { text-align: left; }
3723
- .ui-brand-statement--right { text-align: right; }
3724
-
3725
- .ui-brand-statement-inner {
3726
- max-width: 860px;
3727
- margin: 0 auto;
3728
- }
3729
-
3730
- .ui-brand-statement-text {
3731
- font-size: clamp(1.5rem, 4vw, 2.5rem);
3732
- line-height: 1.25;
3733
- font-weight: 400;
3734
- font-style: italic;
3735
- margin: 0;
3736
- color: var(--ui-text);
3737
- }
3738
-
3739
- .ui-brand-statement--display .ui-brand-statement-text {
3740
- font-style: normal;
3741
- font-weight: 700;
3742
- }
3743
-
3744
- .ui-brand-statement--sans .ui-brand-statement-text {
3745
- font-style: normal;
3746
- }
3747
-
3748
- .ui-brand-statement--sm .ui-brand-statement-text { font-size: clamp(1.1rem, 2.5vw, 1.5rem); }
3749
- .ui-brand-statement--lg .ui-brand-statement-text { font-size: clamp(2rem, 5vw, 3.5rem); }
3750
-
3751
- .ui-brand-statement-attr {
3752
- margin-top: 1.5rem;
3753
- font-size: 0.9375rem;
3754
- color: var(--ui-muted);
3755
- font-style: italic;
3756
- }
3757
-
3758
- /* ------------------------------------------------------------------ */
3759
- /* ServiceCard */
3760
- /* ------------------------------------------------------------------ */
3761
-
3762
- .ui-service-card {
3763
- display: block;
3764
- padding: var(--ui-space-5, 1.25rem);
3765
- border: 1px solid var(--ui-border);
3766
- border-radius: var(--ui-radius-md);
3767
- background: var(--ui-surface);
3768
- text-decoration: none;
3769
- color: inherit;
3770
- }
3771
-
3772
- .ui-service-card--linked {
3773
- transition: border-color 0.15s, box-shadow 0.15s;
3774
- }
3775
-
3776
- .ui-service-card--linked:hover {
3777
- border-color: var(--ui-accent);
3778
- box-shadow: 0 2px 12px var(--ui-shadow, rgba(0,0,0,.08));
3779
- }
3780
-
3781
- .ui-service-card-icon {
3782
- display: inline-flex;
3783
- align-items: center;
3784
- justify-content: center;
3785
- width: 2.5rem;
3786
- height: 2.5rem;
3787
- border-radius: var(--ui-radius);
3788
- background: var(--ui-accent-tint);
3789
- color: var(--ui-accent);
3790
- margin-block-end: var(--ui-space-4, 1rem);
3791
- }
3792
-
3793
- .ui-service-card-title {
3794
- font-size: var(--ui-text-md, 1rem);
3795
- font-weight: 600;
3796
- margin: 0 0 var(--ui-space-2, 0.5rem);
3797
- color: var(--ui-text);
3798
- }
3799
-
3800
- .ui-service-card-desc {
3801
- margin: 0;
3802
- font-size: var(--ui-text-sm, 0.875rem);
3803
- color: var(--ui-muted);
3804
- line-height: 1.6;
3805
- }
3806
-
3807
- /* ------------------------------------------------------------------ */
3808
- /* ContactRow */
3809
- /* ------------------------------------------------------------------ */
3810
-
3811
- .ui-contact-row {
3812
- display: flex;
3813
- flex-wrap: wrap;
3814
- gap: var(--ui-space-3, 0.75rem) var(--ui-space-6, 1.5rem);
3815
- list-style: none;
3816
- margin: 0;
3817
- padding: 0;
3818
- }
3819
-
3820
- .ui-contact-row--sm { font-size: var(--ui-text-sm, 0.875rem); }
3821
-
3822
- .ui-contact-row-item {
3823
- display: flex;
3824
- align-items: center;
3825
- gap: var(--ui-space-2, 0.5rem);
3826
- color: var(--ui-muted);
3827
- }
3828
-
3829
- .ui-contact-row-item a {
3830
- color: inherit;
3831
- text-decoration: none;
3832
- }
3833
-
3834
- .ui-contact-row-item a:hover { color: var(--ui-accent); }
3835
-
3836
- .ui-contact-row-icon {
3837
- flex-shrink: 0;
3838
- color: var(--ui-accent);
3839
- line-height: 0;
3840
- }
3841
-
3842
- /* ------------------------------------------------------------------ */
3843
- /* TrustList */
3844
- /* ------------------------------------------------------------------ */
3845
-
3846
- .ui-trust-list {
3847
- display: flex;
3848
- flex-wrap: wrap;
3849
- gap: var(--ui-space-2, 0.5rem) var(--ui-space-5, 1.25rem);
3850
- list-style: none;
3851
- margin: 0;
3852
- padding: 0;
3853
- }
3854
-
3855
- .ui-trust-list--md { font-size: var(--ui-text-md, 1rem); }
3856
-
3857
- .ui-trust-list-item {
3858
- display: flex;
3859
- align-items: center;
3860
- gap: var(--ui-space-2, 0.5rem);
3861
- font-size: var(--ui-text-sm, 0.875rem);
3862
- color: var(--ui-muted);
3863
- }
3864
-
3865
- .ui-trust-list-icon {
3866
- flex-shrink: 0;
3867
- color: var(--ui-accent);
3868
- line-height: 0;
3869
- }
3870
-
3871
- /* ------------------------------------------------------------------ */
3872
- /* TopStrip */
3873
- /* ------------------------------------------------------------------ */
3874
-
3875
- .ui-top-strip {
3876
- display: flex;
3877
- align-items: center;
3878
- justify-content: space-between;
3879
- padding: var(--ui-space-2, 0.5rem) var(--ui-space-6, 1.5rem);
3880
- background: var(--ui-surface-raised, var(--ui-surface));
3881
- font-size: var(--ui-text-xs, 0.75rem);
3882
- color: var(--ui-muted);
3883
- gap: var(--ui-space-4, 1rem);
3884
- }
3885
-
3886
- .ui-top-strip-content,
3887
- .ui-top-strip-left,
3888
- .ui-top-strip-right {
3889
- display: flex;
3890
- align-items: center;
3891
- gap: var(--ui-space-4, 1rem);
3892
- flex-wrap: wrap;
3893
- }
3894
-
3895
- @media (max-width: 640px) {
3896
- .ui-top-strip {
3897
- flex-direction: column;
3898
- align-items: flex-start;
3899
- gap: var(--ui-space-1, 0.25rem);
3900
- }
3901
- }
3902
-
3903
- /* ------------------------------------------------------------------ */
3904
- /* StatGrid */
3905
- /* ------------------------------------------------------------------ */
3906
-
3907
- .ui-stat-grid {
3908
- display: grid;
3909
- gap: var(--ui-space-4, 1rem);
3910
- grid-template-columns: repeat(var(--stat-cols, 2), 1fr);
3911
- padding: var(--ui-space-6, 1.5rem);
3912
- border-radius: var(--ui-radius-md);
3913
- }
3914
-
3915
- .ui-stat-grid .ui-stat-value {
3916
- font-size: clamp(1.5rem, 3vw, 2.25rem);
3917
- line-height: 1.1;
3918
- }
3919
-
3920
- /* Stat suffix — icon/rating appended to the value */
3921
- .ui-stat-suffix {
3922
- display: inline-flex;
3923
- align-items: center;
3924
- margin-left: 0.2em;
3925
- font-size: 0.6em;
3926
- vertical-align: middle;
3927
- line-height: 0;
3928
- }
3929
-
3930
- /* ─── Editorial Components ───────────────────────────────────────────────────
3931
- Components for editorial/typographic layouts: entryList, displayHeading,
3932
- sectionLabel, dropCap, colophon. */
3933
-
3934
- /* Entry List — tabular list for backlists, release notes, changelogs */
3935
- .ui-entry-list {
3936
- display: flex;
3937
- flex-direction: column;
3938
- gap: 1.5rem;
3939
- }
3940
-
3941
- .ui-entry-list-item {
3942
- display: grid;
3943
- grid-template-columns: minmax(4rem, max-content) 1fr;
3944
- gap: 2rem;
3945
- align-items: baseline;
3946
- }
3947
-
3948
- @media (max-width: 640px) {
3949
- .ui-entry-list-item {
3950
- grid-template-columns: 1fr;
3951
- gap: 0.5rem;
3952
- }
3953
- }
3954
-
3955
- .ui-entry-list-meta {
3956
- font-size: 0.9rem;
3957
- color: var(--ui-muted);
3958
- font-weight: 600;
3959
- text-transform: uppercase;
3960
- letter-spacing: 0.05em;
3961
- font-variant-numeric: tabular-nums;
3962
- }
3963
-
3964
- .ui-entry-list-content {
3965
- display: flex;
3966
- flex-direction: column;
3967
- gap: 0.5rem;
3968
- }
3969
-
3970
- .ui-entry-list-title {
3971
- font-size: 1.1rem;
3972
- font-weight: 600;
3973
- color: var(--ui-text);
3974
- line-height: 1.4;
3975
- margin: 0;
3976
- }
3977
-
3978
- .ui-entry-list-description {
3979
- font-size: 0.9rem;
3980
- color: var(--ui-muted);
3981
- line-height: 1.6;
3982
- margin: 0;
3983
- }
3984
-
3985
- /* Display Heading — large typographic moments */
3986
- .ui-display-heading {
3987
- font-size: clamp(2.5rem, 6vw, 5rem);
3988
- font-weight: 800;
3989
- color: var(--ui-text);
3990
- line-height: 1.1;
3991
- margin: 0;
3992
- }
3993
-
3994
- /* Section Label — eyebrow + h2 + rule */
3995
- .ui-section-label {
3996
- display: flex;
3997
- flex-direction: column;
3998
- gap: 0.75rem;
3999
- margin-bottom: 2rem;
4000
- }
4001
-
4002
- .ui-section-label--center {
4003
- align-items: center;
4004
- text-align: center;
4005
- }
4006
-
4007
- .ui-section-label-eyebrow {
4008
- font-size: 0.85rem;
4009
- color: var(--ui-muted);
4010
- font-weight: 600;
4011
- text-transform: uppercase;
4012
- letter-spacing: 0.08em;
4013
- margin: 0;
4014
- }
4015
-
4016
- .ui-section-label-heading {
4017
- font-size: 1.75rem;
4018
- font-weight: 700;
4019
- color: var(--ui-text);
4020
- line-height: 1.2;
4021
- margin: 0;
4022
- }
4023
-
4024
- .ui-section-label-rule {
4025
- width: 100%;
4026
- max-width: 8rem;
4027
- height: 2px;
4028
- background: var(--ui-border);
4029
- border: none;
4030
- margin: 0;
4031
- }
4032
-
4033
- .ui-section-label--center .ui-section-label-rule {
4034
- margin-left: auto;
4035
- margin-right: auto;
4036
- }
4037
-
4038
- /* Drop Cap — first-letter treatment */
4039
- .ui-drop-cap {
4040
- margin: 0;
4041
- line-height: 1.75;
4042
- color: var(--ui-text);
4043
- }
4044
-
4045
- .ui-drop-cap-letter {
4046
- /* line-height ~cap height keeps the float box hugging the glyph so the cap
4047
- top-aligns with the first text line — a relative line-height makes serif
4048
- caps float below the opening line. Component sets font-size inline. */
4049
- float: left;
4050
- font-weight: 700;
4051
- line-height: 0.82;
4052
- margin-right: 0.1em;
4053
- color: var(--ui-text);
4054
- }
4055
-
4056
- /* Colophon — minimal footer for editorial pages */
4057
- .ui-colophon {
4058
- padding: 3rem 1.5rem 2rem;
4059
- border-top: 1px solid var(--ui-border);
4060
- margin-top: 4rem;
4061
- text-align: center;
4062
- }
4063
-
4064
- .ui-colophon--left {
4065
- text-align: left;
4066
- }
4067
-
4068
- .ui-colophon-inner {
4069
- max-width: 640px;
4070
- margin: 0 auto;
4071
- font-size: 0.85rem;
4072
- color: var(--ui-muted);
4073
- line-height: 1.6;
4074
- }
4075
-
4076
- .ui-colophon-inner p {
4077
- margin: 0.5em 0;
4078
- }
4079
-
4080
- .ui-colophon-inner p:last-child {
4081
- margin-bottom: 0;
4082
- }
4083
-
4084
- .ui-colophon-inner a {
4085
- color: var(--ui-muted);
4086
- text-decoration: underline;
4087
- text-underline-offset: 2px;
4088
- transition: color 0.15s;
4089
- }
4090
-
4091
- .ui-colophon-inner a:hover {
4092
- color: var(--ui-text);
4093
- }