/* Phat Websites — reusable florist theme. Structure lives here; each site injects its
   brand colours + heading font as CSS variables (see build.py -> :root in the page head). */

:root {
  --dark: #3a3a3a;
  --light: #f7f1e6;
  --accent: #b5824e;
  --accent-strong: #7c5836; /* AA-safe accent for small text + button fills; build.py overrides per brand */
  --heading-font: Georgia, serif;
  --body-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --ink: #2a2d31;
  --muted: #6b7178;
  --line: rgba(0, 0, 0, .08);
  --maxw: 1140px;
  /* ---- Type system: a fluid modular scale (confident, editorial). Sites can override --display-font
     for a distinct display face (serif/script) on hero/display headings. ---- */
  --display-font: var(--heading-font);
  --fs-display: clamp(3rem, 8vw, 6.5rem);      /* the giant Worm/flyhyer hero wordmark */
  --fs-hero: clamp(2.6rem, 5.2vw, 4.4rem);     /* standard hero heading, big + confident */
  --fs-hero-compact: clamp(2.1rem, 3.6vw, 3.1rem);
  --fs-h2: clamp(1.7rem, 2.8vw, 2.5rem);
  --fs-h3: clamp(1.12rem, 1.3vw, 1.32rem);
  --fs-lead: clamp(1.08rem, 1.4vw, 1.3rem);
  --lh-tight: 1.05;
  --track-tight: -0.021em;
  --track-loose: 0.14em;
  /* ---- Spacing scale: generous, deliberate vertical rhythm ---- */
  --space-section: clamp(64px, 9vw, 128px);
  --space-section-sm: clamp(44px, 6vw, 80px);
  --space-head: clamp(28px, 4vw, 52px);        /* gap under a section heading block */
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* Accessibility: skip-to-content link (visible only when focused) + visible focus rings */
.skip-link {
  position: absolute; left: 8px; top: -48px; z-index: 200;
  background: var(--dark); color: #fff; padding: 10px 16px; border-radius: 0 0 8px 8px;
  text-decoration: none; transition: top .15s ease;
}
.skip-link:focus { top: 0; }
a:focus-visible, button:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.btn:focus-visible { outline: 3px solid var(--dark); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
}
body {
  margin: 0;
  font-family: var(--body-font);
  color: var(--ink);
  background: var(--light);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { font-family: var(--heading-font); font-weight: 600; line-height: 1.15; letter-spacing: var(--track-tight); }
h1 { font-size: var(--fs-hero); }
/* A page with no hero has no <h1>, so build.py promotes its first <h2> and tags it .as-h2.
   This keeps the ORIGINAL h2 size, so the fix is semantic (crawlers, screen readers skipping
   by heading level) and never visual. Added 2026-08-04. */
h1.as-h2 { font-size: var(--fs-h2); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); letter-spacing: normal; }
a { color: var(--dark); }
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }

/* Header */
.site-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px 24px; max-width: var(--maxw); margin: 0 auto;
}
.logo { font-family: var(--heading-font); font-size: 22px; font-weight: 600; color: var(--dark); text-decoration: none; }
.logo-img { display: inline-flex; align-items: center; }
/* 54px is our house default, not a law: a traditional florist wordmark with the trade under
   the name needs more room or it turns to mush (Cottage display theirs at 113px). Declared
   per site with `site.logo_height`, which sets --logo-h on the header. */
