/* =============================================================================
   base.css â€” the fluid foundation. Copy into every site as css/base.css.
   Nothing here is width-locked: type, spacing and layout scale continuously
   from ~360px phones to ultrawide. This file is why sites are dynamic off the bat.
   ============================================================================= */

/* Pivot brand fonts (local OTFs in /fonts). Worky = display face from the Figma design.
   ponytail: "Adrianna" (Figma subhead face) has no font file yet â€” --font-subhead falls back
   to Montserrat; drop Adrianna.otf into /fonts and add a @font-face when licensed. */
@font-face {
  font-family: "Montserrat";
  src: url("../fonts/Montserrat-Regular.otf") format("opentype");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Montserrat";
  src: url("../fonts/Montserrat-Medium.otf") format("opentype");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Montserrat";
  src: url("../fonts/Montserrat-SemiBold.otf") format("opentype");
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "Montserrat";
  src: url("../fonts/Montserrat-Bold.otf") format("opentype");
  font-weight: 700;
  font-display: swap;
}
@font-face {
  font-family: "Worky";
  src: url("../fonts/Worky.otf") format("opentype");
  font-weight: 400;
  font-display: swap;
}

:root {
  /* COLOURS â€” Pivot (from Figma: WarehouseBlack / PivotPink / SkyBlue / offwhite). */
  --brand: #221d16; /* primary â€” WarehouseBlack */
  --brand-dark: #000000; /* darker primary (hovers, headers) */
  --accent: #dc1478; /* accent â€” PivotPink */
  --muted: #6b6b6b; /* secondary text */
  --surface: #eeece8; /* light section background â€” offwhite */
  --ink: #221d16; /* body text */
  --white: #ffffff;
  --sky: #dadee8; /* hero background â€” SkyBlue */
  --offwhite: #eeece8;

  /* TYPE â€” fluid scale. Never set a size that only looks right at one width. */
  --font:
    "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display:
    "Worky", "Montserrat", system-ui, sans-serif; /* WORK LOGISTICS CONNECTIVITY */
  --font-subhead:
    "Adrianna", "Montserrat", system-ui, sans-serif; /* hero headline (fallback active) */
  --t-header: clamp(48px, 7vw, 88px);
  --t-h1: clamp(40px, 5.4vw, 70px);
  --t-h2: 24px; /* all h2s fixed at 24px (per Devon, 22 Jul) */
  --t-h3: clamp(24px, 2.6vw, 31px);
  --t-lg: 20px;
  --t-body: 12px; /* all body copy fixed at 12px (per Devon, 22 Jul) */
  --t-small: 11px;
  --t-cta: 12px;

  /* SPACING â€” gutters and section rhythm breathe with the viewport. */
  --wrap: 1240px; /* max content width; page itself is fluid */
  --pad: clamp(20px, 5vw, 64px); /* fluid side padding */
  --section-y: clamp(56px, 8vw, 128px); /* vertical section rhythm */
  --measure: 68ch; /* readable line-length cap */

  --nav-h: 68px;
  --radius: 10px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* â”€â”€ Minimal reset â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}
html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
  scroll-behavior: smooth;
  overscroll-behavior-y: none;
} /* no elastic bounce past the top */
html {
  scrollbar-width: none;
} /* scrolling works, scrollbar hidden (per Devon) */
html::-webkit-scrollbar {
  display: none;
}
body {
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden; /* body never gets a horizontal scrollbar */
  overflow-wrap: break-word; /* long words wrap instead of overflowing (else clipped by overflow-x) */
}
img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  font: inherit;
  cursor: pointer;
}
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* â”€â”€ Typography scale â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
h1 {
  font-size: var(--t-h1);
  line-height: 1.05;
  font-weight: 700;
}
h2 {
  font-size: var(--t-h2);
  line-height: 1.12;
  font-weight: 700;
}
h3 {
  font-size: var(--t-h3);
  line-height: 1.2;
  font-weight: 700;
}
p {
  max-width: var(--measure);
}
/* Unbreakable tokens (URLs, emails, long single words) break instead of running off narrow screens. */
a,
h1,
h2,
h3,
h4,
h5,
h6,
td,
li {
  overflow-wrap: anywhere;
}
.eyebrow {
  font-size: var(--t-cta);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
}

/* â”€â”€ Layout helpers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
}
.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;
} /* screen-reader-only text */
.section {
  padding-block: var(--section-y);
}
.section--surface {
  background: var(--surface);
}
.measure {
  max-width: var(--measure);
}
.stack > * + * {
  margin-top: 1rem;
}
.center {
  text-align: center;
  margin-inline: auto;
}

/* Auto-fit grid that never overflows: cells wrap when they can't hold min width. */
.grid {
  display: grid;
  gap: clamp(16px, 3vw, 32px);
}
.grid--auto {
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}

/* Wide content (tables/code/diagrams) scrolls inside its own box, never the page. */
.scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* â”€â”€ Buttons â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.9em 1.6em;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: var(--t-cta);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  transition:
    background 0.2s var(--ease),
    color 0.2s var(--ease),
    transform 0.2s var(--ease);
}
.btn:active {
  transform: translateY(1px);
}
.btn-fill {
  background: var(--brand);
  color: var(--white);
}
.btn-fill:hover {
  background: var(--accent);
}
.btn-outline {
  background: transparent;
  color: var(--brand);
  border-color: currentColor;
}
.btn-outline:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--white);
}

/* â”€â”€ Submit busy state (main.js adds .is-loading + injects the spinner span) â”€â”€â”€â”€
   A form submit can legitimately take many seconds â€” the server retries the Markt
   delivery before answering â€” and a merely-disabled button reads as "the button is
   broken", so visitors re-click or leave. The swapped LABEL is what carries the
   state: the global reduced-motion rule at the end of this file freezes every
   animation, so the spinner must never be the only signal. main.js also sets
   aria-busy. Deliberately standalone classes, not nested under .btn: the submit
   buttons here are .cf__submit and .lpf__submit, neither of which is a .btn.

   The selector below is paired with that aria-busy for specificity as much as for
   meaning — a bare .is-loading ties with .cf__submit's `cursor: pointer` and then
   loses on source order. */
.is-loading[aria-busy="true"] {
  cursor: progress;
}
.btn__spinner {
  /* inline-block + margin rather than a flex gap, for the same reason: these
     buttons are plain block/inline buttons, not flex containers. */
  display: inline-block;
  vertical-align: -0.125em;
  width: 1em;
  height: 1em;
  margin-right: 0.5em;
  border: 2px solid currentColor;
  border-top-color: transparent; /* the gap that makes the rotation legible */
  border-radius: 50%;
  animation: btn-spin 0.7s linear infinite;
}
@keyframes btn-spin {
  to {
    transform: rotate(360deg);
  }
}

/* â”€â”€ Hero (100svh so mobile chrome doesn't clip it) â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh; /* vh fallback for Safari < 15.4 */
  display: grid;
  place-items: center;
  text-align: center;
  color: var(--white);
  overflow: hidden;
}
.hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: -2;
}
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.55));
  z-index: -1;
}
.hero__inner {
  padding: var(--pad);
  display: grid;
  gap: 1.2rem;
  justify-items: center;
}
.hero h1 {
  font-size: var(--t-header);
}

/* â”€â”€ Navigation â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 40;
  transition:
    transform 0.3s var(--ease),
    background 0.3s var(--ease);
}
.nav.nav--hidden {
  transform: translateY(-100%);
} /* hidden on scroll-down; scroll-up or hovering the top edge brings it back */
.nav__bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: var(--nav-h);
}
.nav__logo {
  font-weight: 800;
  letter-spacing: 0.04em;
  font-size: var(--t-lg);
}
.nav__links {
  display: flex;
  gap: clamp(12px, 2vw, 28px);
  margin-left: auto;
}
.nav__links a {
  font-size: var(--t-cta);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
}
.nav__cta {
  padding-block: 0.6em;
}
/* Homepage bar: transparent over hero, solid once scrolled. Sub-page bar: always solid. */
.nav:not(.nav--static) {
  background: transparent;
  color: var(--white);
}
.nav.nav--static,
.nav.is-scrolled {
  background: var(--white);
  color: var(--ink);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
}
.nav.nav--static .nav__cta,
.nav.is-scrolled .nav__cta {
  background: var(--brand);
  color: var(--white);
}

.nav__burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  background: none;
  border: 0;
  padding: 8px;
  min-width: 44px;
  min-height: 44px;
}
.nav__burger span {
  width: 24px;
  height: 2px;
  background: currentColor;
}

/* Drawer */
.drawer-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 50;
}
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  height: 100vh;
  height: 100dvh;
  width: min(86vw, 340px);
  background: var(--white);
  color: var(--ink);
  z-index: 60;
  padding: clamp(24px, 6vw, 48px);
  transform: translateX(100%);
  transition: transform 0.3s var(--ease);
  display: flex;
  flex-direction: column;
}
.drawer.is-open {
  transform: none;
}
.drawer__close {
  align-self: flex-end;
  display: grid;
  place-items: center;
  min-width: 44px;
  min-height: 44px;
  font-size: 32px;
  line-height: 1;
  background: none;
  border: 0;
  color: inherit;
}
.drawer__links {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
  margin-top: 2rem;
  font-size: var(--t-lg);
}

@media (max-width: 860px) {
  .nav__links,
  .nav__cta {
    display: none;
  }
  .nav__burger {
    display: flex;
  }
}

/* â”€â”€ Footer â€” Pivot styling (no Figma frame; follows the contact section's dark
   WarehouseBlack + offwhite + PivotPink accents). â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.footer {
  background: var(--brand);
  color: var(--offwhite);
  padding-block: clamp(40px, 6vw, 72px);
  border-top: 1px solid rgba(238, 236, 232, 0.12);
} /* seam against the equally dark contact section */
.footer__inner {
  display: grid;
  gap: 1.6rem;
  justify-items: center;
  text-align: center;
}
.footer__logo img {
  width: clamp(140px, 11vw, 201px);
  height: auto;
}
.footer__legal {
  display: flex;
  gap: 0.9rem;
  flex-wrap: wrap;
  justify-content: center;
  font-size: var(--t-cta);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
}
.footer__legal span {
  color: var(--accent);
}
.footer__legal a {
  transition: color 0.2s var(--ease);
}
.footer__legal a:hover,
.footer__legal a:focus-visible {
  color: var(--accent);
}
.footer__social {
  display: flex;
  gap: 1rem;
  list-style: none;
  padding: 0;
}
.footer__social a {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid rgba(238, 236, 232, 0.3);
  border-radius: 50%;
  transition:
    background 0.2s var(--ease),
    border-color 0.2s var(--ease);
}
.footer__social a:hover,
.footer__social a:focus-visible {
  background: var(--accent);
  border-color: var(--accent);
}
.footer__copy {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: rgba(238, 236, 232, 0.75);
  line-height: 1.8;
  max-width: none;
}
.footer__copy a {
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color 0.2s var(--ease);
}
.footer__copy a:hover,
.footer__copy a:focus-visible {
  color: var(--accent);
}

/* â”€â”€ Forms â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.form {
  display: grid;
  gap: 1rem;
  max-width: 560px;
}
.form__row {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
}
.form label {
  display: grid;
  gap: 0.4rem;
  font-size: 14px;
}
.form input,
.form select,
.form textarea {
  font: inherit;
  font-size: 16px;
  padding: 0.8em 1em;
  border: 1px solid #cfcfcf;
  border-radius: var(--radius);
  background: var(--white);
  width: 100%; /* font-size >=16px so iOS Safari doesn't zoom on focus */
}
.form input:focus,
.form select:focus,
.form textarea:focus {
  border-color: var(--accent);
  outline: none;
}
.form__consent {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  font-size: 13px;
}
.form__msg {
  font-size: 14px;
}
.form__msg.is-error {
  color: #b0261a;
}

/* Body offset so fixed nav never covers content on sub-pages. */
.has-static-nav {
  padding-top: var(--nav-h);
}

