/**
 * fonts.css — self-hosted webfonts (handoff/03 §3).
 *
 * No Google Fonts / CDN: the guest site stays fully static, private (no third-party
 * requests), fast, and CSP-clean. Variable woff2 subset to `latin`, font-display:swap.
 * Files under ./fonts/ are copied from @fontsource-variable/{fraunces,nunito-sans}.
 *
 * - Fraunces (display serif): variable weight 100–900 + optical-size axis (opsz 9–144),
 *   so headings get the graceful high-contrast display cut automatically via
 *   `font-optical-sizing: auto`. Headings only → normal style, no italic file needed.
 * - Nunito Sans (body/UI sans): variable weight 200–1000, normal + italic.
 *
 * The renderer (handoff/04) copies ./fonts/ into public/assets/fonts/ and serves this
 * alongside tokens.css. Paths here are relative so design/ previews stand alone.
 */

@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url("./fonts/fraunces-variable-latin.woff2") format("woff2");
  /* Latin (basic) — matches @fontsource `latin` subset. */
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Nunito Sans";
  font-style: normal;
  font-display: swap;
  font-weight: 200 1000;
  src: url("./fonts/nunito-sans-variable-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Nunito Sans";
  font-style: italic;
  font-display: swap;
  font-weight: 200 1000;
  src: url("./fonts/nunito-sans-variable-latin-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
    U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
    U+FEFF, U+FFFD;
}


/**
 * tokens.css — the single design system (handoff/03).
 *
 * One file of CSS custom properties + the utility classes the owner's text tools emit
 * (ff-*, sz-*, hl-*, align-*) and radius/shadow helpers. Imported by BOTH the guest
 * site (05) and the admin CMS (06) so they feel like one product. Pairs with fonts.css.
 *
 * Owner color controls: the renderer (04) injects an inline `:root{ --c-bg:…; --c-accent:… }`
 * AFTER this file, so settings.backgroundColor / settings.accentColor (handoff/01) override
 * the defaults below and cascade to buttons, links, and panels. Everything reads from tokens —
 * never hard-code these hexes downstream.
 */

:root {
  color-scheme: light;

  /* ---- Color: warm neutral base + sage accent + gold highlight (§2) ---- */
  --c-bg: #FBF7F0;        /* ivory paper — site background (owner-overridable) */
  --c-surface: #FFFFFF;   /* cards / raised surfaces (admin) */
  --c-ink: #2E2A26;       /* near-black warm brown — primary text */
  --c-ink-soft: #5B534B;  /* secondary text (AA on --c-bg) */
  --c-line: #E7DFD3;      /* hairline borders */

  --c-accent: #7C8B6B;    /* sage/olive — buttons, links (owner-overridable) */
  --c-accent-ink: #FFFFFF;/* text on accent */
  --c-accent-2: #C9A227;  /* warm gold — small highlights, hovers */
  --c-rose: #C99AA0;      /* soft rose — tertiary */

  /* text-highlight (<mark>) options for the owner's "highlight" tool */
  --hl-1: #F3E7C6;  /* gold */
  --hl-2: #DCE4D2;  /* sage */
  --hl-3: #EBD9DA;  /* rose */

  --c-footer-bg: #2E2A26;
  --c-footer-ink: #FBF7F0;

  /* derived accent states (kept in tokens so overrides flow through) */
  --c-accent-hover: color-mix(in srgb, var(--c-accent) 86%, #000 14%);
  --c-focus: color-mix(in srgb, var(--c-accent) 55%, #FFF 45%);

  /* ---- Typography (§3) ---- */
  --ff-serif: "Fraunces", Georgia, "Times New Roman", serif;
  --ff-sans: "Nunito Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  --fs-display: clamp(2.6rem, 6vw, 4.5rem);  /* hero */
  --fs-h2: clamp(1.9rem, 4vw, 2.75rem);      /* panel headings */
  --fs-h3: clamp(1.3rem, 2.5vw, 1.6rem);
  --fs-body: clamp(1.05rem, 1.4vw, 1.2rem);
  --fs-sm: clamp(0.92rem, 1.1vw, 1rem);      /* captions / fine print */

  --lh-body: 1.7;
  --lh-head: 1.12;
  --measure: 62ch;       /* readable line length */
  --tracking-head: -0.01em;

  /* ---- Spacing / radius / shadow / layout (§4) ---- */
  --sp-1: 0.5rem;
  --sp-2: 1rem;
  --sp-3: 1.5rem;
  --sp-4: 2.5rem;
  --sp-5: 4rem;
  --sp-6: 6rem;

  --radius-none: 0;
  --radius-sm: 6px;
  --radius-md: 14px;
  --radius-lg: 24px;
  --radius-pill: 999px;

  --shadow-soft: 0 10px 30px -12px rgba(46, 42, 38, 0.18); /* gentle, warm, never harsh */
  --shadow-lift: 0 16px 40px -14px rgba(46, 42, 38, 0.24);

  --content-max: 820px;  /* readable column cap (panel maxContentWidth default) */
  --panel-pad-y: clamp(3rem, 8vh, 7rem);

  /* Panel `padding` tokens (handoff/01 §3) → vertical rhythm (§4) */
  --pad-compact: var(--sp-4);
  --pad-comfortable: var(--sp-5);
  --pad-spacious: var(--sp-6);

  /* ---- Motion (§5) ---- */
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur-reveal: 600ms;
  --dur-ui: 180ms;
  --reveal-rise: 16px;
  --reveal-stagger: 90ms;
}

/* ============================================================= *
 * Utility classes shared by both apps.                          *
 * These are the ONLY classes the sanitizer (handoff/01 §6)      *
 * allows inside owner rich text: ff-* sz-* hl-* align-*         *
 * ============================================================= */

/* font family */
.ff-serif { font-family: var(--ff-serif); }
.ff-sans  { font-family: var(--ff-sans); }

/* named text-size scale (not arbitrary px) — handoff/01 §4.1 */
.sz-sm { font-size: var(--fs-sm); }
.sz-md { font-size: var(--fs-body); }
.sz-lg { font-size: var(--fs-h3); }
.sz-xl { font-size: var(--fs-h2); }

/* text alignment */
.align-left   { text-align: left; }
.align-center { text-align: center; }
.align-right  { text-align: right; }

/* highlight colors — applied to <mark> */
mark.hl-1, .hl-1 { background: var(--hl-1); }
mark.hl-2, .hl-2 { background: var(--hl-2); }
mark.hl-3, .hl-3 { background: var(--hl-3); }
mark[class^="hl-"], mark[class*=" hl-"] {
  color: var(--c-ink);
  padding: 0.02em 0.22em;
  border-radius: var(--radius-sm);
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* ---- radius / shadow helpers (§8 deliverable) ---- */
.r-none { border-radius: var(--radius-none); }
.r-sm   { border-radius: var(--radius-sm); }
.r-md   { border-radius: var(--radius-md); }
.r-lg   { border-radius: var(--radius-lg); }
.r-pill { border-radius: var(--radius-pill); }
.shadow-soft { box-shadow: var(--shadow-soft); }
.shadow-lift { box-shadow: var(--shadow-lift); }

/* ============================================================= *
 * Reveal-on-enter utility (§5). JS adds `.in-view` via          *
 * IntersectionObserver; guest/admin share this behavior.        *
 * ============================================================= */
[data-reveal] {
  opacity: 0;
  transform: translateY(var(--reveal-rise));
  transition:
    opacity var(--dur-reveal) var(--ease-out),
    transform var(--dur-reveal) var(--ease-out);
  transition-delay: calc(var(--reveal-index, 0) * var(--reveal-stagger));
  will-change: opacity, transform;
}
[data-reveal].in-view {
  opacity: 1;
  transform: none;
}

/* Respect reduced motion: no reveal, no rise — content is simply present. */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  html { scroll-behavior: auto; }
}

/* Older engines without color-mix: fall back to sensible fixed states. */
@supports not (color: color-mix(in srgb, red, blue)) {
  :root {
    --c-accent-hover: #6b795c;
    --c-focus: #aeb99f;
  }
}


/**
 * components.css — the shared component layer (handoff/03 §6).
 *
 * Element defaults + the button / form-field / link / card / image-block looks that
 * BOTH the guest site (05) and admin CMS (06) build on, so they read as one product.
 * Everything is expressed in tokens from tokens.css — no raw hexes here.
 */

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-ink);
  font-family: var(--ff-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---- Headings: warm display serif, optical sizing on ---- */
h1, h2, h3 {
  font-family: var(--ff-serif);
  font-optical-sizing: auto;
  line-height: var(--lh-head);
  letter-spacing: var(--tracking-head);
  color: var(--c-ink);
  font-weight: 500;
  margin: 0 0 var(--sp-2);
  text-wrap: balance;
}
h1, .display {
  font-size: var(--fs-display);
  font-weight: 480;
}
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

p { margin: 0 0 var(--sp-2); }
p:last-child { margin-bottom: 0; }

/* readable measure for body copy */
.measure { max-width: var(--measure); }

/* ---- Links ---- */
a {
  color: var(--c-accent);
  text-decoration: none;
  transition: color var(--dur-ui) var(--ease-out);
}
a:hover { text-decoration: underline; text-underline-offset: 0.15em; }

/* ---- Visible keyboard focus everywhere (§7) ---- */
:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ---- Buttons (§6): pill, accent fill primary, soft outline secondary ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  font-family: var(--ff-sans);
  font-size: var(--fs-body);
  font-weight: 700;
  line-height: 1;
  padding: 0.85em 1.6em;
  border-radius: var(--radius-pill);
  border: 1.5px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition:
    transform var(--dur-ui) var(--ease-out),
    box-shadow var(--dur-ui) var(--ease-out),
    background-color var(--dur-ui) var(--ease-out),
    color var(--dur-ui) var(--ease-out);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-primary {
  background: var(--c-accent);
  color: var(--c-accent-ink);
}
.btn-primary:hover {
  background: var(--c-accent-hover);
  box-shadow: var(--shadow-soft);
  text-decoration: none;
}

.btn-secondary {
  background: transparent;
  color: var(--c-accent);
  border-color: var(--c-accent);
}
.btn-secondary:hover {
  background: color-mix(in srgb, var(--c-accent) 10%, transparent);
  box-shadow: var(--shadow-soft);
  text-decoration: none;
}

/* ---- Form fields (§6): large targets, soft border, accent focus ring ---- */
.field { margin-bottom: var(--sp-3); }
.field > label {
  display: block;
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--c-ink);
  margin-bottom: var(--sp-1);
}
.field .req { color: var(--c-accent-2); }

.input,
.textarea,
.select {
  width: 100%;
  font-family: var(--ff-sans);
  font-size: var(--fs-body);
  color: var(--c-ink);
  background: var(--c-surface);
  border: 1.5px solid var(--c-line);
  border-radius: var(--radius-md);
  padding: 0.75em 0.9em;
  transition:
    border-color var(--dur-ui) var(--ease-out),
    box-shadow var(--dur-ui) var(--ease-out);
}
.textarea { min-height: 7.5rem; resize: vertical; line-height: var(--lh-body); }
.select { appearance: none; background-image: none; padding-right: 2.5em; }

.input:focus,
.textarea:focus,
.select:focus {
  outline: none;
  border-color: var(--c-accent);
  box-shadow: 0 0 0 3px var(--c-focus);
}
.input::placeholder, .textarea::placeholder { color: var(--c-ink-soft); opacity: 0.7; }

/* ---- Cards (admin grid look, §6) ---- */
.card {
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  padding: var(--sp-4);
}

/* ---- Image block (handoff/01 §4.2): size → width, position → align, radius ---- */
figure.image-block {
  margin: var(--sp-3) 0;
  /* --w = widthPct; alignment set by modifier classes below */
  width: var(--w, 60%);
  max-width: 100%;
}
figure.image-block img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-md);
}
figure.image-block.align-left  { margin-right: auto; margin-left: 0; }
figure.image-block.align-center { margin-left: auto; margin-right: auto; }
figure.image-block.align-right { margin-left: auto; margin-right: 0; }
figure.image-block figcaption {
  margin-top: var(--sp-1);
  font-size: var(--fs-sm);
  color: var(--c-ink-soft);
  text-align: center;
}

