diff --git a/hifi-src/src/i18n/de.js b/hifi-src/src/i18n/de.js index b3c71f9..ca1660d 100644 --- a/hifi-src/src/i18n/de.js +++ b/hifi-src/src/i18n/de.js @@ -156,15 +156,6 @@ export default { requestContact: 'Kontakt anfragen', featuredBadge: 'Empfohlen', tierLabels: ['Einstieg', 'Upgrade', 'Performance', 'Premium', 'High-End', 'Signature', 'Referenz'], - tierDescriptions: [ - 'Solider Sound und spürbare Verbesserung für jeden Tag.', - 'Mehr Klarheit und Dynamik für ein intensiveres Hörerlebnis.', - 'Spürbar mehr Leistung und Kontrolle für echte Fahrfreude.', - 'Premium-Komponenten perfekt abgestimmt für höchste Ansprüche.', - 'High-End Performance und individuelle Abstimmung auf höchstem Niveau.', - 'Maßgeschneiderte Lösungen und einzigartige Integration für Kenner.', - 'Außergewöhnliche Projekte. Grenzenlos in Technik und Design.', - ], tiersHeading: (count) => `${count} Stufen. Ein Ziel: perfekter Klang.`, tiersSubheading: 'Von der soliden Basis bis zum kompromisslosen Meisterwerk – finde dein Paket.', }, diff --git a/hifi-src/src/i18n/en.js b/hifi-src/src/i18n/en.js index f9135d6..08eaf48 100644 --- a/hifi-src/src/i18n/en.js +++ b/hifi-src/src/i18n/en.js @@ -156,15 +156,6 @@ export default { requestContact: 'Request contact', featuredBadge: 'Recommended', tierLabels: ['Entry', 'Upgrade', 'Performance', 'Premium', 'High-End', 'Signature', 'Reference'], - tierDescriptions: [ - 'Solid sound and a noticeable improvement for every day.', - 'More clarity and dynamics for a richer listening experience.', - 'Noticeably more power and control for real driving enjoyment.', - 'Premium components perfectly tuned for the highest demands.', - 'High-end performance and individual tuning at the highest level.', - 'Tailored solutions and unique integration for connoisseurs.', - 'Exceptional projects. Limitless in technology and design.', - ], tiersHeading: (count) => `${count} tiers. One goal: perfect sound.`, tiersSubheading: 'From a solid foundation to an uncompromising masterpiece – find your package.', }, diff --git a/hifi-src/src/pages/public/ModelPage.jsx b/hifi-src/src/pages/public/ModelPage.jsx index 14d3bf4..51011d7 100644 --- a/hifi-src/src/pages/public/ModelPage.jsx +++ b/hifi-src/src/pages/public/ModelPage.jsx @@ -48,10 +48,6 @@ const PACKAGE_THEMES = { ], }; -// Ein Icon je Kategorie-Stufe (nicht pro Paket - siehe tierLabels), fuer die erklaerende -// Legende unter der Kachel-Reihe. Reihenfolge muss zu modelPage.tierLabels passen. -const TIER_ICONS = ['route', 'activity', 'gauge', 'shield-check', 'gem', 'crown', 'star']; - const hslToRgb = (h, s, l) => { s /= 100; l /= 100; @@ -130,15 +126,6 @@ export default function ModelPage() { // oben. Das braucht keine zusaetzliche Admin-Einstellung und passt sich automatisch // an jede Paketanzahl an. const tierLabels = t('modelPage.tierLabels'); - const tierDescriptions = t('modelPage.tierDescriptions'); - // Erklaerende Legende unter den Karten: ein Eintrag je Kategorie-Stufe (nicht je Paket), - // Akzentfarbe an einem repraesentativen Punkt der jeweiligen Kategorie-Spanne entnommen, - // damit die Legende farblich zu den Karten oben passt. - const tierLegend = tierLabels.map((label, i) => { - const legendT = (i + 0.5) / tierLabels.length; - const accentRgb = materialRgbAt(MATERIALS, legendT, 'accent').map(Math.round); - return { label, description: tierDescriptions[i], icon: TIER_ICONS[i], color: `rgb(${accentRgb.join(', ')})` }; - }); const rankById = new Map( [...packages].sort((a, b) => a.total_price - b.total_price).map((p, i) => [p.id, i]) ); @@ -172,6 +159,10 @@ export default function ModelPage() { // gleicher Helligkeit wie der Hintergrund landen und unsichtbar werden koennte. const mutedColor = `rgb(${hslToRgb(0, 0, contrastingL(38)).join(', ')})`; const glowAlpha = (0.1 + tierT * 0.3).toFixed(2); + // Der "Lichtweg" im Kartenhintergrund faengt bei der Einstiegsstufe kaum sichtbar an + // und wird zur teuersten Stufe hin kraeftiger/leuchtender - genau wie der Rahmen-Glow. + const roadOpacity = 0.14 + tierT * 0.22; + const roadGlowOpacity = 0.15 + tierT * 0.55; // Leichter "Lichtschein" von oben rechts statt flacher Flaeche - kommt von oben // rechts, weil dort nie Text steht (Titel/Preis/Liste sind linksbuendig), damit die @@ -184,6 +175,8 @@ export default function ModelPage() { tierLabel, accentColor: `rgb(${accentRgb.join(', ')})`, priceColor: `rgb(${priceRgb.join(', ')})`, + roadOpacity, + roadGlowOpacity, iconChipStyle: { backgroundColor: `rgba(${accentRgb.join(', ')}, 0.16)`, color: `rgb(${priceRgb.join(', ')})`, @@ -248,95 +241,124 @@ export default function ModelPage() {
{packages.map((pkg) => { - const { style, priceColor, mutedColor, iconChipStyle, tierNumber, tierLabel, accentColor, glowLineStyle } = - styleOf(pkg); + const { + style, + priceColor, + mutedColor, + iconChipStyle, + tierNumber, + tierLabel, + accentColor, + glowLineStyle, + roadOpacity, + roadGlowOpacity, + } = styleOf(pkg); return ( -
+
+ {/* Abstrakter "Lichtweg" im Hintergrund - je teurer die Stufe, desto praesenter/leuchtender. + Fixe Aspect-Ratio + "slice" statt "none", damit Strich/Kurve bei jeder Kartenhoehe + gleichmaessig aussieht statt verzerrt gestreckt zu werden. */} + + {pkg.is_featured && ( - + {t('modelPage.featuredBadge')} )} -
- - {tierNumber} - - - {tierLabel} - -
- - {pkg.icon_name && ( -
- + {/* Eigener Stapelkontext ueber dem Lichtweg-SVG, damit der Text IMMER lesbar + oben liegt statt vom absolut positionierten Hintergrund verdeckt zu werden. */} +
+
+ + {tierNumber} + + + {tierLabel} +
- )} -

{pkg.name}

- {pkg.tagline && ( -

- {pkg.tagline} -

- )} + {pkg.icon_name && ( +
+ +
+ )} -
+

{pkg.name}

+ {pkg.tagline && ( +

+ {pkg.tagline} +

+ )} -
-

- {t('modelPage.totalPrice')} -

-

- {formatPrice(pkg.total_price)} -

-
+
-
    - {pkg.products.map((product) => ( -
  • - - - {product.name_override || product.scraped_name || t('modelPage.productLoading')} - -
  • - ))} - {pkg.description - ?.split('\n') - .map((line) => line.trim()) - .filter(Boolean) - .map((line, i) => ( -
  • +
    +

    + {t('modelPage.totalPrice')} +

    +

    + {formatPrice(pkg.total_price)} +

    +
    + +
      + {pkg.products.map((product) => ( +
    • - {line} + {product.name_override || product.scraped_name || t('modelPage.productLoading')}
    • ))} -
    + {pkg.description + ?.split('\n') + .map((line) => line.trim()) + .filter(Boolean) + .map((line, i) => ( +
  • + + + {line} + +
  • + ))} +
- - {t('modelPage.requestContact')} - + + {t('modelPage.requestContact')} + +
); })}
- -
- {tierLegend.map((item) => ( -
- -

- {item.label} -

-

{item.description}

-
- ))} -
)}