@repobit/dex-system-design 0.24.17 → 0.24.19

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 (26) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +4 -4
  3. package/src/components/ai-guardian-demo.stories.js +454 -33
  4. package/src/components/bento-grid/bento-grid.css.js +12 -1
  5. package/src/components/bento-grid/bento-grid.js +59 -1
  6. package/src/components/bento-grid/bento-grid.stories.js +45 -0
  7. package/src/components/comparison-panel/comparison-panel.css.js +52 -1
  8. package/src/components/comparison-panel/comparison-panel.js +6 -1
  9. package/src/components/compatibility-table/compatibility-table.css.js +29 -13
  10. package/src/components/compatibility-table/compatibility-table.js +13 -7
  11. package/src/components/cta-banner/cta-banner.css.js +11 -0
  12. package/src/components/cta-banner/cta-banner.js +7 -0
  13. package/src/components/footer/footer-lp.css.js +10 -21
  14. package/src/components/footer/footer-lp.js +3 -18
  15. package/src/components/footer/footer-nav-menu.css.js +0 -2
  16. package/src/components/footer/footer.css.js +18 -35
  17. package/src/components/footer/footer.js +5 -1
  18. package/src/components/header/header-code.css.js +208 -10
  19. package/src/components/header/header-code.js +148 -5
  20. package/src/components/header/header-code.stories.js +83 -27
  21. package/src/components/page-switcher/page-switcher.js +1 -1
  22. package/src/components/paragraph/paragraph.js +6 -0
  23. package/src/components/quick-answer/quick-answer.css.js +2 -0
  24. package/src/components/quick-answer/quick-answer.js +1 -1
  25. package/src/components/terminal/terminal-message.css.js +153 -13
  26. package/src/components/terminal/terminal-message.js +37 -11
@@ -29,6 +29,29 @@ function resolveBreakpoint(width, maxColumns, minCardWidth) {
29
29
  return { bp, columns, gap };
30
30
  }
31
31
 
