fix(coffee): remediate torn-mask clipping, empty-media & JIT-dropped layout

Layout/whitespace bugs:
- .coffee-torn-top/bottom used mask-size:100% 100%, stretching the 12px torn
  SVG over the whole element and masking away ~40% of tall cards as a wavy
  transparent cut-out — the cause of the clipped hero region, featured_pour
  and footer. Reworked to a fixed ~13px deckled band per edge over a solid
  gradient (plus a combined top+bottom selector).
- featured_pour showed an editor-style "Add a hero image" placeholder to
  visitors when the demo seed ships no image; now a tasteful token-based coffee
  glyph on the secondary surface. Same for the image block ("Add an image").
- hours today-highlight was accent-foreground text over a 15% accent tint
  (light-on-light, unreadable "Sunday"); now a readable full-row band with an
  accent left edge (class moved from <th> to <tr>).

Mobile responsiveness / JIT robustness (host Tailwind does not reliably compile
arbitrary/responsive utilities out of theme templates):
- Replaced min-h-[50vh|75vh|400px|320px], md:grid-cols-[2fr_3fr] and
  md:grid-cols-2 in hero/featured_pour/menu-list/hours with explicit CSS helper
  classes carrying real media queries; base is single-column so every grid
  collapses to 1 col on mobile regardless of the JIT.

Semantic tokens only; no version bump.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Alex Dunmow 2026-07-05 17:25:36 +08:00
parent 4b5a37b7d3
commit c2dd751f6b
7 changed files with 145 additions and 45 deletions

View File

@ -98,22 +98,40 @@ body.coffee-paper {
background-color: hsl(var(--muted)); background-color: hsl(var(--muted));
} }
/* --- Torn-paper edges --------------------------------------------------- */ /* --- Torn-paper edges ---------------------------------------------------
* The deckled edge is a FIXED ~13px band at the named edge; the rest of the
* element is masked solid. (The old `mask-size:100% 100%` stretched the 12px
* torn SVG across the whole element, eating ~40% of tall cards as a transparent
* wavy cut-out the source of the hero/featured-pour/footer clipping.) */
.coffee-torn-top { .coffee-torn-top {
-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"); -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black);
mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black);
-webkit-mask-repeat: no-repeat; -webkit-mask-position: top, bottom;
mask-repeat: no-repeat; mask-position: top, bottom;
-webkit-mask-size: 100% 100%; -webkit-mask-size: 100% 13px, 100% calc(100% - 12px);
mask-size: 100% 100%; mask-size: 100% 13px, 100% calc(100% - 12px);
-webkit-mask-repeat: no-repeat, no-repeat;
mask-repeat: no-repeat, no-repeat;
} }
.coffee-torn-bottom { .coffee-torn-bottom {
-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E"); -webkit-mask-image: linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E"); mask-image: linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
-webkit-mask-repeat: no-repeat; -webkit-mask-position: top, bottom;
mask-repeat: no-repeat; mask-position: top, bottom;
-webkit-mask-size: 100% 100%; -webkit-mask-size: 100% calc(100% - 12px), 100% 13px;
mask-size: 100% 100%; mask-size: 100% calc(100% - 12px), 100% 13px;
-webkit-mask-repeat: no-repeat, no-repeat;
mask-repeat: no-repeat, no-repeat;
}
.coffee-torn-top.coffee-torn-bottom {
-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
-webkit-mask-position: top, center, bottom;
mask-position: top, center, bottom;
-webkit-mask-size: 100% 13px, 100% calc(100% - 24px), 100% 13px;
mask-size: 100% 13px, 100% calc(100% - 24px), 100% 13px;
-webkit-mask-repeat: no-repeat, no-repeat, no-repeat;
mask-repeat: no-repeat, no-repeat, no-repeat;
} }
/* --- Surfaces ----------------------------------------------------------- */ /* --- Surfaces ----------------------------------------------------------- */
@ -149,12 +167,44 @@ body.coffee-paper {
color: hsl(var(--background) / 0.72); color: hsl(var(--background) / 0.72);
} }
/* --- Hours: today highlight --------------------------------------------- */ /* --- Hours: today highlight ---------------------------------------------
.coffee-hours-today { * Applied to the whole <tr> so both cells share one readable band. (Was on the
background-color: hsl(var(--accent) / 0.15); * <th> only with accent-foreground text over a 15%-accent tint light-on-light,
color: hsl(var(--accent-foreground)); * unreadable.) accent text over a 12% tint of the same accent reads cleanly. */
border-left: 3px solid hsl(var(--accent)); .coffee-hours-today > th,
.coffee-hours-today > td {
background-color: hsl(var(--accent) / 0.12);
}
.coffee-hours-today > th {
box-shadow: inset 3px 0 0 hsl(var(--accent));
padding-left: 0.75rem; padding-left: 0.75rem;
color: hsl(var(--accent));
}
/* --- Layout helpers ------------------------------------------------------
* Explicit CSS so these layouts never depend on the host Tailwind JIT
* compiling arbitrary/responsive utilities out of THEME templates it does
* not scan them reliably, so `min-h-[50vh]` / `md:grid-cols-[2fr_3fr]` /
* `md:grid-cols-2` in a theme file can silently vanish. Base is always a
* single column, so grids collapse on mobile regardless of the JIT. */
.coffee-minh-50 { min-height: 50vh; }
.coffee-minh-75 { min-height: 75vh; }
.coffee-minh-screen { min-height: 100vh; }
.coffee-minh-400 { min-height: 400px; }
.coffee-minh-320 { min-height: 320px; }
.coffee-split-2 { display: grid; grid-template-columns: 1fr; }
.coffee-pour-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
.coffee-menu-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem 3rem; }
.coffee-info-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem; }
@media (min-width: 768px) {
.coffee-pour-grid { grid-template-columns: 2fr 3fr; align-items: center; }
.coffee-menu-grid.coffee-menu-grid--2 { grid-template-columns: 1fr 1fr; }
.coffee-info-grid.coffee-info-grid--2 { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1024px) {
.coffee-split-2 { grid-template-columns: 1fr 1fr; }
} }
/* --- Price + spec chips ------------------------------------------------- */ /* --- Price + spec chips ------------------------------------------------- */

