/* site-factory concept template. Each page sets --accent / --accent-ink / --accent-soft inline. */
:root {
  --accent: #1d6fd1;
  --accent-ink: #114a8c;
  --accent-soft: #eef4fb;
  --night: #0f1620;
  --night-2: #182130;
  --ink: #1d2730;
  --muted: #55606a;
  --line: #e2e7ea;
  --soft: #f4f6f8;
  --radius: 14px;
  --wrap: 1120px;
  --bar-h: 64px;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0; background: #fff; color: var(--ink);
  font: 400 17px/1.6 "Nunito Sans", system-ui, sans-serif;
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--accent-ink); }
h1, h2, h3 { line-height: 1.15; margin: 0 0 .5em; font-weight: 800; letter-spacing: -.015em; }
h1 { font-size: clamp(2.4rem, 7vw, 4.4rem); line-height: 1.02; }
h2 { font-size: clamp(1.6rem, 3.6vw, 2.3rem); }
h3 { font-size: 1.15rem; }
p { margin: 0 0 1em; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 20px; }
.skip { position: absolute; left: -999px; }
.skip:focus { left: 12px; top: 12px; background: #fff; padding: 8px 12px; z-index: 50; }
.eyebrow { font-size: .85rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-ink); margin: 0 0 .6em; }
.eyebrow-sep { margin: 0 .5em; opacity: .6; }
.lead { font-size: 1.15rem; color: var(--muted); max-width: 40rem; }
.section-head { max-width: 46rem; margin-bottom: 32px; }
section { padding: 72px 0; }

/* Buttons */
.btn {
  display: inline-block; white-space: nowrap; font-weight: 800; text-decoration: none; border-radius: 10px; cursor: pointer;
  padding: 14px 24px; background: var(--accent-ink); color: #fff; border: 2px solid var(--accent-ink); font: inherit; font-weight: 800;
  transition: transform .2s, background .2s;
}
.btn:hover { transform: translateY(-1px); filter: brightness(1.08); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { background: var(--soft); }
.btn-small { padding: 10px 16px; font-size: .95rem; }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }

/* Concept strip + header */
.concept-strip { background: #fff7e0; color: #5a4300; font-size: .85rem; border-bottom: 1px solid #f0dca0; }
.concept-strip .wrap { display: flex; justify-content: space-between; gap: 12px; padding-top: 8px; padding-bottom: 8px; flex-wrap: wrap; }
.concept-strip a { color: inherit; font-weight: 700; }
@media (max-width: 640px) {
  .concept-strip { font-size: .78rem; line-height: 1.35; }
  .concept-strip .wrap { padding-top: 6px; padding-bottom: 6px; gap: 4px; }
}
.site-header { position: sticky; top: 0; z-index: 20; background: rgba(255,255,255,.94); backdrop-filter: blur(8px); border-bottom: 1px solid var(--line); }
.header-row { display: flex; align-items: center; gap: 18px; min-height: 68px; }
.brand { display: flex; align-items: center; text-decoration: none; color: var(--ink); min-width: 0; }
.brand img { height: 48px; width: auto; max-width: 220px; object-fit: contain; }
.brand-text { font-weight: 800; font-size: 1.15rem; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.header-call { margin-left: auto; font-weight: 800; color: var(--accent-ink); text-decoration: none; white-space: nowrap; }
.header-row .btn-small { white-space: nowrap; }
@media (max-width: 640px) {
  .header-row { min-height: 58px; gap: 10px; }
  .brand img { height: 36px; max-width: 150px; }
  .brand-text { font-size: 1rem; }
  .header-call { font-size: .9rem; }
  .header-row .btn-small { display: none; }
}

/* Hero */
.hero {
  position: relative; overflow: clip; background: var(--night); color: #fff; min-height: min(92vh, 860px);
  display: flex; align-items: center; padding: 72px 0 80px; isolation: isolate;
}
.hero-bg { position: absolute; inset: -8% 0; z-index: -2; will-change: transform; }
.hero-bg img { width: 100%; height: 100%; object-fit: cover; opacity: .42; filter: saturate(1.1); }
.hero::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(100deg, rgba(10,14,22,.95) 0%, rgba(10,14,22,.75) 45%, rgba(10,14,22,.35) 100%); }
.hero-glow { position: absolute; width: 60vmax; height: 60vmax; border-radius: 50%; filter: blur(80px); opacity: .35; z-index: -1; pointer-events: none; will-change: transform; }
.hero-glow.a { background: var(--accent); left: -20vmax; top: -20vmax; animation: drift 22s ease-in-out infinite alternate; }
.hero-glow.b { background: var(--accent); right: -25vmax; bottom: -30vmax; opacity: .22; animation: drift 28s ease-in-out infinite alternate-reverse; }
@keyframes drift { from { transform: translate(0, 0) scale(1); } to { transform: translate(8vw, 6vh) scale(1.15); } }
.hero-grid { position: relative; display: grid; grid-template-columns: 1.05fr .95fr; gap: 40px; align-items: center; width: 100%; }
.hero .eyebrow { color: var(--accent); filter: brightness(1.25); }
.hero h1 { margin-bottom: .4em; text-wrap: balance; }
.hero .lead { color: #cdd6e0; }
.hero .btn { background: var(--accent); border-color: var(--accent); color: #0b1017; }
.hero .btn-ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.35); }
.hero .btn-ghost:hover { background: rgba(255,255,255,.08); }
.hero-copy { will-change: transform; }
.scroll-cue { position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%); margin: 0; font-size: .75rem; letter-spacing: .2em; text-transform: uppercase; color: rgba(255,255,255,.55); }
.scroll-cue::after { content: ""; display: block; width: 1px; height: 26px; margin: 6px auto 0; background: linear-gradient(rgba(255,255,255,.7), transparent); animation: cue 1.6s ease-in-out infinite; }
@keyframes cue { 0%, 100% { transform: scaleY(.4); transform-origin: top; } 50% { transform: scaleY(1); transform-origin: top; } }