/* â”€â”€ Blog list cards â€” slant-paired like the nav CTA pair: flat outer edges, a
   parallel diagonal seam between the two cards of each row. Card bg is offwhite
   (or the post image); hover swaps ONLY the background to pink via the ::after
   veil â€” the offwhite caption block at the bottom never changes. â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
[data-route="blog"] .wrap {
  max-width: 1440px;
} /* wider stage for the card pairs */
.blog-cards {
  --slant: 48px;
  --seam: 16px;
  margin-top: 3rem;
  display: flex;
  flex-wrap: wrap;
  row-gap: var(--seam);
}
.blog-card {
  position: relative;
  display: block;
  overflow: hidden;
  background: var(--offwhite);
  aspect-ratio: 933/546;
  width: calc(50% + var(--slant) / 2 - var(--seam) / 2);
}
.blog-card--sr {
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--slant)) 100%, 0 100%);
  border-radius: 12px 0 0 12px;
  /* shape() rounds the slant corners (râ‰ˆ14px; 2px = slope run over 14px at this aspect);
     invalid where unsupported so the polygon above stands (sharp slant) */
  clip-path: shape(
    from 0 0,
    line to calc(100% - 14px) 0,
    curve to calc(100% - 2px) 14px with 100% 0,
    line to calc(100% - var(--slant) + 2px) calc(100% - 14px),
    curve to calc(100% - var(--slant) - 14px) 100% with
      calc(100% - var(--slant)) 100%,
    line to 0 100%,
    close
  );
}
.blog-card--sl {
  clip-path: polygon(var(--slant) 0, 100% 0, 100% 100%, 0 100%);
  border-radius: 0 12px 12px 0;
  clip-path: shape(
    from calc(var(--slant) + 14px) 0,
    line to 100% 0,
    line to 100% 100%,
    line to 14px 100%,
    curve to 2px calc(100% - 14px) with 0 100%,
    line to calc(var(--slant) - 2px) 14px,
    curve to calc(var(--slant) + 14px) 0 with var(--slant) 0,
    close
  );
  margin-left: calc(var(--seam) - var(--slant));
} /* interlock: seam width = --seam, edges parallel */
.blog-card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.blog-card__cap {
  position: absolute;
  z-index: 1;
  left: 0;
  right: 0;
  bottom: 0; /* card clip slants its ends to match */
  background: var(--offwhite);
  padding: clamp(14px, 1.5vw, 26px) clamp(18px, 2vw, 32px);
  transition: background 0.25s var(--ease);
}
.blog-card:hover .blog-card__cap,
.blog-card:focus-visible .blog-card__cap {
  background: var(--accent);
} /* only the caption goes pink */
.blog-card:hover .blog-card__cap *,
.blog-card:focus-visible .blog-card__cap * {
  color: var(--offwhite) !important;
} /* !important: the date's inline muted color */
/* the slant reaches its full inset at the card bottom, where the cap sits â€” the pad
   must clear the whole slant; the narrower --slant is what buys the text more width */
.blog-card--sr .blog-card__cap {
  padding-right: calc(var(--slant) + 8px);
}
.blog-card--sl .blog-card__cap {
  padding-left: calc(var(--slant) + 8px);
}
.blog-card__title {
  font-size: clamp(14px, 1.1vw, 21px);
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--ink);
}
.blog-card__excerpt {
  margin-top: 0.5em;
  font-size: 12px;
  line-height: 1.4;
  color: var(--ink);
}
@media (max-width: 700px) {
  /* single column: full-width cards, no slant pair */
  .blog-card,
  .blog-card--sl {
    width: 100%;
    margin-left: 0;
    clip-path: none;
    border-radius: 5px;
  }
  .blog-card--sr .blog-card__cap,
  .blog-card--sl .blog-card__cap {
    padding-left: 18px;
    padding-right: 18px;
  }
  .blog-card__excerpt {
    display: none;
  } /* heading + date only on phones */
}

/* â”€â”€ Legal pages (privacy / terms) â€” long-form readable typography â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.legal {
  max-width: var(--measure);
}
.legal h1 {
  font-size: var(--t-h2);
}
.legal h2 {
  font-size: var(--t-h3);
  margin-top: 2.2rem;
}
.legal h3 {
  font-size: var(--t-lg);
  margin-top: 1.6rem;
}
.legal p,
.legal ul,
.legal ol {
  margin-top: 1rem;
}
.legal ul,
.legal ol {
  padding-left: 1.4rem;
}
.legal li {
  margin-top: 0.4rem;
}
.legal a {
  color: var(--brand);
  text-decoration: underline;
}

/* â”€â”€ Image-layout repertoire â€” frames, captions, galleries (immersive, not stiff) â”€â”€ */
.media-frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
}
.media-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.media-cap {
  position: absolute;
  inset: auto 0 0 0;
  padding: 1rem 1.2rem;
  color: var(--white);
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.6), transparent);
  font-weight: 600;
  pointer-events: none;
}
.gallery {
  display: grid;
  gap: clamp(12px, 2vw, 24px);
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
.gallery-frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
}
.gallery-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* =============================================================================
   Pivot â€” hero + navbar carried over from Figma (node 2:12 / menu state 2014:28).
   Everything below is fluid: positions in %, type via clamp â€” no fixed canvas.
   ============================================================================= */

/* â”€â”€ Navbar (PIVOT logo Â· MENU toggle Â· QUINNS HILL + CONNECT WITH US) â”€â”€â”€â”€â”€â”€â”€ */
.nav:not(.nav--static) {
  color: var(--ink);
  background: transparent;
} /* transparent over the hero (per Devon, 23 Jul â€” supersedes the solid-white bar) */
.nav.is-scrolled {
  background: var(--white);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
} /* solid once the hero is covered */
.nav.is-menu-open {
  background: none;
} /* the dark menu panel supplies the backdrop */
.nav__bar--pivot {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--nav-h);
  padding-inline: clamp(16px, 1.6vw, 30px);
}
.nav__logo--pivot {
  display: block;
  width: clamp(110px, 8.8vw, 168px); /* shrunk (per Devon) */
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
} /* logo true screen-centre (per Figma) */
.nav__logo--pivot svg,
.nav__logo--pivot img {
  width: 100%;
  height: auto;
  transition: opacity 0.3s var(--ease);
}
/* The bar is solid white now, so the wordmark stays the black version everywhere
   (the old is-over-dark cross-fade to the light logo is retired). */
.nav__logo-light {
  position: absolute;
  inset: 0;
  opacity: 0;
}

.nav__menu {
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  border: 0; /* left-aligned slanted chip (per Figma) */
  height: 34px;
  padding: 0 clamp(18px, 1.7vw, 28px) 0 clamp(12px, 1vw, 16px);
  background: rgb(
    184 191 204 / 0.2
  ); /* same gray as before at 20% opacity; stays in the open state too */
  clip-path: polygon(
    0 0,
    100% 0,
    calc(100% - 24px) 100%,
    0 100%
  ); /* same angle as the staggered lines (6px per 10px) */
  border-radius: 5px 0 0 5px;
  /* shape() rounds the slant corners; invalid where unsupported so the polygon above stands (sharp slant) */
  clip-path: shape(
    from 0 0,
    line to calc(100% - 5px) 0,
    curve to calc(100% - 2.6px) 4.3px with 100% 0,
    line to calc(100% - 21.4px) calc(100% - 4.3px),
    curve to calc(100% - 29px) 100% with calc(100% - 24px) 100%,
    line to 0 100%,
    close
  );
  font-family: var(--font);
  font-weight: 600;
  font-size: clamp(13px, 0.84vw, 16px);
  letter-spacing: 0.05em;
  color: var(--ink);
  text-transform: uppercase;
}
.nav__menu-lines {
  display: inline-flex;
  flex-direction: column;
  gap: 3px;
  width: 28px;
}
.nav__menu-lines span {
  height: 2px;
  background: currentColor;
  transition:
    transform 0.25s,
    opacity 0.25s;
}
.nav__menu-lines span:nth-child(1) {
  transform: translateX(6px);
} /* staggered right-shift = slanted look */
.nav__menu-lines span:nth-child(2) {
  transform: translateX(3px);
}
/* Menu open â†’ lines fold into an Ã— (desktop + mobile share this markup) */
.nav.is-menu-open .nav__menu-lines span:nth-child(1) {
  transform: translateY(5px) rotate(45deg) scale(0.8);
}
.nav.is-menu-open .nav__menu-lines span:nth-child(2) {
  opacity: 0;
}
.nav.is-menu-open .nav__menu-lines span:nth-child(3) {
  transform: translateY(-5px) rotate(-45deg) scale(0.8);
}

/* Menu open: the same MENU button turns white and its lines spin into an X.
   The nav lifts above the drawer so the button keeps working; everything else
   in the bar is handed over to the drawer's own (white) copies. */
/* Hold the elevated z-index until the drawer finishes closing (.4s), so the CTAs
   never dip under the sliding photo â€” no close flicker. */
.nav {
  transition:
    transform 0.3s var(--ease),
    background 0.3s var(--ease),
    z-index 0s 0.45s;
}
.nav.is-menu-open {
  z-index: 70;
  pointer-events: none;
  transition:
    transform 0.3s var(--ease),
    background 0.3s var(--ease);
}
.nav.is-menu-open .nav__menu {
  pointer-events: auto;
  color: var(--white);
} /* white label + Ã— over the dark panel */
.nav.is-menu-open .nav__ctas {
  pointer-events: auto;
} /* CTAs stay the navbar's own â€” always visible, no swap */
.nav.is-menu-open .nav__logo {
  visibility: hidden;
  transition: visibility 0s 0.24s;
} /* centred logo swaps just before the panel fully reaches centre */

.nav__ctas {
  display: flex;
}
.navbtn {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 clamp(14px, 1.2vw, 22px);
  font-family: var(--font);
  font-weight: 600;
  font-size: clamp(10px, 0.7vw, 13px);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--offwhite);
  white-space: nowrap;
  clip-path: polygon(12px 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
}
.navbtn + .navbtn {
  margin-left: -8px;
} /* shared diagonal seam, like the Figma buttons */
/* Nav pair: only the middle seam is diagonal â€” flat outer edges */
.nav__ctas .navbtn:first-child,
.qh__top .navbtn {
  clip-path: polygon(0 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
  border-radius: 5px 0 0 5px;
  /* shape() rounds the slant corners; invalid where unsupported so the polygon above stands (sharp slant) */
  clip-path: shape(
    from 0 0,
    line to calc(100% - 5px) 0,
    curve to calc(100% - 1.4px) 4.8px with 100% 0,
    line to calc(100% - 10.6px) calc(100% - 4.8px),
    curve to calc(100% - 17px) 100% with calc(100% - 12px) 100%,
    line to 0 100%,
    close
  );
}
.nav__ctas .navbtn:last-child,
.popup__cta {
  clip-path: polygon(12px 0, 100% 0, 100% 100%, 0 100%);
  border-radius: 0 5px 5px 0;
  clip-path: shape(
    from 17px 0,
    line to 100% 0,
    line to 100% 100%,
    line to 5px 100%,
    curve to 1.4px calc(100% - 4.8px) with 0 100%,
    line to 10.6px 4.8px,
    curve to 17px 0 with 12px 0,
    close
  );
}
.navbtn--pink {
  background: var(--accent);
}
.navbtn--dark {
  background: var(--brand);
}
.navbtn:hover {
  background: var(--accent);
}
.navbtn--pink:hover {
  background: #b30f61;
}

@media (max-width: 860px) {
  /* compact bar (per Devon): smaller logo + chips, both CTAs stay; "WITH US" drops */
  .nav__logo--pivot {
    width: 100px;
  }
  .navbtn {
    height: 32px;
    padding: 0 12px;
    font-size: 10px;
  }
  .navbtn + .navbtn {
    margin-left: -6px;
  }
  .navbtn__more {
    display: none;
  }
  .nav__menu {
    height: 32px;
    padding: 0 20px 0 12px;
    font-size: 12px;
  }
}
@media (max-width: 640px) {
  /* phones (new design, 22 Jul): logo top-left; CONNECT WITH US + bare lines on the right */
  .nav__logo--pivot {
    position: static;
    transform: none;
  } /* out of the screen-centre â€” leads the bar */
  .navbtn--pink {
    display: none;
  } /* QUINNS HILL dropped on phones */
  .navbtn__more {
    display: inline;
  } /* dark CTA keeps its full "WITH US" */
  .nav__ctas {
    order: 2;
    margin-left: auto;
  } /* auto margin pushes CTA + lines to the right edge */
  /* CONNECT WITH US: slant flips to the RIGHT edge (flat left) so it pairs with the menu chip */
  .nav__ctas .navbtn:last-child {
    padding: 0 18px 0 9px; /* text sits left of centre (per Devon) */
    clip-path: polygon(0 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
    border-radius: 5px 0 0 5px;
    clip-path: shape(
      from 0 0,
      line to calc(100% - 5px) 0,
      curve to calc(100% - 1.4px) 4.8px with 100% 0,
      line to calc(100% - 10.6px) calc(100% - 4.8px),
      curve to calc(100% - 17px) 100% with calc(100% - 12px) 100%,
      line to 0 100%,
      close
    );
  }
  /* menu toggle: grey 20% chip, slanted LEFT edge â€” mirrors the CTA across a small gap */
  .nav__bar {
    padding-inline: 26px;
  } /* logo off the left edge, menu off the right â€” equally */
  .nav__menu {
    order: 3;
    margin-left: -24px;
    height: 32px;
    padding: 0 14px 0 20px;
    background: rgba(74, 66, 56, 0.12);
    clip-path: polygon(12px 0, 100% 0, 100% 100%, 0 100%);
    border-radius: 0 5px 5px 0;
    clip-path: shape(
      from 17px 0,
      line to 100% 0,
      line to 100% 100%,
      line to 5px 100%,
      curve to 1.4px calc(100% - 4.8px) with 0 100%,
      line to 10.6px 4.8px,
      curve to 17px 0 with 12px 0,
      close
    );
  }
  .nav__menu-label {
    display: none;
  }
  .nav__menu-lines {
    width: 22px;
  }
}
@media (max-width: 360px) {
  .nav__logo--pivot {
    width: 88px;
  }
} /* tiny phones: CTA clears the logo */

/* Full-screen menu takeover (Figma menu-open state 2014:28). The container doesn't
   slide: the dark panel enters from the left, the photo from the right, while the
   bar (logo Â· MENU Â· CTAs) holds the same positions as the navbar beneath it. */
.drawer--pivot {
  left: 0;
  right: 0;
  width: auto;
  max-width: none;
  background: none;
  color: var(--offwhite);
  transform: none;
  padding: 0;
  display: block;
  visibility: hidden;
  transition: visibility 0s 0.4s;
}
.drawer--pivot.is-open {
  transform: none;
  visibility: visible;
  transition-delay: 0s;
}
/* Sky backdrop (per Devon 18 Jul): fades in slightly after the menu opens, but is gone
   the instant it closes â€” the base state has no transition, so closing cuts it immediately
   instead of lingering through the .4s panel slide-out. */
.drawer--pivot::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../images/growth-sky-day-1920.webp") center / cover no-repeat;
  opacity: 0;
}
.drawer--pivot.is-open::before {
  opacity: 1;
  transition: opacity 0.3s var(--ease) 0.2s;
}
.drawer__panel {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--brand);
  clip-path: polygon(0 0, 57% 0, calc(57% - 25vh) 100%, 0 100%);
  padding: calc(var(--nav-h) + 5vh) clamp(16px, 1.6vw, 30px)
    clamp(28px, 5vh, 56px);
  transform: translateX(-105%);
  transition: transform 0.4s var(--ease);
}
/* Photo: inset from top/bottom with rounded corners; the slanted left edge comes from
   skewing the wrapper (overflow hidden) and un-skewing the image, so the corners round. */
