fix(gotham): noir remediation — SVG geometry guards, shortcode→SVG, hero string-vs-object, reveal no-scroll fallback, deeper blacks, seed media

- Replace ::icon:: shortcodes with explicit sized <svg><use> (events_marquee,
  membership_tiers, button, hours-location, divider).
- Add width/height presentation attrs to every <use> SVG (recipe 4d guard).
- hero: field.text -> field|get:"text"|default:field (bare-string seed fields
  no longer error the block to EMPTY — About orphaned-rule root cause).
- reveal script: rAF kick + all() no-scroll fallback 2600ms -> 650ms across all
  templates so above/below-fold content never strands invisible without scroll.
- article: render aside + vertical divider only when slots.aside is non-empty
  (kills the empty fenced right column); narrow single-column when no aside.
- presets: deeper near-black backgrounds, higher-contrast foregrounds, richer
  brass/gold accents across all five palettes (light + dark).
- divider/quote: retire busy reel-strip sunburst for clean centred gold rules.
- seed: longer members-club articles; wire licensed noir stock imagery
  (bar-scene B&W hero, bar-shelf About, bar-interior/dark-lounge blog cards).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Alex Dunmow 2026-07-06 16:31:20 +08:00
parent db13a889f5
commit f5af05fd5f
45 changed files with 164 additions and 152 deletions

View File

@ -15,7 +15,7 @@
{% if event.room %}<span class="ml-3 text-sm" style="color:hsl(var(--muted-foreground));">{{ event.room }}</span>{% endif %}
{% if event.note %}<p class="mt-1 text-sm italic" style="color:hsl(var(--muted-foreground));font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ event.note }}</p>{% endif %}
</div>
{% if event.url %}<a href="{{ event.url }}" class="reel-link inline-flex items-center gap-1 justify-self-start text-sm sm:justify-self-end">Book::lucide:arrow-right:sm::</a>{% endif %}
{% if event.url %}<a href="{{ event.url }}" class="reel-link inline-flex items-center gap-1 justify-self-start text-sm sm:justify-self-end">Book<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
</li>
{% endfor %}
</ul>

View File

@ -22,7 +22,7 @@
{% if tier.features %}
<ul class="mt-5 space-y-2 border-t border-[hsl(var(--border))] pt-5 text-sm">
{% for feature in tier.features %}
<li class="flex items-start gap-2"><span class="mt-0.5 shrink-0 text-primary">::lucide:check:sm::</span><span style="color:hsl(var(--foreground));">{{ feature.label }}</span></li>
<li class="flex items-start gap-2"><span class="mt-0.5 shrink-0 text-primary"><svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg></span><span style="color:hsl(var(--foreground));">{{ feature.label }}</span></li>
{% endfor %}
</ul>
{% endif %}

View File

@ -217,7 +217,7 @@ css:
/* reveal — MID-tier scroll reveal. No JS = visible; reduced-motion honoured. */
.reveal { opacity: 1; }
.gotham-js .reveal { opacity: 0; transform: translateY(16px); transition: opacity .5s ease, transform .5s ease; }
.gotham-js .reveal { opacity: 0; transform: translateY(12px); transition: opacity .4s ease, transform .4s ease; }
.gotham-js .reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
.gotham-js .reveal { opacity: 1 !important; transform: none !important; transition: none !important; }

View File