/* ---- Panel scaffold (shared by guest 05 / admin preview 06) ---- */
.panel {
  padding-top: var(--panel-pad-y);
  padding-bottom: var(--panel-pad-y);
  padding-inline: var(--sp-3);
}
.panel.pad-compact { --panel-pad-y: var(--pad-compact); }
.panel.pad-comfortable { --panel-pad-y: var(--pad-comfortable); }
.panel.pad-spacious { --panel-pad-y: var(--pad-spacious); }
.panel-content {
  max-width: var(--content-max);
  margin-inline: auto;
}


/**
 * site.css — guest-site layout & interaction skin (handoff/04 §4, handoff/05 §2–§8).
 *
 * Loaded AFTER fonts.css + tokens.css + components.css (all concatenated into one
 * /assets/site.css at render). Only nav / panel / hero / footer / block layout lives
 * here; every colour comes through CSS variables so per-site settings (background,
 * accent, per-panel bg) cascade without any rule rewrites. Built entirely on the
 * design tokens — no hard-coded hexes.
 */

:root {
  --nav-h: 4.25rem; /* sticky-bar height: drives anchor offset + snap padding */
}

/* ---------------------------------------------------------------------------
 * Scroll feel — "one page to the next" via proximity snap on the scroll root.
 * Proximity (not mandatory) never fights the user; svh keeps mobile chrome from
 * causing jumps. scroll-padding-top clears the sticky bar on jumps + snaps.
 * ------------------------------------------------------------------------- */
