fix(brutalist): Wave B design-review remediation + fresh gallery captures (0.6.0)
- Article title no longer rendered twice: seed article pages drop the duplicate level-1 heading block; the article template's page <h1> is the sole title. - Home dead gap resolved: landing sections divided by a hard 4px rule. The CMS wraps each block in its own <div data-block-id>, so the divider adjacency now targets the block wrappers ([data-block-id]+[data-block-id] .bru-section), not the (non-sibling) sections; landing section padding reduced 4rem->3rem. - SVG geometry guard completed: explicit width/height on every <use> icon SVG, including the 5 testimonial star ratings the earlier regex missed (the ">=" in their class conditional). - Seed quality: HARDSET site title hardset; article expanded to ~9 hard-edged paragraphs to kill the below-article void. - Fresh 2880x1800 light+dark captures for home/about/article; preview = home-light. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ -477,6 +477,16 @@ css:
|
|||||||
|
|
||||||
.bru-section { padding: 2.75rem 0; }
|
.bru-section { padding: 2.75rem 0; }
|
||||||
@media (min-width: 768px) { .bru-section { padding: 4rem 0; } }
|
@media (min-width: 768px) { .bru-section { padding: 4rem 0; } }
|
||||||
|
/* Landing: stacked full-bleed sections butt against a hard rule instead of
|
||||||
|
doubling their padding into a dead void (Wave B design-review fix). The CMS
|
||||||
|
wraps every block in its own <div data-block-id>, so the .bru-section
|
||||||
|
elements are NOT DOM siblings — the divider adjacency must target the block
|
||||||
|
wrappers ([data-block-id] + [data-block-id]), not the sections. */
|
||||||
|
[data-brutalist-template="landing"] main .bru-section { padding-top: 2.75rem; padding-bottom: 2.75rem; }
|
||||||
|
[data-brutalist-template="landing"] main [data-block-id] + [data-block-id] .bru-section { border-top: 4px solid hsl(var(--border)); }
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
[data-brutalist-template="landing"] main .bru-section { padding-top: 3rem; padding-bottom: 3rem; }
|
||||||
|
}
|
||||||
.bru-wrap { width: 100%; max-width: 80rem; margin: 0 auto; padding: 0 1.5rem; }
|
.bru-wrap { width: 100%; max-width: 80rem; margin: 0 auto; padding: 0 1.5rem; }
|
||||||
.bru-wrap-mid { width: 100%; max-width: 64rem; margin: 0 auto; padding: 0 1.5rem; }
|
.bru-wrap-mid { width: 100%; max-width: 64rem; margin: 0 auto; padding: 0 1.5rem; }
|
||||||
.bru-wrap-narrow { width: 100%; max-width: 44rem; margin: 0 auto; padding: 0 1.5rem; }
|
.bru-wrap-narrow { width: 100%; max-width: 44rem; margin: 0 auto; padding: 0 1.5rem; }
|
||||||
@ -647,9 +657,9 @@ css:
|
|||||||
.bru-spec-row dt { text-transform: uppercase; color: hsl(var(--muted-foreground)); }
|
.bru-spec-row dt { text-transform: uppercase; color: hsl(var(--muted-foreground)); }
|
||||||
.bru-spec-row dd { margin: 0; text-align: right; color: hsl(var(--foreground)); }
|
.bru-spec-row dd { margin: 0; text-align: right; color: hsl(var(--foreground)); }
|
||||||
|
|
||||||
/* Base media guarantee (element selector; mirrors Tailwind preflight).
|
/* Base media guarantee: element selector mirroring Tailwind preflight.
|
||||||
All utility-class layout scaffolding (grid/grid-cols/col-span/p-*/
|
All utility-class layout scaffolding -- grid, grid-cols, col-span, p,
|
||||||
gap-*/space-y-*/aspect-*/object-*/w-h-full + sm|md|lg variants) was
|
gap, space-y, aspect, object, w/h-full plus sm/md/lg variants -- was
|
||||||
removed here: the host Tailwind build now scans theme .ninjatpl
|
removed here: the host Tailwind build now scans theme .ninjatpl
|
||||||
templates, so those classes compile natively from template usage. */
|
templates, so those classes compile natively from template usage. */
|
||||||
.brutalist-page img { max-width: 100%; }
|
.brutalist-page img { max-width: 100%; }
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
name = "brutalist"
|
name = "brutalist"
|
||||||
display_name = "Brutalist"
|
display_name = "Brutalist"
|
||||||
scope = "@themes"
|
scope = "@themes"
|
||||||
version = "0.5.2"
|
version = "0.6.0"
|
||||||
description = "Concrete, oversized type, hard 12-col grid theme for design studios, architecture firms and art galleries."
|
description = "Concrete, oversized type, hard 12-col grid theme for design studios, architecture firms and art galleries."
|
||||||
kind = "theme"
|
kind = "theme"
|
||||||
categories = ["templates"]
|
categories = ["templates"]
|
||||||
|
|||||||
BIN
preview.png
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 137 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 428 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 436 KiB |
@ -86,7 +86,7 @@
|
|||||||
"block_key": "brutalist:spec_sheet",
|
"block_key": "brutalist:spec_sheet",
|
||||||
"title": "Studio facts",
|
"title": "Studio facts",
|
||||||
"slot": "main",
|
"slot": "main",
|
||||||
"sort_order": 3,
|
"sort_order": 4,
|
||||||
"content": {
|
"content": {
|
||||||
"heading": "Studio",
|
"heading": "Studio",
|
||||||
"rows": [
|
"rows": [
|
||||||
@ -101,7 +101,7 @@
|
|||||||
"block_key": "brutalist:changelog",
|
"block_key": "brutalist:changelog",
|
||||||
"title": "Recent",
|
"title": "Recent",
|
||||||
"slot": "main",
|
"slot": "main",
|
||||||
"sort_order": 4,
|
"sort_order": 5,
|
||||||
"content": {
|
"content": {
|
||||||
"heading": "Lately",
|
"heading": "Lately",
|
||||||
"entries": [
|
"entries": [
|
||||||
@ -110,7 +110,7 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 5, "content": { "style": "pull", "quote": "Make it obvious, then make it loud.", "attribution": "HARDSET" } }
|
{ "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 3, "content": { "style": "pull", "quote": "Make it obvious, then make it loud.", "attribution": "HARDSET" } }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -129,8 +129,7 @@
|
|||||||
"template_key": "article",
|
"template_key": "article",
|
||||||
"parent_slug": "/blog",
|
"parent_slug": "/blog",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "In praise of a hard border", "level": 1 } },
|
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 1, "content": { "html": "<p>A soft shadow asks you to squint. A hard border does not. It draws the edge, holds the block, and tells you where one thing ends and the next begins. We reach for the line first because it is honest.</p><p>The border is the cheapest structure in design. One rule, one weight, and a page stops being a soup of floating cards. It prints. It reads on a bad screen in bright sun. It survives a screenshot pasted into a slide deck at quarter size.</p><p>We came to it the hard way. Early on we chased depth — blurs, gradients, shadows stacked three deep to fake a little lift. It looked fine in the file and fell apart in the wild. On a cheap monitor the shadows vanished and the whole layout went flat.</p><p>A border never vanishes. It is one pixel or it is four, and it is there in every rendering context you will ever ship into. When a client forwards a mockup to their printer, the printer sees the same edges we did.</p><p>There is a discipline in it too. A border forces you to decide where a thing begins. You cannot let a section bleed vaguely into the next and hope the eye sorts it out. You commit to the edge, and the commitment shows.</p><p>Weight is the only variable that matters. A hairline says these belong together, quietly. A four-pixel rule says stop here, this is a wall. We keep two weights on most projects and never more than three. Past that the borders start arguing with each other.</p><p>Colour is where the energy comes from. The border stays black. Then we add one loud accent — a single hot hue — and let it do all the shouting. Black holds the structure; the accent carries the mood. That split keeps a loud page from turning to noise.</p><p>Offset is the last trick. Take a bordered block and drop a hard shadow four pixels down and right — no blur, just a second solid shape. Now the block sits on the page like a physical object. It reads as printed, stamped, real. It is the whole brutalist move in one property.</p><p>None of this is nostalgia. We are not printing zines. We are building interfaces that have to survive resizing, dark mode, reduced motion, and a decade of browser churn. Hard edges survive all of it because there is nothing to degrade.</p><p>So we start with the line. Draw the edge, hold the block, pick one loud colour, offset the shadow. That is the whole trick, and it has never once let us down on a real screen in bright sun.</p>" } }
|
||||||
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>A soft shadow asks you to squint. A hard border does not. It draws the edge, holds the block, and tells you where one thing ends and the next begins.</p><p>We reach for the line first. It is honest. It prints. It reads on a bad screen in bright sun. When we want energy we add one loud colour and a hard offset. That is the whole trick.</p>" } }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -139,8 +138,7 @@
|
|||||||
"template_key": "article",
|
"template_key": "article",
|
||||||
"parent_slug": "/blog",
|
"parent_slug": "/blog",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "Ship the ugly first draft", "level": 1 } },
|
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 1, "content": { "html": "<p>The first draft is meant to be wrong. Its only job is to exist. Once it is on a real screen, the real problems show up and the fake ones you were bracing for quietly disappear.</p><p>We ship early and we ship rough. A grey box where the photo goes, placeholder copy that says what it needs to say, a layout held together with the bluntest possible structure. Ugly, but real, and in front of someone who can react to it.</p><p>The point is to move the argument out of the abstract. Nobody can usefully review a description of a page. Everybody can react to a page. The ugly draft turns opinions into decisions because there is finally something concrete to point at.</p><p>It also keeps us honest. A polished mock hides its weak spots under nice type and a good photo. A rough one has nowhere to hide — if the structure is wrong, the rough draft shows it on day one, while it is still cheap to fix.</p><p>Polish comes last, after the shape is right. We would rather spend the back half of a project making a correct thing beautiful than the front half making a wrong thing pretty. Ship the ugly draft. Let it take the hits. Then make it good.</p>" } }
|
||||||
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>The first draft is meant to be wrong. Its job is to exist. Once it is on a real screen, the real problems show up and the fake ones fall away.</p><p>We ship early and often. It keeps the brief honest and the feedback specific. Polish comes last, after the shape is right.</p>" } }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -149,8 +147,7 @@
|
|||||||
"template_key": "article",
|
"template_key": "article",
|
||||||
"parent_slug": "/blog",
|
"parent_slug": "/blog",
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "Set it in one typeface", "level": 1 } },
|
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 1, "content": { "html": "<p>One family, used well, beats three used at random. Pick a face with real range, learn its weights, and let scale do the talking. Most projects need far less type than they think.</p><p>Range is the thing to look for. A grotesque with a heavy black, a workable regular, and a tight mono cousin can carry an entire site — headlines, body, meta, code — without ever reaching for a second family.</p><p>The discipline pays off in coherence. When every word on a site comes from one voice, the page reads as one thing. Mixing families is how sites end up feeling like a ransom note assembled from three different brands.</p><p>It pays off in engineering too. One family is fewer font files, fewer weights to load, less layout shift while they arrive. The performance budget thanks you, and so does anyone on a slow connection.</p><p>We set most of a project in a single grotesque. Big and tight for headlines, plain for body, mono for the small print. The result reads as one voice speaking at different volumes — which is exactly what a brand should sound like.</p>" } }
|
||||||
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>One family, used well, beats three used at random. Pick a face with range, learn its weights, and let scale do the talking.</p><p>We set most of a project in a single grotesque. Big for headlines, tight for meta, plain for body. The result reads as one voice.</p>" } }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<div data-bn-announcement data-bn-annkey="{{ variant|default:"promo" }}:{{ message|slugify }}" class="bn-announcement w-full {{ class }}" style="{{ annstyle }};border-bottom:3px solid hsl(var(--border))">
|
<div data-bn-announcement data-bn-annkey="{{ variant|default:"promo" }}:{{ message|slugify }}" class="bn-announcement w-full {{ class }}" style="{{ annstyle }};border-bottom:3px solid hsl(var(--border))">
|
||||||
<div class="bru-wrap py-2 relative flex items-center justify-center gap-2">
|
<div class="bru-wrap py-2 relative flex items-center justify-center gap-2">
|
||||||
<p class="bru-meta" style="color:inherit;letter-spacing:0.08em">{{ message }}{% if linkText and linkUrl %} <a href="{{ linkUrl }}" class="underline underline-offset-2 hover:opacity-80">{{ linkText }}</a>{% endif %}</p>
|
<p class="bru-meta" style="color:inherit;letter-spacing:0.08em">{{ message }}{% if linkText and linkUrl %} <a href="{{ linkUrl }}" class="underline underline-offset-2 hover:opacity-80">{{ linkText }}</a>{% endif %}</p>
|
||||||
{% if dismissable %}<button type="button" data-bn-ann-dismiss aria-label="Dismiss announcement" class="absolute right-3 top-1/2 -translate-y-1/2 inline-flex items-center justify-center p-1"><svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#x"></use></svg></button>{% endif %}
|
{% if dismissable %}<button type="button" data-bn-ann-dismiss aria-label="Dismiss announcement" class="absolute right-3 top-1/2 -translate-y-1/2 inline-flex items-center justify-center p-1"><svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#x"></use></svg></button>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if dismissable %}<script>
|
{% if dismissable %}<script>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{# brutalist audio-embed override — bordered player card. Fields: url, media, artwork, title, artist, download. #}
|
{# brutalist audio-embed override — bordered player card. Fields: url, media, artwork, title, artist, download. #}
|
||||||
<figure class="bn-audio my-8 bru-slab bru-shadow overflow-hidden{% if class %} {{ class }}{% endif %}" data-bn-audio data-audio-url="{{ url|default:"" }}" data-audio-media="{% if media %}{{ media|mediaURL }}{% endif %}"><div class="flex items-center gap-4 p-4">{% if artwork %}<div class="h-16 w-16 shrink-0 overflow-hidden bg-muted" style="border:2px solid hsl(var(--border))">{% img artwork alt=title|default:"" class="h-full w-full object-cover" %}</div>{% endif %}<div class="min-w-0 flex-1">{% if title %}<p class="bru-kicker truncate" style="font-size:1rem;text-transform:none">{{ title }}</p>{% endif %}{% if artist %}<p class="bru-meta truncate">{{ artist }}</p>{% endif %}<div class="mt-2 flex items-center gap-3" data-bn-audio-slot><button type="button" data-bn-audio-play class="bru-btn bru-btn-solid" style="padding:0.4rem 0.9rem;box-shadow:2px 2px 0 0 hsl(var(--border))" aria-label="Play{% if title %}: {{ title }}{% endif %}"><svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg>Play</button>{% if download %}<a href="{% if media %}{{ media|mediaURL }}{% else %}{{ url }}{% endif %}" download class="bru-meta inline-flex items-center gap-1 text-foreground">Download</a>{% endif %}</div></div></div></figure><script>
|
<figure class="bn-audio my-8 bru-slab bru-shadow overflow-hidden{% if class %} {{ class }}{% endif %}" data-bn-audio data-audio-url="{{ url|default:"" }}" data-audio-media="{% if media %}{{ media|mediaURL }}{% endif %}"><div class="flex items-center gap-4 p-4">{% if artwork %}<div class="h-16 w-16 shrink-0 overflow-hidden bg-muted" style="border:2px solid hsl(var(--border))">{% img artwork alt=title|default:"" class="h-full w-full object-cover" %}</div>{% endif %}<div class="min-w-0 flex-1">{% if title %}<p class="bru-kicker truncate" style="font-size:1rem;text-transform:none">{{ title }}</p>{% endif %}{% if artist %}<p class="bru-meta truncate">{{ artist }}</p>{% endif %}<div class="mt-2 flex items-center gap-3" data-bn-audio-slot><button type="button" data-bn-audio-play class="bru-btn bru-btn-solid" style="padding:0.4rem 0.9rem;box-shadow:2px 2px 0 0 hsl(var(--border))" aria-label="Play{% if title %}: {{ title }}{% endif %}"><svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg>Play</button>{% if download %}<a href="{% if media %}{{ media|mediaURL }}{% else %}{{ url }}{% endif %}" download class="bru-meta inline-flex items-center gap-1 text-foreground">Download</a>{% endif %}</div></div></div></figure><script>
|
||||||
(function(){
|
(function(){
|
||||||
if(window.__bnAudioFacade)return;window.__bnAudioFacade=true;
|
if(window.__bnAudioFacade)return;window.__bnAudioFacade=true;
|
||||||
document.addEventListener('click',function(e){
|
document.addEventListener('click',function(e){
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<button type="button" onclick="this.nextElementSibling.classList.toggle('hidden')" class="flex items-center gap-2 bru-meta px-3 py-1.5 text-foreground hover:text-accent transition-colors">
|
<button type="button" onclick="this.nextElementSibling.classList.toggle('hidden')" class="flex items-center gap-2 bru-meta px-3 py-1.5 text-foreground hover:text-accent transition-colors">
|
||||||
<span class="inline-flex items-center justify-center w-7 h-7 text-xs" style="background:hsl(var(--accent));color:hsl(var(--accent-foreground));border:2px solid hsl(var(--border));font-family:var(--font-heading,sans-serif);font-weight:700">{{ displayName|first }}</span>
|
<span class="inline-flex items-center justify-center w-7 h-7 text-xs" style="background:hsl(var(--accent));color:hsl(var(--accent-foreground));border:2px solid hsl(var(--border));font-family:var(--font-heading,sans-serif);font-weight:700">{{ displayName|first }}</span>
|
||||||
<span>{{ displayName }}</span>
|
<span>{{ displayName }}</span>
|
||||||
<svg class="w-3 h-3" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
<svg width="12" height="12" class="w-3 h-3" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
||||||
</button>
|
</button>
|
||||||
<div id="auth-dropdown-menu" class="hidden absolute right-0 top-full mt-2 w-48 bru-slab bru-shadow py-1 z-50">
|
<div id="auth-dropdown-menu" class="hidden absolute right-0 top-full mt-2 w-48 bru-slab bru-shadow py-1 z-50">
|
||||||
<a href="/account" class="block px-4 py-2 text-sm text-foreground hover:bg-accent hover:text-accent-foreground">My Profile</a>
|
<a href="/account" class="block px-4 py-2 text-sm text-foreground hover:bg-accent hover:text-accent-foreground">My Profile</a>
|
||||||
|
|||||||
@ -11,10 +11,10 @@
|
|||||||
{% if author.location %}<span>{{ author.location }}</span>{% endif %}
|
{% if author.location %}<span>{{ author.location }}</span>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if showSocial %}<div class="mt-5 flex items-center justify-center gap-3">
|
{% if showSocial %}<div class="mt-5 flex items-center justify-center gap-3">
|
||||||
{% if author.website_url %}<a href="{{ author.website_url }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="Website"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/lucide.svg#globe"></use></svg></a>{% endif %}
|
{% if author.website_url %}<a href="{{ author.website_url }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="Website"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/lucide.svg#globe"></use></svg></a>{% endif %}
|
||||||
{% if author.twitter_handle %}<a href="https://twitter.com/{{ author.twitter_handle|cut:"@" }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="Twitter"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#x"></use></svg></a>{% endif %}
|
{% if author.twitter_handle %}<a href="https://twitter.com/{{ author.twitter_handle|cut:"@" }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="Twitter"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#x"></use></svg></a>{% endif %}
|
||||||
{% if author.linkedin_url %}<a href="{{ author.linkedin_url }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="LinkedIn"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#linkedin"></use></svg></a>{% endif %}
|
{% if author.linkedin_url %}<a href="{{ author.linkedin_url }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="LinkedIn"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#linkedin"></use></svg></a>{% endif %}
|
||||||
{% if author.github_url %}<a href="{{ author.github_url }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="GitHub"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#github"></use></svg></a>{% endif %}
|
{% if author.github_url %}<a href="{{ author.github_url }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-accent" title="GitHub"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#github"></use></svg></a>{% endif %}
|
||||||
</div>{% endif %}
|
</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
{% if showHome %}<li class="flex items-center"><a href="/" class="text-muted-foreground transition-colors hover:text-accent">{{ homeLabel|default:"Home" }}</a></li>{% endif %}
|
{% if showHome %}<li class="flex items-center"><a href="/" class="text-muted-foreground transition-colors hover:text-accent">{{ homeLabel|default:"Home" }}</a></li>{% endif %}
|
||||||
{% for item in breadcrumbs %}
|
{% for item in breadcrumbs %}
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
{% if showHome or not forloop.First %}{% if arrows %}<svg class="mx-2 h-4 w-4 text-muted-foreground" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"></use></svg>{% else %}<span class="mx-2 text-muted-foreground">{{ separator|default:"/" }}</span>{% endif %}{% endif %}
|
{% if showHome or not forloop.First %}{% if arrows %}<svg width="16" height="16" class="mx-2 h-4 w-4 text-muted-foreground" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"></use></svg>{% else %}<span class="mx-2 text-muted-foreground">{{ separator|default:"/" }}</span>{% endif %}{% endif %}
|
||||||
{% if item.is_current %}{% if showCurrent %}<span class="text-foreground" aria-current="page">{{ item.label }}</span>{% endif %}{% else %}<a href="{{ item.url }}" class="text-muted-foreground transition-colors hover:text-accent">{{ item.label }}</a>{% endif %}
|
{% if item.is_current %}{% if showCurrent %}<span class="text-foreground" aria-current="page">{{ item.label }}</span>{% endif %}{% else %}<a href="{{ item.url }}" class="text-muted-foreground transition-colors hover:text-accent">{{ item.label }}</a>{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
{# brutalist button override — square, hard border, offset shadow, hover snap. Fields: label, link, style, size, icon, iconPosition, align, newTab. #}
|
{# brutalist button override — square, hard border, offset shadow, hover snap. Fields: label, link, style, size, icon, iconPosition, align, newTab. #}
|
||||||
{% with align=align|default:"left" %}<div class="flex {% if align == "center" %}justify-center{% elif align == "right" %}justify-end{% else %}justify-start{% endif %}{% if class %} {{ class }}{% endif %}"><a href="{{ link|default:"#" }}"{% if newTab %} target="_blank" rel="noopener noreferrer"{% endif %} class="bru-btn {% if style == "secondary" or style == "outline" or style == "ghost" or style == "link" %}bru-btn-ghost{% else %}bru-btn-solid{% endif %}{% if size == "sm" %} text-[0.7rem] px-3 py-2{% elif size == "lg" %} text-sm px-6 py-3.5{% endif %}">{% if icon and iconPosition != "right" %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}{{ label|default:"Learn more" }}{% if icon and iconPosition == "right" %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}</a></div>{% endwith %}
|
{% with align=align|default:"left" %}<div class="flex {% if align == "center" %}justify-center{% elif align == "right" %}justify-end{% else %}justify-start{% endif %}{% if class %} {{ class }}{% endif %}"><a href="{{ link|default:"#" }}"{% if newTab %} target="_blank" rel="noopener noreferrer"{% endif %} class="bru-btn {% if style == "secondary" or style == "outline" or style == "ghost" or style == "link" %}bru-btn-ghost{% else %}bru-btn-solid{% endif %}{% if size == "sm" %} text-[0.7rem] px-3 py-2{% elif size == "lg" %} text-sm px-6 py-3.5{% endif %}">{% if icon and iconPosition != "right" %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}{{ label|default:"Learn more" }}{% if icon and iconPosition == "right" %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}</a></div>{% endwith %}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<div class="mt-10 grid grid-cols-1 gap-4 {% if columns == 3 %}sm:grid-cols-2 lg:grid-cols-3{% elif columns == 1 %}{% else %}sm:grid-cols-2{% endif %}">
|
<div class="mt-10 grid grid-cols-1 gap-4 {% if columns == 3 %}sm:grid-cols-2 lg:grid-cols-3{% elif columns == 1 %}{% else %}sm:grid-cols-2{% endif %}">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<div class="bru-slab bru-shadow-sm bru-hover flex items-start gap-4 p-5">
|
<div class="bru-slab bru-shadow-sm bru-hover flex items-start gap-4 p-5">
|
||||||
{% if channel.icon %}<span class="inline-flex h-11 w-11 shrink-0 items-center justify-center bg-accent text-accent-foreground" style="border:3px solid hsl(var(--border))"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ channel.icon|split:":"|first }}.svg#{{ channel.icon|split:":"|last }}"></use></svg></span>{% endif %}
|
{% if channel.icon %}<span class="inline-flex h-11 w-11 shrink-0 items-center justify-center bg-accent text-accent-foreground" style="border:3px solid hsl(var(--border))"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ channel.icon|split:":"|first }}.svg#{{ channel.icon|split:":"|last }}"></use></svg></span>{% endif %}
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
{% if channel.label %}<div class="bru-meta text-muted-foreground">{{ channel.label }}</div>{% endif %}
|
{% if channel.label %}<div class="bru-meta text-muted-foreground">{{ channel.label }}</div>{% endif %}
|
||||||
{% if channel.value %}<div class="mt-0.5 break-words bru-kicker" style="font-size:1rem;text-transform:none">{% if channel.link %}<a href="{{ channel.link }}" class="transition-colors hover:text-accent">{{ channel.value }}</a>{% else %}{{ channel.value }}{% endif %}</div>{% endif %}
|
{% if channel.value %}<div class="mt-0.5 break-words bru-kicker" style="font-size:1rem;text-transform:none">{% if channel.link %}<a href="{{ channel.link }}" class="transition-colors hover:text-accent">{{ channel.value }}</a>{% else %}{{ channel.value }}{% endif %}</div>{% endif %}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<div class="bru-wrap-narrow">
|
<div class="bru-wrap-narrow">
|
||||||
{% if form.submitted %}
|
{% if form.submitted %}
|
||||||
<div class="bru-slab bru-shadow p-8 text-center">
|
<div class="bru-slab bru-shadow p-8 text-center">
|
||||||
<div class="mx-auto mb-4 inline-flex h-12 w-12 items-center justify-center text-accent-foreground" style="background:hsl(var(--accent));border:3px solid hsl(var(--border))"><svg class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg></div>
|
<div class="mx-auto mb-4 inline-flex h-12 w-12 items-center justify-center text-accent-foreground" style="background:hsl(var(--accent));border:3px solid hsl(var(--border))"><svg width="24" height="24" class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg></div>
|
||||||
<p class="bru-kicker" style="font-size:1.2rem;text-transform:none">{{ form.message|default:successMessage|default:"Thanks — your message has been sent." }}</p>
|
<p class="bru-kicker" style="font-size:1.2rem;text-transform:none">{{ form.message|default:successMessage|default:"Thanks — your message has been sent." }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
{# brutalist divider override — hard rule or icon ornament. Fields: variant, weight, width, icon. #}
|
{# brutalist divider override — hard rule or icon ornament. Fields: variant, weight, width, icon. #}
|
||||||
{% with variant=variant|default:"line" weight=weight|default:"thick" width=width|default:"full" %}{% if variant == "ornament" %}<div class="mx-auto my-10 flex items-center gap-4 {% if width == "narrow" %}max-w-[200px]{% elif width == "wide" %}max-w-3xl{% else %}w-full{% endif %}{% if class %} {{ class }}{% endif %}" role="separator"><span class="flex-1" style="border-top:3px solid hsl(var(--border))"></span><svg class="h-5 w-5 text-accent" aria-hidden="true"><use href="/icons/{{ icon|default:"lucide:asterisk"|split:":"|first }}.svg#{{ icon|default:"lucide:asterisk"|split:":"|last }}"></use></svg><span class="flex-1" style="border-top:3px solid hsl(var(--border))"></span></div>{% else %}<hr class="mx-auto my-10 {% if weight == "thin" %}bru-rule-thin{% else %}bru-rule{% endif %} {% if width == "narrow" %}max-w-[200px]{% elif width == "wide" %}max-w-3xl{% else %}w-full{% endif %}{% if class %} {{ class }}{% endif %}" role="separator">{% endif %}{% endwith %}
|
{% with variant=variant|default:"line" weight=weight|default:"thick" width=width|default:"full" %}{% if variant == "ornament" %}<div class="mx-auto my-10 flex items-center gap-4 {% if width == "narrow" %}max-w-[200px]{% elif width == "wide" %}max-w-3xl{% else %}w-full{% endif %}{% if class %} {{ class }}{% endif %}" role="separator"><span class="flex-1" style="border-top:3px solid hsl(var(--border))"></span><svg width="20" height="20" class="h-5 w-5 text-accent" aria-hidden="true"><use href="/icons/{{ icon|default:"lucide:asterisk"|split:":"|first }}.svg#{{ icon|default:"lucide:asterisk"|split:":"|last }}"></use></svg><span class="flex-1" style="border-top:3px solid hsl(var(--border))"></span></div>{% else %}<hr class="mx-auto my-10 {% if weight == "thin" %}bru-rule-thin{% else %}bru-rule{% endif %} {% if width == "narrow" %}max-w-[200px]{% elif width == "wide" %}max-w-3xl{% else %}w-full{% endif %}{% if class %} {{ class }}{% endif %}" role="separator">{% endif %}{% endwith %}
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
<details class="group bru-slab bru-shadow-sm px-5"{% if variant == "open-list" %} open{% endif %}>
|
<details class="group bru-slab bru-shadow-sm px-5"{% if variant == "open-list" %} open{% endif %}>
|
||||||
<summary class="flex cursor-pointer list-none items-center justify-between gap-4 py-4 text-lg font-medium marker:content-none [&::-webkit-details-marker]:hidden">
|
<summary class="flex cursor-pointer list-none items-center justify-between gap-4 py-4 text-lg font-medium marker:content-none [&::-webkit-details-marker]:hidden">
|
||||||
<span class="bru-kicker" style="font-size:1.05rem;text-transform:none">{{ item.question }}</span>
|
<span class="bru-kicker" style="font-size:1.05rem;text-transform:none">{{ item.question }}</span>
|
||||||
<svg class="h-5 w-5 shrink-0 text-accent transition-transform duration-200 group-open:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
<svg width="20" height="20" class="h-5 w-5 shrink-0 text-accent transition-transform duration-200 group-open:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="pb-4 text-muted-foreground [&_a]:text-accent [&_a]:underline">{{ item.answer|safe }}</div>
|
<div class="pb-4 text-muted-foreground [&_a]:text-accent [&_a]:underline">{{ item.answer|safe }}</div>
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<div class="mt-12 grid grid-cols-1 gap-6 sm:grid-cols-2 {% if columns == 2 %}lg:grid-cols-2{% elif columns == 4 %}lg:grid-cols-4{% else %}lg:grid-cols-3{% endif %}">
|
<div class="mt-12 grid grid-cols-1 gap-6 sm:grid-cols-2 {% if columns == 2 %}lg:grid-cols-2{% elif columns == 4 %}lg:grid-cols-4{% else %}lg:grid-cols-3{% endif %}">
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<div class="bru-slab bru-shadow bru-hover flex flex-col gap-2 p-6{% if layout == "centered" %} text-center items-center{% endif %}">
|
<div class="bru-slab bru-shadow bru-hover flex flex-col gap-2 p-6{% if layout == "centered" %} text-center items-center{% endif %}">
|
||||||
{% if item.icon %}<div class="mb-2 inline-flex h-12 w-12 items-center justify-center bg-accent text-accent-foreground" style="border:3px solid hsl(var(--border))"><svg class="h-6 w-6" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg></div>{% endif %}
|
{% if item.icon %}<div class="mb-2 inline-flex h-12 w-12 items-center justify-center bg-accent text-accent-foreground" style="border:3px solid hsl(var(--border))"><svg width="24" height="24" class="h-6 w-6" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg></div>{% endif %}
|
||||||
<h3 class="bru-kicker" style="font-size:1.15rem;text-transform:none">{% if item.linkUrl %}<a href="{{ item.linkUrl }}" class="transition-colors hover:text-accent">{{ item.title }}</a>{% else %}{{ item.title }}{% endif %}</h3>
|
<h3 class="bru-kicker" style="font-size:1.15rem;text-transform:none">{% if item.linkUrl %}<a href="{{ item.linkUrl }}" class="transition-colors hover:text-accent">{{ item.title }}</a>{% else %}{{ item.title }}{% endif %}</h3>
|
||||||
{% if item.text %}<p class="text-muted-foreground">{{ item.text }}</p>{% endif %}
|
{% if item.text %}<p class="text-muted-foreground">{{ item.text }}</p>{% endif %}
|
||||||
{% if item.linkUrl and item.linkLabel %}<a href="{{ item.linkUrl }}" class="bru-meta mt-2 inline-flex items-center gap-1 text-accent">{{ item.linkLabel }} →</a>{% endif %}
|
{% if item.linkUrl and item.linkLabel %}<a href="{{ item.linkUrl }}" class="bru-meta mt-2 inline-flex items-center gap-1 text-accent">{{ item.linkLabel }} →</a>{% endif %}
|
||||||
|
|||||||
@ -19,11 +19,11 @@
|
|||||||
{% if specialHoursNote %}<p class="mt-4 bru-slab-bg px-3 py-2 text-sm text-muted-foreground">{{ specialHoursNote }}</p>{% endif %}
|
{% if specialHoursNote %}<p class="mt-4 bru-slab-bg px-3 py-2 text-sm text-muted-foreground">{{ specialHoursNote }}</p>{% endif %}
|
||||||
{% if address %}<div class="mt-6"><div class="bru-meta text-muted-foreground">Address</div><address class="mt-1 whitespace-pre-line not-italic">{{ address }}</address></div>{% endif %}
|
{% if address %}<div class="mt-6"><div class="bru-meta text-muted-foreground">Address</div><address class="mt-1 whitespace-pre-line not-italic">{{ address }}</address></div>{% endif %}
|
||||||
{% if phone %}<div class="mt-4"><div class="bru-meta text-muted-foreground">Phone</div><a href="tel:{{ phone }}" class="mt-1 inline-block bru-kicker transition-colors hover:text-accent" style="font-size:1rem;text-transform:none">{{ phone }}</a></div>{% endif %}
|
{% if phone %}<div class="mt-4"><div class="bru-meta text-muted-foreground">Phone</div><a href="tel:{{ phone }}" class="mt-1 inline-block bru-kicker transition-colors hover:text-accent" style="font-size:1rem;text-transform:none">{{ phone }}</a></div>{% endif %}
|
||||||
{% if directionsUrl %}<a href="{{ directionsUrl }}" target="_blank" rel="noopener noreferrer" class="bru-btn bru-btn-solid mt-6"><svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#navigation"></use></svg>Get directions</a>{% endif %}
|
{% if directionsUrl %}<a href="{{ directionsUrl }}" target="_blank" rel="noopener noreferrer" class="bru-btn bru-btn-solid mt-6"><svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#navigation"></use></svg>Get directions</a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if mapEmbedUrl %}
|
{% if mapEmbedUrl %}
|
||||||
<div class="bru-slab bru-shadow aspect-square w-full overflow-hidden bg-muted md:aspect-auto">
|
<div class="bru-slab bru-shadow aspect-square w-full overflow-hidden bg-muted md:aspect-auto">
|
||||||
<button type="button" data-map-src="{{ mapEmbedUrl }}" onclick="var f=document.createElement('iframe');f.src=this.getAttribute('data-map-src');f.setAttribute('class','h-full w-full border-0');f.setAttribute('loading','lazy');f.setAttribute('referrerpolicy','no-referrer-when-downgrade');f.setAttribute('title','Map');this.parentNode.replaceChild(f,this);" class="flex h-full min-h-[16rem] w-full items-center justify-center gap-2 bru-meta transition-colors hover:bg-accent hover:text-accent-foreground"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/lucide.svg#map-pin"></use></svg>{{ mapButtonLabel|default:"Load map" }}</button>
|
<button type="button" data-map-src="{{ mapEmbedUrl }}" onclick="var f=document.createElement('iframe');f.src=this.getAttribute('data-map-src');f.setAttribute('class','h-full w-full border-0');f.setAttribute('loading','lazy');f.setAttribute('referrerpolicy','no-referrer-when-downgrade');f.setAttribute('title','Map');this.parentNode.replaceChild(f,this);" class="flex h-full min-h-[16rem] w-full items-center justify-center gap-2 bru-meta transition-colors hover:bg-accent hover:text-accent-foreground"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/lucide.svg#map-pin"></use></svg>{{ mapButtonLabel|default:"Load map" }}</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,20 +4,20 @@
|
|||||||
{% set cta_url = cta.url|default:ctaUrl %}
|
{% set cta_url = cta.url|default:ctaUrl %}
|
||||||
{% macro brand() %}<a href="/" class="flex-shrink-0 flex items-center">{% if logoType == "text" and logoText.text %}<span class="bru-kicker" style="font-size:1.4rem">{{ logoText.text }}</span>{% elif logo %}<img src="{{ logo }}" alt="{{ alt|default:companyName }}" class="h-8 w-auto"/>{% else %}<span class="bru-kicker" style="font-size:1.4rem">{{ companyName|default:"STUDIO" }}</span>{% endif %}</a>{% endmacro %}
|
{% macro brand() %}<a href="/" class="flex-shrink-0 flex items-center">{% if logoType == "text" and logoText.text %}<span class="bru-kicker" style="font-size:1.4rem">{{ logoText.text }}</span>{% elif logo %}<img src="{{ logo }}" alt="{{ alt|default:companyName }}" class="h-8 w-auto"/>{% else %}<span class="bru-kicker" style="font-size:1.4rem">{{ companyName|default:"STUDIO" }}</span>{% endif %}</a>{% endmacro %}
|
||||||
{% macro navlink(item) %}<a href="{{ item.url|default:"#" }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %}{% if item.title %} title="{{ item.title }}"{% endif %} class="bru-meta px-3 py-2 text-foreground hover:text-accent transition-colors {{ item.css_class }}">{{ item.label }}</a>{% endmacro %}
|
{% macro navlink(item) %}<a href="{{ item.url|default:"#" }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %}{% if item.title %} title="{{ item.title }}"{% endif %} class="bru-meta px-3 py-2 text-foreground hover:text-accent transition-colors {{ item.css_class }}">{{ item.label }}</a>{% endmacro %}
|
||||||
{% macro dropdown(item) %}<div class="relative group"><button type="button" class="bru-meta px-3 py-2 text-foreground hover:text-accent transition-colors inline-flex items-center gap-1">{{ item.label }}<svg class="h-3 w-3" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></button><div class="absolute left-0 mt-0 w-56 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-150 z-50"><div class="mt-2 bru-slab bru-shadow py-2">{% for child in item.children %}{% if child.item_type == "header" %}<div class="bru-meta px-4 py-2 text-muted-foreground">{{ child.label }}</div>{% else %}<a href="{{ child.url|default:"#" }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-4 py-2 text-sm text-foreground hover:bg-accent hover:text-accent-foreground transition-colors {{ child.css_class }}">{{ child.label }}</a>{% endif %}{% endfor %}</div></div></div>{% endmacro %}
|
{% macro dropdown(item) %}<div class="relative group"><button type="button" class="bru-meta px-3 py-2 text-foreground hover:text-accent transition-colors inline-flex items-center gap-1">{{ item.label }}<svg width="12" height="12" class="h-3 w-3" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></button><div class="absolute left-0 mt-0 w-56 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-150 z-50"><div class="mt-2 bru-slab bru-shadow py-2">{% for child in item.children %}{% if child.item_type == "header" %}<div class="bru-meta px-4 py-2 text-muted-foreground">{{ child.label }}</div>{% else %}<a href="{{ child.url|default:"#" }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-4 py-2 text-sm text-foreground hover:bg-accent hover:text-accent-foreground transition-colors {{ child.css_class }}">{{ child.label }}</a>{% endif %}{% endfor %}</div></div></div>{% endmacro %}
|
||||||
{% macro ctabtn(extra) %}{% if cta_text %}<a href="{{ cta_url|default:"#" }}" class="bru-btn bru-btn-solid {{ extra }}" style="padding:0.5rem 1rem">{{ cta_text }}</a>{% endif %}{% endmacro %}
|
{% macro ctabtn(extra) %}{% if cta_text %}<a href="{{ cta_url|default:"#" }}" class="bru-btn bru-btn-solid {{ extra }}" style="padding:0.5rem 1rem">{{ cta_text }}</a>{% endif %}{% endmacro %}
|
||||||
<nav data-bn-navbar data-bn-sticky="{{ sb }}" class="bn-navbar w-full bg-background text-foreground {% if sb == "sticky" or sb == "shrink-on-scroll" %}sticky top-0 z-40 {% endif %}{{ class }}" style="border-bottom:4px solid hsl(var(--border))">
|
<nav data-bn-navbar data-bn-sticky="{{ sb }}" class="bn-navbar w-full bg-background text-foreground {% if sb == "sticky" or sb == "shrink-on-scroll" %}sticky top-0 z-40 {% endif %}{{ class }}" style="border-bottom:4px solid hsl(var(--border))">
|
||||||
{% if showUtilityBar %}<div class="w-full bg-foreground text-background {% if not showOnMobile %}hidden sm:block{% endif %}"><div class="bru-wrap flex items-center justify-between h-8 bru-meta" style="color:hsl(var(--background))"><div>{{ utilityBarText|safe }}</div><div class="flex items-center gap-4">{% if utilityBarPhone %}<a href="tel:{{ utilityBarPhone }}" class="hover:text-accent">{{ utilityBarPhone }}</a>{% endif %}{% if utilityBarEmail %}<a href="mailto:{{ utilityBarEmail }}" class="hover:text-accent">{{ utilityBarEmail }}</a>{% endif %}</div></div></div>{% endif %}
|
{% if showUtilityBar %}<div class="w-full bg-foreground text-background {% if not showOnMobile %}hidden sm:block{% endif %}"><div class="bru-wrap flex items-center justify-between h-8 bru-meta" style="color:hsl(var(--background))"><div>{{ utilityBarText|safe }}</div><div class="flex items-center gap-4">{% if utilityBarPhone %}<a href="tel:{{ utilityBarPhone }}" class="hover:text-accent">{{ utilityBarPhone }}</a>{% endif %}{% if utilityBarEmail %}<a href="mailto:{{ utilityBarEmail }}" class="hover:text-accent">{{ utilityBarEmail }}</a>{% endif %}</div></div></div>{% endif %}
|
||||||
<div class="bru-wrap"><div class="bn-navbar-row flex items-center justify-between h-16">
|
<div class="bru-wrap"><div class="bn-navbar-row flex items-center justify-between h-16">
|
||||||
<div class="flex items-center">{{ brand() }}</div>
|
<div class="flex items-center">{{ brand() }}</div>
|
||||||
<div class="hidden md:flex items-center gap-1">{% for item in menu.items %}{% if item.children %}{{ dropdown(item) }}{% else %}{{ navlink(item) }}{% endif %}{% endfor %}{{ ctabtn("ml-3") }}</div>
|
<div class="hidden md:flex items-center gap-1">{% for item in menu.items %}{% if item.children %}{{ dropdown(item) }}{% else %}{{ navlink(item) }}{% endif %}{% endfor %}{{ ctabtn("ml-3") }}</div>
|
||||||
<div class="flex items-center md:hidden"><label for="bn-navbar-toggle" data-bn-nav-open aria-controls="bn-navbar-drawer" aria-expanded="false" class="inline-flex items-center justify-center p-2 cursor-pointer" style="border:2px solid hsl(var(--border))"><span class="sr-only">Open menu</span><svg class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#menu"></use></svg></label></div>
|
<div class="flex items-center md:hidden"><label for="bn-navbar-toggle" data-bn-nav-open aria-controls="bn-navbar-drawer" aria-expanded="false" class="inline-flex items-center justify-center p-2 cursor-pointer" style="border:2px solid hsl(var(--border))"><span class="sr-only">Open menu</span><svg width="24" height="24" class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#menu"></use></svg></label></div>
|
||||||
</div></div>
|
</div></div>
|
||||||
<input type="checkbox" id="bn-navbar-toggle" class="bn-navbar-toggle" aria-hidden="true"/>
|
<input type="checkbox" id="bn-navbar-toggle" class="bn-navbar-toggle" aria-hidden="true"/>
|
||||||
<label for="bn-navbar-toggle" class="bn-navbar-overlay fixed inset-0 bg-black/50 z-40 md:hidden" aria-hidden="true"></label>
|
<label for="bn-navbar-toggle" class="bn-navbar-overlay fixed inset-0 bg-black/50 z-40 md:hidden" aria-hidden="true"></label>
|
||||||
<div id="bn-navbar-drawer" class="bn-navbar-drawer fixed top-0 right-0 h-full w-80 max-w-[85vw] bg-background text-foreground z-50 md:hidden flex flex-col" style="border-left:4px solid hsl(var(--border))" role="dialog" aria-modal="true" aria-label="Site menu">
|
<div id="bn-navbar-drawer" class="bn-navbar-drawer fixed top-0 right-0 h-full w-80 max-w-[85vw] bg-background text-foreground z-50 md:hidden flex flex-col" style="border-left:4px solid hsl(var(--border))" role="dialog" aria-modal="true" aria-label="Site menu">
|
||||||
<div class="flex items-center justify-between p-4" style="border-bottom:4px solid hsl(var(--border))">{{ brand() }}<label for="bn-navbar-toggle" data-bn-nav-close class="p-2 cursor-pointer text-foreground" style="border:2px solid hsl(var(--border))"><span class="sr-only">Close menu</span><svg class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#x"></use></svg></label></div>
|
<div class="flex items-center justify-between p-4" style="border-bottom:4px solid hsl(var(--border))">{{ brand() }}<label for="bn-navbar-toggle" data-bn-nav-close class="p-2 cursor-pointer text-foreground" style="border:2px solid hsl(var(--border))"><span class="sr-only">Close menu</span><svg width="24" height="24" class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#x"></use></svg></label></div>
|
||||||
<nav class="flex-1 overflow-y-auto py-4" aria-label="Mobile">{% for item in menu.items %}{% if item.children %}<details class="group/acc"><summary class="flex items-center justify-between px-6 py-3 bru-meta cursor-pointer hover:bg-accent hover:text-accent-foreground list-none">{{ item.label }}<svg class="h-3 w-3 transition-transform group-open/acc:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></summary><div class="pl-8 pb-2">{% for child in item.children %}{% if child.item_type != "header" %}<a href="{{ child.url|default:"#" }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-2 py-2 text-sm text-muted-foreground hover:text-foreground">{{ child.label }}</a>{% endif %}{% endfor %}</div></details>{% else %}<a href="{{ item.url|default:"#" }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-6 py-3 bru-meta hover:bg-accent hover:text-accent-foreground">{{ item.label }}</a>{% endif %}{% endfor %}</nav>
|
<nav class="flex-1 overflow-y-auto py-4" aria-label="Mobile">{% for item in menu.items %}{% if item.children %}<details class="group/acc"><summary class="flex items-center justify-between px-6 py-3 bru-meta cursor-pointer hover:bg-accent hover:text-accent-foreground list-none">{{ item.label }}<svg width="12" height="12" class="h-3 w-3 transition-transform group-open/acc:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></summary><div class="pl-8 pb-2">{% for child in item.children %}{% if child.item_type != "header" %}<a href="{{ child.url|default:"#" }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-2 py-2 text-sm text-muted-foreground hover:text-foreground">{{ child.label }}</a>{% endif %}{% endfor %}</div></details>{% else %}<a href="{{ item.url|default:"#" }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-6 py-3 bru-meta hover:bg-accent hover:text-accent-foreground">{{ item.label }}</a>{% endif %}{% endfor %}</nav>
|
||||||
{% if cta_text %}<div class="p-4" style="border-top:4px solid hsl(var(--border))"><a href="{{ cta_url|default:"#" }}" class="bru-btn bru-btn-solid w-full">{{ cta_text }}</a></div>{% endif %}
|
{% if cta_text %}<div class="p-4" style="border-top:4px solid hsl(var(--border))"><a href="{{ cta_url|default:"#" }}" class="bru-btn bru-btn-solid w-full">{{ cta_text }}</a></div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
</p>
|
</p>
|
||||||
{% if tier.description %}<p class="mt-3 text-sm {% if tier.highlighted %}opacity-90{% else %}text-muted-foreground{% endif %}">{{ tier.description }}</p>{% endif %}
|
{% if tier.description %}<p class="mt-3 text-sm {% if tier.highlighted %}opacity-90{% else %}text-muted-foreground{% endif %}">{{ tier.description }}</p>{% endif %}
|
||||||
{% if tier.features %}<ul class="mt-6 flex-1 space-y-3 text-sm">
|
{% if tier.features %}<ul class="mt-6 flex-1 space-y-3 text-sm">
|
||||||
{% for feature in tier.features %}<li class="flex items-start gap-2"><svg class="mt-0.5 h-4 w-4 shrink-0 {% if tier.highlighted %}text-accent-foreground{% else %}text-accent{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg><span>{{ feature }}</span></li>{% endfor %}
|
{% for feature in tier.features %}<li class="flex items-start gap-2"><svg width="16" height="16" class="mt-0.5 h-4 w-4 shrink-0 {% if tier.highlighted %}text-accent-foreground{% else %}text-accent{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg><span>{{ feature }}</span></li>{% endfor %}
|
||||||
</ul>{% endif %}
|
</ul>{% endif %}
|
||||||
{% if tier.ctaUrl and tier.ctaLabel %}<a href="{{ tier.ctaUrl }}" class="bru-btn mt-8 w-full justify-center {% if tier.highlighted %}bru-btn-ghost{% else %}bru-btn-solid{% endif %}">{{ tier.ctaLabel }}</a>{% endif %}
|
{% if tier.ctaUrl and tier.ctaLabel %}<a href="{{ tier.ctaUrl }}" class="bru-btn mt-8 w-full justify-center {% if tier.highlighted %}bru-btn-ghost{% else %}bru-btn-solid{% endif %}">{{ tier.ctaLabel }}</a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% if title %}<h3 class="bru-meta text-foreground {% if compact %}px-2 mb-3{% else %}px-3 mb-4{% endif %}">{{ title }}</h3>{% endif %}
|
{% if title %}<h3 class="bru-meta text-foreground {% if compact %}px-2 mb-3{% else %}px-3 mb-4{% endif %}">{{ title }}</h3>{% endif %}
|
||||||
<ul class="{% if compact %}space-y-0.5{% else %}space-y-1{% endif %}">
|
<ul class="{% if compact %}space-y-0.5{% else %}space-y-1{% endif %}">
|
||||||
{% for item in menu.items %}
|
{% for item in menu.items %}
|
||||||
<li><a href="{{ item.url|default:'#' }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %}{% if item.title %} title="{{ item.title }}"{% endif %} data-bn-sidebar-link class="flex items-center text-sm text-muted-foreground transition-colors hover:text-foreground hover:bg-accent {% if compact %}px-2 py-1.5{% else %}px-3 py-2{% endif %} {{ item.css_class }}">{% if item.icon %}<svg class="mr-2 h-4 w-4 text-accent" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg>{% endif %}{{ item.label }}</a></li>
|
<li><a href="{{ item.url|default:'#' }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %}{% if item.title %} title="{{ item.title }}"{% endif %} data-bn-sidebar-link class="flex items-center text-sm text-muted-foreground transition-colors hover:text-foreground hover:bg-accent {% if compact %}px-2 py-1.5{% else %}px-3 py-2{% endif %} {{ item.css_class }}">{% if item.icon %}<svg width="16" height="16" class="mr-2 h-4 w-4 text-accent" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg>{% endif %}{{ item.label }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
{% for link in links %}{% if link.url %}
|
{% for link in links %}{% if link.url %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ link.url }}" target="_blank" rel="noopener noreferrer" aria-label="{{ link.label|default:link.network }}" class="bru-shadow-sm bru-hover inline-flex items-center gap-2 bg-card text-foreground transition-colors hover:bg-accent hover:text-accent-foreground {% if style == "stack" %}w-full px-4 py-2{% else %}p-2.5{% endif %}" style="border:3px solid hsl(var(--border))">
|
<a href="{{ link.url }}" target="_blank" rel="noopener noreferrer" aria-label="{{ link.label|default:link.network }}" class="bru-shadow-sm bru-hover inline-flex items-center gap-2 bg-card text-foreground transition-colors hover:bg-accent hover:text-accent-foreground {% if style == "stack" %}w-full px-4 py-2{% else %}p-2.5{% endif %}" style="border:3px solid hsl(var(--border))">
|
||||||
{% if link.network %}<svg class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ link.network|split:":"|first }}.svg#{{ link.network|split:":"|last }}"></use></svg>{% endif %}
|
{% if link.network %}<svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ link.network|split:":"|first }}.svg#{{ link.network|split:":"|last }}"></use></svg>{% endif %}
|
||||||
{% if style == "stack" and link.label %}<span class="bru-meta">{{ link.label }}</span>{% endif %}
|
{% if style == "stack" and link.label %}<span class="bru-meta">{{ link.label }}</span>{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
{% if member.role %}<p class="bru-meta text-accent">{{ member.role }}</p>{% endif %}
|
{% if member.role %}<p class="bru-meta text-accent">{{ member.role }}</p>{% endif %}
|
||||||
{% if member.bio %}<p class="mt-2 text-sm text-muted-foreground">{{ member.bio }}</p>{% endif %}
|
{% if member.bio %}<p class="mt-2 text-sm text-muted-foreground">{{ member.bio }}</p>{% endif %}
|
||||||
{% if member.socials %}<div class="mt-3 flex gap-3 {% if layout != "list" %}justify-center{% endif %}">
|
{% if member.socials %}<div class="mt-3 flex gap-3 {% if layout != "list" %}justify-center{% endif %}">
|
||||||
{% for social in member.socials %}{% if social.url %}<a href="{{ social.url }}" class="text-muted-foreground transition-colors hover:text-accent" aria-label="Social link"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ social.icon|split:":"|first }}.svg#{{ social.icon|split:":"|last }}"></use></svg></a>{% endif %}{% endfor %}
|
{% for social in member.socials %}{% if social.url %}<a href="{{ social.url }}" class="text-muted-foreground transition-colors hover:text-accent" aria-label="Social link"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ social.icon|split:":"|first }}.svg#{{ social.icon|split:":"|last }}"></use></svg></a>{% endif %}{% endfor %}
|
||||||
</div>{% endif %}
|
</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,11 +6,11 @@
|
|||||||
{% for q in quotes %}
|
{% for q in quotes %}
|
||||||
<figure class="bru-slab bru-shadow flex flex-col p-6{% if layout == "carousel" %} min-w-[18rem] max-w-sm shrink-0 snap-start{% endif %}">
|
<figure class="bru-slab bru-shadow flex flex-col p-6{% if layout == "carousel" %} min-w-[18rem] max-w-sm shrink-0 snap-start{% endif %}">
|
||||||
{% if q.rating %}<div class="mb-3 flex gap-0.5" aria-label="Rated {{ q.rating }} out of 5">
|
{% if q.rating %}<div class="mb-3 flex gap-0.5" aria-label="Rated {{ q.rating }} out of 5">
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 1 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 1 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 2 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 2 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 3 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 3 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 4 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 4 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 5 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 5 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
</div>{% endif %}
|
</div>{% endif %}
|
||||||
<blockquote class="flex-1 text-lg leading-relaxed">{% if q.quote %}“{{ q.quote }}”{% endif %}</blockquote>
|
<blockquote class="flex-1 text-lg leading-relaxed">{% if q.quote %}“{{ q.quote }}”{% endif %}</blockquote>
|
||||||
<figcaption class="mt-5 flex items-center gap-3">
|
<figcaption class="mt-5 flex items-center gap-3">
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
{% for step in steps %}
|
{% for step in steps %}
|
||||||
<li class="{% if orientation == "horizontal" %}text-center{% else %}relative pl-14{% endif %}">
|
<li class="{% if orientation == "horizontal" %}text-center{% else %}relative pl-14{% endif %}">
|
||||||
<span class="flex h-9 w-9 items-center justify-center bg-accent text-accent-foreground {% if orientation == "horizontal" %}mx-auto{% else %}absolute left-0 top-0{% endif %}" style="border:3px solid hsl(var(--border))">
|
<span class="flex h-9 w-9 items-center justify-center bg-accent text-accent-foreground {% if orientation == "horizontal" %}mx-auto{% else %}absolute left-0 top-0{% endif %}" style="border:3px solid hsl(var(--border))">
|
||||||
{% if marker == "numbered" %}<span class="bru-index" style="font-size:1rem">{{ forloop.counter }}</span>{% elif marker == "dot" %}<span class="h-2 w-2 bg-accent-foreground"></span>{% else %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#flag"></use></svg>{% endif %}
|
{% if marker == "numbered" %}<span class="bru-index" style="font-size:1rem">{{ forloop.counter }}</span>{% elif marker == "dot" %}<span class="h-2 w-2 bg-accent-foreground"></span>{% else %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#flag"></use></svg>{% endif %}
|
||||||
</span>
|
</span>
|
||||||
<div class="{% if orientation == "horizontal" %}mt-4{% else %}pt-1{% endif %}">
|
<div class="{% if orientation == "horizontal" %}mt-4{% else %}pt-1{% endif %}">
|
||||||
{% if step.label %}<p class="bru-meta text-accent">{{ step.label }}</p>{% endif %}
|
{% if step.label %}<p class="bru-meta text-accent">{{ step.label }}</p>{% endif %}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{# brutalist video-embed override — hard-bordered click-to-play facade. Fields: url, media, poster, title, caption, aspect. #}
|
{# brutalist video-embed override — hard-bordered click-to-play facade. Fields: url, media, poster, title, caption, aspect. #}
|
||||||
{% with aspect=aspect|default:"16:9" %}<figure class="bn-video my-8{% if class %} {{ class }}{% endif %}"><div class="bn-video-frame bru-slab bru-shadow relative w-full overflow-hidden {% if aspect == "4:3" %}aspect-[4/3]{% elif aspect == "1:1" %}aspect-square{% elif aspect == "21:9" %}aspect-[21/9]{% else %}aspect-video{% endif %}" data-bn-video data-video-url="{{ url|default:"" }}" data-video-media="{% if media %}{{ media|mediaURL }}{% endif %}"><button type="button" data-bn-video-play class="group absolute inset-0 flex h-full w-full items-center justify-center focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring" aria-label="Play video{% if title %}: {{ title }}{% endif %}">{% if poster %}{% img poster alt=title|default:"" class="absolute inset-0 h-full w-full object-cover" %}{% endif %}<span class="absolute inset-0 bg-foreground/10 transition-colors group-hover:bg-foreground/25" aria-hidden="true"></span><span class="relative inline-flex h-16 w-16 items-center justify-center text-accent-foreground transition-transform group-hover:scale-105 motion-reduce:transform-none" style="background:hsl(var(--accent));border:3px solid hsl(var(--border));box-shadow:4px 4px 0 0 hsl(var(--border))"><svg class="h-7 w-7" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg></span></button></div>{% if caption %}<figcaption class="bru-meta mt-3 text-center">{{ caption }}</figcaption>{% endif %}</figure><script>
|
{% with aspect=aspect|default:"16:9" %}<figure class="bn-video my-8{% if class %} {{ class }}{% endif %}"><div class="bn-video-frame bru-slab bru-shadow relative w-full overflow-hidden {% if aspect == "4:3" %}aspect-[4/3]{% elif aspect == "1:1" %}aspect-square{% elif aspect == "21:9" %}aspect-[21/9]{% else %}aspect-video{% endif %}" data-bn-video data-video-url="{{ url|default:"" }}" data-video-media="{% if media %}{{ media|mediaURL }}{% endif %}"><button type="button" data-bn-video-play class="group absolute inset-0 flex h-full w-full items-center justify-center focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ring" aria-label="Play video{% if title %}: {{ title }}{% endif %}">{% if poster %}{% img poster alt=title|default:"" class="absolute inset-0 h-full w-full object-cover" %}{% endif %}<span class="absolute inset-0 bg-foreground/10 transition-colors group-hover:bg-foreground/25" aria-hidden="true"></span><span class="relative inline-flex h-16 w-16 items-center justify-center text-accent-foreground transition-transform group-hover:scale-105 motion-reduce:transform-none" style="background:hsl(var(--accent));border:3px solid hsl(var(--border));box-shadow:4px 4px 0 0 hsl(var(--border))"><svg width="28" height="28" class="h-7 w-7" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg></span></button></div>{% if caption %}<figcaption class="bru-meta mt-3 text-center">{{ caption }}</figcaption>{% endif %}</figure><script>
|
||||||
(function(){
|
(function(){
|
||||||
if(window.__bnVideoFacade)return;window.__bnVideoFacade=true;
|
if(window.__bnVideoFacade)return;window.__bnVideoFacade=true;
|
||||||
function yt(u){var m=u.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([\w-]{6,})/);return m?m[1]:null;}
|
function yt(u){var m=u.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([\w-]{6,})/);return m?m[1]:null;}
|
||||||
|
|||||||