@ -6,46 +6,46 @@
"theme": {
"mode": "both",
"lightColors": {
"background": "40 22% 95%",
"foreground": "30 10% 12%",
"card": "40 24% 98%",
"cardForeground": "30 10% 12%",
"popover": "40 24% 98%",
"popoverForeground": "30 10% 12%",
"primary": "38 58% 42%",
"primaryForeground": "40 30% 96%",
"background": "40 20% 96%",
"foreground": "28 16% 9%",
"card": "40 24% 99%",
"cardForeground": "28 16% 9%",
"popover": "40 24% 99%",
"popoverForeground": "28 16% 9%",
"primary": "36 62% 38%",
"primaryForeground": "40 30% 97%",
"secondary": "40 12% 88%",
"secondaryForeground": "30 12% 16%",
"secondaryForeground": "28 14% 13%",
"muted": "40 12% 90%",
"mutedForeground": "30 8% 40%",
"accent": "36 62% 48%",
"accentForeground": "40 30% 96%",
"destructive": "0 68% 44%",
"mutedForeground": "28 11% 32%",
"accent": "34 64% 44%",
"accentForeground": "40 30% 97%",
"destructive": "0 68% 42%",
"destructiveForeground": "40 26% 96%",
"border": "40 18% 78%",
"input": "40 16% 82%",
"ring": "38 58% 44%"
"border": "38 16% 73%",
"input": "40 16% 80%",
"ring": "36 62% 40%"
},
"darkColors": {
"background": "30 9% 5%",
"foreground": "40 28% 90%",
"card": "30 9% 8%",
"cardForeground": "40 28% 90%",
"popover": "30 9% 8%",
"popoverForeground": "40 28% 90%",
"primary": "40 66% 54%",
"primaryForeground": "30 22% 6%",
"secondary": "30 8% 14%",
"secondaryForeground": "40 24% 86%",
"muted": "30 7% 12%",
"mutedForeground": "40 12% 62%",
"accent": "38 74% 60%",
"accentForeground": "30 22% 6%",
"destructive": "0 70% 50%",
"background": "28 13% 4%",
"foreground": "40 32% 93%",
"card": "28 12% 7%",
"cardForeground": "40 32% 93%",
"popover": "28 12% 7%",
"popoverForeground": "40 32% 93%",
"primary": "40 72% 54%",
"primaryForeground": "28 24% 5%",
"secondary": "28 9% 13%",
"secondaryForeground": "40 26% 88%",
"muted": "28 8% 11%",
"mutedForeground": "40 16% 67%",
"accent": "38 78% 62%",
"accentForeground": "28 24% 5%",
"destructive": "0 72% 52%",
"destructiveForeground": "40 26% 95%",
"border": "40 24% 20%",
"input": "40 18% 16%",
"ring": "40 66% 54%"
"border": "40 22% 17%",
"input": "40 18% 15%",
"ring": "40 72% 54%"
}
}
},
@ -57,17 +57,17 @@
"mode": "both",
"lightColors": {
"background": "220 16% 95%",
"foreground": "222 18% 14%",
"foreground": "222 22% 10%",
"card": "220 20% 98%",
"cardForeground": "222 18% 14%",
"cardForeground": "222 22% 10%",
"popover": "220 20% 98%",
"popoverForeground": "222 18% 14%",
"popoverForeground": "222 22% 10%",
"primary": "40 60% 44%",
"primaryForeground": "220 20% 96%",
"secondary": "220 12% 88%",
"secondaryForeground": "222 16% 18%",
"muted": "220 12% 90%",
"mutedForeground": "220 8% 40%",
"mutedForeground": "220 11% 33%",
"accent": "40 66% 50%",
"accentForeground": "222 20% 8%",
"destructive": "0 68% 46%",
@ -77,18 +77,18 @@
"ring": "40 60% 46%"
},
"darkColors": {
"background": "222 20% 6%",
"foreground": "215 22% 90%",
"card": "222 20% 9%",
"cardForeground": "215 22% 90%",
"popover": "222 20% 9%",
"popoverForeground": "215 22% 90%",
"background": "222 26% 4%",
"foreground": "215 26% 93%",
"card": "222 22% 7%",
"cardForeground": "215 26% 93%",
"popover": "222 22% 7%",
"popoverForeground": "215 26% 93%",
"primary": "42 72% 58%",
"primaryForeground": "222 24% 8%",
"secondary": "222 16% 15%",
"secondaryForeground": "215 20% 86%",
"muted": "222 14% 13%",
"mutedForeground": "215 12% 62%",
"muted": "222 12% 11%",
"mutedForeground": "215 16% 67%",
"accent": "40 78% 62%",
"accentForeground": "222 24% 8%",
"destructive": "0 72% 52%",
@ -107,17 +107,17 @@
"mode": "both",
"lightColors": {
"background": "20 20% 95%",
"foreground": "18 14% 14%",
"foreground": "18 18% 10%",
"card": "20 24% 98%",
"cardForeground": "18 14% 14%",
"cardForeground": "18 18% 10%",
"popover": "20 24% 98%",
"popoverForeground": "18 14% 14%",
"popoverForeground": "18 18% 10%",
"primary": "16 52% 50%",
"primaryForeground": "20 30% 97%",
"secondary": "20 14% 88%",
"secondaryForeground": "18 14% 18%",
"muted": "20 12% 90%",
"mutedForeground": "18 10% 40%",
"mutedForeground": "18 12% 33%",
"accent": "12 60% 56%",
"accentForeground": "20 30% 97%",
"destructive": "0 68% 46%",
@ -127,18 +127,18 @@
"ring": "16 52% 50%"
},
"darkColors": {
"background": "16 12% 6%",
"foreground": "22 24% 90%",
"card": "16 12% 9%",
"cardForeground": "22 24% 90%",
"popover": "16 12% 9%",
"popoverForeground": "22 24% 90%",
"background": "16 17% 4%",
"foreground": "22 28% 93%",
"card": "16 15% 7%",
"cardForeground": "22 28% 93%",
"popover": "16 15% 7%",
"popoverForeground": "22 28% 93%",
"primary": "18 64% 60%",
"primaryForeground": "16 24% 8%",
"secondary": "16 12% 15%",
"secondaryForeground": "22 22% 86%",
"muted": "16 10% 13%",
"mutedForeground": "22 14% 62%",
"muted": "16 9% 11%",
"mutedForeground": "22 16% 67%",
"accent": "10 70% 64%",
"accentForeground": "16 24% 8%",
"destructive": "0 72% 54%",
@ -157,17 +157,17 @@
"mode": "both",
"lightColors": {
"background": "210 8% 95%",
"foreground": "210 10% 14%",
"foreground": "210 13% 10%",
"card": "210 10% 98%",
"cardForeground": "210 10% 14%",
"cardForeground": "210 13% 10%",
"popover": "210 10% 98%",
"popoverForeground": "210 10% 14%",
"popoverForeground": "210 13% 10%",
"primary": "210 8% 38%",
"primaryForeground": "210 12% 97%",
"secondary": "210 8% 88%",
"secondaryForeground": "210 10% 18%",
"muted": "210 8% 90%",
"mutedForeground": "210 6% 42%",
"mutedForeground": "210 9% 34%",
"accent": "42 40% 52%",
"accentForeground": "210 12% 10%",
"destructive": "0 66% 46%",
@ -177,18 +177,18 @@
"ring": "210 8% 42%"
},
"darkColors": {
"background": "210 10% 7%",
"foreground": "210 12% 90%",
"card": "210 10% 10%",
"cardForeground": "210 12% 90%",
"popover": "210 10% 10%",
"popoverForeground": "210 12% 90%",
"background": "210 13% 5%",
"foreground": "210 15% 93%",
"card": "210 12% 8%",
"cardForeground": "210 15% 93%",
"popover": "210 12% 8%",
"popoverForeground": "210 15% 93%",
"primary": "210 14% 74%",
"primaryForeground": "210 12% 8%",
"secondary": "210 10% 15%",
"secondaryForeground": "210 12% 86%",
"muted": "210 8% 13%",
"mutedForeground": "210 8% 60%",
"muted": "210 8% 11%",
"mutedForeground": "210 11% 66%",
"accent": "42 56% 60%",
"accentForeground": "210 12% 8%",
"destructive": "0 70% 52%",
@ -207,17 +207,17 @@
"mode": "both",
"lightColors": {
"background": "36 24% 94%",
"foreground": "28 18% 13%",
"foreground": "28 22% 9%",
"card": "36 26% 98%",
"cardForeground": "28 18% 13%",
"cardForeground": "28 22% 9%",
"popover": "36 26% 98%",
"popoverForeground": "28 18% 13%",
"popoverForeground": "28 22% 9%",
"primary": "30 62% 42%",
"primaryForeground": "36 30% 96%",
"secondary": "36 16% 87%",
"secondaryForeground": "28 16% 17%",
"muted": "36 14% 89%",
"mutedForeground": "28 12% 40%",
"mutedForeground": "28 14% 33%",
"accent": "26 66% 48%",
"accentForeground": "36 30% 96%",
"destructive": "0 68% 44%",
@ -227,18 +227,18 @@
"ring": "30 62% 44%"
},
"darkColors": {
"background": "28 16% 6%",
"foreground": "36 28% 89%",
"card": "28 16% 9%",
"cardForeground": "36 28% 89%",
"popover": "28 16% 9%",
"popoverForeground": "36 28% 89%",
"background": "28 21% 4%",
"foreground": "36 30% 93%",
"card": "28 18% 7%",
"cardForeground": "36 30% 93%",
"popover": "28 18% 7%",
"popoverForeground": "36 30% 93%",
"primary": "32 72% 54%",
"primaryForeground": "28 24% 7%",
"secondary": "28 14% 15%",
"secondaryForeground": "36 24% 85%",
"muted": "28 12% 13%",
"mutedForeground": "36 14% 60%",
"muted": "28 11% 11%",
"mutedForeground": "36 16% 66%",
"accent": "24 80% 58%",
"accentForeground": "28 24% 7%",
"destructive": "0 72% 52%",

BIN
seed/media/bar-interior.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

BIN
seed/media/bar-scene.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

BIN
seed/media/bar-shelf.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

BIN
seed/media/dark-lounge.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

View File

@ -6,6 +6,12 @@
"tagline": "A members' club after dark."
}
},
"media": [
{ "id": "a1b2c3d4-0000-4000-8000-000000000001", "file": "media/bar-scene.jpg", "alt": "Bartenders at work behind a dark backbar, low-lit and grainy", "folder": "Gotham" },
{ "id": "a1b2c3d4-0000-4000-8000-000000000002", "file": "media/bar-shelf.jpg", "alt": "Warm brass-lit shelves of whisky bottles in a dim room", "folder": "Gotham" },
{ "id": "a1b2c3d4-0000-4000-8000-000000000003", "file": "media/bar-interior.jpg", "alt": "Backlit rows of bottles in silhouette against a dark wall", "folder": "Gotham" },
{ "id": "a1b2c3d4-0000-4000-8000-000000000004", "file": "media/dark-lounge.jpg", "alt": "A dark lounge under low hanging lamps casting pools of gold light", "folder": "Gotham" }
],
"data_tables": [
{
"key": "contact_submissions",
@ -33,6 +39,9 @@
"content": {
"template": "centered",
"minHeight": "75vh",
"backgroundImage": "media:a1b2c3d4-0000-4000-8000-000000000001",
"overlayColor": "dark",
"overlayOpacity": 68,
"eyebrow": "Members only",
"headline": "Gotham House",
"subheadline": "A members' club after dark.",
@ -148,8 +157,9 @@
"blocks": [
{ "block_key": "heading", "title": "Heading", "slot": "main", "sort_order": 1, "content": { "text": "The House", "level": 1 } },
{ "block_key": "rich-text", "title": "Story", "slot": "main", "sort_order": 2, "content": { "html": "<p>Gotham House keeps late hours behind an unmarked door. We run four nights a week and hold the rest of the week back.</p><p>The rooms are dark by design. The bar is long. The list is short. Members come first, and their guests come with them.</p>" } },
{ "block_key": "divider", "title": "Divider", "slot": "main", "sort_order": 3, "content": { "variant": "ornament", "icon": "lucide:diamond" } },
{ "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 4, "content": { "style": "block", "align": "center", "quote": "Come late. Stay later.", "attribution": "The House" } }
{ "block_key": "image", "title": "The bar", "slot": "main", "sort_order": 3, "content": { "src": "media:a1b2c3d4-0000-4000-8000-000000000002", "alt": "Warm brass-lit shelves of whisky bottles in a dim room", "caption": "The long bar. Low light, and a shelf that remembers you.", "size": "lg", "aspectRatio": "wide" } },
{ "block_key": "divider", "title": "Divider", "slot": "main", "sort_order": 4, "content": { "variant": "ornament", "icon": "lucide:diamond" } },
{ "block_key": "quote", "title": "Quote", "slot": "main", "sort_order": 5, "content": { "style": "block", "align": "center", "quote": "Come late. Stay later.", "attribution": "The House" } }
]
},
{
@ -157,9 +167,9 @@
"title": "The Journal",
"template_key": "blog-index",
"blocks": [
{ "block_key": "card", "title": "Post: The Door", "slot": "main", "sort_order": 1, "content": { "layout": "vertical", "title": "How the door works", "text": "<p>The list, the card and the guests. What to send and when.</p>", "link": "/blog/how-the-door-works", "linkLabel": "Read on" } },
{ "block_key": "card", "title": "Post: A Night", "slot": "main", "sort_order": 2, "content": { "layout": "vertical", "title": "A night at the house", "text": "<p>From the first pour to the last record. How the evening runs.</p>", "link": "/blog/a-night-at-the-house", "linkLabel": "Read on" } },
{ "block_key": "card", "title": "Post: The Cellar", "slot": "main", "sort_order": 3, "content": { "layout": "vertical", "title": "Notes from the cellar", "text": "<p>What we pour after midnight and why the list stays short.</p>", "link": "/blog/notes-from-the-cellar", "linkLabel": "Read on" } }
{ "block_key": "card", "title": "Post: The Door", "slot": "main", "sort_order": 1, "content": { "layout": "vertical", "media": "media:a1b2c3d4-0000-4000-8000-000000000003", "title": "How the door works", "text": "<p>The list, the card and the guests. What to send and when.</p>", "link": "/blog/how-the-door-works", "linkLabel": "Read on" } },
{ "block_key": "card", "title": "Post: A Night", "slot": "main", "sort_order": 2, "content": { "layout": "vertical", "media": "media:a1b2c3d4-0000-4000-8000-000000000004", "title": "A night at the house", "text": "<p>From the first pour to the last record. How the evening runs.</p>", "link": "/blog/a-night-at-the-house", "linkLabel": "Read on" } },
{ "block_key": "card", "title": "Post: The Cellar", "slot": "main", "sort_order": 3, "content": { "layout": "vertical", "media": "media:a1b2c3d4-0000-4000-8000-000000000002", "title": "Notes from the cellar", "text": "<p>What we pour after midnight and why the list stays short.</p>", "link": "/blog/notes-from-the-cellar", "linkLabel": "Read on" } }
]
},
{
@ -169,7 +179,7 @@
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "How the door works", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>Send your name and party by nine. We hold the list until then and reply the same day.</p><p>Members lead. Guests come with them, and there is a cap. Bring your card. The door checks it.</p>" } }
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>Send your name and party by nine. We hold the list until then and reply the same day. No name, no note, no entry.</p><p>Members lead. A guest comes on a member's word, and the member is the one who answers for them. Bring your card. The door checks it, every night, without exception.</p><p>There is a cap. Some nights it is generous. Most nights it is not. When the room is full the list closes, and the closing is final. We do not reopen it for a better story told at the rail.</p><p>The door is not a negotiation. The people who work it have seen every version of the conversation you are about to start, and they were unmoved the first time. Arrive as though you belong, and more often than not you will.</p><p>Dress for a dark room. We do not print a code, because the room prints it for us. You will know within a step whether you have read it right. When in doubt, wear less colour and better shoes.</p><p>Photographs stay in your pocket. The house is a place people come to be unseen, and that only holds if everyone keeps the same agreement. Break it once and the card goes quiet.</p><p>If you are late, you are late to the list, not to us. The night runs on its own clock and will not wait, but it does not end early either. Come when you can. The door will still be there.</p><p>Lose the card and tell us before you tell anyone else. A card in the wrong hands is a name in the wrong mouth, and we would rather cancel it over a quiet word than read about it later.</p><p>That is the whole of it. Send the name, bring the card, keep the room's secrets, and the door becomes the easiest part of the evening.</p>" } }
]
},
{
@ -179,7 +189,7 @@
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "A night at the house", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>Doors open at nine. The first set starts slow. The main room fills after eleven and holds until the lights come up.</p><p>The cellar bar stays quiet. That is the point. Records, a nightcap and the last pour.</p>" } }
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>Doors open at nine. The first set starts slow, on purpose. The room is meant to be walked into, not fallen into, and the early hour belongs to the people who like it quiet.</p><p>The main room fills after eleven. That is when the residents lean into the good part of the night, and the floor stops being a place to stand and becomes a place to stay. If you came to dance, come late.</p><p>The brass room runs colder and closer. Fewer people, a shorter bar, a door within the door. It is where the house keeps its better hours for the cards that have earned them.</p><p>The cellar bar stays quiet, and that is the point. Records, low light, a bench of rye and a host who remembers what you drank last time. Conversations that would not survive the main room live down here.</p><p>Somewhere past one, the night finds its level. The people who were going to leave have left. The people who were always going to stay have found their corner. The house exhales.</p><p>We do not announce last call. The last pour arrives when the room is ready for it, poured a little slower than the ones before, and nobody has to be told what it means.</p><p>The lights do not come up so much as lean in. First the far corners, then the rail, then the floor. The house dims the evening down the way it brought it up.</p><p>Then the door, which held the list all night, holds it open instead. You leave the way you came, by a member's word, into a street that has no idea what the room behind it was doing.</p><p>Come back on a Sunday if you want to understand the place. The crowd is smaller, the records are older, and the house is most itself when almost no one is watching.</p>" } }
]
},
{
@ -189,7 +199,7 @@
"parent_slug": "/blog",
"blocks": [
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 1, "content": { "text": "Notes from the cellar", "level": 1 } },
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>The list is short by choice. We pour champagne by the glass, keep a bench of rye and hold a small shelf for members who ask.</p><p>Tell the host what you are drinking. The rest follows.</p>" } }
{ "block_key": "rich-text", "title": "Body", "slot": "main", "sort_order": 2, "content": { "html": "<p>The list is short by choice. A long list is a way of hiding that you do not know what you are pouring. We keep ours brief so that every bottle on it has a reason to be there.</p><p>We pour champagne by the glass, because a good glass should not require a commitment. The house brut carries most nights. The vintage rosé sits on a short shelf for the members who ask, and it does not last.</p><p>There is a bench of rye the cellar is quietly proud of. Neat, one large cube, no ceremony. If you want it drowned we will do it, but the host will remember.</p><p>The single malt is Islay, and it is not for everyone, which is exactly why we keep it. Bring water. Let it open. The cellar is a slow room, and the whisky was made by people who understood that.</p><p>Bottle service is a booth and a decision, not a display. We do not run sparklers to the floor. What arrives is what you asked for, cold, on time, and without an audience.</p><p>Ask the host what is drinking well tonight. It is the most useful sentence in the room. The list on the table is the floor of the conversation, not the ceiling.</p><p>We hold a small reserve that never makes the printed page. It goes to the cards that have been patient, on nights that have earned it, and it is offered rather than requested.</p><p>Tell the host what you are drinking and the rest follows. The cellar is built on that one exchange: a name for a glass, a preference remembered, a night made a little better than the last.</p>" } }
]
},
{

View File

@ -6,18 +6,18 @@
<header class="w-full">
<div class="max-w-3xl mx-auto px-4">{{ slots.header|safe }}</div>
</header>
<div class="flex-grow grid gap-12 max-w-5xl mx-auto w-full px-4 py-12 md:py-16 md:grid-cols-[2fr_1fr]">
<div class="flex-grow grid gap-12 w-full px-4 py-12 md:py-16 {% if slots.aside %}max-w-5xl mx-auto md:grid-cols-[2fr_1fr]{% else %}max-w-2xl mx-auto{% endif %}">
<main class="prose max-w-none">
{% if slots.main %}<article class="reel-dropcap" data-reel-dropcap="true">{{ slots.main|safe }}</article>{% else %}<div class="py-20 text-center"><p class="italic" style="color:hsl(var(--muted-foreground));">No content blocks assigned to this page.</p></div>{% endif %}
</main>
<aside class="w-full md:border-l md:border-[hsl(var(--primary)/0.3)] md:pl-10">{{ slots.aside|safe }}</aside>
{% if slots.aside %}<aside class="w-full md:border-l md:border-[hsl(var(--primary)/0.3)] md:pl-10">{{ slots.aside|safe }}</aside>{% endif %}
</div>
<footer class="w-full mt-auto border-t border-[hsl(var(--primary)/0.35)]">
<div class="max-w-5xl mx-auto px-4">{{ slots.footer|safe }}</div>
</footer>
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -15,7 +15,7 @@
</main>
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -20,7 +20,7 @@
{% if slots.footer %}<footer class="w-full mt-auto border-t border-[hsl(var(--primary)/0.35)]">{{ slots.footer|safe }}</footer>{% endif %}
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -10,7 +10,7 @@
<footer class="w-full mt-auto border-t border-[hsl(var(--primary)/0.35)]"><div class="max-w-2xl mx-auto px-4">{{ slots.footer|safe }}</div></footer>
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -19,7 +19,7 @@
{% if slots.footer %}<footer class="w-full mt-auto border-t border-[hsl(var(--primary)/0.35)]">{{ slots.footer|safe }}</footer>{% endif %}
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -14,7 +14,7 @@
</footer>
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -12,7 +12,7 @@
</footer>
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -13,7 +13,7 @@
</footer>
{{ body_end_html|safe }}
<script>
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();window.addEventListener('scroll',inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,2600);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
(function(){if(window.__gothamMotion)return;window.__gothamMotion=1;var d=document,root=d.documentElement;root.classList.add('gotham-js');var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;function pending(){return d.querySelectorAll('.reveal:not(.is-visible)');}function reveal(el){el.classList.add('is-visible');}function inView(){var h=window.innerHeight||root.clientHeight;pending().forEach(function(el){var r=el.getBoundingClientRect();if(r.top<h*1.05&&r.bottom>-h*0.25)reveal(el);});}function all(){pending().forEach(reveal);}function run(){if(reduce){all();return;}inView();if(window.requestAnimationFrame){requestAnimationFrame(inView);}window.addEventListener("scroll",inView,{passive:true});window.addEventListener('resize',inView,{passive:true});window.addEventListener('load',function(){inView();setTimeout(inView,120);},{once:true});setTimeout(inView,400);setTimeout(all,650);d.querySelectorAll('[data-spotlight]').forEach(function(s){s.addEventListener('pointermove',function(ev){var r=s.getBoundingClientRect();s.style.setProperty('--sx',((ev.clientX-r.left)/r.width*100)+'%');s.style.setProperty('--sy',((ev.clientY-r.top)/r.height*100)+'%');});});}if(d.readyState!='loading')run();else d.addEventListener('DOMContentLoaded',run);})();
</script>
</body>
</html>

View File

@ -1,5 +1,5 @@
{# audio-embed override — gold-framed player card. Fields + facade JS mirror builtin verbatim: url, media, artwork, title, artist, download. #}
<figure data-block-override="gotham:audio-embed" class="bn-audio reel-frame my-8 overflow-hidden bg-card text-card-foreground{% 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="reel-mat h-16 w-16 shrink-0 overflow-hidden bg-muted">{% 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="reel-caps truncate text-sm" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif);color:hsl(var(--foreground));">{{ title }}</p>{% endif %}{% if artist %}<p class="truncate text-sm italic" style="color:hsl(var(--muted-foreground));">{{ artist }}</p>{% endif %}<div class="mt-2 flex items-center gap-3" data-bn-audio-slot><button type="button" data-bn-audio-play class="reel-btn inline-flex items-center gap-2 text-sm" aria-label="Play{% if title %}: {{ title }}{% endif %}">::lucide:play:sm:: Play</button>{% if download %}<a href="{% if media %}{{ media|mediaURL }}{% else %}{{ url }}{% endif %}" download class="reel-link inline-flex items-center gap-1 text-sm">::lucide:download:sm:: Download</a>{% endif %}</div></div></div></figure><script>
<figure data-block-override="gotham:audio-embed" class="bn-audio reel-frame my-8 overflow-hidden bg-card text-card-foreground{% 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="reel-mat h-16 w-16 shrink-0 overflow-hidden bg-muted">{% 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="reel-caps truncate text-sm" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif);color:hsl(var(--foreground));">{{ title }}</p>{% endif %}{% if artist %}<p class="truncate text-sm italic" style="color:hsl(var(--muted-foreground));">{{ artist }}</p>{% endif %}<div class="mt-2 flex items-center gap-3" data-bn-audio-slot><button type="button" data-bn-audio-play class="reel-btn inline-flex items-center gap-2 text-sm" aria-label="Play{% if title %}: {{ title }}{% endif %}"><svg class="inline-block h-4 w-4" width="16" height="16" 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="reel-link inline-flex items-center gap-1 text-sm"><svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#download"></use></svg> Download</a>{% endif %}</div></div></div></figure><script>
(function(){
if(window.__bnAudioFacade)return;window.__bnAudioFacade=true;
document.addEventListener('click',function(e){

View File

@ -12,10 +12,10 @@
{% if author.location %}<span>{{ author.location }}</span>{% endif %}
</div>
{% if showSocial %}<div class="mt-6 flex items-center justify-center gap-4">
{% if author.website_url %}<a href="{{ author.website_url }}" target="_blank" rel="noopener noreferrer" class="text-muted-foreground transition-colors hover:text-primary" title="Website"><svg 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-primary" title="Twitter"><svg 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-primary" title="LinkedIn"><svg 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-primary" title="GitHub"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#github"></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-primary" title="Website"><svg class="h-5 w-5" width="20" height="20" 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-primary" title="Twitter"><svg class="h-5 w-5" width="20" height="20" 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-primary" title="LinkedIn"><svg class="h-5 w-5" width="20" height="20" 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-primary" title="GitHub"><svg class="h-5 w-5" width="20" height="20" aria-hidden="true"><use href="/icons/simple-icons.svg#github"></use></svg></a>{% endif %}
</div>{% endif %}
</div>
</section>

View File

@ -2,9 +2,9 @@
{% with align=align|default:"left" %}
<div data-block-override="gotham:button" class="bn-button flex {% if align == "center" %}justify-center{% elif align == "right" %}justify-end{% else %}justify-start{% endif %}{% if class %} {{ class }}{% endif %}">
{% if style == "ghost" or style == "link" or style == "secondary" %}
<a href="{{ link|default:'#' }}"{% if newTab %} target="_blank" rel="noopener"{% endif %} class="reel-link inline-flex items-center gap-2 text-sm">{% if icon and iconPosition != "right" %}::{{ icon }}:sm::{% endif %}{{ label|default:"Learn more" }}{% if icon and iconPosition == "right" %}::{{ icon }}:sm::{% endif %}</a>
{% if icon %}{% set _ic1 = icon %}{% endif %}<a href="{{ link|default:'#' }}"{% if newTab %} target="_blank" rel="noopener"{% endif %} class="reel-link inline-flex items-center gap-2 text-sm">{% if icon and iconPosition != "right" %}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ _ic1|split:":"|first }}.svg#{{ _ic1|split:":"|last }}"></use></svg>{% endif %}{{ label|default:"Learn more" }}{% if icon and iconPosition == "right" %}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ _ic1|split:":"|first }}.svg#{{ _ic1|split:":"|last }}"></use></svg>{% endif %}</a>
{% else %}
<a href="{{ link|default:'#' }}"{% if newTab %} target="_blank" rel="noopener"{% endif %} class="reel-btn inline-flex items-center gap-2">{% if icon and iconPosition != "right" %}::{{ icon }}:sm::{% endif %}{{ label|default:"Learn more" }}{% if icon and iconPosition == "right" %}::{{ icon }}:sm::{% endif %}</a>
{% if icon %}{% set _ic2 = icon %}{% endif %}<a href="{{ link|default:'#' }}"{% if newTab %} target="_blank" rel="noopener"{% endif %} class="reel-btn inline-flex items-center gap-2">{% if icon and iconPosition != "right" %}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ _ic2|split:":"|first }}.svg#{{ _ic2|split:":"|last }}"></use></svg>{% endif %}{{ label|default:"Learn more" }}{% if icon and iconPosition == "right" %}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ _ic2|split:":"|first }}.svg#{{ _ic2|split:":"|last }}"></use></svg>{% endif %}</a>
{% endif %}
</div>
{% endwith %}

View File

@ -1,4 +1,4 @@
{# card override — angular gold Deco panel. Fields mirror builtin: layout, link, media, title, text, linkLabel. Media via {% img %}. #}
{% with layout=layout|default:"vertical" %}
<article data-block-override="gotham:card" class="bn-card reel-frame overflow-hidden bg-card text-card-foreground transition-shadow hover:reel-foil {% if layout == "horizontal" %}flex flex-col sm:flex-row{% endif %}{% if class %} {{ class }}{% endif %}">{% if link %}<a href="{{ link }}" class="contents">{% endif %}{% if media %}<div class="overflow-hidden bg-muted {% if layout == "horizontal" %}sm:w-2/5 sm:shrink-0{% endif %}">{% if layout == "horizontal" %}{% img media alt=title|default:"" class="h-full w-full object-cover" %}{% else %}{% img media alt=title|default:"" class="aspect-video h-full w-full object-cover" %}{% endif %}</div>{% endif %}<div class="flex flex-col gap-2 p-5 md:p-6 {% if layout == "horizontal" %}justify-center{% endif %}">{% if title %}<h3 class="reel-caps text-lg" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif);color:hsl(var(--foreground));">{{ title }}</h3>{% endif %}{% if text %}<div class="text-sm leading-relaxed" style="color:hsl(var(--muted-foreground));font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ text|safe }}</div>{% endif %}{% if linkLabel and link %}<span class="mt-2 inline-flex items-center gap-1 text-sm reel-link">{{ linkLabel }}::lucide:arrow-right:sm::</span>{% endif %}</div>{% if link %}</a>{% endif %}</article>
<article data-block-override="gotham:card" class="bn-card reel-frame overflow-hidden bg-card text-card-foreground transition-shadow hover:reel-foil {% if layout == "horizontal" %}flex flex-col sm:flex-row{% endif %}{% if class %} {{ class }}{% endif %}">{% if link %}<a href="{{ link }}" class="contents">{% endif %}{% if media %}<div class="overflow-hidden bg-muted {% if layout == "horizontal" %}sm:w-2/5 sm:shrink-0{% endif %}">{% if layout == "horizontal" %}{% img media alt=title|default:"" class="h-full w-full object-cover" %}{% else %}{% img media alt=title|default:"" class="aspect-video h-full w-full object-cover" %}{% endif %}</div>{% endif %}<div class="flex flex-col gap-2 p-5 md:p-6 {% if layout == "horizontal" %}justify-center{% endif %}">{% if title %}<h3 class="reel-caps text-lg" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif);color:hsl(var(--foreground));">{{ title }}</h3>{% endif %}{% if text %}<div class="text-sm leading-relaxed" style="color:hsl(var(--muted-foreground));font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ text|safe }}</div>{% endif %}{% if linkLabel and link %}<span class="mt-2 inline-flex items-center gap-1 text-sm reel-link">{{ linkLabel }}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></span>{% endif %}</div>{% if link %}</a>{% endif %}</article>
{% endwith %}