View File

@ -1,8 +1,8 @@
<section data-block="coffee:featured_pour" class="py-12 md:py-16 bg-background text-foreground{% if class %} {{ class }}{% endif %}"> <section data-block="coffee:featured_pour" class="py-12 md:py-16 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
<div class="coffee-card coffee-torn-bottom relative mx-auto grid max-w-4xl gap-6 p-6 md:grid-cols-[2fr_3fr] md:items-center"> <div class="coffee-card coffee-torn-bottom coffee-pour-grid relative mx-auto max-w-4xl p-6">
<span class="coffee-hand absolute -top-4 left-6 inline-flex rotate-[-3deg] items-center gap-1 rounded-full bg-accent px-4 py-1 text-lg text-accent-foreground shadow-sm">{{ label|default:"Featured pour" }}</span> <span class="coffee-hand absolute -top-4 left-6 inline-flex rotate-[-3deg] items-center gap-1 rounded-full bg-accent px-4 py-1 text-lg text-accent-foreground shadow-sm">{{ label|default:"Featured pour" }}</span>
<div class="aspect-square overflow-hidden rounded-sm bg-secondary"> <div class="aspect-square overflow-hidden rounded-sm bg-secondary">
{% if image %}{% img image alt=name|default:"Featured pour" class="h-full w-full object-cover" %}{% else %}<div class="flex h-full w-full items-center justify-center coffee-hand text-2xl text-muted-foreground">Add a hero image</div>{% endif %} {% if image %}{% img image alt=name|default:"Featured pour" class="h-full w-full object-cover" %}{% else %}<div class="flex h-full w-full items-center justify-center bg-secondary text-primary/20"><svg class="h-24 w-24" aria-hidden="true"><use href="/icons/lucide.svg#coffee"></use></svg></div>{% endif %}
</div> </div>
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
{% if origin %}<p class="coffee-hand text-xl text-accent">{{ origin }}</p>{% endif %} {% if origin %}<p class="coffee-hand text-xl text-accent">{{ origin }}</p>{% endif %}

View File

