Store base

This commit is contained in:
Greg Kilmer
2026-08-06 12:13:48 -04:00
parent 51a7b9fee0
commit f4a49fe9bc
28 changed files with 2471 additions and 2 deletions
+109
View File
@@ -0,0 +1,109 @@
---
/**
* /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 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>
{/* 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>