emdash-plugin-avdeb 0.1.0 → 0.1.1

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/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.0 — unreleased
3
+ ## 0.1.1 — 2026-10-03
4
+
5
+ - Fix: product photos were cropped and cards restyled when an embed sat inside a post body whose theme
6
+ styles bare elements (e.g. `.article-content img { margin: 1.75em 0 }`, global `img { height: auto }`,
7
+ `.article-content a { text-decoration: underline }`, `article h3 { font-size }`). Layout-critical
8
+ resets now use real class specificity; the rest stays `:where()`-wrapped. New tokens
9
+ `--avdeb-title-size`, `--avdeb-title-leading`, `--avdeb-heading-size`, `--avdeb-items-margin`,
10
+ `--avdeb-items-pad`, `--avdeb-link-deco`, `--avdeb-btn-bg`, `--avdeb-btn-color`. The embed root gets
11
+ `not-prose` (Tailwind Typography).
12
+
13
+ ## 0.1.0 — 2026-10-03
4
14
 
5
15
  - First release: AVDEB Products / AVDEB Product / AVDEB Button Portable Text blocks; grid, carousel, list
6
16
  and spotlight layouts; horizontal, hero and compact single-product styles; template components
package/README.md CHANGED
@@ -4,7 +4,7 @@ Embed [AVDEB](https://avdeb.com/developers/#emdash) products in an [EmDash](http
4
4
 
5
5
  - **Three editor blocks** — type `/` in any rich-text field: **AVDEB Products**, **AVDEB Product**, **AVDEB Button**. Paste a creator, category or product link and the source is detected automatically.
6
6
  - **Four layouts** — grid, carousel (scroll-snap, keyboard + arrow buttons), list ("shop the post") and spotlight (first product featured). Single products as compact card, horizontal card or hero, with your own badge and note.
7
- - **Looks native on any theme** — container queries (embeds adapt to the column they sit in, not the viewport), inherit / light / dark / system themes, three card styles, accent colour, corner radius, image shape. Every selector is `:where()`-wrapped, so your CSS always wins.
7
+ - **Looks native on any theme** — container queries (embeds adapt to the column they sit in, not the viewport), inherit / light / dark / system themes, three card styles, accent colour, corner radius, image shape. Styling selectors are `:where()`-wrapped, so your CSS always wins; a small layout guard keeps post-body styles (`.prose img`, `.entry-content a`, `article h3`) from cropping images or restyling the cards.
8
8
  - **Fast and resilient** — products are fetched server-side, cached in plugin KV per query, and the last good copy is served for a week if AVDEB is unreachable. Identical embeds on one page share a single lookup.
9
9
  - **Honest links** — referral links get `rel="sponsored"`; an optional disclosure line appears under embeds that carry a code.
10
10
  - **Private by default** — no third-party scripts, no cookies, no iframes, no tracking. The only client JS is ~40 lines for carousel arrows.
@@ -119,7 +119,9 @@ Everything is a CSS custom property on `.avdeb` (embeds) or `.avdeb-cta` (button
119
119
  .avdeb[data-theme="dark"] { --avdeb-card-bg: #111; }
120
120
  ```
121
121
 
122
- Also available: `--avdeb-surface`, `--avdeb-border-soft`, `--avdeb-media-bg`, `--avdeb-muted`, `--avdeb-badge-bg`, `--avdeb-badge-text`, `--avdeb-shadow-hover`, `--avdeb-pad`, `--avdeb-ratio`. BEM classes (`.avdeb-card__title`, `.avdeb-badge--sale`, …) are stable.
122
+ Also available: `--avdeb-surface`, `--avdeb-border-soft`, `--avdeb-media-bg`, `--avdeb-muted`, `--avdeb-badge-bg`, `--avdeb-badge-text`, `--avdeb-shadow-hover`, `--avdeb-pad`, `--avdeb-ratio`, `--avdeb-title-size`, `--avdeb-title-leading`, `--avdeb-heading-size`, `--avdeb-items-margin`, `--avdeb-items-pad`, `--avdeb-link-deco`, and on buttons `--avdeb-btn-bg` / `--avdeb-btn-color`. BEM classes (`.avdeb-card__title`, `.avdeb-badge--sale`, …) are stable.
123
+
124
+ Embeds sit inside your post body, where themes often style bare elements (`.prose img { margin }`, `.entry-content a { text-decoration: underline }`). Layout-critical properties — image sizing/margins/borders, title and heading size and margins, link colour/underline, list indentation — are therefore guarded with real class specificity (`.avdeb .avdeb-card …`, 0,3,x) so those rules can't crop photos or restyle cards. Change them through the custom properties above, or with a more specific selector. The embed root also carries `not-prose`, so Tailwind Typography skips it.
123
125
 
124
126
  ## How it works
125
127
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emdash-plugin-avdeb",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Embed AVDEB products in EmDash CMS — grid, carousel, list and spotlight blocks with your affiliate or creator referral link",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -6,126 +6,149 @@ import type { ContextData } from "../payload.ts";
6
6
  import { relFor } from "../view.ts";
7
7
 
8
8
  interface Props {
9
- context: ContextData | null;
10
- href: string;
11
- label: string;
12
- variant?: ButtonVariant;
13
- align?: Alignment;
14
- class?: string;
9
+ context: ContextData | null;
10
+ href: string;
11
+ label: string;
12
+ variant?: ButtonVariant;
13
+ align?: Alignment;
14
+ class?: string;
15
15
  }
16
16
 
17
- const { context, href, label, variant = "solid", align = "start", class: className } = Astro.props;
17
+ const {
18
+ context,
19
+ href,
20
+ label,
21
+ variant = "solid",
22
+ align = "start",
23
+ class: className,
24
+ } = Astro.props;
18
25
  const url = avdebLink(href, context?.ref ?? "");
19
26
  const accent = context?.display.accentColor;
20
27
  const newTab = context?.display.newTab ?? false;
21
28
  ---
22
29
 
23
- <p class:list={["avdeb-cta", `avdeb-cta--${align}`, className]} style={accent ? `--avdeb-accent:${accent}` : undefined}>
24
- {
25
- url ? (
26
- <a class:list={["avdeb-btn", `avdeb-btn--${variant}`]} href={url} rel={relFor(url)} target={newTab ? "_blank" : undefined}>
27
- <span>{label}</span>
28
- <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M3 8h9.5M8.5 4 12.5 8l-4 4" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" /></svg>
29
- </a>
30
- ) : (
31
- <span>{label}</span>
32
- )
33
- }
30
+ <p
31
+ class:list={["avdeb-cta", `avdeb-cta--${align}`, className]}
32
+ style={accent ? `--avdeb-accent:${accent}` : undefined}
33
+ >
34
+ {url ? (
35
+ <a
36
+ class:list={["avdeb-btn", `avdeb-btn--${variant}`]}
37
+ href={url}
38
+ rel={relFor(url)}
39
+ target={newTab ? "_blank" : undefined}
40
+ >
41
+ <span>{label}</span>
42
+ <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
43
+ <path
44
+ d="M3 8h9.5M8.5 4 12.5 8l-4 4"
45
+ fill="none"
46
+ stroke="currentColor"
47
+ stroke-width="1.6"
48
+ stroke-linecap="round"
49
+ stroke-linejoin="round"
50
+ />
51
+ </svg>
52
+ </a>
53
+ ) : (
54
+ <span>{label}</span>
55
+ )}
34
56
  </p>
35
57
 
36
58
  <style is:global>
37
- :where(.avdeb-cta) {
38
- --avdeb-accent: #3b6548;
39
- --avdeb-accent-contrast: #fff;
40
- display: flex;
41
- margin-block: 1.75em;
42
- }
43
-
44
- :where(.avdeb-cta--center) {
45
- justify-content: center;
46
- }
47
-
48
- :where(.avdeb-cta--end) {
49
- justify-content: flex-end;
50
- }
51
-
52
- :where(.avdeb-btn) {
53
- display: inline-flex;
54
- align-items: center;
55
- gap: 0.55em;
56
- padding: 0.85em 1.4em;
57
- border: 1.5px solid var(--avdeb-accent);
58
- border-radius: 999px;
59
- font: inherit;
60
- font-weight: 600;
61
- line-height: 1.1;
62
- text-decoration: none;
63
- transition:
64
- transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1),
65
- box-shadow 0.2s,
66
- background-color 0.2s,
67
- color 0.2s;
68
- }
69
-
70
- :where(.avdeb-btn svg) {
71
- flex: none;
72
- transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
73
- }
74
-
75
- :where(.avdeb-btn:hover) :where(svg) {
76
- transform: translateX(3px);
77
- }
78
-
79
- :where(.avdeb-btn:dir(rtl)) :where(svg) {
80
- scale: -1 1;
81
- }
82
-
83
- :where(.avdeb-btn:focus-visible) {
84
- outline: 2px solid var(--avdeb-accent);
85
- outline-offset: 3px;
86
- }
87
-
88
- :where(.avdeb-btn--solid) {
89
- background: var(--avdeb-accent);
90
- color: var(--avdeb-accent-contrast);
91
- box-shadow: 0 10px 24px -12px var(--avdeb-accent);
92
- }
93
-
94
- :where(.avdeb-btn--solid:hover) {
95
- transform: translateY(-1px);
96
- box-shadow: 0 14px 30px -12px var(--avdeb-accent);
97
- }
98
-
99
- :where(.avdeb-btn--outline) {
100
- background: transparent;
101
- color: var(--avdeb-accent);
102
- }
103
-
104
- :where(.avdeb-btn--outline:hover) {
105
- background: var(--avdeb-accent);
106
- color: var(--avdeb-accent-contrast);
107
- }
108
-
109
- :where(.avdeb-btn--link) {
110
- padding: 0;
111
- border: 0;
112
- border-radius: 0;
113
- background: none;
114
- color: var(--avdeb-accent);
115
- }
116
-
117
- :where(.avdeb-btn--link:hover) {
118
- text-decoration: underline;
119
- text-underline-offset: 0.2em;
120
- }
121
-
122
- @media (prefers-reduced-motion: reduce) {
123
- :where(.avdeb-btn, .avdeb-btn svg) {
124
- transition: none;
125
- }
126
-
127
- :where(.avdeb-btn:hover, .avdeb-btn:hover svg) {
128
- transform: none;
129
- }
130
- }
59
+ :where(.avdeb-cta) {
60
+ --avdeb-accent: #3b6548;
61
+ --avdeb-accent-contrast: #fff;
62
+ display: flex;
63
+ margin-block: 1.75em;
64
+ }
65
+
66
+ :where(.avdeb-cta--center) {
67
+ justify-content: center;
68
+ }
69
+
70
+ :where(.avdeb-cta--end) {
71
+ justify-content: flex-end;
72
+ }
73
+
74
+ :where(.avdeb-btn) {
75
+ display: inline-flex;
76
+ align-items: center;
77
+ gap: 0.55em;
78
+ padding: 0.85em 1.4em;
79
+ border: 1.5px solid var(--avdeb-accent);
80
+ border-radius: 999px;
81
+ font: inherit;
82
+ line-height: 1.1;
83
+ transition:
84
+ transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1),
85
+ box-shadow 0.2s,
86
+ background-color 0.2s,
87
+ color 0.2s;
88
+ }
89
+
90
+ :where(.avdeb-btn svg) {
91
+ flex: none;
92
+ transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
93
+ }
94
+
95
+ :where(.avdeb-btn:hover) :where(svg) {
96
+ transform: translateX(3px);
97
+ }
98
+
99
+ :where(.avdeb-btn:dir(rtl)) :where(svg) {
100
+ scale: -1 1;
101
+ }
102
+
103
+ :where(.avdeb-btn:focus-visible) {
104
+ outline: 2px solid var(--avdeb-accent);
105
+ outline-offset: 3px;
106
+ }
107
+
108
+ :where(.avdeb-btn--solid) {
109
+ --avdeb-btn-bg: var(--avdeb-accent);
110
+ --avdeb-btn-color: var(--avdeb-accent-contrast);
111
+ box-shadow: 0 10px 24px -12px var(--avdeb-accent);
112
+ }
113
+
114
+ :where(.avdeb-btn--solid:hover) {
115
+ transform: translateY(-1px);
116
+ box-shadow: 0 14px 30px -12px var(--avdeb-accent);
117
+ }
118
+
119
+ :where(.avdeb-btn--outline:hover) {
120
+ --avdeb-btn-bg: var(--avdeb-accent);
121
+ --avdeb-btn-color: var(--avdeb-accent-contrast);
122
+ }
123
+
124
+ :where(.avdeb-btn--link) {
125
+ padding: 0;
126
+ border: 0;
127
+ border-radius: 0;
128
+ }
129
+
130
+ :where(.avdeb-btn--link:hover) {
131
+ --avdeb-link-deco: underline;
132
+ text-underline-offset: 0.2em;
133
+ }
134
+
135
+ /* Guard: post-body styles like `.entry-content a { color; text-decoration: underline }` would
136
+ otherwise recolour and underline the button. Real specificity (0,3,0); restyle via the
137
+ --avdeb-btn-bg / --avdeb-btn-color / --avdeb-accent custom properties. */
138
+ .avdeb-cta > .avdeb-btn[href] {
139
+ background: var(--avdeb-btn-bg, transparent);
140
+ color: var(--avdeb-btn-color, var(--avdeb-accent));
141
+ font-weight: 600;
142
+ text-decoration-line: var(--avdeb-link-deco, none);
143
+ }
144
+
145
+ @media (prefers-reduced-motion: reduce) {
146
+ :where(.avdeb-btn, .avdeb-btn svg) {
147
+ transition: none;
148
+ }
149
+
150
+ :where(.avdeb-btn:hover, .avdeb-btn:hover svg) {
151
+ transform: none;
152
+ }
153
+ }
131
154
  </style>
@@ -72,6 +72,7 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
72
72
  <section
73
73
  class:list={[
74
74
  "avdeb",
75
+ "not-prose",
75
76
  `avdeb--${layout}`,
76
77
  single && `avdeb--${single.variant}`,
77
78
  `avdeb--${display.cardStyle}`,
@@ -420,6 +421,11 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
420
421
  --avdeb-cols: 3;
421
422
  --avdeb-radius: 16px;
422
423
  --avdeb-ratio: 1 / 1;
424
+ --avdeb-heading-size: clamp(1.15rem, 1rem + 0.7vw, 1.55rem);
425
+ --avdeb-title-size: 1rem;
426
+ --avdeb-title-leading: 1.35;
427
+ --avdeb-items-margin: 0;
428
+ --avdeb-items-pad: 0;
423
429
 
424
430
  container: avdeb / inline-size;
425
431
  margin-block: 2em;
@@ -550,15 +556,11 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
550
556
  }
551
557
 
552
558
  :where(.avdeb__heading) {
553
- margin: 0;
554
559
  font-family: var(--avdeb-font-title);
555
- font-size: clamp(1.15rem, 1rem + 0.7vw, 1.55rem);
556
- line-height: 1.2;
557
560
  letter-spacing: -0.01em;
558
561
  }
559
562
 
560
563
  :where(.avdeb__intro) {
561
- margin: 0.4rem 0 0;
562
564
  max-inline-size: 62ch;
563
565
  color: var(--avdeb-muted, currentColor);
564
566
  opacity: var(--avdeb-muted-opacity);
@@ -576,16 +578,13 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
576
578
  display: inline-flex;
577
579
  align-items: center;
578
580
  gap: 0.3em;
579
- color: var(--avdeb-accent-text);
580
581
  font-size: 0.95em;
581
- font-weight: 600;
582
- text-decoration: none;
583
582
  white-space: nowrap;
583
+ text-underline-offset: 0.2em;
584
584
  }
585
585
 
586
586
  :where(.avdeb__all:hover) {
587
- text-decoration: underline;
588
- text-underline-offset: 0.2em;
587
+ --avdeb-link-deco: underline;
589
588
  }
590
589
 
591
590
  :where(.avdeb__all svg, .avdeb-card__cta svg, .avdeb-btn svg) {
@@ -648,17 +647,12 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
648
647
  display: grid;
649
648
  grid-template-columns: repeat(var(--avdeb-cols), minmax(0, 1fr));
650
649
  gap: var(--avdeb-gap);
651
- margin: 0;
652
- padding: 0;
653
- list-style: none;
654
650
  }
655
651
 
656
652
  :where(.avdeb__item) {
657
653
  container: avdeb-item / inline-size;
658
654
  display: flex;
659
655
  min-inline-size: 0;
660
- margin: 0;
661
- padding: 0;
662
656
  }
663
657
 
664
658
  @container avdeb (max-width: 46rem) {
@@ -708,8 +702,8 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
708
702
  overscroll-behavior-x: contain;
709
703
  scroll-snap-type: x mandatory;
710
704
  scrollbar-width: none;
711
- padding: 0.35rem 0.35rem 1.25rem;
712
- margin: -0.35rem -0.35rem -1.25rem;
705
+ --avdeb-items-pad: 0.35rem 0.35rem 1.25rem;
706
+ --avdeb-items-margin: -0.35rem -0.35rem -1.25rem;
713
707
  scroll-padding-inline: 0.35rem;
714
708
  }
715
709
 
@@ -802,7 +796,7 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
802
796
  :where(.avdeb--minimal)
803
797
  :where(.avdeb-card:hover)
804
798
  :where(.avdeb-card__link) {
805
- text-decoration: underline;
799
+ --avdeb-link-deco: underline;
806
800
  text-underline-offset: 0.2em;
807
801
  }
808
802
 
@@ -832,10 +826,6 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
832
826
  }
833
827
 
834
828
  :where(.avdeb-card__media img) {
835
- display: block;
836
- inline-size: 100%;
837
- block-size: 100%;
838
- object-fit: cover;
839
829
  transition: transform 0.7s var(--avdeb-ease);
840
830
  }
841
831
 
@@ -896,7 +886,6 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
896
886
  }
897
887
 
898
888
  :where(.avdeb-card__by) {
899
- margin: 0;
900
889
  color: var(--avdeb-muted, currentColor);
901
890
  opacity: var(--avdeb-muted-opacity);
902
891
  font-size: 0.8rem;
@@ -905,20 +894,15 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
905
894
 
906
895
  :where(.avdeb-card__title) {
907
896
  display: -webkit-box;
908
- margin: 0;
909
897
  overflow: hidden;
910
898
  font-family: var(--avdeb-font-title);
911
- font-size: 1rem;
912
899
  font-weight: 600;
913
- line-height: 1.35;
914
900
  -webkit-box-orient: vertical;
915
901
  -webkit-line-clamp: 2;
916
902
  line-clamp: 2;
917
903
  }
918
904
 
919
905
  :where(.avdeb-card__link) {
920
- color: inherit;
921
- text-decoration: none;
922
906
  outline: none;
923
907
  }
924
908
 
@@ -937,7 +921,6 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
937
921
  }
938
922
 
939
923
  :where(.avdeb-card__note) {
940
- margin: 0.4rem 0 0;
941
924
  padding-inline-start: 0.85rem;
942
925
  border-inline-start: 3px solid var(--avdeb-accent);
943
926
  font-size: 0.95rem;
@@ -958,7 +941,6 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
958
941
  display: flex;
959
942
  align-items: baseline;
960
943
  gap: 0.45em;
961
- margin: 0;
962
944
  font-size: 1.02rem;
963
945
  font-weight: 700;
964
946
  font-variant-numeric: tabular-nums;
@@ -1065,8 +1047,8 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
1065
1047
  }
1066
1048
 
1067
1049
  :where(.avdeb-card--featured) :where(.avdeb-card__title) {
1068
- font-size: clamp(1.15rem, 0.9rem + 1.6cqi, 1.6rem);
1069
- line-height: 1.25;
1050
+ --avdeb-title-size: clamp(1.15rem, 0.9rem + 1.6cqi, 1.6rem);
1051
+ --avdeb-title-leading: 1.25;
1070
1052
  -webkit-line-clamp: 3;
1071
1053
  line-clamp: 3;
1072
1054
  }
@@ -1111,7 +1093,7 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
1111
1093
  }
1112
1094
 
1113
1095
  :where(.avdeb-card--hero) :where(.avdeb-card__title) {
1114
- font-size: clamp(1.35rem, 1rem + 2.4cqi, 2.15rem);
1096
+ --avdeb-title-size: clamp(1.35rem, 1rem + 2.4cqi, 2.15rem);
1115
1097
  letter-spacing: -0.015em;
1116
1098
  -webkit-line-clamp: 4;
1117
1099
  line-clamp: 4;
@@ -1156,7 +1138,6 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
1156
1138
  display: flex;
1157
1139
  align-items: center;
1158
1140
  gap: 0.45em;
1159
- margin: 1.1rem 0 0;
1160
1141
  color: var(--avdeb-muted, currentColor);
1161
1142
  opacity: var(--avdeb-muted-opacity);
1162
1143
  font-size: 0.78rem;
@@ -1167,6 +1148,93 @@ const hasHeader = Boolean(heading || intro || allHref || isCarousel);
1167
1148
  flex: none;
1168
1149
  }
1169
1150
 
1151
+ /* ── Guard against article / prose styles ───────────────────────────────── */
1152
+ /* Embeds live inside post bodies, whose themes style bare elements (`.prose img { margin }`,
1153
+ `.entry-content a { text-decoration: underline }`, `article h3 { font-size }`, global
1154
+ `img { height: auto }`). Those beat the zero-specificity :where() rules above and break the
1155
+ cards: cropped photos, huge underlined titles, indented grids. So these layout-critical resets
1156
+ use real class specificity (0,3,x). Restyle them with the --avdeb-* properties (title/heading
1157
+ size, items margin/padding, link decoration) or a selector of higher specificity. */
1158
+ .avdeb .avdeb__items[role="list"] {
1159
+ margin: var(--avdeb-items-margin);
1160
+ padding: var(--avdeb-items-pad);
1161
+ list-style: none;
1162
+ }
1163
+
1164
+ .avdeb .avdeb__items .avdeb__item {
1165
+ margin: 0;
1166
+ padding: 0;
1167
+ list-style: none;
1168
+ }
1169
+
1170
+ .avdeb .avdeb__items .avdeb__item::marker {
1171
+ content: none;
1172
+ }
1173
+
1174
+ .avdeb .avdeb-card .avdeb-card__media img {
1175
+ display: block;
1176
+ inline-size: 100%;
1177
+ max-inline-size: none;
1178
+ block-size: 100%;
1179
+ max-block-size: none;
1180
+ margin: 0;
1181
+ padding: 0;
1182
+ border: 0;
1183
+ border-radius: 0;
1184
+ box-shadow: none;
1185
+ object-fit: cover;
1186
+ }
1187
+
1188
+ .avdeb .avdeb__header .avdeb__heading {
1189
+ margin: 0;
1190
+ padding: 0;
1191
+ border: 0;
1192
+ color: inherit;
1193
+ font-size: var(--avdeb-heading-size);
1194
+ line-height: 1.2;
1195
+ }
1196
+
1197
+ .avdeb .avdeb-card .avdeb-card__title {
1198
+ margin: 0;
1199
+ padding: 0;
1200
+ border: 0;
1201
+ color: inherit;
1202
+ font-size: var(--avdeb-title-size);
1203
+ line-height: var(--avdeb-title-leading);
1204
+ }
1205
+
1206
+ .avdeb .avdeb-card .avdeb-card__link,
1207
+ .avdeb .avdeb__tools .avdeb__all {
1208
+ background: none;
1209
+ font-weight: inherit;
1210
+ text-decoration-line: var(--avdeb-link-deco, none);
1211
+ }
1212
+
1213
+ .avdeb .avdeb-card .avdeb-card__link {
1214
+ color: inherit;
1215
+ }
1216
+
1217
+ .avdeb .avdeb__tools .avdeb__all {
1218
+ color: var(--avdeb-accent-text);
1219
+ font-weight: 600;
1220
+ }
1221
+
1222
+ .avdeb .avdeb-card :is(.avdeb-card__by, .avdeb-card__price) {
1223
+ margin: 0;
1224
+ }
1225
+
1226
+ .avdeb .avdeb-card .avdeb-card__note {
1227
+ margin: 0.4rem 0 0;
1228
+ }
1229
+
1230
+ .avdeb .avdeb__header .avdeb__intro {
1231
+ margin: 0.4rem 0 0;
1232
+ }
1233
+
1234
+ .avdeb > .avdeb__disclosure.avdeb__disclosure {
1235
+ margin: 1.1rem 0 0;
1236
+ }
1237
+
1170
1238
  /* ── Motion & print ─────────────────────────────────────────────────────── */
1171
1239
  @media (prefers-reduced-motion: reduce) {
1172
1240
  :where(.avdeb) :where(*) {
package/src/constants.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /** Shared identifiers and limits. Pure module: no EmDash or Astro imports. */
2
2
 
3
3
  export const PLUGIN_ID = "avdeb-products";
4
- export const VERSION = "0.1.0";
4
+ export const VERSION = "0.1.1";
5
5
 
6
6
  export const API_HOST = "api.avdeb.com";
7
7
  export const API_BASE = `https://${API_HOST}/v1/catalog`;