/* Photo stack in the hero: layered cards that drift at different rates on scroll */
.stack { position: relative; aspect-ratio: 5 / 4; perspective: 1200px; }
.stack .card-photo {
  position: absolute; border-radius: 18px; overflow: hidden; box-shadow: 0 30px 60px rgba(0,0,0,.45);
  background: var(--night-2); will-change: transform; transform: translate3d(var(--x,0), var(--y,0), 0) rotate(var(--r, 0deg));
}
.stack .card-photo img { width: 100%; height: 100%; object-fit: cover; }
.stack .c1 { inset: 6% 4% 10% 12%; --r: -3deg; z-index: 3; }
.stack .c2 { inset: 0 0 32% 42%; --r: 4deg; z-index: 2; opacity: .95; }
.stack .c3 { inset: 46% 36% 0 0; --r: 2deg; z-index: 1; opacity: .9; }
.stack.one .c1 { inset: 4% 6% 6% 6%; --r: -2deg; }
/* No photos anywhere: a layered stack made of their logo (or name), accent colour and first service */
.hero.no-photo::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: radial-gradient(rgba(255,255,255,.07) 1px, transparent 1px); background-size: 22px 22px; }
.stack.brand .card-photo { display: flex; align-items: flex-end; padding: 22px; }
.stack.brand .brand-face { background: #fff; align-items: center; justify-content: center; padding: 10%; }
.stack.brand .brand-face img { width: auto; height: auto; max-width: 100%; max-height: 70%; object-fit: contain; }
.stack.brand .brand-face .brand-name { color: var(--night); font-weight: 800; font-size: clamp(1.6rem, 3.4vw, 2.6rem); line-height: 1.05; letter-spacing: -.02em; text-align: center; text-wrap: balance; }
.stack.brand .tint { background: linear-gradient(150deg, var(--accent), color-mix(in srgb, var(--accent) 45%, #0b1017)); }
.stack.brand .tint2 { background: linear-gradient(150deg, #243042, #121a25); border: 1px solid rgba(255,255,255,.08); }
.stack.brand .card-photo span { color: #fff; font-weight: 800; font-size: 1.05rem; line-height: 1.2; text-shadow: 0 1px 8px rgba(0,0,0,.35); }
.stack.brand .tint span { color: #0b1017; text-shadow: none; }
.stack.brand .c1 { inset: 16% 10% 14% 8%; }
.stack.brand .c2 { inset: 0 0 40% 40%; align-items: flex-start; justify-content: flex-end; padding: 14px 20px; text-align: right; }
.stack.brand .c3 { inset: auto auto 2% 0; z-index: 4; padding: 10px 16px; border-radius: 999px; --r: -2deg; }
.stack.brand .c3 span { font-size: .9rem; white-space: nowrap; }
@media (max-width: 640px) { .stack.brand .c3 { display: flex; } .stack.brand .card-photo span { font-size: .85rem; } }

@media (max-width: 860px) {
  .hero { min-height: 0; padding: 56px 0 72px; }
  .hero-grid { grid-template-columns: 1fr; gap: 28px; }
  .stack { aspect-ratio: 4 / 3; max-width: 480px; }
}
@media (max-width: 640px) {
  h1 { font-size: clamp(2.1rem, 10vw, 3rem); }
  .hero { padding: 40px 0 64px; }
  .hero .lead { font-size: 1.05rem; }
  .stack .c3 { display: none; }
  .stack .c2 { inset: 0 0 28% 40%; }
}

/* Offerings */
.offer-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
.offer { display: block; min-width: 0; color: var(--ink); text-decoration: none; border: 1px solid var(--line); border-radius: var(--radius); padding: 24px; background: #fff; transition: transform .25s, box-shadow .25s; }
.offer h3, .offer p { overflow-wrap: break-word; }
.offer:hover { transform: translateY(-4px); box-shadow: 0 14px 30px rgba(13,23,38,.10); }
.offer .num { display: inline-grid; place-items: center; width: 38px; height: 38px; border-radius: 10px; background: var(--accent-soft); color: var(--accent-ink); font-weight: 800; margin-bottom: 14px; }
.offer h3 { margin-bottom: .3em; }
.offer p { color: var(--muted); margin: 0; }
@media (max-width: 860px) { .offer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .offer-grid { grid-template-columns: minmax(0, 1fr); } }

/* Statement that lights up word by word */
.statement { background: var(--night); color: #fff; padding: 96px 0; }
.statement .eyebrow { color: var(--accent); filter: brightness(1.3); }
.lit-text { font-size: clamp(1.4rem, 3.4vw, 2.3rem); font-weight: 700; line-height: 1.3; max-width: 52rem; margin: 0; letter-spacing: -.01em; }
.lit-text .w { color: rgba(255,255,255,.22); transition: color .25s; }
.lit-text .w.on { color: #fff; }

/* Contact */
.contact { background: var(--soft); }
.contact-grid { display: grid; grid-template-columns: 1.2fr .8fr; gap: 40px; align-items: start; }
.contact-line { display: grid; grid-template-columns: 80px minmax(0, 1fr); gap: 12px; margin-bottom: .6em; }
.contact-line strong { color: var(--muted); font-weight: 700; }
.contact-line a { font-weight: 700; overflow-wrap: anywhere; }
.contact-copy, .hero-copy, .wrap, .quote-grid > div, .audit-head { min-width: 0; }
body { overflow-x: clip; }
h1, h2, h3, .brand-text { overflow-wrap: break-word; }
.brand-text { overflow-wrap: normal; }
.socials a { margin-right: 14px; }
.hours-card { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 24px; }
.hours-card ul { list-style: none; padding: 0; margin: 0; }
.hours-card li { padding: 6px 0; border-bottom: 1px solid var(--line); }
.hours-card li:last-child { border: 0; }
@media (max-width: 760px) { .contact-grid { grid-template-columns: 1fr; } }

/* Quote */
.quote-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: start; }
.quote-form { display: grid; gap: 14px; background: #fff; border: 1px solid var(--line); border-radius: var(--radius); padding: 24px; }
.quote-form label { display: grid; gap: 6px; font-weight: 700; font-size: .95rem; }
.quote-form input, .quote-form textarea { font: inherit; padding: 12px; border: 1px solid var(--line); border-radius: 10px; }
.quote-form input:focus, .quote-form textarea:focus { outline: 2px solid var(--accent); border-color: transparent; }
.form-note { font-size: .8rem; color: var(--muted); margin: 0; }
@media (max-width: 760px) { .quote-grid { grid-template-columns: 1fr; } }
.thanks { border: 0; border-radius: var(--radius); padding: 28px; max-width: 26rem; box-shadow: 0 30px 60px rgba(0,0,0,.3); }
.thanks::backdrop { background: rgba(10,14,22,.6); }

/* The audit, in the builder's voice */
.audit { background: #11161d; color: #e7ecf2; padding: 80px 0; border-top: 6px solid var(--accent); }
.audit .eyebrow { color: #9fb3c8; }
.audit .lead { color: #b9c5d1; }
.audit .lead a { color: #fff; }
.audit-head { max-width: 50rem; margin-bottom: 36px; }
.audit-list { list-style: none; counter-reset: p; padding: 0; margin: 0 0 40px; display: grid; gap: 14px; }
.audit-list li { counter-increment: p; display: grid; grid-template-columns: 44px 1fr 1fr; gap: 18px; background: #1a212b; border-radius: var(--radius); padding: 20px; align-items: start; }
.audit-list li::before { content: counter(p); display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--accent); color: #0b1017; font-weight: 800; }
.audit-list .found strong, .audit-list .fix strong { display: block; font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; color: #9fb3c8; margin-bottom: 4px; }
.audit-list .found { color: #fff; }
.audit-list .fix { color: #cfe3c0; }
.audit-list .sev-3 .found strong { color: #ffb3a7; }
.audit-ok { color: #cfe3c0; margin-bottom: 36px; }
.audit-cta { display: grid; grid-template-columns: 1fr auto; gap: 24px; align-items: center; background: #1a212b; border-radius: var(--radius); padding: 28px; }
.audit-cta h3 { color: #fff; margin-bottom: .2em; }
.audit-cta p { margin: 0; color: #b9c5d1; }
.audit .btn { background: var(--accent); border-color: var(--accent); color: #0b1017; }
.audit .btn-ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.3); }
@media (max-width: 760px) {
  .audit-list li { grid-template-columns: 36px 1fr; }
  .audit-list .fix { grid-column: 2; }
  .audit-cta { grid-template-columns: 1fr; }
}

/* Footer and mobile bar */
.site-footer { background: #0b0f14; color: #9fb3c8; font-size: .9rem; padding: 36px 0 110px; }
.site-footer a { color: #fff; }
.site-footer p { max-width: 60rem; }
.mobile-bar { display: none; }
@media (max-width: 760px) {
  .mobile-bar { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; padding: 10px 14px calc(10px + env(safe-area-inset-bottom)); background: rgba(15,22,32,.45); -webkit-backdrop-filter: blur(14px) saturate(1.4); backdrop-filter: blur(14px) saturate(1.4); border-top: 1px solid rgba(255,255,255,.12); }
  .mobile-bar .btn { text-align: center; padding: 12px; white-space: nowrap; }
  .mobile-bar .btn { background: var(--accent); border-color: var(--accent); color: #0b1017; }
  .mobile-bar .btn-ghost { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.35); color: #fff; }
}

/* Reveal on scroll: hidden only once the script has set html.js */
.js .reveal { opacity: 0; transform: translateY(24px); transition: opacity .7s ease, transform .7s ease; }
.js .reveal.in { opacity: 1; transform: none; }
/* Headings rise word by word */
.js .rw { display: inline-block; opacity: 0; transform: translateY(.45em); transition: opacity .55s ease, transform .55s cubic-bezier(.2,.7,.2,1); }
.js .in > .rw, .js h1.in .rw, .js h2.in .rw { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .hero-glow, .scroll-cue::after { animation: none; }
  html { scroll-behavior: auto; }
  .lit-text .w { color: #fff; }
}

/* Proof strip: their credentials, brands, areas or review quotes, drifting sideways; drag or flick it */
.proof-strip { padding: 48px 0 56px; background: #fff; overflow: clip; }
.proof-strip .eyebrow { margin-bottom: 18px; }
.ticker { overflow-x: auto; scrollbar-width: none; -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent); }
.ticker::-webkit-scrollbar { display: none; }
.ticker-track { display: flex; align-items: center; gap: 14px; width: max-content; padding: 4px 20px; }
.js .ticker { overflow: hidden; touch-action: pan-y; cursor: grab; user-select: none; -webkit-user-select: none; }
.js .ticker:active { cursor: grabbing; }
.js .ticker-track { will-change: transform; }
.chip { display: inline-flex; flex-direction: column; gap: 2px; max-width: min(72vw, 300px); white-space: normal; line-height: 1.25; padding: 12px 20px; border-radius: 18px; border: 1px solid var(--line); background: var(--soft); font-weight: 800; font-size: 1.05rem; color: var(--ink); }
.chip small { font-size: .72rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-ink); }
.quote-chip { margin: 0; width: min(78vw, 360px); white-space: normal; padding: 18px 20px; border-radius: var(--radius); background: var(--night); color: #fff; }
.quote-chip blockquote { margin: 0 0 8px; font-weight: 700; line-height: 1.4; }
.quote-chip figcaption { font-size: .85rem; color: #9fb3c8; }
@media (prefers-reduced-motion: reduce) {
  .ticker { -webkit-mask-image: none; mask-image: none; overflow: visible; }
  .ticker-track { flex-wrap: wrap; width: auto; max-width: var(--wrap); margin: 0 auto; }
}


/* Review fixes (MW review, Nov 7) */
/* text on a tilted card renders soft: the card that carries the name or logo, and the front photo, stay flat */
.stack.brand .brand-face { --r: 0deg; }
/* services with no descriptions: a compact two-column list instead of tall empty cards */
.offer-grid.compact { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.offer-grid.compact .offer { display: flex; align-items: center; gap: 14px; padding: 16px 18px; }
.offer-grid.compact .offer .num { margin: 0; flex: none; }
.offer-grid.compact .offer h3 { margin: 0; font-size: 1.05rem; }
@media (max-width: 860px) { .offer-grid.compact { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 420px) { .offer-grid.compact .offer { padding: 12px 14px; gap: 10px; } .offer-grid.compact .offer h3 { font-size: .95rem; } }
/* phones: the bottom bar already has Call and Get a quote, so the hero drops its own buttons and gives the room to the photos */
@media (max-width: 760px) { .hero .btn-row { display: none; } .hero .lead { margin-bottom: .4em; } }
/* long business names wrap to two lines in the header instead of being cut off */
.brand-text { white-space: normal; overflow: visible; text-overflow: clip; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.15; max-width: 60vw; }
@media (max-width: 640px) { .brand-text { font-size: .92rem; max-width: 52vw; } }
.stack.brand .brand-face .brand-name { text-shadow: none; }
@media (max-width: 480px) { .offer-grid.compact .offer .num { display: none; } .offer-grid.compact .offer { padding: 14px 16px; } }

.brand { gap: 10px; }
.brand-beside { font-size: 1rem; }
@media (max-width: 640px) { .brand-beside { font-size: .9rem; max-width: 40vw; } }

/* Logo-card hero: the cards float out of step (independent `translate`/`rotate`, so the scroll drift still applies).
   The name card only floats, never tilts, so its text stays sharp. */
@keyframes sf-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -12px; } }
@keyframes sf-sway { 0%, 100% { rotate: 0deg; translate: 0 0; } 50% { rotate: 2.5deg; translate: 6px -8px; } }
.stack.brand .brand-face { animation: sf-float 6s ease-in-out infinite; }
.stack.brand .tint { animation: sf-sway 8s ease-in-out infinite; }
.stack.brand .tint2 { animation: sf-sway 7s ease-in-out -3s infinite reverse; }

/* "About your current website": findings rise in one after another */
.js .audit-list li { opacity: 0; transform: translateY(18px); transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.2,1); }
.js .audit-list li.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .stack.brand .card-photo { animation: none; }
  .js .audit-list li { opacity: 1; transform: none; }
}
/* a service with no description is a slim row, even in the full card grid, instead of a tall empty card */
.offer-grid:not(.compact) .offer.short { display: flex; align-items: center; gap: 14px; padding: 16px 20px; align-self: start; }
.offer-grid:not(.compact) .offer.short .num { margin: 0; flex: none; }
.offer-grid:not(.compact) .offer.short h3 { margin: 0; }

/* ---------- Scroll pins, modelled on Marketing Warehouse ---------- */
:root { --hdr: 69px; }
@media (max-width: 640px) { :root { --hdr: 59px; } }

/* Hero pin: the opening screen sticks under the header inside a taller track, and scrolling through the
   track moves the photos through the stack. Pinned only once the script runs (html.js), so without it
   the page reads normally. */
.js .hero-track { position: relative; height: 240vh; }
.js .hero-track > .hero { position: sticky; top: var(--hdr); min-height: calc(100vh - var(--hdr)); min-height: calc(100svh - var(--hdr)); }
.stage { position: relative; height: min(440px, calc(100svh - var(--hdr) - 140px)); min-height: 280px; perspective: 1100px; }
.stage-inner { position: absolute; inset: 0; }
.shot {
  position: absolute; left: 50%; top: 50%; width: min(86%, 470px); aspect-ratio: 3 / 2;
  border-radius: 16px; overflow: hidden; background: linear-gradient(135deg, #1a2433, #121a25);
  box-shadow: 0 30px 60px rgba(0,0,0,.45), 0 0 0 1px rgba(255,255,255,.08);
  transform: translate(-50%, -50%) translateZ(-420px); opacity: 0;
}
.shot img { width: 100%; height: 100%; object-fit: cover; -webkit-user-drag: none; user-select: none; -webkit-user-select: none; }
.shot span { position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 16px 12px; color: #fff; font-weight: 800; font-size: .95rem; background: linear-gradient(transparent, rgba(0,0,0,.7)); opacity: 0; }
/* without the script (or with reduced motion) the front photo shows, still */
.shot[data-pos="0"] { transform: translate(-50%, -50%); opacity: 1; z-index: 5; }
.shot[data-pos="0"] span { opacity: 1; }
.stage-js .shot { will-change: transform, opacity; }
.stage-js .shot span { opacity: var(--cap, 0); }
.stage-progress { position: absolute; left: 14%; right: 14%; bottom: 0; height: 3px; border-radius: 3px; background: rgba(255,255,255,.14); overflow: hidden; }
.stage-progress span { display: block; height: 100%; background: var(--accent); transform-origin: left; transform: scaleX(0); }
.hero .scroll-cue { opacity: var(--cue, 1); }

/* Phones: the pinned opening is exactly one visible screen (svh: what's left once the browser bars are in),
   the copy takes what it needs and the stage fills the rest above the bottom bar, sizing its photos from
   that space (cqh = % of the stage's own height). */
@media (max-width: 860px) {
  .js .hero-track { height: 230svh; }
  .js .hero-track > .hero { height: calc(100vh - var(--hdr)); height: calc(100svh - var(--hdr)); min-height: 0; padding: 22px 0 92px; align-items: stretch; }
  .js .hero-track > .hero > .hero-grid { display: flex; flex-direction: column; align-items: stretch; height: 100%; gap: 0; }
  .js .hero-track .hero-copy { flex: none; }
  .js .hero-track .stage { flex: 1 1 auto; height: auto; min-height: 110px; margin: 12px -8px 0; container-type: size; }
  .js .hero-track .shot { width: min(80%, 150cqh); }
  .js .hero-track .scroll-cue { display: none; }
}
@media (max-width: 860px) and (max-height: 760px) {
  .js .hero-track h1 { font-size: clamp(1.9rem, 8.4vw, 2.4rem); }
  .js .hero-track .lead { font-size: .98rem; line-height: 1.5; margin-bottom: 0; }
}
@media (max-width: 860px) and (max-height: 620px) {
  .js .hero-track > .hero { padding-top: 14px; }
  .js .hero-track h1 { font-size: clamp(1.7rem, 7.6vw, 2.05rem); margin-bottom: .3em; }
  .js .hero-track .lead { font-size: .92rem; line-height: 1.45; }
  .js .hero-track .eyebrow { margin-bottom: .35em; }
}
/* too short to hold a pinned screen (a phone held sideways): no pin */
@media (max-height: 480px) {
  .js .hero-track { height: auto; }
  .js .hero-track > .hero { position: relative; top: 0; height: auto; }
}

/* Gallery pin: the section sticks and scrolling down slides the photos sideways (continuous, no snapping),
   with dots that follow live. Finger and mouse drags move it too. Below 540px tall, or with reduced motion,
   it is a plain swipeable row. */
.gallery { padding: 56px 0; }
.gal { overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.gal::-webkit-scrollbar { display: none; }
.gal-track { display: flex; gap: 16px; width: max-content; padding: 4px 20px 8px; }
@media (min-width: 1160px) { .gal-track { padding-left: calc((100vw - var(--wrap)) / 2 + 20px); padding-right: calc((100vw - var(--wrap)) / 2 + 20px); } }
.gal-item { flex: 0 0 min(80vw, 480px); margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--soft); }
.gal-item img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; -webkit-user-drag: none; user-select: none; -webkit-user-select: none; }
.gal-item figcaption { font-size: .9rem; color: var(--muted); padding: 10px 14px; }
.gal-foot { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 14px; }
.gal-dots { position: relative; display: flex; gap: 10px; padding: 8px 12px; border-radius: 999px; background: var(--soft); }
.gal-dot { width: 8px; height: 8px; border-radius: 8px; background: #c3ccd6; }
.gal-pill { position: absolute; left: 0; top: 8px; width: 22px; height: 8px; border-radius: 8px; background: var(--accent-ink); will-change: transform; }
.gal-hint { margin: 0; color: var(--muted); font-size: .9rem; font-weight: 700; opacity: 0; }
.gal-pin.is-pinned .gallery { position: sticky; top: var(--hdr); height: calc(100vh - var(--hdr)); height: calc(100svh - var(--hdr)); display: flex; flex-direction: column; justify-content: center; padding: 24px 0; overflow: clip; }
.gal-pin.is-pinned .gal { overflow: visible; }
.gal-pin.is-pinned .gal-track { will-change: transform; touch-action: pan-y; cursor: grab; user-select: none; -webkit-user-select: none; }
.gal-pin.is-pinned .gal-track:active { cursor: grabbing; }
@media (max-width: 760px) {
  .gal-pin.is-pinned .gallery { justify-content: flex-start; padding: 18px 0 92px; }
  .gal-pin.is-pinned .section-head { margin-bottom: 14px; }
}
@media (max-width: 760px) and (max-height: 640px) {
  .gal-pin.is-pinned h2 { font-size: 1.35rem; }
  .gal-pin.is-pinned .gal-item img { height: min(300px, 40svh); }
}

@media (prefers-reduced-motion: reduce) {
  .js .hero-track { height: auto; }
  .js .hero-track > .hero { position: relative; top: 0; height: auto; }
  .stage-progress, .gal-hint { display: none; }
}

/* Stand-in cards in the hero pin (pages with too few photos of their own): the business's real service names
   on a tinted card with a dashed photo frame and a "Your photo here" tag, so the owner sees where their photos
   would go. The logo card is white. Both stay flat (no tilt) so their text renders sharp. */
.shot.stand-in { display: flex; flex-direction: column; justify-content: flex-end; align-items: flex-start; gap: 10px; padding: 22px 24px;
  background: linear-gradient(150deg, var(--accent-ink), #0b1017); color: #fff; }
.shot.stand-in::before { content: ""; position: absolute; inset: 12px; border: 2px dashed rgba(255,255,255,.28); border-radius: 10px; pointer-events: none; }
.shot.stand-in b { position: relative; font-size: clamp(1.05rem, 2.2vw, 1.4rem); line-height: 1.2; font-weight: 800; }
.shot.stand-in small { position: relative; padding: 4px 11px; border: 1px dashed rgba(255,255,255,.7); border-radius: 999px; font-size: .74rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; }
.shot.logo-shot { background: #fff; display: grid; place-items: center; padding: 10% 12%; }
.shot.logo-shot img { width: auto; height: auto; max-width: 100%; max-height: 100%; object-fit: contain; }
@media (max-width: 860px) { .js .hero-track .shot.stand-in { padding: 16px 18px; } .js .hero-track .shot.stand-in b { font-size: 1.05rem; } }
/* only the front card's words show (they fade with its distance from the front, like MW's captions),
   so two cards' text never overlap mid-handover */
.stage-js .shot.stand-in b, .stage-js .shot.stand-in small { opacity: var(--cap, 0); }
.stage-progress { bottom: -16px; }
@media (max-width: 860px) { .stage-progress { bottom: -6px; } }

/* Cards take each photo's own shape (--ar = width/height). Hero cards fit inside the stage both ways: no wider
   than 470px (never wider than the photo itself) and no taller than 86% of the stage (cqh). */
.stage { container-type: size; }
.shot { aspect-ratio: var(--ar, 1.5); width: min(86%, 470px, calc(86cqh * var(--ar, 1.5))); }
.stage .shot.stand-in, .stage .shot.logo-shot { --ar: 1.5; }
@media (max-width: 860px) { .js .hero-track .shot { width: min(80%, 470px, calc(88cqh * var(--ar, 1.5))); } }
/* gallery photos share one height and take their own width */
.gal-item { flex: 0 0 auto; }
.gal-item img { aspect-ratio: var(--ar, 1.333); height: min(360px, 46vh, 46svh); width: auto; max-width: 86vw; }
.gal-item figcaption { max-width: calc(min(360px, 46svh) * var(--ar, 1.333)); }

/* Findings: the two labels appear once, as column headings; each item is just the problem and, beside it
   (under it on phones), the fix with a check mark. No repeated labels. */
.audit-cols { display: grid; grid-template-columns: 44px 1fr 1fr; gap: 18px; padding: 0 20px 10px; font-size: .78rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #9fb3c8; }
.audit-cols span:first-child { grid-column: 2; }
.audit-list li { padding: 18px 20px; gap: 18px; }
.audit-list .found, .audit-list .fix { margin: 0; }
.audit-list .found { color: #fff; font-weight: 600; }
.audit-list .fix { color: #cfe3c0; position: relative; padding-left: 26px; }
.audit-list .fix::before { content: "\2713"; position: absolute; left: 0; top: 0; color: var(--accent); font-weight: 800; }
@media (max-width: 760px) {
  .audit-cols { display: none; }
  .audit-list li { gap: 6px 14px; padding: 16px; }
  .audit-list .fix { font-size: .95rem; }
}

/* Card look (MW): solid cards on a dark base with a shadow; the front card is crisp, the ones behind are darker
   (a dark shade inside the card, whose opacity the script sets), never see-through. Compact: on desktop a card is
   at most 260px tall and 440px wide, so the stack sits inside its column with dark space around it. */
.shot { background: #0b1017; box-shadow: 0 28px 56px rgba(0,0,0,.55), 0 0 0 1px rgba(255,255,255,.08); }
.shot .shade { position: absolute; inset: 0; background: #0b1017; opacity: 0; pointer-events: none; border-radius: inherit; }
.shot { width: min(86%, 440px, calc(min(260px, 62cqh) * var(--ar, 1.5))); }
.stage .shot.stand-in, .stage .shot.logo-shot { --ar: 1.6; }
.shot span { z-index: 1; }
@media (max-width: 860px) { .js .hero-track .shot { width: min(78%, 440px, calc(70cqh * var(--ar, 1.5))); } }

/* PREVIEW (Paesano, Tallman, Griffin): a soft dark inner edge on photo cards, so a photo shot on white (a pizza on
   paper) reads as a photo with an edge, not a bright pasted-in box. */
.preview .shot:not(.flat)::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.06), inset 0 0 70px rgba(11,16,23,.55); z-index: 1; }
.preview .shot span { z-index: 2; }

/* PREVIEW: one card shape (3:2, set by the build as --ar) for every hero card, as on MW. A photo that cropping would
   cut too much of, or one with a sign in it, shows whole and centred over a blurred, darkened copy of itself (or
   on its own plain backdrop colour, set inline), so the card keeps its shape and nothing is cut off. */
.preview .stage .shot.stand-in, .preview .stage .shot.logo-shot { --ar: 1.5; }
.preview .shot.fit .fill { position: absolute; left: -10%; top: -10%; width: 120%; height: 120%; object-fit: cover;
  filter: blur(18px) brightness(.45) saturate(1.15); }
.preview .shot.fit .main { position: relative; object-fit: contain; }

/* PREVIEW, phones: the pinned opening is one screen less the concept strip (--strip, measured by the script), so at
   the very top the stack sits above the bottom call bar; once the strip has scrolled away the extra space shows as
   the hero's own dark background. Cards nearly fill the stage's height (the ones behind peek out sideways and up, not
   down), and stand-in labels stay on one line. */
@media (max-width: 860px) and (min-height: 481px) {
  .preview.js .hero-track { background: var(--night); }
  .preview.js .hero-track > .hero { height: calc(100svh - var(--hdr) - var(--strip, 0px)); }
  .preview.js .hero-track .shot { width: min(75%, 440px, calc(84cqh * var(--ar, 1.5))); }
  .preview.js .hero-track .stage { margin-top: 18px; }
  .preview.js .hero-track > .hero { padding-bottom: 64px; }   /* the stack itself keeps clear of the bottom bar */
  .preview .shot.stand-in { padding: 14px 16px; gap: 8px; }
  .preview .shot.stand-in::before { inset: 9px; }
  .preview .shot.stand-in b { font-size: clamp(.95rem, 4.2vw, 1.2rem); }
  .preview .shot.stand-in small { white-space: nowrap; font-size: .66rem; padding: 3px 9px; }
}

/* PREVIEW: the deck turns as one 3D object (MW): the script rotates .stage-inner, and its cards keep their depth */
.preview .stage-js .stage-inner { transform-style: preserve-3d; will-change: transform; }

/* PREVIEW, MW's hero details: the headline's last phrase in a two-colour gradient (accent to the second glow colour),
   two still glows in two colours (accent top right, a second colour bottom left), a dot grid that fades out
   downward, and the progress bar in the headline's gradient. Hero buttons stay on taller phones, above the stack. */
.preview .hero h1 .hl, .preview .hero h1 .hl .rw { background: linear-gradient(90deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
.preview .hero-glow { animation: none; filter: blur(90px); }
.preview .hero-glow.a { background: var(--accent); left: auto; right: -22vmax; top: -26vmax; opacity: .34; }
.preview .hero-glow.b { background: var(--accent-2); right: auto; left: -26vmax; bottom: -32vmax; top: auto; opacity: .3; }
.preview .hero.no-photo::after { -webkit-mask-image: linear-gradient(180deg, #000, transparent 85%); mask-image: linear-gradient(180deg, #000, transparent 85%); }
.preview .stage-progress span { background: linear-gradient(90deg, var(--accent), var(--accent-2)); }
/* (only on phones at least 700px tall: on shorter ones the buttons squeeze the photo cards too small, and the
   bottom bar carries the same two buttons) */
@media (max-width: 760px) and (min-height: 700px) {
  .preview .hero .btn-row { display: flex; flex-wrap: nowrap; gap: 10px; margin-top: 14px; }
  .preview .hero .btn-row .btn { flex: 1 1 0; text-align: center; padding: 11px 12px; white-space: nowrap; font-size: .92rem; }
}
@media (max-width: 360px) and (min-height: 481px) { .preview.js .hero-track .shot { width: min(72%, 440px, calc(84cqh * var(--ar, 1.5))); } }

/* Google rating line under the hero buttons (only where the data file has a "google" entry) */
.hero .rating { margin: 18px 0 0; color: #cdd6e0; font-size: .95rem; }
.hero .rating strong { color: #fff; }
.hero .rating .stars { color: #ffc940; letter-spacing: .05em; }
.hero .rating-sep { margin: 0 .5em; opacity: .6; }
@media (max-width: 860px) { .js .hero-track .hero .rating { margin-top: 10px; font-size: .88rem; } }
@media (max-width: 860px) { .hero .rating-sep, .hero .rating-years { display: none; } }

/* PREVIEW: one card shape per services grid. When some services have a description and others don't, every card
   keeps the full shape (number on top) and the cards in a row stretch to the same height; four services sit 2 x 2
   instead of three and a lone fourth. */
.preview .offer-grid:not(.compact) .offer.short { display: block; padding: 24px; align-self: stretch; }
.preview .offer-grid:not(.compact) .offer.short .num { margin: 0 0 14px; }
.preview .offer-grid:not(.compact) .offer.short h3 { margin-bottom: .3em; }
@media (min-width: 861px) { .preview .offer-grid.n4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* a long web address in "About your current website" wraps instead of widening the page on small phones */
.audit-head a, .audit-head p, .site-footer a, .site-footer p { overflow-wrap: anywhere; }
.preview .js .ticker.still, .js.preview .ticker.still { cursor: default; -webkit-mask-image: none; mask-image: none; }
.js.preview .ticker.still .ticker-track { margin: 0 auto; }
