fix(pastel-dream): seed product photos, unclippable price row, SVG geometry guard
- Seed 6 licensed bakery photos (media array) and wire them to every product card: home Seasonal Specials (strawberry tart/croissant/lemon loaf) and the article Cake Gallery (tart/sponge/galette). Kills the 'Add a photo' placeholder residue on all six cards. Also adds a bakery interior shot to the About story section. - Card title/price row: price moved to its own line (cake gallery) / a wrapping badge+price row under the title (seasonal specials) so a long product name never collides with the price and '$X.XX' can never clip. - SVG geometry guard: explicit width/height on all 43 <use> icon SVGs so the host Tailwind JIT dropping a size utility can't balloon an icon. - Lengthen the strawberries article to 8 paragraphs (bakery voice). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
d4e21e484b
commit
4ac5f76714
@ -10,14 +10,10 @@
|
|||||||
<figure class="pd-frame overflow-hidden flex flex-col">
|
<figure class="pd-frame overflow-hidden flex flex-col">
|
||||||
{% if cake.image %}<div class="relative w-full overflow-hidden aspect-square pd-torn-bottom bg-secondary">{% img cake.image alt=cake.name|default:"Cake" class="block h-full w-full object-cover" %}</div>{% endif %}
|
{% if cake.image %}<div class="relative w-full overflow-hidden aspect-square pd-torn-bottom bg-secondary">{% img cake.image alt=cake.name|default:"Cake" class="block h-full w-full object-cover" %}</div>{% endif %}
|
||||||
<figcaption class="p-5 md:p-6">
|
<figcaption class="p-5 md:p-6">
|
||||||
<div class="flex items-start justify-between gap-3">
|
|
||||||
<div>
|
|
||||||
{% if cake.name %}<h3 class="pd-display text-xl text-primary">{{ cake.name }}</h3>{% endif %}
|
{% if cake.name %}<h3 class="pd-display text-xl text-primary">{{ cake.name }}</h3>{% endif %}
|
||||||
{% if cake.flavour %}<p class="pd-hand text-base text-accent">{{ cake.flavour }}</p>{% endif %}
|
{% if cake.flavour %}<p class="pd-hand text-base text-accent">{{ cake.flavour }}</p>{% endif %}
|
||||||
</div>
|
{% if cake.price %}<p class="pd-mono mt-1.5 text-lg text-accent tabular-nums">{% if currency %}{{ currency }}{% endif %}{{ cake.price }}</p>{% endif %}
|
||||||
{% if cake.price %}<span class="pd-mono shrink-0 text-lg text-accent tabular-nums">{% if currency %}{{ currency }}{% endif %}{{ cake.price }}</span>{% endif %}
|
{% if cake.orderUrl %}<a href="{{ cake.orderUrl }}" class="pd-tag pd-tag--ghost mt-4 text-sm">Order this cake<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
|
||||||
</div>
|
|
||||||
{% if cake.orderUrl %}<a href="{{ cake.orderUrl }}" class="pd-tag pd-tag--ghost mt-4 text-sm">Order this cake<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
|
|
||||||
</figcaption>
|
</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% if ctaLabel %}
|
{% if ctaLabel %}
|
||||||
<div class="shrink-0">
|
<div class="shrink-0">
|
||||||
<a href="{{ ctaUrl|default:"/contact" }}" class="pd-tag text-base">{{ ctaLabel }}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>
|
<a href="{{ ctaUrl|default:"/contact" }}" class="pd-tag text-base">{{ ctaLabel }}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,11 +11,11 @@
|
|||||||
<article class="pd-card overflow-hidden flex flex-col">
|
<article class="pd-card overflow-hidden flex flex-col">
|
||||||
{% if item.image %}<div class="relative w-full overflow-hidden aspect-[4/3] bg-secondary">{% img item.image alt=item.name|default:"Seasonal special" class="block h-full w-full object-cover" %}</div>{% endif %}
|
{% if item.image %}<div class="relative w-full overflow-hidden aspect-[4/3] bg-secondary">{% img item.image alt=item.name|default:"Seasonal special" class="block h-full w-full object-cover" %}</div>{% endif %}
|
||||||
<div class="p-5 md:p-6">
|
<div class="p-5 md:p-6">
|
||||||
<div class="flex items-start justify-between gap-3">
|
|
||||||
<h3 class="pd-display text-xl text-primary">{{ item.name }}</h3>
|
<h3 class="pd-display text-xl text-primary">{{ item.name }}</h3>
|
||||||
{% if item.price %}<span class="pd-mono shrink-0 text-lg text-accent tabular-nums">{% if currency %}{{ currency }}{% endif %}{{ item.price }}</span>{% endif %}
|
<div class="mt-1.5 flex flex-wrap items-center gap-x-3 gap-y-1.5">
|
||||||
|
{% if item.price %}<span class="pd-mono text-lg text-accent tabular-nums">{% if currency %}{{ currency }}{% endif %}{{ item.price }}</span>{% endif %}
|
||||||
|
{% if item.badge %}<span class="pd-hand inline-flex rounded-full bg-accent/15 px-3 py-0.5 text-sm text-accent">{{ item.badge }}</span>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if item.badge %}<span class="pd-hand mt-2 inline-flex rounded-full bg-accent/15 px-3 py-0.5 text-sm text-accent">{{ item.badge }}</span>{% endif %}
|
|
||||||
{% if item.note %}<p class="pd-body mt-3 text-sm text-muted-foreground">{{ item.note }}</p>{% endif %}
|
{% if item.note %}<p class="pd-body mt-3 text-sm text-muted-foreground">{{ item.note }}</p>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
BIN
seed/media/bakery-interior.jpg
Normal file
BIN
seed/media/bakery-interior.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 344 KiB |
BIN
seed/media/croissants.jpg
Normal file
BIN
seed/media/croissants.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 205 KiB |
BIN
seed/media/fruit-galette.jpg
Normal file
BIN
seed/media/fruit-galette.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 198 KiB |
BIN
seed/media/lemon-loaf.jpg
Normal file
BIN
seed/media/lemon-loaf.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 308 KiB |
BIN
seed/media/sponge-cake.jpg
Normal file
BIN
seed/media/sponge-cake.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 171 KiB |
BIN
seed/media/strawberry-tart.jpg
Normal file
BIN
seed/media/strawberry-tart.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 256 KiB |
@ -6,6 +6,14 @@
|
|||||||
"site_description": "A small patisserie baking cakes, pastries and seasonal treats."
|
"site_description": "A small patisserie baking cakes, pastries and seasonal treats."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"media": [
|
||||||
|
{ "id": "a1b2c3d4-0001-4a00-8000-000000000001", "file": "media/strawberry-tart.jpg", "alt": "Strawberry tart with vanilla custard and a glaze of fresh berries", "folder": "Petal & Crumb" },
|
||||||
|
{ "id": "a1b2c3d4-0001-4a00-8000-000000000002", "file": "media/croissants.jpg", "alt": "Golden laminated croissants fresh from the oven", "folder": "Petal & Crumb" },
|
||||||
|
{ "id": "a1b2c3d4-0001-4a00-8000-000000000003", "file": "media/lemon-loaf.jpg", "alt": "Lemon poppy loaf dusted with sugar, sliced", "folder": "Petal & Crumb" },
|
||||||
|
{ "id": "a1b2c3d4-0001-4a00-8000-000000000004", "file": "media/sponge-cake.jpg", "alt": "Light sponge cake layered with cream", "folder": "Petal & Crumb" },
|
||||||
|
{ "id": "a1b2c3d4-0001-4a00-8000-000000000005", "file": "media/fruit-galette.jpg", "alt": "Rustic fruit galette with berries and whipped cream", "folder": "Petal & Crumb" },
|
||||||
|
{ "id": "a1b2c3d4-0001-4a00-8000-000000000006", "file": "media/bakery-interior.jpg", "alt": "The counter at Petal & Crumb, breads and pastries on display", "folder": "Petal & Crumb" }
|
||||||
|
],
|
||||||
"data_tables": [
|
"data_tables": [
|
||||||
{
|
{
|
||||||
"key": "contact_submissions",
|
"key": "contact_submissions",
|
||||||
@ -36,9 +44,9 @@
|
|||||||
{ "block_key": "navbar", "title": "Navigation", "slot": "header", "sort_order": 0, "content": { "menuName": "main", "companyName": "Petal & Crumb", "ctaLabel": "Order a cake", "ctaUrl": "/contact" } },
|
{ "block_key": "navbar", "title": "Navigation", "slot": "header", "sort_order": 0, "content": { "menuName": "main", "companyName": "Petal & Crumb", "ctaLabel": "Order a cake", "ctaUrl": "/contact" } },
|
||||||
{ "block_key": "hero", "title": "Hero", "slot": "main", "sort_order": 0, "content": { "template": "centered", "eyebrow": "Open from 8", "headline": "Cakes and pastries, baked fresh each morning", "subheadline": "A small patisserie on the corner. Everything is made by hand the day you eat it.", "ctaPrimary": { "text": "See the menu", "url": "/#menu" }, "ctaSecondary": { "text": "Order a cake", "url": "/contact" }, "minHeight": "50vh" } },
|
{ "block_key": "hero", "title": "Hero", "slot": "main", "sort_order": 0, "content": { "template": "centered", "eyebrow": "Open from 8", "headline": "Cakes and pastries, baked fresh each morning", "subheadline": "A small patisserie on the corner. Everything is made by hand the day you eat it.", "ctaPrimary": { "text": "See the menu", "url": "/#menu" }, "ctaSecondary": { "text": "Order a cake", "url": "/contact" }, "minHeight": "50vh" } },
|
||||||
{ "block_key": "pastel-dream:seasonal_specials", "title": "Seasonal Specials", "slot": "main", "sort_order": 1, "content": { "kicker": "This week", "heading": "On the counter now", "intro": "A short list of what we are proud of this week. It changes with the season.", "currency": "$", "items": [
|
{ "block_key": "pastel-dream:seasonal_specials", "title": "Seasonal Specials", "slot": "main", "sort_order": 1, "content": { "kicker": "This week", "heading": "On the counter now", "intro": "A short list of what we are proud of this week. It changes with the season.", "currency": "$", "items": [
|
||||||
{ "name": "Strawberry tart", "note": "Vanilla custard, fresh strawberries, a thin glaze.", "price": "8.00", "badge": "New" },
|
{ "image": "media:a1b2c3d4-0001-4a00-8000-000000000001", "name": "Strawberry tart", "note": "Vanilla custard, fresh strawberries, a thin glaze.", "price": "8.00", "badge": "New" },
|
||||||
{ "name": "Pistachio croissant", "note": "Laminated overnight, filled with pistachio cream.", "price": "6.50", "badge": "Popular" },
|
{ "image": "media:a1b2c3d4-0001-4a00-8000-000000000002", "name": "Pistachio croissant", "note": "Laminated overnight, filled with pistachio cream.", "price": "6.50", "badge": "Popular" },
|
||||||
{ "name": "Lemon poppy loaf", "note": "Soft, tangy, dusted with sugar. Sold by the slice.", "price": "5.00", "badge": "" }
|
{ "image": "media:a1b2c3d4-0001-4a00-8000-000000000003", "name": "Lemon poppy loaf", "note": "Soft, tangy, dusted with sugar. Sold by the slice.", "price": "5.00", "badge": "" }
|
||||||
] } },
|
] } },
|
||||||
{ "block_key": "menu-list", "title": "Menu", "slot": "main", "sort_order": 2, "content": { "heading": "The full menu", "intro": "Prices are for takeaway. We can box anything for a gift.", "currency": "$", "columns": 2, "sections": [
|
{ "block_key": "menu-list", "title": "Menu", "slot": "main", "sort_order": 2, "content": { "heading": "The full menu", "intro": "Prices are for takeaway. We can box anything for a gift.", "currency": "$", "columns": 2, "sections": [
|
||||||
{ "title": "Pastries", "items": [
|
{ "title": "Pastries", "items": [
|
||||||
@ -74,7 +82,7 @@
|
|||||||
"blocks": [
|
"blocks": [
|
||||||
{ "block_key": "navbar", "title": "Navigation", "slot": "header", "sort_order": 0, "content": { "menuName": "main", "companyName": "Petal & Crumb", "ctaLabel": "Order a cake", "ctaUrl": "/contact" } },
|
{ "block_key": "navbar", "title": "Navigation", "slot": "header", "sort_order": 0, "content": { "menuName": "main", "companyName": "Petal & Crumb", "ctaLabel": "Order a cake", "ctaUrl": "/contact" } },
|
||||||
{ "block_key": "hero", "title": "Hero", "slot": "main", "sort_order": 0, "content": { "template": "centered", "eyebrow": "Our story", "headline": "One oven, one small room", "subheadline": "We opened with a single oven and a short menu. We kept it that way on purpose.", "minHeight": "auto" } },
|
{ "block_key": "hero", "title": "Hero", "slot": "main", "sort_order": 0, "content": { "template": "centered", "eyebrow": "Our story", "headline": "One oven, one small room", "subheadline": "We opened with a single oven and a short menu. We kept it that way on purpose.", "minHeight": "auto" } },
|
||||||
{ "block_key": "rich-section", "title": "Story", "slot": "main", "sort_order": 1, "content": { "eyebrow": "How we bake", "heading": "Made the same day", "body": "<p>We start before dawn. The pastry is laminated the night before and baked in the morning, so it reaches you the same day it is made.</p><p>The menu is short because we make everything ourselves. When something is out, it is out until the next bake.</p>", "mediaPosition": "right" } },
|
{ "block_key": "rich-section", "title": "Story", "slot": "main", "sort_order": 1, "content": { "eyebrow": "How we bake", "heading": "Made the same day", "body": "<p>We start before dawn. The pastry is laminated the night before and baked in the morning, so it reaches you the same day it is made.</p><p>The menu is short because we make everything ourselves. When something is out, it is out until the next bake.</p>", "mediaPosition": "right", "media": "media:a1b2c3d4-0001-4a00-8000-000000000006", "mediaAlt": "The counter at Petal & Crumb, breads and pastries on display" } },
|
||||||
{ "block_key": "pastel-dream:bakers_note", "title": "Baker's Note", "slot": "main", "sort_order": 2, "content": { "kicker": "A note from the kitchen", "body": "<p>Thank you for buying from a small shop. Every order helps us keep baking by hand. We taste each batch before it reaches the counter, and we would rather sell out than cut a corner.</p>", "signatureName": "Cara Wells", "signatureRole": "Baker and owner" } },
|
{ "block_key": "pastel-dream:bakers_note", "title": "Baker's Note", "slot": "main", "sort_order": 2, "content": { "kicker": "A note from the kitchen", "body": "<p>Thank you for buying from a small shop. Every order helps us keep baking by hand. We taste each batch before it reaches the counter, and we would rather sell out than cut a corner.</p>", "signatureName": "Cara Wells", "signatureRole": "Baker and owner" } },
|
||||||
{ "block_key": "team", "title": "Team", "slot": "main", "sort_order": 3, "content": { "heading": "The people at the bench", "members": [
|
{ "block_key": "team", "title": "Team", "slot": "main", "sort_order": 3, "content": { "heading": "The people at the bench", "members": [
|
||||||
{ "name": "Cara", "role": "Baker and owner", "bio": "Laminates the pastry and runs the morning bake." },
|
{ "name": "Cara", "role": "Baker and owner", "bio": "Laminates the pastry and runs the morning bake." },
|
||||||
@ -105,11 +113,11 @@
|
|||||||
"blocks": [
|
"blocks": [
|
||||||
{ "block_key": "navbar", "title": "Navigation", "slot": "header", "sort_order": 0, "content": { "menuName": "main", "companyName": "Petal & Crumb", "ctaLabel": "Order a cake", "ctaUrl": "/contact" } },
|
{ "block_key": "navbar", "title": "Navigation", "slot": "header", "sort_order": 0, "content": { "menuName": "main", "companyName": "Petal & Crumb", "ctaLabel": "Order a cake", "ctaUrl": "/contact" } },
|
||||||
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 0, "content": { "level": 1, "text": "Strawberries are in" } },
|
{ "block_key": "heading", "title": "Title", "slot": "main", "sort_order": 0, "content": { "level": 1, "text": "Strawberries are in" } },
|
||||||
{ "block_key": "text", "title": "Body", "slot": "main", "sort_order": 1, "content": { "text": "<p>The first ripe strawberries came in this week. They are small, sweet, and they do not keep, so we use them fast.</p><p>This week they go into the strawberry tart and a plain sponge with cream. When they run out, we move on to the next fruit.</p><p>Come in early. The tarts tend to go before lunch.</p>" } },
|
{ "block_key": "text", "title": "Body", "slot": "main", "sort_order": 1, "content": { "text": "<p>The first ripe strawberries came in this week. They are small, sweet, and they do not keep, so we use them fast. A grower two towns over drops a tray at the back door before we open, still cool from the morning.</p><p>We sort them by hand at the bench. The neat ones go on the tarts, where they sit in rows and catch the light. The soft ones are just as good, so they go into the jam pan and cook down for the sponge.</p><p>A strawberry tart is a simple thing done carefully. We blind bake the pastry until it is properly short, cool it, then pipe in vanilla custard the same morning. The fruit goes on last, with a thin brush of glaze so it shines without turning sticky.</p><p>The sponge is the other side of the same fruit. We fold cream and a spoon of that quick jam between two light layers, then a dusting of sugar on top. It is the cake we make when we want the strawberry to taste like summer rather than like a garnish.</p><p>Strawberries do not wait. They are best the day they are picked and a little tired by the next, so we do not hold them back or freeze a batch for later. What comes in is what we bake, and when it is gone it is gone.</p><p>That is the whole reason the menu changes. We would rather follow the fruit than force it. Next it will be the first stone fruit, and the tarts will turn gold instead of red.</p><p>If you have a favourite, tell us at the counter. We keep a short list of who asked for what, and we will put one aside when the season is at its best.</p><p>Come in early if you can. The tarts tend to go before lunch, and the sponge is usually cut by mid afternoon. There is always something on the counter, but the strawberries are worth the early trip.</p>" } },
|
||||||
{ "block_key": "pastel-dream:cake_gallery", "title": "Cake Gallery", "slot": "main", "sort_order": 2, "content": { "heading": "What we made this week", "intro": "A few things that came out of the oven.", "currency": "$", "cakes": [
|
{ "block_key": "pastel-dream:cake_gallery", "title": "Cake Gallery", "slot": "main", "sort_order": 2, "content": { "heading": "What we made this week", "intro": "A few things that came out of the oven.", "currency": "$", "cakes": [
|
||||||
{ "name": "Strawberry tart", "flavour": "Vanilla custard", "price": "8.00", "orderUrl": "/contact" },
|
{ "image": "media:a1b2c3d4-0001-4a00-8000-000000000001", "name": "Strawberry tart", "flavour": "Vanilla custard", "price": "8.00", "orderUrl": "/contact" },
|
||||||
{ "name": "Strawberry sponge", "flavour": "Cream and jam", "price": "7.00", "orderUrl": "/contact" },
|
{ "image": "media:a1b2c3d4-0001-4a00-8000-000000000004", "name": "Strawberry sponge", "flavour": "Cream and jam", "price": "7.00", "orderUrl": "/contact" },
|
||||||
{ "name": "Fruit galette", "flavour": "Seasonal", "price": "6.50", "orderUrl": "/contact" }
|
{ "image": "media:a1b2c3d4-0001-4a00-8000-000000000005", "name": "Fruit galette", "flavour": "Seasonal", "price": "6.50", "orderUrl": "/contact" }
|
||||||
] } },
|
] } },
|
||||||
{ "block_key": "footer", "title": "Footer", "slot": "footer", "sort_order": 0, "content": { "companyName": "Petal & Crumb", "tagline": "A small patisserie, baked fresh each morning.", "email": "hello@petalandcrumb.test", "copyright": "Petal & Crumb" } }
|
{ "block_key": "footer", "title": "Footer", "slot": "footer", "sort_order": 0, "content": { "companyName": "Petal & Crumb", "tagline": "A small patisserie, baked fresh each morning.", "email": "hello@petalandcrumb.test", "copyright": "Petal & Crumb" } }
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<figure class="bn-audio pd-card my-8 overflow-hidden{% if class %} {{ class }}{% endif %}" data-bn-audio data-audio-url="{{ url|default:"" }}" data-audio-media="{% if media %}{{ media|mediaURL }}{% endif %}"><div class="flex items-center gap-4 p-4">{% if artwork %}<div class="h-16 w-16 shrink-0 overflow-hidden rounded-sm bg-secondary">{% 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="pd-display truncate text-lg text-primary">{{ title }}</p>{% endif %}{% if artist %}<p class="pd-hand truncate text-lg text-accent">{{ artist }}</p>{% endif %}<div class="mt-2 flex items-center gap-3" data-bn-audio-slot><button type="button" data-bn-audio-play class="pd-tag text-xs" aria-label="Play{% if title %}: {{ title }}{% endif %}"><svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg> Play</button>{% if download %}<a href="{% if media %}{{ media|mediaURL }}{% else %}{{ url }}{% endif %}" download class="pd-body inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground"><svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#download"></use></svg> Download</a>{% endif %}</div></div></div></figure><script>
|
<figure class="bn-audio pd-card my-8 overflow-hidden{% if class %} {{ class }}{% endif %}" data-bn-audio data-audio-url="{{ url|default:"" }}" data-audio-media="{% if media %}{{ media|mediaURL }}{% endif %}"><div class="flex items-center gap-4 p-4">{% if artwork %}<div class="h-16 w-16 shrink-0 overflow-hidden rounded-sm bg-secondary">{% 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="pd-display truncate text-lg text-primary">{{ title }}</p>{% endif %}{% if artist %}<p class="pd-hand truncate text-lg text-accent">{{ artist }}</p>{% endif %}<div class="mt-2 flex items-center gap-3" data-bn-audio-slot><button type="button" data-bn-audio-play class="pd-tag text-xs" aria-label="Play{% if title %}: {{ title }}{% endif %}"><svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg> Play</button>{% if download %}<a href="{% if media %}{{ media|mediaURL }}{% else %}{{ url }}{% endif %}" download class="pd-body inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground"><svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#download"></use></svg> Download</a>{% endif %}</div></div></div></figure><script>
|
||||||
(function(){
|
(function(){
|
||||||
if(window.__bnAudioFacade)return;window.__bnAudioFacade=true;
|
if(window.__bnAudioFacade)return;window.__bnAudioFacade=true;
|
||||||
document.addEventListener('click',function(e){
|
document.addEventListener('click',function(e){
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
<button type="button" onclick="this.nextElementSibling.classList.toggle('hidden')" class="pd-body flex items-center gap-2 rounded-lg px-3 py-1.5 text-sm font-medium opacity-90 transition-colors hover:bg-muted hover:opacity-100">
|
<button type="button" onclick="this.nextElementSibling.classList.toggle('hidden')" class="pd-body flex items-center gap-2 rounded-lg px-3 py-1.5 text-sm font-medium opacity-90 transition-colors hover:bg-muted hover:opacity-100">
|
||||||
<span class="pd-hand flex h-7 w-7 items-center justify-center rounded-full bg-accent text-sm text-accent-foreground">{{ auth.display_name|first|upper }}</span>
|
<span class="pd-hand flex h-7 w-7 items-center justify-center rounded-full bg-accent text-sm text-accent-foreground">{{ auth.display_name|first|upper }}</span>
|
||||||
<span>{{ auth.display_name }}</span>
|
<span>{{ auth.display_name }}</span>
|
||||||
<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
||||||
</button>
|
</button>
|
||||||
<div id="auth-dropdown-menu" class="pd-card absolute right-0 top-full z-50 mt-1 hidden w-48 py-1 shadow-lg">
|
<div id="auth-dropdown-menu" class="pd-card absolute right-0 top-full z-50 mt-1 hidden w-48 py-1 shadow-lg">
|
||||||
<a href="/account" class="pd-body block px-4 py-2 text-sm text-foreground hover:bg-muted">My profile</a>
|
<a href="/account" class="pd-body block px-4 py-2 text-sm text-foreground hover:bg-muted">My profile</a>
|
||||||
|
|||||||
@ -10,10 +10,10 @@
|
|||||||
{% if author.location %}<span>{{ author.location }}</span>{% endif %}
|
{% if author.location %}<span>{{ author.location }}</span>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if showSocial %}<div class="mt-5 flex items-center justify-center gap-3">
|
{% if showSocial %}<div class="mt-5 flex items-center justify-center gap-3">
|
||||||
{% if author.website_url %}<a href="{{ author.website_url }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="Website"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/lucide.svg#globe"></use></svg></a>{% endif %}
|
{% if author.website_url %}<a href="{{ author.website_url }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="Website"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/lucide.svg#globe"></use></svg></a>{% endif %}
|
||||||
{% if author.twitter_handle %}<a href="https://twitter.com/{{ author.twitter_handle|cut:"@" }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="Twitter"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#x"></use></svg></a>{% endif %}
|
{% if author.twitter_handle %}<a href="https://twitter.com/{{ author.twitter_handle|cut:"@" }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="Twitter"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#x"></use></svg></a>{% endif %}
|
||||||
{% if author.linkedin_url %}<a href="{{ author.linkedin_url }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="LinkedIn"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#linkedin"></use></svg></a>{% endif %}
|
{% if author.linkedin_url %}<a href="{{ author.linkedin_url }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="LinkedIn"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#linkedin"></use></svg></a>{% endif %}
|
||||||
{% if author.github_url %}<a href="{{ author.github_url }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="GitHub"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#github"></use></svg></a>{% endif %}
|
{% if author.github_url %}<a href="{{ author.github_url }}" target="_blank" rel="noopener" class="text-muted-foreground transition-colors hover:text-accent" title="GitHub"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/simple-icons.svg#github"></use></svg></a>{% endif %}
|
||||||
</div>{% endif %}
|
</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% if showHome %}<li class="flex items-center"><a href="/" class="text-muted-foreground transition-colors hover:text-accent">{{ homeLabel|default:"Home" }}</a></li>{% endif %}
|
{% if showHome %}<li class="flex items-center"><a href="/" class="text-muted-foreground transition-colors hover:text-accent">{{ homeLabel|default:"Home" }}</a></li>{% endif %}
|
||||||
{% for item in breadcrumbs %}
|
{% for item in breadcrumbs %}
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
{% if showHome or not forloop.First %}{% if arrows %}<svg class="mx-2 h-4 w-4 text-accent" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"></use></svg>{% else %}<span class="mx-2 text-accent">{{ separator|default:"/" }}</span>{% endif %}{% endif %}
|
{% if showHome or not forloop.First %}{% if arrows %}<svg width="16" height="16" class="mx-2 h-4 w-4 text-accent" aria-hidden="true"><use href="/icons/lucide.svg#chevron-right"></use></svg>{% else %}<span class="mx-2 text-accent">{{ separator|default:"/" }}</span>{% endif %}{% endif %}
|
||||||
{% if item.is_current %}{% if showCurrent %}<span class="pd-display text-foreground" aria-current="page">{{ item.label }}</span>{% endif %}{% else %}<a href="{{ item.url }}" class="text-muted-foreground transition-colors hover:text-accent">{{ item.label }}</a>{% endif %}
|
{% if item.is_current %}{% if showCurrent %}<span class="pd-display text-foreground" aria-current="page">{{ item.label }}</span>{% endif %}{% else %}<a href="{{ item.url }}" class="text-muted-foreground transition-colors hover:text-accent">{{ item.label }}</a>{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{% with align=align|default:"left" style=style|default:"primary" %}
|
{% with align=align|default:"left" style=style|default:"primary" %}
|
||||||
<div class="bn-button flex {% if align == "center" %}justify-center{% elif align == "right" %}justify-end{% else %}justify-start{% endif %}{% if class %} {{ class }}{% endif %}">
|
<div class="bn-button flex {% if align == "center" %}justify-center{% elif align == "right" %}justify-end{% else %}justify-start{% endif %}{% if class %} {{ class }}{% endif %}">
|
||||||
{% if link %}<a href="{{ link }}"{% if newTab %} target="_blank" rel="noopener"{% endif %} class="pd-tag {% if style == "secondary" %}bg-secondary text-secondary-foreground{% elif style == "outline" or style == "ghost" %}pd-tag--ghost{% elif style == "destructive" %}bg-destructive text-destructive-foreground{% endif %} {% if size == "lg" %}text-base px-6 py-3{% elif size == "sm" %}text-xs px-3 py-1.5{% endif %}">{% if icon and iconPosition != "right" %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}<span>{{ label|default:"Learn more" }}</span>{% if icon and iconPosition == "right" %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}</a>{% else %}<button type="button" class="pd-tag {% if style == "secondary" %}bg-secondary text-secondary-foreground{% elif style == "outline" or style == "ghost" %}pd-tag--ghost{% elif style == "destructive" %}bg-destructive text-destructive-foreground{% endif %} {% if size == "lg" %}text-base px-6 py-3{% elif size == "sm" %}text-xs px-3 py-1.5{% endif %}">{% if icon and iconPosition != "right" %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}<span>{{ label|default:"Learn more" }}</span>{% if icon and iconPosition == "right" %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}</button>{% endif %}
|
{% if link %}<a href="{{ link }}"{% if newTab %} target="_blank" rel="noopener"{% endif %} class="pd-tag {% if style == "secondary" %}bg-secondary text-secondary-foreground{% elif style == "outline" or style == "ghost" %}pd-tag--ghost{% elif style == "destructive" %}bg-destructive text-destructive-foreground{% endif %} {% if size == "lg" %}text-base px-6 py-3{% elif size == "sm" %}text-xs px-3 py-1.5{% endif %}">{% if icon and iconPosition != "right" %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}<span>{{ label|default:"Learn more" }}</span>{% if icon and iconPosition == "right" %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}</a>{% else %}<button type="button" class="pd-tag {% if style == "secondary" %}bg-secondary text-secondary-foreground{% elif style == "outline" or style == "ghost" %}pd-tag--ghost{% elif style == "destructive" %}bg-destructive text-destructive-foreground{% endif %} {% if size == "lg" %}text-base px-6 py-3{% elif size == "sm" %}text-xs px-3 py-1.5{% endif %}">{% if icon and iconPosition != "right" %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}<span>{{ label|default:"Learn more" }}</span>{% if icon and iconPosition == "right" %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/{{ icon|split:":"|first }}.svg#{{ icon|split:":"|last }}"></use></svg>{% endif %}</button>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<div class="flex flex-col gap-2 p-5 md:p-6 {% if layout == "horizontal" %}justify-center{% endif %}">
|
<div class="flex flex-col gap-2 p-5 md:p-6 {% if layout == "horizontal" %}justify-center{% endif %}">
|
||||||
{% if title %}<h3 class="pd-display text-xl text-primary">{{ title }}</h3>{% endif %}
|
{% if title %}<h3 class="pd-display text-xl text-primary">{{ title }}</h3>{% endif %}
|
||||||
{% if text %}<div class="pd-body text-sm leading-relaxed text-muted-foreground">{{ text|safe }}</div>{% endif %}
|
{% if text %}<div class="pd-body text-sm leading-relaxed text-muted-foreground">{{ text|safe }}</div>{% endif %}
|
||||||
{% if linkLabel and link %}<span class="pd-hand mt-2 inline-flex items-center gap-1 text-lg text-accent">{{ linkLabel }} <svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></span>{% endif %}
|
{% if linkLabel and link %}<span class="pd-hand mt-2 inline-flex items-center gap-1 text-lg text-accent">{{ linkLabel }} <svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></span>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if link %}</a>{% endif %}
|
{% if link %}</a>{% endif %}
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<div class="mt-10 grid grid-cols-1 gap-4 {% if columns == 3 %}sm:grid-cols-2 lg:grid-cols-3{% elif columns == 1 %}{% else %}sm:grid-cols-2{% endif %}">
|
<div class="mt-10 grid grid-cols-1 gap-4 {% if columns == 3 %}sm:grid-cols-2 lg:grid-cols-3{% elif columns == 1 %}{% else %}sm:grid-cols-2{% endif %}">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<div class="pd-card flex items-start gap-4 p-5">
|
<div class="pd-card flex items-start gap-4 p-5">
|
||||||
{% if channel.icon %}<span class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent/15 text-accent"><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-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent/15 text-accent"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ channel.icon|split:":"|first }}.svg#{{ channel.icon|split:":"|last }}"></use></svg></span>{% endif %}
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
{% if channel.label %}<div class="pd-hand text-lg text-accent">{{ channel.label }}</div>{% endif %}
|
{% if channel.label %}<div class="pd-hand text-lg text-accent">{{ channel.label }}</div>{% endif %}
|
||||||
{% if channel.value %}<div class="pd-body mt-0.5 break-words font-medium">{% if channel.link %}<a href="{{ channel.link }}" class="transition-colors hover:text-accent">{{ channel.value }}</a>{% else %}{{ channel.value }}{% endif %}</div>{% endif %}
|
{% if channel.value %}<div class="pd-body mt-0.5 break-words font-medium">{% if channel.link %}<a href="{{ channel.link }}" class="transition-colors hover:text-accent">{{ channel.value }}</a>{% else %}{{ channel.value }}{% endif %}</div>{% endif %}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
<div class="mx-auto max-w-2xl px-4">
|
<div class="mx-auto max-w-2xl px-4">
|
||||||
{% if form.submitted %}
|
{% if form.submitted %}
|
||||||
<div class="pd-card pd-torn-top pd-torn-bottom p-8 text-center">
|
<div class="pd-card pd-torn-top pd-torn-bottom p-8 text-center">
|
||||||
<div class="mx-auto mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full bg-accent/15 text-accent"><svg class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg></div>
|
<div class="mx-auto mb-4 inline-flex h-12 w-12 items-center justify-center rounded-full bg-accent/15 text-accent"><svg width="24" height="24" class="h-6 w-6" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg></div>
|
||||||
<p class="pd-display text-xl text-primary">{{ form.message|default:successMessage|default:"Thanks. Your message is on its way." }}</p>
|
<p class="pd-display text-xl text-primary">{{ form.message|default:successMessage|default:"Thanks. Your message is on its way." }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-8 hidden" data-countdown-expired>
|
<div class="mt-8 hidden" data-countdown-expired>
|
||||||
<p class="pd-display text-xl text-primary">{{ expiredMessage|default:"This has started." }}</p>
|
<p class="pd-display text-xl text-primary">{{ expiredMessage|default:"This has started." }}</p>
|
||||||
{% if expiredUrl and expiredLabel %}<a href="{{ expiredUrl }}" class="pd-tag mt-4 text-base px-5 py-3">{{ 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="pd-tag mt-4 text-base px-5 py-3">{{ expiredLabel }}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<noscript><p class="pd-body mt-6 text-muted-foreground">Counting down to <time datetime="{{ target }}">{{ target }}</time>.</p></noscript>
|
<noscript><p class="pd-body mt-6 text-muted-foreground">Counting down to <time datetime="{{ target }}">{{ target }}</time>.</p></noscript>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
{% if text %}<p class="pd-body mt-3 text-lg {% if background == "band" %}text-primary-foreground/80{% else %}text-muted-foreground{% endif %}">{{ text }}</p>{% endif %}
|
{% if text %}<p class="pd-body mt-3 text-lg {% if background == "band" %}text-primary-foreground/80{% else %}text-muted-foreground{% endif %}">{{ text }}</p>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap items-center justify-center gap-3 {% if background != "split" %}mt-8{% else %}shrink-0{% endif %}">
|
<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="pd-tag text-base px-6 py-3 {% if background == "band" %}bg-background text-foreground{% endif %}">{{ 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="pd-tag text-base px-6 py-3 {% if background == "band" %}bg-background text-foreground{% endif %}">{{ primaryLabel }}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
|
||||||
{% if secondaryUrl and secondaryLabel %}<a href="{{ secondaryUrl }}" class="pd-tag pd-tag--ghost text-base px-6 py-3 {% if background == "band" %}border-primary-foreground/40 text-primary-foreground{% endif %}">{{ secondaryLabel }}</a>{% endif %}
|
{% if secondaryUrl and secondaryLabel %}<a href="{{ secondaryUrl }}" class="pd-tag pd-tag--ghost text-base px-6 py-3 {% if background == "band" %}border-primary-foreground/40 text-primary-foreground{% endif %}">{{ secondaryLabel }}</a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<h3 class="pd-display text-lg text-primary">{{ event.title }}</h3>
|
<h3 class="pd-display text-lg text-primary">{{ event.title }}</h3>
|
||||||
{% if event.venue %}<p class="pd-body text-sm text-muted-foreground">{{ event.venue }}</p>{% endif %}
|
{% if event.venue %}<p class="pd-body text-sm text-muted-foreground">{{ event.venue }}</p>{% endif %}
|
||||||
{% if event.description %}<p class="pd-body text-sm text-muted-foreground">{{ event.description }}</p>{% endif %}
|
{% if event.description %}<p class="pd-body text-sm text-muted-foreground">{{ event.description }}</p>{% endif %}
|
||||||
{% if event.link %}<a href="{{ event.link }}" class="pd-hand mt-auto inline-flex items-center gap-1 pt-2 text-lg text-accent hover:underline">{{ 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="pd-hand mt-auto inline-flex items-center gap-1 pt-2 text-lg text-accent hover:underline">{{ event.linkLabel|default:"Details" }}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{% endif %}{% endfor %}
|
{% endif %}{% endfor %}
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<details class="group py-2"{% if variant == "open-list" %} open{% endif %}>
|
<details class="group py-2"{% if variant == "open-list" %} open{% endif %}>
|
||||||
<summary class="pd-display flex cursor-pointer list-none items-center justify-between gap-4 py-3 text-lg text-primary marker:content-none [&::-webkit-details-marker]:hidden">
|
<summary class="pd-display flex cursor-pointer list-none items-center justify-between gap-4 py-3 text-lg text-primary marker:content-none [&::-webkit-details-marker]:hidden">
|
||||||
<span>{{ item.question }}</span>
|
<span>{{ item.question }}</span>
|
||||||
<svg class="h-5 w-5 shrink-0 text-accent transition-transform duration-200 group-open:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
<svg width="20" height="20" class="h-5 w-5 shrink-0 text-accent transition-transform duration-200 group-open:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="pd-body pb-4 text-muted-foreground [&_a]:text-accent [&_a]:underline [&_a]:decoration-dashed">{{ item.answer|safe }}</div>
|
<div class="pd-body pb-4 text-muted-foreground [&_a]:text-accent [&_a]:underline [&_a]:decoration-dashed">{{ item.answer|safe }}</div>
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
@ -6,10 +6,10 @@
|
|||||||
<div class="mt-12 grid grid-cols-1 gap-8 sm:grid-cols-2 {% if columns == 2 %}lg:grid-cols-2{% elif columns == 4 %}lg:grid-cols-4{% else %}lg:grid-cols-3{% endif %}">
|
<div class="mt-12 grid grid-cols-1 gap-8 sm:grid-cols-2 {% if columns == 2 %}lg:grid-cols-2{% elif columns == 4 %}lg:grid-cols-4{% else %}lg:grid-cols-3{% endif %}">
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<div class="{% if layout == "card" %}pd-card p-6 transition-shadow hover:shadow-md{% elif layout == "centered" %}text-center{% endif %}">
|
<div class="{% if layout == "card" %}pd-card p-6 transition-shadow hover:shadow-md{% elif layout == "centered" %}text-center{% endif %}">
|
||||||
{% if item.icon %}<div class="mb-4 inline-flex h-11 w-11 items-center justify-center rounded-full bg-accent/15 text-accent{% 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 rounded-full bg-accent/15 text-accent{% if layout == "centered" %} mx-auto{% endif %}"><svg width="24" height="24" class="h-6 w-6" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg></div>{% endif %}
|
||||||
<h3 class="pd-display text-xl text-primary">{% if item.linkUrl %}<a href="{{ item.linkUrl }}" class="transition-colors hover:text-accent">{{ item.title }}</a>{% else %}{{ item.title }}{% endif %}</h3>
|
<h3 class="pd-display text-xl text-primary">{% if item.linkUrl %}<a href="{{ item.linkUrl }}" class="transition-colors hover:text-accent">{{ item.title }}</a>{% else %}{{ item.title }}{% endif %}</h3>
|
||||||
{% if item.text %}<p class="pd-body mt-2 text-muted-foreground">{{ item.text }}</p>{% endif %}
|
{% if item.text %}<p class="pd-body mt-2 text-muted-foreground">{{ item.text }}</p>{% endif %}
|
||||||
{% if item.linkUrl and item.linkLabel %}<a href="{{ item.linkUrl }}" class="pd-hand mt-3 inline-flex items-center gap-1 text-lg text-accent hover:underline">{{ 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="pd-hand mt-3 inline-flex items-center gap-1 text-lg text-accent hover:underline">{{ item.linkLabel }}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{# pastel-dream footer — scalloped top edge, soft pastel chrome, builtin footer_menus provider. #}
|
{# pastel-dream footer — scalloped top edge, soft pastel chrome, builtin footer_menus provider. #}
|
||||||
{% set fl = layout %}
|
{% set fl = layout %}
|
||||||
{% if not fl %}{% if template == "centered" %}{% set fl = "centered" %}{% else %}{% set fl = "columns" %}{% endif %}{% endif %}
|
{% if not fl %}{% if template == "centered" %}{% set fl = "centered" %}{% else %}{% set fl = "columns" %}{% endif %}{% endif %}
|
||||||
{% macro sociallinks(cls) %}{% if social_items %}<div class="flex items-center gap-3 {{ cls }}">{% for s in social_items %}<a href="{{ s.url }}" target="_blank" rel="noopener" title="{{ s.label }}" class="text-muted-foreground transition-colors hover:text-accent"><span class="sr-only">{{ s.label }}</span>{% if s.icon %}<svg class="h-5 w-5" 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 sociallinks(cls) %}{% if social_items %}<div class="flex items-center gap-3 {{ cls }}">{% for s in social_items %}<a href="{{ s.url }}" target="_blank" rel="noopener" title="{{ s.label }}" class="text-muted-foreground transition-colors hover:text-accent"><span class="sr-only">{{ s.label }}</span>{% if s.icon %}<svg width="20" height="20" class="h-5 w-5" 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="pd-hand text-2xl text-accent">{{ newsletterTitle|default:"Stay in the loop" }}</h3>{% if newsletterDescription %}<p class="pd-body mt-1 text-sm text-muted-foreground">{{ newsletterDescription }}</p>{% endif %}<div class="mt-3">{% signup_form list=newsletterListSlug|default:"main" source="footer" submit=newsletterButtonText|default:"Subscribe" %}</div></div>{% endif %}{% endmacro %}
|
{% macro newsletter() %}{% if showNewsletter %}<div class="max-w-sm"><h3 class="pd-hand text-2xl text-accent">{{ newsletterTitle|default:"Stay in the loop" }}</h3>{% if newsletterDescription %}<p class="pd-body mt-1 text-sm text-muted-foreground">{{ 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 flex flex-col items-center justify-between gap-3 border-t border-dashed border-border pt-6 text-sm text-muted-foreground sm:flex-row"><p class="pd-body">{% if copyright %}© {{ copyright }}{% else %}© {{ 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="pd-body transition-colors hover:text-foreground">{{ l.label }}</a>{% endfor %}</nav>{% endif %}</div>{% endmacro %}
|
{% macro legalbar() %}<div class="mt-10 flex flex-col items-center justify-between gap-3 border-t border-dashed border-border pt-6 text-sm text-muted-foreground sm:flex-row"><p class="pd-body">{% if copyright %}© {{ copyright }}{% else %}© {{ 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="pd-body transition-colors hover:text-foreground">{{ l.label }}</a>{% endfor %}</nav>{% endif %}</div>{% endmacro %}
|
||||||
<footer class="pd-torn-top w-full bg-muted/50 text-foreground {{ class }}">
|
<footer class="pd-torn-top w-full bg-muted/50 text-foreground {{ class }}">
|
||||||
|
|||||||
@ -18,11 +18,11 @@
|
|||||||
{% if specialHoursNote %}<p class="pd-body mt-4 rounded-md border border-dashed border-border bg-muted px-3 py-2 text-sm text-muted-foreground">{{ specialHoursNote }}</p>{% endif %}
|
{% if specialHoursNote %}<p class="pd-body mt-4 rounded-md border border-dashed border-border bg-muted px-3 py-2 text-sm text-muted-foreground">{{ specialHoursNote }}</p>{% endif %}
|
||||||
{% if address %}<div class="mt-6"><div class="pd-hand text-lg text-accent">Find us</div><address class="pd-body mt-1 whitespace-pre-line not-italic">{{ address }}</address></div>{% endif %}
|
{% if address %}<div class="mt-6"><div class="pd-hand text-lg text-accent">Find us</div><address class="pd-body mt-1 whitespace-pre-line not-italic">{{ address }}</address></div>{% endif %}
|
||||||
{% if phone %}<div class="mt-4"><div class="pd-hand text-lg text-accent">Call ahead</div><a href="tel:{{ phone }}" class="pd-body mt-1 inline-block font-medium transition-colors hover:text-accent">{{ phone }}</a></div>{% endif %}
|
{% if phone %}<div class="mt-4"><div class="pd-hand text-lg text-accent">Call ahead</div><a href="tel:{{ phone }}" class="pd-body mt-1 inline-block font-medium transition-colors hover:text-accent">{{ phone }}</a></div>{% endif %}
|
||||||
{% if directionsUrl %}<a href="{{ directionsUrl }}" target="_blank" rel="noopener" class="pd-tag mt-6 text-sm"><svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#navigation"></use></svg>Get directions</a>{% endif %}
|
{% if directionsUrl %}<a href="{{ directionsUrl }}" target="_blank" rel="noopener" class="pd-tag mt-6 text-sm"><svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#navigation"></use></svg>Get directions</a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if mapEmbedUrl %}
|
{% if mapEmbedUrl %}
|
||||||
<div class="pd-frame aspect-square w-full overflow-hidden rounded-sm bg-secondary md:aspect-auto">
|
<div class="pd-frame aspect-square w-full overflow-hidden rounded-sm bg-secondary 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="pd-body flex h-full min-h-[16rem] w-full items-center justify-center gap-2 text-sm font-medium transition-colors hover:bg-muted"><svg class="h-5 w-5 pd-pin" aria-hidden="true"><use href="/icons/lucide.svg#map-pin"></use></svg>{{ mapButtonLabel|default:"Load map" }}</button>
|
<button type="button" data-map-src="{{ mapEmbedUrl }}" onclick="var f=document.createElement('iframe');f.src=this.getAttribute('data-map-src');f.setAttribute('class','h-full w-full border-0');f.setAttribute('loading','lazy');f.setAttribute('referrerpolicy','no-referrer-when-downgrade');f.setAttribute('title','Map');this.parentNode.replaceChild(f,this);" class="pd-body flex h-full min-h-[16rem] w-full items-center justify-center gap-2 text-sm font-medium transition-colors hover:bg-muted"><svg width="20" height="20" class="h-5 w-5 pd-pin" aria-hidden="true"><use href="/icons/lucide.svg#map-pin"></use></svg>{{ mapButtonLabel|default:"Load map" }}</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
{% set cta_text = cta.text|default:ctaLabel %}
|
{% set cta_text = cta.text|default:ctaLabel %}
|
||||||
{% set cta_url = cta.url|default:ctaUrl %}
|
{% set cta_url = cta.url|default:ctaUrl %}
|
||||||
{% 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="pd-body px-3 py-2 text-sm font-medium text-foreground/80 transition-colors hover:text-accent {{ item.css_class }}">{{ item.label }}</a>{% endmacro %}
|
{% macro navlink(item) %}<a href="{{ item.url|default:'#' }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %}{% if item.title %} title="{{ item.title }}"{% endif %} class="pd-body px-3 py-2 text-sm font-medium text-foreground/80 transition-colors hover:text-accent {{ item.css_class }}">{{ item.label }}</a>{% endmacro %}
|
||||||
{% macro dropdown(item) %}<div class="relative group"><button type="button" class="pd-body inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-foreground/80 transition-colors hover:text-accent">{{ item.label }}<svg class="h-4 w-4 transition-transform group-hover:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></button><div class="absolute left-0 z-50 mt-1 w-56 invisible opacity-0 transition-all duration-200 group-hover:visible group-hover:opacity-100"><div class="pd-card py-2 shadow-lg">{% for child in item.children %}{% if child.item_type == "header" %}<div class="pd-hand px-4 py-2 text-base text-accent">{{ child.label }}</div>{% else %}<a href="{{ child.url|default:'#' }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="pd-body block px-4 py-2 text-sm text-foreground transition-colors hover:bg-muted {{ child.css_class }}">{{ child.label }}</a>{% endif %}{% endfor %}</div></div></div>{% endmacro %}
|
{% macro dropdown(item) %}<div class="relative group"><button type="button" class="pd-body inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-foreground/80 transition-colors hover:text-accent">{{ item.label }}<svg width="16" height="16" class="h-4 w-4 transition-transform group-hover:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></button><div class="absolute left-0 z-50 mt-1 w-56 invisible opacity-0 transition-all duration-200 group-hover:visible group-hover:opacity-100"><div class="pd-card py-2 shadow-lg">{% for child in item.children %}{% if child.item_type == "header" %}<div class="pd-hand px-4 py-2 text-base text-accent">{{ child.label }}</div>{% else %}<a href="{{ child.url|default:'#' }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="pd-body block px-4 py-2 text-sm text-foreground transition-colors hover:bg-muted {{ child.css_class }}">{{ child.label }}</a>{% endif %}{% endfor %}</div></div></div>{% endmacro %}
|
||||||
{% macro brand(size) %}<a href="/" class="flex flex-shrink-0 items-center gap-2">{% if logoType == "text" and logoText.text %}<span class="pd-display text-2xl text-primary {{ logoText.color }}">{{ 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="pd-display text-2xl text-primary">{{ companyName }}</span>{% endif %}</a>{% endmacro %}
|
{% macro brand(size) %}<a href="/" class="flex flex-shrink-0 items-center gap-2">{% if logoType == "text" and logoText.text %}<span class="pd-display text-2xl text-primary {{ logoText.color }}">{{ 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="pd-display text-2xl text-primary">{{ companyName }}</span>{% endif %}</a>{% endmacro %}
|
||||||
{% macro ctabtn(extra) %}{% if cta_text %}<a href="{{ cta_url|default:'#' }}" class="pd-tag text-sm {{ extra }}">{{ cta_text }}</a>{% endif %}{% endmacro %}
|
{% macro ctabtn(extra) %}{% if cta_text %}<a href="{{ cta_url|default:'#' }}" class="pd-tag text-sm {{ extra }}">{{ cta_text }}</a>{% endif %}{% endmacro %}
|
||||||
<nav data-bn-navbar data-bn-sticky="{{ sb }}" class="bn-navbar w-full {% if sb == "sticky" or sb == "shrink-on-scroll" %}sticky top-0 z-40 {% endif %}bg-background/95 backdrop-blur border-b border-dashed border-border {{ class }}">
|
<nav data-bn-navbar data-bn-sticky="{{ sb }}" class="bn-navbar w-full {% if sb == "sticky" or sb == "shrink-on-scroll" %}sticky top-0 z-40 {% endif %}bg-background/95 backdrop-blur border-b border-dashed border-border {{ class }}">
|
||||||
@ -30,7 +30,7 @@
|
|||||||
<label for="bn-navbar-toggle" class="bn-navbar-overlay fixed inset-0 z-40 bg-black/50 md:hidden" aria-hidden="true"></label>
|
<label for="bn-navbar-toggle" class="bn-navbar-overlay fixed inset-0 z-40 bg-black/50 md:hidden" aria-hidden="true"></label>
|
||||||
<div id="bn-navbar-drawer" class="bn-navbar-drawer fixed right-0 top-0 z-50 flex h-full w-80 max-w-[85vw] flex-col bg-background text-foreground shadow-xl md:hidden" role="dialog" aria-modal="true" aria-label="Site menu">
|
<div id="bn-navbar-drawer" class="bn-navbar-drawer fixed right-0 top-0 z-50 flex h-full w-80 max-w-[85vw] flex-col bg-background text-foreground shadow-xl md:hidden" role="dialog" aria-modal="true" aria-label="Site menu">
|
||||||
<div class="flex items-center justify-between border-b border-dashed border-border p-4">{{ brand("h-8") }}<label for="bn-navbar-toggle" data-bn-nav-close class="cursor-pointer rounded-md p-2 text-muted-foreground hover:bg-muted hover:text-foreground"><span class="sr-only">Close menu</span><svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg></label></div>
|
<div class="flex items-center justify-between border-b border-dashed border-border p-4">{{ brand("h-8") }}<label for="bn-navbar-toggle" data-bn-nav-close class="cursor-pointer rounded-md p-2 text-muted-foreground hover:bg-muted hover:text-foreground"><span class="sr-only">Close menu</span><svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg></label></div>
|
||||||
<nav class="flex-1 overflow-y-auto py-4" aria-label="Mobile">{% for item in menu.items %}{% if item.children %}<details class="group/acc"><summary class="pd-body flex cursor-pointer list-none items-center justify-between px-6 py-3 text-base font-medium transition-colors hover:bg-muted">{{ item.label }}<svg class="h-4 w-4 transition-transform group-open/acc:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></summary><div class="pb-2 pl-8">{% for child in item.children %}{% if child.item_type != "header" %}<a href="{{ child.url|default:'#' }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="pd-body block px-2 py-2 text-sm text-muted-foreground transition-colors hover:text-foreground">{{ child.label }}</a>{% endif %}{% endfor %}</div></details>{% else %}<a href="{{ item.url|default:'#' }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="pd-body block px-6 py-3 text-base font-medium transition-colors hover:bg-muted">{{ item.label }}</a>{% endif %}{% endfor %}</nav>
|
<nav class="flex-1 overflow-y-auto py-4" aria-label="Mobile">{% for item in menu.items %}{% if item.children %}<details class="group/acc"><summary class="pd-body flex cursor-pointer list-none items-center justify-between px-6 py-3 text-base font-medium transition-colors hover:bg-muted">{{ item.label }}<svg width="16" height="16" class="h-4 w-4 transition-transform group-open/acc:rotate-180" aria-hidden="true"><use href="/icons/lucide.svg#chevron-down"></use></svg></summary><div class="pb-2 pl-8">{% for child in item.children %}{% if child.item_type != "header" %}<a href="{{ child.url|default:'#' }}"{% if child.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="pd-body block px-2 py-2 text-sm text-muted-foreground transition-colors hover:text-foreground">{{ child.label }}</a>{% endif %}{% endfor %}</div></details>{% else %}<a href="{{ item.url|default:'#' }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %} class="pd-body block px-6 py-3 text-base font-medium transition-colors hover:bg-muted">{{ item.label }}</a>{% endif %}{% endfor %}</nav>
|
||||||
{% if cta_text %}<div class="border-t border-dashed border-border p-4"><a href="{{ cta_url|default:'#' }}" class="pd-tag w-full justify-center">{{ cta_text }}</a></div>{% endif %}
|
{% if cta_text %}<div class="border-t border-dashed border-border p-4"><a href="{{ cta_url|default:'#' }}" class="pd-tag w-full justify-center">{{ cta_text }}</a></div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@ -15,6 +15,6 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<p class="pd-body mx-auto mt-4 max-w-xl text-muted-foreground">{{ emptyMessage|default:"That page has wandered off. Head back to the counter and start again." }}</p>
|
<p class="pd-body mx-auto mt-4 max-w-xl text-muted-foreground">{{ emptyMessage|default:"That page has wandered off. Head back to the counter and start again." }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="/" class="pd-tag mt-8"><svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#home"></use></svg>Back home</a>
|
<a href="/" class="pd-tag mt-8"><svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#home"></use></svg>Back home</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
</p>
|
</p>
|
||||||
{% if tier.description %}<p class="pd-body mt-3 text-sm text-muted-foreground">{{ tier.description }}</p>{% endif %}
|
{% if tier.description %}<p class="pd-body mt-3 text-sm text-muted-foreground">{{ tier.description }}</p>{% endif %}
|
||||||
{% if tier.features %}<ul class="mt-6 flex-1 space-y-3 text-sm">
|
{% if tier.features %}<ul class="mt-6 flex-1 space-y-3 text-sm">
|
||||||
{% for feature in tier.features %}<li class="pd-body flex items-start gap-2"><svg class="mt-0.5 h-4 w-4 shrink-0 text-accent" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg><span>{{ feature }}</span></li>{% endfor %}
|
{% for feature in tier.features %}<li class="pd-body flex items-start gap-2"><svg width="16" height="16" class="mt-0.5 h-4 w-4 shrink-0 text-accent" aria-hidden="true"><use href="/icons/lucide.svg#check"></use></svg><span>{{ feature }}</span></li>{% endfor %}
|
||||||
</ul>{% endif %}
|
</ul>{% endif %}
|
||||||
{% if tier.ctaUrl and tier.ctaLabel %}<a href="{{ tier.ctaUrl }}" class="pd-tag mt-8 w-full justify-center {% if not tier.highlighted %}pd-tag--ghost{% endif %}">{{ tier.ctaLabel }}</a>{% endif %}
|
{% if tier.ctaUrl and tier.ctaLabel %}<a href="{{ tier.ctaUrl }}" class="pd-tag mt-8 w-full justify-center {% if not tier.highlighted %}pd-tag--ghost{% endif %}">{{ tier.ctaLabel }}</a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% if eyebrow %}<p class="pd-hand text-2xl text-accent">{{ eyebrow }}</p>{% endif %}
|
{% if eyebrow %}<p class="pd-hand text-2xl text-accent">{{ eyebrow }}</p>{% endif %}
|
||||||
{% if heading %}<h2 class="pd-display mt-1 text-3xl text-primary md:text-4xl"><span class="pd-doodle-underline">{{ heading }}</span></h2>{% endif %}
|
{% if heading %}<h2 class="pd-display mt-1 text-3xl text-primary md:text-4xl"><span class="pd-doodle-underline">{{ heading }}</span></h2>{% endif %}
|
||||||
{% if body %}<div class="pd-body mt-4 space-y-4 text-lg text-muted-foreground [&_a]:text-accent [&_a]:underline [&_a]:decoration-dashed [&_strong]:text-primary">{{ body|safe }}</div>{% endif %}
|
{% if body %}<div class="pd-body mt-4 space-y-4 text-lg text-muted-foreground [&_a]:text-accent [&_a]:underline [&_a]:decoration-dashed [&_strong]:text-primary">{{ body|safe }}</div>{% endif %}
|
||||||
{% if ctaUrl and ctaLabel %}<a href="{{ ctaUrl }}" class="pd-tag mt-6 text-base px-5 py-3">{{ 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="pd-tag mt-6 text-base px-5 py-3">{{ ctaLabel }}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#arrow-right"></use></svg></a>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="{% if mediaPosition == "left" %}md:order-1{% else %}md:order-2{% endif %}">
|
<div class="{% if mediaPosition == "left" %}md:order-1{% else %}md:order-2{% endif %}">
|
||||||
{% if media %}<div class="pd-frame pd-torn-bottom overflow-hidden rounded-sm p-2">{% img media alt=mediaAlt class="h-auto w-full rounded-sm object-cover" %}</div>{% endif %}
|
{% if media %}<div class="pd-frame pd-torn-bottom overflow-hidden rounded-sm p-2">{% img media alt=mediaAlt class="h-auto w-full rounded-sm object-cover" %}</div>{% endif %}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
{% if title %}<h3 class="pd-hand {% if compact %}px-2 mb-3 text-lg{% else %}px-3 mb-4 text-xl{% endif %} text-accent">{{ title }}</h3>{% endif %}
|
{% if title %}<h3 class="pd-hand {% if compact %}px-2 mb-3 text-lg{% else %}px-3 mb-4 text-xl{% endif %} text-accent">{{ title }}</h3>{% endif %}
|
||||||
<ul class="{% if compact %}space-y-0.5{% else %}space-y-1{% endif %}">
|
<ul class="{% if compact %}space-y-0.5{% else %}space-y-1{% endif %}">
|
||||||
{% for item in menu.items %}
|
{% for item in menu.items %}
|
||||||
<li><a href="{{ item.url|default:'#' }}"{% if item.open_in_new_tab %} target="_blank" rel="noopener"{% endif %}{% if item.title %} title="{{ item.title }}"{% endif %} data-bn-sidebar-link class="pd-body flex items-center rounded-md text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground {% 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" 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="pd-body flex items-center rounded-md text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground {% if compact %}px-2 py-1.5{% else %}px-3 py-2{% endif %} {{ item.css_class }}">{% if item.icon %}<svg width="16" height="16" class="mr-2 h-4 w-4" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg>{% endif %}{{ item.label }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% for link in links %}{% if link.url %}
|
{% for link in links %}{% if link.url %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ link.url }}" target="_blank" rel="noopener" aria-label="{{ link.label|default:link.network }}" class="inline-flex items-center gap-2 rounded-full border border-dashed border-border text-foreground transition-colors hover:border-accent hover:text-accent {% if style == "stack" %}w-full px-4 py-2{% else %}p-2.5{% endif %}">
|
<a href="{{ link.url }}" target="_blank" rel="noopener" aria-label="{{ link.label|default:link.network }}" class="inline-flex items-center gap-2 rounded-full border border-dashed border-border text-foreground transition-colors hover:border-accent hover:text-accent {% if style == "stack" %}w-full px-4 py-2{% else %}p-2.5{% endif %}">
|
||||||
{% if link.network %}<svg class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ link.network|split:":"|first }}.svg#{{ link.network|split:":"|last }}"></use></svg>{% endif %}
|
{% if link.network %}<svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ link.network|split:":"|first }}.svg#{{ link.network|split:":"|last }}"></use></svg>{% endif %}
|
||||||
{% if style == "stack" and link.label %}<span class="pd-body text-sm font-medium">{{ link.label }}</span>{% endif %}
|
{% if style == "stack" and link.label %}<span class="pd-body text-sm font-medium">{{ link.label }}</span>{% endif %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
{% if member.role %}<p class="pd-hand text-lg text-accent">{{ member.role }}</p>{% endif %}
|
{% if member.role %}<p class="pd-hand text-lg text-accent">{{ member.role }}</p>{% endif %}
|
||||||
{% if member.bio %}<p class="pd-body mt-2 text-sm text-muted-foreground">{{ member.bio }}</p>{% endif %}
|
{% if member.bio %}<p class="pd-body mt-2 text-sm text-muted-foreground">{{ member.bio }}</p>{% endif %}
|
||||||
{% if member.socials %}<div class="mt-3 flex gap-3 {% if layout != "list" %}justify-center{% endif %}">
|
{% if member.socials %}<div class="mt-3 flex gap-3 {% if layout != "list" %}justify-center{% endif %}">
|
||||||
{% for social in member.socials %}{% if social.url %}<a href="{{ social.url }}" class="text-muted-foreground transition-colors hover:text-accent" aria-label="Social link"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ social.icon|split:":"|first }}.svg#{{ social.icon|split:":"|last }}"></use></svg></a>{% endif %}{% endfor %}
|
{% for social in member.socials %}{% if social.url %}<a href="{{ social.url }}" class="text-muted-foreground transition-colors hover:text-accent" aria-label="Social link"><svg width="20" height="20" class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ social.icon|split:":"|first }}.svg#{{ social.icon|split:":"|last }}"></use></svg></a>{% endif %}{% endfor %}
|
||||||
</div>{% endif %}
|
</div>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -5,11 +5,11 @@
|
|||||||
{% for q in quotes %}
|
{% for q in quotes %}
|
||||||
<figure class="pd-card flex flex-col p-6{% if layout == "carousel" %} min-w-[18rem] max-w-sm shrink-0 snap-start{% endif %}">
|
<figure class="pd-card flex flex-col p-6{% if layout == "carousel" %} min-w-[18rem] max-w-sm shrink-0 snap-start{% endif %}">
|
||||||
{% if q.rating %}<div class="mb-3 flex gap-0.5" aria-label="Rated {{ q.rating }} out of 5">
|
{% if q.rating %}<div class="mb-3 flex gap-0.5" aria-label="Rated {{ q.rating }} out of 5">
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 1 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 1 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 2 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 2 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 3 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 3 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 4 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 4 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
<svg class="h-4 w-4 {% if q.rating >= 5 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
<svg width="16" height="16" class="h-4 w-4 {% if q.rating >= 5 %}text-accent{% else %}text-muted-foreground/30{% endif %}" aria-hidden="true"><use href="/icons/lucide.svg#star"></use></svg>
|
||||||
</div>{% endif %}
|
</div>{% endif %}
|
||||||
<blockquote class="pd-body flex-1 text-lg leading-relaxed text-foreground">{% if q.quote %}“{{ q.quote }}”{% endif %}</blockquote>
|
<blockquote class="pd-body flex-1 text-lg leading-relaxed text-foreground">{% if q.quote %}“{{ q.quote }}”{% endif %}</blockquote>
|
||||||
<figcaption class="mt-5 flex items-center gap-3">
|
<figcaption class="mt-5 flex items-center gap-3">
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
{% for step in steps %}
|
{% for step in steps %}
|
||||||
<li class="{% if orientation == "horizontal" %}text-center{% else %}relative pl-14{% endif %}">
|
<li class="{% if orientation == "horizontal" %}text-center{% else %}relative pl-14{% endif %}">
|
||||||
<span class="pd-stamp pd-stamp-sm {% if orientation == "horizontal" %}mx-auto{% else %}absolute left-0 top-0 ring-4 ring-background{% endif %}">
|
<span class="pd-stamp pd-stamp-sm {% 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 rounded-full bg-accent-foreground"></span>{% else %}<svg class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#croissant"></use></svg>{% endif %}
|
{% if marker == "numbered" %}{{ forloop.counter }}{% elif marker == "dot" %}<span class="h-2 w-2 rounded-full bg-accent-foreground"></span>{% else %}<svg width="16" height="16" class="h-4 w-4" aria-hidden="true"><use href="/icons/lucide.svg#croissant"></use></svg>{% endif %}
|
||||||
</span>
|
</span>
|
||||||
<div class="{% if orientation == "horizontal" %}mt-4{% else %}pt-1{% endif %}">
|
<div class="{% if orientation == "horizontal" %}mt-4{% else %}pt-1{% endif %}">
|
||||||
{% if step.label %}<p class="pd-hand text-lg text-accent">{{ step.label }}</p>{% endif %}
|
{% if step.label %}<p class="pd-hand text-lg text-accent">{{ step.label }}</p>{% endif %}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{# pastel-dream utility-bar — thin contact strip; left/right item lists {icon,label,link}. #}
|
{# pastel-dream utility-bar — thin contact strip; left/right item lists {icon,label,link}. #}
|
||||||
{% set ubcls = "bg-muted text-muted-foreground border-b border-dashed border-border" %}
|
{% set ubcls = "bg-muted text-muted-foreground border-b border-dashed border-border" %}
|
||||||
{% if variant == "primary" %}{% set ubcls = "bg-primary text-primary-foreground" %}{% elif variant == "dark" %}{% set ubcls = "bg-foreground text-background" %}{% endif %}
|
{% 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="inline-flex items-center gap-1.5 transition-opacity hover:opacity-80">{% if it.icon %}<svg class="h-3.5 w-3.5" 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="inline-flex items-center gap-1.5">{% if it.icon %}<svg class="h-3.5 w-3.5" 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 %}
|
{% macro ubitem(it) %}{% if it.link %}<a href="{{ it.link }}" class="inline-flex items-center gap-1.5 transition-opacity hover:opacity-80">{% if it.icon %}<svg width="12" height="12" class="h-3.5 w-3.5" 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="inline-flex items-center gap-1.5">{% if it.icon %}<svg width="12" height="12" class="h-3.5 w-3.5" 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 class="pd-body w-full text-xs {% if not showOnMobile %}hidden sm:block{% endif %} {{ ubcls }} {{ class }}">
|
<div class="pd-body w-full text-xs {% if not showOnMobile %}hidden sm:block{% endif %} {{ ubcls }} {{ class }}">
|
||||||
<div class="mx-auto flex h-9 max-w-7xl items-center justify-between gap-4 px-4 sm:px-6 lg:px-8">
|
<div class="mx-auto flex h-9 max-w-7xl items-center justify-between gap-4 px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex flex-wrap items-center gap-4">{% for it in leftItems %}{{ ubitem(it) }}{% endfor %}</div>
|
<div class="flex flex-wrap items-center gap-4">{% for it in leftItems %}{{ ubitem(it) }}{% endfor %}</div>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
{% with aspect=aspect|default:"16:9" %}<figure class="bn-video my-8{% if class %} {{ class }}{% endif %}"><div class="bn-video-frame pd-frame relative w-full overflow-hidden rounded-sm bg-secondary p-1.5 {% 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 rounded-sm object-cover" %}{% endif %}<span class="absolute inset-0 bg-foreground/10 transition-colors group-hover:bg-foreground/20" aria-hidden="true"></span><span class="relative inline-flex h-16 w-16 items-center justify-center rounded-full bg-accent text-accent-foreground shadow-lg transition-transform group-hover:scale-105 motion-reduce:transform-none"><svg class="h-7 w-7" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg></span></button></div>{% if caption %}<figcaption class="pd-hand mt-3 text-center text-xl text-accent">{{ caption }}</figcaption>{% endif %}</figure><script>
|
{% with aspect=aspect|default:"16:9" %}<figure class="bn-video my-8{% if class %} {{ class }}{% endif %}"><div class="bn-video-frame pd-frame relative w-full overflow-hidden rounded-sm bg-secondary p-1.5 {% 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 rounded-sm object-cover" %}{% endif %}<span class="absolute inset-0 bg-foreground/10 transition-colors group-hover:bg-foreground/20" aria-hidden="true"></span><span class="relative inline-flex h-16 w-16 items-center justify-center rounded-full bg-accent text-accent-foreground shadow-lg transition-transform group-hover:scale-105 motion-reduce:transform-none"><svg width="28" height="28" class="h-7 w-7" aria-hidden="true"><use href="/icons/lucide.svg#play"></use></svg></span></button></div>{% if caption %}<figcaption class="pd-hand mt-3 text-center text-xl text-accent">{{ caption }}</figcaption>{% endif %}</figure><script>
|
||||||
(function(){
|
(function(){
|
||||||
if(window.__bnVideoFacade)return;window.__bnVideoFacade=true;
|
if(window.__bnVideoFacade)return;window.__bnVideoFacade=true;
|
||||||
function yt(u){var m=u.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([\w-]{6,})/);return m?m[1]:null;}
|
function yt(u){var m=u.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([\w-]{6,})/);return m?m[1]:null;}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user