Content Rewrite

This commit is contained in:
2026-05-07 21:47:42 +12:00
parent 0d86f450ec
commit a90dfb7c66
47 changed files with 1352 additions and 527 deletions
+160 -35
View File
@@ -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>