/* ============================================================
   FONTS — General Sans self-hosted from fonts/general-sans/.
   Previously loaded from Fontshare's CDN API, which started returning
   "Access to the Fontshare API has been temporarily restricted" instead
   of font data, silently dropping every heading to the browser's
   fallback sans-serif. Self-hosting removes that single point of failure.
============================================================ */
@font-face {
  font-family: 'General Sans';
  src: url('../fonts/general-sans/GeneralSans-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'General Sans';
  src: url('../fonts/general-sans/GeneralSans-Semibold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'General Sans';
  src: url('../fonts/general-sans/GeneralSans-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Cabinet Grotesk for headings — shared with the landing page, self-hosted
   from fonts/cabinet-grotesk/ (see index.html for why it's off Fontshare's CDN).
   Cabinet Grotesk has no 600 weight, so headings set to font-weight: 600 resolve
   up to the 700 face and render Bold. */
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../fonts/cabinet-grotesk/CabinetGrotesk-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../fonts/cabinet-grotesk/CabinetGrotesk-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ============================================================
   DESIGN TOKENS
============================================================ */
:root {
  --green: oklch(52% 0.15 158);
  --green-hover: oklch(46% 0.15 158);
  --green-text: oklch(40% 0.14 158);
  --green-pale: oklch(94% 0.03 158);
  --bg: oklch(0.989 0 0);
  --surface: oklch(100% 0 0);
  --surface-sunken: oklch(96% 0.012 158);
  /* Same raw value as --surface, but a distinct token on purpose: --surface names a
     background role (cards, form fields), --white names a text/icon-fill role (white
     text on the green buttons, white text on the dark closing band). */
  --white: oklch(100% 0 0);
  --ink: #071a31; /* navy, shared with the landing page (was oklch(21% 0.02 158)) */
  --ink-muted: oklch(42% 0.02 158);
  --border: oklch(90% 0.01 158);
  --danger: oklch(55% 0.19 25);
  --danger-pale: oklch(96% 0.03 25);
  --danger-text: oklch(42% 0.17 25);
  --deep: oklch(26% 0.05 158);
  --deep-2: oklch(20% 0.045 158);
  --on-deep: oklch(97% 0.006 158);
  --on-deep-muted: oklch(78% 0.02 158);
  /* Section backgrounds are true achromatic neutrals (chroma 0), matching --bg's own
     chroma-0 value. Green stays reserved for the nav, buttons, selected states, and
     the closing band, where it's genuinely Karibify's or an interactive accent, not
     a backdrop any business's own brand has to sit on top of. */
  --section-bg-light: oklch(100% 0 0);
  --section-bg-deep: oklch(98% 0 0);
  --radius-btn: 10px;
  --radius-card: 18px;
  --font-display: 'MuseoModerno', sans-serif;   /* wordmark only */
  --font-heading: 'Cabinet Grotesk', 'General Sans', sans-serif;
  --font-body: 'DM Sans', sans-serif;
  --shadow-card: 0 16px 40px oklch(52% 0.15 158 / 0.08);
  --shadow-tile: 0 8px 20px oklch(52% 0.15 158 / 0.06);
}

/* Deliberately light-mode only: no data-theme system, no toggle. This surface is
   for the business's own clients (general public, often arriving from an Instagram
   or WhatsApp link), not a tech-savvy crowd who'd expect a dark UI. */

/* ============================================================
   RESET & BASE
============================================================ */
.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;
}
.hidden { display: none !important; }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* overflow-x:hidden stays on <html> only. Putting it on <body> too makes body a
   scroll container, which becomes the containing block for position:sticky .nav
   — and since body never scrolls independently, the sticky nav gets carried
   off-screen as the page scrolls. Same fix as the landing page (commit a1161ee). */
html { overflow-x: hidden; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  line-height: 1.55;
}
a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; display: block; }
button { cursor: pointer; border: none; background: none; font-family: inherit; }

.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.section { padding: 88px 0; position: relative; }
@media (max-width: 768px) { .section { padding: 56px 0; } }

.eyebrow { display: inline-block; font-weight: 500; font-size: 0.8125rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--green-text); }

h1, h2, h3 { margin: 0; }
h2 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 1.875rem;
  letter-spacing: -0.005em;
  line-height: 1.2;
  color: var(--ink);
  text-wrap: balance;
}
@media (min-width: 1024px) { h2 { font-size: 2.25rem; } }

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: 50px; padding: 0 26px; border-radius: var(--radius-btn);
  font-family: var(--font-body); font-weight: 500; font-size: 0.9375rem;
  border: none; cursor: pointer; white-space: nowrap;
  transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.btn:active { transform: translateY(1px) scale(0.98); }
.btn-primary { background: var(--green); color: var(--white); }
.btn-primary:hover { background: var(--green-hover); transform: translateY(-1px); box-shadow: 0 10px 28px oklch(52% 0.15 158 / 0.28); }
.btn-outline { background: transparent; border: 1.5px solid var(--green); color: var(--green-text); }
.btn-outline:hover { background: var(--green-pale); }
.btn-sm { height: 44px; padding: 0 18px; font-size: 0.875rem; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn:disabled:hover { transform: none; box-shadow: none; }

a:focus-visible, button:focus-visible, select:focus-visible, input:focus-visible, textarea:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--bg), 0 0 0 5px var(--green);
}

/* Resting state uses "transform: none", not "translateY(0)" - the two render identically,
   but translateY(0) is still a non-none transform, which makes the element a new
   containing block for any position:fixed descendant (like the mobile booking-ticket
   panel), trapping it instead of leaving it fixed to the real viewport. */
/* Hidden state only applies once .has-js confirms the reveal script actually loaded.
   Without JS, content is visible by default instead of stuck at opacity:0 forever.
   The JS itself also carries a timeout fail-safe in case the observer never fires. */
