mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
164 lines
5.0 KiB
Plaintext
164 lines
5.0 KiB
Plaintext
---
|
|
/**
|
|
* /store/deck-boxes — 3D-printed deck boxes & counters product line
|
|
* ---------------------------------------------------------------------------
|
|
* Order: back-link + title → live slot tracker → image carousel → specs →
|
|
* pricing → key requirements → CTA.
|
|
*
|
|
* The carousel images + labels are managed server-side in store-products.ts
|
|
* (deckBoxProduct.images). The specs block is image-free now; examples live in
|
|
* the carousel only.
|
|
*/
|
|
import StoreLayout from "@layouts/StoreLayout.astro";
|
|
import Reveal from "@components/motion/Reveal.astro";
|
|
import SectionHeader from "@components/layout/SectionHeader.astro";
|
|
import Icon from "@components/Icon.astro";
|
|
import Carousel from "@components/store/Carousel.tsx";
|
|
import ProductCard from "@components/store/ProductCard.astro";
|
|
import PricingTable from "@components/store/PricingTable.astro";
|
|
import SlotMeter from "@components/store/SlotMeter.astro";
|
|
import ColorGrid from "@components/store/ColorGrid.astro";
|
|
import RequirementList from "@components/store/RequirementList.astro";
|
|
import { deckBoxProduct, requirements } from "@data/store-products";
|
|
import { storeAvailability } from "@data/store-availability";
|
|
|
|
const av = storeAvailability;
|
|
const slot = av.slots[deckBoxProduct.slotKey];
|
|
const keyReqs = requirements.filter(
|
|
(r) =>
|
|
r.title.toLowerCase().includes("final") ||
|
|
r.title.toLowerCase().includes("capacity") ||
|
|
r.title.toLowerCase().includes("affiliation"),
|
|
);
|
|
---
|
|
|
|
<StoreLayout
|
|
title="3D-Printed Deck Boxes & Counters"
|
|
description="3D-printed deck boxes, life counters, and tokens. Specs and pricing for printed storage and trackers."
|
|
>
|
|
<div class="container-prose flex flex-col gap-14 py-28 sm:py-32">
|
|
{/* Header */}
|
|
<section class="flex flex-col gap-5">
|
|
<Reveal>
|
|
<a
|
|
href="/store"
|
|
class="inline-flex items-center gap-1.5 font-mono text-xs uppercase tracking-[0.18em]"
|
|
style="color: var(--color-accent);"
|
|
>
|
|
<Icon name="arrow-left" class="h-4 w-4" />
|
|
Back to store
|
|
</a>
|
|
</Reveal>
|
|
<Reveal delay={60}>
|
|
<SectionHeader
|
|
kicker="Product"
|
|
icon={deckBoxProduct.icon}
|
|
title={deckBoxProduct.title}
|
|
subtitle={deckBoxProduct.summary}
|
|
/>
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Live slot tracker for this product line (top of content). */}
|
|
<section class="flex flex-col gap-3">
|
|
<Reveal>
|
|
<SlotMeter
|
|
label="3D-print slots"
|
|
icon="printer-3d-nozzle"
|
|
open={slot.open}
|
|
total={slot.total}
|
|
/>
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Image carousel (server-driven, swipeable). */}
|
|
<section class="flex flex-col gap-4">
|
|
<Reveal
|
|
><SectionHeader
|
|
kicker="Examples"
|
|
icon="image-multiple"
|
|
title={`See the ${deckBoxProduct.title.toLowerCase()}`}
|
|
/></Reveal
|
|
>
|
|
<Reveal delay={60}>
|
|
<Carousel
|
|
client:visible
|
|
slides={deckBoxProduct.images}
|
|
label={`${deckBoxProduct.title} examples`}
|
|
/>
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Specifications (no image — examples live in the carousel). */}
|
|
<section class="flex flex-col gap-6">
|
|
<Reveal
|
|
><SectionHeader
|
|
kicker="Details"
|
|
icon="ruler"
|
|
title="Specifications"
|
|
/></Reveal
|
|
>
|
|
<Reveal delay={60}>
|
|
<ProductCard product={deckBoxProduct} detailed />
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Pricing */}
|
|
<section class="flex flex-col gap-6">
|
|
<Reveal
|
|
><SectionHeader
|
|
kicker="Pricing"
|
|
icon="currency-usd"
|
|
title="Prints"
|
|
/></Reveal
|
|
>
|
|
<Reveal delay={60}>
|
|
<PricingTable
|
|
icon="printer-3d-nozzle"
|
|
caption="Per-print pricing"
|
|
subtitle="Final pricing confirmed when your request is received. Prices are placeholders pending update."
|
|
tiers={deckBoxProduct.pricing}
|
|
/>
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Available print colors (filament). Managed in store-products.ts. */}
|
|
<section class="flex flex-col gap-6">
|
|
<Reveal
|
|
><SectionHeader
|
|
kicker="Colors"
|
|
icon="palette"
|
|
title="Available print colors"
|
|
/></Reveal
|
|
>
|
|
<Reveal delay={60}>
|
|
<ColorGrid colors={deckBoxProduct.colors} />
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* Key requirements */}
|
|
<section class="flex flex-col gap-6">
|
|
<Reveal
|
|
><SectionHeader
|
|
kicker="Before you order"
|
|
icon="clipboard-check"
|
|
title="Key requirements"
|
|
/></Reveal
|
|
>
|
|
<Reveal delay={60}>
|
|
<RequirementList items={keyReqs} />
|
|
</Reveal>
|
|
</section>
|
|
|
|
{/* CTA */}
|
|
<Reveal>
|
|
<div class="flex flex-col items-center gap-4 text-center">
|
|
<a href="/store/order" class="btn btn-primary">
|
|
<Icon name="clipboard-list" class="h-5 w-5" />
|
|
{av.ordersOpen ? "Start an order request" : "View order page"}
|
|
</a>
|
|
</div>
|
|
</Reveal>
|
|
</div>
|
|
</StoreLayout>
|