.drawer__photo {
  position: absolute;
  top: 11px;
  bottom: 11px;
  left: calc(58% - 12.5vh);
  right: -18vh;
  overflow: hidden;
  border-radius: var(--radius);
  transform: translateX(110%) skewX(-14deg);
  transition: transform 0.4s var(--ease);
}
.drawer__photo img {
  position: absolute;
  left: -18vh;
  top: 0;
  width: calc(100% + 36vh);
  height: 100%;
  object-fit: cover;
  object-position: center bottom; /* keep the loading-dock foreground, not the sky (per Devon, 24 Jul) */
  transform: skewX(14deg);
}
.drawer--pivot.is-open .drawer__panel {
  transform: none;
}
.drawer--pivot.is-open .drawer__photo {
  transform: skewX(-14deg);
}
.drawer__bar {
  position: relative;
  visibility: hidden;
}
.drawer--pivot.is-open .drawer__bar {
  visibility: visible;
  transition: visibility 0s 0.24s;
} /* white logo pops in just before the panel reaches centre */
.drawer__x {
  font-size: 26px;
  font-weight: 400;
  line-height: 1;
}
.drawer--pivot .drawer__links {
  gap: 0.1rem;
  margin-top: -2.5vh;
} /* higher + tighter link stack (per Devon) */
.drawer--pivot .drawer__links a {
  font-weight: 600;
  font-size: clamp(18px, 2vw, 24px);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.drawer--pivot .drawer__links a:hover {
  color: var(--accent);
}
/* dev-only mapper links â€” small chips pinned top-right under the nav CTAs (outside the
   clipped panel, above the photo) so they never move the menu layout; render only while
   _point-mapper.html exists */
.drawer__dev {
  position: absolute;
  top: 92px;
  right: clamp(16px, 1.6vw, 30px);
  z-index: 3;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  background: rgba(34, 29, 22, 0.85);
  border: 1px dashed var(--accent);
  border-radius: 4px;
  padding: 0.4em 0.7em;
}
.drawer__dev--2 {
  top: 121px;
}
.drawer__promo {
  margin-top: auto;
  font-weight: 400;
  text-transform: uppercase;
  font-size: clamp(22px, 2.3vw, 40px);
  line-height: 1.15;
  letter-spacing: 0.02em;
}
.drawer__promo-lead {
  font-weight: 700;
  color: var(--accent);
}
.drawer__img {
  margin-top: 16px;
  width: min(480px, 32vw);
  height: auto;
  border-radius: 8px;
} /* bottom-left render (Figma 2072:2) */
@media (max-width: 860px) {
  /* mobile: solid full-width panel, no side photo */
  .drawer__photo {
    display: none;
  }
  .drawer__panel {
    clip-path: none;
  }
  .drawer__img {
    width: min(480px, 78vw);
  } /* promo render stays (per Devon), scaled to the panel */
  .drawer__dev {
    display: none;
  } /* dev chips sit over the links here â€” desktop-only tools */
  .nav.is-menu-open .navbtn--dark {
    background: #4a4238;
  } /* WarehouseBlack on WarehouseBlack panel â€” lift it a shade */
  /* full-width panel covers the centre sooner than the desktop wedge â€” swap the
     logo to the drawer's white copy earlier */
  .nav.is-menu-open .nav__logo {
    transition-delay: 0.12s;
  }
  .drawer--pivot.is-open .drawer__bar {
    transition-delay: 0.12s;
  }
}

/* â”€â”€ Hero (SkyBlue, dark type, angled image strip along the bottom) â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
   Static banner (per client reverts, 13 Aug): no pin, no scroll-driven focus
   sequence. Every frame sits at one size in full colour and the strip drifts
   left on a CSS loop; reduced-motion holds it still. The wrapper stays because
   the Vision band still scrolls over it (see the sticky-cover pass in main.js). */
.hero-pin {
  position: relative;
}
.hero--pivot {
  background: var(--sky);
  color: var(--ink);
  display: block;
  text-align: left;
  place-items: normal; /* undo the kit hero's centering â€” Chrome applies justify-items to block children too */
  --hero-top: calc(
    var(--nav-h) + clamp(24px, 8vh, 110px) + clamp(20px, 4vh, 44px)
  ); /* + trailing clamp = headline nudged down (per Devon) */
  --hl-line: 55px; /* one headline line: 52px Ã— 1.05 */
  --hl-indent: 72.8px; /* 1.4em of the 52px headline â€” the stagger on lines 2 and 3 */
  --hero-gap: clamp(
    56px,
    13vh,
    170px
  ); /* open sky between the headline and the strip â€” the knob for how big the frames read */
  /* Frame height: from below the three headline lines down to the strip's bottom
     edge (2.5svh inset + its 24px padding). One size for every frame. */
  --card-h: max(
    200px,
    calc(
      100svh - var(--hero-top) - var(--hl-line) * 3 - var(--hero-gap) - 2.5svh -
        24px
    )
  );
}
.hero--pivot::after {
  content: none;
} /* no dark scrim â€” type is dark on sky */
.hero--pivot .hero__bg {
  z-index: 0;
  opacity: 0.7;
}
.hero__copy {
  position: relative;
  z-index: 1;
  width: 100%;
  display: flex;
  flex-direction: column; /* headline, then the tag beneath it */
  align-items: flex-start;
  gap: 1.2rem;
  padding: var(--hero-top) clamp(16px, 1.6vw, 30px) 0;
}
/* Headings are FIXED sizes (per Devon) â€” they don't scale with the viewport; only the
   mobile breakpoint switches to a smaller fixed size. */
.hero--pivot .hero__headline {
  font-family: var(--font-subhead);
  font-weight: 400;
  text-transform: uppercase;
  font-size: 52px;
  line-height: 1.05;
  letter-spacing: 0.03em;
  max-width: none;
} /* .hero--pivot prefix outranks the kit's `.hero h1` size */
.hero__headline .indent {
  display: block;
  padding-left: var(--hl-indent);
} /* the old clamp existed to clear "WORK"; with the display block gone it's the same modest stagger as .nl__headline */
.hero__pink {
  color: var(--accent);
} /* "Quinns Hill" — third headline line, same type as the second, in PivotPink */

/* Image strip: one flex track that loops leftward forever. Every frame carries its
   own left margin (the flex `gap` is deliberately not used) so each repeat of the
   three-photo set contributes exactly the same width â€” that's what lets the loop
   travel a flat -50% and land on an identical frame with no seam. */
.hero__strip {
  position: absolute;
  inset: auto 0 2.5%;
  z-index: 0;
  padding-block: 24px;
  overflow-x: clip;
  overflow-y: visible;
  cursor: grab;
  touch-action: pan-y; /* horizontal drags the strip, vertical still scrolls the page */
  user-select: none;
  -webkit-user-select: none;
} /* clip the sliding track sideways */
.hero__strip.dragging {
  cursor: grabbing;
}
.hero__track {
  display: flex;
  align-items: flex-end;
  width: max-content;
  will-change: transform;
  animation: hero-drift 60s linear infinite; /* the drift speed â€” one number, longer = slower */
}
/* -50% is exactly two of the four sets, so the frame under the left edge at the end
   of the cycle is the same photo that was there at the start. */
@keyframes hero-drift {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero__track {
    animation: none;
  }
}
/* Frames are clip-path parallelograms (not skew) so individual edges can be straight.
   The SVG clips (defined inline in index.php) round the slanted vertices; the polygon
   here is only the fallback if those defs ever go missing. */
.angle {
  position: relative;
  flex: 0 0 auto;
  margin: 0 0 0 10px; /* the gap between sets â€” on the item, not the container, so every frame counts the same */
  aspect-ratio: 930 / 545;
  height: var(--card-h);
  clip-path: polygon(10.3% 0, 100% 0, 89.7% 100%, 0 100%);
}
.angle--a {
  clip-path: url(#angle-right);
} /* straight left edge, slanted right */
.angle--b {
  clip-path: url(#angle-both);
  margin-left: -3.4vw;
} /* slanted both, tucked over a's slant whitespace */
.angle--c {
  clip-path: url(#angle-left);
  margin-left: -3.4vw;
} /* slanted left, straight right â€” meets the next set's a on two flat edges */
.angle img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 14px;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none; /* the strip owns the drag â€” no native image-drag ghost */
}
@media (max-width: 760px) {
  /* Mobile (22 Jul): flex column â€” headline block, then the drifting strip along the bottom. */
  .hero--pivot {
    --hl-line: 30px;
    --hl-indent: 0px; /* no stagger on phones — every headline line sits flush left */
    display: flex;
    flex-direction: column;
  }
  /* Big stacked headline â€” the second line bold + smaller beneath. */
  .hero--pivot .hero__headline {
    font-size: min(34px, 8.2vw);
    line-height: 1.1;
    max-width: 8em;
  }
  .hero--pivot .hero__headline .indent {
    font-size: 0.5em;
    font-weight: 700;
    padding-left: 0;
    margin-top: 0.5em;
  }
  /* Strip in flow under the headline (relative, not static: it must paint over
     the absolutely-positioned z-0 sky), pushed to the bottom of the column. */
  .hero__strip {
    position: relative;
    inset: auto;
    margin-top: auto;
    margin-bottom: 6svh;
  }
  /* Height-driven frames outgrow a narrow screen â€” stay width-driven on mobile. */
  .angle {
    width: 70vw;
    height: auto;
  }
  .angle--b,
  .angle--c {
    margin-left: -5.4vw;
  } /* deeper tuck: the slant run is a bigger share of a narrow frame */
}

/* â”€â”€ Key differentiators (#differentiators) â€” Figma 2072:12 + 2081:*. Five slides:
   offwhite slanted panel (outlined pink number, eyebrow, pink title) over a photo.
   Desktop + JS (html.fx-kd): the section pins and vertical scroll plays the slides
   horizontally. Base (mobile / no-JS): slides stack vertically, panel above photo. â”€â”€ */
.kd {
  background: var(--brand);
}
.kd-slide__img {
  width: 100%;
  height: auto;
  display: block;
}
.kd-slide:nth-of-type(3) .kd-slide__img {
  object-position: center bottom;
} /* 03: keep the ground-level action (differentiator-2) in frame, not cropped at the bottom */
.kd-slide:nth-of-type(5) .kd-slide__img {
  object-position: right center;
} /* 05: Coomera Connector label sits right of frame */
.kd-slide__panel {
  background: var(--offwhite);
  padding: clamp(24px, 4vh, 56px) var(--pad);
  display: flex;
  flex-direction: column;
}
.kd-slide__num {
  font-size: clamp(72px, 9.5vw, 190px);
  line-height: 0.95;
  font-weight: 300;
  color: transparent;
  -webkit-text-stroke: 2.5px var(--accent);
}
/* Scroll progress bar above the number â€” 5 parts, filled by --kd-p (0â€“1, set by JS
   from the pin's scroll progress). One static element outside the slides, so it never
   rides the slide transition. Only exists in the pinned desktop layout. */
.kd-progress,
.kd__heading {
  display: none;
} /* both only exist in the pinned desktop layout */
.kd-progress span {
  flex: 1;
  height: 3px;
  border-radius: 2px;
  background: rgba(74, 66, 56, 0.18);
  overflow: hidden;
}
.kd-progress span::before {
  content: "";
  display: block;
  height: 100%;
  background: var(--accent);
  transform-origin: left;
  transform: scaleX(clamp(0, var(--kd-p, 0) * 5 - var(--i), 1));
}
.kd-progress span:nth-child(1) {
  --i: 0;
}
.kd-progress span:nth-child(2) {
  --i: 1;
}
.kd-progress span:nth-child(3) {
  --i: 2;
}
.kd-progress span:nth-child(4) {
  --i: 3;
}
.kd-progress span:nth-child(5) {
  --i: 4;
}
.kd-slide__eyebrow {
  margin-top: clamp(12px, 2.5vh, 30px);
  font-size: var(--t-cta);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  max-width: 34em;
}
.kd-slide__title {
  margin-top: clamp(20px, 4vh, 48px);
  color: var(--accent);
  text-transform: uppercase;
  font-size: clamp(26px, 2.9vw, 56px);
  line-height: 1.08;
  font-weight: 700;
  max-width: 9em;
}
.kd-panelbg {
  display: none;
}
/* Slide arrows â€” only in the desktop slideshow; the phone layout is a stacked pile
   with nothing to step through, so they stay hidden there. */
.kd-arrows {
  display: none;
}
.kd-arrow {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  color: var(--brand);
  background: rgba(255, 255, 255, 0.92);
  transition:
    background 0.2s ease,
    color 0.2s ease;
}
.kd-arrow svg {
  width: 22px;
  height: 22px;
}
.kd-arrow:hover,
.kd-arrow:focus-visible {
  background: var(--accent);
  color: var(--white);
}
/* Mobile: card-stack-vertical (kit pattern) â€” each slide is a rounded card (image on
   top, 01/eyebrow/title below) that sticks under the nav at a slightly deeper offset
   than the one before, so they stack and layer as you scroll. Pure CSS, no JS. */
@media (max-width: 899px) {
  .kd {
    padding: calc(var(--nav-h) + 4px) var(--pad) 40px;
  } /* top pad = card 1's sticky offset, so it never jumps down to it */
  .kd__track {
    display: flex;
    flex-direction: column;
    gap: 24px;
  }
  /* a sticky card unpins once its bottom hits the track's bottom â€” when a later card is
     shorter, the one above runs out of range and gets pushed off before the pile finishes.
     This spacer extends every card's sticky range so 04 holds until 05 joins the pile. */
  .kd__track::after {
    content: "";
    height: 200px;
    margin-top: -24px;
  }
  .kd-slide {
    position: sticky;
    border-radius: 8px;
    overflow: hidden;
    background: var(--offwhite);
  }
  .kd-slide:nth-child(1) {
    top: calc(var(--nav-h) + 4px);
  }
  .kd-slide:nth-child(2) {
    top: calc(var(--nav-h) + 14px);
  }
  .kd-slide:nth-child(3) {
    top: calc(var(--nav-h) + 24px);
  }
  .kd-slide:nth-child(4) {
    top: calc(var(--nav-h) + 34px);
  }
  .kd-slide:nth-child(5) {
    top: calc(var(--nav-h) + 44px);
  }
}
@media (min-width: 900px) {
  /* The section used to pin for 560vh and scrub the slides off scroll; since 13 Aug it
     scrolls past like any other section and the slides play themselves (main.js). */
  html.fx-kd .kd {
    position: relative;
    height: 90vh;
    height: 90svh; /* 10% shorter than a full screen (per client, 13 Aug) */
    overflow: hidden;
    --kd-slant: clamp(
      150px,
      13vw,
      250px
    ); /* shared slant run â€” panel + photo edges stay parallel */
    --kd-gap: clamp(
      18px,
      1.4vw,
      26px
    ); /* dark seam between them (true visible width) */
    --kd-inset: clamp(20px, 1.8vw, 35px); /* photo's frame (top/right) */
    --kd-pad-b: var(--kd-inset); /* bottom frame matches the top */
    --kd-panel: min(760px, 40vw); /* narrower panel, wider photo (per Devon, 23 Jul) */
  } /* content panel width (top edge) */
  /* Step switch (per Devon): the panel is one static shape; each step's TEXT and IMAGE
     ride in with the same small left-slide. main.js only sets is-in / is-cur on the
     slide; the transitions below do the moving. Images stack â€” once a slide is in, its
     photo stays put and the next one slides over it; only the copy crossfades. */
  html.fx-kd .kd__track {
    display: contents;
  } /* slides layer against .kd itself */
  html.fx-kd .kd-slide {
    position: absolute;
    inset: 0;
  }
  html.fx-kd .kd-panelbg {
    display: block;
    position: absolute;
    inset: 12px auto 12px 12px;
    width: var(--kd-panel);
    background: var(--offwhite);
    clip-path: url(#kd-clip-panel);
    z-index: 2;
  }
  /* photo: an inset, rounded card whose slanted left edge parallels the panel's (Figma 2072:12).
     Explicit width/height calcs â€” an abs-positioned <img> never stretches between insets. */
  html.fx-kd .kd-slide__img {
    position: absolute;
    z-index: 1;
    /* 12px = the panel's left inset, so --kd-gap is the real seam width */
    top: var(--kd-inset);
    left: calc(12px + var(--kd-panel) - var(--kd-slant) + var(--kd-gap));
    width: calc(
      100% - (12px + var(--kd-panel) - var(--kd-slant) + var(--kd-gap)) -
        var(--kd-inset)
    );
    height: calc(100% - var(--kd-inset) - var(--kd-pad-b));
    object-fit: cover;
    clip-path: url(#kd-clip-photo); /* rounded slant clip from main.js */
    opacity: 0;
    transform: translateX(60px); /* rest state: waiting off to the right */
    will-change: opacity, transform;
    transition:
      opacity 0.55s ease,
      transform 0.55s ease;
  }
  html.fx-kd .kd-slide__panel {
    position: absolute;
    inset: 12px auto 12px 12px;
    width: var(--kd-panel);
    background: none;
    z-index: 3;
    pointer-events: none;
    padding: clamp(28px, 5vh, 64px) clamp(24px, 2.2vw, 48px);
    padding-right: calc(
      var(--kd-slant) - 40px
    ); /* keep copy clear of the slant wedge */
    opacity: 0;
    transform: translateX(-60px);
    transition:
      opacity 0.55s ease,
      transform 0.55s ease;
  } /* step text waits off to the left */
  /* is-in: this slide's photo has arrived and holds. is-cur: its copy is the one showing. */
  html.fx-kd .kd-slide.is-in .kd-slide__img,
  html.fx-kd .kd-slide.is-cur .kd-slide__panel {
    opacity: 1;
    transform: none;
  }
  @media (prefers-reduced-motion: reduce) {
    html.fx-kd .kd-slide__img,
    html.fx-kd .kd-slide__panel {
      transition: none;
    }
  } /* arrows still step through — the change is just instant */
  /* static heading at the panel top; progress bar + slide content drop below it */
  html.fx-kd .kd__heading span {
    display: block;
  } /* "Infrastructure" wraps to its own line */
  html.fx-kd .kd__heading {
    display: block;
    position: absolute;
    z-index: 4;
    top: calc(12px + clamp(28px, 5vh, 64px) + clamp(28px, 4vh, 48px)); /* whole block sits lower (per Devon, 23 Jul) */
    left: calc(12px + clamp(24px, 2.2vw, 48px));
    font-size: clamp(28px, 2vw, 48px); /* matches the other section headings */
    font-weight: 400;
    line-height: 1.2;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ink);
  }
  /* progress bar pinned under the heading; the number drops below it */
  html.fx-kd .kd-progress {
    display: flex;
    gap: 5px;
    position: absolute;
    z-index: 4;
    /* below the now two-line heading (~2 lines of 2vw type) + a wider gap */
    top: calc(12px + clamp(28px, 5vh, 64px) + clamp(28px, 4vh, 48px) + clamp(96px, 7vw, 150px));
    left: calc(12px + clamp(24px, 2.2vw, 48px));
    width: min(260px, calc(var(--kd-panel) - var(--kd-slant)));
  }
  html.fx-kd .kd-slide__num {
    margin-top: calc(3px + clamp(14px, 2.5vh, 30px) + clamp(28px, 4vh, 48px) + clamp(96px, 7vw, 150px));
  }
  html.fx-kd .kd-slide__title {
    margin-top: auto;
  }
  /* arrows sit in the photo's top-right corner, inside its inset frame */
  html.fx-kd .kd-arrows {
    display: flex;
    gap: 10px;
    position: absolute;
    z-index: 5;
    right: calc(var(--kd-inset) + 22px);
    top: calc(var(--kd-inset) + 22px);
  }
}

/* â”€â”€ Growth metrics (#growth) â€” Figma 2078:104 + day/night layers. Count-up stats
   over a layered scene: day sky + day building at rest; the section pins and scroll
   crossfades in the night sky and the lit-up building (opacity driven from JS),
   with a subtle parallax lift on the building as the section enters. â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.growth {
  position: relative;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh;
  background: var(--sky);
  text-align: center;
  --growth-sky: max(
    44vh,
    350px
  ); /* reserved sky for the stats â€” the building never rises into it */
  padding-top: calc(var(--section-y) * 0.6);
} /* stats sit a touch higher in the sky */
.growth__sky {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.growth__sky--night {
  opacity: 0;
}
/* day â†’ night: fades in while the section is hovered (main.js toggles .is-night).
   The night layers are the identical cutouts, so it's a straight crossfade, no halo. */
.growth__sky--night,
.growth__bld--night {
  transition: opacity 0.9s ease;
}
.growth.is-night .growth__sky--night,
.growth.is-night .growth__bld--night {
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .growth__sky--night,
  .growth__bld--night {
    transition: none;
  }
}
/* same fixed-sky-gap crop as .nl--layered: the building's TOP holds at --growth-sky;
   short screens crop its bottom out of frame instead. .3979 = image h/w (764/1920) */
.growth__bld {
  position: absolute;
  left: 0;
  bottom: min(0px, calc(100vh - var(--growth-sky) - 100vw * 0.3979));
  width: 100%;
  height: auto;
  z-index: 1;
  will-change: transform;
}
.growth__bld--night {
  opacity: 0;
}
.growth__title {
  position: relative;
  z-index: 2;
  text-align: center;
  color: var(--white);
  font-weight: 400;
  font-size: clamp(28px, 2vw, 48px); /* matches the other section headings */
  line-height: 1.2;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: clamp(20px, 3vh, 44px);
} /* per client reverts, 23 Jul */
.growth__stats {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  max-width: 1500px;
  margin-inline: auto;
  padding-inline: var(--pad);
}
.growth__num {
  font-size: clamp(52px, calc(7.8vw - 4px), 146px);
  font-weight: 600;
  line-height: 1.05;
  color: var(--white);
}
.growth__name {
  color: var(--white);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: clamp(15px, 1.15vw, 22px);
  line-height: 1.35;
  margin-top: 0.4rem;
}
.growth__copy {
  font-size: 12px;
  line-height: 1.5;
  margin: 0.8rem auto 0;
  max-width: 30em;
}
@media (max-width: 760px) {
  .growth__stats {
    grid-template-columns: 1fr;
    gap: 2.6rem;
  }
  .growth {
    padding-bottom: calc(100vw * 0.3979 + 24px);
  } /* reserve the building's height so it never overlaps the last stat */
  /* the building is never cropped on phones â€” it sits on the section bottom whole,
     eating into the sky on short screens instead (desktop keeps the fixed-sky crop) */
  .growth__bld {
    bottom: 0;
  }
  /* The stat column used to ride up from behind the building, scrubbed by the pin's
     scroll progress; that came out with the pin on 13 Aug â€” the stats now just stack. */
}

/* â”€â”€ Why Pivot Quinns Hill (#business) â€” Figma 2044:146's full-viewport WarehouseBlack
   band with a background render. Heading sits at the top over the scrim, the four
   numbered points along the bottom, render visible between them. Replaced "The Pivot
   Difference" and its pinned, scroll-rolled industry list on 13 Aug. â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.biz {
  position: relative;
  min-height: 95vh;
  min-height: 95svh; /* a touch under a full screen (per client, 13 Aug) */
  background: var(--brand);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.biz__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 75%;
} /* render is taller than 16:9 â€” crop mostly off the dark top, keep the workshop floor */
.biz::before {
  /* scrim so the heading AND the points at the bottom read over the render — the render
     still shows through the middle (Figma 2044:148, extended for the 13 Aug content) */
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    var(--brand) 10%,
    rgba(34, 29, 22, 0.35) 42%,
    rgba(34, 29, 22, 0.82) 78%,
    rgba(34, 29, 22, 0.94) 100%
  );
}
.biz__head {
  position: relative;
  z-index: 2;
  width: 100%;
  padding: calc(var(--nav-h) + clamp(16px, 2.5vh, 34px)) var(--pad) 0; /* section is sticky at top:0 â€” clear the fixed nav (per Devon, 23 Jul) */
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: clamp(22px, 3.1vw, 60px);
  line-height: 1.2;
}
.biz__title {
  font-size: 24px;
  font-weight: 400;
  color: #e8e3dc;
} /* PremiumOW */
@media (max-width: 760px) {
  .biz__head {
    padding-top: 90px;
  }
} /* heading sits lower on phones */
.biz__lead {
  margin: 0.5em auto 0;
  max-width: 24em;
  color: var(--accent);
  font-weight: 700;
  font-size: clamp(18px, 2vw, 34px);
  line-height: 1.25;
} /* the .biz__head clamp is sized for a one-word drum, far too big for a sentence */
/* Four numbered points along the bottom of the band. */
.biz__points {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1500px;
  margin: clamp(40px, 8vh, 110px) auto 0;
  padding: 0 var(--pad) clamp(72px, 12vh, 160px); /* the points were sitting too close to the section's bottom edge */
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(20px, 2.4vw, 46px);
}
.biz__num {
  font-size: clamp(38px, 3.4vw, 64px);
  line-height: 1;
  font-weight: 300;
  color: var(--white);
} /* solid white — not the outlined pink numeral the differentiator slides use */
.biz__ptitle {
  margin-top: 0.5em;
  color: var(--white);
  font-size: clamp(16px, 1.2vw, 22px);
  font-weight: 700;
  line-height: 1.2;
  text-transform: uppercase;
}
.biz__pcopy {
  margin-top: 0.75em;
  color: #e8e3dc; /* PremiumOW */
  font-size: 12px;
  line-height: 1.55;
}
@media (max-width: 1024px) {
  .biz__points {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 620px) {
  .biz__points {
    grid-template-columns: 1fr;
    gap: clamp(24px, 4vh, 40px);
  }
}

/* â”€â”€ Newest location band â€” Figma 2055:175 (top). Layers, bottom â†’ top: full image
   (its sky stays static) â†’ headline/blurb â†’ foreground copy clipped to the traced
   treeline (includes/treeline.json). JS slides the copy up from behind the trees
   and drifts the foreground up a touch; static (aligned, invisible) otherwise. â”€â”€ */
.nl {
  position: relative;
  overflow: hidden;
  background: var(--sky);
  --nl-lift: 0px;
} /* lift 0: scene bottom uncropped; the treeline fg no longer drifts (the crop was its seam-hider) */
/* Layered variant (newest location): the designer's big sky sits behind everything and
   the trucks scene starts lower, leaving open sky for the headline to rise into. */
.nl--layered {
  --nl-h: 100vh;
  height: var(--nl-h);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  --nl-sky: max(
    21vh,
    210px
  ); /* guaranteed open sky for the headline + blurb â€” the scene never rises into it */
  --nl-ratio: 0.5453;
} /* scene image h/w (1047/1920) â€” sizes the bottom crop below */
.nl--layered .nl__skybg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  z-index: 0;
}
/* scene bottom-anchored to the viewport-height section: extra sky opens above it on tall
   screens, the top of the scene's own sky crops away on short ones */
.nl--layered .nl__bg {
  position: relative;
  z-index: 2;
} /* scene's sky is transparent â€” copy (z1) tucks behind the trees, sky shows through */
.nl--layered .nl__fg {
  inset: auto 0 calc(-1 * (var(--nl-lift) + var(--nl-crop, 0px))) 0;
} /* fg copy tracks the scene's bottom edge */
/* Section is one lift shorter than the image, so the foreground copy's bottom edge is
   always clipped â€” no visible seam where the two image copies meet as it drifts up. */
.nl__bg {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: calc(-1 * (var(--nl-lift) + var(--nl-crop, 0px)));
}
.nl__copy {
  position: absolute;
  inset: 11% var(--pad) auto;
  z-index: 1; /* rests lower â€” the rise stops short of the section top */
  display: flex;
  justify-content: space-between;
  gap: 2rem;
  will-change: transform;
}
@media (min-width: 761px) {
  #newest-location .nl__copy {
    top: calc(var(--nl-sky) - 16.5vh);
  } /* settles the same distance above the scene top as before the sky grew */
  /* Taller band + more open sky (per Devon, 22 Jul). The max() grows the section to fit
     the FULL scene under the sky gap â€” never bottom-crops it (per Devon, 22 Jul).
     Sky extended further up for the static "Pivot's Vision" intro (per Devon, 23 Jul);
     .nl__copy's top holds the rising heading at its old spot relative to the scene. */
  /* Vision sequence: the band covers the hero with a run of open sky holding only
     "Pivot's Vision". The sky is sticky, so further scrolling slides the vision copy up
     and away over a stationary sky; only then does the scene (and the rising heading)
     arrive from below. The sky ran nearly a full screen (95svh) up to 13 Aug â€” halved
     on the client's note that the section was too big. */
  #newest-location {
    --nl-sky: max(50svh, 380px); /* open sky the vision sits in, before the scene arrives â€” the knob for this band's length */
    /* Capped at ~one screen (per client, 13 Aug — the render was way too big). This used
       to be a max(), which grew the band to fit the WHOLE scene and pushed it past 160vh
       on wide screens. min() instead lets .nl--layered's --nl-mb crop the scene's bottom. */
    --nl-h: min(calc(var(--nl-sky) + 100vw * var(--nl-ratio)), 108svh);
    background: #eaeaea; /* matches the sky render's lower tone â€” no blue peeking through (per Devon, 23 Jul) */
  }
  /* sky: the base absolute full-section cover (sticky can't work under the section's
     overflow:hidden) â€” one continuous gradient behind both the vision and the scene */
  #newest-location .nl__vision {
    position: absolute;
    inset: calc(var(--nl-sky) / 2 - 2svh) var(--pad) auto;
    transform: translateY(-50%);
    z-index: 1;
    text-align: center;
  } /* centred in the sky band, nudged just above true centre; scrolls up and out as the scene rises */
  #newest-location .nl__vision .nl__headline {
    font-size: 24px;
    font-weight: 700;
    line-height: 1.15;
  } /* matches the Quinns Hill card title (per Devon, 23 Jul) */
  #newest-location .nl__vision .nl__blurb {
    margin: 1.2em auto 0;
    max-width: 52em;
    font-size: 12px;
    line-height: 1.5;
    text-transform: none;
    letter-spacing: normal;
  } /* 12px body copy, sentence case (per Devon, 23 Jul) */
}
.nl__headline {
  font-size: 24px;
  line-height: 1.25;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.nl__headline .indent {
  display: block;
  font-weight: 700;
  padding-left: 1.4em;
}
.nl__blurb {
  max-width: 36em;
  font-size: 12px;
  line-height: 1.55;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
@media (min-width: 761px) {
  .nl__headline {
    font-size: clamp(28px, 2vw, 48px);
  } /* desktop: 28px base, scales up on bigger screens (per Devon, 22 Jul) */
  .nl__blurb {
    margin-top: calc(clamp(28px, 2vw, 48px) * 1.25);
  } /* blurb top aligns with the headline's second line */
}
/* Fixed sky gap: the scene is bottom-anchored, but the negative margin crops its
   bottom by exactly what's needed so its TOP never rises above --nl-sky. Tall
   screens: margin hits 0 and the full scene shows. Short/wide screens: more and
   more of the scene's bottom crops away, the sky gap stays constant. */
@media (min-width: 761px) {
  /* ponytail: 100vw includes the scrollbar â€” a few px of extra crop, invisible */
  .nl--layered {
    --nl-mb: min(
      0px,
      calc(var(--nl-h) - var(--nl-sky) - 100vw * var(--nl-ratio))
    );
  }
  .nl--layered .nl__bg {
    margin-bottom: var(--nl-mb);
  }
  .nl--layered .nl__fg {
    inset: auto 0 var(--nl-mb) 0;
  } /* treeline copy stays aligned with the cropped scene */
}
.nl__fg {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  will-change: transform;
}
.nl__fg img {
  width: 100%;
  height: auto;
}
/* darken the image bottom so the white caption stays readable */
.nl::after {
  content: "";
  position: absolute;
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  height: 38%;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.55));
}
.nl__caption {
  position: absolute;
  z-index: 3;
  bottom: 5.5%;
  left: 50%;
  font-weight: 600;
  transform: translateX(-50%);
  width: min(600px, 84%);
  margin: 0;
  text-align: center;
  color: var(--white);
  font-size: 12px;
  line-height: 1.5;
}
/* Quinns Hill's caption carries the key detail (address, unit count, frontage), so it
   runs 5px up on the other bands' captions (per client, 13 Aug). The id outranks the
   phone override below, so it holds at both breakpoints. */