View File

@ -5,7 +5,7 @@
<div class="mt-12 grid grid-cols-1 gap-6 text-left {% if columns == 3 %}sm:grid-cols-2 lg:grid-cols-3{% elif columns == 1 %}{% else %}sm:grid-cols-2{% endif %}">
{% for channel in channels %}
<div class="reel-frame reel-foil flex items-start gap-4 rounded-none bg-card p-6 text-card-foreground">
{% if channel.icon %}<span class="inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-none border border-[hsl(var(--primary)/0.45)] bg-primary/10 text-primary"><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 rounded-none border border-[hsl(var(--primary)/0.45)] bg-primary/10 text-primary"><svg class="h-5 w-5" width="20" height="20" aria-hidden="true"><use href="/icons/{{ channel.icon|split:":"|first }}.svg#{{ channel.icon|split:":"|last }}"></use></svg></span>{% endif %}
<div class="min-w-0">
{% if channel.label %}<div class="reel-caps text-xs tracking-[0.16em] text-muted-foreground">{{ channel.label }}</div>{% endif %}
{% if channel.value %}<div class="mt-1 break-words text-lg text-foreground" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif)">{% if channel.link %}<a href="{{ channel.link }}" class="reel-link transition-colors hover:text-primary">{{ channel.value }}</a>{% else %}{{ channel.value }}{% endif %}</div>{% endif %}