32
+ // Same breakpoint logic as resolveBreakpoint, but allows more than 2
33
+ // columns (up to maxColumns) since the "equal" variant is a plain grid
34
+ // with no wide/narrow pairing to worry about.
35
+ function resolveEqualColumns(width, maxColumns, minCardWidth) {
36
+ const bp =
37
+ width >= BREAKPOINT_WIDTHS.xl
38
+ ? "xl" :
39
+ width >= BREAKPOINT_WIDTHS.lg
40
+ ? "lg" :
41
+ width >= BREAKPOINT_WIDTHS.md ? "md" : "sm";
42
+
43
+ let columns = bp === "sm" ? 1 : bp === "md" ? Math.min(2, maxColumns) : Math.max(1, maxColumns);
44
+ const gap = DEFAULT_GAP[bp];
45
+
46
+ while (columns > 1) {
47
+ const cardWidth = (width - gap * (columns - 1)) / columns;
48
+ if (cardWidth >= minCardWidth) break;
49
+ columns -= 1;
50
+ }
51
+
52
+ return { bp, columns, gap };
53
+ }
54
+
32
55
  class BentoGrid extends LitElement {
33
56
  static properties = {
34
57
  eyebrow : { type: String },
@@ -37,7 +60,20 @@ class BentoGrid extends LitElement {
37
60
  maxColumns : { type: Number, attribute: "max-columns" },
38
61
  minCardWidth: { type: Number, attribute: "min-card-width" },
39
62
  // Fixed wide/narrow ratio applied to every pair, e.g. 0.7 = 70/30.
63
+ // Only used when variant="weighted" (the default).
40
64
  wideShare : { type: Number, attribute: "wide-share" },
65
+ // "weighted" (default) — pairs of cards alternate wide/narrow, per
66
+ // _applyWeights below. "equal" — every card gets the same width, laid
67
+ // out in a plain N-column grid (see equalColumns) with no pairing.
68
+ variant : { type: String, reflect: true },
69
+ // Column count for variant="equal" at the widest breakpoint (xl/lg);
70
+ // narrows to min(2, this) at md, and 1 at sm, same responsive pattern
71
+ // as the weighted variant. Ignored when variant="weighted".
72
+ equalColumns: { type: Number, attribute: "equal-columns" },
73
+ // "none" (default, transparent) | "tint" (light blue wash behind the
74
+ // whole grid, including header text) — a section-level background, not
75
+ // per-card (bd-bento-item already has its own `tone="tint"` for that).
76
+ background : { type: String, reflect: true },
41
77
  _columns : { state: true },
42
78
  _gap : { state: true }
43
79
  };
@@ -52,6 +88,9 @@ class BentoGrid extends LitElement {
52
88
  this.maxColumns = 2;
53
89
  this.minCardWidth = 260;
54
90
  this.wideShare = 0.7;
91
+ this.variant = "weighted";
92
+ this.equalColumns = 3;
93
+ this.background = "none";
55
94
  this._columns = 2;
56
95
  this._gap = 24;
57
96
  this._resizeObserver = null;
@@ -124,13 +163,32 @@ class BentoGrid extends LitElement {
124
163
  }
125
164
  }
126
165
 
166
+ // Every item gets the same span (TOTAL_UNITS / columns) — no pairing, no
167
+ // "featured" full-width exception. Rounds if TOTAL_UNITS doesn't divide
168
+ // evenly by columns; for common column counts (1, 2, 3, 4, 6, 8, 12, 24)
169
+ // against TOTAL_UNITS=24 this is always exact.
170
+ _applyEqualSpans(columns) {
171
+ const span = Math.round(TOTAL_UNITS / Math.max(1, columns));
172
+ this._items.forEach((item) => item.style.setProperty("--bd-bento-span", String(span)));
173
+ }
174
+
127
175
  _relayout() {
128
176
  const width = this.clientWidth || 960;
177
+ this.style.setProperty("--bd-bento-total-units", String(TOTAL_UNITS));
178
+
179
+ if (this.variant === "equal") {
180
+ const { columns, gap } = resolveEqualColumns(width, this.equalColumns, this.minCardWidth);
181
+ this._columns = columns;
182
+ this._gap = gap;
183
+ this.style.setProperty("--bd-bento-gap", `${gap}px`);
184
+ this._applyEqualSpans(columns);
185
+ return;
186
+ }
187
+
129
188
  const { columns, gap } = resolveBreakpoint(width, this.maxColumns, this.minCardWidth);
130
189
  this._columns = columns;
131
190
  this._gap = gap;
132
191
  this.style.setProperty("--bd-bento-gap", `${gap}px`);
133
- this.style.setProperty("--bd-bento-total-units", String(TOTAL_UNITS));
134
192
 
135
193
  if (columns <= 1) {
136
194
  this._items.forEach((item) => item.style.setProperty("--bd-bento-span", String(TOTAL_UNITS)));
@@ -437,4 +437,49 @@ export const TwentySevenItems = {
437
437
  }
438
438
  }
439
439
  }
440
+ };
441
+ export const EqualColumns = {
442
+ name : "Equal Columns — Protection",
443
+ render: () => html`
444
+ <bd-bento-grid
445
+ variant="equal"
446
+ equal-columns="3"
447
+ eyebrow="Protection"
448
+ title="What does VPN for AI Agents protect against?"
449
+ description="Each protection is structural: every request the agent routes through Bitdefender's MCP tools gets it automatically, with no setting to remember."
450
+ >
451
+ <bd-bento-item>
452
+ <span slot="icon" style="color: var(--color-blue-500, #006DFF); font-weight: 700; font-family: var(--typography-fontFamily-mono, monospace); font-size: 14px; letter-spacing: 0.05em;">01</span>
453
+ <bd-h as="h5" font-weight="700" style="margin: 0 0 8px;">IP masking</bd-h>
454
+ <bd-p color="var(--color-neutral-600)">When your agent reaches a site, it sees the VPN server's exit IP. Not your home address or IP-based location.</bd-p>
455
+ </bd-bento-item>
456
+ <bd-bento-item>
457
+ <span slot="icon" style="color: var(--color-blue-500, #006DFF); font-weight: 700; font-family: var(--typography-fontFamily-mono, monospace); font-size: 14px; letter-spacing: 0.05em;">02</span>
458
+ <bd-h as="h5" font-weight="700" style="margin: 0 0 8px;">Per-prompt encryption</bd-h>
459
+ <bd-p color="var(--color-neutral-600)">Every request opens its own encrypted tunnel from your device to Bitdefender, so whoever runs the Wi-Fi you're on can't read what the agent sends.</bd-p>
460
+ </bd-bento-item>
461
+ <bd-bento-item>
462
+ <span slot="icon" style="color: var(--color-blue-500, #006DFF); font-weight: 700; font-family: var(--typography-fontFamily-mono, monospace); font-size: 14px; letter-spacing: 0.05em;">03</span>
463
+ <bd-h as="h5" font-weight="700" style="margin: 0 0 8px;">Session isolation</bd-h>
464
+ <bd-p color="var(--color-neutral-600)">Each tunnel closes the moment the prompt ends. If a site sees two of your agent's requests, it has no network-level way to tell they came from the same prompt.</bd-p>
465
+ </bd-bento-item>
466
+ <bd-bento-item>
467
+ <span slot="icon" style="color: var(--color-blue-500, #006DFF); font-weight: 700; font-family: var(--typography-fontFamily-mono, monospace); font-size: 14px; letter-spacing: 0.05em;">04</span>
468
+ <bd-h as="h5" font-weight="700" style="margin: 0 0 8px;">Clean-IP browsing</bd-h>
469
+ <bd-p color="var(--color-neutral-600)">Every request exits on the VPN server's IP rather than the same home address every time, useful for QA and monitoring work that needs a neutral, non-residential vantage point.</bd-p>
470
+ </bd-bento-item>
471
+ <bd-bento-item>
472
+ <span slot="icon" style="color: var(--color-blue-500, #006DFF); font-weight: 700; font-family: var(--typography-fontFamily-mono, monospace); font-size: 14px; letter-spacing: 0.05em;">05</span>
473
+ <bd-h as="h5" font-weight="700" style="margin: 0 0 8px;">Regional routing</bd-h>
474
+ <bd-p color="var(--color-neutral-600)">Need to see a page the way a visitor from a specific country would? Route that one request through a Bitdefender server there, just for that prompt.</bd-p>
475
+ </bd-bento-item>
476
+ </bd-bento-grid>
477
+ `,
478
+ parameters: {
479
+ docs: {
480
+ description: {
481
+ story: "`variant=\"equal\"` gives every card the same width in a plain N-column grid (`equal-columns`), with no wide/narrow pairing — unlike the default `\"weighted\"` variant."
482
+ }
483
+ }
484
+ }
440
485
  };
@@ -4,7 +4,50 @@ export default css`
4
4
  :host {
5
5
  display: block;
6
6
  font-family: var(--typography-fontFamily-sans);
7
- background: var(--color-blue-50);
7
+ background: var(--color-blue-50);
8
+ }
9
+
10
+ /* === DARK VARIANT === */
11
+ :host([variant="dark"]) {
12
+ background: linear-gradient(160deg, var(--color-neutral-800) 0%, #0b1626 100%);
13
+ }
14
+
15
+ :host([variant="dark"]) .bd-comparisonpanel-title {
16
+ color: var(--color-neutral-0, #fff);
17
+ }
18
+
19
+ :host([variant="dark"]) .bd-comparisonpanel-description {
20
+ color: rgba(255, 255, 255, 0.55);
21
+ }
22
+
23
+ :host([variant="dark"]) .bd-comparisonpanel-eyebrow {
24
+ color: var(--color-blue-400, #60a5fa);
25
+ }
26
+
27
+ :host([variant="dark"]) .bd-comparisonpanel-column {
28
+ background: rgba(255, 255, 255, 0.03);
29
+ border-color: rgba(255, 255, 255, 0.1);
30
+ }
31
+
32
+ :host([variant="dark"]) .bd-comparisonpanel-column-title {
33
+ color: rgba(255, 255, 255, 0.5);
34
+ font-family: var(--typography-fontFamily-mono, monospace);
35
+ text-transform: uppercase;
36
+ letter-spacing: 0.08em;
37
+ font-weight: var(--typography-fontWeight-bold, 700);
38
+ font-size: var(--typography-fontSize-xs, 12px);
39
+ }
40
+
41
+ :host([variant="dark"]) .bd-comparisonpanel-text {
42
+ color: rgba(255, 255, 255, 0.85);
43
+ }
44
+
45
+ :host([variant="dark"]) .bd-comparisonpanel-icon--positive {
46
+ background: var(--color-green-600, #16a34a);
47
+ }
48
+
49
+ :host([variant="dark"]) .bd-comparisonpanel-icon--negative {
50
+ background: var(--color-red-500, #ef4444);
8
51
  }
9
52
 
10
53
  .bd-comparisonpanel-wrapper {
@@ -14,6 +57,14 @@ export default css`
14
57
  box-sizing: border-box;
15
58
  }