html {
  scroll-behavior: smooth;
  scroll-snap-type: y proximity;
  scroll-padding-top: var(--nav-h);
}
body {
  background: var(--c-bg);
  /* Guard against a stray horizontal scrollbar. `clip` (not `hidden`) is used
   * deliberately: `overflow-x:hidden` would make <body> a scroll container and
   * break the sticky nav; `clip` prevents overflow without that side effect. */
  overflow-x: clip;
}

/* skip-link for keyboard users */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--c-accent); color: var(--c-accent-ink);
  padding: var(--sp-1) var(--sp-2); border-radius: 0 0 var(--radius-sm) 0;
  font-weight: 700;
}
.skip-link:focus { left: 0; }

/* ============================ Nav (dropdown) ============================ */
/* Default: a quiet translucent bar (works with JS off). guest.js adds `.is-top`
 * while the hero fills the view so the bar is nearly invisible until you scroll. */
.site-nav {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--c-bg) 85%, transparent);
  backdrop-filter: saturate(1.1) blur(10px);
  -webkit-backdrop-filter: saturate(1.1) blur(10px);
  border-bottom: 1px solid var(--c-line);
  transition:
    background-color var(--dur-ui) var(--ease-out),
    border-color var(--dur-ui) var(--ease-out),
    box-shadow var(--dur-ui) var(--ease-out);
}
.site-nav.is-top {
  background: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}
