Bring the terminal dev-tool/OSS-docs theme to full Wave A OVERRIDE-CONTRACT compliance. - 49 mandatory builtin overrides in templates/overrides/terminal/ (TTY chrome, re-skinned from the frozen builtin defaults; every content field, provider var, custom tag, data-bn-* attr and inline script preserved verbatim). - 7 page templates (default, full-width, landing, article, blog-index, contact, auth) with TTY-window chrome, man-page article layout, and theme_mode-driven light/dark switching. - GO BIG motion: dependency-free ASCII glyph-rain canvas on the hero override only (lazy-init, prefers-reduced-motion honored, static phosphor fallback). - 4 persona blocks (manpage_header, code_console, keybind_table, boot_log); ascii_header/toc/footer blocks retired in favour of overrides + template furniture. - 5 dual-mode presets (mode "both", all 19 tokens) with intentional paper-teletype light and phosphor dark sides. - Bundled OFL mono fonts (JetBrains Mono, IBM Plex Mono) with LICENSES record; all font-family via var(--font-heading|body|mono, fallback). - Themed email-safe wrapper (retained), master pages, and a seeded "grid" OSS dev-tool demo site (home, about, changelog + 3 posts, contact with row_inserted -> email-admins workflow, login). - Declared required_icon_packs = [lucide, simple-icons]. Verified: make build exit 0, make verify exit 0, check-safety exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
485 lines
15 KiB
YAML
485 lines
15 KiB
YAML
# Terminal theme — codeless .bnp manifest (WO-TF-025, 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: terminal
|
|
title: Terminal
|
|
description: "Phosphor-on-black TTY theme for dev tools and OSS docs — window chrome, man-page article layouts, keybind tables, boot logs, monospace type, and a typed-terminal canvas hero. Paper-teletype light, phosphor dark."
|
|
|
|
page_templates:
|
|
- system: terminal
|
|
key: default
|
|
title: Default
|
|
description: "Centered 80-col TTY page with window chrome and a sticky header"
|
|
slots: [header, main, footer]
|
|
- system: terminal
|
|
key: full-width
|
|
title: Full Width
|
|
description: "Edge-to-edge layout for tool dashboards and status pages"
|
|
slots: [header, main, footer]
|
|
- system: terminal
|
|
key: landing
|
|
title: Landing
|
|
description: "Typed-terminal canvas hero, feature grid, boot log, and CTA for README-style project sites"
|
|
slots: [header, main, footer]
|
|
- system: terminal
|
|
key: article
|
|
title: Article (man-page)
|
|
description: "Man-page two-column layout with a section rail, ideal for docs and writeups"
|
|
slots: [header, main, aside, footer]
|
|
- system: terminal
|
|
key: blog-index
|
|
title: Blog Index
|
|
description: "Changelog-style post feed with a sidebar"
|
|
slots: [header, main, footer]
|
|
- system: terminal
|
|
key: contact
|
|
title: Contact
|
|
description: "Terminal contact console — form panel plus a contact card"
|
|
slots: [header, main, footer]
|
|
- system: terminal
|
|
key: auth
|
|
title: Auth
|
|
description: "Centered login/register/reset console in a TTY window"
|
|
slots: [header, main, footer]
|
|
|
|
template_overrides:
|
|
# Chrome (4)
|
|
- { template: terminal, block: navbar }
|
|
- { template: terminal, block: footer }
|
|
- { template: terminal, block: utility-bar }
|
|
- { template: terminal, block: announcement-bar }
|
|
# Marketing (12)
|
|
- { template: terminal, block: hero }
|
|
- { template: terminal, block: feature-grid }
|
|
- { template: terminal, block: rich-section }
|
|
- { template: terminal, block: stats }
|
|
- { template: terminal, block: testimonial }
|
|
- { template: terminal, block: logo-strip }
|
|
- { template: terminal, block: pricing }
|
|
- { template: terminal, block: team }
|
|
- { template: terminal, block: faq }
|
|
- { template: terminal, block: timeline }
|
|
- { template: terminal, block: cta }
|
|
- { template: terminal, block: countdown }
|
|
# Primitives (11)
|
|
- { template: terminal, block: heading }
|
|
- { template: terminal, block: text }
|
|
- { template: terminal, block: rich-text }
|
|
- { template: terminal, block: image }
|
|
- { template: terminal, block: quote }
|
|
- { template: terminal, block: divider }
|
|
- { template: terminal, block: button }
|
|
- { template: terminal, block: card }
|
|
- { template: terminal, block: gallery }
|
|
- { template: terminal, block: video-embed }
|
|
- { template: terminal, block: audio-embed }
|
|
# Commerce / local (6)
|
|
- { template: terminal, block: menu-list }
|
|
- { template: terminal, block: event-list }
|
|
- { template: terminal, block: contact-form }
|
|
- { template: terminal, block: contact-card }
|
|
- { template: terminal, block: hours-location }
|
|
- { template: terminal, block: social-links }
|
|
# Blog family (12)
|
|
- { template: terminal, block: blog-hero }
|
|
- { template: terminal, block: featured-posts }
|
|
- { template: terminal, block: related-posts }
|
|
- { template: terminal, block: popular-posts }
|
|
- { template: terminal, block: category-list }
|
|
- { template: terminal, block: post-hero }
|
|
- { template: terminal, block: post-metadata }
|
|
- { template: terminal, block: author-bio }
|
|
- { template: terminal, block: author-bio-hero }
|
|
- { template: terminal, block: newsletter-signup }
|
|
- { template: terminal, block: breadcrumbs }
|
|
- { template: terminal, block: sidebar-nav }
|
|
# Auth surface (3)
|
|
- { template: terminal, block: auth-form }
|
|
- { template: terminal, block: password-reset-form }
|
|
- { template: terminal, block: auth-status }
|
|
# System (1)
|
|
- { template: terminal, block: page-suggestions }
|
|
|
|
email_wrappers:
|
|
- terminal
|
|
|
|
css:
|
|
input_css_append: |
|
|
/* ============================================================
|
|
Terminal — Phosphor-on-black TTY theme (WO-TF-025).
|
|
All colours consume the host shadcn HSL tokens via
|
|
hsl(var(--token)). No hardcoded hex / rgb / named colours.
|
|
Dual-mode: light = paper teletype, dark = phosphor CRT.
|
|
============================================================ */
|
|
|
|
/* --- Globals: square corners, mono stack ------------------ */
|
|
|
|
:root { --radius: 0; }
|
|
|
|
.terminal-page {
|
|
font-family: var(--font-body, "IBM Plex Mono", "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
letter-spacing: 0.01em;
|
|
}
|
|
|
|
.terminal-page * { border-radius: 0 !important; }
|
|
|
|
/* --- Typography helpers ----------------------------------- */
|
|
|
|
.terminal-heading {
|
|
font-family: var(--font-heading, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
}
|
|
|
|
.terminal-mono {
|
|
font-family: var(--font-mono, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
}
|
|
|
|
.terminal-eyebrow {
|
|
font-family: var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.2em;
|
|
font-size: 0.75rem;
|
|
color: hsl(var(--accent));
|
|
}
|
|
|
|
.terminal-prose,
|
|
.terminal-prose p,
|
|
.terminal-prose li {
|
|
font-family: var(--font-body, "IBM Plex Mono", ui-monospace, monospace);
|
|
line-height: 1.7;
|
|
}
|
|
|
|
.terminal-prose a {
|
|
color: hsl(var(--accent));
|
|
text-decoration: underline;
|
|
text-underline-offset: 0.2em;
|
|
}
|
|
|
|
.terminal-prose code,
|
|
code.terminal-mono {
|
|
color: hsl(var(--accent));
|
|
background-color: hsl(var(--muted));
|
|
padding: 0.1rem 0.35rem;
|
|
border: 1px solid hsl(var(--border));
|
|
font-family: var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
font-size: 0.875em;
|
|
}
|
|
|
|
/* --- Caret blink (element opacity; used as <span class="caret-blink">_</span>) --- */
|
|
|
|
@keyframes caret-blink { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }
|
|
|
|
.caret-blink {
|
|
display: inline-block;
|
|
animation: caret-blink 1s step-end infinite;
|
|
}
|
|
|
|
/* --- TTY window chrome (signature) ------------------------ */
|
|
|
|
.tty-window {
|
|
border: 1px solid hsl(var(--border));
|
|
background-color: hsl(var(--card));
|
|
color: hsl(var(--card-foreground));
|
|
}
|
|
|
|
.tty-titlebar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.4rem 0.75rem;
|
|
border-bottom: 1px solid hsl(var(--border));
|
|
background-color: hsl(var(--muted));
|
|
color: hsl(var(--muted-foreground));
|
|
font-family: var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
font-size: 0.75rem;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.tty-dot {
|
|
display: inline-block;
|
|
width: 0.6rem;
|
|
height: 0.6rem;
|
|
border: 1px solid hsl(var(--border));
|
|
background-color: hsl(var(--secondary));
|
|
}
|
|
|
|
/* --- TTY frame: bordered panel with hover glow ------------ */
|
|
|
|
.tty-frame {
|
|
border: 1px solid hsl(var(--border));
|
|
background-color: hsl(var(--card));
|
|
transition: box-shadow 180ms ease, border-color 180ms ease;
|
|
}
|
|
.tty-frame:hover,
|
|
.tty-frame:focus-within {
|
|
border-color: hsl(var(--primary));
|
|
box-shadow: 0 0 0 1px hsl(var(--primary) / 0.5), 0 0 18px hsl(var(--primary) / 0.18);
|
|
}
|
|
|
|
/* --- ASCII corner brackets (accent + on the corners) ------ */
|
|
|
|
.tty-corners { position: relative; }
|
|
.tty-corners::before,
|
|
.tty-corners::after {
|
|
content: "+";
|
|
position: absolute;
|
|
color: hsl(var(--primary));
|
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
pointer-events: none;
|
|
}
|
|
.tty-corners::before { top: -0.55em; left: -0.35em; }
|
|
.tty-corners::after { bottom: -0.55em; right: -0.35em; }
|
|
|
|
/* --- ASCII figure frame (image override) ------------------ */
|
|
|
|
.ascii-frame {
|
|
display: inline-block;
|
|
padding: 0.5rem;
|
|
border: 1px solid hsl(var(--border));
|
|
background-color: hsl(var(--card));
|
|
position: relative;
|
|
}
|
|
.ascii-frame figcaption {
|
|
display: block;
|
|
margin-top: 0.5rem;
|
|
color: hsl(var(--muted-foreground));
|
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
font-size: 0.875rem;
|
|
text-align: center;
|
|
}
|
|
|
|
/* --- TTY scanlines overlay element (hero/landing) --------- */
|
|
|
|
.tty-scanlines {
|
|
opacity: 0.06;
|
|
background-image: linear-gradient(
|
|
to bottom,
|
|
hsl(var(--foreground)) 0px,
|
|
hsl(var(--foreground)) 1px,
|
|
transparent 1px,
|
|
transparent 3px
|
|
);
|
|
background-size: 100% 3px;
|
|
animation: tty-scan-drift 6s linear infinite;
|
|
}
|
|
@keyframes tty-scan-drift { 0% { background-position: 0 0; } 100% { background-position: 0 3px; } }
|
|
|
|
/* --- Page-level CRT scanline wash (subtle, whole page) ---- */
|
|
|
|
.crt-scanlines { position: relative; }
|
|
.crt-scanlines::before {
|
|
content: "";
|
|
position: fixed;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
z-index: 1000;
|
|
background: repeating-linear-gradient(
|
|
to bottom,
|
|
transparent 0,
|
|
transparent 2px,
|
|
hsl(var(--foreground) / 0.04) 2px,
|
|
hsl(var(--foreground) / 0.04) 3px
|
|
);
|
|
}
|
|
|
|
/* --- Status dot pulse ------------------------------------- */
|
|
|
|
.terminal-status-dot { animation: terminal-pulse 2.2s ease-in-out infinite; }
|
|
@keyframes terminal-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
|
|
|
|
/* --- Typed-terminal canvas showpiece (hero override only) - */
|
|
|
|
.tty-rain-wrap {
|
|
position: absolute;
|
|
inset: 0;
|
|
overflow: hidden;
|
|
pointer-events: none;
|
|
}
|
|
.tty-rain-canvas {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
opacity: 0.45;
|
|
}
|
|
.tty-rain-fallback {
|
|
position: absolute;
|
|
inset: 0;
|
|
background:
|
|
radial-gradient(120% 80% at 50% 0%, hsl(var(--primary) / 0.16), transparent 60%),
|
|
linear-gradient(to bottom, transparent, hsl(var(--background) / 0.7));
|
|
}
|
|
|
|
/* --- Man-page header block -------------------------------- */
|
|
|
|
.manpage-header {
|
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
border-top: 1px solid hsl(var(--border));
|
|
border-bottom: 1px solid hsl(var(--border));
|
|
padding: 0.6rem 0;
|
|
margin-bottom: 1rem;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
color: hsl(var(--foreground));
|
|
}
|
|
.manpage-header .left,
|
|
.manpage-header .center,
|
|
.manpage-header .right { flex: 1; }
|
|
.manpage-header .center { text-align: center; }
|
|
.manpage-header .right { text-align: right; }
|
|
|
|
/* --- Section rail (article aside furniture) --------------- */
|
|
|
|
.terminal-toc {
|
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
color: hsl(var(--muted-foreground));
|
|
padding: 1rem;
|
|
border: 1px solid hsl(var(--border));
|
|
background: hsl(var(--card));
|
|
position: sticky;
|
|
top: 1rem;
|
|
}
|
|
.terminal-toc h4 {
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
color: hsl(var(--foreground));
|
|
margin: 0 0 0.5rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
.terminal-toc ul { list-style: none; margin: 0; padding: 0; }
|
|
.terminal-toc li { margin: 0.2rem 0; }
|
|
.terminal-toc a { color: hsl(var(--muted-foreground)); text-decoration: none; }
|
|
.terminal-toc a:hover { color: hsl(var(--foreground)); }
|
|
@media (max-width: 768px) { .terminal-toc { display: none; } }
|
|
|
|
/* --- Code console block ----------------------------------- */
|
|
|
|
.code-console {
|
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
background: hsl(var(--card));
|
|
border: 1px solid hsl(var(--border));
|
|
padding: 0.75rem 1rem;
|
|
margin: 1rem 0;
|
|
overflow-x: auto;
|
|
color: hsl(var(--card-foreground));
|
|
}
|
|
.code-console .cmd-line { display: flex; align-items: baseline; gap: 0.5em; margin: 0; }
|
|
.code-console .cmd-prompt { color: hsl(var(--accent)); }
|
|
.code-console .cmd-text { color: hsl(var(--foreground)); }
|
|
.code-console pre {
|
|
margin: 0.5rem 0 0;
|
|
white-space: pre-wrap;
|
|
color: hsl(var(--muted-foreground));
|
|
font-family: inherit;
|
|
}
|
|
|
|
/* --- Keybinding table ------------------------------------- */
|
|
|
|
.keybind-table {
|
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
border-collapse: collapse;
|
|
margin: 1rem 0;
|
|
width: 100%;
|
|
max-width: 80ch;
|
|
color: hsl(var(--foreground));
|
|
}
|
|
.keybind-table th,
|
|
.keybind-table td {
|
|
border-bottom: 1px dashed hsl(var(--border));
|
|
padding: 0.4rem 0.6rem;
|
|
text-align: left;
|
|
vertical-align: top;
|
|
}
|
|
.keybind-table th {
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: hsl(var(--accent));
|
|
font-weight: 600;
|
|
}
|
|
.keybind-table kbd {
|
|
font-family: inherit;
|
|
background: hsl(var(--muted));
|
|
color: hsl(var(--foreground));
|
|
border: 1px solid hsl(var(--border));
|
|
padding: 0.05rem 0.4rem;
|
|
margin-right: 0.25rem;
|
|
font-size: 0.875em;
|
|
}
|
|
|
|
/* --- Boot log --------------------------------------------- */
|
|
|
|
.boot-log {
|
|
font-family: var(--font-mono, ui-monospace, monospace);
|
|
background: hsl(var(--background));
|
|
color: hsl(var(--foreground));
|
|
padding: 1rem;
|
|
border: 1px solid hsl(var(--border));
|
|
margin: 1rem 0;
|
|
white-space: pre-wrap;
|
|
overflow-x: auto;
|
|
}
|
|
.boot-log .boot-line {
|
|
display: block;
|
|
opacity: 0;
|
|
animation: boot-line-in 0.2s ease-out forwards;
|
|
}
|
|
@keyframes boot-line-in {
|
|
from { opacity: 0; transform: translateY(2px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
.boot-log .boot-cursor {
|
|
display: inline-block;
|
|
color: hsl(var(--accent));
|
|
animation: caret-blink 1s step-end infinite;
|
|
}
|
|
|
|
/* --- Layout helpers --------------------------------------- */
|
|
|
|
.terminal-main-80 { max-width: 80ch; margin: 0 auto; }
|
|
|
|
.terminal-article-grid {
|
|
display: grid;
|
|
grid-template-columns: 20ch 1fr;
|
|
gap: 2rem;
|
|
align-items: start;
|
|
}
|
|
@media (max-width: 768px) { .terminal-article-grid { grid-template-columns: 1fr; } }
|
|
|
|
/* --- Reduced motion: kill all motion ---------------------- */
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.caret-blink,
|
|
.tty-scanlines,
|
|
.terminal-status-dot,
|
|
.tty-rain-canvas,
|
|
.boot-log .boot-line,
|
|
.boot-log .boot-cursor {
|
|
animation: none !important;
|
|
animation-duration: 0.01ms !important;
|
|
}
|
|
.boot-log .boot-line { opacity: 1; transform: none; }
|
|
.tty-scanlines { opacity: 0; }
|
|
.tty-rain-canvas { display: none; }
|
|
}
|
|
|
|
/* --- High contrast: drop the CRT overlays ----------------- */
|
|
|
|
@media (prefers-contrast: more) {
|
|
.tty-scanlines,
|
|
.crt-scanlines::before,
|
|
.tty-rain-canvas { display: none; }
|
|
}
|