Content Rewrite
This commit is contained in:
@@ -10,9 +10,35 @@
|
||||
export let pageContent: ServicePageContent;
|
||||
export let currentPath = '';
|
||||
|
||||
function numericPrice(price: string) {
|
||||
const value = Number(price.replace(/[^0-9.]/g, ''));
|
||||
return Number.isFinite(value) ? value : Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
function decoratePlans<T extends { price: string }>(plans: T[]) {
|
||||
const sorted = [...plans]
|
||||
.map((plan, index) => ({ plan, index, value: numericPrice(plan.price) }))
|
||||
.sort((a, b) => a.value - b.value || a.index - b.index);
|
||||
|
||||
const cheapestIndex = sorted[0]?.index ?? -1;
|
||||
const mobileOrder = new Map(sorted.map((entry, order) => [entry.index, order]));
|
||||
|
||||
return plans.map((plan, index) => ({
|
||||
...plan,
|
||||
isPopular: index === cheapestIndex,
|
||||
mobileOrder: mobileOrder.get(index) ?? index
|
||||
}));
|
||||
}
|
||||
|
||||
$: heroImage = getImageMetadata(pageContent.hero.imageUrl);
|
||||
$: highlightImage = pageContent.highlight ? getImageMetadata(pageContent.highlight.imageUrl) : null;
|
||||
$: highlightCollageImages =
|
||||
pageContent.highlight?.collageImages?.map((image) => ({
|
||||
...image,
|
||||
meta: getImageMetadata(image.imageUrl)
|
||||
})) ?? [];
|
||||
$: relatedServices = content.services.filter((s) => s.href && s.href !== currentPath);
|
||||
$: pricingPlans = decoratePlans(pageContent.pricing.plans);
|
||||
|
||||
$: relatedCards = [
|
||||
...relatedServices.map((s) => ({
|
||||
@@ -68,16 +94,33 @@
|
||||
</div>
|
||||
|
||||
<div class="service-inner">
|
||||
<div class="service-highlight-image">
|
||||
<img
|
||||
src={pageContent.highlight.imageUrl}
|
||||
alt={pageContent.highlight.imageAlt}
|
||||
width={highlightImage?.width}
|
||||
height={highlightImage?.height}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</div>
|
||||
{#if highlightCollageImages.length}
|
||||
<div class="service-highlight-collage" aria-label={pageContent.highlight.title}>
|
||||
{#each highlightCollageImages as image, index}
|
||||
<figure class={`service-collage-card service-collage-card-${index + 1}`}>
|
||||
<img
|
||||
src={image.imageUrl}
|
||||
alt={image.imageAlt}
|
||||
width={image.meta?.width}
|
||||
height={image.meta?.height}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</figure>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="service-highlight-image">
|
||||
<img
|
||||
src={pageContent.highlight.imageUrl}
|
||||
alt={pageContent.highlight.imageAlt}
|
||||
width={highlightImage?.width}
|
||||
height={highlightImage?.height}
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
@@ -92,9 +135,13 @@
|
||||
</div>
|
||||
|
||||
<div class:service-plan-grid-three={pageContent.pricing.plans.length === 3} class="service-plan-grid">
|
||||
{#each pageContent.pricing.plans as plan}
|
||||
<article class:service-plan-popular={plan.popular} class="service-plan-card">
|
||||
{#if plan.popular}
|
||||
{#each pricingPlans as plan}
|
||||
<article
|
||||
class:service-plan-popular={plan.isPopular}
|
||||
class="service-plan-card"
|
||||
style={`--mobile-order:${plan.mobileOrder};`}
|
||||
>
|
||||
{#if plan.isPopular}
|
||||
<span class="service-plan-ribbon">Popular</span>
|
||||
{/if}
|
||||
|
||||
@@ -263,11 +310,11 @@
|
||||
}
|
||||
|
||||
.service-related-tint-1 {
|
||||
--card-accent: var(--green);
|
||||
--card-accent: var(--gw-green);
|
||||
}
|
||||
.service-related-tint-1 .service-related-icon {
|
||||
background: #dce6dc;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
}
|
||||
|
||||
.service-related-tint-2 {
|
||||
@@ -275,7 +322,7 @@
|
||||
}
|
||||
.service-related-tint-2 .service-related-icon {
|
||||
background: #efe4d1;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
}
|
||||
|
||||
.service-related-tint-3 {
|
||||
@@ -305,7 +352,7 @@
|
||||
height: 52px;
|
||||
border-radius: 50%;
|
||||
background: #efe4d1;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
font-size: 18px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@@ -334,7 +381,7 @@
|
||||
.service-related-price {
|
||||
font-family: var(--font-head);
|
||||
font-weight: 700;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@@ -352,7 +399,7 @@
|
||||
.service-related-link {
|
||||
margin-top: auto;
|
||||
padding-top: 6px;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
font-family: var(--font-head);
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
@@ -386,18 +433,69 @@
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.service-hero-media,
|
||||
.service-highlight-image {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 28px;
|
||||
background: #f4efe7;
|
||||
box-shadow: 0 16px 40px rgba(17, 20, 24, 0.08);
|
||||
}
|
||||
|
||||
.service-hero-media {
|
||||
aspect-ratio: 4 / 3;
|
||||
}
|
||||
|
||||
.service-highlight-image {
|
||||
aspect-ratio: 4 / 3;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.service-highlight-collage {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
max-width: 780px;
|
||||
margin: 0 auto;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.service-collage-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 28px;
|
||||
background: #f4efe7;
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(17, 20, 24, 0.05),
|
||||
0 16px 40px rgba(17, 20, 24, 0.08);
|
||||
}
|
||||
|
||||
.service-collage-card img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.service-collage-card-1 {
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.service-collage-card-2 {
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.service-collage-card-3 {
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
.service-hero-media img,
|
||||
.service-highlight-image img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-radius: 28px;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
box-shadow: 0 16px 40px rgba(17, 20, 24, 0.08);
|
||||
}
|
||||
|
||||
.service-hero-media img {
|
||||
aspect-ratio: 4 / 3;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.service-highlight {
|
||||
@@ -418,10 +516,6 @@
|
||||
margin: 0 0 16px;
|
||||
}
|
||||
|
||||
.service-highlight-image img {
|
||||
max-height: 620px;
|
||||
}
|
||||
|
||||
.service-pricing,
|
||||
.service-benefits {
|
||||
padding: 0 0 96px;
|
||||
@@ -460,6 +554,13 @@
|
||||
border-color 0.22s ease;
|
||||
}
|
||||
|
||||
.service-plan-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.service-plan-popular {
|
||||
border: 2px solid var(--yellow);
|
||||
}
|
||||
@@ -521,7 +622,7 @@
|
||||
font-family: var(--font-head);
|
||||
font-size: 44px;
|
||||
line-height: 1;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
}
|
||||
|
||||
.service-plan-period {
|
||||
@@ -537,6 +638,7 @@
|
||||
margin: 24px 0 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.service-plan-features li {
|
||||
@@ -583,7 +685,7 @@
|
||||
padding: 8px 16px;
|
||||
border-radius: 999px;
|
||||
background: rgba(33, 48, 33, 0.06);
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -662,7 +764,7 @@
|
||||
.service-extra-price {
|
||||
font-family: var(--font-head);
|
||||
font-weight: 700;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -680,7 +782,7 @@
|
||||
height: 52px;
|
||||
border-radius: 50%;
|
||||
background: #efe4d1;
|
||||
color: var(--green);
|
||||
color: var(--gw-green);
|
||||
font-size: 18px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
@@ -702,6 +804,16 @@
|
||||
.service-hero-grid {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.service-highlight-collage {
|
||||
max-width: 720px;
|
||||
}
|
||||
|
||||
.service-collage-card-2,
|
||||
.service-collage-card-3,
|
||||
.service-collage-card-1 {
|
||||
min-height: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
@@ -723,7 +835,7 @@
|
||||
}
|
||||
|
||||
.service-plan-popular {
|
||||
order: -1;
|
||||
order: var(--mobile-order, 0);
|
||||
}
|
||||
|
||||
.service-highlight,
|
||||
@@ -748,5 +860,18 @@
|
||||
margin: 18px auto 0;
|
||||
font-family: var(--font-head);
|
||||
}
|
||||
|
||||
.service-highlight-collage {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
max-width: 420px;
|
||||
}
|
||||
|
||||
.service-collage-card-1,
|
||||
.service-collage-card-2,
|
||||
.service-collage-card-3 {
|
||||
min-height: 220px;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user