.site-nav__inner {
  max-width: 1100px; margin-inline: auto;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); padding: var(--sp-2) var(--sp-3);
  min-height: var(--nav-h);
}
.site-nav__brand {
  font-family: var(--ff-serif); font-optical-sizing: auto;
  font-size: var(--fs-h3); font-weight: 500; color: var(--c-ink);
  text-decoration: none; letter-spacing: var(--tracking-head);
  display: inline-flex; align-items: center; min-height: 44px;
  /* shrink gracefully so the Menu button never gets pushed off a narrow screen */
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.site-nav__brand:hover { text-decoration: none; color: var(--c-accent); }
.site-nav__menu { position: relative; flex: 0 0 auto; }

.site-nav__toggle {
  display: inline-flex; align-items: center; gap: .5em;
  min-height: 44px; /* tap target */
  font-family: var(--ff-sans); font-size: var(--fs-sm); font-weight: 700; color: var(--c-ink);
  background: transparent; border: 1.5px solid var(--c-line);
  border-radius: var(--radius-pill); padding: .5em 1.1em; cursor: pointer;
  transition: border-color var(--dur-ui) var(--ease-out), background-color var(--dur-ui) var(--ease-out);
}
.site-nav__toggle:hover { border-color: var(--c-accent); }
.site-nav__chevron {
  width: .5em; height: .5em; border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translateY(-1px); transition: transform var(--dur-ui) var(--ease-out);
}
.site-nav__toggle[aria-expanded="true"] .site-nav__chevron { transform: rotate(-135deg) translateY(1px); }

.site-nav__list {
  list-style: none; margin: 0; padding: var(--sp-1);
  position: absolute; right: 0; top: calc(100% + .5rem); min-width: 13rem;
  background: var(--c-surface); border: 1px solid var(--c-line);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lift);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition:
    opacity var(--dur-ui) var(--ease-out),
    transform var(--dur-ui) var(--ease-out),
    visibility var(--dur-ui);
}
.site-nav__toggle[aria-expanded="true"] + .site-nav__list {
  opacity: 1; visibility: visible; transform: none;
}
.site-nav__list li { margin: 0; }
.site-nav__list a {
  display: flex; align-items: center; min-height: 44px; /* tap target */
  padding: .55em .85em; border-radius: var(--radius-sm);
  color: var(--c-ink); text-decoration: none; font-weight: 600; font-size: var(--fs-sm);
  transition: background-color var(--dur-ui) var(--ease-out), color var(--dur-ui) var(--ease-out);
}
.site-nav__list a:hover, .site-nav__list a:focus-visible {
  background: color-mix(in srgb, var(--c-accent) 12%, transparent);
  color: var(--c-ink); text-decoration: none;
}