html.has-js [data-reveal] { opacity: 0; transform: translateY(20px); transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1); }
html.has-js [data-reveal].is-visible { opacity: 1; transform: none; }
html.has-js [data-reveal-stagger] > * { opacity: 0; transform: translateY(18px); transition: opacity 0.55s cubic-bezier(0.16, 1, 0.3, 1), transform 0.55s cubic-bezier(0.16, 1, 0.3, 1); }
html.has-js [data-reveal-stagger].is-visible > * { opacity: 1; transform: none; }
[data-reveal-stagger].is-visible > *:nth-child(1) { transition-delay: 0s; }
[data-reveal-stagger].is-visible > *:nth-child(2) { transition-delay: 0.06s; }
[data-reveal-stagger].is-visible > *:nth-child(3) { transition-delay: 0.12s; }
[data-reveal-stagger].is-visible > *:nth-child(4) { transition-delay: 0.18s; }
[data-reveal-stagger].is-visible > *:nth-child(5) { transition-delay: 0.24s; }
[data-reveal-stagger].is-visible > *:nth-child(6) { transition-delay: 0.3s; }
@media (prefers-reduced-motion: reduce) {
  [data-reveal], [data-reveal-stagger] > * { opacity: 1 !important; transform: none !important; transition: none !important; }
  .nav, .btn, .portfolio-item img, .hours-chevron, .hours-detail-wrap, .date-pill, .slot-btn, .social-btn,
  .step-route-fill, .booking-ticket-col, .ticket-card, .ticket-body dd, .step-panel,
  .service-pick-extra-wrap, .service-pick-toggle-chevron, .date-strip-arrow, .service-card,
  .lightbox, .lightbox-content, .portfolio-expand-icon, .hero-photo-card, .hero-photo-glow,
  .btn-spinner { transition: none !important; animation: none !important; }
  /* Disabling the float animation removes its transform too, so the resting rotation
     has to be set explicitly here, or the cards would render perfectly upright instead
     of at their intended angle. */
  .hero-photo-primary .hero-photo-card { transform: rotate(-2deg) !important; }
  .hero-photo-support-a .hero-photo-card { transform: rotate(4deg) !important; }
  .hero-photo-support-b .hero-photo-card { transform: rotate(-5deg) !important; }
}

/* ============================================================
   SKELETON
============================================================ */
.page-skeleton {
  position: fixed; inset: 0; z-index: 9999;
  background: var(--bg);
  display: flex; flex-direction: column;
  transition: opacity 0.3s ease;
}
.page-skeleton.fade-out { opacity: 0; pointer-events: none; }
.skel-nav { height: 64px; background: var(--surface-sunken); animation: skel-pulse 1.4s ease-in-out infinite; }
.skel-hero {
  flex: 1; max-height: 500px; background: var(--surface);
  display: flex; align-items: center; justify-content: center; padding: 3rem;
  animation: skel-pulse 1.4s ease-in-out infinite;
}
.skel-hero-inner { display: flex; flex-direction: column; gap: 1rem; max-width: 360px; width: 100%; align-items: center; }
.skel-line { border-radius: 6px; background: var(--border); }
.skel-line-lg { height: 36px; width: 70%; animation: skel-pulse 1.4s 0s ease-in-out infinite; }
.skel-line-md { height: 18px; width: 50%; animation: skel-pulse 1.4s 0.1s ease-in-out infinite; }
.skel-line-sm { height: 14px; width: 35%; animation: skel-pulse 1.4s 0.2s ease-in-out infinite; }
@keyframes skel-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }

