themes-cyberpunk/manifest.yaml
Alex Dunmow 02a84ab31e feat(cyberpunk): Wave A build — 49 builtin overrides, 7 templates, canvas hero, seed
WO-TF-015 (game-studio / hacker-collective persona, GO-BIG motion).

- Overrides: all 49 mandatory builtin keys in templates/overrides/cyberpunk/
  (dashed keys), each restyled to neon-HUD chrome preserving builtin field
  reads + scripts. Legacy button/card/heading/text reconciled to new field
  names (label/link/style, text/media). Auth surface (auth-form,
  auth-status, password-reset-form) reproduces the builtin hardcoded HTMX
  endpoints + Cap widget verbatim. page-suggestions ships themed 404 chrome.
- Page templates: 7 (default, full-width, landing, article, blog-index,
  contact, auth), dual-mode via theme_mode, scanline overlay chrome.
- Hero override: dependency-free canvas digital-rain showpiece — lazy-init
  via IntersectionObserver, prefers-reduced-motion honored, static neon
  gradient no-JS fallback, token-derived colors only.
- Blocks: deleted 6 builtin-duplicating theme blocks (now overrides); kept
  code_neon (+ copy handler); added persona blocks glitch_hero, roster_grid,
  patch_notes with schemas + sample data.
- Presets: 5 (neon-noir, acid-rain, toxic-bloom, hotline, ghost-protocol),
  all 19 tokens, light+dark both tuned.
- Fonts: bundled OFL woff2 (Orbitron, Share Tech Mono, Inter latin subsets)
  in assets/fonts + fonts.json + LICENSES; all font-family via CSS vars.
- Email: preset-aware email-safe wrapper (tables, inline styles, colors.*).
- Master pages + demo seed (home, about, blog+3 posts, contact with
  data-table + row_inserted email-admins workflow, login).
- manifest CSS: hud-frame, clip-cut, cyberpunk-eyebrow, canvas-rain utils.
- plugin.mod + manifest required_icon_packs = [lucide, simple-icons].

make build + verify exit 0; check-safety exit 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:57:00 +08:00

378 lines
13 KiB
YAML