View File

@ -4,7 +4,7 @@
<div class="mx-auto max-w-2xl px-4">
{% if form.submitted %}
<div class="reel-frame bg-card p-10 text-center">
<div class="mx-auto mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full text-primary" style="box-shadow:inset 0 0 0 1px hsl(var(--primary));">::lucide:check:lg::</div>
<div class="mx-auto mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full text-primary" style="box-shadow:inset 0 0 0 1px hsl(var(--primary));"><svg class="inline-block h-6 w-6" width="24" height="24" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg></div>
<p class="text-lg italic" style="font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ form.message|default:successMessage|default:"Thank you. Your table request has been received." }}</p>
</div>
{% else %}

View File

@ -11,7 +11,7 @@
</div>
<div class="mt-8 hidden" data-countdown-expired>
<p class="reel-caps text-xl" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif)">{{ expiredMessage|default:"This has started." }}</p>
{% if expiredUrl and expiredLabel %}<a href="{{ expiredUrl }}" class="reel-btn mt-4 inline-flex items-center gap-2">{{ expiredLabel }}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
{% if expiredUrl and expiredLabel %}<a href="{{ expiredUrl }}" class="reel-btn mt-4 inline-flex items-center gap-2">{{ expiredLabel }}<svg class="h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
</div>
</div>
<noscript><p class="mt-6 text-muted-foreground">Counting down to <time datetime="{{ target }}">{{ target }}</time>.</p></noscript>

