fix(art-deco): remediate empty-media balloons, dead whitespace + mobile layout

- Hero: image-less heroes no longer reserve min-h-[75vh]; use guaranteed
  .deco-hero-compact padding (kills the tall empty band above the fold).
- Landing template: stop double-wrapping main in max-w-5xl/py-16/text-center
  (double padding + clamped full-bleed sections + forced centering); render
  section blocks and the footer full-bleed so each self-manages width/rhythm.
- private_dining: with no image, collapse the 2-col grid to a single centred
  column instead of stranding text beside an empty media half; route the
  capacity/minimum figures through guaranteed .deco-stats gap so values no
  longer collide ("14From").
- Reservation strip: populate phone/hours/book link so it reads as a proper
  gilded bar instead of a cramped empty dark strip under the nav.
- default/article templates: full-bleed header + footer (navbar no longer
  narrowed to max-w-3xl/5xl; dark footer spans edge-to-edge, not a floating
  box with dead vertical space).
- chef_signature: trim md:py-24 -> md:py-20 for tighter section rhythm.
- Layout-critical rules added as explicit CSS (manifest css.input_css_append
  + assets/style.css) rather than JIT-fragile theme-template Tailwind combos.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Alex Dunmow 2026-07-05 17:23:35 +08:00
parent 4e4344298c
commit 3b3adfdf43
9 changed files with 39 additions and 30 deletions

View File

