@bytebrand/fe-ui-core-autobahn 1.0.74 → 1.0.75

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/cards/CarCard.tsx CHANGED
@@ -72,6 +72,15 @@ export interface CarCardProps {
72
72
  * the same one.
73
73
  */
74
74
  onOpenRateAdjust?: (mode: PaymentMode) => void;
75
+ /**
76
+ * takes over the "Finanzierungsdetails"/"Details" link under the price row — e.g. navigate to
77
+ * this car's own VDP and open its finance modal already expanded/scrolled to the breakdown,
78
+ * instead of the default plain onOpen(car) navigation. Receives the tab the card was showing
79
+ * (Finanzierung/Leasing/Kaufen) so the destination modal opens on the same one. Optional/
80
+ * page-owned like onOpenRateAdjust; the mobile CTA row's "Rate anpassen" button is untouched
81
+ * (still onOpenRateAdjust).
82
+ */
83
+ onShowFinancingDetails?: (car: AutobahnCar, mode: PaymentMode) => void;
75
84
  }
76
85
 
77
86
  const CarCard: React.FunctionComponent<CarCardProps> = ({
@@ -85,6 +94,7 @@ const CarCard: React.FunctionComponent<CarCardProps> = ({
85
94
  onRequestOffer,
86
95
  onCall,
87
96
  onOpenRateAdjust,
97
+ onShowFinancingDetails,
88
98
  }) => {
89
99
  const [mode, setMode] = useState<PaymentMode>('financing');
90
100
  const [photoIndex, setPhotoIndex] = useState(0);
@@ -103,11 +113,11 @@ const CarCard: React.FunctionComponent<CarCardProps> = ({
103
113
  onMouseEnter={onMediaEnter}
104
114
  onTouchStart={onMediaEnter}
105
115
  >
106
- <CardCarousel images={car.gallery} height="100%" fit="contain" onChange={setPhotoIndex} />
116
+ <CardCarousel images={car.gallery} height="100%" fit="contain" padded={false} onChange={setPhotoIndex} />
107
117
  {/* max two overlays: heart + ONE deal signal — rating moved next to the price */}
108
118
  <div
109
119
  className="cc-fav"
110
- style={{ position: 'absolute', top: 6, right: 6, zIndex: 3 }}
120
+ style={{ position: 'absolute', top: 6, right: 6, zIndex: 6 }}
111
121
  onClick={(e) => e.stopPropagation()}
112
122
  >
113
123
  <IconButton name="heart" filled active={isFavorite} onClick={onToggleFavorite} label={t('autobahn:card.action.save')} />
@@ -133,7 +143,24 @@ const CarCard: React.FunctionComponent<CarCardProps> = ({
133
143
  <div style={{ display: 'flex', flexWrap: 'nowrap', gap: 5, alignItems: 'center' }}>
134
144
  {car.isNew && <span className="neu-badge">NEU</span>}
135
145
  {car.drop != null ? <DropChip t={t} amount={car.drop} /> : showSave && <SaveChip t={t} amount={car.savings!} />}
136
- <ZeroDownChip t={t} show={car.zeroDown} />
146
+ <ZeroDownChip
147
+ t={t}
148
+ show={car.zeroDown}
149
+ style={{
150
+ width: 104,
151
+ height: 30,
152
+ padding: 0,
153
+ justifyContent: 'center',
154
+ background: 'rgb(204, 222, 255)',
155
+ border: '1px solid rgba(0, 92, 255, 0.05)',
156
+ borderRadius: 15,
157
+ fontFamily: 'Arial',
158
+ fontWeight: 700,
159
+ fontSize: 13,
160
+ lineHeight: '15px',
161
+ color: '#005CFF',
162
+ }}
163
+ />
137
164
  <PercentChip pct={car.dropPct} />
138
165
  </div>
139
166
  <OfferBadge show={showOfferBadge} t={t} />
@@ -172,7 +199,13 @@ const CarCard: React.FunctionComponent<CarCardProps> = ({
172
199
  </div>
173
200
  {/* same fallback CardCtaRow already uses below: pages that haven't wired a real
174
201
  "Rate anpassen" sheet yet still get a working "Details" link (opens the car). */}
175
- <PriceTerms car={car} mode={mode} onOpenRateAdjust={onOpenRateAdjust || (() => onOpen(car))} t={t} />
202
+ <PriceTerms
203
+ car={car}
204
+ mode={mode}
205
+ onOpenRateAdjust={onOpenRateAdjust || (() => onOpen(car))}
206
+ onShowDetails={onShowFinancingDetails ? () => onShowFinancingDetails(car, mode) : undefined}
207
+ t={t}
208
+ />
176
209
  </div>
177
210
  <EcoLine
178
211
  t={t}
@@ -564,22 +564,34 @@ export const PriceHero: React.FunctionComponent<PriceHeroProps> = ({ car, mode,
564
564
  eyebrow/unit have nothing to caption, so the whole group stays hidden. */}
565
565
  {!isMoney && showOld && (
566
566
  <span className="pp-hero-unit-group">
567
- <span className="pp-eyebrow">
568
- {t('autobahn:card.price.uvpRateLabel')}
569
- <UvpBadge
570
- n={3}
571
- open={uvpTooltipOpen}
572
- onToggle={() => setUvpTooltipOpen((v) => !v)}
573
- onClose={() => setUvpTooltipOpen(false)}
574
- closeLabel={t('autobahn:modal.close')}
575
- body={t(
576
- mode === 'leasing'
577
- ? 'autobahn:card.price.uvpRateTooltipBodyLeasing'
578
- : 'autobahn:card.price.uvpRateTooltipBody',
579
- )}
580
- />
567
+ {/* a real (not display:contents) flex-column box, matching .pp-hero-unit-group's own
568
+ column layout exactly — so the click target covers the full area INCLUDING the
569
+ gap between the two stacked lines, not just their text glyphs (display:contents
570
+ has no box of its own there, so clicks in that gap fell through to the card link
571
+ behind it instead of opening the tooltip). */}
572
+ <span
573
+ style={{ display: 'flex', flexDirection: 'column' }}
574
+ role="button"
575
+ tabIndex={0}
576
+ onClick={() => setUvpTooltipOpen((v) => !v)}
577
+ >
578
+ <span className="pp-eyebrow">
579
+ {t('autobahn:card.price.uvpRateLabel')}
580
+ <UvpBadge
581
+ n={3}
582
+ open={uvpTooltipOpen}
583
+ onToggle={() => setUvpTooltipOpen((v) => !v)}
584
+ onClose={() => setUvpTooltipOpen(false)}
585
+ closeLabel={t('autobahn:modal.close')}
586
+ body={t(
587
+ mode === 'leasing'
588
+ ? 'autobahn:card.price.uvpRateTooltipBodyLeasing'
589
+ : 'autobahn:card.price.uvpRateTooltipBody',
590
+ )}
591
+ />
592
+ </span>
593
+ <span className={'pp-hero-old' + oldLenClass}>{Math.round(oldValue as number).toLocaleString('de-DE')} €</span>
581
594
  </span>
582
- <span className={'pp-hero-old' + oldLenClass}>{Math.round(oldValue as number).toLocaleString('de-DE')} €</span>
583
595
  <span className="pp-hero-unit">{t('autobahn:card.price.perMonth')}</span>
584
596
  </span>
585
597
  )}
@@ -591,7 +603,15 @@ export const PriceHero: React.FunctionComponent<PriceHeroProps> = ({ car, mode,
591
603
  car.listPrice already used by DropChip/PpRow. */}
592
604
  {isMoney && showOld && (
593
605
  <span className="pp-hero-unit-group">
594
- <span className={'pp-hero-old' + oldLenClass}>
606
+ <span
607
+ className={'pp-hero-old' + oldLenClass}
608
+ role="button"
609
+ tabIndex={0}
610
+ onClick={(e) => {
611
+ e.stopPropagation();
612
+ setUvpTooltipOpen((v) => !v);
613
+ }}
614
+ >
595
615
  {Math.round(oldValue as number).toLocaleString('de-DE')} €
596
616
  <UvpBadge
597
617
  n={2}
@@ -621,8 +641,13 @@ export const PriceTerms: React.FunctionComponent<{
621
641
  car: AutobahnCar;
622
642
  mode: PaymentMode;
623
643
  onOpenRateAdjust?: (mode: PaymentMode) => void;
644
+ /** takes over the "Finanzierungsdetails"/"Details" link's click (e.g. navigate to the VDP and
645
+ * open the finance modal already expanded, scrolled to the breakdown) — when given, it wins
646
+ * over onOpenRateAdjust for THIS link only; the mobile CTA row's own "Rate anpassen" button
647
+ * keeps using onOpenRateAdjust regardless. */
648
+ onShowDetails?: () => void;
624
649
  t: TranslationFunction;
625
- }> = ({ car, mode, onOpenRateAdjust, t }) => {
650
+ }> = ({ car, mode, onOpenRateAdjust, onShowDetails, t }) => {
626
651
  if (mode === 'buy') return null;
627
652
  const finFirstInstallment =
628
653
  car.finFirstInstallment != null ? car.finFirstInstallment.toLocaleString('de-DE') : _finFirstInstallment;
@@ -639,7 +664,7 @@ export const PriceTerms: React.FunctionComponent<{
639
664
  ? t('autobahn:card.price.leaseTerms', { firstInstallment: leasFirstInstallment, months: leasMonths, mileage: leasMileageStr })
640
665
  : ''
641
666
  : t('autobahn:card.price.financeTerms', { firstInstallment: finFirstInstallment, months: finMonths, count: finMonths });
642
- if (!termsText && !onOpenRateAdjust) return null;
667
+ if (!termsText && !onOpenRateAdjust && !onShowDetails) return null;
643
668
  const detailsLabel = mode === 'leasing' ? t('autobahn:card.price.detailsLink') : t('autobahn:modal.financingDetails');
644
669
  // split on the translation's own ' · ' separator so the dot can be styled lighter than the
645
670
  // two figures around it (same literal separator convention as FinanceCalculator's condParts).
@@ -652,7 +677,7 @@ export const PriceTerms: React.FunctionComponent<{
652
677
  {part}
653
678
  </React.Fragment>
654
679
  ))}
655
- {onOpenRateAdjust && (
680
+ {(onOpenRateAdjust || onShowDetails) && (
656
681
  <>
657
682
  {termsText && <span className="cc-terms-dot"> · </span>}
658
683
  <button
@@ -660,7 +685,8 @@ export const PriceTerms: React.FunctionComponent<{
660
685
  className="cc-terms-link"
661
686
  onClick={(e) => {
662
687
  e.stopPropagation();
663
- onOpenRateAdjust(mode);
688
+ if (onShowDetails) onShowDetails();
689
+ else onOpenRateAdjust!(mode);
664
690
  }}
665
691
  >
666
692
  {detailsLabel}
@@ -706,7 +732,7 @@ export interface CardCtaRowProps {
706
732
  * keeps its text label — only the phone button is icon-only, matching the mockup.
707
733
  */
708
734
  export const CardCtaRow: React.FunctionComponent<CardCtaRowProps> = ({ car, mode, onRequestOffer, onCall, onOpenRateAdjust, t }) => (
709
- <div className="card-cta-row show-mobile" style={{ display: 'flex', gap: 8, marginTop: 10 }}>
735
+ <div className="card-cta-row show-mobile" style={{ display: 'flex', gap: 8 }}>
710
736
  <Button
711
737
  variant="filled"
712
738
  style={{ flex: 2 }}
package/chrome/Footer.tsx CHANGED
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import { TranslationFunction } from '../types';
3
- import { defaultConfig } from '@bytebrand/fe-financing';
4
3
 
5
4
  import logoUrl from '../assets/autode-logo.svg';
6
5
 
@@ -73,10 +72,6 @@ const APPS: ReadonlyArray<{ name: string; labelKey: string; href: string }> = [
73
72
  { name: 'android', labelKey: 'autobahn:chrome.androidApp', href: 'https://play.google.com/store/apps/details?id=de.auto.app' },
74
73
  ];
75
74
 
76
- /** financing defaults for the §17a PAngV representative example (same source the legacy footer uses). */
77
- const FIN = defaultConfig.financing;
78
- const fmt2 = (n: number): string => Number(n).toFixed(2);
79
-
80
75
  export interface FooterProps {
81
76
  /**
82
77
  * i18n function. The footer: namespace holds the LEGALLY REQUIRED disclaimer text (PAngV
@@ -93,7 +88,12 @@ export interface FooterProps {
93
88
  */
94
89
  const Footer: React.FunctionComponent<FooterProps> = ({ t }) => {
95
90
  const scrollTop = (): void => window.scroll({ top: 0, left: 0, behavior: 'smooth' });
96
- const year = new Date().getFullYear();
91
+ const now = new Date();
92
+ const year = now.getFullYear();
93
+ // de-DE always renders DD.MM.YYYY — the disclaimer's "Stand: …" date, same format regardless
94
+ // of UI language (this is a German-market legal notice). Computed fresh on every render, so it
95
+ // reads correctly on any future day without needing a manual update.
96
+ const today = now.toLocaleDateString('de-DE');
97
97
 
98
98
  return (
99
99
  <footer style={{ background: 'var(--md-sc-low)', borderTop: '1px solid var(--md-outline-variant)' }}>
@@ -167,18 +167,23 @@ const Footer: React.FunctionComponent<FooterProps> = ({ t }) => {
167
167
  term, DAT CO₂-Leitfaden, MwSt, Streichpreis, image notice). Same text as the legacy footer. */}
168
168
  <div style={{ borderTop: '1px solid var(--md-outline-variant)' }}>
169
169
  <div className="container" style={{ padding: '18px 24px' }}>
170
- <p className="md-label-sm" style={{ lineHeight: 1.55, color: 'var(--md-on-surface-variant)', margin: 0 }}>
171
- {t('footer:vatReportable')}<br />
172
- {t('footer:strikePrice')}<br />
173
- {t('footer:financingInfo', {
174
- rawPaybackPeriod: FIN.rawPaybackPeriod,
175
- nominalInterestRate: fmt2(FIN.nominalInterestRate),
176
- annualPercentageRate: fmt2(FIN.annualPercentageRate),
177
- })}<br />
178
- * {t('footer:co2Info')}<br />
179
- {t('footer:EnvPremium')}<br />
180
- {t('footer:images')}
181
- </p>
170
+ <p
171
+ className="md-label-sm"
172
+ style={{ lineHeight: 1.55, color: 'var(--md-on-surface-variant)', margin: 0 }}
173
+ // legal disclaimer text only (no user input) — <b> tags on the defined terms
174
+ // (Hersteller-UVP / UVP-Vergleichsrate / Fahrzeugabbildungen und Fahrzeugdaten) live
175
+ // directly in the translation strings, one key per footnote like the rest of this file.
176
+ dangerouslySetInnerHTML={{
177
+ __html: [
178
+ t('footer:vatReportable'),
179
+ t('footer:manufacturerUvp'),
180
+ t('footer:uvpComparisonRate'),
181
+ t('footer:priceEvaluation', { date: today }),
182
+ t('footer:consumptionInfo'),
183
+ t('footer:vehicleImages'),
184
+ ].join('<br />'),
185
+ }}
186
+ />
182
187
  </div>
183
188
  </div>
184
189
 
package/constants.ts CHANGED
@@ -1,31 +1,31 @@
1
- // Autobahn (auto.de redesign) — shared lookup constants barrel.
2
- // Pure data re-exported from ./constants/autobahn (kept import-safe for plain Node consumers,
3
- // see that file's header) plus the legacy fe-ui-core shim re-exports below.
4
- export * from './constants/autobahn';
5
-
6
- // ---------------------------------------------------------------------------
7
- // Legacy shared constants (moved here from fe-ui-core).
8
- //
9
- // This block mirrors the public symbol set of the old
10
- // `@bytebrand/fe-ui-core/constants` barrel so consumers can swap that
11
- // specifier for `@bytebrand/fe-ui-core-autobahn/constants` 1:1. The
12
- // implementations live under ./constants/ (core.ts, app.ts, price.ts,
13
- // Search.ts, …); fe-ui-core re-exports them via shims until it is deleted.
14
- // ---------------------------------------------------------------------------
15
-
16
- export {
17
- offers,
18
- checkoutOffers,
19
- checkoutWarranties,
20
- checkoutSteps,
21
- checkoutSubStep,
22
- DELIVERY_PERIODS_EXTRA,
23
- THREE,
24
- WLTP_ENERGY_EFFICIENCY_CLASS
25
- } from './constants/core';
26
-
27
- export { CUSTOM_ERROR_MESSAGES, supportPhone, supportPhoneLink } from './constants/app';
28
-
29
- export { priceRatings } from './constants/price';
30
-
31
- export { THROTTLE_DELAY } from './constants/Search';
1
+ // Autobahn (auto.de redesign) — shared lookup constants barrel.
2
+ // Pure data re-exported from ./constants/autobahn (kept import-safe for plain Node consumers,
3
+ // see that file's header) plus the legacy fe-ui-core shim re-exports below.
4
+ export * from './constants/autobahn';
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Legacy shared constants (moved here from fe-ui-core).
8
+ //
9
+ // This block mirrors the public symbol set of the old
10
+ // `@bytebrand/fe-ui-core/constants` barrel so consumers can swap that
11
+ // specifier for `@bytebrand/fe-ui-core-autobahn/constants` 1:1. The
12
+ // implementations live under ./constants/ (core.ts, app.ts, price.ts,
13
+ // Search.ts, …); fe-ui-core re-exports them via shims until it is deleted.
14
+ // ---------------------------------------------------------------------------
15
+
16
+ export {
17
+ offers,
18
+ checkoutOffers,
19
+ checkoutWarranties,
20
+ checkoutSteps,
21
+ checkoutSubStep,
22
+ DELIVERY_PERIODS_EXTRA,
23
+ THREE,
24
+ WLTP_ENERGY_EFFICIENCY_CLASS
25
+ } from './constants/core';
26
+
27
+ export { CUSTOM_ERROR_MESSAGES, supportPhone, supportPhoneLink } from './constants/app';
28
+
29
+ export { priceRatings } from './constants/price';
30
+
31
+ export { THROTTLE_DELAY } from './constants/Search';
@@ -66,7 +66,6 @@
66
66
  "finance": {
67
67
  "termSelection": "Laufzeit",
68
68
  "termSelectionMonths": "Laufzeit (Monate)",
69
- "exampleLabel": "z.B.",
70
69
  "headerTitle": "Dein Angebot",
71
70
  "adjustRate": "Rate anpassen",
72
71
  "secureOffer": "Angebot anfragen",
@@ -91,19 +90,22 @@
91
90
  "warrantyValue": "1 Jahr inklusive",
92
91
  "deliveryLabel": "Lieferung",
93
92
  "deliveryValue": "ca. 7–14 Tage · oder Abholung",
93
+ "availabilityLabel": "Verfügbarkeit",
94
+ "availabilityValue": "Sofort",
94
95
  "downPaymentSliderLabel": "Anzahlung",
95
96
  "annualMileageLabel": "Laufleistung / Jahr",
96
97
  "purchasePrice": "Kaufpreis",
97
98
  "perMonth": "/mtl.",
98
99
  "leasingDetails": "Leasing-Details",
99
- "financingDetails": "Finanzierungsdetails",
100
+ "financingDetails": "Finanzierungs-Details",
100
101
  "personalConsultationLine": "Persönliche Beratung. Wir sind für Sie da!",
101
102
  "requestRate": "Rate anfragen",
102
103
  "callCta": "Anrufen",
103
104
  "finalInstallmentToggle": "Mit Schlussrate",
104
105
  "addServicesToggle": "Rundum-Sorglos-Paket",
105
106
  "addServicesPerMonth": "+{{value}} € / Monat",
106
- "addServicesOnce": "+{{value}} €"
107
+ "addServicesOnce": "+{{value}} €",
108
+ "addServicesIncluded": "inklusive"
107
109
  },
108
110
  "specTable": {
109
111
  "title": "Fahrzeugdaten",
@@ -684,7 +686,7 @@
684
686
  },
685
687
  "modal": {
686
688
  "leasingDetails": "Leasingdetails",
687
- "financingDetails": "Finanzierungsdetails",
689
+ "financingDetails": "Finanzierungs-Details",
688
690
  "close": "Schließen",
689
691
  "vehiclePrice": "Fahrzeugpreis ggf. inkl. MwSt.",
690
692
  "leasingAmount": "Leasingbetrag",
@@ -699,8 +701,8 @@
699
701
  "finalInstallment": "Schlussrate",
700
702
  "leasingRate": "Leasingrate",
701
703
  "monthlyRate": "Monatsrate",
702
- "leasingRateCount": "{{count}} Leasingrate à",
703
- "leasingRateCount_plural": "{{count}} Leasingraten à",
704
+ "leasingRateCount": "{{count}} Monatsrate à",
705
+ "leasingRateCount_plural": "{{count}} Monatsraten à",
704
706
  "monthlyRateCount": "{{count}} Rate à",
705
707
  "monthlyRateCount_plural": "{{count}} Raten à",
706
708
  "addServicesRow": "Rundum-Sorglos-Paket (einmalig)",
@@ -709,11 +711,30 @@
709
711
  "totalRepayment": "Gesamtbetrag Finanzierung",
710
712
  "totalCostWithPackage": "Gesamtbelastung inkl. Anzahlung & Paket",
711
713
  "totalCost": "Gesamtbelastung inkl. Anzahlung",
712
- "listPrice": "Listenpreis (UVP)",
714
+ "listPrice": "Listenpreis (UVP)³",
715
+ "leaseVehiclePrice": "Anschaffungspreis¹",
716
+ "leaseDownPayment": "Einmalige Sonderzahlung",
717
+ "finalPaymentDue": "Schlusszahlung (fällig am Vertragsende)",
718
+ "residualValue": "Restwert (verpflichtend)",
719
+ "rateSumLabel": "Summe der Leasingraten ({{term}} × {{amount}} €)",
720
+ "addServicesRowLease": "Rundum-Sorglos-Paket (Einmalzahlung)",
721
+ "subtotalWithPackage": "Gesamt inkl. Sonderzahl. & Paket",
722
+ "subtotalNoPackage": "Gesamt inkl. Sonderzahlung",
723
+ "grandTotalWithResidual": "Gesamt inkl. Restwert (verpflichtend)",
724
+ "listPriceLease": "Listenpreis (UVP)²",
713
725
  "representativeExample": "Repräsentatives Beispiel",
714
726
  "vatDisclaimer": "(alle Preisangaben ggf. inkl. der jeweils gesetzlich gültigen MwSt., derzeit 19%)",
715
727
  "lenderLabel": "Darlehensgeber:",
716
- "lenderName": "Open Bank AG, Santander-Platz 1, 41061 Mönchengladbach",
728
+ "lenderName": "Santander Consumer Bank AG, Santander-Platz 1, 41061 Mönchengladbach",
729
+ "leaseLenderLabel": "Leasinggeber:",
730
+ "leaseLenderName": "Santander Consumer Leasing GmbH, Santander-Platz 1, 41061 Mönchengladbach",
731
+ "contractTypeLabel": "Vertragsart:",
732
+ "contractTypeValue": "Restwertleasing",
733
+ "packageMandatoryNotice": "Das Rundum-Sorglos-Paket ist verpflichtend. In der dargestellten Konfiguration ist es als Einmalzahlung von {{amount}} € zu leisten und nicht in der Monatsrate enthalten. Bei Rateneinrechnung werden Monatsrate und Gesamtbeträge entsprechend angepasst.",
734
+ "legalFootnoteAcquisitionPrice": "¹ Der Anschaffungspreis bezeichnet den Preis, den die Santander Consumer Leasing GmbH für das Fahrzeug zu bezahlen hat.",
735
+ "legalFootnoteListPriceLease": "² Listenpreis (UVP) = unverbindliche Preisempfehlung des Herstellers.",
736
+ "closingDisclaimerLine1": "Änderungen und Irrtümer vorbehalten. Farbe und Ausstattung können vom Angebot abweichen.",
737
+ "closingDisclaimerLine2": "Kostenpflichtige Sonderausstattung möglich.",
717
738
  "legalNoticesTitle": "Rechtliche Hinweise",
718
739
  "legalNoticeCreditworthiness": "Bonität vorausgesetzt.",
719
740
  "legalNoticeExample": "Repräsentatives Beispiel gem. § 17 PAngV.",
@@ -66,7 +66,6 @@
66
66
  "finance": {
67
67
  "termSelection": "Term",
68
68
  "termSelectionMonths": "Term (months)",
69
- "exampleLabel": "e.g.",
70
69
  "headerTitle": "Your offer",
71
70
  "adjustRate": "Adjust rate",
72
71
  "secureOffer": "Request offer",
@@ -91,6 +90,8 @@
91
90
  "warrantyValue": "1 year included",
92
91
  "deliveryLabel": "Delivery",
93
92
  "deliveryValue": "approx. 7–14 days · or collection",
93
+ "availabilityLabel": "Availability",
94
+ "availabilityValue": "Immediately",
94
95
  "downPaymentSliderLabel": "Down payment",
95
96
  "annualMileageLabel": "Mileage / year",
96
97
  "purchasePrice": "Purchase price",
@@ -103,7 +104,8 @@
103
104
  "finalInstallmentToggle": "With final installment",
104
105
  "addServicesToggle": "All-round care package",
105
106
  "addServicesPerMonth": "+€{{value}} / month",
106
- "addServicesOnce": "+€{{value}}"
107
+ "addServicesOnce": "+€{{value}}",
108
+ "addServicesIncluded": "included"
107
109
  },
108
110
  "specTable": {
109
111
  "title": "Vehicle data",
@@ -699,8 +701,8 @@
699
701
  "finalInstallment": "Final installment",
700
702
  "leasingRate": "Leasing rate",
701
703
  "monthlyRate": "Monthly rate",
702
- "leasingRateCount": "{{count}} leasing installment of",
703
- "leasingRateCount_plural": "{{count}} leasing installments of",
704
+ "leasingRateCount": "{{count}} monthly installment of",
705
+ "leasingRateCount_plural": "{{count}} monthly installments of",
704
706
  "monthlyRateCount": "{{count}} installment of",
705
707
  "monthlyRateCount_plural": "{{count}} installments of",
706
708
  "addServicesRow": "Complete care package (one-time)",
@@ -709,11 +711,30 @@
709
711
  "totalRepayment": "Total financing amount",
710
712
  "totalCostWithPackage": "Total cost incl. down payment & package",
711
713
  "totalCost": "Total cost incl. down payment",
712
- "listPrice": "List price (RRP)",
714
+ "listPrice": "List price (RRP)³",
715
+ "leaseVehiclePrice": "Acquisition price¹",
716
+ "leaseDownPayment": "One-time special payment",
717
+ "finalPaymentDue": "Final payment (due at contract end)",
718
+ "residualValue": "Residual value (mandatory)",
719
+ "rateSumLabel": "Sum of leasing installments ({{term}} × {{amount}} €)",
720
+ "addServicesRowLease": "Complete care package (one-time payment)",
721
+ "subtotalWithPackage": "Total incl. special payment & package",
722
+ "subtotalNoPackage": "Total incl. special payment",
723
+ "grandTotalWithResidual": "Total incl. residual value (mandatory)",
724
+ "listPriceLease": "List price (RRP)²",
713
725
  "representativeExample": "Representative example",
714
726
  "vatDisclaimer": "(all prices may incl. the applicable statutory VAT, currently 19%)",
715
727
  "lenderLabel": "Lender:",
716
- "lenderName": "Open Bank AG, Santander-Platz 1, 41061 Mönchengladbach",
728
+ "lenderName": "Santander Consumer Bank AG, Santander-Platz 1, 41061 Mönchengladbach",
729
+ "leaseLenderLabel": "Lessor:",
730
+ "leaseLenderName": "Santander Consumer Leasing GmbH, Santander-Platz 1, 41061 Mönchengladbach",
731
+ "contractTypeLabel": "Contract type:",
732
+ "contractTypeValue": "Residual value leasing",
733
+ "packageMandatoryNotice": "The complete care package is mandatory. In the configuration shown, it must be paid as a one-time payment of {{amount}} € and is not included in the monthly rate. If rolled into the installments, the monthly rate and totals are adjusted accordingly.",
734
+ "legalFootnoteAcquisitionPrice": "¹ The acquisition price denotes the price Santander Consumer Leasing GmbH pays for the vehicle.",
735
+ "legalFootnoteListPriceLease": "² List price (RRP) = manufacturer's non-binding recommended retail price.",
736
+ "closingDisclaimerLine1": "Subject to change and errors. Color and equipment may differ from the offer shown.",
737
+ "closingDisclaimerLine2": "Optional equipment may incur additional costs.",
717
738
  "legalNoticesTitle": "Legal notices",
718
739
  "legalNoticeCreditworthiness": "Subject to creditworthiness.",
719
740
  "legalNoticeExample": "Representative example per § 17 PAngV.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/fe-ui-core-autobahn",
3
- "version": "1.0.74",
3
+ "version": "1.0.75",
4
4
  "description": "auto.de md3 (Autobahn) design system — UI primitives, cards, chrome, VDP modules, theme CSS and locales. Ships raw TypeScript source (like fe-ui-core before it); each consumer's bundler compiles it.",
5
5
  "main": "index.ts",
6
6
  "license": "UNLICENSED",