@bytebrand/fe-ui-core-autobahn 1.0.155 → 1.0.157
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 +9 -39
- package/cards/cardParts.tsx +1 -6
- package/constants/app.ts +1 -11
- package/constants/core.ts +1 -12
- package/locales/de/autobahn.json +2 -2
- package/locales/en/autobahn.json +1 -1
- package/locales/legacy/data.ts +1 -2
- package/package.json +1 -1
- package/theme/md3.css +237 -8
- package/vehiclesProps/decoratedLightProps.tsx +6 -16
- package/vehiclesProps/decoratedProps.tsx +4 -8
package/cards/CarCard.tsx
CHANGED
|
@@ -157,8 +157,6 @@ const CarCard: React.FunctionComponent<CarCardProps> = ({
|
|
|
157
157
|
// active that's already 3, so NEU is dropped rather than causing a 4th to overflow.
|
|
158
158
|
const activeDealChips = [showDrop || showSave, showPct, !!car.zeroDown].filter(Boolean).length;
|
|
159
159
|
const showNeu = asGoodAsNew && car.isNew && activeDealChips < 3;
|
|
160
|
-
// tabs the price block can switch to (PriceTabs shows Leasing only when the car has a lease rate)
|
|
161
|
-
const paymentModes: PaymentMode[] = car.lease != null ? ['financing', 'leasing', 'buy'] : ['financing', 'buy'];
|
|
162
160
|
return (
|
|
163
161
|
<article
|
|
164
162
|
className="mcard mcard--interactive cc-card"
|
|
@@ -279,46 +277,18 @@ const CarCard: React.FunctionComponent<CarCardProps> = ({
|
|
|
279
277
|
<div className="cc-price" style={{ marginTop: 0, borderTop: '1px solid var(--md-outline-variant)' }}>
|
|
280
278
|
<PriceTabs car={car} mode={mode} onModeChange={setMode} t={t} />
|
|
281
279
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, marginTop: 10 }}>
|
|
282
|
-
{
|
|
283
|
-
visible, bottom-aligned — Kaufen's struck list price sits on its own line above
|
|
284
|
-
the price, so without this the row (and the card) grew/shrank by that line on
|
|
285
|
-
every tab switch. Same trick as .cc-terms-stack below. */}
|
|
286
|
-
<div className="cc-hero-stack">
|
|
287
|
-
{paymentModes.map((m) => (
|
|
288
|
-
<div
|
|
289
|
-
key={m}
|
|
290
|
-
className={'cc-hero-slot' + (m === mode ? '' : ' cc-hero-slot--hidden')}
|
|
291
|
-
aria-hidden={m === mode ? undefined : true}
|
|
292
|
-
>
|
|
293
|
-
<PriceHero car={car} mode={m} t={t} alwaysShowUnit />
|
|
294
|
-
</div>
|
|
295
|
-
))}
|
|
296
|
-
</div>
|
|
280
|
+
<PriceHero car={car} mode={mode} t={t} alwaysShowUnit />
|
|
297
281
|
<PriceEvalCol car={car} t={t} />
|
|
298
282
|
</div>
|
|
299
283
|
{/* same fallback CardCtaRow already uses below: pages that haven't wired a real
|
|
300
|
-
"Rate anpassen" sheet yet still get a working "Details" link (opens the car).
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
{
|
|
307
|
-
|
|
308
|
-
key={m}
|
|
309
|
-
className={'cc-terms-slot' + (m === mode ? '' : ' cc-terms-slot--hidden')}
|
|
310
|
-
aria-hidden={m === mode ? undefined : true}
|
|
311
|
-
>
|
|
312
|
-
<PriceTerms
|
|
313
|
-
car={car}
|
|
314
|
-
mode={m}
|
|
315
|
-
onOpenRateAdjust={onOpenRateAdjust || (() => onOpen(car))}
|
|
316
|
-
onShowDetails={onShowFinancingDetails ? () => onShowFinancingDetails(car, m) : undefined}
|
|
317
|
-
t={t}
|
|
318
|
-
/>
|
|
319
|
-
</div>
|
|
320
|
-
))}
|
|
321
|
-
</div>
|
|
284
|
+
"Rate anpassen" sheet yet still get a working "Details" link (opens the car). */}
|
|
285
|
+
<PriceTerms
|
|
286
|
+
car={car}
|
|
287
|
+
mode={mode}
|
|
288
|
+
onOpenRateAdjust={onOpenRateAdjust || (() => onOpen(car))}
|
|
289
|
+
onShowDetails={onShowFinancingDetails ? () => onShowFinancingDetails(car, mode) : undefined}
|
|
290
|
+
t={t}
|
|
291
|
+
/>
|
|
322
292
|
</div>
|
|
323
293
|
{/* Mobile-only row (CardCtaRow itself carries the show-mobile class) — always
|
|
324
294
|
rendered, with real fallbacks the page can override once it wires its own
|
package/cards/cardParts.tsx
CHANGED
|
@@ -710,12 +710,7 @@ export const PriceTerms: React.FunctionComponent<{
|
|
|
710
710
|
onShowDetails?: () => void;
|
|
711
711
|
t: TranslationFunction;
|
|
712
712
|
}> = ({ car, mode, onOpenRateAdjust, onShowDetails, t }) => {
|
|
713
|
-
|
|
714
|
-
// here, which collapsed .cc-terms to 0 height on that tab while Financing/Leasing rendered a
|
|
715
|
-
// real line, jumping the price row (and everything below it: rating pill, CTA row) up/down on
|
|
716
|
-
// every tab switch. Render an empty, still-present .cc-terms div instead — same fix as the VDP
|
|
717
|
-
// FinanceCalculator's .fin-cond (md3.css), which reserves its line's height the same way.
|
|
718
|
-
if (mode === 'buy') return <div className="cc-terms" />;
|
|
713
|
+
if (mode === 'buy') return null;
|
|
719
714
|
const finFirstInstallment =
|
|
720
715
|
car.finFirstInstallment != null ? car.finFirstInstallment.toLocaleString('de-DE') : _finFirstInstallment;
|
|
721
716
|
const finMonths = car.finMonths ?? _finMonths;
|
package/constants/app.ts
CHANGED
|
@@ -40,17 +40,7 @@ export const LOCAL_STORAGE_KEY = {
|
|
|
40
40
|
i18n_KEY: 'i18nLanguage'
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
// SecurityError that took down the whole bundle. Blocked storage behaves like "nothing saved".
|
|
45
|
-
const readStoredLang = (): string | null => {
|
|
46
|
-
try {
|
|
47
|
-
return localStorage.getItem(LOCAL_STORAGE_KEY.i18n_KEY);
|
|
48
|
-
} catch (e) {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const DEFAULT_LANG: string = typeof window !== 'undefined' ? readStoredLang() : 'de';
|
|
43
|
+
export const DEFAULT_LANG: string = typeof window !== 'undefined' ? localStorage.getItem(LOCAL_STORAGE_KEY.i18n_KEY) : 'de';
|
|
54
44
|
|
|
55
45
|
// Default support contact phone
|
|
56
46
|
export const CONTACT_PHONE: string = '+498004030182';
|
package/constants/core.ts
CHANGED
|
@@ -35,18 +35,7 @@ export const LOCAL_STORAGE_KEY = {
|
|
|
35
35
|
i18n_KEY: 'i18nLanguage'
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
// window.localStorage throws a SecurityError, which took down the whole bundle (landing
|
|
40
|
-
// page never rendered). Treat blocked storage like "no language saved".
|
|
41
|
-
const readStoredLang = (): string | null => {
|
|
42
|
-
try {
|
|
43
|
-
return typeof window !== 'undefined' ? window.localStorage.getItem(LOCAL_STORAGE_KEY.i18n_KEY) : null;
|
|
44
|
-
} catch (e) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export const DEFAULT_LANG: string = readStoredLang() ?? 'de';
|
|
38
|
+
export const DEFAULT_LANG: string = (typeof window !== 'undefined' ? window.localStorage.getItem(LOCAL_STORAGE_KEY.i18n_KEY) : null) ?? 'de';
|
|
50
39
|
|
|
51
40
|
export const ROW_STYLES = {
|
|
52
41
|
marginBottom: 10
|
package/locales/de/autobahn.json
CHANGED
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"detailsShow": "Details anzeigen",
|
|
89
89
|
"paymentLabel": "Zahlung",
|
|
90
90
|
"paymentValue": "Überweisung",
|
|
91
|
-
"warrantyLabel": "
|
|
91
|
+
"warrantyLabel": "Zusatzgarantie (Multipart)",
|
|
92
92
|
"warrantyValue": "1 Jahr inklusive",
|
|
93
93
|
"deliveryLabel": "Lieferung",
|
|
94
94
|
"deliveryValue": "ca. 7–14 Tage · oder Abholung",
|
|
@@ -701,7 +701,7 @@
|
|
|
701
701
|
},
|
|
702
702
|
"modal": {
|
|
703
703
|
"leasingDetails": "Leasingdetails",
|
|
704
|
-
"financingDetails": "
|
|
704
|
+
"financingDetails": "Finanzierungsdetails",
|
|
705
705
|
"close": "Schließen",
|
|
706
706
|
"vehiclePrice": "Fahrzeugpreis ggf. inkl. MwSt.",
|
|
707
707
|
"leasingAmount": "Leasingbetrag",
|
package/locales/en/autobahn.json
CHANGED
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"detailsShow": "Show details",
|
|
89
89
|
"paymentLabel": "Payment",
|
|
90
90
|
"paymentValue": "Bank transfer",
|
|
91
|
-
"warrantyLabel": "
|
|
91
|
+
"warrantyLabel": "Additional warranty (Multipart)",
|
|
92
92
|
"warrantyValue": "1 year included",
|
|
93
93
|
"deliveryLabel": "Delivery",
|
|
94
94
|
"deliveryValue": "approx. 7–14 days · or collection",
|
package/locales/legacy/data.ts
CHANGED
|
@@ -103,8 +103,7 @@ export const vehicleProps = (car?: any, isOfferAvailable: boolean = true) => {
|
|
|
103
103
|
wltpDischargedCombinedLabel: `${getFormattedNumber(vehicleOption.wltpCombined != null ? vehicleOption.wltpCombined : 19.9)}l/100km (entladen, komb)`,
|
|
104
104
|
wltpCo2WtdCombinedShort: `${getFormattedNumber(vehicleOption.wltpCo2)}g CO2/km (gew., komb)*`,
|
|
105
105
|
co2ClassWeighted: `CO2-Klasse ${(cbd.cbd as any)[vehicleOption.wltpEnergyEfficiencyClass] || vehicleOption.wltpEnergyEfficiencyClass || ''} (gew., komb)`,
|
|
106
|
-
|
|
107
|
-
co2ClassDischarged: `CO2-Klasse ${(cbd.cbd as any)[vehicleOption.wltpDischargedEnergyEfficiencyClass] || vehicleOption.wltpDischargedEnergyEfficiencyClass || ''} (entladen, komb)`
|
|
106
|
+
co2ClassDischarged: `CO2-Klasse ${(cbd.cbd as any)[vehicleOption.wltpDischargedEnergyEfficiencyClass || 'selector_energyEfficiencyClass_g'] || ''} (entladen, komb)`
|
|
108
107
|
},
|
|
109
108
|
title: {
|
|
110
109
|
'addOfferToMainSlide': 'Zum Schieberegler hinzufügen',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bytebrand/fe-ui-core-autobahn",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.157",
|
|
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",
|
package/theme/md3.css
CHANGED
|
@@ -1822,6 +1822,14 @@ line-height: 31px;
|
|
|
1822
1822
|
gap: 8px;
|
|
1823
1823
|
flex-wrap: wrap;
|
|
1824
1824
|
}
|
|
1825
|
+
/* Figma 64860-62117 (Kaufen only): ground-truth design-context pull — "row" is gap-[14px]
|
|
1826
|
+
items-start, not the shared gap-8/align-center financing/leasing's own row keeps (base rule
|
|
1827
|
+
above, untouched) — the taller 2-row old-price stack (badge above struck price, see
|
|
1828
|
+
.cf-rate-old--buy below) needs top alignment against the big price instead of centering. */
|
|
1829
|
+
.md3 .cf-rate-row.cf-rate-row--buy {
|
|
1830
|
+
gap: 14px;
|
|
1831
|
+
align-items: flex-start;
|
|
1832
|
+
}
|
|
1825
1833
|
.md3 .cf-rate-amount {
|
|
1826
1834
|
font-family: 'Arial';
|
|
1827
1835
|
font-style: normal;
|
|
@@ -1830,6 +1838,16 @@ line-height: 31px;
|
|
|
1830
1838
|
line-height: 58px;
|
|
1831
1839
|
color: #005CFF;
|
|
1832
1840
|
}
|
|
1841
|
+
/* Figma 64860-62117 (Kaufen only): exact text spec pasted by user — Arimo/700/36px/100%
|
|
1842
|
+
line-height/-1.6px letter-spacing — smaller + tighter than the shared 54px Arial price
|
|
1843
|
+
financing/leasing keep (base rule above, untouched). 2-class selector scopes to
|
|
1844
|
+
.cf-rate-amount--buy only; the ≤600px rule further down already matches this 36px size. */
|
|
1845
|
+
.md3 .cf-rate-amount.cf-rate-amount--buy {
|
|
1846
|
+
font-family: 'Arimo';
|
|
1847
|
+
font-size: 36px;
|
|
1848
|
+
line-height: 100%;
|
|
1849
|
+
letter-spacing: -1.6px;
|
|
1850
|
+
}
|
|
1833
1851
|
.md3 .cf-rate-side {
|
|
1834
1852
|
display: flex;
|
|
1835
1853
|
flex-direction: column;
|
|
@@ -1856,6 +1874,51 @@ line-height: 31px;
|
|
|
1856
1874
|
color: #0E2238;
|
|
1857
1875
|
white-space: nowrap;
|
|
1858
1876
|
}
|
|
1877
|
+
/* Figma 64860-62117 (Kaufen only): ground-truth design-context pull ("uvp" node) — flex column
|
|
1878
|
+
(badge row stacked above the struck price, gap 1px), Arimo/700/15px/normal line-height/0
|
|
1879
|
+
letter-spacing/native line-through, color var(--semantic-error, #ba1a1a) — replaces the shared
|
|
1880
|
+
Arial/400/20px dark .cf-rate-old treatment financing/leasing's own isStrike price keeps
|
|
1881
|
+
untouched below. 2-class selector scopes this to .cf-rate-old--buy only. */
|
|
1882
|
+
.md3 .cf-rate-old.cf-rate-old--buy {
|
|
1883
|
+
display: flex;
|
|
1884
|
+
flex-direction: column;
|
|
1885
|
+
align-items: flex-start;
|
|
1886
|
+
gap: 1px;
|
|
1887
|
+
font-family: 'Arimo';
|
|
1888
|
+
font-weight: 700;
|
|
1889
|
+
font-size: 15px;
|
|
1890
|
+
line-height: normal;
|
|
1891
|
+
letter-spacing: 0;
|
|
1892
|
+
color: #BA1A1A;
|
|
1893
|
+
}
|
|
1894
|
+
/* line-through lives on .cf-rate-old-text (the price span) only, not the flex container above —
|
|
1895
|
+
a descendant's own text-decoration:none is NOT reliable for "undoing" an ancestor's decoration
|
|
1896
|
+
line (well-known CSS quirk: the line is drawn across the ancestor's whole inline content
|
|
1897
|
+
regardless), which was still drawing the strike through the badge's "2" one level up. */
|
|
1898
|
+
.md3 .cf-panel .cf-rate-old--buy .cf-rate-old-text {
|
|
1899
|
+
text-decoration: line-through;
|
|
1900
|
+
}
|
|
1901
|
+
/* replaces the custom red diagonal bar for Kaufen only — financing/leasing's own isStrike price
|
|
1902
|
+
keeps the shared ::after bar (base rule below, untouched). */
|
|
1903
|
+
.md3 .cf-rate-old.cf-rate-old--buy::after {
|
|
1904
|
+
display: none;
|
|
1905
|
+
}
|
|
1906
|
+
/* Same Figma frame ("footnote" node): a plain 13x13 ring in brand/primary, Arimo Regular 8px
|
|
1907
|
+
text-primary (#0e2238) — sits in normal flow as its own row above the struck price (the
|
|
1908
|
+
flex-column .cf-rate-old--buy above), not absolutely overlaid — scoped to .cf-rate-old--buy,
|
|
1909
|
+
financing/leasing's isStrike badge keeps the shared corner-overlay .pp-eyebrow-badge rule
|
|
1910
|
+
(top-right, bigger ring) untouched below. */
|
|
1911
|
+
.md3 .cf-panel .cf-rate-old--buy .pp-eyebrow-badge {
|
|
1912
|
+
position: static;
|
|
1913
|
+
width: 13px;
|
|
1914
|
+
height: 13px;
|
|
1915
|
+
font-family: 'Arimo';
|
|
1916
|
+
font-weight: 400;
|
|
1917
|
+
font-size: 8px;
|
|
1918
|
+
line-height: normal;
|
|
1919
|
+
border-width: 1px;
|
|
1920
|
+
color: #0E2238;
|
|
1921
|
+
}
|
|
1859
1922
|
/* must stay AFTER the base .cf-rate-amount/.cf-rate-old rules above — equal specificity means
|
|
1860
1923
|
source order decides the tie (same rule as the .co-form media query elsewhere in this file). */
|
|
1861
1924
|
@media (max-width: 600px) {
|
|
@@ -1968,6 +2031,20 @@ line-height: 31px;
|
|
|
1968
2031
|
gap: 6px;
|
|
1969
2032
|
}
|
|
1970
2033
|
}
|
|
2034
|
+
/* Figma 64860-62117 (Kaufen only): ground-truth "hero" node is a plain gap-[10px] row (price
|
|
2035
|
+
block + rating column packed together on the left), not the shared space-between push-to-
|
|
2036
|
+
far-edge financing/leasing's own hero row keeps (base rule above, untouched) — the 10px gap
|
|
2037
|
+
itself lives on .fin-eval-col--buy's margin-left just below, so this only cancels the
|
|
2038
|
+
space-between/gap-16 that would otherwise ADD to it. 2-class selector scopes to
|
|
2039
|
+
.cf-rate-top--buy; applies at every width (.fin-eval-col--buy's margin-left is the only
|
|
2040
|
+
intended gap, mobile included). */
|
|
2041
|
+
.md3 .cf-rate-top.cf-rate-top--buy {
|
|
2042
|
+
justify-content: flex-start;
|
|
2043
|
+
gap: 0;
|
|
2044
|
+
}
|
|
2045
|
+
.md3 .cf-panel .fin-eval-col.fin-eval-col--buy {
|
|
2046
|
+
margin-left: 10px;
|
|
2047
|
+
}
|
|
1971
2048
|
.md3 .cf-rate-left {
|
|
1972
2049
|
display: flex;
|
|
1973
2050
|
flex-direction: column;
|
|
@@ -1982,13 +2059,15 @@ line-height: 31px;
|
|
|
1982
2059
|
line-height: 15px;
|
|
1983
2060
|
color: #0E2238;
|
|
1984
2061
|
}
|
|
1985
|
-
/* Kaufen's compact "Überweisung ·
|
|
1986
|
-
desktop
|
|
1987
|
-
(.cf-buy-info)
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2062
|
+
/* Kaufen's compact "Überweisung · sofort verfügbar" recap — Figma 64860-62117 renders it
|
|
2063
|
+
unconditionally (desktop AND mobile) right under the price, alongside the separate Zahlung/
|
|
2064
|
+
Zusatzgarantie/Verfügbar rows further down (.cf-buy-info) — previously hidden on desktop
|
|
2065
|
+
(show-mobile) on the wrong assumption that it only duplicated those rows; removed from JSX.
|
|
2066
|
+
5px (ground-truth "Rate" column gap) replaces the shared 10px .co-aside-cond gap financing/
|
|
2067
|
+
leasing's own cond line keeps (base rule above, untouched) — was mobile-only before; Figma's
|
|
2068
|
+
same frame carries this gap at any width, so it's no longer scoped to the ≤600px query. */
|
|
2069
|
+
.md3 .cf-panel .co-aside-cond.co-aside-cond--buy {
|
|
2070
|
+
margin-top: 5px;
|
|
1992
2071
|
}
|
|
1993
2072
|
/* .fin-eval-col's shared base rule is `display: contents` (a CSS-grid trick that relies on a
|
|
1994
2073
|
`.fin-price-grid` grid ancestor with named areas — cf-panel isn't a grid), so it needs the
|
|
@@ -1999,6 +2078,10 @@ line-height: 31px;
|
|
|
1999
2078
|
gap: 8px;
|
|
2000
2079
|
flex: none;
|
|
2001
2080
|
align-items: stretch;
|
|
2081
|
+
/* Figma 64860-62117: fixed 106px column so the pill (below, display:flex + align-items:
|
|
2082
|
+
stretch cascading down) and the bar (already width:100%) both span the same width instead
|
|
2083
|
+
of shrink-wrapping to whichever tier label happens to be widest. */
|
|
2084
|
+
width: 106px;
|
|
2002
2085
|
}
|
|
2003
2086
|
@media (max-width: 600px) {
|
|
2004
2087
|
.md3 .cf-panel .fin-eval-col {
|
|
@@ -2201,6 +2284,31 @@ line-height: 31px;
|
|
|
2201
2284
|
width: 40px;
|
|
2202
2285
|
height: 40px;
|
|
2203
2286
|
}
|
|
2287
|
+
/* Rundum-Sorglos-Paket title "i" popover — same reasoning/pattern as the .cf-toggle override
|
|
2288
|
+
above (inherited rule is tuned for the small UVP-Rate footnote badge, top:16px/left:0/
|
|
2289
|
+
width:260px): left:0 was relative to the title's own 20px padding box, bleeding the popover
|
|
2290
|
+
past the card's left border. left:20px nudges it to align with the title's own content edge
|
|
2291
|
+
instead (close to the original 260px width — a full left:0/right:0/width:auto span was tried
|
|
2292
|
+
and was too wide/plain). right:20px + max-width is the mobile safety net: on a narrow card it
|
|
2293
|
+
shrinks instead of overflowing; on a normal-width card max-width wins and the box just sits
|
|
2294
|
+
280px wide, anchored at left:20px (CSS over-constrained resolution recalculates the unused
|
|
2295
|
+
"right" rather than stretching). 3 class-selectors deep so it always wins over the 2-deep base
|
|
2296
|
+
rule regardless of source order. */
|
|
2297
|
+
.md3 .cf-panel .co-card-title .pp-uvp-tooltip {
|
|
2298
|
+
top: 28px;
|
|
2299
|
+
left: 40px;
|
|
2300
|
+
right: 20px;
|
|
2301
|
+
width: auto;
|
|
2302
|
+
max-width: 280px;
|
|
2303
|
+
}
|
|
2304
|
+
/* same box, narrower safety margin so the 280px cap still comfortably fits a phone-width card
|
|
2305
|
+
instead of being cut flush against the right edge. */
|
|
2306
|
+
@media (max-width: 600px) {
|
|
2307
|
+
.md3 .cf-panel .co-card-title .pp-uvp-tooltip {
|
|
2308
|
+
left: 20px;
|
|
2309
|
+
right: 12px;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2204
2312
|
.md3 .cf-toggle .md-title-sm {
|
|
2205
2313
|
display: inline-flex;
|
|
2206
2314
|
align-items: center;
|
|
@@ -2212,6 +2320,14 @@ line-height: 31px;
|
|
|
2212
2320
|
line-height: 15px;
|
|
2213
2321
|
color: #1A1B22;
|
|
2214
2322
|
}
|
|
2323
|
+
/* Rundum-Sorglos-Paket's toggle label should read the same size as the Zahlung/Zusatzgarantie/
|
|
2324
|
+
Verfügbarkeit rows above it (.cf-buy-info .calcrow-label, 15px/17px) — .cf-panel scopes this to
|
|
2325
|
+
CheckoutFinancePanelNext only, leaving AdditionalServicesNext's unrelated .co-rundum-footer
|
|
2326
|
+
.cf-toggle (step 4) at its own 13px untouched. */
|
|
2327
|
+
.md3 .cf-panel .cf-toggle .md-title-sm {
|
|
2328
|
+
font-size: 15px;
|
|
2329
|
+
line-height: 17px;
|
|
2330
|
+
}
|
|
2215
2331
|
.md3 .cf-toggle .md-title-sm svg {
|
|
2216
2332
|
cursor: pointer;
|
|
2217
2333
|
}
|
|
@@ -2515,6 +2631,12 @@ line-height: 31px;
|
|
|
2515
2631
|
padding: 14px 20px;
|
|
2516
2632
|
border-bottom: 1px solid #C5C6D2;
|
|
2517
2633
|
}
|
|
2634
|
+
/* Kaufen: .co-rundum-footer (the "in die Rate einrechnen" toggle) isn't rendered at all, so
|
|
2635
|
+
.co-rundum-box is the card's last element — the border-bottom above would just be a dangling
|
|
2636
|
+
line with nothing below it. */
|
|
2637
|
+
.md3 .cf-panel .co-rundum-box.co-rundum-box--buy {
|
|
2638
|
+
border-bottom: 0;
|
|
2639
|
+
}
|
|
2518
2640
|
.md3 .cf-panel .co-rundum-footer {
|
|
2519
2641
|
padding: 14px 20px;
|
|
2520
2642
|
}
|
|
@@ -4565,6 +4687,23 @@ line-height: 31px;
|
|
|
4565
4687
|
justify-content: space-between;
|
|
4566
4688
|
gap: 10px;
|
|
4567
4689
|
}
|
|
4690
|
+
/* "2. Rechnungsadresse" / "3. Lieferadresse" (.oo-addr-grid's two cards only — the shared 10px
|
|
4691
|
+
above still fits "Lieferung & Services"/Zahldetails fine, which have a whole row to themselves)
|
|
4692
|
+
— the base gap left too little room for "Rechnungsadresse" next to "Ändern" in the half-width
|
|
4693
|
+
grid column, wrapping the title to 2 lines. align-items: center (inherited from the base rule
|
|
4694
|
+
above) only centers against the FULL flex-row height, so while wrapped it centered "Ändern"
|
|
4695
|
+
against both title lines instead of matching the first one. */
|
|
4696
|
+
.md3 .oo-addr-grid .oo-card-title--action {
|
|
4697
|
+
gap: 4px;
|
|
4698
|
+
}
|
|
4699
|
+
/* The button has no explicit line-height, so the UA default ("normal", ~1.15-1.2x its 13px font)
|
|
4700
|
+
gives it a taller box than its own glyphs — align-items: center then centers that whole taller
|
|
4701
|
+
box against the title's 23px line-height box, landing "Ändern"'s visible text a bit low. line-
|
|
4702
|
+
height: 1 collapses the button's box to its font-size itself, so both sides center on their
|
|
4703
|
+
actual text instead of on mismatched leading. */
|
|
4704
|
+
.md3 .oo-addr-grid .oo-card-action {
|
|
4705
|
+
line-height: 1;
|
|
4706
|
+
}
|
|
4568
4707
|
.md3 .oo-card-action {
|
|
4569
4708
|
font-family: Arial;
|
|
4570
4709
|
font-weight: 700;
|
|
@@ -4677,6 +4816,49 @@ line-height: 31px;
|
|
|
4677
4816
|
border-left: 0 !important;
|
|
4678
4817
|
}
|
|
4679
4818
|
}
|
|
4819
|
+
/* "2 Jahre Garantie" "i" popover (OrderOverviewNext.tsx) — same AddServicesTooltipBody/
|
|
4820
|
+
pp-uvp-tooltip markup as step 3's title info trigger, but there's no .cf-panel ancestor here to
|
|
4821
|
+
inherit the shared "grey card" look from, so the full style (not just a position override) is
|
|
4822
|
+
defined fresh under .oo-ls-title-row. Anchored right:0 (the garantie cell is the row's last/
|
|
4823
|
+
rightmost of 3) so the box opens leftward instead of overflowing past the card's right edge;
|
|
4824
|
+
max-width keeps it inside a narrow phone screen once .oo-ls-row stacks to full width below. */
|
|
4825
|
+
.md3 .oo-ls-title-row .pp-uvp-tooltip {
|
|
4826
|
+
position: absolute;
|
|
4827
|
+
top: 24px;
|
|
4828
|
+
left: auto;
|
|
4829
|
+
right: 0;
|
|
4830
|
+
z-index: 20;
|
|
4831
|
+
width: 300px;
|
|
4832
|
+
max-width: calc(100vw - 48px);
|
|
4833
|
+
padding: 10px 12px;
|
|
4834
|
+
border-radius: 15px;
|
|
4835
|
+
background: #c5c6d2;
|
|
4836
|
+
box-shadow: var(--md-e2, 0 4px 12px rgba(0, 0, 0, 0.15));
|
|
4837
|
+
white-space: normal;
|
|
4838
|
+
cursor: default;
|
|
4839
|
+
}
|
|
4840
|
+
.md3 .oo-ls-title-row .pp-uvp-tooltip-close {
|
|
4841
|
+
position: absolute;
|
|
4842
|
+
top: -14px;
|
|
4843
|
+
right: -14px;
|
|
4844
|
+
display: flex;
|
|
4845
|
+
align-items: center;
|
|
4846
|
+
justify-content: center;
|
|
4847
|
+
width: 26px;
|
|
4848
|
+
height: 26px;
|
|
4849
|
+
border-radius: 50%;
|
|
4850
|
+
background: rgba(11, 19, 32, 0.55);
|
|
4851
|
+
border: 1.5px solid rgba(255, 255, 255, 0.25);
|
|
4852
|
+
padding: 0;
|
|
4853
|
+
cursor: pointer;
|
|
4854
|
+
}
|
|
4855
|
+
.md3 .oo-ls-title-row .pp-uvp-tooltip-body {
|
|
4856
|
+
font-family: 'Arimo';
|
|
4857
|
+
font-weight: 400;
|
|
4858
|
+
font-size: 11px;
|
|
4859
|
+
line-height: 13px;
|
|
4860
|
+
color: #0e2238;
|
|
4861
|
+
}
|
|
4680
4862
|
/* "5. Monatlich zu zahlen" / "5. Gesamtpreis" (Figma: Finanzierung 64763:107263, Leasing
|
|
4681
4863
|
64794:110315, Kaufen 64794:109673) — own "oo-pay-*" namespace, NOT the shared
|
|
4682
4864
|
.cf-rate-row/.fin-eval-* classes CheckoutFinancePanelNext.tsx (step 3) uses: that component
|
|
@@ -4700,12 +4882,55 @@ line-height: 31px;
|
|
|
4700
4882
|
width: 100%;
|
|
4701
4883
|
}
|
|
4702
4884
|
.md3 .oo-pay-price-row {
|
|
4885
|
+
position: relative;
|
|
4703
4886
|
display: flex;
|
|
4704
4887
|
align-items: center;
|
|
4705
4888
|
justify-content: space-between;
|
|
4706
4889
|
gap: 16px;
|
|
4707
4890
|
width: 100%;
|
|
4708
4891
|
}
|
|
4892
|
+
/* UVP footnote popover (both the Buy "②" and the Financing/Leasing "UVP-Rate ③" branches above —
|
|
4893
|
+
oo-pay-buy-uvp-row and oo-pay-secondary respectively, both descendants of this row) — same
|
|
4894
|
+
"grey card" pp-uvp-tooltip look step 3's .cf-panel scope and order-overview's own
|
|
4895
|
+
.oo-ls-title-row scope already give it, but nothing scoped it under this card's own oo-pay-*
|
|
4896
|
+
namespace, so it rendered as plain unstyled text. position:relative lives on this shared
|
|
4897
|
+
ancestor (not each branch's own element) since one rule here covers both. */
|
|
4898
|
+
.md3 .oo-pay-price-row .pp-uvp-tooltip {
|
|
4899
|
+
position: absolute;
|
|
4900
|
+
top: 28px;
|
|
4901
|
+
left: 0;
|
|
4902
|
+
z-index: 20;
|
|
4903
|
+
width: 300px;
|
|
4904
|
+
max-width: calc(100vw - 48px);
|
|
4905
|
+
padding: 10px 12px;
|
|
4906
|
+
border-radius: 15px;
|
|
4907
|
+
background: #c5c6d2;
|
|
4908
|
+
box-shadow: var(--md-e2, 0 4px 12px rgba(0, 0, 0, 0.15));
|
|
4909
|
+
white-space: normal;
|
|
4910
|
+
cursor: default;
|
|
4911
|
+
}
|
|
4912
|
+
.md3 .oo-pay-price-row .pp-uvp-tooltip-close {
|
|
4913
|
+
position: absolute;
|
|
4914
|
+
top: -14px;
|
|
4915
|
+
right: -14px;
|
|
4916
|
+
display: flex;
|
|
4917
|
+
align-items: center;
|
|
4918
|
+
justify-content: center;
|
|
4919
|
+
width: 26px;
|
|
4920
|
+
height: 26px;
|
|
4921
|
+
border-radius: 50%;
|
|
4922
|
+
background: rgba(11, 19, 32, 0.55);
|
|
4923
|
+
border: 1.5px solid rgba(255, 255, 255, 0.25);
|
|
4924
|
+
padding: 0;
|
|
4925
|
+
cursor: pointer;
|
|
4926
|
+
}
|
|
4927
|
+
.md3 .oo-pay-price-row .pp-uvp-tooltip-body {
|
|
4928
|
+
font-family: 'Arimo';
|
|
4929
|
+
font-weight: 400;
|
|
4930
|
+
font-size: 11px;
|
|
4931
|
+
line-height: 13px;
|
|
4932
|
+
color: #0e2238;
|
|
4933
|
+
}
|
|
4709
4934
|
.md3 .oo-pay-left {
|
|
4710
4935
|
display: flex;
|
|
4711
4936
|
align-items: center;
|
|
@@ -4835,9 +5060,13 @@ line-height: 31px;
|
|
|
4835
5060
|
align-items: flex-end;
|
|
4836
5061
|
gap: 2px;
|
|
4837
5062
|
}
|
|
5063
|
+
/* Figma 64794-109673 "secondaryStack": items-start, not center — the footnote badge (now a
|
|
5064
|
+
direct sibling of .oo-pay-uvp-amount, moved out so the struck price's own ::after bar doesn't
|
|
5065
|
+
draw its strike across the badge too) sits top-aligned/raised next to the price instead of
|
|
5066
|
+
vertically centered against it. */
|
|
4838
5067
|
.md3 .oo-pay-buy-uvp-row {
|
|
4839
5068
|
display: flex;
|
|
4840
|
-
align-items:
|
|
5069
|
+
align-items: flex-start;
|
|
4841
5070
|
gap: 2px;
|
|
4842
5071
|
}
|
|
4843
5072
|
.md3 .oo-pay-buy-leftgroup {
|
|
@@ -165,10 +165,7 @@ const getDecoratedLightProps = (
|
|
|
165
165
|
if (hybridPlugin) {
|
|
166
166
|
if (wltpWeightedPowerCombinedContent && wltpWeightedCombinedContent) {
|
|
167
167
|
const dischargedCombined = Number.isFinite(wltpConsumptionCombined) ? wltpConsumptionCombined : 19.9;
|
|
168
|
-
|
|
169
|
-
// backend could not derive it the field is selector_unknown — hide the segment, never
|
|
170
|
-
// fall back to a hard-coded class here.
|
|
171
|
-
const dischargedClass = car.environmentEmissions.wltpDischargedEnergyEfficiencyClass;
|
|
168
|
+
const dischargedClass = car.environmentEmissions.wltpDischargedEnergyEfficiencyClass || 'selector_energyEfficiencyClass_g';
|
|
172
169
|
const weightedCombinedLabeled = t('vehicleProps:value.wltpWeightedCombinedLabel', { consumption: wltpWeightedCombined.toLocaleString(language), unit: translatedUnit });
|
|
173
170
|
const dischargedCombinedLabeled = t('vehicleProps:value.wltpDischargedCombinedLabel', { consumption: dischargedCombined.toLocaleString(language), unit: translatedUnit });
|
|
174
171
|
const co2WeightedContent = Number.isFinite(wltpCo2)
|
|
@@ -177,16 +174,14 @@ const getDecoratedLightProps = (
|
|
|
177
174
|
const co2ClassWeighted = isPropDefined(wltpEnergyEfficiencyClass)
|
|
178
175
|
? t('vehicleProps:value.co2ClassWeighted', { class: t(`cbd:${wltpEnergyEfficiencyClass}`) })
|
|
179
176
|
: null;
|
|
180
|
-
const co2ClassDischarged =
|
|
181
|
-
? t('vehicleProps:value.co2ClassDischarged', { class: t(`cbd:${dischargedClass}`) })
|
|
182
|
-
: null;
|
|
177
|
+
const co2ClassDischarged = t('vehicleProps:value.co2ClassDischarged', { class: t(`cbd:${dischargedClass}`) });
|
|
183
178
|
return <React.Fragment>
|
|
184
179
|
{`${wltpWeightedPowerCombinedContent} + `}
|
|
185
180
|
{`${weightedCombinedLabeled}, `}
|
|
186
181
|
{`${dischargedCombinedLabeled}`}
|
|
187
182
|
{co2WeightedContent && <>, {co2WeightedContent}</>}
|
|
188
183
|
{co2ClassWeighted && <>, {co2ClassWeighted}</>}
|
|
189
|
-
{
|
|
184
|
+
{<>, {co2ClassDischarged}</>}
|
|
190
185
|
</React.Fragment>
|
|
191
186
|
}
|
|
192
187
|
|
|
@@ -321,10 +316,7 @@ const getDecoratedLightProps = (
|
|
|
321
316
|
if (hybridPlugin) {
|
|
322
317
|
if (wltpWeightedPowerCombinedContent && wltpWeightedCombinedContent) {
|
|
323
318
|
const dischargedCombined = Number.isFinite(wltpConsumptionCombined) ? wltpConsumptionCombined : 19.9;
|
|
324
|
-
|
|
325
|
-
// backend could not derive it the field is selector_unknown — hide the segment, never
|
|
326
|
-
// fall back to a hard-coded class here.
|
|
327
|
-
const dischargedClass = car.environmentEmissions.wltpDischargedEnergyEfficiencyClass;
|
|
319
|
+
const dischargedClass = car.environmentEmissions.wltpDischargedEnergyEfficiencyClass || 'selector_energyEfficiencyClass_g';
|
|
328
320
|
const weightedCombinedLabeled = t('vehicleProps:value.wltpWeightedCombinedLabel', { consumption: wltpWeightedCombined.toLocaleString(language), unit: translatedUnit });
|
|
329
321
|
const dischargedCombinedLabeled = t('vehicleProps:value.wltpDischargedCombinedLabel', { consumption: dischargedCombined.toLocaleString(language), unit: translatedUnit });
|
|
330
322
|
const co2WeightedContent = Number.isFinite(wltpCo2)
|
|
@@ -333,16 +325,14 @@ const getDecoratedLightProps = (
|
|
|
333
325
|
const co2ClassWeighted = isPropDefined(wltpEnergyEfficiencyClass)
|
|
334
326
|
? t('vehicleProps:value.co2ClassWeighted', { class: t(`cbd:${wltpEnergyEfficiencyClass}`) })
|
|
335
327
|
: null;
|
|
336
|
-
const co2ClassDischarged =
|
|
337
|
-
? t('vehicleProps:value.co2ClassDischarged', { class: t(`cbd:${dischargedClass}`) })
|
|
338
|
-
: null;
|
|
328
|
+
const co2ClassDischarged = t('vehicleProps:value.co2ClassDischarged', { class: t(`cbd:${dischargedClass}`) });
|
|
339
329
|
return <React.Fragment>
|
|
340
330
|
{`${wltpWeightedPowerCombinedContent} + `}
|
|
341
331
|
{`${weightedCombinedLabeled}, `}
|
|
342
332
|
{`${dischargedCombinedLabeled}`}
|
|
343
333
|
{co2WeightedContent && <>, {co2WeightedContent}</>}
|
|
344
334
|
{co2ClassWeighted && <>, {co2ClassWeighted}</>}
|
|
345
|
-
{
|
|
335
|
+
{<>, {co2ClassDischarged}</>}
|
|
346
336
|
</React.Fragment>
|
|
347
337
|
}
|
|
348
338
|
|
|
@@ -880,12 +880,10 @@ const getDecoratedProps = (
|
|
|
880
880
|
// (entladen, komb) fuel consumption + a discharged CO2 class.
|
|
881
881
|
if (hybridPlugin && wltpConsumptionWeightedPowerCombinedContent && wltpConsumptionWeightedCombinedContent) {
|
|
882
882
|
const ADV88_DEFAULT_DISCHARGED_COMBINED = 19.9;
|
|
883
|
+
const ADV88_DEFAULT_DISCHARGED_CO2_CLASS = 'selector_energyEfficiencyClass_g';
|
|
883
884
|
|
|
884
885
|
const dischargedCombined = Number.isFinite(wltpCombined) ? wltpCombined : ADV88_DEFAULT_DISCHARGED_COMBINED;
|
|
885
|
-
|
|
886
|
-
// backend could not derive it the field is selector_unknown — hide the segment, never
|
|
887
|
-
// fall back to a hard-coded class here.
|
|
888
|
-
const dischargedClass = car.environmentEmissions.wltpDischargedEnergyEfficiencyClass;
|
|
886
|
+
const dischargedClass = car.environmentEmissions.wltpDischargedEnergyEfficiencyClass || ADV88_DEFAULT_DISCHARGED_CO2_CLASS;
|
|
889
887
|
|
|
890
888
|
const weightedCombinedLabeled = t('vehicleProps:value.wltpWeightedCombinedLabel', { consumption: wltpWeightedCombined.toLocaleString(language), unit: translatedUnit });
|
|
891
889
|
const dischargedCombinedLabeled = t('vehicleProps:value.wltpDischargedCombinedLabel', { consumption: dischargedCombined.toLocaleString(language), unit: translatedUnit });
|
|
@@ -895,9 +893,7 @@ const getDecoratedProps = (
|
|
|
895
893
|
const co2ClassWeighted = isPropDefined(wltpEnergyEfficiencyClass)
|
|
896
894
|
? t('vehicleProps:value.co2ClassWeighted', { class: t(`cbd:${wltpEnergyEfficiencyClass}`) })
|
|
897
895
|
: null;
|
|
898
|
-
const co2ClassDischarged =
|
|
899
|
-
? t('vehicleProps:value.co2ClassDischarged', { class: t(`cbd:${dischargedClass}`) })
|
|
900
|
-
: null;
|
|
896
|
+
const co2ClassDischarged = t('vehicleProps:value.co2ClassDischarged', { class: t(`cbd:${dischargedClass}`) });
|
|
901
897
|
|
|
902
898
|
return <React.Fragment>
|
|
903
899
|
{wrapValue(wltpConsumptionWeightedPowerCombinedContent)}{' + '}
|
|
@@ -905,7 +901,7 @@ const getDecoratedProps = (
|
|
|
905
901
|
{wrapValue(dischargedCombinedLabeled)}
|
|
906
902
|
{co2WeightedContent && <>{', '}{wrapValue(co2WeightedContent)}</>}
|
|
907
903
|
{co2ClassWeighted && <>{', '}{co2ClassWeighted}</>}
|
|
908
|
-
{
|
|
904
|
+
{', '}{co2ClassDischarged}
|
|
909
905
|
</React.Fragment>
|
|
910
906
|
}
|
|
911
907
|
|