/* #newest-location's caption moved out of the band on 13 Aug — it's .qh__lead now, in
   the light section below. Its readability scrim goes with it; nothing sits there. */
#newest-location.nl::after {
  content: none;
}
@media (max-width: 760px) {
  .nl__headline {
    font-size: 20px;
  } /* sky headings smaller on phones (per Devon, 23 Jul) */
  /* Pivot's Vision on phones: static block at the top of a taller skybox; the rising
     copy and the scene sit below it (per Devon, 23 Jul) */
  .nl__vision {
    position: absolute;
    inset: max(8vw, 40px) var(--pad) auto;
    z-index: 1;
    text-align: center;
  }
  .nl__vision .nl__headline {
    font-weight: 700;
    line-height: 1.15;
  }
  .nl__vision .nl__blurb {
    margin: 1em auto 0;
    font-size: 12px;
    line-height: 1.5;
    text-transform: none;
    letter-spacing: normal;
  }
  #newest-location .nl__copy {
    top: calc(max(8vw, 40px) + 200px);
  } /* rising copy drops below the vision block */
  /* phones (design 22 Jul): every band gets a tall skybox â€” heading + blurb
     rest together IN the sky and RISE from behind the scene on scroll, like desktop.
     The copy is an absolute overlay (z1, under the z2 scene whose sky is transparent) â€”
     the JS rise targets the whole copy block because it's absolute. Caption stays below. */
  .nl--layered {
    height: auto;
    display: block;
    padding-top: max(62vw, 250px);
  } /* skybox tall enough for heading + blurb */
  .nl__bg {
    margin-bottom: 0;
  } /* no fixed-sky crop in the stacked layout */
  /* the scene zooms past the viewport edges (sides crop away) so it runs taller */
  .nl--layered .nl__bg {
    width: 170vw;
    max-width: none;
    margin-left: -35vw;
  }
  .nl--layered .nl__copy {
    position: absolute;
    inset: max(8vw, 40px) var(--pad) auto;
    flex-direction: column;
    gap: 1rem;
  }
  .nl__headline .indent {
    display: inline;
    padding-left: 0;
  } /* wraps as one sentence */
  .nl__headline .indent::before {
    content: " ";
  } /* the blockâ†’inline collapse loses the word gap ("locationIn") â€” restore it */
  #newest-location .nl__headline .indent {
    font-weight: 400;
  } /* only the <b> "logistics position" is bold */
  .nl__fg {
    display: none;
  } /* no room for the treeline drift â€” plain image */
  /* all three bands (per Devon): the lower paragraph overlays the BOTTOM of the image,
     white over the section's darkening gradient so it stays readable */
  .nl__caption {
    position: absolute;
    z-index: 3;
    bottom: 3%;
    left: 50%;
    transform: translateX(-50%);
    width: 92%;
    padding: 0;
    color: var(--white);
  }
  /* community: headline breaks before "Business community" */
  .nl--comm .nl__headline .indent {
    display: block;
  }
  .nl--comm .nl__copy {
    top: max(15vw, 68px);
  } /* community: copy rests a bit lower in the skybox */
  #newest-location {
    padding-top: calc(max(74vw, 300px) + 200px);
  } /* taller skybox â€” vision block + heading + blurb all fit in the sky */
}