/* ---------- nav ---------- */
.nav { position: sticky; top: 0; z-index: 100; background: oklch(99% 0.004 158 / 0.86); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--border); transition: box-shadow 0.3s ease; }
.nav.is-scrolled { box-shadow: 0 1px 0 var(--border), 0 8px 24px oklch(52% 0.15 158 / 0.05); }
.nav-inner { max-width: 1200px; margin: 0 auto; padding: 16px 24px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
/* The business's own name stands in for a logo — this is their site, not Karibify's.
   min-width:0 + ellipsis lets a long name truncate instead of shoving the nav around. */
.nav-brand { display: flex; align-items: center; min-width: 0; }
.nav-brand-name { font-family: var(--font-heading); font-weight: 600; font-size: 1.3rem; color: var(--ink); letter-spacing: -0.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-links { display: flex; gap: 28px; align-items: center; flex-shrink: 0; }
.nav-links a { font-size: 0.9375rem; font-weight: 500; color: var(--ink-muted); }
.nav-links a:hover { color: var(--ink); }
.nav-actions { display: flex; align-items: center; gap: 16px; flex-shrink: 0; }
.nav .btn { height: 44px; padding: 0 20px; font-size: 0.9375rem; }
@media (max-width: 860px) {
  .nav-links { display: none; }
  .nav-brand-name { font-size: 1.2rem; }
}

/* ---------- hero ---------- */
.hero { position: relative; padding: 40px 0 32px; }
@media (min-width: 640px) { .hero { padding: 56px 0 40px; } }
@media (min-width: 860px) { .hero { padding: 88px 0 88px; } }
.hero-inner { display: grid; grid-template-columns: 1fr; gap: 40px; align-items: center; }
@media (min-width: 860px) { .hero-inner { grid-template-columns: minmax(360px, 1fr) minmax(420px, 1.15fr); gap: 64px; } }
/* Zero-photo businesses: the photo stack is removed from the DOM entirely, so the
   text column becomes the grid's only track and fills the full width. */
.hero-inner.is-text-only { grid-template-columns: 1fr; }
.hero-content { position: relative; z-index: 1; }

.hero h1 { font-family: var(--font-heading); font-weight: 600; font-size: 2.25rem; line-height: 1.1; letter-spacing: -0.01em; color: var(--ink); margin-top: 12px; text-wrap: balance; }
@media (min-width: 640px) { .hero h1 { font-size: 2.75rem; line-height: 1.08; } }
@media (min-width: 860px) { .hero h1 { font-size: 3.75rem; line-height: 1.05; } }
.hero-sub { font-size: 1.0625rem; line-height: 1.6; color: var(--ink-muted); margin: 16px 0 0; max-width: 44ch; text-wrap: pretty; }
.hero-sub:empty { display: none; }
.hero-actions { margin-top: 28px; display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
@media (min-width: 560px) { .hero-actions { flex-direction: row; } }

/* ---------- hero photo stack ---------- */
.hero-photo-stack { position: relative; width: 260px; height: 300px; margin: 0; }
@media (min-width: 860px) { .hero-photo-stack { width: 100%; max-width: 460px; height: 460px; } }
/* With only 1 photo, shrink the stack to hug the single card instead of leaving the
   empty space the missing support cards would have occupied. */
.hero-photo-stack[data-count="1"] { height: 260px; }
@media (min-width: 860px) { .hero-photo-stack[data-count="1"] { width: 288px; height: 384px; justify-self: end; } }
/* 2 photos: primary + support-a only, no support-b - same "shrink to what's actually
   rendered" principle as the 1-photo variant above. */
.hero-photo-stack[data-count="2"] { height: 300px; }
@media (min-width: 860px) { .hero-photo-stack[data-count="2"] { width: 400px; height: 420px; justify-self: end; } }
.hero-photo-glow {
  position: absolute; inset: -40px -40px auto -40px; height: 340px;
  background: radial-gradient(ellipse, var(--green-pale) 0%, transparent 70%);
  filter: blur(30px); z-index: 0; pointer-events: none;
}
.hero-photo-card-wrap { position: absolute; }
.hero-photo-card {
  display: block; width: 100%; height: 100%; overflow: hidden;
  box-shadow: var(--shadow-tile);
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s ease, z-index 0s;
}
.hero-photo-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero-photo-card:hover {
  transform: translateY(-6px) scale(1.03) rotate(0deg) !important;
  box-shadow: 0 30px 60px oklch(52% 0.15 158 / 0.22);
  z-index: 5;
  animation-play-state: paused;
}

.hero-photo-primary { width: 208px; height: 260px; top: 0; right: 0; }
.hero-photo-support-a { width: 128px; height: 160px; bottom: 0; left: 0; }
.hero-photo-support-b { display: none; }
@media (min-width: 860px) {
  .hero-photo-primary { width: 288px; height: 384px; top: 0; right: 0; }
  .hero-photo-support-a { width: 176px; height: 220px; bottom: 24px; left: 0; }
  .hero-photo-support-b { display: block; width: 200px; height: 150px; top: 40px; left: 40px; }
}
/* [data-count="2"] never shows support-b at any width - the "display:block at 860px"
   base rule above only applies when support-b is actually present in the DOM. */
.hero-photo-stack[data-count="1"] .hero-photo-support-a,
.hero-photo-stack[data-count="1"] .hero-photo-support-b,
.hero-photo-stack[data-count="2"] .hero-photo-support-b { display: none !important; }

.hero-photo-primary .hero-photo-card { border-radius: 22px; box-shadow: 0 24px 48px oklch(52% 0.15 158 / 0.16); }
.hero-photo-support-a .hero-photo-card, .hero-photo-support-b .hero-photo-card { border-radius: var(--radius-card); box-shadow: 0 16px 32px oklch(52% 0.15 158 / 0.12); }

.hero-photo-primary .hero-photo-card { animation: hero-float-primary 6s ease-in-out 0.2s infinite; }
.hero-photo-support-a .hero-photo-card { animation: hero-float-support-a 7s ease-in-out 0.6s infinite; }
.hero-photo-support-b .hero-photo-card { animation: hero-float-support-b 6.5s ease-in-out 1s infinite; }
@keyframes hero-float-primary { 0%, 100% { transform: rotate(-2deg) translateY(0); } 50% { transform: rotate(-2deg) translateY(-10px); } }
@keyframes hero-float-support-a { 0%, 100% { transform: rotate(4deg) translateY(0); } 50% { transform: rotate(4deg) translateY(-12px); } }
@keyframes hero-float-support-b { 0%, 100% { transform: rotate(-5deg) translateY(0); } 50% { transform: rotate(-5deg) translateY(-8px); } }
@media (max-width: 859px) {
  .hero-photo-primary .hero-photo-card, .hero-photo-support-a .hero-photo-card { animation: none; }
  .hero-photo-primary .hero-photo-card { transform: rotate(-2deg); }
  .hero-photo-support-a .hero-photo-card { transform: rotate(4deg); }
}

/* ---------- section banding ---------- */
/* Each section gets its own neutral backdrop rather than a shared "sunken" green tint,
   so the page reads as a clean template any business's own brand can sit on top of. */
#portfolio { background: var(--section-bg-light); }
#about { background: var(--section-bg-deep); }
#services { background: var(--section-bg-light); }
#booking { background: var(--section-bg-deep); }
.section-head { margin-bottom: 32px; display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.section-head .meta { color: var(--ink-muted); font-size: 0.9375rem; }

/* ---------- portfolio ---------- */
/* Businesses can have 0-12 portfolio photos. The 6-photo mosaic is the default/most
   common case, but a brand-new business with zero or one photo is exactly when a
   confidence-building profile matters most. Each [data-count] variant is a deliberate
   composition; past 6 photos there's no more art-directing to do, so that count
   switches to a plain scalable grid instead of inventing more one-offs. */
.portfolio-grid { display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(3, 170px); grid-template-areas: "a a b c" "a a d d" "e e f f"; gap: 14px; }
.portfolio-grid[hidden] { display: none; }
@media (min-width: 700px) { .portfolio-grid { grid-template-rows: repeat(3, 210px); } }
@media (max-width: 640px) { .portfolio-grid { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(4, 170px); grid-template-areas: "a a" "b c" "d d" "e f"; } }
.portfolio-item { grid-area: var(--area); position: relative; }
.portfolio-item.item-a { --area: a; } .portfolio-item.item-b { --area: b; } .portfolio-item.item-c { --area: c; }
.portfolio-item.item-d { --area: d; } .portfolio-item.item-e { --area: e; } .portfolio-item.item-f { --area: f; }

.portfolio-grid[data-count="1"] .portfolio-item:nth-child(n+2),
.portfolio-grid[data-count="2"] .portfolio-item:nth-child(n+3),
.portfolio-grid[data-count="3"] .portfolio-item:nth-child(n+4),
.portfolio-grid[data-count="4"] .portfolio-item:nth-child(n+5),
.portfolio-grid[data-count="5"] .portfolio-item:nth-child(n+6) { display: none; }

.portfolio-grid[data-count="1"] { grid-template-columns: 1fr; grid-template-rows: 320px; grid-template-areas: "a"; }

.portfolio-grid[data-count="2"] { grid-template-columns: 1.4fr 1fr; grid-template-rows: 320px; grid-template-areas: "a b"; }
@media (max-width: 640px) { .portfolio-grid[data-count="2"] { grid-template-columns: 1fr; grid-template-rows: repeat(2, 220px); grid-template-areas: "a" "b"; } }

.portfolio-grid[data-count="3"] { grid-template-columns: 1.6fr 1fr; grid-template-rows: repeat(2, 160px); grid-template-areas: "a b" "a c"; }
@media (min-width: 700px) { .portfolio-grid[data-count="3"] { grid-template-rows: repeat(2, 200px); } }
@media (max-width: 640px) { .portfolio-grid[data-count="3"] { grid-template-columns: repeat(2, 1fr); grid-template-rows: 220px 170px; grid-template-areas: "a a" "b c"; } }

.portfolio-grid[data-count="4"] { grid-template-columns: repeat(3, 1fr); grid-template-rows: 220px 170px; grid-template-areas: "a a a" "b c d"; }
@media (max-width: 640px) { .portfolio-grid[data-count="4"] { grid-template-columns: repeat(2, 1fr); grid-template-rows: 200px repeat(2, 150px); grid-template-areas: "a a" "b c" "d d"; } }

.portfolio-grid[data-count="5"] { grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(3, 170px); grid-template-areas: "a a b c" "a a d d" "e e e e"; }
@media (min-width: 700px) { .portfolio-grid[data-count="5"] { grid-template-rows: repeat(3, 210px); } }
@media (max-width: 640px) { .portfolio-grid[data-count="5"] { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(4, 170px); grid-template-areas: "a a" "b c" "d d" "e e"; } }

/* 7-12 photos: no more bespoke mosaics past this point - the pattern just keeps
   adding same-sized tiles as auto-fill wraps them into new rows. */
.portfolio-grid[data-count="7"] { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); grid-template-areas: none; grid-auto-rows: 200px; }
.portfolio-grid[data-count="7"] .portfolio-item { grid-area: auto; }

.portfolio-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; padding: 64px 32px; background: var(--surface-sunken); border-radius: var(--radius-card); }
.portfolio-empty[hidden] { display: none; }
.portfolio-empty-icon { display: flex; align-items: center; justify-content: center; width: 52px; height: 52px; border-radius: 50%; background: var(--surface); color: var(--ink-muted); margin-bottom: 6px; }
.portfolio-empty-title { font-family: var(--font-heading); font-weight: 500; font-size: 1.125rem; color: var(--ink); margin: 0; }
.portfolio-empty-body { color: var(--ink-muted); font-size: 0.9375rem; max-width: 340px; margin: 0 0 6px; }

/* The rounded-corner clip lives on .portfolio-media, one layer inside the button,
   not on .portfolio-item or .portfolio-trigger itself. An ancestor's overflow:hidden
   clips a focused descendant's focus-visible ring the same way it clips anything else
   that paints past the clip edge - so the button that receives the ring has to stay
   unclipped, with only its inner media wrapper cropping the photo and its hover-zoom. */
.portfolio-trigger { display: block; width: 100%; height: 100%; border: none; padding: 0; margin: 0; background: none; cursor: pointer; border-radius: 14px; }
.portfolio-media { display: block; width: 100%; height: 100%; overflow: hidden; border-radius: 14px; }
.portfolio-item img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1); }
.portfolio-item:hover img { transform: scale(1.05); }
.portfolio-expand-icon { position: absolute; top: 12px; right: 12px; width: 32px; height: 32px; border-radius: 50%; background: oklch(15% 0.02 158 / 0.55); color: var(--white); display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.2s ease; pointer-events: none; }
.portfolio-item:hover .portfolio-expand-icon, .portfolio-trigger:focus-visible ~ .portfolio-expand-icon { opacity: 1; }