16
59
 
60
+ /* Small eyebrow label above the title, e.g. "Clarity" — optional, only
61
+ rendered when the eyebrow prop/slot is used. */
62
+ .bd-comparisonpanel-eyebrow {
63
+ margin: 0 0 var(--spacing-8);
64
+ color: var(--color-blue-500);
65
+ font-weight: var(--typography-fontWeight-bold, 700);
66
+ }
67
+
17
68
  .bd-comparisonpanel-title {
18
69
  margin: 0 0 var(--spacing-16);
19
70
  color: var(--color-neutral-900);
@@ -11,7 +11,11 @@ class ComparisonPanel extends LitElement {
11
11
  positiveTitle: { type: String, attribute: "positive-title" },
12
12
  negativeTitle: { type: String, attribute: "negative-title" },
13
13
  positiveItems: { type: Array }, // [String]
14
- negativeItems: { type: Array } // [String]
14
+ negativeItems: { type: Array }, // [String]
15
+ // "light" (default) — white section, bordered white cards, sans-serif
16
+ // column titles. "dark" — near-black gradient section, dark bordered
17
+ // cards, mono uppercase column titles (e.g. "VPN FOR AI AGENTS IS").
18
+ variant : { type: String, reflect: true }
15
19
  };
16
20
 
17
21
  static styles = [tokens, comparisonPanelCSS];
@@ -24,6 +28,7 @@ class ComparisonPanel extends LitElement {
24
28
  this.negativeTitle = "";
25
29
  this.positiveItems = [];
26
30
  this.negativeItems = [];
31
+ this.variant = "light";
27
32
  }
28
33
 
29
34
  _renderColumn(kind, colTitle, items, slotName) {
@@ -9,7 +9,27 @@ export default css`
9
9
  :host([background="blue"]) {
10
10
  background: var(--color-blue-50);
11
11
  }
12
+ /* variant="light" + background="bordered": renders its own card border
13
+ and hover lift, so callers don't need a manual wrapper <div> just to
14
+ get the bordered-card look (e.g. side-by-side requirement cards). */
15
+ :host([variant="light"][background="bordered"]) {
16
+ display: block;
17
+ border: 1px solid var(--color-neutral-100, #e5e7eb);
18
+ border-radius: var(--radius-xl, 12px);
19
+ padding: var(--spacing-24, 24px);
20
+ box-sizing: border-box;
21
+ transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
22
+ }
23
+
24
+ :host([variant="light"][background="bordered"]:hover) {
25
+ transform: translateY(-3px);
26
+ box-shadow: 0 14px 40px #00000012;
27
+ border-color: var(--color-neutral-200);
28
+ }
12
29
 
30
+ :host([variant="light"][background="bordered"]) .bd-compattable-wrapper {
31
+ padding: 0;
32
+ }
13
33
  .bd-compattable-wrapper {
14
34
  max-width: var(--layout-ensemble-max-width, 1200px);
15
35
  margin: 0 auto;
@@ -31,7 +51,6 @@ export default css`
31
51
  max-width: 72ch;
32
52
  }
33
53
 
34
- /* === TABLE CONTAINER (default / outcome / risk) === */
35
54
  .bd-compattable-table-container {
36
55
  display: table;
37
56
  width: 100%;
@@ -42,7 +61,6 @@ export default css`
42
61
  box-sizing: border-box;
43
62
  }
44
63
 
45
- /* === HEADER ROW === */
46
64
  .bd-compattable-header {
47
65
  display: grid;
48
66
  grid-template-columns: 1.4fr 1.2fr 2.4fr;
@@ -74,7 +92,6 @@ export default css`
74
92
  color: var(--color-neutral-600);
75
93
  }
76
94
 
77
- /* === BODY === */
78
95
  .bd-compattable-body {
79
96
  display: flex;
80
97
  flex-direction: column;
@@ -141,15 +158,15 @@ export default css`
141
158
  .bd-compattable-cell--riskcoverage {
142
159
  color: var(--color-neutral-900);
143
160
  }
144
-
145
- /* === LIGHT VARIANT === */
146
- .bd-compattable-lightgrid {
147
- display: grid;
148
- grid-template-columns: 1fr 1fr;
149
- column-gap: var(--spacing-48);
150
- row-gap: 0;
151
- }
152
-
161
+ .bd-compattable-lightgrid {
162
+ display: grid;
163
+ grid-template-columns: repeat(var(--bd-compattable-light-columns, 2), 1fr);
164
+ column-gap: var(--spacing-48);
165
+ row-gap: 0;
166
+ }
167
+ .bd-compattable-lightrow:last-of-type {
168
+ border-bottom: none;
169
+ }
153
170
  .bd-compattable-lightrow {
154
171
  display: flex;
155
172
  align-items: baseline;
@@ -171,7 +188,6 @@ export default css`
171
188
  text-align: right;
172
189
  }
173
190
 
174
- /* === RESPONSIVE === */
175
191
  @media (max-width: 767px) {
176
192
  .bd-compattable-header {
177
193
  display: none;
@@ -6,12 +6,13 @@ import compatibilityTableCSS from "./compatibility-table.css.js";
6
6
 
7
7
  class CompatibilityTable extends LitElement {
8
8
  static properties = {
9
- title : { type: String },
10
- description: { type: String },
11
- variant : { type: String, reflect: true }, // "default" | "outcome" | "risk" | "light"
12
- background : { type: String, reflect: true }, // "default" | "blue"
13
- columns : { type: Array },
14
- rows : { type: Array }
9
+ title : { type: String },
10
+ description : { type: String },
11
+ variant : { type: String, reflect: true },
12
+ background : { type: String, reflect: true },
13
+ lightColumns: { type: Number, attribute: "light-columns" },
14
+ columns : { type: Array },
15
+ rows : { type: Array }
15
16
  };
16
17
 
17
18
  static styles = [tokens, compatibilityTableCSS];
@@ -22,6 +23,7 @@ class CompatibilityTable extends LitElement {
22
23
  this.description = "";
23
24
  this.variant = "default";
24
25
  this.background = "default";
26
+ this.lightColumns = 2;
25
27
  this.columns = null;
26
28
  this.rows = [];
27
29
  }
@@ -95,7 +97,11 @@ class CompatibilityTable extends LitElement {
95
97
 
96
98
  ${this.variant === "light"
97
99
  ? html`
98
- <div class="bd-compattable-lightgrid" role="table">
100
+ <div
101
+ class="bd-compattable-lightgrid"
102
+ role="table"
103
+ style="--bd-compattable-light-columns: ${this.lightColumns};"
104
+ >
99
105
  ${this.rows.map((row) => this._renderRow(row))}
100
106
  <slot name="rows"></slot>
101
107
  </div>
@@ -16,7 +16,18 @@ export default css`
16
16
  text-align: center;
17
17
  gap: var(--spacing-16);
18
18
  }
19
+ .bd-ctabanner-footer {
20
+ margin-top: var(--spacing-24, 24px);
21
+ display: flex;
22
+ flex-direction: column;
23
+ align-items: center;
24
+ gap: var(--spacing-8, 8px);
25
+ text-align: center;
26
+ }
19
27
 
28
+ .bd-ctabanner-footer:not(:has(*)) {
29
+ display: none;
30
+ }
20
31
  .bd-ctabanner-title {
21
32
  display: block;
22
33
  margin: 0;
@@ -55,6 +55,13 @@ class CtaBanner extends LitElement {
55
55
  </bd-p>
56
56
  `
57
57
  : nothing}
58
+
59
+ <!-- Freeform slot for extra content below the caption — contact
60
+ info, legal disclaimers, links, etc. Empty by default,
61
+ collapses to nothing when unused. -->
62
+ <div class="bd-ctabanner-footer">
63
+ <slot name="footer"></slot>
64
+ </div>
58
65
  </div>
59
66
  `;
60
67
  }
@@ -10,11 +10,6 @@ export default css`
10
10
  line-height: var(--typography-lineHeight-normal);
11
11
  }
12
12
 
13
- .footer-secondary-nav {
14
- padding-top: var(--spacing-12);
15
- padding-bottom: var(--spacing-12);
16
- }
17
-
18
13
  bd-divider-vertical {
19
14
  display: inline-block;
20
15
  width: var(--form-input-default-borderWidth);
@@ -47,7 +42,15 @@ padding-bottom: var(--spacing-12);
47
42
  padding: var(--spacing-24) 0;
48
43
  }
49
44
 
45
+ /* Wraps the "secondary-nav" slot (Legal / Privacy Policy / etc). This
46
+ rule previously only had padding — no display:flex/gap — so the
47
+ slotted links ran together with no spacing between them, same root
48
+ cause as the bug that was fixed in bd-footer's own footer.css.js. */
50
49
  .footer-secondary-nav {
50
+ display: flex;
51
+ align-items: center;
52
+ flex-wrap: wrap;
53
+ gap: var(--spacing-16);
51
54
  padding: var(--spacing-24) 0;
52
55
  }
53
56
 
@@ -80,7 +83,6 @@ padding-bottom: var(--spacing-12);
80
83
  background: var(--color-blue-500);
81
84
  }
82
85
 
83
- /* Stiluri pentru link-uri */
84
86
  a {
85
87
  color: var(--color-neutral-0);
86
88
  text-decoration: none;
@@ -90,7 +92,6 @@ padding-bottom: var(--spacing-12);
90
92
  text-decoration: underline;
91
93
  }
92
94
 
93
- /* Stiluri de accesibilitate */
94
95
  a:focus {
95
96
  outline: none;
96
97
  border: 2px solid var(--color-blue-500);
@@ -98,18 +99,6 @@ padding-bottom: var(--spacing-12);
98
99
  border-radius: 4px;
99
100
  }
100
101
 
101
- /* Stiluri pentru navigație */
102
- .footer-nav-main {
103
- display: flex;
104
- align-items: center;
105
- justify-content: flex-start;
106
- gap: var(--spacing-16);
107
- flex-wrap: wrap;
108
- font-size: var(--typography-body-regular-fontSize);
109
- font-family: var(--typography-fontFamily-sans, 'IBM Plex Sans');
110
- }
111
-
112
- /* Responsive styles */
113
102
  @media (max-width: 768px) {
114
103
  .footer-top {
115
104
  flex-direction: column;
@@ -128,13 +117,13 @@ padding-bottom: var(--spacing-12);
128
117
  margin-bottom: var(--spacing-16);
129
118
  }
130
119
 
131
- .footer-nav-main {
120
+ .footer-secondary-nav {
132
121
  flex-direction: column;
133
122
  align-items: flex-start;
134
123
  gap: var(--spacing-8);
135
124
  }
136
125
 
137
- .footer-nav-main bd-divider-vertical {
126
+ .footer-secondary-nav bd-divider-vertical {
138
127
  display: none !important;
139
128
  }
140
129
  }
@@ -22,7 +22,7 @@ export class BdFooterLP extends LitElement {
22
22
 
23
23
  connectedCallback() {
24
24
  super.connectedCallback();
25
- this._initLocaleFromUrl(); // Adaugă inițializarea locale-ului din URL
25
+ this._initLocaleFromUrl();
26
26
  window.addEventListener('resize', this._handleResize.bind(this));
27
27
  }
28
28
 
@@ -33,12 +33,12 @@ export class BdFooterLP extends LitElement {
33
33
 
34
34
  firstUpdated() {
35
35
  super.firstUpdated();
36
- this._toggleImpressumVisibility(); // Apelează la initializare
36
+ this._toggleImpressumVisibility();
37
37
  }
38
38
 
39
39
  updated(changedProps) {
40
40
  if (changedProps.has('currentLocale')) {
41
- this._toggleImpressumVisibility(); // Apelează când se schimbă locale-ul
41
+ this._toggleImpressumVisibility();
42
42
  }
43
43
  }
44
44
 
@@ -49,27 +49,22 @@ export class BdFooterLP extends LitElement {
49
49
  return;
50
50
  }
51
51
 
52
- // Creează o versiune normalized a localeMap cu cheile lowercase
53
52
  const normalizedLocaleMap = {};
54
53
  Object.entries(localeMap).forEach(([key, value]) => {
55
54
  normalizedLocaleMap[key.toLowerCase()] = value;
56
55
  });
57
56
 
58
- // Încearcă mai întâi potrivire exactă
59
57
  let country = normalizedLocaleMap[urlLocale];
60
58
 
61
- // Dacă nu găsești potrivire exactă, încearcă să găsești cea mai bună potrivire
62
59
  if (!country && urlLocale) {
63
60
  const localeParts = urlLocale.split('-');
64
61
  const language = localeParts[0];
65
62
  const region = localeParts[1];
66
63
 
67
- // Caută o potrivire care să înceapă cu același limbaj
68
64
  const possibleMatches = Object.entries(normalizedLocaleMap)
69
65
  .filter(([key]) => key.startsWith(language));
70
66
 
71
67
  if (possibleMatches.length > 0) {
72
- // Preferă potrivirea cu aceeași regiune dacă există
73
68
  const exactRegionMatch = possibleMatches.find(([key]) => {
74
69
  const keyParts = key.split('-');
75
70
  const keyRegion = keyParts[1];
@@ -81,13 +76,11 @@ export class BdFooterLP extends LitElement {
81
76
 
82
77
  if (exactRegionMatch) {
83
78
  country = exactRegionMatch[1];
84
- // Recuperează cheia originală din localeMap
85
79
  const originalKey = Object.keys(localeMap).find(k =>
86
80
  k.toLowerCase() === exactRegionMatch[0]
87
81
  );
88
82
  this.currentLocale = originalKey || exactRegionMatch[0];
89
83
  } else {
90
- // Altfel, ia prima potrivire
91
84
  country = possibleMatches[0][1];
92
85
  const originalKey = Object.keys(localeMap).find(k =>
93
86
  k.toLowerCase() === possibleMatches[0][0]
@@ -114,25 +107,20 @@ export class BdFooterLP extends LitElement {
114
107
  const footerNav = assignedElements[0];
115
108
  const impressumLink = footerNav.querySelector('.impressum-link');
116
109
 
117
- // Găsește separatorul care precede link-ul Impressum
118
110
  let impressumDivider = null;
119
111
  if (impressumLink) {
120
112
  impressumDivider = impressumLink.previousElementSibling;
121
113
 
122
- // Verifică dacă elementul anterior este un divider și este imediat înainte
123
114
  if (impressumDivider && impressumDivider.tagName === 'BD-DIVIDER-VERTICAL' &&
124
115
  impressumDivider.nextElementSibling === impressumLink) {
125
- // Este separatorul corect
126
116
  } else {
127
117
  impressumDivider = null;
128
118
  }
129
119
  }
130
120
 
131
121
  if (impressumLink) {
132
- // Ascunde/afișează link-ul Impressum
133
122
  impressumLink.style.display = showImpressum ? '' : 'none';
134
123
 
135
- // Ascunde/afișează și separatorul dinaintea lui
136
124
  if (impressumDivider && impressumDivider.tagName === 'BD-DIVIDER-VERTICAL') {
137
125
  impressumDivider.style.display = showImpressum ? '' : 'none';
138
126
  }
@@ -214,14 +202,12 @@ export class BdFooterLP extends LitElement {
214
202
  `;
215
203
  }
216
204
 
217
- // Metodă specifică pentru secondary-nav care verifică și elementele custom
218
205
  _hasSecondaryNavContent() {
219
206
  const slot = this.shadowRoot?.querySelector('slot[name="secondary-nav"]');
220
207
  if (!slot) return false;
221
208
 
222
209
  const assignedNodes = slot.assignedNodes({ flatten: true });
223
210
 
224
- // Verifică dacă există noduri care nu sunt doar spații albe
225
211
  const hasContent = assignedNodes.some(node => {
226
212
  if (node.nodeType === Node.ELEMENT_NODE) {
227
213
  return true;
@@ -235,7 +221,6 @@ export class BdFooterLP extends LitElement {
235
221
  return hasContent;
236
222
  }
237
223
 
238
- // Metodă helper pentru a verifica dacă un slot are conținut
239
224
  _hasSlotContent(slotName) {
240
225
  const slot = this.shadowRoot?.querySelector(`slot[name="${slotName}"]`);
241
226
  if (!slot) return false;
@@ -16,7 +16,6 @@ export default css`
16
16
  font-weight: var(--typography-heading-h3-fontWeight);
17
17
  }
18
18
 
19
- /* Corect: stilizare pentru elementele slottate */
20
19
  ::slotted(a) {
21
20
  color: white !important;
22
21
  text-decoration: none;
@@ -33,5 +32,4 @@ export default css`
33
32
  display: none !important;
34
33
  }
35
34
  }
36
-
37
35
  `;