/* ============================ Panels ============================ */
.panels { display: block; }
.panel {
  position: relative;
  background: var(--panel-bg, var(--c-bg));
  scroll-snap-align: start;
  scroll-margin-top: var(--nav-h); /* anchor jumps clear the sticky bar */
  padding-inline: var(--sp-3);
}
.panel--has-image {
  background-image: var(--panel-bg-image);
  background-size: cover; background-position: center;
}
.panel--has-image .panel-content { color: var(--c-accent-ink); }
.panel-content {
  max-width: var(--content-max, 820px); /* per-panel override via inline --content-max */
  margin-inline: auto; width: 100%;
}

/* height behaviour (§2): full fills the viewport, fit shrinks to content, custom = Nvh */
.panel[data-height="full"] {
  min-height: 100svh; display: flex; flex-direction: column;
  padding-block: var(--panel-pad-y);
}
.panel[data-height="fit"] { padding-block: var(--panel-pad-y); }
.panel[data-height="custom"] {
  min-height: var(--panel-minh, 60vh); display: flex; flex-direction: column;
  padding-block: var(--panel-pad-y);
}
/* vertical alignment within full/custom panels */
.panel[data-valign="start"]  { justify-content: flex-start; }
.panel[data-valign="center"] { justify-content: center; }
.panel[data-valign="end"]    { justify-content: flex-end; }

/* per-panel padding scale (maps handoff/01 padding tokens) */
.panel.pad-compact { --panel-pad-y: var(--pad-compact); }
.panel.pad-comfortable { --panel-pad-y: var(--pad-comfortable); }
.panel.pad-spacious { --panel-pad-y: var(--pad-spacious); }

/* Alternating subtle warmth between stacked content panels (§2): a whisper of
 * extra warmth on every other section creates rhythm without hard lines. Skips
 * the hero and any image-backed panel. Respects the panel's own --panel-bg base. */
.panel:not(.panel--hero):not(.panel--has-image):nth-of-type(even) {
  background: color-mix(in srgb, var(--panel-bg, var(--c-bg)) 90%, var(--c-line));
}

/* ============================ Hero ============================ */
.panel--hero { text-align: center; }
.panel--hero .panel-content { max-width: 42rem; }

/* logo slot — real uploaded logo (image block) */
.panel--hero .image-block { margin-inline: auto; margin-bottom: var(--sp-3); }

/* logo slot — monogram placeholder until a logo is uploaded */
.hero__logo--placeholder { display: flex; justify-content: center; margin-bottom: var(--sp-3); }
.hero__monogram {
  display: grid; place-items: center;
  width: clamp(4.75rem, 12vw, 7rem); aspect-ratio: 1;
  border-radius: var(--radius-pill);
  font-family: var(--ff-serif); font-weight: 500; font-optical-sizing: auto;
  font-size: clamp(1.9rem, 5vw, 2.9rem); line-height: 1;
  color: var(--c-accent);
  background: color-mix(in srgb, var(--c-accent) 12%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-accent) 28%, transparent);
  box-shadow: var(--shadow-soft);
}

.panel--hero .block--heading :is(h1, h2, h3) {
  font-size: var(--fs-display); font-weight: 480; letter-spacing: -0.015em;
}
.panel--hero .block--body {
  color: var(--c-ink-soft); font-size: var(--fs-h3); font-weight: 400; max-width: none;
}