@ -206,22 +206,40 @@ css:
background-color: hsl(var(--muted)); background-color: hsl(var(--muted));
} }
/* --- Torn-paper edges --------------------------------------------------- */ /* --- Torn-paper edges ---------------------------------------------------
* The deckled edge is a FIXED ~13px band at the named edge; the rest of the
* element is masked solid. (The old `mask-size:100% 100%` stretched the 12px
* torn SVG across the whole element, eating ~40% of tall cards as a transparent
* wavy cut-out — the source of the hero/featured-pour/footer clipping.) */
.coffee-torn-top { .coffee-torn-top {
-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"); -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black);
mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"); mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black);
-webkit-mask-repeat: no-repeat; -webkit-mask-position: top, bottom;
mask-repeat: no-repeat; mask-position: top, bottom;
-webkit-mask-size: 100% 100%; -webkit-mask-size: 100% 13px, 100% calc(100% - 12px);
mask-size: 100% 100%; mask-size: 100% 13px, 100% calc(100% - 12px);
-webkit-mask-repeat: no-repeat, no-repeat;
mask-repeat: no-repeat, no-repeat;
} }
.coffee-torn-bottom { .coffee-torn-bottom {
-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E"); -webkit-mask-image: linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E"); mask-image: linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
-webkit-mask-repeat: no-repeat; -webkit-mask-position: top, bottom;
mask-repeat: no-repeat; mask-position: top, bottom;
-webkit-mask-size: 100% 100%; -webkit-mask-size: 100% calc(100% - 12px), 100% 13px;
mask-size: 100% 100%; mask-size: 100% calc(100% - 12px), 100% 13px;
-webkit-mask-repeat: no-repeat, no-repeat;
mask-repeat: no-repeat, no-repeat;
}
.coffee-torn-top.coffee-torn-bottom {
-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12 L0 6 Q 5 2 10 5 T 20 4 T 30 6 T 40 3 T 50 5 T 60 4 T 70 5 T 80 3 T 90 5 T 100 4 L100 12 Z' fill='black'/%3E%3C/svg%3E"), linear-gradient(black, black), url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 0 L100 0 L100 6 Q 95 10 90 7 T 80 8 T 70 6 T 60 9 T 50 7 T 40 8 T 30 7 T 20 9 T 10 7 T 0 8 Z' fill='black'/%3E%3C/svg%3E");
-webkit-mask-position: top, center, bottom;
mask-position: top, center, bottom;
-webkit-mask-size: 100% 13px, 100% calc(100% - 24px), 100% 13px;
mask-size: 100% 13px, 100% calc(100% - 24px), 100% 13px;
-webkit-mask-repeat: no-repeat, no-repeat, no-repeat;
mask-repeat: no-repeat, no-repeat, no-repeat;
} }
/* --- Surfaces ----------------------------------------------------------- */ /* --- Surfaces ----------------------------------------------------------- */
@ -257,14 +275,46 @@ css:
color: hsl(var(--background) / 0.72); color: hsl(var(--background) / 0.72);
} }
/* --- Hours: today highlight --------------------------------------------- */ /* --- Hours: today highlight ---------------------------------------------
.coffee-hours-today { * Applied to the whole <tr> so both cells share one readable band. (Was on the
background-color: hsl(var(--accent) / 0.15); * <th> only with accent-foreground text over a 15%-accent tint — light-on-light,
color: hsl(var(--accent-foreground)); * unreadable.) accent text over a 12% tint of the same accent reads cleanly. */
border-left: 3px solid hsl(var(--accent)); .coffee-hours-today > th,
.coffee-hours-today > td {
background-color: hsl(var(--accent) / 0.12);
}
.coffee-hours-today > th {
box-shadow: inset 3px 0 0 hsl(var(--accent));
padding-left: 0.75rem; padding-left: 0.75rem;
color: hsl(var(--accent));
} }
/* --- Layout helpers ------------------------------------------------------
* Explicit CSS so these layouts never depend on the host Tailwind JIT
* compiling arbitrary/responsive utilities out of THEME templates — it does
* not scan them reliably, so `min-h-[50vh]` / `md:grid-cols-[2fr_3fr]` /
* `md:grid-cols-2` in a theme file can silently vanish. Base is always a
* single column, so grids collapse on mobile regardless of the JIT. */
.coffee-minh-50 { min-height: 50vh; }
.coffee-minh-75 { min-height: 75vh; }
.coffee-minh-screen { min-height: 100vh; }
.coffee-minh-400 { min-height: 400px; }
.coffee-minh-320 { min-height: 320px; }
.coffee-split-2 { display: grid; grid-template-columns: 1fr; }
.coffee-pour-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
.coffee-menu-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem 3rem; }
.coffee-info-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem; }
@media (min-width: 768px) {
.coffee-pour-grid { grid-template-columns: 2fr 3fr; align-items: center; }
.coffee-menu-grid.coffee-menu-grid--2 { grid-template-columns: 1fr 1fr; }
.coffee-info-grid.coffee-info-grid--2 { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1024px) {
.coffee-split-2 { grid-template-columns: 1fr 1fr; }
}
/* --- Price + spec chips ------------------------------------------------- */ /* --- Price + spec chips ------------------------------------------------- */
.coffee-price { .coffee-price {
font-family: var(--font-mono, var(--coffee-mono-fallback)); font-family: var(--font-mono, var(--coffee-mono-fallback));

View File

@ -22,14 +22,14 @@
{% if trustLogos %}<div class="mt-10"><p class="coffee-hand mb-3 text-lg text-accent">Regulars love</p><div class="flex flex-wrap items-center gap-6{% if align == "center" %} justify-center{% endif %}">{% for logo in trustLogos %}{% if logo.url %}<a href="{{ logo.url }}" target="_blank" rel="noopener" class="opacity-60 transition-opacity hover:opacity-100">{% img logo.image alt=logo.alt class="h-8 w-auto" %}</a>{% else %}{% img logo.image alt=logo.alt class="h-8 w-auto opacity-60" %}{% endif %}{% endfor %}</div></div>{% endif %} {% if trustLogos %}<div class="mt-10"><p class="coffee-hand mb-3 text-lg text-accent">Regulars love</p><div class="flex flex-wrap items-center gap-6{% if align == "center" %} justify-center{% endif %}">{% for logo in trustLogos %}{% if logo.url %}<a href="{{ logo.url }}" target="_blank" rel="noopener" class="opacity-60 transition-opacity hover:opacity-100">{% img logo.image alt=logo.alt class="h-8 w-auto" %}</a>{% else %}{% img logo.image alt=logo.alt class="h-8 w-auto opacity-60" %}{% endif %}{% endfor %}</div></div>{% endif %}
{% endmacro %} {% endmacro %}
{% if variant == "split" %} {% if variant == "split" %}
<section class="hero grid grid-cols-1 overflow-hidden bg-background text-foreground lg:grid-cols-2{% if class %} {{ class }}{% endif %}"> <section class="hero coffee-split-2 overflow-hidden bg-background text-foreground{% if class %} {{ class }}{% endif %}">
<div class="relative min-h-[320px] bg-secondary {% if mediaPosition == "left" %}order-1 lg:order-1{% else %}order-1 lg:order-2{% endif %}">{% if hasImage %}{% img backgroundImage alt=headlineText class="absolute inset-0 h-full w-full object-cover" layout="hero" %}{% endif %}</div> <div class="coffee-minh-320 relative bg-secondary {% if mediaPosition == "left" %}order-1 lg:order-1{% else %}order-1 lg:order-2{% endif %}">{% if hasImage %}{% img backgroundImage alt=headlineText class="absolute inset-0 h-full w-full object-cover" layout="hero" %}{% endif %}</div>
<div class="flex flex-col justify-center px-6 py-16 lg:px-12 {% if mediaPosition == "left" %}order-2 lg:order-2{% else %}order-2 lg:order-1{% endif %}"><div class="max-w-lg text-left">{{ herocontent("left") }}</div></div> <div class="flex flex-col justify-center px-6 py-16 lg:px-12 {% if mediaPosition == "left" %}order-2 lg:order-2{% else %}order-2 lg:order-1{% endif %}"><div class="max-w-lg text-left">{{ herocontent("left") }}</div></div>
</section> </section>
{% else %} {% else %}
{% set align = "center" %} {% set align = "center" %}
{% if variant == "left-aligned" %}{% set align = "left" %}{% endif %} {% if variant == "left-aligned" %}{% set align = "left" %}{% endif %}
<section class="hero relative flex flex-col overflow-hidden bg-background text-foreground {% 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 class="hero relative flex flex-col overflow-hidden bg-background text-foreground {% if minHeight == "screen" %}coffee-minh-screen{% elif minHeight == "50vh" %}coffee-minh-50{% elif minHeight == "auto" %}coffee-minh-400{% else %}coffee-minh-75{% 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 %} {% 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="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 %}">{{ herocontent(align) }}</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 %}">{{ herocontent(align) }}</div>
</section> </section>

View File

@ -1,7 +1,7 @@
<section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}"> <section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
<div class="mx-auto max-w-5xl px-4"> <div class="mx-auto max-w-5xl px-4">
{% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %} {% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %}
<div class="mt-10 grid grid-cols-1 gap-10 md:grid-cols-2"> <div class="coffee-info-grid{% if mapEmbedUrl %} coffee-info-grid--2{% endif %} mt-10">
<div> <div>
{% if hours %} {% if hours %}
<table class="coffee-body w-full text-sm" data-coffee-hours> <table class="coffee-body w-full text-sm" data-coffee-hours>
@ -34,7 +34,7 @@
var today=days[new Date().getDay()]; var today=days[new Date().getDay()];
document.querySelectorAll('[data-coffee-hours] tr[data-day]').forEach(function(tr){ document.querySelectorAll('[data-coffee-hours] tr[data-day]').forEach(function(tr){
var d=(tr.getAttribute('data-day')||'').trim(); var d=(tr.getAttribute('data-day')||'').trim();
if(d.toLowerCase().indexOf(today.toLowerCase())===0){tr.querySelector('th').classList.add('coffee-hours-today');} if(d.toLowerCase().indexOf(today.toLowerCase())===0){tr.classList.add('coffee-hours-today');}
}); });
})(); })();
</script> </script>

