themes-cyberpunk/manifest.yaml
Alex Dunmow 8ea1477d37 feat: convert to codeless .bnp — templates + manifest, Go/templ deleted (WO-WZ-021)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 15:26:00 +08:00

278 lines
7.8 KiB
YAML

# Cyberpunk theme — codeless .bnp manifest (WO-WZ-021 Phase B).
# Synthesized into manifest.pb by `ninja plugin build` (no plugin.wasm).
theme_presets: presets.json
bundled_fonts: fonts.json
master_pages: master_pages.json
system_templates:
- key: cyberpunk
title: Cyberpunk
description: "Neon-on-black BlockNinja theme with glitch motifs, monospace accents, and magenta/cyan/lime tri-accent palette for SaaS, dev tools, and crypto."
page_templates:
- system: cyberpunk
key: default
title: Default
description: "Standard dark page with scanline overlay, sticky terminal-style header"
slots: [header, main, footer]
- system: cyberpunk
key: landing
title: Landing
description: "Hero with glitch H1, neon CTA, feature grid, social proof, footer"
slots: [hero, features, cta, footer]
- system: cyberpunk
key: article
title: Article
description: "Mono-metadata header, prose column, code-friendly aside"
slots: [header, main, aside, footer]
- system: cyberpunk
key: full-width
title: Full Width
description: "Edge-to-edge dashboard / showcase layout, no max-width"
slots: [header, main, footer]
template_overrides:
- { template: cyberpunk, block: heading }
- { template: cyberpunk, block: text }
- { template: cyberpunk, block: button }
- { template: cyberpunk, block: card }
email_wrappers:
- cyberpunk
css:
input_css_append: |
/* ============================================================
Cyberpunk — Neon-on-black BlockNinja theme
Scanlines / glitch / RGB-split / caret-blink / neon-edge utilities.
All colours consume the host shadcn HSL tokens via hsl(var(--token)).
No hardcoded hex / rgb / named colours.
============================================================ */
/* --- Typography fallbacks --------------------------------- */
.cyberpunk-body {
font-family: var(--font-body, "Inter", system-ui, -apple-system, "Segoe UI", sans-serif);
}
.cyberpunk-mono,
.cyberpunk-mono *,
.cyberpunk-mono code,
pre.cyberpunk-mono,
code.cyberpunk-mono {
font-family: var(--font-mono, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace);
}
.cyberpunk-display {
font-family: var(--font-heading, "Space Grotesk", 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;
}
.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, "JetBrains Mono", ui-monospace, monospace);
font-size: 0.875em;
}
/* --- Scanlines -------------------------------------------- */
.scanlines {
opacity: 0.04;
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 H1/H2 -------------- */
.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);
}
/* Touch tap-flash fallback (iOS strips :hover after touchend) */
.cyberpunk-btn:active,
.rgb-split:active,
button.cyberpunk-btn:active {
box-shadow:
-2px 0 0 hsl(var(--primary)),
2px 0 0 hsl(var(--accent));
}
/* :focus-visible ring uses the ring token, not browser default */
.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) ---------- */
.neon-edge-magenta {
box-shadow:
0 0 0 1px hsl(var(--primary) / 0.4),
0 0 18px hsl(var(--primary) / 0.25);
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.45);
transform: translateY(-1px);
}
.neon-edge-cyan {
box-shadow:
0 0 0 1px hsl(var(--accent) / 0.4),
0 0 18px hsl(var(--accent) / 0.25);
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.45);
transform: translateY(-1px);
}
.neon-edge-lime {
/* Lime accent is the toxic-bloom primary; magenta-noir uses the primary
token. We reuse --ring as a third neon channel so this utility renders
visibly across all three presets. */
box-shadow:
0 0 0 1px hsl(var(--ring) / 0.4),
0 0 18px hsl(var(--ring) / 0.25);
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.45);
transform: translateY(-1px);
}
/* --- Card override dashed border --------------------------- */
.cyberpunk-card {
position: relative;
}
/* --- Status pill / dot animation -------------------------- */
.cyberpunk-status-dot {
animation: cyberpunk-pulse 2.2s ease-in-out infinite;
}
@keyframes cyberpunk-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
/* --- Reduced motion: disable glitch, caret, scanline ------ */
@media (prefers-reduced-motion: reduce) {
.glitch,
.caret-blink,
.scanlines,
.cyberpunk-status-dot {
animation: none !important;
animation-duration: 0.01ms !important;
}
.glitch {
text-shadow: none;
}
.scanlines {
opacity: 0;
}
.rgb-split:hover,
.rgb-split:focus-visible {
transform: none;
}
}
/* --- High-contrast: kill scanlines ------------------------ */
@media (prefers-contrast: more) {
.scanlines {
display: none;
}
}