/* ---------- portfolio lightbox: full, uncropped image, click to open ---------- */
.lightbox { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; padding: 56px 24px; opacity: 0; transition: opacity 0.25s ease; }
.lightbox[hidden] { display: none; }
.lightbox.is-visible { opacity: 1; }
.lightbox-backdrop { position: absolute; inset: 0; background: oklch(12% 0.02 158 / 0.86); }
.lightbox-close { position: absolute; top: 20px; right: 20px; z-index: 1; width: 44px; height: 44px; border-radius: 50%; background: rgba(255, 255, 255, 0.12); border: 1px solid rgba(255, 255, 255, 0.25); color: var(--white); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.2s ease; }
.lightbox-close:hover { background: rgba(255, 255, 255, 0.22); }
.lightbox-content { position: relative; z-index: 1; max-width: 90vw; max-height: 85vh; display: flex; flex-direction: column; align-items: center; gap: 14px; transform: scale(0.96); transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1); }
.lightbox.is-visible .lightbox-content { transform: scale(1); }
.lightbox-img { display: block; max-width: 90vw; max-height: 76vh; width: auto; height: auto; object-fit: contain; border-radius: 12px; box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5); }

/* ---------- about ---------- */
.about-inner { display: flex; flex-direction: column-reverse; gap: 36px; }
@media (min-width: 900px) { .about-inner { flex-direction: row; align-items: flex-start; gap: 56px; } .about-text { flex: 1.1; } .about-photo-col { flex: 0.9; } }
.about-photo-col[hidden] { display: none; }
.about-photo-frame { width: 100%; max-width: 360px; aspect-ratio: 4 / 5; border-radius: 20px; overflow: hidden; border: 1px solid var(--border); box-shadow: var(--shadow-card); margin: 0 auto; }
.about-photo-frame img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Square-or-wider uploads (logos, wordmarks, graphics) are a designed asset,
   not a croppable photo: forcing one into the tall 4:5 frame above crops off
   most of it. js/profile.js measures the loaded image's real dimensions and
   adds this class when the ratio calls for it, so the frame instead sizes
   itself to the image's own shape with no cropping. */