@ -17,6 +17,16 @@
margin: 0;
}
/* deco-hero-compact — image-less hero: comfortable padding, no viewport-height balloon. */
.deco-hero-compact { padding-top: 4rem; padding-bottom: 4rem; }
@media (min-width: 768px) {
.deco-hero-compact { padding-top: 6rem; padding-bottom: 6rem; }
}
/* deco-stats — capacity/minimum figure row: guaranteed column gap so values never collide. */
.deco-stats { display: flex; flex-wrap: wrap; gap: 0.75rem 3rem; }
.deco-stats-center { justify-content: center; }
/* deco-frame — stepped ziggurat frame, layered borders + clipped corners. */
.deco-frame {
position: relative;

View File

@ -1,5 +1,5 @@
{# chef_signature persona block — centred signature-dish feature with sunburst crests. Media via {% img %}. #}
<section data-block="art-deco:chef_signature" class="py-16 md:py-24 bg-background text-foreground">
<section data-block="art-deco:chef_signature" class="py-16 md:py-20 bg-background text-foreground">
<div class="mx-auto max-w-3xl px-4 text-center">
{% if eyebrow %}<div class="mb-4 flex items-center justify-center gap-4"><span class="deco-rule w-10"></span><span class="deco-caps text-xs" style="color:hsl(var(--primary));">{{ eyebrow }}</span><span class="deco-rule w-10"></span></div>{% endif %}
{% if image %}<div class="deco-step mx-auto mb-8 max-w-md">{% img image alt=dish class="w-full h-auto object-cover" %}</div>{% endif %}

View File

@ -1,14 +1,13 @@
{# private_dining persona block — framed room image + gilded details panel. Media via {% img %}. #}
<section data-block="art-deco:private_dining" class="py-16 md:py-24 bg-background text-foreground">
<div class="mx-auto grid max-w-6xl items-center gap-10 px-4 md:grid-cols-2 md:gap-16">
<div class="{% if mediaPosition == "right" %}md:order-2{% else %}md:order-1{% endif %}">
{% if image %}<div class="deco-step">{% img image alt=title class="w-full h-auto object-cover" %}</div>{% endif %}
</div>
<div class="{% if mediaPosition == "right" %}md:order-1{% else %}md:order-2{% endif %}">
{% if eyebrow %}<div class="mb-3 flex items-center gap-4"><span class="deco-rule w-10"></span><span class="deco-caps text-xs" style="color:hsl(var(--primary));">{{ eyebrow }}</span></div>{% endif %}
{# private_dining persona block — framed room image + gilded details panel. Media via {% img %}. With no image, collapses to a single centred column so the empty media half never balloons. #}
{% set hasImage = image %}
<section data-block="art-deco:private_dining" class="py-16 md:py-20 bg-background text-foreground">
<div class="mx-auto grid items-center gap-10 px-4 {% if hasImage %}max-w-6xl md:grid-cols-2 md:gap-16{% else %}max-w-3xl{% endif %}">
{% if hasImage %}<div class="{% if mediaPosition == "right" %}md:order-2{% else %}md:order-1{% endif %}"><div class="deco-step">{% img image alt=title class="w-full h-auto object-cover" %}</div></div>{% endif %}
<div class="{% if hasImage %}{% if mediaPosition == "right" %}md:order-1{% else %}md:order-2{% endif %}{% else %}text-center{% endif %}">
{% if eyebrow %}<div class="mb-3 flex items-center gap-4 {% if not hasImage %}justify-center{% endif %}"><span class="deco-rule w-10"></span><span class="deco-caps text-xs" style="color:hsl(var(--primary));">{{ eyebrow }}</span>{% if not hasImage %}<span class="deco-rule w-10"></span>{% endif %}</div>{% endif %}
{% if title %}<h2 class="deco-caps text-3xl md:text-4xl" style="font-family:var(--font-heading, 'Cinzel', 'Italiana', Georgia, serif);color:hsl(var(--foreground));">{{ title }}</h2>{% endif %}
{% if description %}<div class="mt-4 space-y-4 text-lg italic" style="color:hsl(var(--muted-foreground));font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ description|safe }}</div>{% endif %}
{% if seats or minimum %}<dl class="mt-6 flex flex-wrap gap-x-10 gap-y-3">{% if seats %}<div><dt class="deco-caps text-xs" style="color:hsl(var(--primary));">Capacity</dt><dd class="mt-1">{{ seats }}</dd></div>{% endif %}{% if minimum %}<div><dt class="deco-caps text-xs" style="color:hsl(var(--primary));">Minimum</dt><dd class="mt-1">{{ minimum }}</dd></div>{% endif %}</dl>{% endif %}
{% if description %}<div class="mt-4 space-y-4 text-lg italic {% if not hasImage %}mx-auto max-w-xl{% endif %}" style="color:hsl(var(--muted-foreground));font-family:var(--font-body, 'Cormorant Garamond', Georgia, serif);">{{ description|safe }}</div>{% endif %}
{% if seats or minimum %}<dl class="deco-stats mt-6 {% if not hasImage %}deco-stats-center{% endif %}">{% if seats %}<div><dt class="deco-caps text-xs" style="color:hsl(var(--primary));">Capacity</dt><dd class="mt-1">{{ seats }}</dd></div>{% endif %}{% if minimum %}<div><dt class="deco-caps text-xs" style="color:hsl(var(--primary));">Minimum</dt><dd class="mt-1">{{ minimum }}</dd></div>{% endif %}</dl>{% endif %}
{% if enquireUrl %}<a href="{{ enquireUrl }}" class="deco-pill mt-8 inline-flex items-center gap-2">{{ enquireLabel|default:"Enquire" }}</a>{% endif %}
</div>
</div>

View File

@ -128,6 +128,16 @@ css:
margin: 0;
}
/* deco-hero-compact — image-less hero: comfortable padding, no viewport-height balloon. */
.deco-hero-compact { padding-top: 4rem; padding-bottom: 4rem; }
@media (min-width: 768px) {
.deco-hero-compact { padding-top: 6rem; padding-bottom: 6rem; }
}
/* deco-stats — capacity/minimum figure row: guaranteed column gap so values never collide. */
.deco-stats { display: flex; flex-wrap: wrap; gap: 0.75rem 3rem; }
.deco-stats-center { justify-content: center; }
/* deco-frame — stepped ziggurat frame, layered borders + clipped corners. */
.deco-frame {
position: relative;

View File

@ -16,7 +16,7 @@
"page_templates": ["landing", "full-width"],
"blocks": [
{ "block_key": "navbar", "title": "Gilded Navigation", "content": { "menuName": "main", "logoType": "text", "logoText": { "text": "Maison Doré" } }, "slot": "marquee", "sort_order": 0 },
{ "block_key": "art-deco:reservation", "title": "Reservation Strip", "content": { "phone": "", "openTable": "", "hours": [] }, "slot": "marquee", "sort_order": 1 },
{ "block_key": "art-deco:reservation", "title": "Reservation Strip", "content": { "phone": "+1 555 0126", "openTable": "/contact", "hours": ["Dinner Tuesday to Sunday", "6pm to late"] }, "slot": "marquee", "sort_order": 1 },
{ "block_key": "slot", "title": "Main Content", "content": { "slotName": "main" }, "slot": "main", "sort_order": 0 },
{ "block_key": "divider", "title": "CTA Fan Divider", "content": { "variant": "ornament", "icon": "lucide:diamond" }, "slot": "cta", "sort_order": 0 },
{ "block_key": "footer", "title": "Site Footer", "content": { "layout": "centered", "companyName": "Maison Doré", "tagline": "A supper club in the grand manner." }, "slot": "footer", "sort_order": 0 }

View File

@ -3,18 +3,14 @@
{{ head_html|safe }}
<body class="bg-background text-foreground antialiased min-h-screen flex flex-col" style="font-family: var(--font-body, &quot;Cormorant Garamond&quot;, &quot;Cormorant&quot;, Georgia, serif);">
{{ admin_banner_html|safe }}
<header class="w-full">
<div class="max-w-3xl mx-auto px-4">{{ slots.header|safe }}</div>
</header>
<header class="w-full">{{ slots.header|safe }}</header>
<div class="flex-grow grid gap-12 max-w-5xl mx-auto w-full px-4 py-12 md:grid-cols-[2fr_1fr]">
<main class="prose max-w-none">
{% if slots.main %}<article class="deco-dropcap" data-deco-dropcap="true">{{ slots.main|safe }}</article>{% else %}<div class="py-20 text-center"><p class="text-muted-foreground">No content blocks assigned to this page.</p></div>{% endif %}
</main>
<aside class="w-full">{{ slots.aside|safe }}</aside>
</div>
<footer class="w-full mt-auto">
<div class="max-w-5xl mx-auto px-4">{{ slots.footer|safe }}</div>
</footer>
<footer class="w-full mt-auto">{{ slots.footer|safe }}</footer>
{{ body_end_html|safe }}
</body>
</html>

View File

@ -3,15 +3,11 @@
{{ head_html|safe }}
<body class="bg-background text-foreground antialiased min-h-screen flex flex-col" style="font-family: var(--font-body, &quot;Cormorant Garamond&quot;, &quot;Cormorant&quot;, Georgia, serif);">
{{ admin_banner_html|safe }}
<header class="w-full">
<div class="max-w-5xl mx-auto px-4">{{ slots.header|safe }}</div>
</header>
<header class="w-full">{{ slots.header|safe }}</header>
<main class="flex-grow max-w-3xl mx-auto w-full px-4 py-12 text-center">
{% if slots.main %}{{ slots.main|safe }}{% else %}<div class="py-20"><p class="text-muted-foreground">No content blocks assigned to this page.</p></div>{% endif %}
</main>
<footer class="w-full mt-auto">
<div class="max-w-5xl mx-auto px-4">{{ slots.footer|safe }}</div>
</footer>
<footer class="w-full mt-auto">{{ slots.footer|safe }}</footer>
{{ body_end_html|safe }}
</body>
</html>

View File

@ -4,13 +4,11 @@
<body class="bg-background text-foreground antialiased min-h-screen flex flex-col" style="font-family: var(--font-body, &quot;Cormorant Garamond&quot;, &quot;Cormorant&quot;, Georgia, serif);">
{{ admin_banner_html|safe }}
<section class="w-full">{{ slots.marquee|safe }}</section>
<main class="flex-grow">
{% if slots.main %}<div class="max-w-5xl mx-auto px-4 py-16 text-center">{{ slots.main|safe }}</div>{% endif %}
<main class="flex-grow w-full">
{% if slots.main %}{{ slots.main|safe }}{% endif %}
</main>
<section class="w-full">{{ slots.cta|safe }}</section>
<footer class="w-full mt-auto">
<div class="max-w-5xl mx-auto px-4">{{ slots.footer|safe }}</div>
</footer>
<footer class="w-full mt-auto">{{ slots.footer|safe }}</footer>
{{ body_end_html|safe }}
</body>
</html>

View File

@ -32,7 +32,7 @@
{% else %}
{% set align = "center" %}
{% if variant == "left-aligned" %}{% set align = "left" %}{% endif %}
<section data-block-override="art-deco:hero" class="hero relative flex flex-col overflow-hidden bg-background text-foreground deco-grain {% if minHeight == "screen" %}min-h-screen{% elif minHeight == "50vh" %}min-h-[50vh]{% elif minHeight == "auto" %}min-h-[400px]{% else %}min-h-[75vh]{% endif %} {% if verticalAlign == "top" %}justify-start pt-20{% elif verticalAlign == "bottom" %}justify-end pb-20{% else %}justify-center{% endif %}{% if class %} {{ class }}{% endif %}">
<section data-block-override="art-deco:hero" class="hero relative flex flex-col overflow-hidden bg-background text-foreground deco-grain {% if hasImage %}{% if minHeight == "screen" %}min-h-screen{% elif minHeight == "50vh" %}min-h-[50vh]{% elif minHeight == "auto" %}min-h-[400px]{% else %}min-h-[75vh]{% endif %}{% else %}deco-hero-compact{% endif %} {% if verticalAlign == "top" %}justify-start pt-20{% elif verticalAlign == "bottom" %}justify-end pb-20{% else %}justify-center{% endif %}{% if class %} {{ class }}{% endif %}">
{% if hasImage %}<div class="absolute inset-0 z-0">{% img backgroundImage alt=headlineText class="h-full w-full object-cover" layout="hero" %}{% if showOverlay %}<div class="absolute inset-0 {% if overlayColor == "light" %}bg-background/60{% elif overlayColor == "primary" %}bg-primary/50{% elif overlayOpacity <= 30 %}bg-black/30{% elif overlayOpacity <= 50 %}bg-black/50{% elif overlayOpacity <= 70 %}bg-black/70{% else %}bg-black/80{% endif %}"></div>{% endif %}</div>{% endif %}
<div class="pointer-events-none absolute inset-x-0 top-0 z-[1] h-40 opacity-40 deco-sunburst" aria-hidden="true"></div>
<div class="relative z-10 mx-auto w-full max-w-4xl px-4 sm:px-6 lg:px-8 {% if variant == "left-aligned" %}text-left{% else %}text-center{% endif %}"><div class="deco-frame bg-transparent px-6 py-10 sm:px-10 sm:py-14">{{ herocontent(align) }}</div></div>