View File

@ -6,7 +6,7 @@
{% if text %}<p class="mt-3 text-lg {% if background == "band" %}text-primary-foreground/80{% else %}text-muted-foreground{% endif %}" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{{ text }}</p>{% endif %}
</div>
<div class="flex flex-wrap items-center justify-center gap-3 {% if background != "split" %}mt-8{% else %}shrink-0{% endif %}">
{% if primaryUrl and primaryLabel %}<a href="{{ primaryUrl }}" class="reel-btn inline-flex items-center gap-2">{{ primaryLabel }}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
{% if primaryUrl and primaryLabel %}<a href="{{ primaryUrl }}" class="reel-btn inline-flex items-center gap-2">{{ primaryLabel }}<svg class="h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
{% if secondaryUrl and secondaryLabel %}<a href="{{ secondaryUrl }}" class="reel-link inline-flex items-center">{{ secondaryLabel }}</a>{% endif %}
</div>
</div>

View File

@ -1,9 +1,11 @@
{# divider override — folds in the old divider_fan: gold geometric rules. Fields mirror builtin: variant (line|ornament|spacer-rule), weight, width, icon. ornament renders a sunburst fan crest; spacer-rule a short centred gold rule; line a hairline gold rule. #}
{% with variant=variant|default:"line" weight=weight|default:"thin" width=width|default:"full" %}
{% if variant == "ornament" %}
<div data-block-override="gotham:divider" class="bn-divider mx-auto my-10 flex flex-col items-center gap-2 {% if width == "narrow" %}max-w-[200px]{% elif width == "wide" %}max-w-3xl{% else %}w-full{% endif %}{% if class %} {{ class }}{% endif %}" role="separator">
<div class="h-8 w-40 reel-strip" aria-hidden="true"></div>
<div class="flex w-full items-center gap-4"><span class="reel-rule flex-1"></span><span style="color:hsl(var(--primary));">::{{ icon|default:"lucide:diamond" }}:sm::</span><span class="reel-rule flex-1"></span></div>
{% set dicon = icon|default:"lucide:diamond" %}
<div data-block-override="gotham:divider" class="bn-divider mx-auto my-12 flex items-center justify-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="reel-rule w-14 sm:w-24" aria-hidden="true"></span>
<span class="shrink-0" style="color:hsl(var(--primary));"><svg class="h-3.5 w-3.5" width="14" height="14" aria-hidden="true"><use href="/icons/{{ dicon|split:":"|first }}.svg#{{ dicon|split:":"|last }}"></use></svg></span>
<span class="reel-rule w-14 sm:w-24" aria-hidden="true"></span>
</div>
{% elif variant == "spacer-rule" %}
<div data-block-override="gotham:divider" class="bn-divider mx-auto py-10 flex justify-center {% if width == "narrow" %}max-w-[200px]{% elif width == "wide" %}max-w-3xl{% else %}w-full{% endif %}{% if class %} {{ class }}{% endif %}" role="separator"><span class="{% if weight == "thick" %}reel-rule-thick{% else %}reel-rule{% endif %} w-16"></span></div>

View File

@ -12,7 +12,7 @@
<h3 class="text-xl text-foreground" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif)">{{ event.title }}</h3>
{% if event.venue %}<p class="reel-caps text-xs tracking-[0.14em] text-muted-foreground">{{ event.venue }}</p>{% endif %}
{% if event.description %}<p class="text-sm text-muted-foreground" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{{ event.description }}</p>{% endif %}
{% if event.link %}<a href="{{ event.link }}" class="reel-link mt-auto inline-flex items-center gap-2 pt-3 text-sm text-primary">{{ event.linkLabel|default:"Details" }}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
{% if event.link %}<a href="{{ event.link }}" class="reel-link mt-auto inline-flex items-center gap-2 pt-3 text-sm text-primary">{{ event.linkLabel|default:"Details" }}<svg class="h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
</div>
</article>
{% endif %}{% endfor %}

View File

@ -7,7 +7,7 @@
<details class="group py-2"{% if variant == "open-list" %} open{% endif %}>
<summary class="flex cursor-pointer list-none items-center justify-between gap-4 py-3 text-lg font-medium marker:content-none [&::-webkit-details-marker]:hidden" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif)">
<span>{{ item.question }}</span>
<svg class="h-5 w-5 shrink-0 text-primary transition-transform duration-200 group-open:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
<svg class="h-5 w-5 shrink-0 text-primary transition-transform duration-200 group-open:rotate-180" width="20" height="20" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
</summary>
<div class="pb-4 text-muted-foreground [&_a]:text-primary [&_a]:underline" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{{ item.answer|safe }}</div>
</details>

View File

@ -6,10 +6,10 @@
<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 %}
<div class="{% if layout == "card" %}reel-frame bg-card p-6 text-card-foreground reel-foil transition-shadow{% elif layout == "centered" %}text-center{% endif %}">
{% if item.icon %}<div class="mb-4 inline-flex h-11 w-11 items-center justify-center border border-[hsl(var(--primary)/0.35)] bg-primary/10 text-primary{% if layout == "centered" %} mx-auto{% endif %}"><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-4 inline-flex h-11 w-11 items-center justify-center border border-[hsl(var(--primary)/0.35)] bg-primary/10 text-primary{% if layout == "centered" %} mx-auto{% endif %}"><svg class="h-6 w-6" width="24" height="24" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg></div>{% endif %}
<h3 class="reel-caps text-lg text-foreground" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif)">{% if item.linkUrl %}<a href="{{ item.linkUrl }}" class="transition-colors hover:text-primary">{{ item.title }}</a>{% else %}{{ item.title }}{% endif %}</h3>
{% if item.text %}<p class="mt-2 text-muted-foreground" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{{ item.text }}</p>{% endif %}
{% if item.linkUrl and item.linkLabel %}<a href="{{ item.linkUrl }}" class="reel-link mt-3 inline-flex items-center gap-1 text-sm">{{ item.linkLabel }}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
{% if item.linkUrl and item.linkLabel %}<a href="{{ item.linkUrl }}" class="reel-link mt-3 inline-flex items-center gap-1 text-sm">{{ item.linkLabel }}<svg class="h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
</div>
{% endfor %}
</div>

