fix(pastel-dream): reliable layout via theme CSS + graceful empty media
Host Tailwind (v4, source(none)) does not scan installed .bnp theme templates, so grid/aspect/gap/padding utilities used only in this theme were silently dropped: custom persona blocks collapsed to a single full-width column, media boxes rendered as thin strips, and p-5 loss clipped the first glyph of every description. Move the theme's layout primitives into css.input_css_append as plain CSS with explicit media queries (mobile-first, collapse to 1 column) so the render no longer depends on the JIT content scan. - Add .pd-section / .pd-grid(--2/--3/--lg-2/--lg-4) / .pd-menu-cols / .pd-menu-list / .pd-media(--square) / .pd-card-body helpers to both manifest.yaml (served) and assets/style.css. Semantic tokens only. - seasonal_specials + cake_gallery: reliable responsive grid, OMIT the media box when no image is set (no ballooning empty boxes / thin strips), real body padding. - menu-list: honor columns=2 as a true two-up board; reliable item spacing. - hours-location / feature-grid: reliable responsive grids. - Tighten section rhythm (py-14/py-24 -> .pd-section) to remove dead bands. - navbar drawer width pinned in its inline <style>; body overflow-x: clip guards against horizontal scroll on small screens. No .reveal/scroll-reveal content-hiding in this theme (stats count-up only, values render by default). No version bump. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
8eaf3a68aa
commit
e6348edd10
@ -32,6 +32,10 @@ body.pd-paper {
|
||||
radial-gradient(50% 50% at 25% 90%, hsl(var(--primary) / 0.08) 0%, transparent 60%);
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
/* Guard against horizontal scroll on small screens from any off-canvas
|
||||
* chrome (mobile drawer). `clip` does not create a scroll container, so
|
||||
* it will not break the sticky navbar the way `hidden` can. */
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
/* --- Type roles --------------------------------------------------------- */
|
||||
@ -247,3 +251,43 @@ body.pd-paper {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Layout helpers (theme-owned, semantic tokens only) -----------------
|
||||
* Installed .bnp themes live outside the host Tailwind @source globs, so the
|
||||
* host build does NOT compile grid / aspect-ratio / gap / padding utilities
|
||||
* that appear only in this theme's own templates. The theme therefore owns
|
||||
* those layout primitives here as plain CSS: mobile-first, collapsing to a
|
||||
* single column on small screens, with explicit media queries so the render
|
||||
* is reliable regardless of the JIT content scan. No colors — layout only. */
|
||||
.pd-section { padding-top: 2.75rem; padding-bottom: 2.75rem; }
|
||||
@media (min-width: 768px) {
|
||||
.pd-section { padding-top: 4rem; padding-bottom: 4rem; }
|
||||
}
|
||||
|
||||
.pd-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem; }
|
||||
@media (min-width: 640px) {
|
||||
.pd-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.pd-grid--lg-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.pd-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
.pd-grid--lg-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||
}
|
||||
|
||||
/* Two-up menu board: one column on phones, two side by side from md. */
|
||||
.pd-menu-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.5rem 3rem; }
|
||||
@media (min-width: 768px) {
|
||||
.pd-menu-cols--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
.pd-menu-list { margin-top: 1rem; }
|
||||
.pd-menu-list > li + li { margin-top: 1.25rem; }
|
||||
|
||||
/* Media frames: a fixed aspect box so a photo fills gracefully. The EMPTY
|
||||
* state is omitted in-template (no ballooning boxes when no photo is set). */
|
||||
.pd-media { position: relative; width: 100%; overflow: hidden; aspect-ratio: 4 / 3; }
|
||||
.pd-media--square { aspect-ratio: 1 / 1; }
|
||||
.pd-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
||||
|
||||
/* Card body padding (host may not emit p-5 for theme templates). */
|
||||
.pd-card-body { padding: 1.25rem 1.25rem 1.5rem; }
|
||||
@media (min-width: 768px) { .pd-card-body { padding: 1.5rem; } }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<section data-block="pastel-dream:bakers_note" class="py-14 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<section data-block="pastel-dream:bakers_note" class="pd-section bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<div class="mx-auto max-w-3xl px-4">
|
||||
<div class="pd-card relative overflow-hidden p-8 text-center md:p-12">
|
||||
<div class="pointer-events-none absolute -right-16 -top-16 h-48 w-48 rounded-full bg-accent/15 pd-breathe" aria-hidden="true"></div>
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
<section data-block="pastel-dream:cake_gallery" class="py-14 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<section data-block="pastel-dream:cake_gallery" class="pd-section bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<div class="mx-auto max-w-6xl px-4">
|
||||
<div class="text-center">
|
||||
{% if heading %}<h2 class="pd-display text-3xl text-primary md:text-4xl"><span class="pd-doodle-underline">{{ heading }}</span></h2>{% endif %}
|
||||
{% if intro %}<p class="pd-body mx-auto mt-3 max-w-2xl text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
||||
</div>
|
||||
{% if cakes %}
|
||||
<div class="mt-10 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div class="mt-10 pd-grid pd-grid--2 pd-grid--3">
|
||||
{% for cake in cakes %}
|
||||
<figure class="pd-frame overflow-hidden">
|
||||
<div class="pd-torn-bottom aspect-square w-full overflow-hidden bg-secondary">
|
||||
{% if cake.image %}{% img cake.image alt=cake.name|default:"Cake" class="h-full w-full object-cover" %}{% else %}<div class="flex h-full w-full items-center justify-center pd-hand text-xl text-muted-foreground">Add a photo</div>{% endif %}
|
||||
</div>
|
||||
<figcaption class="p-5">
|
||||
<figure class="pd-frame overflow-hidden flex flex-col">
|
||||
{% if cake.image %}<div class="pd-media pd-media--square pd-torn-bottom bg-secondary">{% img cake.image alt=cake.name|default:"Cake" class="h-full w-full object-cover" %}</div>{% endif %}
|
||||
<figcaption class="pd-card-body">
|
||||
<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 %}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<section data-block="pastel-dream:order_ribbon" class="py-14 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<section data-block="pastel-dream:order_ribbon" class="pd-section bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<div class="mx-auto max-w-5xl px-4">
|
||||
<div class="pd-chalkboard relative overflow-hidden p-8 md:p-12">
|
||||
<div class="relative flex flex-col items-start gap-6 md:flex-row md:items-center md:justify-between">
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<section data-block="pastel-dream:seasonal_specials" class="py-14 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<section data-block="pastel-dream:seasonal_specials" class="pd-section bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<div class="mx-auto max-w-6xl px-4">
|
||||
<div class="max-w-2xl">
|
||||
{% if kicker %}<p class="pd-hand text-xl text-accent">{{ kicker }}</p>{% endif %}
|
||||
@ -6,13 +6,11 @@
|
||||
{% if intro %}<p class="pd-body mt-3 text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
||||
</div>
|
||||
{% if items %}
|
||||
<div class="mt-10 grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<div class="mt-10 pd-grid pd-grid--2 pd-grid--3">
|
||||
{% for item in items %}
|
||||
<article class="pd-card overflow-hidden">
|
||||
<div class="aspect-[4/3] w-full overflow-hidden bg-secondary">
|
||||
{% if item.image %}{% img item.image alt=item.name|default:"Seasonal special" class="h-full w-full object-cover" %}{% else %}<div class="flex h-full w-full items-center justify-center pd-hand text-xl text-muted-foreground">Add a photo</div>{% endif %}
|
||||
</div>
|
||||
<div class="p-5">
|
||||
<article class="pd-card overflow-hidden flex flex-col">
|
||||
{% if item.image %}<div class="pd-media bg-secondary">{% img item.image alt=item.name|default:"Seasonal special" class="h-full w-full object-cover" %}</div>{% endif %}
|
||||
<div class="pd-card-body">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<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 %}
|
||||
|
||||
@ -141,6 +141,10 @@ css:
|
||||
radial-gradient(50% 50% at 25% 90%, hsl(var(--primary) / 0.08) 0%, transparent 60%);
|
||||
background-attachment: fixed;
|
||||
background-repeat: no-repeat;
|
||||
/* Guard against horizontal scroll on small screens from any off-canvas
|
||||
* chrome (mobile drawer). `clip` does not create a scroll container, so
|
||||
* it will not break the sticky navbar the way `hidden` can. */
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
/* --- Type roles --------------------------------------------------------- */
|
||||
@ -356,3 +360,43 @@ css:
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Layout helpers (theme-owned, semantic tokens only) -----------------
|
||||
* Installed .bnp themes live outside the host Tailwind @source globs, so the
|
||||
* host build does NOT compile grid / aspect-ratio / gap / padding utilities
|
||||
* that appear only in this theme's own templates. The theme therefore owns
|
||||
* those layout primitives here as plain CSS: mobile-first, collapsing to a
|
||||
* single column on small screens, with explicit media queries so the render
|
||||
* is reliable regardless of the JIT content scan. No colors — layout only. */
|
||||
.pd-section { padding-top: 2.75rem; padding-bottom: 2.75rem; }
|
||||
@media (min-width: 768px) {
|
||||
.pd-section { padding-top: 4rem; padding-bottom: 4rem; }
|
||||
}
|
||||
|
||||
.pd-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem; }
|
||||
@media (min-width: 640px) {
|
||||
.pd-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.pd-grid--lg-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.pd-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
.pd-grid--lg-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||
}
|
||||
|
||||
/* Two-up menu board: one column on phones, two side by side from md. */
|
||||
.pd-menu-cols { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.5rem 3rem; }
|
||||
@media (min-width: 768px) {
|
||||
.pd-menu-cols--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
.pd-menu-list { margin-top: 1rem; }
|
||||
.pd-menu-list > li + li { margin-top: 1.25rem; }
|
||||
|
||||
/* Media frames: a fixed aspect box so a photo fills gracefully. The EMPTY
|
||||
* state is omitted in-template (no ballooning boxes when no photo is set). */
|
||||
.pd-media { position: relative; width: 100%; overflow: hidden; aspect-ratio: 4 / 3; }
|
||||
.pd-media--square { aspect-ratio: 1 / 1; }
|
||||
.pd-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
|
||||
|
||||
/* Card body padding (host may not emit p-5 for theme templates). */
|
||||
.pd-card-body { padding: 1.25rem 1.25rem 1.5rem; }
|
||||
@media (min-width: 768px) { .pd-card-body { padding: 1.5rem; } }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<section class="pd-section bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<div class="mx-auto max-w-6xl px-4">
|
||||
<div class="{% if background == "band" %}pd-torn-top pd-torn-bottom rounded-2xl bg-primary px-6 py-14 text-center text-primary-foreground md:px-12{% elif background == "card" %}pd-card px-6 py-14 text-center md:px-12{% else %}flex flex-col items-center gap-8 rounded-2xl bg-muted px-6 py-12 text-foreground md:flex-row md:justify-between md:px-12 md:text-left{% endif %}">
|
||||
<div class="{% if background != "split" %}mx-auto max-w-2xl{% endif %}">
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
{% if eyebrow %}<p class="pd-hand text-center text-2xl text-accent">{{ eyebrow }}</p>{% endif %}
|
||||
{% if heading %}<h2 class="pd-display mt-1 text-center text-3xl text-primary md:text-4xl"><span class="pd-doodle-underline">{{ heading }}</span></h2>{% endif %}
|
||||
{% if intro %}<p class="pd-body mx-auto mt-4 max-w-2xl text-center text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
||||
<div class="mt-12 grid grid-cols-1 gap-6 sm:grid-cols-2 {% if columns == 2 %}lg:grid-cols-2{% elif columns == 4 %}lg:grid-cols-4{% else %}lg:grid-cols-3{% endif %}">
|
||||
<div class="mt-12 pd-grid pd-grid--2 {% if columns == 2 %}pd-grid--lg-2{% elif columns == 4 %}pd-grid--lg-4{% else %}pd-grid--3{% endif %}">
|
||||
{% for item in items %}
|
||||
<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 %}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<section class="pd-section bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<div class="mx-auto max-w-5xl px-4">
|
||||
{% if heading %}<h2 class="pd-display text-3xl text-primary md:text-4xl"><span class="pd-doodle-underline">{{ heading }}</span></h2>{% endif %}
|
||||
<div class="mt-10 grid grid-cols-1 gap-10 md:grid-cols-2">
|
||||
<div class="mt-10 pd-grid pd-grid--2">
|
||||
<div>
|
||||
{% if hours %}
|
||||
<table class="pd-body w-full text-sm" data-pd-hours>
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
<section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<section class="pd-section bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||
<div class="mx-auto max-w-5xl px-4">
|
||||
{% if heading %}<h2 class="pd-display text-3xl text-primary md:text-4xl"><span class="pd-doodle-underline">{{ heading }}</span></h2>{% endif %}
|
||||
{% if intro %}<p class="pd-body mt-3 max-w-2xl text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
||||
<div class="pd-chalkboard mt-10 p-6 md:p-10">
|
||||
<div class="grid grid-cols-1 gap-x-12 gap-y-10 {% if columns == 2 %}md:grid-cols-2{% endif %}">
|
||||
<div class="pd-menu-cols {% if columns == 2 %}pd-menu-cols--2{% endif %}">
|
||||
{% for section in sections %}
|
||||
<div class="menu-section">
|
||||
{% if section.title %}<h3 class="pd-hand border-b pd-chalk-rule pb-2 text-3xl">{{ section.title }}</h3>{% endif %}
|
||||
{% if section.note %}<p class="pd-body pd-chalk-muted mt-2 text-sm">{{ section.note }}</p>{% endif %}
|
||||
<ul class="mt-4 space-y-5">
|
||||
<ul class="pd-menu-list">
|
||||
{% for item in section.items %}
|
||||
<li class="flex items-baseline gap-4">
|
||||
<div class="min-w-0 flex-1">
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
</div>
|
||||
<style>
|
||||
.bn-navbar-toggle{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;}
|
||||
.bn-navbar-drawer{transform:translateX(100%);transition:transform .3s ease;}
|
||||
.bn-navbar-drawer{width:20rem;max-width:85vw;transform:translateX(100%);transition:transform .3s ease;}
|
||||
.bn-navbar-overlay{opacity:0;pointer-events:none;transition:opacity .3s ease;}
|
||||
.bn-navbar-toggle:checked ~ .bn-navbar-drawer{transform:translateX(0);}
|
||||
.bn-navbar-toggle:checked ~ .bn-navbar-overlay{opacity:1;pointer-events:auto;}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user