# Cyberpunk theme — codeless .bnp manifest (WO-TF-015, Wave A).
# Synthesized into manifest.pb by `ninja plugin build` (no plugin.wasm).
theme_presets: presets.json
bundled_fonts: fonts.json
master_pages: master_pages.json
required_icon_packs: ["lucide", "simple-icons"]
system_templates:
- key: cyberpunk
title: Cyberpunk
description: "Neon-on-black game-studio / hacker-collective theme — RGB-split glitch, CRT scanlines, HUD brackets, angled clip cuts, and a canvas digital-rain hero."
page_templates:
- system: cyberpunk
key: default
title: Default
description: "Standard dark page with scanline overlay and a sticky terminal-style header"
slots: [header, main, footer]
- system: cyberpunk
key: full-width
title: Full Width
description: "Edge-to-edge dashboard / showcase layout, no max-width"
slots: [header, main, footer]
- system: cyberpunk
key: landing
title: Landing
description: "Canvas digital-rain hero, neon feature grid, glowing CTA, footer"
slots: [header, main, footer]
- system: cyberpunk
key: article
title: Article
description: "Mono-metadata header, prose column, HUD-framed aside"
slots: [header, main, aside, footer]
- system: cyberpunk
key: blog-index
title: Blog Index
description: "Patch-notes feed layout with neon post cards and sidebar"
slots: [header, main, footer]
- system: cyberpunk
key: contact
title: Contact
description: "Terminal contact console — form panel plus HUD contact card"
slots: [header, main, footer]
- system: cyberpunk
key: auth
title: Auth
description: "Centered neon auth console for login / register / reset"
slots: [header, main, footer]
# All 49 mandatory-tier builtin overrides (OVERRIDE-CONTRACT §1), dashed keys.
template_overrides:
# Chrome (4)
- { template: cyberpunk, block: navbar }
- { template: cyberpunk, block: footer }
- { template: cyberpunk, block: utility-bar }
- { template: cyberpunk, block: announcement-bar }
# Marketing (12)
- { template: cyberpunk, block: hero }
- { template: cyberpunk, block: feature-grid }
- { template: cyberpunk, block: rich-section }
- { template: cyberpunk, block: stats }
- { template: cyberpunk, block: testimonial }
- { template: cyberpunk, block: logo-strip }
- { template: cyberpunk, block: pricing }
- { template: cyberpunk, block: team }
- { template: cyberpunk, block: faq }
- { template: cyberpunk, block: timeline }
- { template: cyberpunk, block: cta }
- { template: cyberpunk, block: countdown }
# Primitives (11)
- { template: cyberpunk, block: heading }
- { template: cyberpunk, block: text }
- { template: cyberpunk, block: rich-text }
- { template: cyberpunk, block: image }
- { template: cyberpunk, block: quote }
- { template: cyberpunk, block: divider }
- { template: cyberpunk, block: button }
- { template: cyberpunk, block: card }
- { template: cyberpunk, block: gallery }
- { template: cyberpunk, block: video-embed }
- { template: cyberpunk, block: audio-embed }
# Commerce / local (6)
- { template: cyberpunk, block: menu-list }
- { template: cyberpunk, block: event-list }
- { template: cyberpunk, block: contact-form }
- { template: cyberpunk, block: contact-card }
- { template: cyberpunk, block: hours-location }
- { template: cyberpunk, block: social-links }
# Blog family (12)
- { template: cyberpunk, block: blog-hero }
- { template: cyberpunk, block: featured-posts }
- { template: cyberpunk, block: related-posts }
- { template: cyberpunk, block: popular-posts }
- { template: cyberpunk, block: category-list }
- { template: cyberpunk, block: post-hero }
- { template: cyberpunk, block: post-metadata }
- { template: cyberpunk, block: author-bio }
- { template: cyberpunk, block: author-bio-hero }
- { template: cyberpunk, block: newsletter-signup }
- { template: cyberpunk, block: breadcrumbs }
- { template: cyberpunk, block: sidebar-nav }
# Auth surface (3)
- { template: cyberpunk, block: auth-form }
- { template: cyberpunk, block: password-reset-form }
- { template: cyberpunk, block: auth-status }
# System (1)
- { template: cyberpunk, block: page-suggestions }
email_wrappers:
- cyberpunk
css:
input_css_append: |
/* ============================================================
Cyberpunk — Neon-on-black game-studio / hacker-collective theme
(WO-TF-015). Scanlines / glitch / RGB-split / caret-blink /
neon-edge / HUD-bracket / clip-cut / digital-rain utilities.
All colours consume the host shadcn HSL tokens via hsl(var(--token)).
No hardcoded hex / rgb / named colours.
============================================================ */
/* --- Typography ------------------------------------------- */
/* Families flow through the admin-bound CSS variables; the fallback
leads with the bundled OFL family so the intended look survives
before the admin assigns a slot. @font-face for the bundled
families is auto-emitted from fonts.json (source=template rows). */
.cyberpunk-body {
font-family: var(--font-body, "Inter", system-ui, -apple-system, "Segoe UI", sans-serif);
}
.cyberpunk-mono,
.cyberpunk-mono code,
pre.cyberpunk-mono,
code.cyberpunk-mono {
font-family: var(--font-mono, "Share Tech Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
}
.cyberpunk-display {
font-family: var(--font-heading, "Orbitron", system-ui, -apple-system, "Segoe UI", sans-serif);
letter-spacing: 0.01em;
}
.cyberpunk-prose,
.cyberpunk-prose p,
.cyberpunk-prose li {
font-family: var(--font-body, "Inter", system-ui, sans-serif);
line-height: 1.75;
}
/* Eyebrow / kicker: mono, uppercase, wide-tracked accent readout. Carries
enough on its own that it is never a silent no-op when used alone. */
.cyberpunk-eyebrow {
font-family: var(--font-mono, "Share Tech Mono", ui-monospace, monospace);
text-transform: uppercase;
letter-spacing: 0.2em;
font-size: 0.75rem;
color: hsl(var(--accent));
}
.cyberpunk-prose code {
color: hsl(var(--accent));
background-color: hsl(var(--muted));
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
font-family: var(--font-mono, "Share Tech Mono", ui-monospace, monospace);
font-size: 0.875em;
}
/* --- Scanlines -------------------------------------------- */
.scanlines {
opacity: 0.05;
background-image: linear-gradient(
to bottom,
hsl(var(--foreground)) 0px,
hsl(var(--foreground)) 1px,
transparent 1px,
transparent 3px
);
background-size: 100% 3px;
animation: scanline-drift 6s linear infinite;
}
@keyframes scanline-drift {
0% { background-position: 0 0; }
100% { background-position: 0 3px; }
}
/* --- Glitch (RGB-split text-shadow) on big headings ------- */
.glitch {
position: relative;
text-shadow:
-2px 0 hsl(var(--primary)),
2px 0 hsl(var(--accent));
animation: glitch-x 3.6s steps(1, end) infinite;
}
@keyframes glitch-x {
0%, 92%, 100% {
text-shadow: -2px 0 hsl(var(--primary)), 2px 0 hsl(var(--accent));
}
93% {
text-shadow: -3px 0 hsl(var(--primary)), 3px 0 hsl(var(--accent)), 0 1px hsl(var(--accent));
}
95% {
text-shadow: -1px 0 hsl(var(--accent)), 4px 0 hsl(var(--primary));
}
97% {
text-shadow: -2px 0 hsl(var(--primary)), 2px 0 hsl(var(--accent));
}
}
/* --- RGB-split hover/focus/active on primary buttons ------ */
.rgb-split {
transition: transform 120ms ease, box-shadow 120ms ease;
}
.rgb-split:hover,
.rgb-split:focus-visible {
box-shadow: -2px 0 0 hsl(var(--primary)), 2px 0 0 hsl(var(--accent));
transform: translateY(-1px);
}
.cyberpunk-btn:active,
.rgb-split:active,
button.cyberpunk-btn:active {
box-shadow: -2px 0 0 hsl(var(--primary)), 2px 0 0 hsl(var(--accent));
}
.cyberpunk-btn:focus-visible,
.cyberpunk-btn-ghost:focus-visible,
button:focus-visible,
a:focus-visible {
outline: 2px solid hsl(var(--ring));
outline-offset: 2px;
}
/* --- Caret blink ------------------------------------------ */
.caret-blink {
display: inline-block;
animation: caret 1.05s steps(2, end) infinite;
}
@keyframes caret {
0%, 50% { opacity: 1; }
51%, 100% { opacity: 0; }
}
/* --- Neon edge utilities (magenta / cyan / lime channels) - */
/* --primary is the lead accent, --accent the secondary, --ring
the third neon channel (present in every preset). */
.neon-edge-magenta {
box-shadow: 0 0 0 1px hsl(var(--primary) / 0.4), 0 0 18px hsl(var(--primary) / 0.22);
transition: box-shadow 180ms ease, transform 180ms ease;
}
.neon-edge-magenta:hover,
.neon-edge-magenta:focus-within {
box-shadow: 0 0 0 1px hsl(var(--primary) / 0.85), 0 0 28px hsl(var(--primary) / 0.42);
transform: translateY(-1px);
}
.neon-edge-cyan {
box-shadow: 0 0 0 1px hsl(var(--accent) / 0.4), 0 0 18px hsl(var(--accent) / 0.22);
transition: box-shadow 180ms ease, transform 180ms ease;
}
.neon-edge-cyan:hover,
.neon-edge-cyan:focus-within {
box-shadow: 0 0 0 1px hsl(var(--accent) / 0.85), 0 0 28px hsl(var(--accent) / 0.42);
transform: translateY(-1px);
}
.neon-edge-lime {
box-shadow: 0 0 0 1px hsl(var(--ring) / 0.4), 0 0 18px hsl(var(--ring) / 0.22);
transition: box-shadow 180ms ease, transform 180ms ease;
}
.neon-edge-lime:hover,
.neon-edge-lime:focus-within {
box-shadow: 0 0 0 1px hsl(var(--ring) / 0.85), 0 0 28px hsl(var(--ring) / 0.42);
transform: translateY(-1px);
}
/* --- HUD corner brackets ---------------------------------- */
/* Draw two L-brackets (top-left, bottom-right) around any panel. */
.hud-frame {
position: relative;
}
.hud-frame::before,
.hud-frame::after {
content: "";
position: absolute;
width: 14px;
height: 14px;
pointer-events: none;
z-index: 1;
}
.hud-frame::before {
top: -1px;
left: -1px;
border-top: 2px solid hsl(var(--primary));
border-left: 2px solid hsl(var(--primary));
}
.hud-frame::after {
bottom: -1px;
right: -1px;
border-bottom: 2px solid hsl(var(--accent));
border-right: 2px solid hsl(var(--accent));
}
/* --- Angled clip-path cut (arcade panel silhouette) ------- */
.clip-cut {
clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px));
}
/* --- Status pill / dot pulse ------------------------------ */
.cyberpunk-status-dot {
animation: cyberpunk-pulse 2.2s ease-in-out infinite;
}
@keyframes cyberpunk-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
/* --- Digital-rain canvas showpiece (hero override only) --- */
/* The <canvas> lazy-inits from the hero's inline script. This block
styles the container + the static no-JS neon fallback layer. */
.cyberpunk-rain-wrap {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
}
.cyberpunk-rain-canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
display: block;
opacity: 0.5;
}
/* Static fallback: a neon vertical-gradient wash shown until (or instead
of) the canvas. Tokens only. */
.cyberpunk-rain-fallback {
position: absolute;
inset: 0;
background:
radial-gradient(120% 80% at 50% 0%, hsl(var(--primary) / 0.18), transparent 60%),
radial-gradient(120% 80% at 100% 100%, hsl(var(--accent) / 0.16), transparent 55%),
linear-gradient(to bottom, transparent, hsl(var(--background) / 0.6));
}
/* --- Reduced motion: kill all motion --------------------- */
@media (prefers-reduced-motion: reduce) {
.glitch,
.caret-blink,
.scanlines,
.cyberpunk-status-dot,
.cyberpunk-rain-canvas {
animation: none !important;
animation-duration: 0.01ms !important;
}
.glitch { text-shadow: none; }
.scanlines { opacity: 0; }
.cyberpunk-rain-canvas { display: none; }
.rgb-split:hover,
.rgb-split:focus-visible { transform: none; }
}
/* --- High-contrast: kill scanlines + rain ---------------- */
@media (prefers-contrast: more) {
.scanlines,
.cyberpunk-rain-canvas { display: none; }
}