View File

@ -1,7 +1,7 @@
{% with size=size|default:"full" align=align|default:"center" %} {% with size=size|default:"full" align=align|default:"center" %}
<figure class="my-8 flex flex-1 flex-col {% if align == "left" %}items-start{% elif align == "right" %}items-end{% else %}items-center{% endif %}{% if class %} {{ class }}{% endif %}"> <figure class="my-8 flex flex-1 flex-col {% if align == "left" %}items-start{% elif align == "right" %}items-end{% else %}items-center{% endif %}{% if class %} {{ class }}{% endif %}">
<div class="coffee-frame coffee-torn-bottom relative overflow-hidden p-2 {% if size == "xs" %}max-w-[200px] w-full{% elif size == "sm" %}max-w-[400px] w-full{% elif size == "md" %}max-w-[600px] w-full{% elif size == "lg" %}max-w-[800px] w-full{% else %}w-full{% endif %}"> <div class="coffee-frame coffee-torn-bottom relative overflow-hidden p-2 {% if size == "xs" %}max-w-[200px] w-full{% elif size == "sm" %}max-w-[400px] w-full{% elif size == "md" %}max-w-[600px] w-full{% elif size == "lg" %}max-w-[800px] w-full{% else %}w-full{% endif %}">
{% if src %}{% img src alt=alt class="block h-auto w-full rounded-sm object-cover" layout=size %}{% else %}<div class="flex h-48 w-full items-center justify-center coffee-hand text-2xl text-muted-foreground">Add an image</div>{% endif %} {% if src %}{% img src alt=alt class="block h-auto w-full rounded-sm object-cover" layout=size %}{% else %}<div class="flex h-48 w-full items-center justify-center bg-secondary text-primary/20"><svg class="h-12 w-12" aria-hidden="true"><use href="/icons/lucide.svg#image"></use></svg></div>{% endif %}
</div> </div>
{% if caption %}<figcaption class="coffee-hand mt-3 text-center text-xl text-accent">{{ caption }}</figcaption>{% endif %} {% if caption %}<figcaption class="coffee-hand mt-3 text-center text-xl text-accent">{{ caption }}</figcaption>{% endif %}
</figure> </figure>

View File

@ -3,7 +3,7 @@
{% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %} {% if heading %}<h2 class="coffee-display text-3xl text-primary md:text-4xl"><span class="coffee-doodle-underline">{{ heading }}</span></h2>{% endif %}
{% if intro %}<p class="coffee-body mt-3 max-w-2xl text-lg text-muted-foreground">{{ intro }}</p>{% endif %} {% if intro %}<p class="coffee-body mt-3 max-w-2xl text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
<div class="coffee-chalkboard mt-10 p-6 md:p-10"> <div class="coffee-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="coffee-menu-grid{% if columns == 2 %} coffee-menu-grid--2{% endif %}">
{% for section in sections %} {% for section in sections %}
<div class="menu-section"> <div class="menu-section">
{% if section.title %}<h3 class="coffee-hand border-b coffee-chalk-rule pb-2 text-3xl">{{ section.title }}</h3>{% endif %} {% if section.title %}<h3 class="coffee-hand border-b coffee-chalk-rule pb-2 text-3xl">{{ section.title }}</h3>{% endif %}