View File

@ -2,7 +2,7 @@
{% set fl = layout %}
{% if not fl %}{% if template == "centered" %}{% set fl = "centered" %}{% else %}{% set fl = "columns" %}{% endif %}{% endif %}
{% set fbg = backgroundColor|default:"bg-foreground text-background" %}
{% macro sociallinks(cls) %}{% if social_items %}<div class="flex items-center gap-4 {{ cls }}">{% for s in social_items %}<a href="{{ s.url }}" target="_blank" rel="noopener" title="{{ s.label }}" class="text-background/70 hover:text-primary transition-colors"><span class="sr-only">{{ s.label }}</span>{% if s.icon %}::{{ s.icon }}::{% else %}{{ s.label }}{% endif %}</a>{% endfor %}</div>{% endif %}{% endmacro %}
{% macro sociallinks(cls) %}{% if social_items %}<div class="flex items-center gap-4 {{ cls }}">{% for s in social_items %}<a href="{{ s.url }}" target="_blank" rel="noopener" title="{{ s.label }}" class="text-background/70 hover:text-primary transition-colors"><span class="sr-only">{{ s.label }}</span>{% if s.icon %}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ s.icon|split:":"|first }}.svg#{{ s.icon|split:":"|last }}"></use></svg>{% else %}{{ s.label }}{% endif %}</a>{% endfor %}</div>{% endif %}{% endmacro %}
{% macro newsletter() %}{% if showNewsletter %}<div class="max-w-sm"><h3 class="reel-caps text-sm text-primary">{{ newsletterTitle|default:"Join the guest list" }}</h3>{% if newsletterDescription %}<p class="mt-1 text-sm italic text-background/70">{{ newsletterDescription }}</p>{% endif %}<div class="mt-3">{% signup_form list=newsletterListSlug|default:"main" source="footer" submit=newsletterButtonText|default:"Subscribe" %}</div></div>{% endif %}{% endmacro %}
{% macro legalbar() %}<div class="mt-10 pt-6 border-t border-[hsl(var(--primary)/0.4)] flex flex-col sm:flex-row items-center justify-between gap-3 text-sm text-background/60"><p>{% if copyright %}&copy; {{ copyright }}{% else %}&copy; {{ companyName }}{% endif %}</p>{% if legal_items %}<nav class="flex flex-wrap items-center gap-x-4 gap-y-1">{% for l in legal_items %}<a href="{{ l.url|default:'#' }}"{% if l.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="hover:text-primary transition-colors">{{ l.label }}</a>{% endfor %}</nav>{% endif %}</div>{% endmacro %}
<footer data-block-override="gotham:footer" class="w-full border-t-2 border-[hsl(var(--primary))] {{ fbg }} {{ class }}">

View File

@ -10,10 +10,10 @@
ov.style.cssText='position:fixed;inset:0;z-index:9999;display:none;align-items:center;justify-content:center;background:rgba(0,0,0,0.9);padding:2rem;';
var btn='position:absolute;width:2.75rem;height:2.75rem;display:inline-flex;align-items:center;justify-content:center;border-radius:9999px;border:none;background:hsl(var(--background));color:hsl(var(--foreground));cursor:pointer;';
ov.innerHTML=
'<button type="button" data-lb-close aria-label="Close" style="'+btn+'top:1rem;right:1rem;"><svg style="width:1.25rem;height:1.25rem" aria-hidden="true"><use href="/icons/lucide.svg#x"/></svg></button>'+
'<button type="button" data-lb-prev aria-label="Previous image" style="'+btn+'left:1rem;top:50%;transform:translateY(-50%);"><svg style="width:1.25rem;height:1.25rem" aria-hidden="true"><use href="/icons/lucide.svg#chevron-left"/></svg></button>'+
'<button type="button" data-lb-close aria-label="Close" style="'+btn+'top:1rem;right:1rem;"><svg style="width:1.25rem;height:1.25rem" width="20" height="20" aria-hidden="true"><use href="/icons/lucide.svg#x"/></svg></button>'+
'<button type="button" data-lb-prev aria-label="Previous image" style="'+btn+'left:1rem;top:50%;transform:translateY(-50%);"><svg style="width:1.25rem;height:1.25rem" width="20" height="20" aria-hidden="true"><use href="/icons/lucide.svg#chevron-left"/></svg></button>'+
'<figure style="margin:0;max-width:92vw;max-height:92vh;display:flex;flex-direction:column;align-items:center;gap:0.75rem;"><img data-lb-img alt="" style="max-width:92vw;max-height:82vh;object-fit:contain;border-radius:0.5rem;'+(reduce?'':'transition:opacity .2s ease;')+'"><figcaption data-lb-cap style="color:hsl(var(--background));opacity:.85;font-size:.875rem;text-align:center;max-width:60ch;"></figcaption></figure>'+
'<button type="button" data-lb-next aria-label="Next image" style="'+btn+'right:1rem;top:50%;transform:translateY(-50%);"><svg style="width:1.25rem;height:1.25rem" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"/></svg></button>';
'<button type="button" data-lb-next aria-label="Next image" style="'+btn+'right:1rem;top:50%;transform:translateY(-50%);"><svg style="width:1.25rem;height:1.25rem" width="20" height="20" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"/></svg></button>';
document.body.appendChild(ov);
imgEl=ov.querySelector('[data-lb-img]');capEl=ov.querySelector('[data-lb-cap]');
ov.addEventListener('click',function(e){if(e.target===ov||e.target.closest('[data-lb-close]'))close();});

View File

@ -1,12 +1,12 @@
{# hero override — folds in the old marquee_hero: sunburst overlay + stepped ziggurat framing, gold-foil Antonio headline. Structure/fields/{% img %} calls preserved from builtin. Styled-text fields accept {text,color} or a bare string. #}
{% set eyebrowText = eyebrow.text|default:eyebrow %}
{% set headlineText = headline.text|default:headline %}
{% set subText = subheadline.text|default:subheadline %}
{% set descText = description.text|default:description %}
{% set pText = ctaPrimary.text %}
{% set pUrl = ctaPrimary.url %}
{% set sText = ctaSecondary.text %}
{% set sUrl = ctaSecondary.url %}
{% set eyebrowText = eyebrow|get:"text"|default:eyebrow %}
{% set headlineText = headline|get:"text"|default:headline %}
{% set subText = subheadline|get:"text"|default:subheadline %}
{% set descText = description|get:"text"|default:description %}
{% set pText = ctaPrimary|get:"text" %}
{% set pUrl = ctaPrimary|get:"url" %}
{% set sText = ctaSecondary|get:"text" %}
{% set sUrl = ctaSecondary|get:"url" %}
{% set variant = template|default:"centered" %}
{% set hasImage = backgroundImage %}
{% set showOverlay = hasImage and overlayColor != "none" and overlayColor != "" %}

View File

@ -19,11 +19,11 @@
{% if specialHoursNote %}<p class="mt-4 border-t border-[hsl(var(--primary)/0.3)] pt-3 text-sm italic" style="color:hsl(var(--muted-foreground));">{{ specialHoursNote }}</p>{% endif %}
{% if address %}<div class="mt-6"><div class="reel-caps text-xs" style="color:hsl(var(--primary));">Address</div><address class="mt-1 whitespace-pre-line not-italic" style="font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ address }}</address></div>{% endif %}
{% if phone %}<div class="mt-4"><div class="reel-caps text-xs" style="color:hsl(var(--primary));">Reservations</div><a href="tel:{{ phone }}" class="reel-link mt-1 inline-block">{{ phone }}</a></div>{% endif %}
{% if directionsUrl %}<a href="{{ directionsUrl }}" target="_blank" rel="noopener noreferrer" class="reel-btn mt-6 inline-flex items-center gap-2">::lucide:navigation:sm:: Get directions</a>{% endif %}
{% if directionsUrl %}<a href="{{ directionsUrl }}" target="_blank" rel="noopener noreferrer" class="reel-btn mt-6 inline-flex items-center gap-2"><svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#navigation"></use></svg> Get directions</a>{% endif %}
</div>
{% if mapEmbedUrl %}
<div class="reel-mat 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="reel-caps flex h-full min-h-[16rem] w-full items-center justify-center gap-2 text-sm transition-colors hover:bg-accent hover:text-accent-foreground" style="color:hsl(var(--primary));">::lucide:map-pin:md:: {{ 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="reel-caps flex h-full min-h-[16rem] w-full items-center justify-center gap-2 text-sm transition-colors hover:bg-accent hover:text-accent-foreground" style="color:hsl(var(--primary));"><svg class="inline-block h-5 w-5" width="20" height="20" aria-hidden="true"><use href="/icons/lucide.svg#map-pin"></use></svg> {{ mapButtonLabel|default:"Load map" }}</button>
</div>
{% endif %}
</div>

View File

@ -11,7 +11,7 @@
{% 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="reel-caps px-3 py-2 text-xs text-foreground/80 hover:text-primary transition-colors {{ item.css_class }}">{{ item.label }}</a>{% endmacro %}
{% macro dropdown(item) %}<div class="relative group">
<button type="button" class="reel-caps px-3 py-2 text-xs text-foreground/80 hover:text-primary transition-colors inline-flex items-center gap-1">{{ item.label }}<svg class="h-4 w-4 transition-transform group-hover:rotate-180" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg></button>
{% if use_mega %}<div class="absolute left-1/2 -translate-x-1/2 mt-1 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50"><div class="reel-frame p-6 bg-card grid gap-8" style="grid-template-columns:repeat({{ item.children|length|default:1 }},minmax(10rem,1fr));min-width:min(90vw,42rem)">{% for child in item.children %}<div class="space-y-1">{% if child.item_type == "header" %}<div class="reel-caps px-2 py-1 text-[0.65rem] text-primary border-b border-[hsl(var(--primary)/0.3)] mb-2">{{ child.label }}</div>{% else %}<a href="{{ child.url|default:'#' }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-2 py-2 hover:bg-accent transition-colors {{ child.css_class }}">{% if child.icon %}<span class="mr-1.5 text-primary">::{{ child.icon }}::</span>{% endif %}<span class="text-sm font-medium text-foreground">{{ child.label }}</span>{% if child.description %}<span class="block text-xs text-muted-foreground mt-0.5">{{ child.description }}</span>{% endif %}</a>{% endif %}</div>{% endfor %}</div></div>
{% if use_mega %}<div class="absolute left-1/2 -translate-x-1/2 mt-1 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50"><div class="reel-frame p-6 bg-card grid gap-8" style="grid-template-columns:repeat({{ item.children|length|default:1 }},minmax(10rem,1fr));min-width:min(90vw,42rem)">{% for child in item.children %}<div class="space-y-1">{% if child.item_type == "header" %}<div class="reel-caps px-2 py-1 text-[0.65rem] text-primary border-b border-[hsl(var(--primary)/0.3)] mb-2">{{ child.label }}</div>{% else %}<a href="{{ child.url|default:'#' }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="block px-2 py-2 hover:bg-accent transition-colors {{ child.css_class }}">{% if child.icon %}<span class="mr-1.5 text-primary"><svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ child.icon|split:":"|first }}.svg#{{ child.icon|split:":"|last }}"></use></svg></span>{% endif %}<span class="text-sm font-medium text-foreground">{{ child.label }}</span>{% if child.description %}<span class="block text-xs text-muted-foreground mt-0.5">{{ child.description }}</span>{% endif %}</a>{% endif %}</div>{% endfor %}</div></div>
{% else %}<div class="absolute left-0 mt-1 w-56 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-50"><div class="reel-frame py-2 bg-card">{% for child in item.children %}{% if child.item_type == "header" %}<div class="reel-caps px-4 py-2 text-[0.65rem] text-primary">{{ 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 transition-colors {{ child.css_class }}">{{ child.label }}</a>{% endif %}{% endfor %}</div></div>{% endif %}
</div>{% endmacro %}
{% macro brand(size) %}<a href="/" class="flex-shrink-0 flex items-center">{% if logoType == "text" and logoText.text %}<span class="reel-caps text-xl {{ logoText.color }}" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif);color:hsl(var(--foreground));">{{ logoText.text }}</span>{% elif logo %}<img src="{{ logo }}" alt="{{ alt|default:companyName }}" class="{{ size }} w-auto"{% if logoMaxWidth or logoMaxHeight %} style="{% if logoMaxWidth %}max-width:{{ logoMaxWidth }};{% endif %}{% if logoMaxHeight %}max-height:{{ logoMaxHeight }};{% endif %}"{% endif %}/>{% elif companyName %}<span class="reel-caps text-xl" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif);color:hsl(var(--foreground));">{{ companyName }}</span>{% endif %}</a>{% endmacro %}

View File

@ -5,7 +5,7 @@
<ul class="mt-6 space-y-3 max-w-lg mx-auto">
{% for suggestion in suggestions %}
<li class="flex items-start gap-3">
<span class="mt-0.5 shrink-0" style="color:hsl(var(--primary));">::lucide:chevron-right:sm::</span>
<span class="mt-0.5 shrink-0" style="color:hsl(var(--primary));"><svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"></use></svg></span>
<div>
<a href="{{ suggestion.slug }}" class="reel-link font-medium">{{ suggestion.title }}</a>
{% if showDescription and suggestion.excerpt %}<p class="mt-1 text-sm italic" style="color:hsl(var(--muted-foreground));">{{ suggestion.excerpt }}</p>{% endif %}

View File

@ -14,7 +14,7 @@
</p>
{% if tier.description %}<p class="mt-3 text-center text-sm text-muted-foreground" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{{ tier.description }}</p>{% endif %}
{% 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 text-primary" 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 class="mt-0.5 h-4 w-4 shrink-0 text-primary" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg><span>{{ feature }}</span></li>{% endfor %}
</ul>{% endif %}
{% if tier.ctaUrl and tier.ctaLabel %}{% if tier.highlighted %}<a href="{{ tier.ctaUrl }}" class="reel-btn mt-8 inline-flex w-full items-center justify-center">{{ tier.ctaLabel }}</a>{% else %}<a href="{{ tier.ctaUrl }}" class="reel-link mt-8 inline-flex w-full items-center justify-center">{{ tier.ctaLabel }}</a>{% endif %}{% endif %}
</div>

View File

@ -1,7 +1,7 @@
{# quote override — supper-club press pull-quote: large italic Cormorant flanked by gold sunburst crests. Fields mirror builtin: quote, style, align, cite, attribution, role. #}
{% with style=style|default:"block" align=align|default:"left" %}
<figure data-block-override="gotham:quote" class="bn-quote my-10 {% if style == "inline-card" %}reel-frame bg-card p-8 md:p-10{% elif style == "pull" %}border-l-2 border-[hsl(var(--primary))] pl-6 md:pl-8 py-2{% else %}px-2 py-1{% endif %}{% if align == "center" %} text-center{% endif %}{% if class %} {{ class }}{% endif %}">
{% if align == "center" %}<div class="mb-5 h-6 reel-strip" aria-hidden="true"></div>{% endif %}
{% if align == "center" %}<div class="mb-6 flex justify-center" aria-hidden="true"><span class="reel-rule w-12"></span></div>{% endif %}
<blockquote{% if cite %} cite="{{ cite }}"{% endif %} class="{% if style == "pull" %}text-2xl md:text-3xl leading-snug{% else %}text-xl md:text-2xl leading-relaxed{% endif %} italic" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif);color:hsl(var(--foreground));">{{ quote|safe }}</blockquote>
{% if attribution or role or cite %}<figcaption class="mt-4 text-sm{% if align == "center" %} flex flex-col items-center{% endif %}" style="color:hsl(var(--muted-foreground));">{% if attribution %}<span class="reel-caps text-xs" style="color:hsl(var(--primary));">{{ attribution }}</span>{% endif %}{% if role %}<span class="{% if attribution %}block {% endif %}italic">{{ role }}</span>{% endif %}{% if cite %}<a href="{{ cite }}" class="reel-link {% if attribution or role %}mt-1 {% endif %}inline-block text-xs">Source</a>{% endif %}</figcaption>{% endif %}
</figure>

View File

@ -4,7 +4,7 @@
{% if eyebrow %}<div class="mb-3 flex items-center gap-4"><span class="reel-rule w-12"></span><p class="reel-caps text-xs text-primary">{{ eyebrow }}</p></div>{% endif %}
{% if heading %}<h2 class="reel-caps reel-underline mt-2 text-3xl text-foreground md:text-4xl" style="font-family:var(--font-heading, 'Antonio', 'Oswald', 'Bebas Neue', sans-serif)">{{ heading }}</h2>{% endif %}
{% if body %}<div class="mt-4 space-y-4 text-lg text-muted-foreground [&_a]:text-primary [&_a]:underline [&_strong]:text-foreground" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{{ body|safe }}</div>{% endif %}
{% if ctaUrl and ctaLabel %}<a href="{{ ctaUrl }}" class="reel-btn mt-6 inline-flex items-center gap-2">{{ ctaLabel }}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
{% if ctaUrl and ctaLabel %}<a href="{{ ctaUrl }}" class="reel-btn mt-6 inline-flex items-center gap-2">{{ ctaLabel }}<svg class="h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
</div>
<div class="{% if mediaPosition == "left" %}md:order-1{% else %}md:order-2{% endif %}">
{% if media %}<div class="reel-mat overflow-hidden">{% img media alt=mediaAlt class="w-full h-auto object-cover" %}</div>{% endif %}

View File

@ -6,7 +6,7 @@
{% if title %}<h3 class="reel-caps reel-underline {% if compact %}px-2 mb-4 text-xs text-primary{% else %}px-3 mb-5 text-sm text-foreground{% endif %}" style="font-family:var(--font-heading, &quot;Antonio&quot;, &quot;Oswald&quot;, Georgia, serif)">{{ title }}</h3>{% endif %}
<ul class="{% if compact %}space-y-0.5{% else %}space-y-1{% endif %}">
{% 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="reel-caps flex items-center rounded-none text-sm text-muted-foreground transition-colors hover:text-primary 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-primary" 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="reel-caps flex items-center rounded-none text-sm text-muted-foreground transition-colors hover:text-primary 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-primary" width="16" height="16" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg>{% endif %}{{ item.label }}</a></li>
{% endfor %}
</ul>
</nav>

View File

@ -4,7 +4,7 @@
{% for link in links %}{% if link.url %}
<li>
<a href="{{ link.url }}" target="_blank" rel="noopener noreferrer" aria-label="{{ link.label|default:link.network }}" class="reel-foil inline-flex items-center gap-2 rounded-none border border-[hsl(var(--primary)/0.45)] text-foreground transition-colors hover:bg-primary/10 hover:text-primary {% if style == "stack" %}w-full px-4 py-2.5{% else %}p-2.5{% endif %}">
{% if link.network %}<svg class="h-5 w-5 text-primary" aria-hidden="true"><use href="/icons/{{ link.network|split:":"|first }}.svg#{{ link.network|split:":"|last }}"></use></svg>{% endif %}
{% if link.network %}<svg class="h-5 w-5 text-primary" width="20" height="20" 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="reel-caps text-xs tracking-[0.14em]">{{ link.label }}</span>{% endif %}
</a>
</li>

View File

@ -11,7 +11,7 @@
{% if member.role %}<p class="reel-caps text-xs text-primary">{{ member.role }}</p>{% endif %}
{% if member.bio %}<p class="mt-2 text-sm text-muted-foreground" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{{ member.bio }}</p>{% 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-primary" 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-primary" aria-label="Social link"><svg class="h-5 w-5" width="20" height="20" aria-hidden="true"><use href="/icons/{{ social.icon|split:":"|first }}.svg#{{ social.icon|split:":"|last }}"></use></svg></a>{% endif %}{% endfor %}
</div>{% endif %}
</div>
</div>

View File

@ -5,11 +5,11 @@
{% for q in quotes %}
<figure class="reel-frame flex flex-col bg-card p-6 text-card-foreground{% if layout == "carousel" %} min-w-[18rem] max-w-sm shrink-0 snap-start{% endif %}">
{% if q.rating %}<div class="mb-3 flex justify-center gap-0.5" aria-label="Rated {{ q.rating }} out of 5">
<svg class="h-4 w-4 {% if q.rating >= 1 %}text-primary{% 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-primary{% 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-primary{% 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-primary{% 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-primary{% 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 >= 1 %}text-primary{% else %}text-muted-foreground/30{% endif %}" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
<svg class="h-4 w-4 {% if q.rating >= 2 %}text-primary{% else %}text-muted-foreground/30{% endif %}" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
<svg class="h-4 w-4 {% if q.rating >= 3 %}text-primary{% else %}text-muted-foreground/30{% endif %}" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
<svg class="h-4 w-4 {% if q.rating >= 4 %}text-primary{% else %}text-muted-foreground/30{% endif %}" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
<svg class="h-4 w-4 {% if q.rating >= 5 %}text-primary{% else %}text-muted-foreground/30{% endif %}" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
</div>{% endif %}
<blockquote class="flex-1 text-center text-lg leading-relaxed" style="font-family:var(--font-body, 'Cormorant Garamond', 'Cormorant', Georgia, serif)">{% if q.quote %}&ldquo;{{ q.quote }}&rdquo;{% endif %}</blockquote>
<div class="mx-auto my-4 flex items-center justify-center"><span class="reel-rule w-16"></span></div>

View File

@ -6,7 +6,7 @@
{% for step in steps %}
<li class="{% if orientation == "horizontal" %}text-center{% else %}relative pl-14{% endif %}">
<span class="reel-caps flex h-8 w-8 items-center justify-center border border-primary bg-primary text-sm text-primary-foreground {% if orientation == "horizontal" %}mx-auto{% else %}absolute left-0 top-0 ring-4 ring-background{% endif %}">
{% if marker == "numbered" %}{{ forloop.counter }}{% elif marker == "dot" %}<span class="h-2 w-2 bg-primary-foreground"></span>{% else %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#flag"></use></svg>{% endif %}
{% if marker == "numbered" %}{{ forloop.counter }}{% elif marker == "dot" %}<span class="h-2 w-2 bg-primary-foreground"></span>{% else %}<svg class="h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/lucide.svg#flag"></use></svg>{% endif %}
</span>
<div class="{% if orientation == "horizontal" %}mt-4{% else %}pt-1{% endif %}">
{% if step.label %}<p class="reel-caps text-xs text-primary">{{ step.label }}</p>{% endif %}

View File

@ -1,7 +1,7 @@
{# utility-bar override — thin lacquer contact strip, gold text. Fields mirror builtin: variant, showOnMobile, leftItems/rightItems {icon,label,link}. #}
{% set ubcls = "bg-foreground text-background" %}
{% if variant == "primary" %}{% set ubcls = "bg-primary text-primary-foreground" %}{% elif variant == "dark" %}{% set ubcls = "bg-foreground text-background" %}{% endif %}
{% macro ubitem(it) %}{% if it.link %}<a href="{{ it.link }}" class="reel-caps inline-flex items-center gap-1.5 hover:text-primary transition-colors">{% if it.icon %}::{{ it.icon }}::{% endif %}{% if it.label %}<span>{{ it.label }}</span>{% endif %}</a>{% else %}<span class="reel-caps inline-flex items-center gap-1.5">{% if it.icon %}::{{ it.icon }}::{% endif %}{% if it.label %}<span>{{ it.label }}</span>{% endif %}</span>{% endif %}{% endmacro %}
{% macro ubitem(it) %}{% if it.link %}<a href="{{ it.link }}" class="reel-caps inline-flex items-center gap-1.5 hover:text-primary transition-colors">{% if it.icon %}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ it.icon|split:":"|first }}.svg#{{ it.icon|split:":"|last }}"></use></svg>{% endif %}{% if it.label %}<span>{{ it.label }}</span>{% endif %}</a>{% else %}<span class="reel-caps inline-flex items-center gap-1.5">{% if it.icon %}<svg class="inline-block h-4 w-4" width="16" height="16" aria-hidden="true"><use href="/icons/{{ it.icon|split:":"|first }}.svg#{{ it.icon|split:":"|last }}"></use></svg>{% endif %}{% if it.label %}<span>{{ it.label }}</span>{% endif %}</span>{% endif %}{% endmacro %}
<div data-block-override="gotham:utility-bar" class="w-full text-[0.7rem] {% if not showOnMobile %}hidden sm:block{% endif %} {{ ubcls }} {{ class }}">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-9 flex items-center justify-between gap-4">
<div class="flex items-center gap-5 flex-wrap">{% for it in leftItems %}{{ ubitem(it) }}{% endfor %}</div>

View File

@ -1,5 +1,5 @@
{# video-embed override — gold-framed facade; play button in a gold-ringed medallion. Fields + facade JS mirror builtin verbatim: aspect, url, media, poster, title, caption. #}
{% with aspect=aspect|default:"16:9" %}<figure data-block-override="gotham:video-embed" class="bn-video my-8{% if class %} {{ class }}{% endif %}"><div class="reel-mat"><div class="bn-video-frame relative w-full overflow-hidden bg-muted {% 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:ring-2 focus-visible:ring-inset focus-visible:ring-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/20" aria-hidden="true"></span><span class="reel-foil relative inline-flex h-16 w-16 items-center justify-center rounded-full bg-background/90 text-primary transition-transform group-hover:scale-105 motion-reduce:transform-none">::lucide:play:xl::</span></button></div></div>{% if caption %}<figcaption class="mt-3 text-center text-sm italic" style="color:hsl(var(--muted-foreground));font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ caption }}</figcaption>{% endif %}</figure><script>
{% with aspect=aspect|default:"16:9" %}<figure data-block-override="gotham:video-embed" class="bn-video my-8{% if class %} {{ class }}{% endif %}"><div class="reel-mat"><div class="bn-video-frame relative w-full overflow-hidden bg-muted {% 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:ring-2 focus-visible:ring-inset focus-visible:ring-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/20" aria-hidden="true"></span><span class="reel-foil relative inline-flex h-16 w-16 items-center justify-center rounded-full bg-background/90 text-primary transition-transform group-hover:scale-105 motion-reduce:transform-none"><svg class="inline-block h-8 w-8" width="32" height="32" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg></span></button></div></div>{% if caption %}<figcaption class="mt-3 text-center text-sm italic" style="color:hsl(var(--muted-foreground));font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ caption }}</figcaption>{% endif %}</figure><script>
(function(){
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;}