/* Scroll reveal: fades in when the IntersectionObserver adds .in (main.js). Opacity
   only â€” the band captions carry a translateX(-50%), so no transform here. */
html.fx-on .fade-up {
  opacity: 0;
  transition: opacity 0.8s ease;
}
html.fx-on .fade-up.in {
  opacity: 1;
}

/* Every top-level block is positioned so paint order = DOM order: a section pinned
   under the cover effect (main.js) stays behind everything after it â€” without
   negative z-index, which would put its buttons behind <main> and eat their clicks. */
main > * {
  position: relative;
}

/* Business community band (#community, Figma 2097:96) â€” same layout as the newest-location
   band, no treeline effect. (The Convenience band shared this flat variant until it was
   removed on 13 Aug.) */
.nl--comm {
  --nl-lift: 0px; /* no foreground layer â†’ no seam crop */
  --nl-ratio: 0.5708; /* 1096/1920 */
}
/* community: nudge the headline right so it rests in open sky (desktop only â€”
   the stacked mobile copy is left-aligned like the other bands) */
@media (min-width: 761px) {
  /* Community: the band holds to one screen so the heading, blurb and caption are all
     in frame at once (per client, 13 Aug). This was a max() that grew the section to fit
     the WHOLE scene and ran to ~145vh on a wide screen, pushing the caption below the
     fold; min() instead lets .nl--layered's --nl-mb crop the scene's bottom tarmac. */
  .nl--comm {
    --nl-h: min(calc(var(--nl-sky) + 100vw * var(--nl-ratio)), 100svh);
  }
  .nl--comm .nl__caption {
    bottom: 5%;
  }
  .nl--comm .nl__headline {
    margin-left: 8vw;
  }
  .nl__blurb {
    margin-right: 6vw;
  } /* all sky bands: paragraph pulled in from the right edge (per Devon, 23 Jul) */
}