.about-photo-frame.is-logo { aspect-ratio: auto; height: auto; }
.about-photo-frame.is-logo img { height: auto; object-fit: contain; background: var(--surface); }
.about-body { color: var(--ink-muted); line-height: 1.75; font-size: 1.0625rem; max-width: 60ch; margin-top: 16px; text-wrap: pretty; white-space: pre-wrap; }

.hours-block { margin-top: 28px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); }
.hours-block[hidden] { display: none; }
.hours-summary { width: 100%; display: flex; align-items: center; gap: 12px; padding: 16px 18px; background: none; border: none; cursor: pointer; text-align: left; font-family: var(--font-body); font-weight: 500; color: var(--ink); }
.hours-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); flex-shrink: 0; }
.hours-summary-text { flex: 1; }
.hours-chevron { flex-shrink: 0; color: var(--ink-muted); transition: transform 0.25s ease; }
.hours-block.open .hours-chevron { transform: rotate(180deg); }
.hours-detail-wrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.3s ease; }
.hours-block.open .hours-detail-wrap { grid-template-rows: 1fr; }
.hours-detail-inner { overflow: hidden; }
.hours-row { display: flex; justify-content: space-between; padding: 8px 18px; font-size: 0.9375rem; color: var(--ink-muted); border-top: 1px solid var(--border); }
.hours-row.is-today { color: var(--ink); font-weight: 500; }
.hours-row:last-child { padding-bottom: 16px; }