.logo-img img { display: block; width: auto; height: auto; max-height: var(--logo-h, 54px); max-width: var(--logo-maxw, 200px); }
/* Wordmark treatments (site.wordmark): character without hand-CSS per site. */
.logo-wordmark { display: inline-flex; align-items: center; gap: 12px; text-transform: uppercase; letter-spacing: .07em; font-size: 16px; font-weight: 700; }
.logo-badge { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 10px; background: var(--dark); color: #fff; font-size: 14px; font-weight: 700; letter-spacing: .02em; text-transform: none; }
.logo-caps { text-transform: uppercase; letter-spacing: .13em; font-size: 15px; font-weight: 700; }
.logo-serif { font-family: var(--display-font); font-size: 24px; letter-spacing: var(--track-tight); }
/* `:not(.nav-cta)` because the CTA is a BUTTON that happens to sit in the nav, not a nav link: it
   sets its own colour, size, margin and decoration. These three rules used to catch it, and being
   more specific than `.nav-cta` they won, which is why `.nav-cta` needed `color:#fff !important` to
   claw it back — and why removing that !important on 2026-07-28 turned tracy's live header button
   near-black. Excluding it here is the actual fix: no !important needed on either side. The same
   pattern is already used for the animated underline further down. */
.nav a:not(.nav-cta) { margin-left: 26px; text-decoration: none; color: var(--ink); font-size: 15px; }
.nav a:not(.nav-cta):hover { color: var(--accent-strong); }
.nav a:not(.nav-cta).active { color: var(--accent-strong); }

/* Nav dropdown (site.nav_children): opens on hover / keyboard focus (CSS only), stacked in the mobile panel. */
.nav .nav-item { position: relative; margin-left: 26px; }
.nav .nav-item .nav-parent { margin-left: 0; display: inline-flex; align-items: center; gap: 5px; }
.nav-parent .nav-caret { display: inline-flex; transition: transform .2s ease; }
.nav-parent .nav-caret .ti { font-size: 15px; }
.nav-menu { position: absolute; top: 100%; left: -8px; min-width: 210px; background: var(--light);
  border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 16px 36px rgba(40, 50, 44, .13);
  padding: 8px; display: flex; flex-direction: column; gap: 2px; z-index: 120;
  opacity: 0; visibility: hidden; transform: translateY(6px); transition: opacity .16s ease, transform .16s ease, visibility .16s; }
.nav-item:hover .nav-menu, .nav-item:focus-within .nav-menu { opacity: 1; visibility: visible; transform: translateY(3px); }
.nav-item:hover .nav-caret, .nav-item:focus-within .nav-caret { transform: rotate(180deg); }
.nav .nav-menu a { margin: 0; padding: 9px 12px; border-radius: 8px; font-size: 14.5px; white-space: nowrap; color: var(--ink); }
.nav .nav-menu a:hover, .nav .nav-menu a.active { background: var(--sage-wash, color-mix(in srgb, var(--accent) 10%, var(--light))); color: var(--accent-strong); }
.nav .nav-menu a::after { display: none; }  /* no animated underline inside the menu */

/* Buttons */
.btn {
  display: inline-block; background: var(--accent-strong); color: #fff; text-decoration: none;
  padding: 13px 26px; border-radius: 40px; font-weight: 600; font-size: 15px;
  letter-spacing: .2px; transition: background .15s ease;
}
.btn:hover { background: var(--dark); }

/* Hero */
.hero { text-align: center; padding: var(--space-section) 24px; }
.hero h1 { font-size: var(--fs-hero); font-family: var(--display-font); color: var(--dark);
  margin: 0 auto 22px; max-width: 15ch; line-height: var(--lh-tight); letter-spacing: var(--track-tight); }
.hero p { font-size: var(--fs-lead); color: var(--muted); max-width: 60ch; margin: 0 auto 32px; line-height: 1.55; }

/* Compact hero for interior pages (no photo) */
.hero.compact { padding: var(--space-section-sm) 24px; }
.hero.compact h1 { font-size: var(--fs-hero-compact); margin-bottom: 14px; }

/* Display hero: the giant editorial wordmark/heading (Worm / flyhyer). Opt-in via "display": true. */
.hero.display h1 { font-size: var(--fs-display); max-width: 18ch; }

/* Call-to-action band */
/* `cta-plain`: a quiet centred call to action on the page ground (no band, no dark fill), for a
   button-only beat between white sections. Buttons inherit the site's declared style. */
.cta-plain { text-align: center; padding: var(--space-section-sm) 24px; }
.cta-plain h2 { font-size: var(--fs-h2); margin: 0 0 10px; }
.cta-plain p { color: var(--muted); max-width: 560px; margin: 0 auto 22px; }
.cta-band { text-align: center; background: var(--dark); padding: 62px 24px; margin-top: 30px; }
.cta-band h2 { font-size: var(--fs-h2); color: #fff; margin: 0 0 10px; }
.cta-band p { color: rgba(255, 255, 255, .85); font-size: 17px; max-width: 560px; margin: 0 auto 22px; }
.cta-band .btn { background: var(--accent-strong); margin: 0 6px; }
.cta-band .btn:hover { background: #fff; color: var(--dark); }
/* The optional second (ghost) CTA button, on the dark band: outline style must survive the
   solid .cta-band .btn override above. */
.cta-band .btn-ghost { background: transparent; color: #fff; border: 1.5px solid rgba(255, 255, 255, .55); }
.cta-band .btn-ghost:hover { background: #fff; color: var(--dark); border-color: #fff; }

/* Hero with a photo — a real <img> (the LCP image), not a CSS background, so it can
   be prioritised and served responsively. Image layer sits behind the text + overlay. */
.hero.has-image {
  position: relative; overflow: hidden;
  padding: 130px 24px; color: #fff;
}
.hero.has-image.short { padding: 84px 24px; }
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media img, .hero-media picture { width: 100%; height: 100%; display: block; }
/* object-position defaults to centre, which is a GUESS: it crops heads off tall portraits and
   centres busy heroes on their busiest part. `"focal": "50% 30%"` in a hero section sets --focal
   on .hero-media and aims the crop deliberately. Falls back to centre when unset, so nothing
   changes for a site that has not been tuned. */
.hero-media img { object-fit: cover; object-position: var(--focal, 50% 50%); }
/* Hero SLIDESHOW (`"slides": [...]`). Pure CSS cross-fade: every slide runs the same keyframes over
   one shared cycle, staggered by animation-delay, so no JavaScript is involved and nothing shifts
   layout. The first photograph stays a real eager <img> underneath, so the LCP is the same image it
   would have been without a slideshow; the extra slides sit on top and are decorative. */
.hero.has-slideshow .hero-slide {
  position: absolute; inset: 0; background-size: cover;
  background-position: var(--focal, 50% 50%); opacity: 0;
  animation: pd-hero-slides var(--slide-cycle, 30s) infinite;
}
@keyframes pd-hero-slides {          /* visible for roughly one slot, cross-fading either side */
  0%   { opacity: 0; }
  4%   { opacity: 1; }
  18%  { opacity: 1; }
  24%  { opacity: 0; }
  100% { opacity: 0; }
}
/* Reduced motion: hold the first photograph and never animate. */
@media (prefers-reduced-motion: reduce) {
  .hero.has-slideshow .hero-slide { animation: none; opacity: 0; }
}
.hero.has-image::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(0,0,0,.32), rgba(0,0,0,.55));
}
.hero.has-image .hero-inner { position: relative; z-index: 2; }
.hero.has-image h1 { color: #fff; text-shadow: 0 1px 20px rgba(0,0,0,.25); }
.hero.has-image p { color: rgba(255,255,255,.9); }

/* Video-background hero: a muted looping clip behind the text (poster shows first). */
.hero-video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Asymmetric hero: heading + copy pulled to one side with negative space beyond (flyhyer). */
.hero.hero-left { text-align: left; }
.hero.hero-left .hero-inner { margin: 0; max-width: min(66%, 720px); }
/* Left the WHOLE hero head: the kicker carries its own text-align:center, so an offset hero must
   override it or the kicker floats centred above a left-aligned heading (reads as "slipping left"). */
.hero.hero-left .kicker, .hero.hero-left h1, .hero.hero-left p { margin-left: 0; margin-right: 0; text-align: left; }
.hero.hero-left .hero-btns { justify-content: flex-start; }
.hero.has-image.hero-left .hero-inner { margin: 0; }
@media (max-width: 720px) { .hero.hero-left .hero-inner { max-width: 100%; } }
/* Immersive full-bleed photo hero: fills most of the viewport (Worm / Wild at Heart). */
.hero.has-image.immersive { min-height: min(84vh, 760px); display: flex; align-items: flex-end; padding-bottom: var(--space-section); }
.hero.has-image.immersive.display h1 { font-size: var(--fs-display); }

/* Bento panels: a composed grid of image + colour-block panels with varied widths. */
.panels { padding: var(--space-section-sm) 0; }
.panels-head { margin-bottom: 26px; text-align: center; }
.panels-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
.panel { position: relative; min-height: clamp(300px, 38vw, 460px); display: flex; flex-direction: column; justify-content: flex-end; overflow: hidden; text-decoration: none; }
.panel-wide { grid-column: span 2; }
.panel-image img, .panel-image picture { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.panel-image:hover img { transform: scale(1.04); }
.panel-image::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 45%, rgba(0,0,0,.5)); }
.panel-image .panel-label { position: relative; z-index: 2; color: #fff; font-family: var(--display-font); font-size: clamp(1.4rem, 2.4vw, 2.1rem); letter-spacing: var(--track-tight); padding: 28px 30px; }
/* Colour panels hold only text, so they don't need the tall photo min-height (they still stretch to a
   taller image panel beside them in a mixed row). Keeps text-only bentos proportionate, not cavernous. */
.panel-color { padding: clamp(28px, 4vw, 44px) clamp(24px, 3vw, 34px); justify-content: center; min-height: clamp(200px, 22vw, 300px); }
.panel-color h3 { font-size: clamp(1.3rem, 2vw, 1.9rem); margin: 4px 0 10px; color: var(--dark); }
.panel-color p { color: var(--muted); font-size: 14.5px; line-height: 1.55; margin: 0 0 18px; }
.panel-dark, .panel-dark h3 { color: #fff; }
.panel-dark p { color: rgba(255, 255, 255, .82); }
.panel-dark .btn { background: #fff; color: var(--dark); }
.panels-grid.pg-cols-2 { grid-template-columns: 1fr 1fr; }
.panels-grid.pg-cols-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 820px) { .panels-grid.pg-cols-4 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 820px) { .panels-grid { grid-template-columns: 1fr 1fr; } .panel-wide { grid-column: span 2; } }
@media (max-width: 560px) { .panels-grid { grid-template-columns: 1fr; } .panel-wide { grid-column: auto; } }


/* Scroll parallax: the hero media drifts slower than the page. Pure CSS scroll-driven animation,
   so it no-ops where unsupported; disabled for reduced-motion. The scale keeps edges covered. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero.has-parallax .hero-media {
      animation: hero-parallax linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
      will-change: transform;
    }
    @keyframes hero-parallax {
      from { transform: translateY(-9%) scale(1.14); }
      to   { transform: translateY(9%) scale(1.14); }
    }
  }
}

/* Animated-gradient ("aurora") hero: soft brand-tinted blobs drift behind the text. Kept subtle so
   dark heading text stays legible; freezes for reduced-motion. */
.hero-anim { position: relative; overflow: hidden; }
.hero-anim .hero-inner { position: relative; z-index: 1; }
.hero-aurora {
  position: absolute; inset: -25%; z-index: 0; pointer-events: none;
  filter: blur(64px); opacity: .5;
  background:
    radial-gradient(38% 38% at 22% 30%, var(--accent) 0%, transparent 62%),
    radial-gradient(34% 34% at 78% 22%, var(--accent-strong) 0%, transparent 62%),
    radial-gradient(42% 42% at 62% 82%, var(--dark) 0%, transparent 62%);
  animation: aurora-drift 20s ease-in-out infinite alternate;
}
@keyframes aurora-drift {
  from { transform: translate3d(-3%, 2%, 0) scale(1); }
  to   { transform: translate3d(4%, -3%, 0) scale(1.12); }
}
@media (prefers-reduced-motion: reduce) { .hero-aurora { animation: none; } }

/* Gallery */
.gallery { padding: 40px 0 20px; }
.gallery h2 { text-align: center; font-size: var(--fs-h2); color: var(--dark); margin: 0 0 30px; }
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.tile { overflow: hidden; border-radius: 12px; aspect-ratio: 1 / 1; }
.tile img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .35s ease; }
.tile:hover img { transform: scale(1.05); }
@media (max-width: 720px) { .tiles { grid-template-columns: repeat(2, 1fr); } }

/* Masonry gallery (opt-in): Pinterest-style columns, tiles keep their natural aspect ratio. */
.tiles-masonry { display: block; column-count: 3; column-gap: 14px; grid-template-columns: none; }
.tiles-masonry .tile { break-inside: avoid; margin: 0 0 14px; aspect-ratio: auto; display: block; }
.tiles-masonry .tile img, .tiles-masonry .tile picture { height: auto; }
@media (max-width: 720px) { .tiles-masonry { column-count: 2; } }
@media (max-width: 480px) { .tiles-masonry { column-count: 1; } }

/* Sections */
/* (a stray global `section { padding: 8px 0 }` lived here and quietly offset every section's
   own spacing by 8px on top of its class. Removed 2026-07-25, design audit finding 20.) */
.intro { text-align: center; padding: 30px 0 50px; }
.intro h2 { font-size: var(--fs-h2); color: var(--dark); margin: 0 0 14px; }
.intro p { font-size: 18px; color: var(--muted); max-width: 680px; margin: 0 auto; }

/* ---- Prose / editorial text block: the text-heavy building block that carries an explanation and
   gives a page structure between the modules. Measured reading width, generous line-height. ---- */
.prose { padding: var(--space-section-sm) 0; }
.prose .wrap { max-width: var(--maxw); }
.prose .sec-head { margin-bottom: 22px; }
.prose-body { max-width: 68ch; }
.prose-body .prose-lead { font-size: clamp(1.15rem, 1.7vw, 1.38rem); line-height: 1.55; color: var(--dark); font-weight: 500; margin: 0 0 20px; }
.prose-body p { font-size: 17px; line-height: 1.75; color: var(--ink, var(--muted)); margin: 0 0 18px; }
/* No `letter-spacing`: same reason as `.split-text h2`. Restating the theme default at (0,1,1) beats
   the brand's own declared tracking, so a client's blog subheadings would silently come out on the
   theme's negative tracking while every other heading used theirs. Found by auditing every heading
   rule in this file for properties the brand is supposed to own (2026-07-28). Sites that declare
   nothing still inherit --track-tight from the base h1,h2,h3 rule. */
.prose-body h3 { font-family: var(--heading-font); font-size: clamp(1.15rem, 1.6vw, 1.4rem); color: var(--dark);
  margin: 30px 0 10px; }
.prose-body > *:first-child { margin-top: 0; }
.prose-body > *:last-child { margin-bottom: 0; }
.prose-quote { margin: 26px 0; padding: 4px 0 4px 22px; border-left: 3px solid var(--accent-strong);
  font-family: var(--heading-font); font-size: clamp(1.2rem, 1.9vw, 1.5rem); line-height: 1.45; color: var(--dark); font-style: italic; }
.prose-quote cite { display: block; margin-top: 10px; font-size: 14px; font-style: normal; color: var(--accent-strong); letter-spacing: .3px; }
.prose-list { margin: 0 0 18px; padding-left: 20px; }
.prose-list li { font-size: 16.5px; line-height: 1.65; color: var(--ink, var(--muted)); margin-bottom: 9px; }
.prose-list li::marker { color: var(--accent-strong); }
/* Text + aside: prose beside a small supporting card (a stat / note), so a text-heavy section still
   feels composed rather than a wall of text. */
.prose-split .prose-grid { display: grid; grid-template-columns: 1.7fr 1fr; gap: clamp(28px, 4vw, 56px); align-items: start; }
.prose-split .prose-body { max-width: none; }
.prose-aside-card { background: var(--sage-wash, color-mix(in srgb, var(--accent) 12%, var(--light)));
  border-radius: 14px; padding: 24px 26px; position: sticky; top: 92px; }
.prose-aside-card .kicker { text-align: left; margin-bottom: 8px; }
.prose-aside-card .prose-stat { font-family: var(--display-font, var(--heading-font)); font-size: clamp(2.2rem, 4vw, 3rem);
  line-height: 1; color: var(--dark); letter-spacing: var(--track-tight); }
.prose-aside-card .prose-stat-label { font-size: 13px; color: var(--muted); margin-top: 6px; }
.prose-aside-card h4 { font-family: var(--heading-font); font-size: 1.1rem; color: var(--dark); margin: 0 0 8px; }
.prose-aside-card p { font-size: 14.5px; line-height: 1.6; color: var(--muted); margin: 0; }
@media (max-width: 760px) { .prose-split .prose-grid { grid-template-columns: 1fr; } .prose-aside-card { position: static; } }

.services { padding: var(--space-section-sm) 0; background: #fff; }
.services h2 { text-align: center; font-size: var(--fs-h2); color: var(--dark); margin: 0 0 34px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; }
.card {
  background: var(--light); border: 1px solid var(--line); border-radius: 14px;
  padding: 24px 22px;
}
.card h3 { font-size: 19px; color: var(--dark); margin: 0 0 10px; }
.card h3::after { content: ""; display: block; width: 34px; height: 2px; background: var(--accent); margin-top: 9px; }
.card p { font-size: 15px; color: var(--muted); margin: 0; }

/* Feature: image + text side by side (alternating with .flip) */
.feature { padding: 34px 0; }
.feature-inner { display: flex; align-items: center; gap: 44px; }
.feature.flip .feature-inner { flex-direction: row-reverse; }
.feature-media { flex: 1 1 50%; }
.feature-media img { width: 100%; border-radius: 14px; display: block; aspect-ratio: 4 / 3; object-fit: cover; }
.feature-text { flex: 1 1 50%; }
.feature-text h2 { font-size: var(--fs-h2); color: var(--dark); margin: 0 0 14px; }
.feature-text p { font-size: 17px; color: var(--muted); margin: 0 0 18px; }
@media (max-width: 720px) {
  .feature-inner, .feature.flip .feature-inner { flex-direction: column; gap: 22px; }
}

/* ---- Split: the text + graphic workhorse (rich text column beside a visual), alternating via flip.
   The main way to weave explanation alongside a graphic in a column structure. ---- */
.split { padding: var(--space-section-sm) 0; }
.split.bg-wash { background: var(--sage-wash, color-mix(in srgb, var(--accent) 10%, var(--light))); }
.split.bg-dark { background: var(--dark); }
.split.bg-dark .split-text .kicker { color: var(--clay, var(--accent)); }
.split.bg-dark .split-text h2, .split.bg-dark .split-lead { color: #fff; }
.split.bg-dark .split-text p { color: rgba(255,255,255,.82); }
.split.bg-dark .split-ticks li { color: rgba(255,255,255,.92); }
.split-inner { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 5vw, 72px); align-items: center; }
.split.flip .split-text { order: 2; }
.split.flip .split-media { order: 1; }
.split-text .kicker { text-align: left; margin-bottom: 12px; }
/* No `letter-spacing` here: it restated the theme default at a specificity (0,1,1) that BEAT the
   brand's own declared tracking (emitted as `h1,h2,h3,...`, (0,0,1)). A client declaring wide
   uppercase tracking got it everywhere except in a split, where their headings came out on the
   theme's NEGATIVE --track-tight instead — measured at -0.75px against Cottage's declared +2.87px on
   three of their homepage sections. Sites that declare nothing still inherit --track-tight from the
   base h1,h2,h3 rule, so nothing moves for them. Fifth instance of the same bug shape in this
   takeover: the record carries the intent and something downstream quietly overrides it. */
.split-text h2 { font-size: var(--fs-h2); color: var(--dark); margin: 0 0 14px; line-height: var(--lh-tight, 1.15); }
.split-lead { font-size: clamp(1.1rem, 1.5vw, 1.28rem); color: var(--dark); font-weight: 500; line-height: 1.5; margin: 0 0 14px; }
.split-text p { font-size: 16.5px; color: var(--muted); line-height: 1.7; margin: 0 0 14px; }
.split-ticks { list-style: none; margin: 8px 0 20px; padding: 0; }
.split-ticks li { display: flex; gap: 11px; align-items: flex-start; margin-bottom: 11px; font-size: 16px; color: var(--ink); line-height: 1.5; }
.split-ticks li .ti { color: var(--accent-strong); flex: none; font-size: 19px; margin-top: 1px; }
.split.bg-dark .split-ticks li .ti { color: var(--clay, var(--accent)); }
.split-btns { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 4px; }
/* Square (not portrait) so a two-column row doesn't stretch the page depth; balances the text column. */
.split-media img { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; border-radius: 16px; display: block; }
.split-media.wide img { aspect-ratio: 4 / 3; }   /* opt-in landscape where a shorter image suits */
.split-media .hero-mockup { margin: 0 auto; }
/* PANEL: the copy sits in a solid colour box beside the photo (`"panel": "#596a7c"`), rather than
   over a full-bleed photo. The colour is inline, so only the treatment lives here: on a dark panel
   the heading takes the warm accent and the body goes light, mirroring how the same brand behaves
   over a photo. A site wanting the panel to overlap the photo does that in its own stylesheet. */
.split-text.has-panel { padding: clamp(30px, 3.4vw, 54px); }
.split-text.has-panel h2 { color: var(--accent); }
.split-text.has-panel p, .split-text.has-panel .split-lead { color: rgba(255, 255, 255, .92); }
.split-text.has-panel .kicker { color: var(--light); }
.split-text.has-panel .btn { color: var(--light); border-color: var(--light); background: transparent; }
.split-text.has-panel .btn:hover { background: var(--light); color: var(--dark); }
.split-media .bmock { margin: 0; }
@media (max-width: 760px) { .split-inner { grid-template-columns: 1fr; gap: 30px; }
  .split.flip .split-text, .split.flip .split-media { order: 0; } }

/* On-brand abstract graphics for a split with no photo (pure CSS, decorative). */
.brandgraphic { width: 100%; aspect-ratio: 4 / 3; border-radius: 18px; background: var(--sage-wash, #E8EEE4);
  position: relative; overflow: hidden; box-shadow: 0 20px 50px rgba(40,50,44,.10); }
.split.bg-dark .brandgraphic { background: rgba(255,255,255,.06); box-shadow: none; }
/* grid: an Instagram-style feed */
.bg-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 1fr; gap: 10px; padding: 18px; }
.bg-grid .bg-cell { border-radius: 9px; background: color-mix(in srgb, var(--sage, #6E8C68) 30%, #fff); }
.bg-grid .bg-cell.on { background: var(--soft-clay, var(--accent)); }
/* cards: a stack of content/posts */
.bg-cards .bg-card { position: absolute; left: 50%; top: 50%; width: 58%; height: 68%; border-radius: 14px;
  background: #fff; box-shadow: 0 12px 30px rgba(40,50,44,.12); transform: translate(-50%,-50%); }
.bg-cards .c1 { padding: 16px; }
.bg-cards .c2 { transform: translate(-62%,-44%) rotate(-6deg); background: color-mix(in srgb, var(--sage) 22%, #fff); }
.bg-cards .c3 { transform: translate(-38%,-56%) rotate(6deg); background: color-mix(in srgb, var(--soft-clay, var(--accent)) 26%, #fff); }
.bg-cards .bg-bar { display: block; width: 40%; height: 10px; border-radius: 5px; background: var(--accent-strong); }
.bg-cards .bg-ln { display: block; height: 8px; border-radius: 4px; background: color-mix(in srgb, var(--ink) 18%, #fff); margin-top: 12px; }
.bg-cards .bg-ln.s { width: 62%; }
/* chat: an approval exchange */
.bg-chat { display: flex; flex-direction: column; justify-content: center; gap: 12px; padding: 30px; }
.bg-chat .bg-bubble { height: 34px; border-radius: 18px; }
.bg-chat .bg-bubble.in { width: 62%; background: #fff; box-shadow: 0 4px 14px rgba(40,50,44,.08); }
.bg-chat .bg-bubble.in.s { width: 44%; }
.bg-chat .bg-bubble.out { align-self: flex-end; width: auto; padding: 0 18px; display: flex; align-items: center;
  color: #fff; font-size: 14px; font-weight: 600; background: var(--accent-strong); }

.quote { text-align: center; padding: 60px 24px; }
.quote blockquote {
  font-family: var(--heading-font); font-size: 27px; font-style: italic; color: var(--dark);
  margin: 0 auto 12px; max-width: 720px;
}
.quote cite { font-style: normal; color: var(--accent-strong); font-size: 15px; letter-spacing: .3px; }

.contact { text-align: center; padding: var(--space-section-sm) 0 60px; }
.contact h2 { font-size: var(--fs-h2); color: var(--dark); margin: 0 0 12px; }
.contact p { font-size: 18px; color: var(--muted); max-width: 560px; margin: 0 auto 22px; }
.contact .details { font-size: 16px; color: var(--ink); line-height: 2; }
.contact .details a { color: var(--dark); text-decoration: none; }

/* Footer */
.site-footer { background: var(--dark); color: var(--light); text-align: center; padding: 40px 24px; margin-top: 0; border-top: 1px solid rgba(255, 255, 255, .12); }
.site-footer .fname { font-family: var(--heading-font); font-size: 20px; margin-bottom: 6px; }
.site-footer .fmeta { font-size: 14px; opacity: .85; }
.site-footer .fnav { margin: 16px 0 10px; }
.site-footer .fnav a { color: var(--light); opacity: .9; text-decoration: none; margin: 0 12px; font-size: 14px; }
.site-footer .fnav a:hover { opacity: 1; text-decoration: underline; }
.site-footer .fcontact { font-size: 13px; opacity: .72; }

/* Hamburger nav toggle: hidden on desktop, shown at 1024px and below (tablet + phone). Three CSS bars
   that morph to an X when open. Wired by enhance.js (aria-expanded + .nav-open); degrades to a plain row
   no-JS.

   The breakpoint was 860px, tuned when headings ran in a narrow Avenir-ish stack. Self-hosted Poppins
   (2026-07-25) is a wider face: measured on phatdigital.uk, the logo plus a 7-item nav plus the CTA
   needs a 974px viewport, so between 861px and 974px the "Get a free sample" button wrapped onto a
   second line and overlapped the row. 1024px clears it, and a tablet gets the same clean panel a
   phone does.

   Headroom is only ~50px. If a client's nav grows past 7 items, re-measure (set .nav to
   width:max-content and read its box) and raise this number; a media query cannot read a CSS
   variable, so it is a real constant rather than a token. */
.nav-toggle { display: none; }
.nav-toggle-bars, .nav-toggle-bars::before, .nav-toggle-bars::after {
  display: block; width: 24px; height: 2px; background: var(--dark); border-radius: 2px;
  transition: transform .22s ease, opacity .22s ease; }
.nav-toggle-bars { position: relative; }
.nav-toggle-bars::before, .nav-toggle-bars::after { content: ""; position: absolute; left: 0; }
.nav-toggle-bars::before { top: -7px; }
.nav-toggle-bars::after { top: 7px; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::before { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::after { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 1024px) {
  .nav-toggle { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px;
    padding: 0; margin: 0; background: none; border: none; cursor: pointer; z-index: 2; }
  .site-header { position: relative; }
  /* Nav collapses into a dropdown panel under the bar; hidden until the toggle opens it. No-JS: the
     :not clause keeps it a normal wrapped row so links stay reachable without the toggle script. */
  .site-header .nav { position: absolute; top: 100%; left: 0; right: 0; display: flex; flex-direction: column; align-items: stretch;
    gap: 2px; padding: 10px 16px 16px; background: var(--light);
    box-shadow: 0 12px 30px rgba(0,0,0,.10); border-top: 1px solid var(--line);
    max-height: 0; overflow: hidden; opacity: 0; visibility: hidden;
    transition: max-height .28s ease, opacity .2s ease, visibility .2s; }
  .site-header .nav.nav-open { max-height: 80vh; opacity: 1; visibility: visible; overflow: auto; }
  .site-header .nav a { margin: 0; padding: 13px 8px; font-size: 17px; border-bottom: 1px solid var(--line); }
  .site-header .nav a:last-of-type { border-bottom: none; }
  .site-header .nav .nav-cta { margin: 12px 0 0; text-align: center; }
  /* Dropdown items sit inline (expanded) inside the mobile panel, indented under the parent. */
  .site-header .nav .nav-item { position: static; margin: 0; display: block; }
  .site-header .nav .nav-item .nav-parent { padding: 13px 8px; border-bottom: 1px solid var(--line); }
  .site-header .nav .nav-parent .nav-caret { display: none; }
  .site-header .nav .nav-menu { position: static; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: none; background: transparent; border-radius: 0; padding: 4px 0 4px 16px; min-width: 0; }
  .site-header .nav .nav-menu a { padding: 11px 8px; font-size: 15.5px; border-bottom: 1px solid var(--line); }
  /* No-JS fallback: if the toggle never got wired, show the nav as a simple wrapped row. */
  html:not(.js) .site-header .nav { position: static; max-height: none; opacity: 1; visibility: visible;
    flex-direction: row; flex-wrap: wrap; box-shadow: none; padding: 8px 0 0; }
  html:not(.js) .nav-toggle { display: none; }
  body.nav-locked { overflow: hidden; }
}
@media (max-width: 640px) {
  .hero h1 { font-size: 33px; }
}

/* ---- Step C section types: occasions, reviews, delivery, hours, map ---- */

/* Occasions grid (a florist's primary navigation: browse by occasion) */
.occasions { padding: var(--space-section-sm) 0; }
.occasions h2 { text-align: center; font-size: var(--fs-h2); color: var(--dark); margin: 0 0 30px; }
.occasion-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.occasion-card {
  position: relative; display: block; aspect-ratio: 4 / 3; border-radius: 14px;
  overflow: hidden; text-decoration: none; background: var(--dark);
}
.occasion-card img, .occasion-card picture { width: 100%; height: 100%; display: block; }
.occasion-card img { object-fit: cover; transition: transform .4s ease; }
.occasion-card:hover img { transform: scale(1.06); }
.occasion-card::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.05) 40%, rgba(0,0,0,.55));
}
.occasion-label {
  position: absolute; left: 16px; bottom: 14px; z-index: 1; color: #fff;
  font-family: var(--heading-font); font-size: 20px; font-weight: 600;
  text-shadow: 0 1px 12px rgba(0,0,0,.45);
}
@media (max-width: 720px) { .occasion-grid { grid-template-columns: repeat(2, 1fr); } }

/* Reviews (real testimonials, placed near a CTA) */
.reviews { padding: var(--space-section-sm) 0; background: #fff; }
.reviews h2 { text-align: center; font-size: var(--fs-h2); color: var(--dark); margin: 0 0 34px; }
.review-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; }
.review {
  margin: 0; background: var(--light); border: 1px solid var(--line);
  border-radius: 14px; padding: 24px 22px;
}
.review .stars { color: var(--accent-strong); letter-spacing: 2px; font-size: 15px; margin-bottom: 10px; }
.review blockquote { margin: 0 0 16px; font-size: clamp(16.5px, 1.5vw, 18.5px); color: var(--ink); line-height: 1.55; font-family: var(--display-font); }
/* Featured review: a single large pull-quote, first-class social proof (reviews layout:"featured"). */
.reviews.featured .review-grid { grid-template-columns: 1fr; max-width: 820px; margin: 0 auto; }
.reviews.featured .review { border: none; background: transparent; text-align: center; padding: 0; }
.reviews.featured .review blockquote { font-size: clamp(1.4rem, 2.6vw, 2.1rem); line-height: 1.35; color: var(--dark); letter-spacing: var(--track-tight); }
.reviews.featured .review .stars { font-size: 18px; }
.review figcaption { font-size: 14px; color: var(--muted); font-weight: 600; }
.review .review-source { font-weight: 400; margin-left: 6px; opacity: .8; }
.reviews-cta { text-align: center; margin-top: 30px; }

/* Delivery (top florist conversion factor: show it clearly and up front) */
.delivery { padding: var(--space-section-sm) 0; text-align: center; }
.delivery h2 { font-size: var(--fs-h2); color: var(--dark); margin: 0 0 26px; }
.delivery-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 18px; margin-bottom: 20px;
}
.delivery-item {
  background: var(--light); border: 1px solid var(--line); border-radius: 14px; padding: 22px 18px;
}
.delivery-item h3 { font-size: 17px; color: var(--dark); margin: 0 0 8px; }
.delivery-item p { font-size: 15px; color: var(--muted); margin: 0; }
.delivery-note { font-size: 15px; color: var(--muted); max-width: 620px; margin: 0 auto 20px; }

/* Opening hours */
.hours { padding: 40px 0; }
.hours h2 { text-align: center; font-size: 26px; color: var(--dark); margin: 0 0 22px; }
.hours-table { max-width: 460px; margin: 0 auto; width: 100%; border-collapse: collapse; }
.hours-table th, .hours-table td { padding: 11px 14px; border-bottom: 1px solid var(--line); font-size: 16px; }
.hours-table th { text-align: left; font-weight: 600; color: var(--dark); }
.hours-table td { text-align: right; color: var(--muted); }
.hours-note { text-align: center; font-size: 14px; color: var(--muted); margin: 16px auto 0; max-width: 460px; }

/* Map embed */
.map { padding: 20px 0 0; }
.map iframe { display: block; }

/* Click-to-load map facade (privacy + CWV: no Google request until asked) */
.map-facade {
  display: flex; align-items: center; gap: 16px; height: 200px; padding: 0 28px; text-decoration: none;
  background: linear-gradient(120deg, color-mix(in srgb, var(--dark) 8%, var(--light)),
              color-mix(in srgb, var(--accent) 10%, var(--light)));
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); cursor: pointer;
}
.map-pin { flex: none; width: 48px; height: 48px; border-radius: 50%; background: var(--accent-strong); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 24px; }
.map-facade-text { display: flex; flex-direction: column; }
.map-facade-text b { font-family: var(--heading-font); font-size: 18px; color: var(--dark); }
.map-facade-text span { font-size: 14px; color: var(--muted); }
.map-load { margin-left: auto; flex: none; background: var(--accent-strong); color: #fff; font-family: var(--heading-font); font-weight: 600; font-size: 14px; padding: 10px 20px; border-radius: 40px; transition: background .15s ease; }
.map-facade:hover .map-load { background: var(--dark); }
@media (max-width: 560px) { .map-facade { flex-wrap: wrap; height: auto; padding: 22px; } .map-load { margin-left: 0; } }

/* ---- Extended section types: kicker/sub, richer hero, stats, steps, tiles, founder, banner ---- */

.kicker {
  font-family: var(--heading-font); font-weight: 600; font-size: 12px; letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--accent-strong); text-align: center; margin-bottom: 8px;
}
.section-sub { text-align: center; font-size: 16px; color: var(--muted); max-width: 640px; margin: 0 auto 26px; }
.stats h2, .steps h2, .tiles-sec h2 { text-align: center; font-size: var(--fs-h2); color: var(--dark); margin: 0 0 6px; }

/* Richer hero: kicker + two buttons */
.hero .kicker { margin-bottom: 12px; }
.hero-btns { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.btn-ghost { background: transparent; color: var(--dark); border: 1.5px solid var(--line); }
.btn-ghost:hover { background: var(--dark); color: #fff; border-color: var(--dark); }
.hero.has-image .btn-ghost { color: #fff; border-color: rgba(255, 255, 255, .6); }
.hero.has-image .btn-ghost:hover { background: #fff; color: var(--dark); }

/* Stats band (headline numbers, illustration-led) */
.stats { padding: 30px 0; }
.stats-band {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
  background: var(--dark); border-radius: 16px; padding: 30px 20px;
}
.stat-cell { text-align: center; padding: 0 10px; position: relative; }
.stat-cell:not(:last-child)::after {
  content: ""; position: absolute; right: 0; top: 14%; height: 72%; width: 1px; background: rgba(255, 255, 255, .15);
}
.stat-ic { color: var(--accent); font-size: 22px; margin-bottom: 8px; } /* on the dark stats-band, keep the brand accent (accent-strong is for light bgs) */

/* Link-in-bio hub (a bare page: no site header/footer, mobile-first) */
body.bare-page { background: var(--light); }
.linkhub { min-height: 100vh; display: flex; align-items: flex-start; justify-content: center; padding: 52px 20px 40px; }
.lh-card { width: 100%; max-width: 480px; text-align: center; }
.lh-avatar { width: 96px; height: 96px; border-radius: 50%; object-fit: cover; margin: 0 auto 18px; display: block; box-shadow: 0 4px 18px rgba(0,0,0,.10); }
.lh-mono { display: flex; align-items: center; justify-content: center; background: var(--accent-strong); color: #fff; font-family: var(--heading-font); font-size: 40px; line-height: 1; }
.lh-name { font-size: 26px; color: var(--dark); margin: 0 0 6px; }
.lh-tag { color: var(--muted); font-size: 15px; margin: 0 auto 26px; max-width: 380px; }
.lh-links { display: flex; flex-direction: column; gap: 12px; }
.lh-link { display: flex; align-items: center; justify-content: center; gap: 10px; background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 15px 18px; color: var(--dark); text-decoration: none; font-family: var(--heading-font); font-weight: 600; font-size: 16px; transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease; }
.lh-link:hover { transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,.08); border-color: var(--accent); }
.lh-link .ti { font-size: 19px; color: var(--accent-strong); }
.lh-link.primary { background: var(--accent-strong); color: #fff; border-color: var(--accent-strong); }
.lh-link.primary .ti { color: #fff; }
.lh-foot { margin-top: 28px; font-size: 12px; color: var(--muted); }
.lh-foot a { color: var(--muted); }
.lh-empty { color: var(--muted); }
.stat-num { font-family: var(--heading-font); font-weight: 700; font-size: 30px; color: #fff; line-height: 1; }
.stat-lab { font-size: 13px; color: rgba(255, 255, 255, .82); margin-top: 8px; line-height: 1.4; }
/* The provenance line under a GENERATED case-study figure (proof.py): how it was measured
   and when. Deliberately quiet — it must be readable without competing with the number, and
   it must never be optional, because a figure about a real business with no method beside it
   is exactly what the generated-not-typed rule exists to prevent. */
.stat-note { font-size: 11px; color: rgba(255, 255, 255, .62); margin-top: 6px;
  line-height: 1.35; max-width: 30ch; margin-inline: auto; }
@media (max-width: 640px) {
  .stats-band { grid-template-columns: 1fr 1fr; gap: 24px 10px; }
  .stat-cell:nth-child(2)::after { display: none; }
}

/* Steps (how it works) */
.steps { padding: var(--space-section-sm) 0; }
.steps-flow { display: flex; align-items: stretch; gap: 14px; justify-content: center; margin-top: 24px; }
.step { flex: 1 1 0; background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 22px 18px; text-align: center; }
.step-ic {
  width: 48px; height: 48px; margin: 0 auto 12px; border-radius: 12px; background: var(--light);
  display: flex; align-items: center; justify-content: center; color: var(--dark); font-size: 22px;
}
.step-n { font-family: var(--heading-font); font-weight: 700; color: var(--accent-strong); font-size: 20px; }
.step h3 { font-size: 17px; color: var(--dark); margin: 0 0 6px; }
.step p { font-size: 14px; color: var(--muted); margin: 0; }
.step-arrow { display: flex; align-items: center; color: var(--accent-strong); font-size: 24px; flex: none; }
@media (max-width: 720px) {
  .steps-flow { flex-direction: column; }
  .step-arrow { transform: rotate(90deg); justify-content: center; }
}

/* Tiles (icon + title + desc benefit grid) */
.tiles-sec { padding: var(--space-section-sm) 0; }
.tile-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; max-width: 720px; margin: 24px auto 0; }
.tile-card { display: flex; gap: 14px; align-items: flex-start; background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 20px; }
.tile-ic {
  flex: none; width: 42px; height: 42px; border-radius: 10px; background: var(--light);
  display: flex; align-items: center; justify-content: center; color: var(--dark); font-size: 20px;
}
.tile-body h3 { font-size: 16px; color: var(--dark); margin: 0 0 4px; }
.tile-body p { font-size: 14px; color: var(--muted); margin: 0; line-height: 1.5; }
.tiles-link { display: block; text-align: center; font-family: var(--heading-font); font-weight: 600; color: var(--accent-strong); margin-top: 24px; text-decoration: none; }
@media (max-width: 640px) { .tile-grid { grid-template-columns: 1fr; } }
/* Tiles layout variation (opt-in): column count + a stacked "rows" layout. */
.tile-grid.tg-cols-3 { grid-template-columns: repeat(3, 1fr); max-width: 1000px; }
.tile-grid.tg-cols-4 { grid-template-columns: repeat(4, 1fr); max-width: none; }
.tile-grid.tiles-rows { grid-template-columns: 1fr; max-width: 840px; }
.tile-grid.tiles-rows .tile-card { padding: 22px 26px; }
/* Editorial thin-rule feature blocks (flyhyer): a rule above each, no card chrome, bold + light. */
.tile-grid.tiles-rule { max-width: none; gap: 30px 34px; }
.tile-grid.tiles-rule .tile-card { background: transparent; border: none; border-top: 1.5px solid var(--dark); border-radius: 0; padding: 16px 0 0; box-shadow: none; display: block; }
.tile-grid.tiles-rule .tile-ic { width: auto; height: auto; background: none; margin-bottom: 8px; color: var(--accent-strong); }
.tile-grid.tiles-rule .tile-card:hover { transform: none; }
@media (max-width: 900px) { .tile-grid.tg-cols-3, .tile-grid.tg-cols-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) { .tile-grid.tg-cols-3, .tile-grid.tg-cols-4 { grid-template-columns: 1fr; } }

/* Founder (owner intro with a round photo) */
.founder { padding: var(--space-section-sm) 0; }
.founder-inner { display: flex; gap: clamp(28px, 4vw, 52px); align-items: center; }
.founder-media { flex: none; }
.founder-media img, .founder-media picture {
  width: clamp(150px, 20vw, 230px); height: clamp(150px, 20vw, 230px);
  border-radius: 50%; object-fit: cover; display: block;
}
.founder-text h2 { font-size: var(--fs-h2); color: var(--dark); margin: 0 0 14px; }
.founder-text p { font-size: var(--fs-lead); color: var(--muted); margin: 0 0 12px; max-width: 56ch; line-height: 1.6; }
.founder-link { font-family: var(--heading-font); font-weight: 600; color: var(--accent-strong); text-decoration: none; font-size: 14px; }
@media (max-width: 640px) { .founder-inner { flex-direction: column; text-align: center; } }

/* Hero background bands (themed off the brand via color-mix) */
.hero.bg-wash { background: color-mix(in srgb, var(--dark) 9%, #fff); }
.hero.bg-dark { background: var(--dark); }
.hero.bg-dark h1, .hero.bg-dark .hero-copy p { color: #fff; }
.hero.bg-dark .btn-ghost { color: #fff; border-color: rgba(255, 255, 255, .6); }

/* Split hero: copy alongside a phone mockup */
.hero.split { text-align: left; padding: 60px 24px 68px; }
.hero.split .hero-inner { display: flex; align-items: center; gap: 44px; }
.hero.split .hero-copy { flex: 1 1 auto; }
.hero.split .kicker { text-align: left; }
.hero.split h1 { margin: 0 0 16px; max-width: 520px; }
.hero.split .hero-copy p { font-size: 18px; color: var(--muted); max-width: 460px; margin: 0 0 26px; }
.hero.split .hero-btns { justify-content: flex-start; }

/* Photo hero: a real framed photograph beside the text, with an optional floating post card. */
.hero-photo .hero-inner { align-items: center; }
.hero-photo-media { flex: 0 1 46%; position: relative; }
.hero-photo-media > img, .hero-photo-media > picture img { width: 100%; height: auto; aspect-ratio: 4 / 5;
  object-fit: cover; border-radius: 20px; box-shadow: 0 24px 60px rgba(40, 50, 44, .20); display: block; }
.hero-postcard { position: absolute; left: -22px; bottom: 26px; width: 210px; margin: 0; background: #fff;
  border-radius: 14px; padding: 12px 14px; box-shadow: 0 18px 44px rgba(40, 50, 44, .22); }
.hero-postcard .hpc-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.hero-postcard .hpc-av { width: 26px; height: 26px; border-radius: 50%; background: var(--accent-strong);
  color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px; }
.hero-postcard .hpc-handle { font-family: var(--heading-font); font-weight: 600; font-size: 13px; color: var(--ink); }
.hero-postcard .hpc-cap { font-size: 13px; line-height: 1.45; color: var(--slate, var(--muted)); }
@media (max-width: 820px) {
  .hero-photo .hero-inner { flex-direction: column; align-items: flex-start; }
  .hero-photo-media { flex-basis: auto; width: 100%; margin-top: 8px; }
  .hero-postcard { left: auto; right: 14px; width: 190px; }
}

/* Phone mockup (illustration-led social post) */
.hero-mockup { flex: none; }
.phone { width: 204px; height: 404px; background: #1c211b; border-radius: 30px; padding: 8px; box-shadow: 0 16px 40px rgba(0, 0, 0, .22); }
.phone-screen { width: 100%; height: 100%; background: #fff; border-radius: 23px; overflow: hidden; display: flex; flex-direction: column; }
.pm-top { display: flex; align-items: center; gap: 7px; padding: 11px 12px; }
.pm-av { width: 24px; height: 24px; border-radius: 50%; background: color-mix(in srgb, var(--dark) 30%, #fff); display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 11px; color: var(--dark); }
.pm-handle { font-weight: 500; font-size: 12px; color: var(--ink); }
.pm-photo { flex: 1; position: relative; overflow: hidden; background: color-mix(in srgb, var(--accent) 16%, #fff); }
.pm-b1, .pm-b2, .pm-b3 { position: absolute; border-radius: 50%; }
.pm-b1 { width: 92px; height: 92px; background: var(--accent); opacity: .88; top: 24px; left: 26px; }
.pm-b2 { width: 58px; height: 58px; background: color-mix(in srgb, var(--accent) 55%, #fff); top: 86px; left: 104px; }
.pm-b3 { width: 44px; height: 44px; background: color-mix(in srgb, var(--dark) 55%, #fff); top: 42px; left: 132px; }
.pm-actions { display: flex; gap: 13px; padding: 9px 12px 4px; font-size: 16px; color: var(--ink); }
.pm-cap { padding: 0 12px 12px; font-size: 11px; line-height: 1.4; color: var(--ink); }
.pm-cap b { font-weight: 600; }
@media (max-width: 720px) {
  .hero.split .hero-inner { flex-direction: column; text-align: center; }
  .hero.split .kicker, .hero.split .hero-btns { text-align: center; justify-content: center; }
  .hero.split h1, .hero.split .hero-copy p { margin-left: auto; margin-right: auto; }
}

/* Nav CTA button in the header */
/* The `!important` this used to carry is gone, and correctly: the `.nav a` rules above now exclude
   `.nav-cta`, so nothing competes and the colour is reachable by a brand's own button token again.
   Removing the !important WITHOUT that exclusion is what broke tracy's live header on 2026-07-28. */
.nav-cta { margin-left: 26px; background: var(--accent-strong); color: #fff; padding: 8px 16px; border-radius: 22px; font-family: var(--heading-font); font-weight: 600; font-size: 13px; text-decoration: none; }
.nav-cta:hover { background: var(--dark); }

/* Highlighted "process" step panel with chips */
.step.step-hl { flex: 1.5 1 0; background: var(--dark); color: #fff; text-align: left; }
.step-hl-top { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.step-mark { width: 30px; height: 30px; border-radius: 8px; background: color-mix(in srgb, var(--dark) 55%, #fff); color: #fff; display: flex; align-items: center; justify-content: center; font-family: var(--heading-font); font-weight: 700; font-size: 11px; flex: none; }
.step-hl h3 { color: #fff; margin: 0; font-size: 16px; }
.step-hl-sub { color: rgba(255, 255, 255, .7); font-size: 12px; margin: 2px 0 0; }
.step-chips { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.step-chip { display: flex; align-items: center; gap: 8px; background: rgba(255, 255, 255, .09); border-radius: 9px; padding: 9px 11px; font-size: 12px; color: #eef2ea; }
.step-chip .ti { color: color-mix(in srgb, var(--accent) 60%, #fff); font-size: 15px; flex: none; }
@media (max-width: 720px) { .step.step-hl { flex: 1 1 auto; } }

/* Callout: empathy / problem band (optional quiet-phone illustration + bold statement) */
.callout { padding: 44px 0; }
.callout-inner { display: flex; align-items: center; gap: 30px; max-width: 780px; }
.callout-illus { flex: none; }
.qphone { width: 150px; background: #fff; border: 1px solid var(--line); border-radius: 16px; padding: 10px; box-shadow: 0 8px 22px rgba(0, 0, 0, .08); }
.qp-top { display: flex; align-items: center; gap: 7px; margin-bottom: 9px; }
.qp-av { width: 22px; height: 22px; border-radius: 50%; background: color-mix(in srgb, var(--dark) 25%, #fff); display: block; }
.qp-line { height: 7px; width: 62px; border-radius: 4px; background: #e2e5df; display: block; }
.qp-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 4px; opacity: .45; }
.qp-grid span { aspect-ratio: 1 / 1; border-radius: 3px; background: #dfe3da; display: block; }
.qp-stamp { margin-top: 10px; font-size: 10.5px; color: var(--muted); display: flex; align-items: center; justify-content: center; gap: 5px; background: var(--light); border-radius: 20px; padding: 6px 8px; }
.callout-text { font-family: var(--heading-font); font-weight: 600; font-size: 21px; line-height: 1.4; color: var(--dark); margin: 0; }
.callout-emph { color: var(--accent-strong); }
@media (max-width: 640px) { .callout-inner { flex-direction: column; text-align: center; } }

/* Blog: article body (constrained reading width) */
.article { padding: 40px 0 20px; }
.article-wrap { max-width: 720px; margin: 0 auto; padding: 0 24px; }
.article-wrap h1 { font-size: 38px; color: var(--dark); margin: 0 0 10px; line-height: 1.15; }
.article-meta { font-size: 14px; color: var(--muted); margin: 0 0 24px; }
.article-hero { margin: 0 0 28px; }
.article-hero img, .article-hero picture { width: 100%; border-radius: 14px; display: block; }
.article-wrap h2 { font-size: 26px; color: var(--dark); margin: 34px 0 12px; }
.article-wrap h3 { font-size: 20px; color: var(--dark); margin: 26px 0 10px; }
.article-wrap p { font-size: 18px; color: var(--ink); line-height: 1.75; margin: 0 0 18px; }
.article-wrap ul { font-size: 18px; color: var(--ink); line-height: 1.7; margin: 0 0 18px; padding-left: 22px; }
.article-wrap li { margin: 0 0 8px; }
.article-wrap a { color: var(--accent-strong); }
.article-fig { margin: 26px 0; }
.article-fig img, .article-fig picture { width: 100%; border-radius: 12px; display: block; }
.article-fig figcaption { font-size: 13px; color: var(--muted); text-align: center; margin-top: 8px; }
.article-cta { margin: 36px 0 8px; text-align: center; }

/* Blog: index of posts */
.blog-index { padding: var(--space-section-sm) 0; }
.blog-index h2 { text-align: center; font-size: var(--fs-h2); color: var(--dark); margin: 0 0 30px; }
/* Article/blog library: a 3-up grid of cards (cut page depth), each with an on-brand cover to bring it to life. */
.post-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 900px) { .post-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .post-grid { grid-template-columns: 1fr; } }
.post-card { display: flex; flex-direction: column; background: #fff; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; text-decoration: none; transition: border-color .15s ease, transform .18s ease, box-shadow .18s ease; }
.post-card.has-cover { padding: 0; }
.post-card:not(.has-cover) { padding: 22px; }
.post-card:hover { border-color: var(--accent-strong); transform: translateY(-3px); box-shadow: 0 14px 30px rgba(40,50,44,.09); }
.post-cover { aspect-ratio: 3 / 2; overflow: hidden; }
.post-cover img, .post-cover picture { width: 100%; height: 100%; object-fit: cover; display: block; }
.post-body { padding: 18px 20px 20px; }
.post-card h3 { font-size: 18px; color: var(--dark); margin: 6px 0 6px; line-height: 1.25; }
.post-date { font-size: 13px; color: var(--muted); }
.post-card p { font-size: 14.5px; color: var(--muted); margin: 8px 0 0; line-height: 1.55; }
.post-empty { text-align: center; color: var(--muted); }

/* Shop / product-listing grid (the store view; reusable for any ecommerce client) */
.shop { padding: var(--space-section-sm) 0; }
.shop h2 { text-align: center; font-size: var(--fs-h2); color: var(--dark); margin: 0 0 6px; }
.shop-note {
  text-align: center; font-size: 14px; color: var(--muted); max-width: 560px;
  margin: 0 auto 30px; background: var(--light); border: 1px solid var(--line);
  border-radius: 30px; padding: 10px 20px;
}
.shop-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.shop-card {
  background: #fff; border: 1px solid var(--line); border-radius: 14px; overflow: hidden;
  display: flex; flex-direction: column; transition: transform .15s ease, box-shadow .15s ease;
}
.shop-card:hover { transform: translateY(-3px); box-shadow: 0 12px 28px rgba(0, 0, 0, .10); }
.shop-media { position: relative; aspect-ratio: 4 / 5; overflow: hidden; }
.shop-media img, .shop-media picture { width: 100%; height: 100%; object-fit: cover; display: block; }
.shop-badge {
  position: absolute; top: 12px; left: 12px; z-index: 1; background: rgba(0, 0, 0, .62); color: #fff;
  font-size: 11px; letter-spacing: 1px; text-transform: uppercase; padding: 5px 11px; border-radius: 20px;
}
.shop-body { padding: 18px 18px 20px; display: flex; flex-direction: column; flex: 1; }
.shop-tag {
  font-family: var(--heading-font); font-size: 11px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--accent-strong); margin-bottom: 6px;
}
.shop-title { font-size: 18px; color: var(--dark); margin: 0 0 6px; }
.shop-desc { font-size: 14px; color: var(--muted); margin: 0 0 16px; line-height: 1.55; }
.shop-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: auto; }
.shop-price { font-family: var(--heading-font); font-weight: 700; font-size: 19px; color: var(--dark); }
.shop-btn {
  background: var(--accent-strong); color: #fff; text-decoration: none; font-size: 13px; font-weight: 600;
  padding: 9px 18px; border-radius: 22px; white-space: nowrap; transition: background .15s ease;
}
.shop-btn:hover { background: var(--dark); }
@media (max-width: 860px) { .shop-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .shop-grid { grid-template-columns: 1fr; } }

/* ============================================================================
   DYNAMISM LAYER — motion + micro-interactions (progressive enhancement)
   All effects are additive: without JS the `.js` class is absent, so reveal
   targets stay fully visible and nothing is hidden. Motion is disabled wholesale
   by the prefers-reduced-motion block above (transition + animation none). Colours
   come from the brand variables, so every effect themes per client + per variant.
   ============================================================================ */

/* (No body overflow clipping: the sticky-header backdrop spans the header box, not the
   viewport, so nothing overflows horizontally. Clipping here would also create a containing
   block that mis-anchors the position:fixed lightbox + back-to-top button.) */

/* 1. Scroll reveal — hidden ONLY when JS is present (so no-JS shows everything). */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .7s cubic-bezier(.16,.8,.3,1), transform .7s cubic-bezier(.16,.8,.3,1);
  will-change: opacity, transform;
}
.js [data-reveal].is-visible { opacity: 1; transform: none; }
/* Reduced motion: never hide reveal targets, even before enhance.js runs. */
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1 !important; transform: none !important; }
}
/* A gentle stagger for grids revealed as one section (cards flow in in sequence). */
.js [data-reveal].is-visible .grid > *,
.js [data-reveal].is-visible .tile-grid > *,
.js [data-reveal].is-visible .review-grid > *,
.js [data-reveal].is-visible .occasion-grid > *,
.js [data-reveal].is-visible .tiles > *,
.js [data-reveal].is-visible .shop-grid > *,
.js [data-reveal].is-visible .post-grid > * {
  animation: pd-rise .6s both;
}
.js [data-reveal].is-visible .grid > *:nth-child(2),
.js [data-reveal].is-visible .tile-grid > *:nth-child(2),
.js [data-reveal].is-visible .review-grid > *:nth-child(2),
.js [data-reveal].is-visible .occasion-grid > *:nth-child(2),
.js [data-reveal].is-visible .tiles > *:nth-child(2),
.js [data-reveal].is-visible .shop-grid > *:nth-child(2),
.js [data-reveal].is-visible .post-grid > *:nth-child(2) { animation-delay: .08s; }
.js [data-reveal].is-visible .grid > *:nth-child(3),
.js [data-reveal].is-visible .tile-grid > *:nth-child(3),
.js [data-reveal].is-visible .review-grid > *:nth-child(3),
.js [data-reveal].is-visible .occasion-grid > *:nth-child(3),
.js [data-reveal].is-visible .tiles > *:nth-child(3),
.js [data-reveal].is-visible .shop-grid > *:nth-child(3),
.js [data-reveal].is-visible .post-grid > *:nth-child(3) { animation-delay: .16s; }
.js [data-reveal].is-visible .grid > *:nth-child(n+4),
.js [data-reveal].is-visible .tile-grid > *:nth-child(n+4),
.js [data-reveal].is-visible .review-grid > *:nth-child(n+4),
.js [data-reveal].is-visible .occasion-grid > *:nth-child(n+4),
.js [data-reveal].is-visible .tiles > *:nth-child(n+4),
.js [data-reveal].is-visible .shop-grid > *:nth-child(n+4),
.js [data-reveal].is-visible .post-grid > *:nth-child(n+4) { animation-delay: .24s; }
@keyframes pd-rise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

/* 2. Sticky, shrinking header with a brand-themed frosted backdrop that fades in on scroll.
   The backdrop spans the header's own box (inset:0, never overflows), so it reads full-width on
   the variants that make the header full-width and centred on the base theme. --light is the
   brand's page colour, so the bar is cream on light themes and near-black on dark ones. */
.site-header {
  position: sticky; top: 0; z-index: 100;
  transition: padding .25s ease;
}
.site-header::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: color-mix(in srgb, var(--light) 90%, transparent);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 var(--line), 0 6px 24px rgba(0, 0, 0, .06);
  opacity: 0; transition: opacity .3s ease;
}
.site-header.is-scrolled::before { opacity: 1; }
.site-header.is-scrolled { padding-top: 12px; padding-bottom: 12px; }

/* 3. Hover micro-interactions — lift + accent response on interactive cards.
   (Reduced-motion disables the transition via the block above.) */
.card, .tile-card, .review, .delivery-item, .step, .post-card, .occasion-card, .shop-card {
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.card:hover, .tile-card:hover, .delivery-item:hover, .step:hover {
  transform: translateY(-3px); box-shadow: 0 10px 26px rgba(0, 0, 0, .07); border-color: var(--accent);
}
.review:hover { transform: translateY(-3px); box-shadow: 0 10px 26px rgba(0, 0, 0, .07); }
.btn, .nav-cta, .shop-btn, .banner-btn { transition: transform .15s ease, background .15s ease, box-shadow .15s ease; }
.btn:hover, .nav-cta:hover, .shop-btn:hover, .banner-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0, 0, 0, .14); }
.btn:active, .nav-cta:active, .shop-btn:active, .banner-btn:active { transform: translateY(0); }
/* Animated underline on nav links (grows from the start on hover / active). */
.nav a:not(.nav-cta) { position: relative; }
.nav a:not(.nav-cta)::after {
  content: ""; position: absolute; left: 0; bottom: -4px; height: 2px; width: 100%;
  background: var(--accent-strong); transform: scaleX(0); transform-origin: left;
  transition: transform .22s ease;
}
.nav a:not(.nav-cta):hover::after, .nav a:not(.nav-cta).active::after { transform: scaleX(1); }

/* 4. Back-to-top button (JS-shown after scrolling; hidden entirely without JS). */
.to-top {
  position: fixed; right: 22px; bottom: 22px; z-index: 90;
  width: 46px; height: 46px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--accent-strong); color: #fff; font-size: 22px; line-height: 1;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .18);
  opacity: 0; visibility: hidden; transform: translateY(12px);
  transition: opacity .25s ease, transform .25s ease, visibility .25s, background .15s ease;
}
.to-top.is-shown { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { background: var(--dark); }
.to-top { display: none; }         /* hidden without JS (it can't do anything there) */
.js .to-top { display: block; }

/* ---- Interactive gallery: tap-to-enlarge lightbox + occasion/style filtering ---- */

/* Tile becomes a link (opens the full image without JS). A zoom cue fades in on hover/focus. */
a.tile { display: block; position: relative; cursor: zoom-in; }
a.tile:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.tile-zoom {
  position: absolute; right: 10px; bottom: 10px; z-index: 2;
  width: 34px; height: 34px; border-radius: 50%;
  background: rgba(0, 0, 0, .5); color: #fff; font-size: 18px;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; transform: scale(.8); transition: opacity .2s ease, transform .2s ease;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
a.tile:hover .tile-zoom, a.tile:focus-visible .tile-zoom { opacity: 1; transform: scale(1); }

/* Filter bar (chips). Inert + still shown without JS is fine — but the click behaviour needs JS,
   so we only render it when categories exist; keyboard + aria-pressed handled by enhance.js. */
.filter-bar { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin: 0 0 26px; }
.filter-chip {
  border: 1px solid var(--line); background: #fff; color: var(--ink); cursor: pointer;
  font-family: var(--body-font); font-size: 14px; font-weight: 600;
  padding: 8px 18px; border-radius: 40px; transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.filter-chip:hover { border-color: var(--accent-strong); color: var(--accent-strong); }
.filter-chip[aria-pressed="true"] { background: var(--accent-strong); color: #fff; border-color: var(--accent-strong); }
.tile.is-hidden { display: none !important; }
.post-card.is-hidden { display: none !important; }
.post-cat { display: inline-block; font-size: 11.5px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--accent-strong); margin-bottom: 8px; }

/* Breadcrumbs (pairs with BreadcrumbList schema) */
.breadcrumbs ol { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 0; list-style: none; margin: 0; padding: 16px 24px 0; font-size: 13px; color: var(--muted); }
.breadcrumbs li { display: flex; align-items: center; }
.breadcrumbs li:not(:last-child)::after { content: "/"; margin: 0 9px; color: var(--line); }
.breadcrumbs a { color: var(--muted); text-decoration: none; }
.breadcrumbs a:hover { color: var(--accent-strong); }
.breadcrumbs [aria-current="page"] { color: var(--dark); font-weight: 600; }

/* Article byline + table of contents */
.article-byline { font-size: 14.5px; color: var(--muted); margin: -4px 0 20px; }
.article-byline a { color: var(--accent-strong); font-weight: 600; text-decoration: none; }
.article-byline a:hover { text-decoration: underline; }
.art-rev { color: var(--muted); }
.article-toc { background: var(--card, #fff); border: 1px solid var(--line); border-radius: 12px; padding: 14px 20px; margin: 0 0 26px; }
.article-toc .toc-title { font-weight: 700; font-size: 12px; color: var(--dark); margin: 0 0 8px; text-transform: uppercase; letter-spacing: .05em; }
.article-toc ol { margin: 0; padding-left: 18px; font-size: 14.5px; line-height: 1.7; }
.article-toc a { color: var(--accent-strong); text-decoration: none; }
.article-toc a:hover { text-decoration: underline; }
.article-wrap h2 { scroll-margin-top: 84px; } /* so an anchored heading clears the sticky header */

/* Related "read next" */
.related { padding: 24px 0 44px; }
.related h2 { text-align: center; font-size: 24px; color: var(--dark); margin: 0 0 24px; }

/* Lightbox overlay (built by enhance.js; absent without JS). */
.lightbox {
  position: fixed; inset: 0; z-index: 300; display: none;
  align-items: center; justify-content: center; padding: 4vh 3vw;
  background: rgba(15, 14, 12, .92); opacity: 0; transition: opacity .2s ease;
}
.lightbox.is-open { display: flex; opacity: 1; }
.lb-stage { margin: 0; max-width: 92vw; max-height: 92vh; display: flex; flex-direction: column; align-items: center; }
.lb-img {
  max-width: 100%; max-height: 84vh; width: auto; height: auto;
  border-radius: 8px; box-shadow: 0 20px 60px rgba(0, 0, 0, .5);
  animation: lb-in .25s ease;
}
@keyframes lb-in { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }
.lb-cap { color: rgba(255, 255, 255, .82); font-size: 14px; margin-top: 14px; text-align: center; max-width: 60ch; }
.lightbox button {
  position: absolute; background: rgba(255, 255, 255, .12); color: #fff; border: none; cursor: pointer;
  border-radius: 50%; display: flex; align-items: center; justify-content: center; transition: background .15s ease;
}
.lightbox button:hover { background: rgba(255, 255, 255, .28); }
.lightbox button:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }
.lb-close { top: 18px; right: 20px; width: 46px; height: 46px; font-size: 30px; line-height: 1; }
.lb-prev, .lb-next { top: 50%; transform: translateY(-50%); width: 52px; height: 52px; font-size: 34px; line-height: 1; }
.lb-prev { left: max(12px, 2vw); }
.lb-next { right: max(12px, 2vw); }
@media (max-width: 640px) {
  .lb-prev, .lb-next { top: auto; bottom: 16px; transform: none; width: 46px; height: 46px; }
  .lb-prev { left: 24%; } .lb-next { right: 24%; }
}

/* Scroll-lock the page while a full-screen overlay (nav / lightbox) is open. */
body.nav-locked { overflow: hidden; }

/* ---- Stronger hero: Ken Burns zoom, layered entrance, scroll cue ---- */

/* Ken Burns: a slow, gentle zoom on the hero photo (opt-in .has-kenburns). Animates only a
   transform, so the LCP paint is never delayed; reduced-motion turns it off (animation:none). */
.hero.has-image.has-kenburns .hero-media img { animation: pd-kenburns 22s ease-out both; transform-origin: center; }
@keyframes pd-kenburns { from { transform: scale(1.001); } to { transform: scale(1.09); } }

/* Layered entrance: the kicker, sub-copy and buttons rise in on load. The <h1> is deliberately
   NOT animated — it is usually the LCP element, so it paints immediately. Pure CSS, so it needs
   no JS; reduced-motion disables it (animation:none) leaving everything at its normal, visible state. */
.hero .kicker { animation: pd-hero-in .6s .05s both; }
.hero-inner > p, .hero .hero-copy p { animation: pd-hero-in .6s .16s both; }
.hero .hero-btns { animation: pd-hero-in .6s .28s both; }
@keyframes pd-hero-in { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

/* Scroll cue: a soft bouncing chevron at the foot of a full-bleed hero (opt-in, decorative). */
.hero.has-image { position: relative; }
.hero-cue {
  position: absolute; left: 50%; bottom: 20px; transform: translateX(-50%); z-index: 3;
  width: 40px; height: 40px; border-radius: 50%; color: #fff; font-size: 22px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, .14); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  animation: pd-cue 1.8s ease-in-out infinite;
}
.hero:not(.has-image) .hero-cue { color: var(--accent-strong); background: color-mix(in srgb, var(--accent) 14%, transparent); }
@keyframes pd-cue { 0%, 100% { transform: translate(-50%, 0); } 50% { transform: translate(-50%, 7px); } }

/* ---- Interactive sections: carousel, FAQ accordion, tabs ---- */

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Carousel — a scroll-snap track (works by swipe/scroll without JS); enhance.js adds arrows + dots. */
.carousel-sec { padding: var(--space-section-sm) 0; }
.carousel { position: relative; }
.carousel-track {
  display: flex; gap: 18px; overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 6px 4px 14px; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.carousel-track::-webkit-scrollbar { display: none; }
.cslide {
  flex: 0 0 58%; scroll-snap-align: center; position: relative;
  border-radius: 16px; overflow: hidden; background: var(--dark);
}
.cslide img, .cslide picture { width: 100%; height: 100%; display: block; aspect-ratio: 3 / 2; object-fit: cover; }
.cslide-cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 22px 20px; color: #fff;
  background: linear-gradient(180deg, transparent, rgba(0, 0, 0, .72));
}
.cslide-cap h3 { color: #fff; font-size: 22px; margin: 0 0 4px; }
.cslide-cap p { color: rgba(255, 255, 255, .9); font-size: 14px; margin: 0 0 12px; }
.cslide-cap .btn { padding: 9px 18px; font-size: 13px; }
.carousel-prev, .carousel-next {
  display: none; position: absolute; top: 42%; transform: translateY(-50%); z-index: 2;
  width: 44px; height: 44px; border: none; border-radius: 50%; cursor: pointer;
  background: color-mix(in srgb, var(--light) 82%, transparent); color: var(--dark); font-size: 22px;
  align-items: center; justify-content: center; box-shadow: 0 4px 14px rgba(0, 0, 0, .14);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); transition: background .15s ease, transform .15s ease;
}
.js .carousel-prev, .js .carousel-next { display: flex; }
.carousel-prev:hover, .carousel-next:hover { background: var(--accent-strong); color: #fff; }
.carousel-prev { left: 10px; } .carousel-next { right: 10px; }
.carousel-dots { display: none; justify-content: center; gap: 9px; margin-top: 16px; }
.js .carousel-dots { display: flex; }
.carousel-dot {
  width: 9px; height: 9px; padding: 0; border: none; border-radius: 50%; cursor: pointer;
  background: color-mix(in srgb, var(--ink) 24%, transparent); transition: background .15s ease, transform .15s ease;
}
.carousel-dot[aria-selected="true"] { background: var(--accent-strong); transform: scale(1.25); }
@media (max-width: 720px) { .cslide { flex-basis: 86%; } }

/* Trading banner: the one dated notice that applies today, injected by the Worker (see
   trading_calendar.py). Sits above the header so it reads as a notice rather than as page content,
   and uses the brand accent so it cannot be mistaken for a cookie bar. Quiet on purpose: a seasonal
   notice that shouts is indistinguishable from an ad. */
/* INK ON A WASH, not white on the accent. Two measured attempts got here: the raw --accent is a
   large/decorative colour and can be pale (Cottage's is a light sand, so white on it was far below
   AA), and --accent-strong measured 4.52:1, which passes by 0.02 and is far too tight for a
   mechanism EVERY client inherits. A wash background with body ink is high-contrast for any brand
   because the two are derived together, and a tinted band with dark text reads as a notice rather
   than as an ad. Measured in the browser, not judged by eye. */
.trading-banner { background: var(--sage-wash, #efece6); color: var(--ink, #20251f);
  border-bottom: 1px solid var(--line, #e4e7e0); }
.trading-banner .wrap { padding: 10px 20px; display: flex; gap: 10px 22px; flex-wrap: wrap;
  align-items: baseline; justify-content: center; text-align: center; }
.trading-banner p { margin: 0; font-size: 15px; line-height: 1.45; }
.trading-banner .tc-cutoff { font-weight: 600; }
@media (max-width: 640px) { .trading-banner .wrap { padding: 9px 14px; }
  .trading-banner p { font-size: 14px; } }

/* Answer-first block: the direct answer at the top of a page, before the page argues its case.
   Deliberately plain. It exists to be read and quoted, so it gets size and measure, not decoration. */
.answer { padding: var(--space-section-sm) 0 0; }
.answer .answer-lede { max-width: 660px; margin: 0 auto; font-size: 20px; line-height: 1.55;
  color: var(--ink); text-wrap: pretty; }
.answer h2 { text-align: center; margin: 0 0 14px; }
@media (max-width: 640px) { .answer .answer-lede { font-size: 18px; } }

/* FAQ accordion (native <details>, zero-JS accessible) */
.faq { padding: var(--space-section-sm) 0; }
.faq-list { max-width: 760px; margin: 0 auto; display: flex; flex-direction: column; gap: 10px; }
.faq-item { border: 1px solid var(--line); border-radius: 12px; background: var(--card, #fff); overflow: hidden; }
.faq-item summary {
  list-style: none; cursor: pointer; padding: 17px 20px; font-family: var(--heading-font);
  font-size: 17px; color: var(--dark); display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; border-radius: 12px; }
.faq-ic { flex: none; color: var(--accent-strong); font-size: 20px; transition: transform .2s ease; display: flex; }
.faq-item[open] .faq-ic { transform: rotate(45deg); }
.faq-a { padding: 0 20px 18px; }
.faq-a p { margin: 0; color: var(--muted); font-size: 15.5px; line-height: 1.65; }
.faq-item[open] .faq-a { animation: pd-hero-in .3s ease both; }

/* Tabs — no-JS shows every panel stacked; enhance.js reveals the strip + one panel at a time */
.tabs-sec { padding: var(--space-section-sm) 0; }
.tab-list { display: none; flex-wrap: wrap; justify-content: center; gap: 6px; margin-bottom: 26px; border-bottom: 1px solid var(--line); }
.js .tab-list { display: flex; }
.tab-btn {
  border: none; background: none; cursor: pointer; font-family: var(--heading-font); font-weight: 600;
  font-size: 16px; color: var(--muted); padding: 12px 20px; position: relative; transition: color .15s ease;
}
.tab-btn::after { content: ""; position: absolute; left: 14px; right: 14px; bottom: -1px; height: 2px; background: var(--accent-strong); transform: scaleX(0); transition: transform .2s ease; }
.tab-btn:hover { color: var(--dark); }
.tab-btn[aria-selected="true"] { color: var(--dark); }
.tab-btn[aria-selected="true"]::after { transform: scaleX(1); }
.tab-btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 8px; }
.tab-panel-label { display: block; font-family: var(--heading-font); font-size: 22px; color: var(--dark); margin: 22px 0 12px; }
.js .tab-panel-label { display: none; }
.js .tab-panel { display: none; }
.js .tab-panel.is-active { display: block; animation: pd-hero-in .35s ease both; }
.tab-panel-inner { display: flex; gap: 34px; align-items: center; }
.tab-media { flex: 1 1 46%; }
.tab-media img, .tab-media picture { width: 100%; border-radius: 14px; display: block; aspect-ratio: 4 / 3; object-fit: cover; }
.tab-copy { flex: 1 1 54%; }
.tab-copy h3 { font-size: 24px; color: var(--dark); margin: 0 0 12px; }
.tab-copy p { font-size: 16px; color: var(--muted); margin: 0; line-height: 1.65; }
@media (max-width: 720px) { .tab-panel-inner { flex-direction: column; align-items: stretch; gap: 18px; } }

/* ---- Interactive sections batch 2: before/after compare, hotspot image, lookbook ---- */

/* Before/after compare slider */
.compare-sec { padding: var(--space-section-sm) 0; }
.compare {
  position: relative; aspect-ratio: 3 / 2; max-width: 900px; margin: 0 auto;
  border-radius: 16px; overflow: hidden; touch-action: pan-y; user-select: none;
}
.cmp-after, .cmp-before { position: absolute; inset: 0; }
.cmp-after img, .cmp-after picture, .cmp-before img, .cmp-before picture {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.cmp-before { clip-path: inset(0 calc(100% - var(--pos, 50%)) 0 0); }
.cmp-lab {
  position: absolute; bottom: 14px; z-index: 3; background: rgba(0, 0, 0, .55); color: #fff;
  font-size: 11px; letter-spacing: 1px; text-transform: uppercase; padding: 5px 12px; border-radius: 20px;
}
.cmp-lab-before { left: 14px; } .cmp-lab-after { right: 14px; }
.cmp-handle {
  position: absolute; top: 0; bottom: 0; left: var(--pos, 50%); width: 2px; background: #fff;
  transform: translateX(-1px); z-index: 4; pointer-events: none; box-shadow: 0 0 10px rgba(0, 0, 0, .45);
}
.cmp-grip {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 40px; height: 40px; border-radius: 50%; background: #fff; color: var(--dark);
  display: flex; align-items: center; justify-content: center; font-size: 20px; box-shadow: 0 2px 12px rgba(0, 0, 0, .3);
}
.cmp-range { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize; z-index: 5; }
.compare:focus-within .cmp-grip { outline: 3px solid var(--accent); outline-offset: 3px; }

/* Hotspot image */
.hotspot-sec { padding: var(--space-section-sm) 0; }
.hotspot { position: relative; max-width: 820px; margin: 0 auto; border-radius: 16px; overflow: hidden; }
.hotspot-media img, .hotspot-media picture { width: 100%; display: block; }
.hs-point { position: absolute; transform: translate(-50%, -50%); width: 30px; height: 30px; padding: 0; border: none; background: none; cursor: pointer; z-index: 2; }
.hs-dot {
  display: block; width: 20px; height: 20px; margin: 5px; border-radius: 50%;
  background: var(--accent-strong); border: 2px solid #fff; animation: hs-pulse 2.2s infinite;
}
@keyframes hs-pulse {
  0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, .55); }
  70% { box-shadow: 0 0 0 13px rgba(255, 255, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}
.hs-pop {
  position: absolute; bottom: 132%; left: 50%; transform: translateX(-50%) translateY(6px);
  width: 190px; background: var(--dark); color: #fff; padding: 12px 14px; border-radius: 10px;
  font-size: 13px; line-height: 1.5; opacity: 0; visibility: hidden; pointer-events: none; z-index: 5;
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
}
.hs-pop b { display: block; font-family: var(--heading-font); font-size: 15px; margin-bottom: 3px; }
.hs-pop::after { content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border: 7px solid transparent; border-top-color: var(--dark); }
.hs-point:hover .hs-pop, .hs-point:focus-visible .hs-pop, .hs-point[aria-expanded="true"] .hs-pop {
  opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0);
}
.hs-point:focus-visible .hs-dot { outline: 3px solid #fff; outline-offset: 2px; }

/* Lookbook (asymmetric editorial montage) */
.lookbook { padding: var(--space-section-sm) 0; }
.lb-grid { display: grid; grid-template-columns: repeat(4, 1fr); grid-auto-rows: 168px; gap: 12px; grid-auto-flow: dense; }
.lb-cell { margin: 0; position: relative; overflow: hidden; border-radius: 12px; }
.lb-cell img, .lb-cell picture { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .45s ease; }
.lb-cell:hover img { transform: scale(1.05); }
.lb-wide { grid-column: span 2; } .lb-tall { grid-row: span 2; } .lb-big { grid-column: span 2; grid-row: span 2; }
.lb-cell figcaption { position: absolute; left: 0; right: 0; bottom: 0; padding: 20px 14px 12px; color: #fff; font-size: 13px; background: linear-gradient(transparent, rgba(0, 0, 0, .62)); }
.lb-quote {
  grid-column: span 2; margin: 0; display: flex; flex-direction: column; justify-content: center;
  padding: 22px; background: var(--light); border: 1px solid var(--line); border-radius: 12px;
}
.lb-quote blockquote { font-family: var(--heading-font); font-style: italic; font-size: 20px; color: var(--dark); margin: 0 0 8px; line-height: 1.4; }
.lb-quote cite { color: var(--accent-strong); font-size: 13px; font-style: normal; letter-spacing: .3px; }
@media (max-width: 720px) {
  .lb-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 140px; }
  .lb-big { grid-column: span 2; } .lb-quote { grid-column: span 2; }
}

/* ---- Atmosphere sections batch 3: marquee, timeline, divider, packages, seasonal ---- */

/* Marquee (gently scrolling trust strip; pauses on hover + reduced-motion) */
.marquee { overflow: hidden; padding: 22px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.marquee-track { display: flex; width: max-content; animation: mq-scroll 34s linear infinite; }
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-row { display: flex; flex: none; }
.mq-item {
  display: inline-flex; align-items: center; gap: 8px; padding: 0 34px; white-space: nowrap;
  font-family: var(--heading-font); font-size: 16px; color: var(--dark); letter-spacing: .3px;
}
.mq-item .ti { color: var(--accent-strong); font-size: 18px; }
@keyframes mq-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* Timeline (vertical journey / heritage) */
.timeline { padding: var(--space-section-sm) 0; }
.tl-list { list-style: none; margin: 22px auto 0; padding: 0; max-width: 640px; position: relative; }
.tl-list::before { content: ""; position: absolute; left: 9px; top: 6px; bottom: 6px; width: 2px; background: var(--line); }
.tl-item { position: relative; padding: 0 0 26px 42px; }
.tl-item:last-child { padding-bottom: 0; }
.tl-dot { position: absolute; left: 2px; top: 4px; width: 18px; height: 18px; border-radius: 50%; background: var(--accent-strong); border: 3px solid var(--light); box-shadow: 0 0 0 1px var(--line); }
.tl-marker { font-family: var(--heading-font); font-weight: 700; font-size: 13px; letter-spacing: 1px; text-transform: uppercase; color: var(--accent-strong); }
.tl-body h3 { font-size: 19px; color: var(--dark); margin: 2px 0 6px; }
.tl-body p { font-size: 15px; color: var(--muted); margin: 0; line-height: 1.6; }

/* Divider (botanical sprig separator) */
.divider { padding: 30px 0; }
.dv-inner { display: flex; align-items: center; justify-content: center; gap: 18px; }
.dv-rule { height: 1px; width: min(120px, 22vw); background: linear-gradient(90deg, transparent, var(--line), transparent); }
.dv-sprig { width: 34px; height: 34px; color: var(--accent); flex: none; }
.dv-dots { height: 3px; width: min(320px, 60vw); color: var(--accent); opacity: .65;
  background-image: radial-gradient(currentColor 1.3px, transparent 1.6px); background-size: 11px 3px; background-repeat: repeat-x; background-position: center; }
.divider .dv-inner > .dv-line, .dv-inner .dv-line { height: 1px; width: min(320px, 60vw); background: var(--line); }

/* Shaped band transitions: a full-width SVG shape that blends two colour bands. Set the next
   section's background to the divider's `fill` so the shape flows into it (the "designed" look). */
.shape-divider { line-height: 0; background: var(--shape-bg, transparent); margin: 0; }
.shape-divider svg { display: block; width: 100%; height: clamp(48px, 7vw, 96px); }
.shape-divider.shape-flip svg { transform: scaleY(-1); }
/* Sit flush against the next band so the shape flows straight into its colour (no seam). */
.shape-divider + * { margin-top: 0; }

/* Kinetic hero heading: each word rises in on load, staggered. Gated by .js, so no-JS shows the
   words instantly; reduced-motion shows them instantly too. */
.hero-kinetic h1 .kw { display: inline-block; }
.js .hero-kinetic h1 .kw {
  opacity: 0; transform: translateY(0.45em);
  animation: kw-rise .62s cubic-bezier(.2, .7, .2, 1) both;
  animation-delay: calc(var(--i, 0) * 70ms);
}
@keyframes kw-rise { to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .js .hero-kinetic h1 .kw { opacity: 1 !important; transform: none !important; animation: none !important; }
}
/* Gradient heading fill (opt-in). Falls back to solid --dark where background-clip:text is unsupported.
   Also applied to the kinetic .kw spans: background-clip:text does not fill child elements' text, so
   without this the gradient + kinetic combo would render the words invisible. */
.hero-gradient h1, .hero-gradient h1 .kw {
  background: linear-gradient(115deg, var(--accent-strong), var(--accent) 55%, var(--dark));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero-gradient h1, .hero-gradient h1 .kw { color: var(--dark); }
}

/* Packages / pricing cards */
.packages { padding: var(--space-section-sm) 0; }
.pkg-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; align-items: stretch; margin-top: 26px; }
.pkg-card {
  position: relative; background: var(--card, #fff); border: 1px solid var(--line); border-radius: 16px;
  padding: 28px 24px; display: flex; flex-direction: column; text-align: center;
}
.pkg-card.featured { border-color: var(--accent-strong); box-shadow: 0 12px 32px rgba(0, 0, 0, .08); }
.pkg-badge {
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%); background: var(--accent-strong); color: #fff;
  font-size: 11px; letter-spacing: .5px; text-transform: uppercase; padding: 4px 14px; border-radius: 20px; white-space: nowrap;
}
.pkg-card h3 { font-size: 20px; color: var(--dark); margin: 4px 0 8px; }
.pkg-price { font-family: var(--heading-font); font-weight: 700; font-size: 30px; color: var(--dark); }
.pkg-note { font-size: 13px; color: var(--muted); margin: 4px 0 16px; }
.pkg-feats { list-style: none; margin: 0 0 22px; padding: 0; text-align: left; display: flex; flex-direction: column; gap: 10px; }
.pkg-feats li { display: flex; align-items: flex-start; gap: 10px; font-size: 14.5px; color: var(--ink); }
.pkg-feats .ti { color: var(--accent-strong); font-size: 18px; flex: none; margin-top: 1px; }
.pkg-card .btn { margin-top: auto; }

/* Comparison (us vs the alternatives) */
.comparison { padding: var(--space-section-sm) 0; }
.cmp-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; margin-top: 26px; align-items: start; }
.cmp-col { position: relative; border: 1px solid var(--line); border-radius: 16px; padding: 26px 24px; background: var(--card, #fff); }
.cmp-col.featured { border-color: var(--accent-strong); box-shadow: 0 14px 34px rgba(0, 0, 0, .09); }
.cmp-badge { position: absolute; top: -12px; left: 50%; transform: translateX(-50%); background: var(--accent-strong); color: #fff; font-size: 12px; font-weight: 700; letter-spacing: .4px; padding: 5px 12px; border-radius: 999px; }
.cmp-col h3 { font-size: 19px; color: var(--dark); margin: 4px 0 6px; }
.cmp-note { font-size: 13px; color: var(--muted); margin: 0 0 16px; }
.cmp-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; text-align: left; }
.cmp-list li { display: flex; align-items: flex-start; gap: 10px; font-size: 14.5px; color: var(--ink); }
.cmp-list .ti { font-size: 18px; flex: none; margin-top: 1px; }
.cmp-pro .cmp-list .ti { color: #3f7d54; }
.cmp-con .cmp-list .ti { color: #b4523a; }
.cmp-neutral .cmp-list .ti { color: var(--muted); }

/* Logo wall (clients / press / partners) */
.logos { padding: var(--space-section-sm) 0; }
.logo-wall { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 30px 46px; margin-top: 22px; }
.logo-cell { display: inline-flex; align-items: center; }
.logo-cell img { height: 40px; width: auto; max-width: 160px; object-fit: contain; filter: grayscale(1); opacity: .62; transition: filter .25s ease, opacity .25s ease; }
.logo-cell:hover img, a.logo-cell:focus-visible img { filter: grayscale(0); opacity: 1; }
@media (prefers-reduced-motion: reduce) { .logo-cell img { transition: none; } }
/* `plain`: award/accreditation badges, shown as earned marks — full colour, full size, no hover
   trick. Opt-in (section "plain": true) so existing press walls are untouched. */
.logos-plain .logo-wall { gap: 24px 40px; }
.logos-plain .logo-cell img { height: 150px; max-width: 150px; filter: none; opacity: 1; }
@media (max-width: 700px) { .logos-plain .logo-cell img { height: 104px; max-width: 104px; } }

/* Team / staff grid */
.team { padding: var(--space-section-sm) 0; }
.tm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 22px; margin-top: 28px; }
.tm-card { margin: 0; text-align: center; }
.tm-photo { border-radius: 14px; overflow: hidden; aspect-ratio: 4 / 5; margin-bottom: 14px; }
.tm-photo img, .tm-photo picture { width: 100%; height: 100%; object-fit: cover; display: block; }
.tm-card b { display: block; color: var(--dark); font-size: 17px; }
.tm-role { display: block; color: var(--accent-strong); font-size: 13.5px; font-weight: 600; margin-top: 2px; }
.tm-bio { color: var(--muted); font-size: 14px; margin: 10px 0 0; }

/* Seasonal "what's in bloom" (reuses the tabs interaction) */
.seasonal { padding: var(--space-section-sm) 0; }
.season-note { text-align: center; color: var(--muted); font-size: 15px; margin: 0 auto 18px; max-width: 560px; }
.season-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; max-width: 640px; margin: 0 auto; }
.season-chip {
  background: color-mix(in srgb, var(--accent) 12%, var(--light)); color: var(--dark);
  border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent); border-radius: 30px;
  padding: 9px 18px; font-size: 15px; font-family: var(--heading-font);
}

/* ---- Enquiry / contact form (lead capture) ---- */
.form-sec { padding: var(--space-section-sm) 0; }
.form-wrap { max-width: 680px; }
.field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field-wide { grid-column: 1 / -1; }
.field label { font-size: 14px; font-weight: 600; color: var(--dark); }
.field .req { color: var(--accent-strong); }
.field input, .field textarea, .field select {
  font-family: var(--body-font); font-size: 16px; color: var(--ink); background: var(--card, #fff);
  border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; width: 100%;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field textarea { resize: vertical; min-height: 120px; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none; border-color: var(--accent-strong);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.field input.has-error, .field textarea.has-error, .field select.has-error { border-color: #b4523a; }
.field-err { font-size: 13px; color: #b4523a; min-height: 1em; }
/* Marketing opt-in. Spans the grid (it is one sentence, not a field), and the tick sits beside the
   words rather than above them, because a checkbox stacked over its label reads as a heading. */
.consent-field { margin-top: 16px; }
.consent-label { display: flex; align-items: flex-start; gap: 10px; font-weight: 400 !important;
                 font-size: 14px; line-height: 1.45; color: var(--muted); cursor: pointer; }
.consent-label input[type="checkbox"] { width: 17px; height: 17px; margin: 1px 0 0; flex: none;
                                        accent-color: var(--accent-strong); cursor: pointer; }
/* Honeypot: kept in the DOM for bots, hidden from people + assistive tech + tab order. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-foot { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin-top: 22px; }
.form-status { margin: 0; font-size: 14.5px; }
.form-status.is-ok { color: var(--accent-strong); font-weight: 600; }
.form-status.is-err { color: #b4523a; }
.form-status.is-sending { color: var(--muted); }
.form-note { font-size: 13px; color: var(--muted); margin: 14px 0 0; }
.field-note { font-size: 13px; color: var(--muted); }
.field input[type=file] { padding: 10px 12px; font-size: 14.5px; cursor: pointer; }
.field input[type=file]::file-selector-button {
  font-family: var(--body-font); font-size: 13px; font-weight: 600; color: var(--dark);
  background: color-mix(in srgb, var(--accent) 12%, #fff); border: 1px solid var(--line);
  border-radius: 8px; padding: 7px 12px; margin-right: 12px; cursor: pointer;
}
@media (max-width: 560px) { .field-grid { grid-template-columns: 1fr; } }

/* ---- Booking request (service picker cards, reuses the form) ---- */
.bk-services { border: none; margin: 0 0 22px; padding: 0; }
.bk-services legend { font-size: 14px; font-weight: 600; color: var(--dark); margin-bottom: 10px; padding: 0; }
.bk-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
.bk-service { position: relative; display: block; cursor: pointer; }
.bk-service input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.bk-card {
  display: flex; flex-direction: column; gap: 4px; height: 100%; padding: 16px 18px;
  background: var(--card, #fff); border: 1.5px solid var(--line); border-radius: 12px; transition: border-color .15s ease, box-shadow .15s ease;
}
.bk-card b { font-family: var(--heading-font); font-size: 16px; color: var(--dark); }
.bk-meta { font-size: 12px; letter-spacing: .3px; text-transform: uppercase; color: var(--accent-strong); }
.bk-desc { font-size: 14px; color: var(--muted); }
.bk-service:hover .bk-card { border-color: var(--accent); }
.bk-service input:checked + .bk-card { border-color: var(--accent-strong); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent); }
.bk-service input:focus-visible + .bk-card { outline: 3px solid var(--accent); outline-offset: 2px; }

/* ---- Delivery service-area / postcode checker ---- */
.delivery-check { padding: var(--space-section-sm) 0; }
.dc-wrap { max-width: 640px; }
.dc-form { display: none; margin-bottom: 22px; }        /* JS-only (needs JS to check) */
.js .dc-form { display: block; }
.dc-form label { display: block; font-size: 14px; font-weight: 600; color: var(--dark); margin-bottom: 8px; }
.dc-row { display: flex; gap: 10px; flex-wrap: wrap; }
.dc-row input {
  flex: 1 1 200px; font-family: var(--body-font); font-size: 16px; color: var(--ink); background: var(--card, #fff);
  border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px;
}
.dc-row input:focus { outline: none; border-color: var(--accent-strong); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.dc-row .btn { flex: none; }
.dc-result { margin: 14px 0 0; font-size: 15.5px; min-height: 1.2em; }
.dc-result.is-yes { color: var(--accent-strong); font-weight: 600; }
.dc-result.is-no { color: var(--ink); }
.dc-zones { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.dc-zones li { background: var(--card, #fff); border: 1px solid var(--line); border-radius: 10px; padding: 12px 16px; font-size: 15px; color: var(--muted); }
.dc-zones li b { color: var(--dark); }
.js .dc-zones { border-top: 1px solid var(--line); padding-top: 18px; }
.js .dc-zones::before { content: "All our delivery areas"; display: block; font-size: 13px; color: var(--muted); margin-bottom: 10px; letter-spacing: .3px; }

/* ---- Shopping cart (Stripe Checkout) ---- */
.cart-toggle {
  position: fixed; right: 22px; bottom: 22px; z-index: 95; display: none; align-items: center; gap: 8px;
  background: var(--dark); color: #fff; border: none; cursor: pointer; padding: 12px 18px; border-radius: 40px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .2); font-family: var(--heading-font); font-weight: 600; font-size: 15px;
  transition: transform .15s ease;
}
.js .cart-toggle { display: inline-flex; }
.cart-toggle:hover { transform: translateY(-2px); }
.cart-toggle .ti { font-size: 20px; }
.cart-count { background: var(--accent-strong); color: #fff; border-radius: 20px; min-width: 22px; height: 22px; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; padding: 0 6px; }
.cart-toggle:not(.has-items) .cart-count { display: none; }
body:has(.cart-toggle) .to-top { bottom: 84px; }        /* stack back-to-top above the basket */

.cart-drawer { position: fixed; inset: 0; z-index: 300; display: none; }
.cart-drawer.is-open { display: block; }
.cart-backdrop { position: absolute; inset: 0; background: rgba(15, 14, 12, .5); }
.cart-panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(420px, 92vw); background: var(--light);
  box-shadow: -8px 0 34px rgba(0, 0, 0, .22); display: flex; flex-direction: column; padding: 22px; overflow-y: auto;
}
.cart-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cart-head h2 { margin: 0; font-size: 22px; color: var(--dark); }
.cart-close { background: none; border: none; font-size: 30px; line-height: 1; cursor: pointer; color: var(--muted); }
.cart-close:hover { color: var(--dark); }
.cart-items { flex: 1; }
.cart-empty { color: var(--muted); text-align: center; padding: 40px 0; }
.cart-item { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--line); }
.ci-info { display: flex; flex-direction: column; gap: 2px; }
.ci-name { font-weight: 600; color: var(--dark); }
.ci-price { color: var(--muted); font-size: 14px; }
.ci-qty { display: flex; align-items: center; gap: 6px; }
.ci-qty button { border: 1px solid var(--line); background: var(--card, #fff); width: 28px; height: 28px; border-radius: 8px; cursor: pointer; font-size: 15px; color: var(--dark); }
.ci-qty .ci-n { min-width: 20px; text-align: center; }
.ci-remove { width: auto !important; padding: 0 8px; font-size: 12px !important; color: var(--muted); }
.cart-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 16px; border-top: 1px solid var(--line); margin-top: 10px; }
.cart-total { font-family: var(--heading-font); font-weight: 700; font-size: 18px; color: var(--dark); }
.cart-checkout:disabled { opacity: .5; cursor: default; }
.cart-msg { font-size: 13px; color: var(--muted); margin: 10px 0 0; text-align: center; }

/* ---- Instagram feed (keeps a site looking fresh) ---- */
.instagram { padding: var(--space-section-sm) 0; text-align: center; }
.ig-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.ig-tile { position: relative; display: block; aspect-ratio: 1 / 1; overflow: hidden; border-radius: 10px; background: var(--dark); }
.ig-tile img, .ig-tile picture { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .4s ease; }
.ig-tile:hover img { transform: scale(1.06); }
.ig-tile::after { content: ""; position: absolute; inset: 0; background: rgba(0, 0, 0, 0); transition: background .2s ease; }
.ig-tile:hover::after { background: rgba(0, 0, 0, .12); }
.ig-loading, .ig-empty { grid-column: 1 / -1; color: var(--muted); padding: 30px 0; }
.ig-follow { display: inline-flex; align-items: center; gap: 8px; margin-top: 24px; font-family: var(--heading-font); font-weight: 600; color: var(--accent-strong); text-decoration: none; }
.ig-follow:hover { color: var(--dark); }
.ig-follow .ti { font-size: 20px; }
@media (max-width: 720px) { .ig-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 460px) { .ig-grid { grid-template-columns: repeat(2, 1fr); } }

/* Announcement banner (a promo/offer strip) */
.banner { background: var(--accent-strong); }
.banner-inner { display: flex; align-items: center; justify-content: center; gap: 18px; flex-wrap: wrap; text-align: center; padding-top: 15px; padding-bottom: 15px; }
.banner p { margin: 0; color: #fff; font-size: 15px; }
.banner strong { font-weight: 700; }
.banner-btn { flex: none; background: #fff; color: var(--accent-strong); font-family: var(--heading-font); font-weight: 600; font-size: 13px; border-radius: 22px; padding: 9px 18px; text-decoration: none; white-space: nowrap; }
/* `banner-band`: the band carrying a paired heading (kicker + h2 + body), rather than the slim
   promo strip. A real section in the vertical rhythm, not a 15px strip. */
.banner-band .banner-inner { gap: 34px; padding-block: clamp(52px, 6vw, 96px); }
.banner-band .banner-copy { max-width: 620px; }
.banner-band h2 { font-size: var(--fs-h2); color: var(--light); margin: 0 0 14px; }
.banner-band p { font-size: 16px; line-height: 1.7; color: rgba(255, 255, 255, .88); }
.banner-band .kicker { color: var(--light); margin-bottom: 4px; }
/* Photo column beside the colour. Decorative, so it is a background on an aria-hidden div rather
   than an <img> with invented alt text. Drops away on narrow screens, where the band stacks. */
/* min-height so the photo column reads as a column rather than a stripe: padding alone leaves the
   band too shallow for a photo to read. Neutral defaults; a site replicating a measured band
   overrides the width and height in its own sites/<slug>/style.css. */
.banner-band.has-media { position: relative; overflow: hidden; padding-left: 34%; min-height: 380px; display: flex; align-items: center; }
.banner-band.has-media .banner-inner { width: 100%; }
.banner-band .banner-media { position: absolute; top: 0; bottom: 0; left: 0; width: 34%; background-size: cover; background-repeat: no-repeat; }
@media (max-width: 860px) {
  .banner-band.has-media { padding-left: 0; }
  .banner-band .banner-media { position: static; width: 100%; height: 220px; }
}

/* ============================================================================
   Late overrides (must come after every component rule to win on equal specificity).
   ---------------------------------------------------------------------------- */
/* Centred section head (default): keep the whole block aligned as one unit. Without this the kicker +
   sub centre but a bare section h2 falls to the left, which read as a misalignment. */
.sec-head { text-align: center; }
/* Offset / left-aligned section headings (editorial, per-section align:"left"). */
.sec-head-left, .sec-head-left h2, .sec-head-left .kicker, .sec-head-left .section-sub { text-align: left !important; }
.sec-head-left h2 { margin-left: 0; margin-right: 0; max-width: 22ch; }
.sec-head-left .section-sub { margin-left: 0; margin-right: 0; max-width: 60ch; }
.sec-head-left { margin-bottom: var(--space-head); }

/* Optional decorative botanical texture (site.texture:"botanical"): a faint tiled sprig behind the
   page, for a characterful, hand-crafted feel (Scarlet & Violet). Kept very subtle so text stays clean. */
body.tex-botanical {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300' viewBox='0 0 300 300'%3E%3Cg fill='none' stroke='%236E8C68' stroke-width='1.1' stroke-linecap='round' opacity='0.10'%3E%3Cpath d='M60 90 C60 60 60 40 60 24'/%3E%3Cpath d='M60 60 C48 56 42 60 39 70 C50 70 56 66 60 60Z' fill='%236E8C68'/%3E%3Cpath d='M60 60 C72 56 78 60 81 70 C70 70 64 66 60 60Z' fill='%236E8C68'/%3E%3Cpath d='M60 44 C50 40 45 44 42 52 C52 52 57 49 60 44Z' fill='%236E8C68'/%3E%3Cpath d='M210 240 C210 210 210 190 210 174'/%3E%3Cpath d='M210 210 C198 206 192 210 189 220 C200 220 206 216 210 210Z' fill='%236E8C68'/%3E%3Cpath d='M210 210 C222 206 228 210 231 220 C220 220 214 216 210 210Z' fill='%236E8C68'/%3E%3C/g%3E%3C/svg%3E");
  background-attachment: fixed;
}

/* ---- Website mockups (a web agency's "product imagery"): browser frame + a stylized site or a
   real screenshot, shown in a showreel/portfolio. ---- */
.showreel { padding: var(--space-section-sm) 0; }
.showreel .wrap > h2, .showreel .sec-head { margin-bottom: var(--space-head); }
/* Flex + centre so a row with fewer than 3 mockups (e.g. two case studies) sits centred, not left-bunched. */
.showreel-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 22px; }
.showreel-row .bmock { flex: 0 1 360px; }
@media (max-width: 600px) { .showreel-row .bmock { flex-basis: 100%; } }
.bmock { margin: 0; border-radius: 12px; overflow: hidden; background: #fff; border: 1px solid var(--line);
  box-shadow: 0 18px 44px rgba(0,0,0,.10); transition: transform .3s ease, box-shadow .3s ease; }
.bmock:hover { transform: translateY(-4px); box-shadow: 0 26px 60px rgba(0,0,0,.14); }
.bmock-bar { display: flex; align-items: center; gap: 6px; padding: 9px 12px; background: #f3f3f1; border-bottom: 1px solid var(--line); }
.bmock-dot { width: 9px; height: 9px; border-radius: 50%; background: #d5d5cf; }
.bmock-dot:nth-child(1) { background: #e6a08c; } .bmock-dot:nth-child(2) { background: #e6cf8c; } .bmock-dot:nth-child(3) { background: #a9bfa1; }
.bmock-url { margin-left: 10px; flex: 1; background: #fff; border-radius: 20px; font-size: 10.5px; color: var(--muted); padding: 3px 12px; text-align: center; letter-spacing: .02em; }
.bmock-screen { aspect-ratio: 4 / 3; overflow: hidden; position: relative; }
.bmock-screen img, .bmock-screen picture { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.bmock-label { padding: 12px 16px; font-family: var(--heading-font); font-weight: 600; font-size: 14px; color: var(--dark); }

/* The stylized fake-site placeholder. Themed per INSTANCE by _fake_site() in build.py,
   which always sets --m-bg/--m-dark/--m-acc/--m-img inline. The fallbacks are the safety net:
   without them a missing var silently drops the declaration and the mockup renders as a blank
   box, and a whole-site scan cannot tell a deliberate per-element token from a typo. */
.fsite { position: absolute; inset: 0; background: var(--m-bg, var(--light)); display: flex; flex-direction: column; padding: 9% 8% 0; gap: 6%; }
.fsite-nav { display: flex; align-items: center; justify-content: space-between; }
.fsite-logo { width: 22%; height: 8px; border-radius: 3px; background: var(--m-dark, var(--dark)); }
.fsite-links { display: flex; gap: 8px; } .fsite-links i { width: 22px; height: 5px; border-radius: 3px; background: color-mix(in srgb, var(--m-dark, var(--dark)) 40%, transparent); }
.fsite-hero { flex: 1; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; gap: 6px; position: relative; }
.fsite-hero-img { position: absolute; inset: 0; background: var(--m-img, linear-gradient(135deg,#cbb7a6,#9fb08f)); border-radius: 8px; }
.fsite-hero-copy { position: relative; display: flex; flex-direction: column; align-items: center; gap: 7px; }
.fsite-hero .l1 { width: 130px; height: 12px; border-radius: 4px; background: #fff; }
.fsite-hero .l2 { width: 90px; height: 8px; border-radius: 4px; background: rgba(255,255,255,.8); }
.fsite-hero .pill { width: 66px; height: 16px; border-radius: 20px; background: var(--m-acc, var(--accent)); margin-top: 4px; }
.fsite-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5%; padding-bottom: 8%; }
.fsite-grid span { aspect-ratio: 1; border-radius: 6px; background: color-mix(in srgb, var(--m-dark, var(--dark)) 14%, var(--m-bg, var(--light))); }
.fsite-split .fsite-hero { flex-direction: row; align-items: stretch; }
.fsite-split .fsite-hero-img { position: relative; inset: auto; width: 48%; }
.fsite-split .fsite-hero-copy { align-items: flex-start; justify-content: center; flex: 1; padding-left: 7%; }
.fsite-split .fsite-hero .l1, .fsite-split .fsite-hero .l2 { background: var(--m-dark, var(--dark)); }
.fsite-split .fsite-hero .l2 { background: color-mix(in srgb, var(--m-dark, var(--dark)) 55%, transparent); }

/* ---- Two-tone headline (Stripe): a bold lead + a muted continuation in one <h1> ---- */
.hero h1 .h-trail { color: var(--muted); }
.hero.has-image h1 .h-trail, .hero.bg-dark h1 .h-trail { color: rgba(255,255,255,.62); }

/* ---- Rich footer (the modern standard): brand + CTA, link columns, a bottom bar ---- */
.site-footer.rich { text-align: left; padding: 0; }
.site-footer.rich .footer-top { display: grid; grid-template-columns: 1.3fr 2fr; gap: 40px; padding: clamp(48px, 6vw, 72px) 24px clamp(32px, 4vw, 48px); align-items: start; }
.site-footer.rich .footer-brand .fname { font-size: 22px; margin: 0 0 8px; }
/* A light logo on the dark band, in place of the name in type (`footer.logo`). */
.site-footer.rich .footer-brand .flogo { display: block; width: auto; height: auto; max-width: 240px; max-height: var(--flogo-h, 120px); margin: 0 0 18px; }
.site-footer.rich .footer-brand .fmeta { font-size: 15px; opacity: .82; margin: 0 0 20px; max-width: 40ch; }
.site-footer.rich .footer-cta { background: #fff; color: var(--dark); }
.site-footer.rich .footer-cta:hover { background: var(--accent-strong); color: #fff; }
.site-footer.rich .footer-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 28px; }
.site-footer.rich .fcol h4 { font-family: var(--heading-font); font-size: 13px; letter-spacing: .04em; text-transform: uppercase; opacity: .7; margin: 0 0 14px; }
.site-footer.rich .fcol ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.site-footer.rich .fcol a { color: var(--light); opacity: .88; text-decoration: none; font-size: 14.5px; }
.site-footer.rich .fcol a:hover { opacity: 1; }
.site-footer.rich .footer-bottom { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; padding: 20px 24px; border-top: 1px solid rgba(255,255,255,.14); font-size: 13px; opacity: .74; }
.site-footer.rich .footer-bottom .fcopy { margin-left: auto; }
/* Trading disclosure. Legally required text, so it never sits below the AA contrast the rest
   of this band holds, and it wraps to its own line rather than truncating. */
.site-footer.rich .footer-bottom .flegal { flex: 1 1 100%; order: 9; opacity: .82; }

/* Prose tables (terms, privacy, any data-protection annex). Legal content has to stay READABLE and
   checkable, so: real borders, generous cells, and a horizontal scroll on small screens rather than
   a squashed grid that hides a column. Neutral by default; no site-specific numbers here. */
.prose-tablewrap { overflow-x: auto; margin: 20px 0 26px; -webkit-overflow-scrolling: touch; }
.prose-table { border-collapse: collapse; width: 100%; min-width: 480px; font-size: 15px; line-height: 1.5; }
.prose-table th, .prose-table td { text-align: left; vertical-align: top; padding: 10px 14px; border: 1px solid var(--line, #e4e8e0); }
.prose-table th { font-weight: 600; background: var(--sage-wash, #e8eee4); }
.prose-table tbody tr:nth-child(even) td { background: rgba(0,0,0,.015); }
.site-footer.rich .fsocial a { color: var(--light); text-decoration: none; margin-right: 14px; opacity: .88; }
.site-footer.rich .fsocial a:hover { opacity: 1; text-decoration: underline; }
@media (max-width: 720px) { .site-footer.rich .footer-top { grid-template-columns: 1fr; } .site-footer.rich .footer-bottom .fcopy { margin-left: 0; } }

/* ---- Hero announcement row (Linear): a pill tag + linked label + arrow, low-key launch/offer cue ---- */
.hero-ann { display: inline-flex; align-items: center; gap: 10px; margin-top: 22px; padding: 6px 6px 6px 6px;
  text-decoration: none; font-size: 14.5px; color: var(--muted); width: fit-content;
  border: 1px solid var(--line); border-radius: 999px; background: color-mix(in srgb, var(--light) 60%, transparent);
  transition: border-color .18s ease, transform .18s ease; }
.hero-ann:hover { border-color: var(--accent-strong); transform: translateY(-1px); }
.hero-ann .ann-tag { background: var(--accent-strong); color: #fff; font-weight: 600; font-size: 12px;
  letter-spacing: .02em; padding: 3px 10px; border-radius: 999px; text-transform: uppercase; }
.hero-ann .ann-label { color: var(--ink); font-weight: 500; }
.hero-ann .ann-arrow { color: var(--accent-strong); padding-right: 8px; transition: transform .18s ease; }
.hero-ann:hover .ann-arrow { transform: translateX(3px); }
.hero.has-image .hero-ann, .hero.bg-dark .hero-ann { border-color: rgba(255,255,255,.28); background: rgba(255,255,255,.08); color: rgba(255,255,255,.72); }
.hero.has-image .hero-ann .ann-label, .hero.bg-dark .hero-ann .ann-label { color: #fff; }

/* ── Photo band ────────────────────────────────────────────────────────────────
   A full-bleed photograph with the text over it. The dominant section on
   photography-led sites (a florist's About/Workshops/Testimonials are usually
   this), and the engine previously had no way to express it: `split` could only
   put a photo BESIDE text, and only `hero` could put text OVER a photo. Added
   2026-07-28 after the fidelity harness measured a takeover at 3 photo-bearing
   sections against the client's 6. Set with `"background": "photo"` + `"image"`.
   The scrim is baked into the inline background so the text stays legible on any
   photograph without a second element. */
.split.split-photo { background-color: var(--dark); color: #fff; }
.split.split-photo .split-inner { min-height: 62vh; display: flex; align-items: center;
  padding-block: clamp(64px, 9vw, 132px); }
/* Their photo sections are TWO COLUMN: the text sits in one half over the photograph,
   not centred across it (measured: cols=2, align=start). `flip` puts it on the right. */
.split.split-photo .split-inner { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; }
.split.split-photo .split-text { max-width: 34rem; text-align: left; }
.split.split-photo.flip .split-inner { direction: rtl; }
.split.split-photo.flip .split-text { direction: ltr; grid-column: 2; }
@media (max-width: 860px) {
  .split.split-photo .split-inner { grid-template-columns: 1fr; }
  .split.split-photo.flip .split-text { grid-column: 1; }
}
.split.split-photo h2 { color: var(--accent); }
.split.split-photo .kicker,
.split.split-photo p,
.split.split-photo .split-lead { color: #fff; }
.split.split-photo .btn { color: #fff; border-color: #fff; }
.split.split-photo .btn:hover { background: #fff; color: var(--dark); }
@media (max-width: 720px) { .split.split-photo .split-inner { min-height: 52vh; } }

/* ── Vertical rhythm, brand-declared ───────────────────────────────────────────
   Several sections carry hardcoded paddings (.intro 30/50, .feature 34) that are
   much tighter than the --space-section tokens they sit beside. That is fine as a
   house default and wrong for a replica: measured 2026-07-28, Cottage's own page
   is ~5,850px where our rebuild was 3,928px, median section 600px against our
   471px. Their site breathes; ours was compressed.

   OPT-IN so no live client is silently restyled: only applies when the brand
   record declares `section_rhythm: "generous"`, which emits body.rhythm-generous. */
body.rhythm-generous .intro { padding: var(--space-section) 0; }
body.rhythm-generous .feature { padding: var(--space-section) 0; }
body.rhythm-generous .gallery { padding: var(--space-section-sm) 0; }
body.rhythm-generous .quote { padding: var(--space-section) 24px; }
body.rhythm-generous .services { padding: var(--space-section) 0; }
body.rhythm-generous .split { padding: var(--space-section) 0; }
body.rhythm-generous .banner .banner-inner { padding-block: clamp(40px, 5vw, 72px); }
body.rhythm-generous .cta-band { padding: var(--space-section) 24px; }

/* ── Service cards as photo tiles ──────────────────────────────────────────────
   A photograph with a scrim, an uppercase title over it and a ghost button. This
   is how traditional florist sites present their lines of business; text-only
   cards read as a different kind of site entirely. Opt-in per item: a card only
   becomes a tile when it carries an "image". Added 2026-07-28 (Batch 4). */
.card.card-photo { position: relative; min-height: 340px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 14px; text-align: center;
  padding: 32px 24px; border: none; box-shadow: none; overflow: hidden; }
.card.card-photo h3 { color: #fff; margin: 0; }
.card.card-photo p { color: rgba(255,255,255,.92); margin: 0; max-width: 26ch; }
.card.card-photo .btn { color: #fff; border-color: #fff; background: rgba(0,0,0,.28); }
.card.card-photo .btn:hover { background: #fff; color: var(--dark); }
@media (max-width: 720px) { .card.card-photo { min-height: 260px; } }

/* ── Centred-logo header ───────────────────────────────────────────────────────
   Toggle left, logo centred, nav behind the toggle. The traditional florist
   header; the engine previously only drew a left logo with an inline nav.
   Opt-in via `site.logo_align: "center"`. Added 2026-07-28 (Batch 4). */
.site-header.header-centred { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.site-header.header-centred .nav-toggle { display: inline-flex; grid-column: 1; justify-self: start; }
.site-header.header-centred .logo { grid-column: 2; justify-self: center; }
.site-header.header-centred .nav { grid-column: 3; justify-self: end; }
@media (min-width: 861px) {
  .site-header.header-centred .nav { display: none; }
  /* enhance.js sets `nav-open`, not `open`. This said `.open`, so the centred header's menu
     could not be opened at all above 861px. Fixed 2026-07-28. */
  .site-header.header-centred .nav.nav-open { display: flex; }
}

/* ── Two-row header with a colour nav bar ──────────────────────────────────────
   A logo row over a full-width nav strip in a declared colour. The traditional
   florist header, and the engine could not draw it at all, so a replica of one
   came out wearing a hamburger the client does not have. Opt-in via
   `site.nav_bar`; `site.header_cta` fills the left slot. Measured off Cottage's
   own header 2026-07-28: 181px total, a 41px slate #596a7c bar of uppercase
   Montserrat 14px links. Added 2026-07-28. */
/* Full-bleed and STATIC: the colour bar has to reach both edges, and the header this
   replicates does not stick (theirs is position: static, measured). The base .site-header
   is a centred max-width flex row that sticks, so both are overridden here. */
.site-header.has-navbar {
  display: block; padding: 0; max-width: none; width: 100%; position: static;
}
/* Neutral defaults. A site replicating a specific header overrides the padding in its OWN
   sites/<slug>/style.css, so one client's measurements never become everyone's. */
.site-header.has-navbar .header-row {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: 16px; padding: 20px 32px;
}
/* The logo row sits on the page ground, so its buttons take the dark treatment. Without
   this the ghost CTA inherits the light-on-dark rule and renders white on white. */
.site-header.has-navbar .header-row .nav-cta,
.site-header.has-navbar .header-row .header-cta {
  color: var(--dark); border-color: var(--dark); background: transparent;
}
.site-header.has-navbar .header-row .nav-cta:hover,
.site-header.has-navbar .header-row .header-cta:hover { background: var(--dark); color: var(--light); }
.site-header.has-navbar .nav-toggle { grid-column: 1; justify-self: start; }
.site-header.has-navbar .header-cta { grid-column: 1; justify-self: start; }
.site-header.has-navbar .logo { grid-column: 2; justify-self: center; }
.site-header.has-navbar .nav-cta { grid-column: 3; justify-self: end; }
.site-header.has-navbar .nav-strip { width: 100%; }
.site-header.has-navbar .nav-strip .nav {
  display: flex; justify-content: center; align-items: center; flex-wrap: wrap;
  gap: 0 38px; padding: 11px 24px; max-width: var(--wrap, 1200px); margin: 0 auto;
}
.site-header.has-navbar .nav-strip .nav a {
  font-family: var(--body-font); font-size: 14px; font-weight: 500;
  text-transform: uppercase; letter-spacing: normal; color: var(--light); opacity: .92;
}
.site-header.has-navbar .nav-strip .nav a:hover,
.site-header.has-navbar .nav-strip .nav a.active { opacity: 1; }
.site-header.has-navbar .nav-strip .nav-caret { color: currentColor; }
/* The dropdown panel stays a light card on the page ground. `background: inherit` was wrong twice
   over: background is not an inherited property, so it resolved against the transparent .nav-item
   and the panel rendered see-through. The links inside it also have to opt OUT of the bar's white
   text, or they are white on a white card and the whole submenu is invisible. */
.site-header.has-navbar .nav-strip .nav-menu { background: var(--light); }
.site-header.has-navbar .nav-strip .nav-menu a { color: var(--ink); opacity: 1; }
.site-header.has-navbar .nav-strip .nav-menu a:hover { color: var(--accent-strong); }
/* Below the nav breakpoint the hamburger takes over, exactly as on their own site,
   which shows no colour bar on a phone. enhance.js toggles `.open` on #site-nav (the
   .nav), so the STRIP is keyed off that with :has() — where :has() is unsupported the
   rule is simply dropped and the bar stays visible, which degrades quietly. */
@media (max-width: 860px) {
  .site-header.has-navbar .nav-strip:not(:has(.nav.nav-open)) { display: none; }
  .site-header.has-navbar .nav-strip .nav { display: none; }
  .site-header.has-navbar .nav-strip .nav.nav-open { display: flex; flex-direction: column; gap: 4px; padding: 14px 24px; }
  .site-header.has-navbar .header-cta { display: none; }
}
@media (min-width: 861px) {
  .site-header.has-navbar .nav-toggle { display: none; }
  .site-header.has-navbar .nav-strip .nav { display: flex; }
}