/* gentle scroll-cue chevron pinned to the bottom of the hero */
.hero__scroll-cue {
  position: absolute; left: 50%; bottom: clamp(1rem, 4vh, 2.5rem);
  transform: translateX(-50%);
  display: grid; place-items: center; width: 44px; height: 44px; /* tap target */
  color: var(--c-ink-soft); text-decoration: none;
  transition: color var(--dur-ui) var(--ease-out);
}
.hero__scroll-cue:hover { color: var(--c-accent); text-decoration: none; }
.hero__scroll-chevron {
  width: .8rem; height: .8rem;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  animation: hero-bob 2.4s var(--ease-out) infinite;
}
@keyframes hero-bob {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: .5; }
  50%      { transform: rotate(45deg) translate(3px, 3px); opacity: 1; }
}

/* ============================ Blocks ============================ */
.block + .block { margin-top: var(--sp-3); }

.block--text.align-left   { text-align: left; }
.block--text.align-center { text-align: center; }
.block--text.align-right  { text-align: right; }
/* readable measure for body copy; alignment also positions the column */
.block--body { max-width: var(--measure); }
.block--body.align-center { margin-inline: auto; }
.block--body.align-right { margin-inline: auto 0; }
.panel--hero .block--body { max-width: none; }

.block--heading :is(h1, h2, h3) { margin: 0; }

/* editorial accent rule under section headings (not the hero) */
.panel:not(.panel--hero) .block--heading :is(h2, h3)::after {
  content: ""; display: block; width: 2.5rem; height: 3px; margin-top: .7rem;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--c-accent) 70%, transparent);
}
.block--heading.align-center :is(h2, h3)::after { margin-inline: auto; }
.block--heading.align-right  :is(h2, h3)::after { margin-inline: auto 0; }

/* image block placeholder (no upload yet / missing file) */
.image-block--placeholder {
  display: grid; place-items: center; aspect-ratio: 3 / 2;
  background: repeating-linear-gradient(45deg,
    color-mix(in srgb, var(--c-line) 55%, transparent) 0 12px,
    color-mix(in srgb, var(--c-line) 25%, transparent) 12px 24px);
  color: var(--c-ink-soft); font-size: var(--fs-sm); text-align: center; padding: var(--sp-3);
}

/* honeypot: visually + a11y hidden, still submitted by bots */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ============================ Contact form ============================ */
/* An inviting, centred card — not a wall of inputs (§7). The heading keeps
 * whatever alignment the model gives it; the form card is always centred. */
.contact-form {
  max-width: 34rem; margin-inline: auto; width: 100%;
  text-align: left;
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
  padding: clamp(1.5rem, 4vw, 2.5rem);
}
.contact-form .field:last-of-type { margin-bottom: 0; }
.form-actions { margin-top: var(--sp-3); display: flex; justify-content: center; }
.form-actions .btn { min-width: 12rem; }
.form-error {
  color: #9b2c2c; margin-top: var(--sp-2); font-weight: 600; text-align: center;
}
.form-success {
  margin: 0; padding: var(--sp-3);
  background: var(--hl-2); border-radius: var(--radius-md); color: var(--c-ink);
  text-align: center; font-weight: 600;
}

/* ============================ Footer ============================ */
.site-footer {
  background: var(--footer-bg, var(--c-footer-bg));
  color: var(--footer-ink, var(--c-footer-ink));
  padding: var(--sp-5) var(--sp-3);
  /* Give the footer its own snap point (aligned to the viewport bottom) so scrolling
   * down rests on it instead of the panels' proximity-snap yanking back up. */
  scroll-snap-align: end;
}
.site-footer__inner {
  max-width: var(--content-max); margin-inline: auto; text-align: center;
  color: var(--footer-ink, var(--c-footer-ink));
}
.site-footer a { color: var(--footer-ink, var(--c-footer-ink)); text-decoration: underline; }
.site-footer a:hover { text-decoration: underline; opacity: .85; }

/* ============================ Responsive ============================ */
@media (max-width: 480px) {
  .site-nav__inner { padding-inline: var(--sp-2); gap: var(--sp-1); }
  .site-nav__brand { font-size: var(--fs-body); } /* keep brand + Menu on one line */
  .contact-form { padding: var(--sp-3); }
  .form-actions .btn { width: 100%; }
}

/* ============================ Motion guards ============================ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-snap-type: none; scroll-behavior: auto; }
  .hero__scroll-chevron { animation: none; }
  .site-nav { transition: none; }
}