/* ---------- services: peek strip + full-view toggle ---------- */
.service-view-toggle { flex-shrink: 0; }
.service-view-toggle[hidden] { display: none; }
.service-browser { position: relative; }
.service-strip { display: grid; grid-auto-flow: row; grid-template-rows: repeat(2, auto); grid-template-columns: repeat(var(--strip-cols, 10), 260px); gap: 18px; overflow-x: auto; scroll-snap-type: x mandatory; padding: 2px; scrollbar-width: none; -ms-overflow-style: none; }
.service-strip::-webkit-scrollbar { display: none; }
.service-strip .service-card { scroll-snap-align: start; }
.service-browser.is-grid-view .date-strip-nav { display: none; }
.service-browser.is-grid-view .service-strip { grid-template-rows: none; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); overflow: visible; scroll-snap-type: none; }
.service-browser.is-grid-view .service-strip .service-card { scroll-snap-align: none; }
.service-collapse-btn { width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; margin-top: 22px; padding: 12px 4px; background: none; border: none; border-top: 1px solid var(--border); color: var(--green-text); font-family: var(--font-body); font-weight: 500; font-size: 0.9375rem; cursor: pointer; }
.service-collapse-btn:hover { color: var(--green-hover); }
.service-collapse-btn[hidden] { display: none; }
.service-card { display: block; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); padding: 22px; transition: border-color 0.2s ease, transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.2s ease; }
.service-card:hover { border-color: var(--green); transform: translateY(-3px); box-shadow: var(--shadow-tile); }
.service-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.service-card-head h3 { font-family: var(--font-heading); font-weight: 600; font-size: 1.0625rem; color: var(--ink); }
.service-card-arrow { flex-shrink: 0; color: var(--ink-muted); margin-top: 2px; transition: transform 0.2s ease, color 0.2s ease; }
.service-card:hover .service-card-arrow { color: var(--green); transform: translate(2px, -2px); }
.service-card-desc { color: var(--ink-muted); font-size: 0.9375rem; margin-top: 8px; line-height: 1.5; overflow-wrap: break-word; }
.service-card-meta { display: flex; align-items: center; justify-content: space-between; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.service-card-duration { color: var(--ink-muted); font-size: 0.875rem; }
.service-card-price { font-family: var(--font-heading); font-weight: 600; font-size: 1.0625rem; color: var(--ink); }
.service-card-price small { font-weight: 500; font-size: 0.75rem; color: var(--ink-muted); }
.services-empty { padding: 24px 4px; font-size: 0.9375rem; color: var(--ink-muted); }

/* ---------- booking: guided step flow + ticket summary ---------- */
.booking-flow { display: flex; flex-direction: column; gap: 32px; }
@media (min-width: 1024px) { .booking-flow { flex-direction: row; align-items: flex-start; gap: 44px; } .booking-steps { flex: 1.3; min-width: 0; } .booking-ticket-col { flex: 1; position: sticky; top: 96px; } }

/* step route indicator: ticks + fill line, deliberately not the numbered-badge pattern used elsewhere */
.step-route { margin-bottom: 32px; }
.step-route-line { position: relative; height: 2px; background: var(--border); border-radius: 2px; margin-bottom: 12px; }
.step-route-fill { position: absolute; inset: 0; background: var(--green); border-radius: 2px; transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease; }
.step-route-ticks { display: flex; justify-content: space-between; }
.step-tick-wrap { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.step-tick { width: 2px; height: 8px; background: var(--border); display: block; }
.step-tick-wrap.is-complete .step-tick, .step-tick-wrap.is-current .step-tick { background: var(--green); }
.step-tick-label { background: none; border: none; padding: 4px 8px; min-height: 44px; font-family: var(--font-body); font-size: 0.8125rem; cursor: default; color: var(--ink-muted); font-weight: 500; }
.step-tick-wrap.is-current .step-tick-label { color: var(--ink); font-weight: 500; }
.step-tick-wrap.is-complete .step-tick-label { color: var(--green-text); cursor: pointer; }
.step-tick-label:disabled { cursor: default; }

/* step panels */
.step-panel[hidden] { display: none; }
.step-heading-row { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; min-height: 44px; }
.step-back { display: inline-flex; align-items: center; gap: 2px; height: 44px; padding: 0 8px 0 2px; background: none; border: none; color: var(--ink-muted); font-family: var(--font-body); font-weight: 500; font-size: 0.9375rem; cursor: pointer; flex-shrink: 0; }
.step-back:hover { color: var(--ink); }
.step-heading { font-family: var(--font-heading); font-weight: 600; font-size: 1.25rem; color: var(--ink); outline: none; }
.step-enter { animation: step-enter-fwd 0.38s cubic-bezier(0.16, 1, 0.3, 1); }
.step-enter-back { animation: step-enter-back 0.38s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes step-enter-fwd { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: translateX(0); } }
@keyframes step-enter-back { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: translateX(0); } }

/* step 1: service rows */
.service-pick-row { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 4px; min-height: 56px; border: none; border-top: 1px solid var(--border); background: none; text-align: left; cursor: pointer; transition: background-color 0.2s ease; }
.service-pick-row:first-child { border-top: none; }
.service-pick-row:hover { background: var(--surface-sunken); }
.service-pick-row.is-selected { background: var(--green-pale); }
.service-pick-main h4 { font-family: var(--font-heading); font-weight: 600; font-size: 1.0625rem; color: var(--ink); margin: 0; }
.service-pick-meta { display: flex; align-items: center; gap: 14px; flex-shrink: 0; }
.service-pick-duration { color: var(--ink-muted); font-size: 0.875rem; white-space: nowrap; }
.service-pick-price { font-family: var(--font-heading); font-weight: 600; font-size: 1.0625rem; color: var(--ink); white-space: nowrap; }
.service-pick-check { width: 24px; height: 24px; border-radius: 50%; border: 1.5px solid var(--border); flex-shrink: 0; display: flex; align-items: center; justify-content: center; color: transparent; transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease; }
.service-pick-row.is-selected .service-pick-check { background: var(--green); border-color: var(--green); color: var(--white); }
/* Mobile shows only the first 4 services by default (not 5) - the 5th joins the
   collapsed set until "Show all services" is opened. */
@media (max-width: 639px) {
  .service-pick-row-fifth:not(.force-visible) { display: none; }
}
.service-pick-extra-wrap { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.3s ease; }
.service-pick-extra-wrap.open { grid-template-rows: 1fr; }
.service-pick-extra-inner { overflow: hidden; }
.service-pick-toggle { width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; margin-top: 4px; padding: 12px 4px; background: none; border: none; border-top: 1px solid var(--border); color: var(--green-text); font-family: var(--font-body); font-weight: 500; font-size: 0.9375rem; cursor: pointer; }
.service-pick-toggle[hidden] { display: none; }
.service-pick-toggle:hover { color: var(--green-hover); }
.service-pick-toggle-chevron { transition: transform 0.25s ease; }
.service-pick-toggle[aria-expanded="true"] .service-pick-toggle-chevron { transform: rotate(180deg); }

/* step 2: date */
.date-strip-nav { display: flex; justify-content: flex-end; gap: 8px; margin-bottom: 12px; }
.date-strip-nav[hidden] { display: none; }
.date-strip-arrow { width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--border); background: var(--surface); display: flex; align-items: center; justify-content: center; color: var(--ink); cursor: pointer; flex-shrink: 0; transition: border-color 0.2s ease, opacity 0.2s ease; }
.date-strip-arrow:hover:not(:disabled) { border-color: var(--green); }
.date-strip-arrow:disabled { opacity: 0.35; cursor: not-allowed; }
.date-strip { display: flex; gap: 10px; overflow-x: auto; scroll-snap-type: x mandatory; padding: 2px; scrollbar-width: none; -ms-overflow-style: none; }
.date-strip::-webkit-scrollbar { display: none; }
.date-pill { scroll-snap-align: start; flex: 0 0 auto; width: 72px; min-height: 88px; border-radius: 14px; border: 1px solid var(--border); background: var(--surface); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; cursor: pointer; font-family: var(--font-body); color: var(--ink); transition: background-color 0.2s ease, transform 0.1s ease, border-color 0.2s ease, color 0.2s ease; }
.date-pill:active:not(:disabled) { transform: scale(0.93); }
.date-pill .dow { font-size: 0.75rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.date-pill .num { font-family: var(--font-heading); font-weight: 600; font-size: 1.375rem; }
.date-pill .month { font-size: 0.75rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.date-pill:hover:not(:disabled) { border-color: var(--green); }
.date-pill.is-selected { background: var(--green); border-color: var(--green); color: var(--white); }
.date-pill.is-selected .dow, .date-pill.is-selected .month { color: oklch(94% 0.03 158); }
.date-pill.is-closed, .date-pill:disabled { opacity: 0.4; cursor: not-allowed; }

/* step 3: time, grouped Morning / Afternoon */
.slot-hint, .slot-empty { color: var(--ink-muted); font-size: 0.9375rem; margin-bottom: 20px; }
.slot-hint[hidden], .slot-empty[hidden] { display: none; }
.slot-group[hidden] { display: none; }
.slot-group { margin-top: 22px; }
.slot-group:first-of-type { margin-top: 0; }
.slot-group-label { font-family: var(--font-body); font-weight: 500; font-size: 0.9375rem; color: var(--ink); margin-bottom: 12px; }
.slots-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px; }
.slot-btn {
  height: 44px; border-radius: 10px; border: 1px solid var(--border); background: var(--surface);
  font-family: var(--font-body); font-weight: 500; font-size: 0.9375rem; color: var(--ink); cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease, transform 0.1s ease;
  animation: slot-rise 0.22s cubic-bezier(0.16, 1, 0.3, 1) calc(var(--i, 0) * 28ms) both;
}
@keyframes slot-rise { from { opacity: 0; transform: scale(0.88); } to { opacity: 1; transform: scale(1); } }
.slot-btn:active:not(:disabled) { transform: scale(0.94); }
.slot-btn:hover:not(:disabled) { border-color: var(--green); }
.slot-btn--selected { background: var(--green); border-color: var(--green); color: var(--white); }
.slot-btn--unavailable, .slot-btn:disabled { opacity: 0.35; cursor: not-allowed; text-decoration: line-through; }

/* step 3 (details) form */
.booking-error {
  margin: 0 0 4px; padding: 12px 14px; border-radius: 12px;
  background: var(--danger-pale); color: var(--danger-text); font-size: 0.875rem; line-height: 1.5;
}
.form-field { margin-bottom: 0; display: flex; flex-direction: column; gap: 0; }
.form-field label { display: block; font-size: 0.8125rem; font-weight: 500; color: var(--ink); margin-bottom: 6px; }
.form-label-optional { font-weight: 400; color: var(--ink-muted); }
.form-field input, .form-field textarea, .form-input {
  width: 100%; border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px;
  font-family: var(--font-body); font-size: 0.9375rem; color: var(--ink); background: var(--bg);
}
.form-field textarea, textarea.form-input { resize: vertical; min-height: 72px; }
.form-field input::placeholder, .form-field textarea::placeholder { color: var(--ink-muted); opacity: 1; }
.form-field input[aria-invalid="true"], .form-field textarea[aria-invalid="true"] { border-color: var(--danger); }
.field-error { display: none; margin: 6px 0 0; font-size: 0.8125rem; color: var(--danger-text); }
.form-field.has-error .field-error { display: block; }
.booking-form { display: flex; flex-direction: column; gap: 14px; }
.booking-honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.booking-submit { width: 100%; margin-top: 4px; }
.booking-success { display: none; text-align: center; padding: 8px 0 4px; }
.booking-success.is-visible { display: block; }
.booking-success svg { color: var(--green); margin: 0 auto 12px; }
.booking-success h3 { font-family: var(--font-heading); font-weight: 600; font-size: 1.125rem; margin-bottom: 6px; }
.booking-success p { color: var(--ink-muted); font-size: 0.9375rem; }

/* Booking submit: spinner while confirming */
@keyframes spin { to { transform: rotate(360deg); } }
.btn-spinner {
  width: 16px; height: 16px; margin-left: 8px;
  border: 2px solid rgba(255, 255, 255, 0.35); border-top-color: var(--white);
  border-radius: 50%; animation: spin 0.65s linear infinite; flex-shrink: 0;
}

/* Slot-collision recovery: the one realistic race condition this flow can hit -
   two people booking the same open slot at once. Shown instead of the success
   state if the slot is no longer available at submit time. */
.booking-alert { display: none; gap: 12px; align-items: flex-start; padding: 16px; margin-bottom: 4px; border-radius: 12px; background: var(--danger-pale); }
.booking-alert:not([hidden]) { display: flex; }
.booking-alert svg { flex-shrink: 0; color: var(--danger); margin-top: 2px; }
.booking-alert-title { font-family: var(--font-heading); font-weight: 500; font-size: 0.9375rem; color: var(--danger-text); margin: 0 0 4px; }
.booking-alert-body { font-size: 0.875rem; color: var(--ink); margin: 0 0 12px; }

/* the ticket: one deliberate structural gesture (a real cut perforation), done once on the page */
.ticket-card { position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-card); box-shadow: var(--shadow-card); overflow: hidden; transition: border-color 0.3s ease; }
.ticket-card.is-confirmed { border-color: var(--green); }
.ticket-head { padding: 22px 24px 20px; }
.ticket-head-label { font-size: 0.75rem; color: var(--ink-muted); font-weight: 500; }
.ticket-service-name { font-family: var(--font-heading); font-weight: 600; font-size: 1.125rem; color: var(--ink); margin-top: 4px; text-wrap: pretty; }
.ticket-service-duration { font-size: 0.875rem; color: var(--ink-muted); margin-top: 2px; }
.ticket-perforation { position: relative; height: 1px; background-image: repeating-linear-gradient(to right, var(--border) 0 6px, transparent 6px 12px); }
.ticket-perforation::before, .ticket-perforation::after { content: ''; position: absolute; top: 50%; width: 20px; height: 20px; border-radius: 50%; background: var(--bg); transform: translateY(-50%); }
.ticket-perforation::before { left: -11px; }
.ticket-perforation::after { right: -11px; }
.ticket-body { padding: 20px 24px 4px; }
.ticket-body dl { margin: 0; display: flex; flex-direction: column; gap: 12px; }
.ticket-row { display: flex; justify-content: space-between; align-items: baseline; margin: 0; }
.ticket-row dt { font-size: 0.8125rem; color: var(--ink-muted); font-weight: 500; margin: 0; }
.ticket-row dd { margin: 0; font-weight: 500; color: var(--ink); font-size: 0.9375rem; }
.ticket-row dd.is-empty, .ticket-row dd .is-empty { color: var(--ink-muted); font-weight: 500; }
/* Date/Time rows get a "Change" jump-link back to Step 2 - but only while the step
   is still editable. Toggled by updateTicketChangeLinks(), which runs on every step
   change so it can't drift out of sync with is-confirmed. */
