pcbjam/site/src/components/Placeholder.astro
Viktor Vaczi 7f9dbdd068 feat(site): 🛬 PCBJam landing page — waitlist, sections, Tailwind
Replace the placeholder homepage with the PCBJam waitlist conversion page
(13 sections from the copy spec), shared chrome, and a real email-capture
backend, keeping the site zero-runtime-JS / zero-web-font.

- Tailwind v4 via @tailwindcss/postcss (the Vite plugin breaks on Astro 6
  rolldown-vite); Preflight skipped; brand tokens in :root + @theme inline.
- Waitlist: /api/waitlist serverless route (prerender=false) + Resend, with
  dual JSON/303 responses; WaitlistForm progressive enhancement bound on
  astro:page-load (survives ClientRouter swaps); honeypot + validation.
- New components (Icon, Placeholder, DemoVideo, SectionBand, Chip, EECredit,
  StatBar, Pillar, Step, CheckItem, WaitlistForm) + 13 section components.
- Redesigned Header (sticky, mobile menu, CTA) + 4-col Footer (KiCad
  attribution); BaseLayout gains full-bleed mode + OG/canonical meta.
- Assets scaffolded with marked placeholders; EE/generic/client SVGs copied.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 14:59:13 +02:00

63 lines
1.6 KiB
Text

---
/**
* Placeholder — a clearly-marked, dashed-box slot for an asset that doesn't
* exist yet (PCBJam logo, demo video, product screenshots…). Real assets drop
* into the same spot later by swapping this component for an <img>/<DemoVideo>.
*
* The `label` should name what to produce + the spec ref, e.g.
* "PRODUCE: multiplayer demo loop (§4b.2)"
*/
interface Props {
label: string;
ratio?: string; // e.g. "16 / 9", "1 / 1"; default 16/9
kind?: 'image' | 'video' | 'logo';
class?: string;
}
const { label, ratio = '16 / 9', kind = 'image', class: cls = '' } = Astro.props;
const glyph = kind === 'video' ? '▶' : kind === 'logo' ? '◆' : '▦';
---
<div
class={`placeholder ${cls}`}
data-placeholder={kind}
style={`aspect-ratio:${ratio};`}
role="img"
aria-label={label}
>
<span class="ph-glyph" aria-hidden="true">{glyph}</span>
<span class="ph-label">{label}</span>
</div>
<style>
.placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.5rem;
width: 100%;
padding: 1.5rem;
text-align: center;
border: 2px dashed var(--border);
border-radius: var(--radius);
background:
repeating-linear-gradient(
45deg,
color-mix(in srgb, var(--bg-soft) 88%, transparent),
color-mix(in srgb, var(--bg-soft) 88%, transparent) 12px,
var(--bg-soft) 12px,
var(--bg-soft) 24px
);
color: var(--fg-muted);
}
.ph-glyph {
font-size: 1.75rem;
opacity: 0.6;
}
.ph-label {
font-family: var(--font-mono);
font-size: 0.8rem;
letter-spacing: 0.01em;
}
</style>