Convert the Art Deco theme from a wasm (Go+templ) plugin to a fully codeless
.bnp: pure declaration the host runs, no plugin.wasm, no block/core dependency.
- blocks/: blocks.yaml (7 fully-qualified art-deco:* keys) + per-block
.schema.json (moved from schemas/) + .ninjatpl transcribed byte-for-byte
(modulo whitespace) from the templ sources.
- templates/art-deco/{default,landing,article,full-width}.ninjatpl — page
layouts.
- templates/overrides/art-deco/{heading,text,button,image}.ninjatpl.
- templates/email/art-deco.ninjatpl.
- manifest.yaml (system/page templates, template_overrides, email_wrappers,
theme_presets, bundled_fonts, master_pages, css input_css_append) +
master_pages.json.
- plugin.mod bumped to 0.2.0; [compatibility] block_core dropped (codeless has
no core dependency).
- Deleted all Go/templ/*_templ.go, go.mod/go.sum; Makefile rewritten to the
codeless build/verify/publish targets.
Render parity verified against the prior templ output (static pongo2 harness,
whitespace-normalised): all 7 blocks, 4 overrides and the email wrapper match.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
257 lines
9.4 KiB
YAML
257 lines
9.4 KiB
YAML
# Art Deco 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: art-deco
|
|
title: Art Deco
|
|
description: "Luxury Art Deco theme with champagne gold gradients, jet black, ivory and geometric fan motifs for hotels, fine dining, weddings and jewellers."
|
|
|
|
page_templates:
|
|
- system: art-deco
|
|
key: default
|
|
title: Default
|
|
description: "Centered symmetric layout with gold rule header and footer."
|
|
slots: [header, main, footer]
|
|
- system: art-deco
|
|
key: landing
|
|
title: Marquee Landing
|
|
description: "Wide hero with sunburst overlay, reservation strip, CTA."
|
|
slots: [marquee, main, cta, footer]
|
|
- system: art-deco
|
|
key: article
|
|
title: Editorial
|
|
description: "Narrow editorial column for press, menus and stories."
|
|
slots: [header, main, aside, footer]
|
|
- system: art-deco
|
|
key: full-width
|
|
title: Grand Ballroom
|
|
description: "Edge-to-edge gallery layout for venues and lookbooks."
|
|
slots: [header, main, footer]
|
|
|
|
template_overrides:
|
|
- { template: art-deco, block: heading }
|
|
- { template: art-deco, block: text }
|
|
- { template: art-deco, block: button }
|
|
- { template: art-deco, block: image }
|
|
|
|
email_wrappers:
|
|
- art-deco
|
|
|
|
css:
|
|
input_css_append: |
|
|
/* Art Deco theme — utility CSS for foil, frames, fans and grain.
|
|
*
|
|
* Color is always consumed via hsl(var(--token)) — the tokens carry HSL triples.
|
|
* Font families always come from var(--font-heading|body|mono, <fallback>).
|
|
*/
|
|
|
|
@layer utilities {
|
|
/* deco-rule — hairline gold rule, 1px ascending to 2px on accent lines. */
|
|
.deco-rule {
|
|
border: none;
|
|
border-top: 1px solid hsl(var(--primary));
|
|
margin: 0;
|
|
}
|
|
.deco-rule-thick {
|
|
border: none;
|
|
border-top: 2px solid hsl(var(--primary));
|
|
margin: 0;
|
|
}
|
|
|
|
/* deco-frame — stepped ziggurat frame, layered borders + clipped corners. */
|
|
.deco-frame {
|
|
position: relative;
|
|
border: 1px solid hsl(var(--primary));
|
|
padding: 1.25rem;
|
|
}
|
|
.deco-frame::before,
|
|
.deco-frame::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: -6px;
|
|
right: -6px;
|
|
height: 4px;
|
|
background: hsl(var(--primary));
|
|
opacity: 0.85;
|
|
}
|
|
.deco-frame::before { top: -6px; }
|
|
.deco-frame::after { bottom: -6px; }
|
|
|
|
/* deco-step — stepped corner mask suitable for image frames. */
|
|
.deco-step {
|
|
position: relative;
|
|
padding: 4px;
|
|
background:
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) top left / 14px 1px no-repeat,
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) top left / 1px 14px no-repeat,
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) top right / 14px 1px no-repeat,
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) top right / 1px 14px no-repeat,
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) bottom left / 14px 1px no-repeat,
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) bottom left / 1px 14px no-repeat,
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) bottom right / 14px 1px no-repeat,
|
|
linear-gradient(hsl(var(--primary)), hsl(var(--primary))) bottom right / 1px 14px no-repeat;
|
|
}
|
|
.deco-step > * {
|
|
display: block;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
/* deco-grain — 3% film-grain noise, dark surfaces only. */
|
|
.deco-grain {
|
|
position: relative;
|
|
isolation: isolate;
|
|
}
|
|
.deco-grain::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: -1;
|
|
pointer-events: none;
|
|
opacity: 0.03;
|
|
background-image:
|
|
repeating-radial-gradient(circle at 17% 23%, hsl(var(--foreground)) 0 1px, transparent 1px 3px),
|
|
repeating-radial-gradient(circle at 73% 61%, hsl(var(--foreground)) 0 1px, transparent 1px 3px);
|
|
mix-blend-mode: overlay;
|
|
}
|
|
|
|
/* deco-foil — inset gold "stamp" shadow used on hover states. */
|
|
.deco-foil {
|
|
box-shadow:
|
|
inset 0 0 0 1px hsl(var(--primary)),
|
|
inset 0 1px 0 hsl(var(--primary) / 0.6),
|
|
inset 0 -1px 0 hsl(var(--primary) / 0.3);
|
|
}
|
|
|
|
/* deco-sunburst — conic-gradient sunburst rays. Used by divider_fan & marquee_hero. */
|
|
.deco-sunburst {
|
|
background-image:
|
|
conic-gradient(
|
|
from 180deg at 50% 100%,
|
|
transparent 0deg,
|
|
hsl(var(--primary) / 0.7) 5deg,
|
|
transparent 10deg,
|
|
transparent 20deg,
|
|
hsl(var(--primary) / 0.55) 25deg,
|
|
transparent 30deg,
|
|
transparent 40deg,
|
|
hsl(var(--primary) / 0.7) 45deg,
|
|
transparent 50deg,
|
|
transparent 60deg,
|
|
hsl(var(--primary) / 0.55) 65deg,
|
|
transparent 70deg,
|
|
transparent 80deg,
|
|
hsl(var(--primary) / 0.7) 85deg,
|
|
transparent 90deg,
|
|
transparent 100deg,
|
|
hsl(var(--primary) / 0.55) 105deg,
|
|
transparent 110deg,
|
|
transparent 120deg,
|
|
hsl(var(--primary) / 0.7) 125deg,
|
|
transparent 130deg,
|
|
transparent 140deg,
|
|
hsl(var(--primary) / 0.55) 145deg,
|
|
transparent 150deg,
|
|
transparent 160deg,
|
|
hsl(var(--primary) / 0.7) 165deg,
|
|
transparent 170deg,
|
|
transparent 180deg
|
|
);
|
|
}
|
|
|
|
/* deco-scallop — scalloped fan crest via radial gradient. */
|
|
.deco-scallop {
|
|
background-image:
|
|
radial-gradient(circle at 50% 100%, hsl(var(--primary) / 0.7) 0 2px, transparent 3px),
|
|
repeating-linear-gradient(
|
|
to right,
|
|
transparent 0,
|
|
transparent 12px,
|
|
hsl(var(--primary) / 0.55) 12px,
|
|
hsl(var(--primary) / 0.55) 13px,
|
|
transparent 13px,
|
|
transparent 24px
|
|
);
|
|
}
|
|
|
|
/* deco-ziggurat — stepped ziggurat divider stripes. */
|
|
.deco-ziggurat {
|
|
background-image:
|
|
linear-gradient(to bottom, transparent 0 30%, hsl(var(--primary)) 30% 32%, transparent 32% 50%, hsl(var(--primary)) 50% 52%, transparent 52% 70%, hsl(var(--primary)) 70% 72%, transparent 72% 100%);
|
|
}
|
|
|
|
/* deco-caps — caps tracking helper for Italiana display headings. */
|
|
.deco-caps {
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.18em;
|
|
}
|
|
|
|
/* deco-dropcap — classical italic dropcap on first paragraph. */
|
|
.deco-dropcap[data-deco-dropcap]::first-letter {
|
|
font-family: var(--font-body, "Cormorant Garamond", "Cormorant", Georgia, serif);
|
|
font-style: italic;
|
|
font-size: 3.2em;
|
|
line-height: 0.95;
|
|
float: left;
|
|
padding: 0.05em 0.12em 0 0;
|
|
color: hsl(var(--primary));
|
|
}
|
|
|
|
/* deco-underline — hairline gold underline on headings. */
|
|
.deco-underline {
|
|
position: relative;
|
|
padding-bottom: 0.35em;
|
|
}
|
|
.deco-underline::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
height: 1px;
|
|
background: hsl(var(--primary));
|
|
}
|
|
|
|
/* deco-pill — black pill button base for the button override. */
|
|
.deco-pill {
|
|
border-radius: 9999px;
|
|
border-width: 1px;
|
|
border-style: solid;
|
|
border-color: hsl(var(--primary));
|
|
background-color: hsl(var(--foreground));
|
|
color: hsl(var(--background));
|
|
padding: 0.65rem 1.6rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.18em;
|
|
font-size: 0.85rem;
|
|
transition: box-shadow 200ms ease, background-color 200ms ease;
|
|
}
|
|
.deco-pill:hover,
|
|
.deco-pill:focus-visible {
|
|
box-shadow:
|
|
inset 0 0 0 1px hsl(var(--primary)),
|
|
inset 0 1px 0 hsl(var(--primary) / 0.6),
|
|
inset 0 -1px 0 hsl(var(--primary) / 0.4);
|
|
}
|
|
.deco-pill:focus-visible {
|
|
outline: 2px solid hsl(var(--ring));
|
|
outline-offset: 3px;
|
|
}
|
|
|
|
/* deco-link — gold underline link state. */
|
|
.deco-link {
|
|
color: hsl(var(--primary));
|
|
text-decoration: none;
|
|
border-bottom: 1px solid hsl(var(--primary));
|
|
transition: color 200ms ease, border-color 200ms ease;
|
|
}
|
|
.deco-link:hover,
|
|
.deco-link:focus-visible {
|
|
color: hsl(var(--accent));
|
|
border-bottom-color: hsl(var(--accent));
|
|
}
|
|
}
|