@getvitops/core 0.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 (57) hide show
  1. package/README.md +29 -0
  2. package/css/animation.css +526 -0
  3. package/css/global.css +17 -0
  4. package/css/index.css +58 -0
  5. package/css/layout.css +723 -0
  6. package/css/patterns/anchor-link.css +66 -0
  7. package/css/patterns/banner.css +64 -0
  8. package/css/patterns/carousel.css +269 -0
  9. package/css/patterns/cluster.css +64 -0
  10. package/css/patterns/code.css +17 -0
  11. package/css/patterns/combobox.css +97 -0
  12. package/css/patterns/comment.css +88 -0
  13. package/css/patterns/copy.css +82 -0
  14. package/css/patterns/details.css +87 -0
  15. package/css/patterns/dialog.css +99 -0
  16. package/css/patterns/drawer.css +108 -0
  17. package/css/patterns/dropdown.css +45 -0
  18. package/css/patterns/forms.css +335 -0
  19. package/css/patterns/grouped.css +86 -0
  20. package/css/patterns/horizontal-scroll.css +40 -0
  21. package/css/patterns/icon.css +72 -0
  22. package/css/patterns/lightbox.css +156 -0
  23. package/css/patterns/list.css +272 -0
  24. package/css/patterns/marquee.css +68 -0
  25. package/css/patterns/masonry.css +40 -0
  26. package/css/patterns/media.css +70 -0
  27. package/css/patterns/nav.css +241 -0
  28. package/css/patterns/notification.css +114 -0
  29. package/css/patterns/overlay.css +28 -0
  30. package/css/patterns/popover.css +68 -0
  31. package/css/patterns/pull-quote.css +71 -0
  32. package/css/patterns/scroll-based.css +227 -0
  33. package/css/patterns/scroll-target.css +124 -0
  34. package/css/patterns/separator.css +130 -0
  35. package/css/patterns/sitenav.css +582 -0
  36. package/css/patterns/split-link.css +113 -0
  37. package/css/patterns/splitter.css +212 -0
  38. package/css/patterns/stack.css +67 -0
  39. package/css/patterns/sticky.css +127 -0
  40. package/css/patterns/subgrid.css +178 -0
  41. package/css/patterns/svg.css +166 -0
  42. package/css/patterns/table.css +106 -0
  43. package/css/patterns/tag.css +75 -0
  44. package/css/patterns/text-effects.css +317 -0
  45. package/css/patterns/tooltip.css +68 -0
  46. package/css/patterns/tree.css +126 -0
  47. package/css/utilities.css +351 -0
  48. package/dist/deferred.js +1 -0
  49. package/dist/elements.js +887 -0
  50. package/dist/polyfills/adoptedStyleSheets.js +1 -0
  51. package/dist/polyfills/css-anchor-positioning-fn.js +17 -0
  52. package/dist/polyfills/global.esm.js +1 -0
  53. package/dist/polyfills/popover.js +63 -0
  54. package/dist/polyfills/template-shadowroot.js +24 -0
  55. package/dist/polyfills/webcomponents-bundle.js +27 -0
  56. package/dist/polyfills.js +1 -0
  57. package/package.json +33 -0
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Split Link — a primary <a> paired with a <button> that toggles an anchored
3
+ * [popover] of secondary content (the "split button" pattern).
4
+ *
5
+ * No JS: the toggle uses the native Popover API (a `popovertarget` invoker); the
6
+ * panel is placed with CSS Anchor Positioning. Placement is authored via a single
7
+ * `--split-link-area` custom property (a `position-area` value expressed with
8
+ * logical keywords) — the Bricks control writes it onto the wrapper, where it
9
+ * inherits down to the panel.
10
+ *
11
+ * Anchoring: the panel lives in the top layer, so a plain `position: relative`
12
+ * parent can't contain it — each instance needs a unique `anchor-name`. The Bricks
13
+ * element sets `anchor-name` on the wrapper and a matching `position-anchor` on the
14
+ * panel inline (derived from the element id). For hand-authored one-offs, add your
15
+ * own matching pair.
16
+ *
17
+ * `.split-link--show-on-hover` (a CSS-only, non-top-layer hover reveal) lives in
18
+ * dropdown.css and is a separate mechanism from this click-to-toggle component.
19
+ */
20
+
21
+ /* ── Group — the link and its toggle sit flush as one control ──────────────── */
22
+ .split-link {
23
+ display: inline-flex;
24
+ align-items: stretch;
25
+ position: relative; /* containing-block fallback where anchoring is unsupported */
26
+ }
27
+
28
+ .split-link__toggle {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ padding-inline: var(--split-link-toggle-pad, 0.5rem);
33
+ background: transparent;
34
+ border: none;
35
+ color: inherit;
36
+ cursor: pointer;
37
+ line-height: 1;
38
+ transition: background-color 0.15s ease;
39
+
40
+ &:hover {
41
+ background: var(--color-surface-l);
42
+ }
43
+
44
+ &:focus-visible {
45
+ outline: 2px solid var(--split-link-focus-color, var(--color-brand-primary-l));
46
+ outline-offset: 2px;
47
+ }
48
+
49
+ /* Caret flips while the panel is open (button reflects aria-expanded). */
50
+ .split-link__caret {
51
+ display: inline-block;
52
+ transition: rotate 0.15s ease;
53
+ }
54
+
55
+ &[aria-expanded='true'] .split-link__caret {
56
+ rotate: 180deg;
57
+ }
58
+ }
59
+
60
+ /* ── Panel — the content box (shared by the live popover and the builder's
61
+ always-visible editing variant, which omits the `popover` attribute) ───── */
62
+ .split-link__panel {
63
+ --_p: var(--p-split-link, var(--p-split-link-group, var(--p-panel)));
64
+ --_b: var(--b-split-link, var(--b-split-link-group, var(--b-panel)));
65
+ --_br: var(--br-split-link, var(--br-split-link-group, var(--br-panel)));
66
+ --_ds: var(--ds-split-link, var(--ds-split-link-group, var(--ds-panel)));
67
+
68
+ min-inline-size: max-content;
69
+ max-inline-size: min(24rem, 90vw);
70
+ padding: var(--_p);
71
+ border: var(--_b);
72
+ border-radius: var(--_br);
73
+ box-shadow: var(--_ds);
74
+ background: var(--color-surface-xxl);
75
+ color: var(--color-surface-xxd);
76
+ }
77
+
78
+ /* Top-layer popover: anchored + placed via position-area. */
79
+ [popover].split-link__panel {
80
+ position: fixed;
81
+ inset: auto;
82
+ /* Logical default: open below the group, spanning toward inline-end. The
83
+ Bricks placement control overrides --split-link-area. position-area shifts
84
+ to stay on-screen (it does not flip — a click panel staying put is fine). */
85
+ position-area: var(--split-link-area, block-end span-inline-end);
86
+ margin: var(--split-link-gap, 0.5rem);
87
+ z-index: var(--z-tier-overlay);
88
+
89
+ /* Popover API toggles display; fade across the top-layer transition. */
90
+ opacity: 0;
91
+ transition:
92
+ opacity 0.15s ease,
93
+ overlay 0.15s allow-discrete,
94
+ display 0.15s allow-discrete;
95
+
96
+ &:popover-open {
97
+ opacity: 1;
98
+
99
+ @starting-style {
100
+ opacity: 0;
101
+ }
102
+ }
103
+
104
+ &::backdrop {
105
+ background: transparent;
106
+ }
107
+ }
108
+
109
+ /* Builder-only: rendered without the `popover` attribute so nested content is
110
+ visible and droppable while editing (a live [popover] is display:none). */
111
+ .split-link__panel--editing {
112
+ margin-block-start: var(--split-link-gap, 0.5rem);
113
+ }
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Splitter — pattern partial migrated from old-css-lib.
3
+ * Consumes the generated token cascade (src/css/generated/tokens.css).
4
+ */
5
+
6
+ /* ── Splitter + Image-compare — CSS shell; drag behaviour lands via Lit ────── */
7
+ .splitter {
8
+ --_splitter-handle-size: var(--splitter-handle-size, 8px);
9
+
10
+ display: flex;
11
+
12
+ &:not(.splitter--vertical) {
13
+ flex-direction: row;
14
+ }
15
+ &.splitter--vertical {
16
+ flex-direction: column;
17
+ }
18
+
19
+ .splitter__panel {
20
+ overflow: auto;
21
+ }
22
+
23
+ .splitter__panel:first-child {
24
+ flex: var(--splitter-ratio, 1);
25
+ }
26
+ .splitter__panel:last-child {
27
+ flex: calc(2 - var(--splitter-ratio, 1));
28
+ }
29
+
30
+ .splitter__handle {
31
+ flex-shrink: 0;
32
+ background: currentColor;
33
+ opacity: 0.15;
34
+ transition: opacity 0.15s ease;
35
+ position: relative;
36
+
37
+ &:hover,
38
+ &:focus-visible {
39
+ opacity: 0.3;
40
+ }
41
+ &:focus-visible {
42
+ outline: 2px solid;
43
+ outline-offset: 2px;
44
+ }
45
+
46
+ &::after {
47
+ content: '';
48
+ position: absolute;
49
+ inset: 50%;
50
+ translate: -50% -50%;
51
+ background: currentColor;
52
+ opacity: 0.3;
53
+ border-radius: 1px;
54
+ }
55
+ }
56
+
57
+ &:not(.splitter--vertical) .splitter__handle {
58
+ inline-size: var(--_splitter-handle-size);
59
+ cursor: col-resize;
60
+
61
+ &::after {
62
+ inline-size: 2px;
63
+ block-size: 24px;
64
+ }
65
+ }
66
+
67
+ &.splitter--vertical .splitter__handle {
68
+ block-size: var(--_splitter-handle-size);
69
+ cursor: row-resize;
70
+
71
+ &::after {
72
+ inline-size: 24px;
73
+ block-size: 2px;
74
+ }
75
+ }
76
+ }
77
+
78
+ .image-compare {
79
+ --_compare-position: var(--compare-position, 50%);
80
+ --_compare-handle-size: var(--compare-handle-size, 40px);
81
+
82
+ position: relative;
83
+ overflow: hidden;
84
+ touch-action: pan-y;
85
+ user-select: none;
86
+
87
+ .image-compare__before {
88
+ position: absolute;
89
+ inset: 0;
90
+ clip-path: inset(0 calc(100% - var(--_compare-position)) 0 0);
91
+ }
92
+
93
+ .image-compare__before > img {
94
+ inline-size: 100%;
95
+ block-size: 100%;
96
+ object-fit: cover;
97
+ }
98
+
99
+ .image-compare__after {
100
+ display: block;
101
+ }
102
+
103
+ .image-compare__after > img {
104
+ inline-size: 100%;
105
+ block-size: auto;
106
+ display: block;
107
+ }
108
+
109
+ .image-compare__handle {
110
+ position: absolute;
111
+ inset-block: 0;
112
+ inset-inline-start: var(--_compare-position);
113
+ translate: -50% 0;
114
+ inline-size: var(--_compare-handle-size);
115
+ display: flex;
116
+ flex-direction: column;
117
+ align-items: center;
118
+ cursor: ew-resize;
119
+ }
120
+
121
+ .image-compare__handle::before {
122
+ content: '';
123
+ position: absolute;
124
+ inset-block: 0;
125
+ inset-inline-start: 50%;
126
+ translate: -50% 0;
127
+ inline-size: 2px;
128
+ background: currentColor;
129
+ }
130
+
131
+ .image-compare__grip {
132
+ position: absolute;
133
+ inset-block-start: 50%;
134
+ inset-inline-start: 50%;
135
+ translate: -50% -50%;
136
+ inline-size: var(--_compare-handle-size);
137
+ block-size: var(--_compare-handle-size);
138
+ background: currentColor;
139
+ border-radius: 50%;
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ gap: 4px;
144
+ }
145
+
146
+ .image-compare__grip::before,
147
+ .image-compare__grip::after {
148
+ content: '';
149
+ inline-size: 0;
150
+ block-size: 0;
151
+ border: 5px solid transparent;
152
+ }
153
+
154
+ .image-compare__grip::before {
155
+ border-inline-end-color: currentColor;
156
+ }
157
+ .image-compare__grip::after {
158
+ border-inline-start-color: currentColor;
159
+ }
160
+
161
+ .image-compare__label {
162
+ position: absolute;
163
+ padding: 0.25rem 0.5rem;
164
+ font-size: 0.75rem;
165
+ text-transform: uppercase;
166
+ letter-spacing: 0.05em;
167
+ pointer-events: none;
168
+ }
169
+
170
+ .image-compare__label--before {
171
+ inset-block-end: 1rem;
172
+ inset-inline-start: 1rem;
173
+ }
174
+ .image-compare__label--after {
175
+ inset-block-end: 1rem;
176
+ inset-inline-end: 1rem;
177
+ }
178
+
179
+ &.image-compare--vertical {
180
+ touch-action: pan-x;
181
+
182
+ .image-compare__before {
183
+ clip-path: inset(0 0 calc(100% - var(--_compare-position)) 0);
184
+ }
185
+
186
+ .image-compare__handle {
187
+ inset-block-start: var(--_compare-position);
188
+ inset-inline: 0;
189
+ inset-block-end: auto;
190
+ translate: 0 -50%;
191
+ flex-direction: row;
192
+ cursor: ns-resize;
193
+ }
194
+
195
+ .image-compare__handle::before {
196
+ inset-inline: 0;
197
+ inset-block: auto;
198
+ inline-size: 100%;
199
+ block-size: 2px;
200
+ translate: 0 -50%;
201
+ }
202
+
203
+ .image-compare__grip::before {
204
+ border-block-end-color: currentColor;
205
+ border-inline-end-color: transparent;
206
+ }
207
+ .image-compare__grip::after {
208
+ border-block-start-color: currentColor;
209
+ border-inline-start-color: transparent;
210
+ }
211
+ }
212
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Stack — pattern partial migrated from old-css-lib.
3
+ * Consumes the generated token cascade (src/css/generated/tokens.css).
4
+ */
5
+
6
+ /* ── Stack — scroll-driven stacking cards (view-timeline) ──────────────────── */
7
+ .stack {
8
+ --stack-count: 4;
9
+ --stack-card-height: 60vh;
10
+ display: grid;
11
+ }
12
+
13
+ .stack__card {
14
+ --stack-index: 1;
15
+ position: sticky;
16
+ top: var(--stack-top, 10vh);
17
+ }
18
+
19
+ .stack__card__content {
20
+ box-shadow: var(--ds-card, var(--ds-card-group, var(--ds-default)));
21
+ border-radius: var(--br-card, var(--br-card-group, var(--br-default)));
22
+ min-block-size: var(--stack-card-height);
23
+ }
24
+
25
+ @supports (animation-timeline: view()) {
26
+ .stack__card {
27
+ --_index0: calc(var(--stack-index) - 1);
28
+ --_reverse-index: calc(var(--stack-count) - var(--_index0));
29
+ --_reverse-index0: calc(var(--_reverse-index) - 1);
30
+
31
+ view-timeline: --card block;
32
+ }
33
+
34
+ @keyframes stack-scale {
35
+ to {
36
+ transform: scale(calc(1.1 - calc(0.1 * var(--_reverse-index))));
37
+ }
38
+ }
39
+
40
+ .stack__card__content {
41
+ animation: stack-scale linear forwards;
42
+ animation-timeline: --card;
43
+ animation-range: contain 0% contain 100%;
44
+ }
45
+
46
+ @keyframes stack-fade {
47
+ to {
48
+ opacity: calc(0.5 + 0.5 * (var(--_reverse-index) / var(--stack-count)));
49
+ }
50
+ }
51
+
52
+ .stack--fade .stack__card__content {
53
+ animation:
54
+ stack-scale linear forwards,
55
+ stack-fade linear forwards;
56
+ animation-timeline: --card, --card;
57
+ animation-range:
58
+ contain 0% contain 100%,
59
+ contain 0% contain 100%;
60
+ }
61
+ }
62
+
63
+ @media (prefers-reduced-motion: reduce) {
64
+ .stack__card__content {
65
+ animation: none !important;
66
+ }
67
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Sticky — pattern partial migrated from old-css-lib.
3
+ * Consumes the generated token cascade (src/css/generated/tokens.css).
4
+ */
5
+
6
+ /* ── Sticky — position:sticky variants + scroll-state() stuck detection ────── */
7
+ .sticky {
8
+ --_sticky-offset: var(--sticky-offset, 0);
9
+
10
+ position: sticky;
11
+ inset-block-start: var(--_sticky-offset);
12
+ z-index: var(--z-tier-sticky);
13
+
14
+ &.sticky--bottom {
15
+ inset-block-start: auto;
16
+ inset-block-end: var(--_sticky-offset);
17
+ }
18
+
19
+ &.sticky--inline-start {
20
+ inset-inline-start: var(--_sticky-offset);
21
+ inset-block-start: auto;
22
+ }
23
+
24
+ &.sticky--inline-end {
25
+ inset-inline-end: var(--_sticky-offset);
26
+ inset-inline-start: auto;
27
+ inset-block-start: auto;
28
+ }
29
+ }
30
+
31
+ .sticky-header {
32
+ --_sticky-offset: var(--sticky-header-offset, 0);
33
+
34
+ position: sticky;
35
+ inset-block-start: var(--_sticky-offset);
36
+ z-index: var(--z-tier-sticky);
37
+ container-type: scroll-state;
38
+
39
+ .sticky-header__stuck-only {
40
+ display: none;
41
+ }
42
+
43
+ @container scroll-state(stuck: top) {
44
+ .sticky-header__logo {
45
+ scale: 0.85;
46
+ }
47
+ .sticky-header__stuck-only {
48
+ display: block;
49
+ }
50
+ .sticky-header__unstuck-only {
51
+ display: none;
52
+ }
53
+ }
54
+ }
55
+
56
+ .sticky-sidebar {
57
+ --_sticky-offset: var(--sticky-sidebar-offset, 1rem);
58
+ --_sticky-max-height: var(--sticky-sidebar-max-height, calc(100vh - 2rem));
59
+
60
+ position: sticky;
61
+ inset-block-start: var(--_sticky-offset);
62
+ max-block-size: var(--_sticky-max-height);
63
+ overflow-y: auto;
64
+ align-self: flex-start;
65
+ }
66
+
67
+ table.sticky-table {
68
+ position: relative;
69
+
70
+ thead {
71
+ position: sticky;
72
+ inset-block-start: 0;
73
+ z-index: 10;
74
+ }
75
+
76
+ thead th {
77
+ background: inherit;
78
+ }
79
+
80
+ &.sticky-table--first-col th:first-child,
81
+ &.sticky-table--first-col td:first-child {
82
+ position: sticky;
83
+ inset-inline-start: 0;
84
+ z-index: 5;
85
+ }
86
+
87
+ &.sticky-table--first-col thead th:first-child {
88
+ z-index: 15;
89
+ }
90
+ }
91
+
92
+ .sticky-footer {
93
+ --_sticky-offset: var(--sticky-footer-offset, 0);
94
+
95
+ position: sticky;
96
+ inset-block-end: var(--_sticky-offset);
97
+ z-index: var(--z-tier-sticky);
98
+ container-type: scroll-state;
99
+ }
100
+
101
+ .sticky-nav {
102
+ position: sticky;
103
+ inset-block-start: var(--sticky-nav-offset, 0);
104
+ z-index: var(--z-tier-sticky);
105
+
106
+ .sticky-nav__item {
107
+ container-type: scroll-state;
108
+ }
109
+
110
+ .sticky-nav__indicator {
111
+ opacity: 0;
112
+ scale: 0.8;
113
+ transition:
114
+ opacity 0.2s ease,
115
+ scale 0.2s ease;
116
+ }
117
+
118
+ @container scroll-state(snapped: block) {
119
+ .sticky-nav__link {
120
+ font-weight: 600;
121
+ }
122
+ .sticky-nav__indicator {
123
+ opacity: 1;
124
+ scale: 1;
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Subgrid — pattern partial migrated from old-css-lib.
3
+ * Consumes the generated token cascade (src/css/generated/tokens.css).
4
+ */
5
+
6
+ /* ── Subgrid — content-aligned cards/tables via CSS subgrid ────────────────── */
7
+ .subgrid {
8
+ --_items-per-row: var(--items-per-row, 3);
9
+ --_rows-per-item: var(--rows-per-item, 2);
10
+ --_subgrid-gap: var(--subgrid-gap, 1.5rem);
11
+
12
+ display: grid;
13
+ grid-template-columns: repeat(var(--_items-per-row), 1fr);
14
+ gap: var(--_subgrid-gap);
15
+
16
+ > * {
17
+ grid-row: span var(--_rows-per-item);
18
+ display: grid;
19
+ grid-template-rows: subgrid;
20
+ }
21
+
22
+ &.subgrid-cols-1 {
23
+ --_items-per-row: 1;
24
+ }
25
+ &.subgrid-cols-2 {
26
+ --_items-per-row: 2;
27
+ }
28
+ &.subgrid-cols-3 {
29
+ --_items-per-row: 3;
30
+ }
31
+ &.subgrid-cols-4 {
32
+ --_items-per-row: 4;
33
+ }
34
+
35
+ &.subgrid-rows-2 {
36
+ --_rows-per-item: 2;
37
+ }
38
+ &.subgrid-rows-3 {
39
+ --_rows-per-item: 3;
40
+ }
41
+ &.subgrid-rows-4 {
42
+ --_rows-per-item: 4;
43
+ }
44
+
45
+ &.subgrid-responsive {
46
+ @media (width < 60rem) {
47
+ --_items-per-row: min(var(--items-per-row, 3), 2);
48
+ }
49
+ @media (width < 40rem) {
50
+ --_items-per-row: 1;
51
+ }
52
+ }
53
+ }
54
+
55
+ /* Subgrid card — internal rows align across siblings */
56
+ .subgrid-card {
57
+ --_card-rows: var(--subgrid-card-rows, 4);
58
+ --_card-padding: var(--subgrid-card-padding, 1.5rem);
59
+
60
+ display: grid;
61
+ grid-template-rows: subgrid;
62
+ grid-row: span var(--_card-rows);
63
+ padding: var(--_card-padding);
64
+ border: var(--b-card, var(--b-card-group, var(--b-default)));
65
+ border-radius: var(--br-card, var(--br-card-group, var(--br-default)));
66
+
67
+ .subgrid-card__media {
68
+ margin-inline: calc(-1 * var(--_card-padding));
69
+
70
+ > img {
71
+ inline-size: 100%;
72
+ block-size: 100%;
73
+ object-fit: cover;
74
+ }
75
+ }
76
+
77
+ .subgrid-card__footer {
78
+ align-self: end;
79
+ }
80
+ }
81
+
82
+ /* Pricing table with aligned feature rows */
83
+ .pricing-grid {
84
+ display: grid;
85
+ grid-template-columns: repeat(var(--pricing-columns, 3), 1fr);
86
+ }
87
+
88
+ .pricing-card {
89
+ --_pricing-rows: var(--pricing-card-rows, auto);
90
+
91
+ display: grid;
92
+ grid-template-rows: subgrid;
93
+ grid-row: span var(--_pricing-rows);
94
+ gap: 0;
95
+ border: var(--b-card, var(--b-card-group, var(--b-default)));
96
+ border-radius: var(--br-card, var(--br-card-group, var(--br-default)));
97
+ overflow: hidden;
98
+
99
+ .pricing-card__header {
100
+ padding: var(--pricing-header-padding, 1.5rem);
101
+ text-align: center;
102
+ }
103
+
104
+ .pricing-card__price {
105
+ padding: var(--pricing-price-padding, 1rem 1.5rem);
106
+ text-align: center;
107
+ font-size: var(--pricing-price-size, 2.5rem);
108
+ font-weight: 700;
109
+ }
110
+
111
+ .pricing-card__features {
112
+ padding: var(--pricing-features-padding, 1.5rem);
113
+ list-style: none;
114
+ margin: 0;
115
+ }
116
+
117
+ .pricing-card__feature {
118
+ padding-block: 0.5rem;
119
+ border-block-end: var(--b-card, var(--b-card-group, var(--b-default)));
120
+
121
+ &:last-child {
122
+ border-block-end: none;
123
+ }
124
+ }
125
+
126
+ .pricing-card__cta {
127
+ padding: var(--pricing-cta-padding, 1.5rem);
128
+ text-align: center;
129
+ align-self: end;
130
+ }
131
+
132
+ &.pricing-card--featured {
133
+ scale: 1.02;
134
+ z-index: var(--z-tier-raised);
135
+ }
136
+ }
137
+
138
+ /* Comparison table with subgrid columns */
139
+ .comparison-table {
140
+ --_comparison-columns: var(--comparison-columns, 4);
141
+
142
+ display: grid;
143
+ grid-template-columns:
144
+ minmax(150px, 1fr)
145
+ repeat(calc(var(--_comparison-columns) - 1), minmax(100px, 1fr));
146
+ border: var(--b-card, var(--b-card-group, var(--b-default)));
147
+ border-radius: var(--br-card, var(--br-card-group, var(--br-default)));
148
+ overflow: hidden;
149
+
150
+ .comparison-table__header,
151
+ .comparison-table__row {
152
+ display: contents;
153
+ }
154
+
155
+ .comparison-table__header > * {
156
+ padding: var(--comparison-header-padding, 1rem);
157
+ font-weight: 600;
158
+ text-align: center;
159
+ border-block-end: var(--b-card, var(--b-card-group, var(--b-default)));
160
+ }
161
+
162
+ .comparison-table__row > * {
163
+ padding: var(--comparison-cell-padding, 1rem);
164
+ border-block-end: var(--b-card, var(--b-card-group, var(--b-default)));
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ }
169
+
170
+ .comparison-table__row > *:first-child {
171
+ justify-content: flex-start;
172
+ font-weight: 500;
173
+ }
174
+
175
+ .comparison-table__row:last-child > * {
176
+ border-block-end: none;
177
+ }
178
+ }