.ticket-value-row { display: flex; align-items: baseline; gap: 8px; }
.ticket-change-btn { border: none; background: none; padding: 0 8px; min-height: 44px; font-family: var(--font-body); font-weight: 500; font-size: 0.8125rem; color: var(--green-text); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.ticket-change-btn:hover { color: var(--green-hover); }
.ticket-change-btn[hidden] { display: none; }
.ticket-row.total dd { font-family: var(--font-heading); font-weight: 600; font-size: 1.375rem; color: var(--green-text); }
.ticket-field-pop { animation: ticket-field-pop 0.15s cubic-bezier(0.16, 1, 0.3, 1); }
@keyframes ticket-field-pop { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
.ticket-ref { padding: 16px 24px 22px; font-size: 0.8125rem; color: var(--ink-muted); }
.ticket-ref[hidden] { display: none; }
.ticket-ref strong { color: var(--ink); font-family: var(--font-heading); }
.ticket-stamp { display: none; align-items: center; gap: 8px; padding: 14px 24px; background: var(--green-pale); color: var(--green-text); font-weight: 500; font-size: 0.875rem; }
.ticket-card.is-confirmed .ticket-stamp { display: flex; }

/* mobile: collapsed ticket bar fixed to the bottom, expands the same ticket card upward.
   Stays hidden until the visitor actually starts booking (picks a service). */
.ticket-mobile-bar { display: none; }
@media (max-width: 1023px) {
  .ticket-mobile-bar.is-visible {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    height: 64px; padding: 0 20px; background: var(--surface); border-top: 1px solid var(--border);
    box-shadow: 0 -8px 24px oklch(52% 0.15 158 / 0.08);
  }
  .booking-ticket-col {
    position: fixed; left: 0; right: 0; bottom: 64px; z-index: 89; max-height: 70vh; overflow-y: auto;
    padding: 16px; background: var(--bg); border-top: 1px solid var(--border);
    transform: translateY(calc(100% + 84px)); transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  }
  .booking-ticket-col.is-open { transform: translateY(0); }
  /* Only reserve space for the fixed bottom bar once it's actually shown - otherwise
     Step 1 gets 80px of dead padding before anyone has picked a service. */
  .booking-steps.has-mobile-bar { padding-bottom: 80px; }
}
.ticket-mobile-summary { font-size: 0.9375rem; font-weight: 500; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ticket-mobile-toggle { flex-shrink: 0; background: var(--green); color: var(--white); border: none; border-radius: 999px; height: 44px; padding: 0 18px; font-family: var(--font-body); font-weight: 500; font-size: 0.875rem; cursor: pointer; }

/* ---------- contact + footer band ---------- */
.deep-band { background: linear-gradient(165deg, var(--deep) 0%, var(--deep-2) 100%); color: var(--on-deep); position: relative; overflow: hidden; }
.contact-inner { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 40px; }
@media (min-width: 900px) { .contact-inner { flex-direction: row; align-items: stretch; gap: 60px; } }
.contact-col { display: flex; flex-direction: column; }
@media (min-width: 900px) { .contact-col { flex: 1.1; } }
.contact-col h2 { color: var(--white); }
.contact-detail-list { display: flex; flex-direction: column; gap: 18px; margin-top: 24px; }
.contact-detail { display: flex; align-items: flex-start; gap: 14px; }
.contact-detail svg { flex-shrink: 0; margin-top: 2px; color: var(--on-deep-muted); }
.contact-detail .label { font-size: 0.8125rem; color: var(--on-deep-muted); }
.contact-detail .value { font-weight: 500; }
.contact-detail .value a { color: inherit; }
.contact-detail .value a:hover { color: var(--white); }
.social-row { display: flex; gap: 12px; margin-top: 28px; }
.social-btn { width: 44px; height: 44px; border-radius: 50%; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2); display: flex; align-items: center; justify-content: center; color: var(--on-deep); transition: background-color 0.2s ease, transform 0.2s ease; }
.social-btn:hover { background: rgba(255, 255, 255, 0.18); transform: translateY(-2px); }

/* A real map embed (the business's address, keyless Google embed) with
   the address as a caption and a separate wayfinding link below it —
   that link prefers the owner's own pasted maps_link when set, since an
   arbitrary pasted link can't reliably become the embed's own source. */
.contact-map-card {
  flex: 1; min-height: 240px; border-radius: var(--radius-card); overflow: hidden;
  display: flex; flex-direction: column; gap: 14px;
  padding: 20px; color: var(--on-deep);
  background: linear-gradient(155deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%);
  border: 1px solid rgba(255, 255, 255, 0.14);
}
.contact-map-card[hidden] { display: none; }
.contact-map-frame { width: 100%; flex: 1; min-height: 160px; border: 0; border-radius: 12px; background: var(--surface); }
.contact-map-address { font-weight: 500; font-size: 1.0625rem; color: var(--white); text-align: center; }
.contact-map-cta { align-self: center; display: inline-flex; align-items: center; gap: 6px; font-size: 0.875rem; font-weight: 500; color: var(--on-deep-muted); transition: color 0.2s ease; }
.contact-map-cta svg { transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1); }
.contact-map-cta:hover { color: var(--white); }
.contact-map-cta:hover svg { transform: translateX(3px); }

/* Two-tier footer: a primary row (brand + page nav) and a quieter fine-print row
   below a hairline (copyright, legal, powered-by). Not a multi-column mega-footer -
   this is a one-page business profile, there's nothing to put in extra columns. */
.footer-top {
  position: relative; z-index: 1; margin-top: 56px;
  display: flex; flex-direction: column; gap: 20px; align-items: center; text-align: center;
}
@media (min-width: 768px) { .footer-top { flex-direction: row; justify-content: space-between; align-items: center; text-align: left; } }
.footer-wordmark { font-family: var(--font-display); font-weight: 800; font-size: 1.375rem; color: var(--white); letter-spacing: -0.03em; }
.footer-nav { display: flex; flex-wrap: wrap; justify-content: center; gap: 24px; font-size: 0.9375rem; font-weight: 500; }
@media (min-width: 768px) { .footer-nav { justify-content: flex-end; } }
.footer-nav a { color: var(--on-deep-muted); transition: color 0.2s ease; }
.footer-nav a:hover { color: var(--white); }

.footer-bottom {
  position: relative; z-index: 1; border-top: 1px solid rgba(255, 255, 255, 0.12);
  margin-top: 32px; padding: 20px 0 40px;
  display: flex; flex-direction: column; gap: 14px; align-items: center; text-align: center;
  font-size: 0.8125rem; color: var(--on-deep-muted);
}
@media (min-width: 768px) { .footer-bottom { flex-direction: row; justify-content: space-between; text-align: left; } }
.footer-copy { margin: 0; }
.footer-meta { display: flex; flex-direction: column; align-items: center; gap: 10px; }
@media (min-width: 768px) { .footer-meta { flex-direction: row; gap: 20px; align-items: center; } }
.footer-legal { display: flex; gap: 16px; }
.footer-legal a { color: var(--on-deep-muted); transition: color 0.2s ease; }
.footer-legal a:hover { color: var(--white); }
.powered-by { margin: 0; }
.powered-by a { color: var(--white); font-weight: 500; }

/* ── Preview mode (onboarding iframe) ─────────────────── */
body.preview-mode .nav { display: none; }
body.preview-mode .hero { padding-top: 0; }
body.preview-mode { scroll-behavior: auto; }