/* The Dual market entry (#own-or-invest) panel pair and the Why act now
   (#why-act-now) land-supply statistic band were both removed on 13 Aug per
   the client; their styles came out with them. */

/* â”€â”€ Investment snapshot (#investments) â€” Figma 2091:51. Slanted photo cards with
   offwhite caption bars over their bottom edge; infinite drag carousel (main.js
   dragCarousel, same mechanics as the Quinns Hill dev cards). Cards tuck over each
   other's slant whitespace. JS-off: duplicate set hidden, native scroll. â”€â”€ */
.inv {
  background: var(--sky);
  height: 100vh;
  height: 100svh;
  min-height: max-content;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: clamp(20px, 4svh, 48px) 0;
  /* card width: capped by design size, viewport width, AND viewport height â€” the
     100svh section must hold title + intro + cards, so the card shrinks on short
     screens (height = width / 1.709; ~300px is the non-card chrome budget). */
  --inv-cw: min(820px, 78vw, calc((100svh - 430px) * 2.12)); /* wider, flatter cards (per Devon, 23 Jul) */
} /* 430: title + intro + the caption bar now BELOW the image */
.inv__title {
  text-align: center;
  font-weight: 700;
  font-size: 24px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.inv__intro {
  margin: clamp(10px, 1.5svh, 24px) auto 0;
  padding: 0 var(--pad);
  max-width: 72em; /* wider measure (per Devon, 22 Jul) */
  text-align: center;
  font-size: 12px;
  line-height: 1.35;
  letter-spacing: 0.02em;
}
.inv-carousel {
  margin-top: clamp(44px, 9svh, 120px); /* cards sit lower (per Devon, 22 Jul) */
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
} /* dragging must never text-select the caps */
.inv-carousel.dragging {
  cursor: grabbing;
}
html:not(.fx-carousel) .inv-carousel {
  overflow-x: auto;
}
html:not(.fx-carousel) .inv-card[aria-hidden] {
  display: none;
}
.inv__row {
  display: flex;
  width: max-content;
  list-style: none;
  margin: 0;
  padding: 0;
}
.inv__row img {
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
/* Card geometry decoded from the Figma frame (933Ã—546 cards @1920): the slant edge
   runs 140.3px over the 546px height (14.42Â°, tan .257) â€” right edge .9974â†’.847 of
   the width, left edge .153â†’.0026 on the mirrored cards. Odd cards are straight-left/
   slanted-right (--sr), even cards slanted-left/straight-right (--sl). Slant pairs
   interlock (âˆ’127px, an 18px sky gap runs along the two parallel edges); straight
   pairs sit 20px apart. All junction lengths scale with the card (--inv-cw). */
.inv-card {
  position: relative;
  flex: 0 0 var(--inv-cw);
  display: flex;
  flex-direction: column;
}
.inv-card--sr {
  margin-right: calc(var(--inv-cw) * -0.1361);
} /* next card's slant interlocks (127/933) */
.inv-card--sl {
  margin-right: calc(var(--inv-cw) * 0.0214);
} /* straight junction gap (20/933) */
/* Clips are built by qhClip in main.js (rounded corners: 12px slanted / 5px square,
   like the other slant shapes). No JS â†’ no clip â†’ plain rectangles, as elsewhere. */
.inv-card img {
  display: block;
  width: 100%;
  aspect-ratio: 933/440; /* flatter than the Figma 933/546 (per Devon, 22 Jul) */
  object-fit: cover;
}
.inv-card--sr img {
  clip-path: url(#inv-clip-sr);
}
.inv-card--sl img {
  clip-path: url(#inv-clip-sl);
}
/* Caption bar: a skewX(-14.42deg) background keeps the image's exact slant angle at
   any caption height (a fractional clip like the image's polygon can't â€” the angle
   would change with the bar's own aspect). The skewed ::before supplies the slanted
   end, collinear with the image's clipped edge; the square ::after covers the skew
   on the straight end. z-index 0 keeps both pseudos above the image. */
.inv-card__cap {
  position: relative;
  z-index: 0;
  flex: 1; /* bars stretch to one shared bottom line â€” every card the same block */
  margin-top: -6px; /* tucks under the image's bottom edge â€” covers the clip's rounded corners, no seam */
  padding: clamp(12px, 1.3vw, 24px) calc(var(--inv-cw) * 0.064)
    clamp(14px, 1.5vw, 28px);
}
.inv-card__cap::before,
.inv-card__cap::after {
  content: "";
  position: absolute;
  z-index: -1;
  background: var(--offwhite);
  border-radius: 0 0 4px 4px;
} /* top corners square â€” seamless with the image */
/* sr: the slanted end CONTINUES the image's clipped right edge â€” the skew hinges on the
   TOP edge (junction line), so the two stay collinear whatever the caption's height.
   ::before starts at 20% so its skewed bottom-left can never poke past the card edge;
   the square ::after supplies the straight left half. */
.inv-card--sr .inv-card__cap {
  padding-right: calc(var(--inv-cw) * 0.23);
} /* keeps text clear of the slant */
.inv-card--sr .inv-card__cap::before {
  inset: 0 calc(15.3% - 1.6px) 0 20%; /* +1.6px: the bar's top 6px hide under the image, the skew eats .257Ã—6px by the visible seam */
  transform: skewX(-14.42deg);
  transform-origin: top left;
}
.inv-card--sr .inv-card__cap::after {
  inset: 0 50% 0 0;
}
/* sl: left end slanted like its image â€” the skew hinges on the top edge at the image's
   bottom-left corner, so the edge continues the card seam, overhanging into the
   interlock gap (which is open sky, 18px clear of the previous card's slant). */
.inv-card--sl .inv-card__cap::before {
  inset: 0 0 0 calc(0.26% + 1.6px);
  transform: skewX(-14.42deg);
  transform-origin: top left;
}
.inv-card--sl .inv-card__cap::after {
  inset: 0 0 0 40%;
} /* squares off the straight right end (the skew tilts ::before's right edge) */
.inv-card__cap h3 {
  font-size: clamp(13px, 1.15vw, 22px);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.inv-card__cap p {
  margin-top: 0.35em;
  font-size: 12px;
  line-height: 1.35;
}
@media (max-width: 760px) {
  /* phones: content-height section â€” the 100svh box leaves big empty bands */
  .inv {
    height: auto;
    min-height: 0;
    padding: 72px 0 88px;
  } /* taller band (per Devon, 22 Jul) */
  .inv__intro {
    margin-top: 30px;
  } /* more air under the heading */
  .inv-carousel {
    margin-top: 60px;
  } /* more air between the intro and the cards */
}

/* â”€â”€ Pre-footer image band â€” Figma 2200:6: plain full-bleed photo, no copy. â”€â”€ */
.prefooter img {
  display: block;
  width: 100%;
  height: auto;
}

/* â”€â”€ Connect with us (#contact) â€” Figma 2097:169. Pink wedge + offwhite panel over the
   dark band; the Markt tablet cutout swivels toward the cursor (data-tilt, main.js).
   Underline form fields; consent + submit share the bottom row. â”€â”€ */
.cf {
  position: relative;
  overflow: hidden;
  background: var(--brand);
  --cf-slant: clamp(
    120px,
    10.5vw,
    200px
  ); /* shared px run â†’ the two inner edges stay parallel */
  --cf-gap: clamp(18px, 1.8vw, 36px);
} /* dark seam between the shapes */
.cf__pink {
  position: absolute;
  inset: 2% auto 2% 0.9%;
  width: 37%;
  background: var(--accent);
  border-radius: 5px;
  clip-path: url(#cf-clip-pink);
} /* flat left; rounded slant clip computed per box size in main.js */
.cf__panel {
  position: absolute;
  inset: 3.5% 1.5% 3.5% calc(37.9% - var(--cf-slant) + var(--cf-gap)); /* slightly shorter than the pink wedge (2%) */
  background: var(--offwhite);
  border-radius: 5px;
  clip-path: url(#cf-clip-panel);
} /* flat right; rounded slant clip from main.js */
.cf__inner {
  position: relative;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  min-height: 100vh;
  align-items: center;
  gap: clamp(24px, 4vw, 80px);
  /* vertical rhythm in vh so the section compresses to one viewport */
  padding: clamp(30px, 6.5vh, 80px) clamp(24px, 8vw, 170px)
    clamp(30px, 6.5vh, 80px) clamp(16px, 2.5vw, 50px);
}
.cf__stage {
  perspective: 1200px;
}
.cf__ipad {
  display: block;
  width: 100%;
  max-height: 82vh;
  height: auto;
  object-fit: contain;
  will-change: transform;
}
.cf__title {
  text-align: left; /* in line with the form + paragraph (Figma revision, 23 Jul) */
  font-weight: 400;
  font-size: 24px;
  line-height: 1.25;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.cf__title strong {
  font-weight: 800;
} /* CONNECT bold, "with us" regular */
@media (min-width: 761px) {
  .cf__title {
    font-size: clamp(28px, 2vw, 48px);
  } /* desktop bump, matches the skybox headings (per Devon, 22 Jul) */
}
/* contact pitch copy (per client reverts, 23 Jul â€” replaced the numbered steps) */
.cf__pitch {
  margin-top: clamp(16px, 3.5vh, 44px);
  display: grid;
  gap: clamp(10px, 1.8vh, 20px);
}
.cf__pitch p {
  max-width: 46em;
  font-size: 12px;
  line-height: 1.5;
  letter-spacing: 0.02em;
} /* sentence case, aligned with the form (Figma revision, 23 Jul) */
.cf__login a {
  color: var(--accent);
  text-decoration: underline;
}
.cf__contact-head {
  margin-top: clamp(24px, 4.5vh, 52px);
  font-size: 24px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.cf__direct {
  margin-top: 0.9em;
  font-size: 12px;
  letter-spacing: 0.02em;
}
.cf__direct a {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.cf__direct a:hover,
.cf__direct a:focus-visible {
  color: var(--accent);
}
.cf__form {
  margin-top: clamp(16px, 4vh, 52px);
  display: grid;
  gap: clamp(10px, 1.7vh, 20px);
}
.cf__form input:not([type="checkbox"]),
.cf__form select,
.cf__form textarea {
  width: 100%;
  background: none;
  border: 0;
  border-radius: 0;
  border-bottom: 1px solid var(--ink);
  padding: 0 0 clamp(6px, 0.5vw, 10px);
  font: inherit;
  font-size: clamp(13px, 1.05vw, 20px);
  letter-spacing: 0.02em;
  color: var(--ink);
}
.cf__form textarea {
  resize: vertical;
}
.cf__form select {
  appearance: none;
  cursor: pointer;
  font-size: clamp(12px, 0.85vw, 16px); /* smaller than the inputs (per Devon, 22 Jul) */
  text-transform: none; /* keep typed casing so unit sizes read "200mÂ²" not "200MÂ²" */
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 8"><path d="M1 1l5 5 5-5" fill="none" stroke="%23221d16" stroke-width="1.5"/></svg>')
    no-repeat right 2px top 40% / 12px;
}
.cf__form select:invalid {
  color: rgba(34, 29, 22, 0.3);
} /* "Interested in" placeholder option â€” matches the input placeholders */
.cf__form input::placeholder {
  color: var(--ink);
  opacity: 0.3;
  text-transform: uppercase;
}
.cf__form input:not([type="checkbox"]):focus,
.cf__form select:focus {
  outline: none;
  border-bottom-color: var(--accent);
}
/* invalid fields: red underline, faint red wash and an ! badge on the right */
.cf__form input.is-invalid:not([type="checkbox"]),
.cf__form select.is-invalid {
  border-bottom-color: #b0261a;
  background: rgba(176, 38, 26, 0.06)
    url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><circle cx="10" cy="10" r="9" fill="%23b0261a"/><rect x="9" y="4.5" width="2" height="7" rx="1" fill="white"/><circle cx="10" cy="14.7" r="1.3" fill="white"/></svg>')
    no-repeat right 0.5em center / 16px;
}
.cf__consent.is-invalid {
  color: #b0261a;
}
.cf__consent.is-invalid a {
  color: inherit;
}
.cf__consent.is-invalid input {
  outline: 2px solid #b0261a;
  outline-offset: 1px;
}
.cf__foot {
  margin-top: clamp(8px, 0.9vw, 18px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 12px;
}
.cf__consent {
  display: flex;
  align-items: center;
  gap: 0.75em;
  cursor: pointer;
}
.cf__consent input {
  width: clamp(18px, 1.55vw, 30px);
  height: clamp(18px, 1.55vw, 30px);
  appearance: none;
  border: 1px solid var(--ink);
  cursor: pointer;
  flex: none;
}
.cf__consent input:checked {
  background: var(--accent);
  border-color: var(--accent);
}
.cf__consent input {
  display: grid;
  place-content: center;
}
.cf__consent input:checked::before {
  content: "\d7";
  color: var(--white, #fff); /* white Ã— */
  font-size: 1.3em;
  line-height: 1;
}
.cf__submit {
  background: none;
  border: 0;
  cursor: pointer;
  font: inherit;
  color: var(--ink);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: clamp(13px, 1.05vw, 20px);
  opacity: 0.55;
}
.cf__submit:hover {
  opacity: 1;
  color: var(--accent);
}
@media (max-width: 860px) {
  /* stacked: tablet above, panel behind the form */
  .cf__inner {
    grid-template-columns: 1fr;
    padding: clamp(28px, 6vw, 48px) var(--pad);
  }
  /* pink full-width on top (slanted bottom), panel below (matching slanted top) â€”
     the vertical clip pair comes from main.js; panel tucks up into the slant wedge */
  .cf__pink {
    inset: 1.5% 2% auto;
    width: auto;
    height: 40%;
  } /* height/top refined per content in main.js */
  .cf__panel {
    inset: calc(41.5% + 10px - 13.4vw) 2% 1.5%;
  }
  .cf__title {
    text-align: left;
  }
  .cf__pitch {
    margin-top: calc(13.4vw + 40px);
  } /* clears the slanted seam band below the title */
}

/* â”€â”€ Quinns Hill (#opportunities) â€” Figma 2055:175. Offwhite card (title/price, CTA,
   pink-square feature list) beside the loading-dock photo, whose left edge takes
   the brand slant (reuses the hero's #angle-left rounded clip). Street-view row
   below is placeholder imagery. â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.section--qh {
  background: var(--sky);
  padding-top: clamp(30px, 3.6vw, 60px); /* tighter than the standard --section-y: the lead paragraph sat too far below the band above (per client, 13 Aug) */
  padding-bottom: clamp(16px, 2.2vw, 44px); /* slimmer tail: the section pins bottom-to-viewport
    during the cover transition, so LESS space below the carousel = the heading and cards
    rest LOWER on screen (per Devon, 23 Jul) */
}
/* Lead paragraph above the Quinns Hill card. Was white type overlaid on the render in
   the band above until 13 Aug; now black on this section's own sky background, with its
   own air above and below (per client). */
.qh__lead {
  margin: 0 auto clamp(52px, 6.5vw, 108px);
  max-width: 46em;
  text-align: center;
  color: var(--ink);
  font-size: 17px;
  font-weight: 500; /* one step up from body regular — Montserrat Medium is a real cut */
  line-height: 1.5;
}
.section--qh .wrap {
  max-width: 1800px;
} /* near full-bleed like the Figma frame (30px gutters at 1920) */
.qh {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 10px;
  align-items: stretch; /* white card slightly wider than the photo */
  max-width: 1320px; /* wider so the title + price each hold one line (per Devon, 23 Jul) */
  margin-inline: auto; /* card + photo brought in; carousel below stays full section width */
  --qh-slant: 90px; /* fallback only â€” main.js overwrites it to match the contact wedge's angle */
  --qh-seam: 18px; /* slightly tighter cardâ†”photo gap (per Devon, 23 Jul) */
} /* visible diagonal gap between card and photo */
.qh__card {
  background: var(--offwhite);
  border-radius: 5px;
  padding: clamp(28px, 3.5vw, 54px);
  clip-path: url(#qh-clip-card);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
} /* rounded slant clip, computed per box size in main.js */
.qh__card > .navbtn {
  margin-top: auto;
  clip-path: url(#qh-clip-btn); /* straight left, slanted right, rounded corners (per Devon, 23 Jul) */
  border-radius: 6px; /* no-JS fallback: plain rounded chip like the carousel CTAs */
  padding: 0 clamp(18px, 1.5vw, 28px) 0 clamp(13px, 1.1vw, 20px); /* text nudged a touch left of centre, clear of the right slant */
} /* CTA pinned to the panel bottom (per Devon, 23 Jul) */
.qh__top {
  align-self: stretch;
} /* title with the price stacked beneath it (per Devon, 23 Jul) */
.qh__title {
  font-size: 24px;
  line-height: 1.15;
  text-transform: uppercase;
}
.qh__price {
  margin-top: 0.35em;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  text-transform: uppercase;
} /* own line under the title, all caps (per Devon, 23 Jul) */
.qh__intro {
  margin-top: clamp(24px, 3vw, 46px);
  font-size: 12px;
  max-width: 38em;
  padding-right: clamp(16px, 4%, 40px); /* copy never reaches the panel's edge */
}
.qh__intro + .qh__intro {
  margin-top: clamp(10px, 1.2vw, 18px);
} /* tighter gap between the two intro paragraphs (per Devon, 23 Jul) */
.qh__list {
  list-style: none;
  padding: 0;
  margin-top: clamp(12px, 1.5vw, 22px); /* tighter under the intro (per Devon, 23 Jul) */
  margin-bottom: clamp(20px, 2.6vw, 40px); /* min gap above the bottom-pinned CTA */
  display: grid;
  gap: 14px;
}
.qh__list li {
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  gap: 12px;
}
.qh__list li::before {
  content: "";
  width: 8px;
  height: 8px;
  background: var(--accent);
  flex: none;
}
/* Photo's left edge slants with the same pixel run as the card's right edge, so the
   two are always parallel; the pull-left leaves exactly --qh-seam of sky between them. */
.qh__photo {
  clip-path: url(#qh-clip-photo);
  border-radius: 5px;
  overflow: hidden;
  margin-left: calc(var(--qh-seam) - var(--qh-slant) - 10px);
} /* 10px = grid gap */
.qh__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* development cards: 3-up infinite drag carousel (drag/swipe + momentum, seamless
   loop â€” marquee mechanics without the auto-drift). Card width --cw is set by JS;
   spacing is margin (not flex gap) so half the track is exactly one card set.
   JS-off: the duplicate set stays hidden and the row scrolls natively. */
.qh-carousel__heading {
  margin-top: clamp(72px, 8vw, 140px);
  margin-bottom: clamp(40px, 4.5vw, 84px); /* extra air under the heading, on top of the carousel's own gap */
  text-align: center;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  text-transform: uppercase;
} /* same treatment as the Quinns Hill card title (per Devon, 23 Jul) */
.qh-carousel__blurb {
  margin: calc(-1 * clamp(16px, 1.8vw, 34px)) auto 0; /* sits a touch lower under the heading (per Devon, 23 Jul) */
  max-width: 44em;
  text-align: center;
  font-size: 12px;
  line-height: 1.5;
} /* body copy â€” sentence case (per Devon, 23 Jul) */
.qh-carousel {
  margin-top: clamp(64px, 7vw, 130px); /* more air between the blurb and the cards (per Devon, 23 Jul) */
  margin-bottom: clamp(48px, 5vw, 100px); /* more air under the carousel (per Devon, 23 Jul) */
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none; /* dragging must never text-select the cards */
  margin-inline: calc(50% - 50vw);
} /* break out of the wrap: full viewport width */
.qh-carousel.dragging {
  cursor: grabbing;
}
html:not(.fx-carousel) .qh-carousel {
  overflow-x: auto;
}
html:not(.fx-carousel) .qh-site--dup {
  display: none;
}
.qh-track {
  display: flex;
  width: max-content;
}
.qh-track .qh-site {
  width: var(--cw, 380px);
  flex: none;
  margin-right: clamp(8px, 0.9vw, 14px);
}
.qh-track img {
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
.qh-site__media {
  position: relative;
  border-radius: 5px;
  overflow: hidden;
}
/* hero-style alternating slants around the loop: --ar = right edge slanted (left straight),
   --al = left edge slanted (right straight). Fixed 48px run = every diagonal is parallel;
   --al cards tuck left by the same 48px so slanted seams read as wide as straight ones. */
/* rounded-corner slant clips built in main.js (like the qh card/photo above);
   no JS â†’ url() unresolved â†’ plain rounded rectangles */
.qh-site--ar .qh-site__media {
  clip-path: url(#qh-clip-site-ar);
}
.qh-site--al .qh-site__media {
  clip-path: url(#qh-clip-site-al);
}
/* flat both sides â€” no slant (used for the "coming soon" Coomera Connector card) */
.qh-site--flat .qh-site__media {
  clip-path: none;
}
.qh-site--al {
  margin-left: calc(-1 * var(--qh-cs, 48px));
}
.qh-site--al .qh-site__status {
  left: calc(var(--qh-cs, 48px) + 14px);
} /* clear of the clipped top-left wedge */
.qh-site__media img {
  width: 100%;
  height: auto;
  aspect-ratio: 620 / 349;
  object-fit: cover;
}
.qh-site__status {
  position: absolute;
  top: 16px;
  left: 18px;
  font-size: var(--t-cta);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand);
  max-width: calc(100% - 245px);
  line-height: 1.35;
} /* wraps before the JOIN WAITING LIST chip (245px: widest chip + both insets) */
.qh-site__cta {
  position: absolute;
  top: 11px;
  right: 14px;
  /* transparent with a slight outline (per Devon, 23 Jul). The clip would cut a CSS
     border off, so main.js paints the outline as an SVG background stroked along the
     same rounded slant path; the CSS border here is only the pre-JS/no-JS fallback. */
  background: transparent no-repeat;
  border: 1px solid var(--brand);
  clip-path: url(#qh-clip-cta-al);
  border-radius: 6px;
  padding: 0.65em 1em 0.65em calc(1em + 10px);
  font-size: var(--t-cta);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand);
  transition:
    background 0.2s var(--ease),
    color 0.2s var(--ease);
}
/* --ar cards (Transport Street, Vantage): the image's RIGHT edge is the slanted one,
   so their chip mounts flush on it â€” straight left edge, slanted right (per Devon, 22 Jul) */
.qh-site--ar .qh-site__cta {
  right: 16px; /* parallel slants â†’ constant offset = an even sky gap along the seam */
  clip-path: url(#qh-clip-cta-ar);
  padding: 0.65em calc(1em + 3px) 0.65em calc(1em + 7px); /* text nudged right (per Devon, 23 Jul) */
  border-radius: 6px 0 0 6px;
}
.qh-site__cta:hover,
.qh-site__cta:focus-visible {
  background: var(--accent);
  background-image: none !important; /* beats the inline SVG outline â€” border gone on hover */
  border-color: transparent;
  color: var(--offwhite);
}
.qh-site__name {
  margin-top: 0.9rem;
  text-align: center;
  font-size: 15px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.qh-site__units {
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  max-width: none;
}
@media (max-width: 860px) {
  .qh {
    grid-template-columns: 1fr;
  }
  .qh__top {
    flex-direction: column;
  }
  /* stacked: the seam turns horizontal â€” card keeps a slanted bottom edge, photo a
     matching slanted top edge (clips swap to the vertical variant in main.js) */
  .qh__card,
  .qh__photo {
    border-radius: 5px;
    overflow: hidden;
    margin-left: 0;
  }
  .qh__card {
    padding-bottom: calc(28px + 13.4vw);
  } /* keep the list clear of the clipped bottom wedge */
  .qh__photo {
    margin-top: calc(0px - 13.4vw);
  } /* tuck into the slant wedge â€” hairline seam */
}

/* â”€â”€ Locations map â€” Figma 2051:158. Bare map background (2051:161) with everything
   dynamic on top: heading, POI photo cards + wordmarks and route lines are %-positioned
   from includes/map-points.json (authored with _point-mapper.html). â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
/* Freight-routes intro above the map (per client, 13 Aug). Same paper tone as the map
   section so the two read as one block, which is why the padding is generous above and
   tight below. Type matches the "Explore our other locations" heading + blurb pair. */
.mapintro {
  padding-block: clamp(72px, 8vw, 140px) clamp(28px, 3vw, 52px);
  background: #f1f1f1;
}
.mapintro__title {
  margin: 0;
  text-align: center;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.15;
  text-transform: uppercase;
}
.mapintro__blurb {
  margin: 1.2em auto 0;
  max-width: 44em;
  text-align: center;
  font-size: 12px;
  line-height: 1.5;
}
.section--map {
  padding-block: 0;
  background: #f1f1f1; /* matches the map render's paper tone â€” the centered map blends in */
  overflow-x: clip;
} /* the mobile zoomed map is 160vw wide â€” the section swallows the overhang so the page never scrolls sideways */
.map {
  position: relative;
  margin: 0;
  overflow: clip; /* clips the heading's rise to the map edge; clip (not hidden) so .map is no scroll container â€” that would hijack the heading's view timeline */
  view-timeline: --map-view block;
}
@media (min-width: 761px) {
  /* map is always 100svh tall (16:9 â†’ width = 1.778 Ã— height), centered; on viewports
     too narrow for that width it caps at 96% and the height follows the ratio down */
  .map {
    width: min(calc(100svh * 16 / 9), 96%);
    margin-inline: auto;
  }
}
.map__img {
  width: 100%;
  height: auto;
}
/* Heading in the map's open bottom-right. The homepage renders the map without one (its
   .mapintro section above carries the heading instead); the landing page still uses it. */
.map__heading {
  position: absolute;
  right: 5.4%;
  bottom: 4%;
  z-index: 2;
  margin: 0;
  text-align: right;
  text-transform: uppercase;
  color: var(--brand);
  font-size: clamp(32px, 2.6vw, 56px); /* big (per Devon, 23 Jul) */
  line-height: 1.22;
}
.map__heading span {
  display: block;
  font-weight: 500;
}
.map__heading strong {
  display: block;
  font-weight: 800;
}
/* scroll-linked rise: the heading climbs from the map's bottom edge to its resting
   spot as it scrolls into view (linear, reversible â€” native scroll-driven animation;
   ponytail: no-support/reduced-motion browsers just show it settled) */
@supports (animation-timeline: view()) {
  /* driven by the MAP's view timeline: rise runs while the map scrolls in and settles
     exactly at entry 100% â€” the moment the map fully fills the screen */
  html.fx-on .map__heading {
    animation: map-head-rise linear both;
    animation-timeline: --map-view;
    animation-range: entry 0% entry 100%;
  }
}
@keyframes map-head-rise {
  from {
    transform: translateY(clamp(120px, 22vh, 260px));
  }
}
/* POI marker â€” matches the Figma card design: square photo (rounded corners baked into
   the export) with a pink dot on its bottom-right corner, wordmark under it */
.map__poi {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4vw;
  width: clamp(48px, 4.8vw, 92px);
}
.map__poi-card {
  position: relative;
  width: 100%;
  margin-bottom: 12%;
} /* room for the tip below the image */
/* --flip: logo + name sit ABOVE the photo (used by Yatala | Queensland) */
.map__poi--flip .map__poi-card {
  order: 3;
  margin-bottom: 0;
  margin-top: 2%;
}
/* pink frame + rounding live here (stripped from the old baked exports) so every photo matches */
.map__poi-img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0; /* square corners (per Devon, 23 Jul) */
  border: clamp(2px, 0.26vw, 5px) solid var(--brand);
}
/* pointer tip: upside-down trapezoid (flat top AND flattened point) tucked 2px up under
   the image's bottom edge so there's no seam, inset from the right */
.map__poi-tip {
  position: absolute;
  top: calc(100% - 2px);
  right: 8%;
  width: 15%;
  aspect-ratio: 1.6;
  background: var(--brand); /* black tip to match the card border */
  clip-path: polygon(0 0, 100% 0, 68% 100%, 32% 100%);
}
/* freestanding map labels â€” plain black text, or a pink badge with the map's sky-grey text */
.map__text {
  font-size: clamp(8px, 0.85vw, 16px);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
  white-space: pre;
  line-height: 1.25;
  text-align: center;
}
.map__text--box {
  background: var(--accent);
  color: var(--sky);
  font-weight: 700;
  padding: 0.35em 0.55em;
  border-radius: 0.18em;
}
.map__poi-logo {
  display: block;
  width: 82%;
  height: auto;
  aspect-ratio: 201 / 40;
} /* svg has %-sizing attrs â€” ratio forced here */
.map__poi-name {
  display: block;
  width: max-content;
  text-align: center;
  color: var(--brand);
  white-space: pre;
  font-size: clamp(6px, 0.58vw, 11px);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.3;
} /* one line unless "/" breaks it */
.map__marker {
  position: absolute;
  transform: translate(-50%, -50%);
  z-index: 2;
}
.map__lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}
.map__line {
  fill: none;
  stroke: #c5d8ec; /* thin + hair roads: lighter sky blue (per Devon, 23 Jul) */
  stroke-width: 4.5px;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.map__line--hair {
  stroke-width: 2.5px;
}
.map__line--thick {
  stroke: var(--brand);
  stroke-width: 7px;
}
.map__line--dash {
  stroke: var(--brand);
  stroke-dasharray: 7 7;
}
/* heading flowing along a line (textPath) â€” sized in the svg's 1600Ã—900 units, so it scales with the map */
/* direction arrow on a line â€” open V chevron */
.map__arrowhead {
  fill: none;
  stroke: var(--brand);
  stroke-width: 7px;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.map__line-label {
  font:
    600 32px Montserrat,
    sans-serif;
  fill: var(--brand); /* line heading black, like its dash line */
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: pre;
} /* stacked spaces count */
/* dashed lines can't draw on (dasharray is the dash), so they fade in instead */
html.fx-on .line-fade {
  opacity: 0;
  transition: opacity 0.9s ease 0.25s;
}
html.fx-on .line-fade.in {
  opacity: 1;
}
/* â”€â”€ mobile: the map is tiny, so shrink the big elements and grow the arrows
   (arrows live in map-scaled svg units â€” on phones they all but vanish) â”€â”€ */
@media (max-width: 760px) {
  #locations {
    scroll-margin-top: calc(var(--nav-h) + 60px);
  } /* anchor lands clear of the fixed nav, plus extra air */
  /* zoomed-in map (per Devon, 22 Jul): the figure runs past the viewport sides and the
     section clips it â€” sides + a band off the bottom crop away. Markers/lines/labels are
     %-positioned on the figure, so they track the zoom untouched. */
  .map {
    width: 160vw;
    margin-left: -20vw; /* 20vw off the left, 40vw off the right */
    /* no bottom crop â€” full map height shows (per Devon, 22 Jul) */
  }
  .map__heading {
    display: none;
  } /* no heading on mobile (per Devon, 22 Jul) */
  .map__poi {
    width: 9vw;
  }
  .map__poi-name {
    font-size: 6px;
    letter-spacing: 0.05em;
  }
  .map__text {
    font-size: 5.5px;
  } /* freestanding labels (plain + box) */
  .map__line {
    stroke-width: 1.5px;
  }
  .map__line--hair {
    stroke-width: 1px;
  }
  .map__line--thick {
    stroke-width: 3.5px;
  }
  /* ponytail: CSS `d` override â€” browsers without support just keep the small arrow */
  .map__arrowhead {
    d: path("M-14 -20 L14 0 L-14 20");
    stroke-width: 10px;
  }
}
/* line-draw: the route strokes draw on when the map scrolls into view â€” dash = the
   path's own length (JS sets --len), offset animates to 0 like a pen. */
html.fx-on .line-draw {
  stroke-dasharray: var(--len, 0);
  stroke-dashoffset: var(--len, 0);
  transition: stroke-dashoffset 1.8s var(--ease) 0.15s;
}
html.fx-on .line-draw.in {
  stroke-dashoffset: 0;
}
/* marker-pop: staggered pop-in when the map scrolls into view (html.fx-on = JS present;
   with JS off the markers simply sit visible). --i is the marker's index, set inline. */
html.fx-on .marker-pop {
  opacity: 0;
  transform: translate(-50%, -50%) scale(0);
  transition:
    transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--i, 0) * 90ms),
    opacity 0.3s ease calc(var(--i, 0) * 90ms);
}
html.fx-on .marker-pop.in {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* â”€â”€ Quinns Hill popup (#qh-popup) â€” Figma 2147:325. Offwhite rounded panel over an
   80% scrim: pink eyebrow left, sub-line right, render photo with the CTA overlaid
   top-right. Opened once per session from main.js; [hidden] keeps it out of no-JS. â”€â”€ */
.popup {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.popup[hidden] {
  display: none;
}
.popup__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.8);
}
.popup__panel:focus {
  outline: none;
} /* programmatic focus target on open â€” no ring */
.popup__panel {
  position: relative;
  width: min(930px, 100%);
  background: var(--offwhite);
  border-radius: 5px;
  padding: 52px 26px 21px;
}
.popup__x {
  position: absolute;
  top: 10px;
  right: 16px;
  border: 0;
  background: none;
  cursor: pointer;
  color: var(--ink);
  font-size: 26px;
  line-height: 1;
  padding: 6px;
}
.popup__eyebrow {
  color: var(--accent);
  font-weight: 700;
  font-size: 42px;
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.popup__sub {
  text-align: right;
  font-size: 40px;
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 18px;
  margin-right: 14px;
} /* "now" ends flush with the CTA's right edge below */
.popup__media {
  position: relative;
}
.popup__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 5px;
}
.popup__cta {
  position: absolute;
  top: 24px;
  right: 14px;
}
@media (max-width: 640px) {
  .popup .navbtn--dark {
    display: inline-flex;
  } /* nav hides its dark CTA on phones â€” the popup keeps its own */
  .popup__cta {
    padding-left: 20px;
    top: 14px;
  } /* text clear of the slanted left edge; top = right inset so the corner gap is even */
  .popup__panel {
    padding: 20px 16px 14px;
  }
  .popup__eyebrow {
    font-size: 19px;
  }
  .popup__sub {
    font-size: 18px;
    margin-bottom: 10px;
  }
}

/* â”€â”€ FAQs page â€” pink wedge under the heading, echoing the contact section's
   .cf__pink: flat left, slanted right edge (top out further than bottom). JS
   drives --g 0â†’1 with page scroll so the wedge slowly widens to the right;
   JS-off / reduced-motion sits at the rest width. Content stays measure-capped
   well left of the slant, so the clip never cuts text. â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */
.faqrow {
  position: relative;
  margin-top: 2.5rem;
}
.faqrow__img {
  display: none;
} /* desktop-only companion panel */
.faqp {
  margin-inline: 2%;
  background: var(--accent);
  color: var(--offwhite);
  border-radius: 12px;
  padding: clamp(28px, 5vh, 56px) 0 clamp(36px, 7vh, 72px);
}
.faqp details {
  border-bottom: 1px solid rgba(238, 236, 232, 0.35);
  padding: 1rem 0;
}
.faqp summary {
  font-weight: 700;
  cursor: pointer;
}
.faqp details p {
  margin-top: 0.6rem;
}
@media (min-width: 861px) {
  .faqp {
    --faqp-run: clamp(
      120px,
      14vw,
      280px
    ); /* how far the wedge grows rightward over the scroll */
    --faqp-slant: clamp(
      90px,
      9vw,
      170px
    ); /* right-edge slant run â€” same family as --cf-slant */
    margin-inline: 1% 26%; /* detached from both screen edges (right pulled in further) */
    position: relative;
    z-index: 1; /* above the image panel that slides beneath its slant */
    clip-path: url(#faqp-clip); /* rounded slant clip from main.js; JS-off â†’ plain rounded rect */
    padding-right: calc(var(--faqp-run) + var(--faqp-slant));
  } /* content clear of the slant at rest */
  /* Offwhite image panel to the wedge's right: spans under the pink (which covers it),
     its visible left edge cut parallel to the pink's slant by the main.js clip â€” so it
     shrinks as the wedge grows. JS-off: no clip â†’ the strip right of the pink shows. */
  .faqrow__img {
    display: block;
    position: absolute;
    inset: 0 1% 0 40%;
    width: 59%;
    height: 100%;
    object-fit: cover;
    background: var(--offwhite);
    border-radius: 12px;
    clip-path: url(#faqp-clip-img);
  }
}

/* â”€â”€ Reduced motion: every animation must have a no-motion path (spec Â§1.5). â”€â”€ */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
