/* ============================================================
   Coastal Grove Builders — Design Tokens
   ============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..700;1,9..144,300..600&family=Karla:wght@400;500;600;700&display=swap');

:root {
  /* Color — primitive (extracted from coastalgrovelogo.png) */
  --green-900: #0F2A1A;
  --green-700: #1A4229;
  --green-500: #3C6B47;
  --teal-800: #123F42;
  --teal-600: #1F6E72;
  --teal-400: #4FA3A0;
  --cream-300: #FBF6EA;
  --cream-500: #F7EACD;
  --cream-700: #E8D6AC;
  --tan-600: #8A8368;
  --tan-800: #5C563F;
  --ink-900: #16241A;
  --white: #FFFFFF;

  /* Color — semantic */
  --color-primary: var(--green-700);
  --color-primary-dark: var(--green-900);
  --color-primary-light: var(--green-500);
  --color-secondary: var(--cream-500);
  --color-surface: var(--cream-300);
  --color-surface-alt: var(--cream-700);
  --color-accent: var(--teal-600);
  --color-accent-dark: var(--teal-800);
  --color-accent-light: var(--teal-400);
  --color-text: var(--ink-900);
  --color-muted: var(--tan-600);
  --color-muted-dark: var(--tan-800);
  --color-border: rgba(22, 36, 26, 0.14);
  --color-border-on-dark: rgba(247, 234, 205, 0.35);

  /* Typography */
  --font-display: 'Fraunces', 'Iowan Old Style', serif;
  --font-body: 'Karla', -apple-system, BlinkMacSystemFont, sans-serif;

  --text-xs: 0.75rem;
  --text-sm: 0.8125rem;
  --text-base: 1rem;
  --text-md: 1.125rem;
  --text-lg: 1.375rem;
  --text-xl: 1.75rem;
  --text-headline: clamp(2rem, 4.6vw + 0.9rem, 3.75rem);

  /* Spacing (8px base) */
  --space-1: 0.5rem;
  --space-2: 0.75rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2rem;
  --space-6: 3rem;
  --space-7: 4rem;
  --space-8: 6rem;

  /* Shape */
  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 6px;
  --border-hairline: 1px solid var(--color-border);

  /* Motion */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-settle: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 180ms;
  --duration-base: 260ms;
  --duration-entrance: 820ms;

  /* Layout */
  --header-height: 76px;
  --header-height-shrunk: 58px;
  --content-max: 1280px;
}

/* ============================================================
   Reset & base
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  min-height: 100svh;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--color-text);
  background: var(--color-surface);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, video { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  left: var(--space-3);
  top: -100px;
  z-index: 1000;
  background: var(--color-primary-dark);
  color: var(--white);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-weight: 600;
  transition: top var(--duration-base) var(--ease-standard);
}
.skip-link:focus {
  top: var(--space-3);
}

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

/* ============================================================
   Site header — "stamped site board"
   ============================================================ */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--header-height);
  display: flex;
  align-items: center;
  background: var(--color-surface);
  border-bottom: 2px solid var(--color-primary);
  transition: height var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
}

.site-header.is-scrolled {
  box-shadow: 0 6px 18px -10px rgba(15, 42, 26, 0.35);
}

.site-header.is-shrunk {
  height: var(--header-height-shrunk);
}

/* The header is now fixed (out of flow) so its own height is free to
   change. This spacer reserves the header's UNSHRUNK height in the
   document's normal flow, so the hero/footer below never move —
   without it, `main` would start at the very top of the page and sit
   underneath the fixed header. It stays constant on purpose: when the
   header condenses, a small sliver of hero footage becomes visible
   between the header's new (shorter) edge and the spacer's (constant)
   edge — a deliberate, expected side effect, not a bug. */
.header-spacer {
  height: var(--header-height);
}

.site-header__inner {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 var(--space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.brand-mark {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.brand-mark__logo {
  width: 42px;
  height: 42px;
  aspect-ratio: 1 / 1;
  flex-shrink: 0;
  transition: width var(--duration-base) var(--ease-standard),
              height var(--duration-base) var(--ease-standard);
}

/* The whole bar condenses on scroll now (header height itself
   transitions above), so every element inside steps down together:
   logo, wordmark, nav type, and CTA. */
.site-header.is-shrunk .brand-mark__logo {
  width: 34px;
  height: 34px;
}

.brand-mark__text {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-primary);
  line-height: 1.1;
  transition: font-size var(--duration-base) var(--ease-standard);
}

.site-header.is-shrunk .brand-mark__text {
  font-size: 0.92rem;
}

.brand-mark__text small {
  display: block;
  font-family: var(--font-body);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--color-muted-dark);
  text-transform: uppercase;
  margin-top: 2px;
  transition: font-size var(--duration-base) var(--ease-standard);
}

.site-header.is-shrunk .brand-mark__text small {
  font-size: 0.55rem;
}

.main-nav {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.main-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.main-nav__list a {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-text);
  padding: var(--space-1) 0;
  position: relative;
  transition: font-size var(--duration-base) var(--ease-standard);
}

.site-header.is-shrunk .main-nav__list a {
  font-size: 0.85rem;
}

.main-nav__list a::after {
  content: '';
  position: absolute;
  left: 0; right: 100%;
  bottom: -2px;
  height: 2px;
  background: var(--color-accent);
  transition: right var(--duration-base) var(--ease-standard);
}

.main-nav__list a:hover::after,
.main-nav__list a:focus-visible::after {
  right: 0;
}

.cta-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2) var(--space-4);
  background: var(--color-accent);
  color: var(--white);
  font-weight: 600;
  font-size: 0.9375rem;
  border: none;
  border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
  white-space: nowrap;
  min-height: 44px;
  transition: background var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard),
              padding var(--duration-base) var(--ease-standard),
              font-size var(--duration-base) var(--ease-standard);
}

/* min-height stays untouched here on purpose — it's the 44px touch
   target floor, and condensing shouldn't shrink it below that. Only
   padding and font-size step down, so the button visually shrinks
   without becoming a harder target to hit. */
.site-header.is-shrunk .cta-tag {
  padding: var(--space-1) var(--space-3);
  font-size: 0.85rem;
}

.cta-tag:hover,
.cta-tag:focus-visible {
  background: var(--color-accent-dark);
  transform: translateY(-2px) scale(1.02);
  box-shadow: 0 10px 24px -8px rgba(31, 110, 114, 0.55),
              inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.cta-tag:active {
  transform: translateY(0) scale(0.99);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15);
}

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  color: var(--color-primary);
}

.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: '';
  display: block;
  width: 22px;
  height: 2px;
  background: currentColor;
  transition: transform var(--duration-base) var(--ease-standard),
              opacity var(--duration-base) var(--ease-standard);
}
.nav-toggle__bars { position: relative; }
.nav-toggle__bars::before { position: absolute; top: -7px; left: 0; }
.nav-toggle__bars::after { position: absolute; top: 7px; left: 0; }

.site-header.nav-open .nav-toggle__bars { background: transparent; }
.site-header.nav-open .nav-toggle__bars::before { transform: translateY(7px) rotate(45deg); }
.site-header.nav-open .nav-toggle__bars::after { transform: translateY(-7px) rotate(-45deg); }

/* ============================================================
   Hero
   ============================================================ */
.hero {
  --hero-eased: 0;
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: var(--color-primary-dark);
}

.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero__video,
.hero__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 38%;
}

.hero__poster { display: none; }

@media (prefers-reduced-motion: reduce) {
  .hero__video { display: none; }
  .hero__poster { display: block; }
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(
    ellipse 80% 65% at 50% 48%,
    rgba(15, 42, 26, 0.8) 0%,
    rgba(15, 42, 26, 0.7) 45%,
    rgba(15, 42, 26, 0.66) 100%
  );
  /* Lightens in step with the same eased exit curve as the content
     (not a separate linear fade), so the footage clarifies as part of
     one choreography rather than snapping clear on its own timeline. */
  opacity: calc(1 - (var(--hero-eased) * 0.65));
}

.hero__content {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--space-7) var(--space-4);
  max-width: 44rem;
}

.hero__content.is-scroll-hidden {
  pointer-events: none;
}

.hero__plate {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-5) var(--space-5);
  border-top: 1px solid var(--color-border-on-dark);
  border-bottom: 1px solid var(--color-border-on-dark);
  /* The frame itself doesn't travel — only its contents do, at their
     own differing rates below — but it fades with them so nothing
     lingers once the logo and headline are gone. */
  opacity: calc(1 - var(--hero-eased));
}

.hero__logo {
  width: clamp(130px, 17vw, 240px);
  height: clamp(130px, 17vw, 240px);
  aspect-ratio: 1 / 1;
  margin-bottom: var(--space-4);
  filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.35));
  /* Exit: shorter travel, the more grounded of the two elements. */
  opacity: calc(1 - var(--hero-eased));
  transform: translateY(calc(var(--hero-eased) * -64px))
             scale(calc(1 - (var(--hero-eased) * 0.07)));
}

.hero__text {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Exit: travels further/faster than the logo — that gap opening up
     between the two as they rise is the parallax depth cue. */
  opacity: calc(1 - var(--hero-eased));
  transform: translateY(calc(var(--hero-eased) * -104px))
             scale(calc(1 - (var(--hero-eased) * 0.045)));
}

.hero__headline {
  font-family: var(--font-display);
  font-size: var(--text-headline);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--white);
  margin: 0;
}

.hero__headline em {
  display: inline-block;
  font-style: italic;
  font-weight: 400;
  color: var(--color-secondary);
  /* "Builders" is alone on its own centered line; italic's lighter
     left sidebearing reads as slightly off-center against "Coastal
     Grove" above it without this nudge. */
  transform: translateX(-0.03em);
}

.hero__tagline {
  margin-top: var(--space-4);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--white);
}

/* Entrance: logo, then headline+tagline ~180ms behind it. Scoped
   entirely inside this media query — the "from" keyframe is the
   only place opacity:0 is ever declared, so if animations are
   unsupported the rule simply doesn't apply and both elements render
   at their normal, fully visible default. Nothing depends on JS.

   fill-mode is `backwards`, not `both`/`forwards`, on purpose: a
   `forwards`-filling animation would permanently own opacity/transform
   on these elements, silently overriding the plain scroll-exit rules
   above for the rest of the page's life. `backwards` only holds the
   "from" state during the animation-delay (preventing a flash-of-
   visible-content before it plays) and lets go the instant the
   animation finishes, handing opacity/transform back to the scroll-
   driven rules from then on. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes hero-rise-in {
    from {
      opacity: 0;
      transform: translateY(22px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  .hero__logo {
    animation: hero-rise-in var(--duration-entrance) var(--ease-settle) backwards;
  }

  .hero__text {
    animation: hero-rise-in var(--duration-entrance) var(--ease-settle) 180ms backwards;
  }
}

/* ============================================================
   Footer — "routed nameplate"
   ============================================================ */
.site-footer {
  background: var(--color-primary-dark);
  color: var(--cream-500);
  border-top: 6px solid var(--color-accent);
}

.site-footer__inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-7) var(--space-4) var(--space-5);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-6);
}

.footer-brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.footer-brand__logo {
  width: 56px;
  height: 56px;
  aspect-ratio: 1 / 1;
  flex-shrink: 0;
}

.footer-brand__name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: 600;
  color: var(--white);
}

.footer-brand__est {
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cream-700);
  margin-top: 2px;
}

.footer-meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
  text-align: right;
}

.footer-meta__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--space-1) var(--space-3);
  color: var(--cream-500);
}

.footer-meta__row .placeholder {
  color: var(--cream-700);
  font-style: italic;
}

.footer-meta__link {
  transition: color var(--duration-fast) var(--ease-standard);
}

.footer-meta__link:hover,
.footer-meta__link:focus-visible {
  color: var(--color-secondary);
  text-decoration: underline;
}

.site-footer__bottom {
  border-top: 1px solid var(--color-border-on-dark);
}

.site-footer__bottom-inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-4);
  font-size: var(--text-xs);
  color: var(--cream-700);
  text-align: center;
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 860px) {
  .main-nav {
    /* Absolute against `.site-header` (the nearest positioned
       ancestor — `.site-header__inner` in between is static, so it's
       skipped) rather than fixed with a hardcoded top offset. `top:
       100%` tracks whatever the header's CURRENT height is, shrunk or
       not, with no JS needed to keep the dropdown flush against it. */
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    bottom: auto;
    flex-direction: column;
    align-items: stretch;
    background: var(--color-surface);
    border-bottom: 2px solid var(--color-primary);
    padding: var(--space-4);
    gap: var(--space-4);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-standard),
                transform var(--duration-base) var(--ease-standard),
                visibility var(--duration-base);
  }

  .site-header.nav-open .main-nav {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateY(0);
  }

  .main-nav__list {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
    width: 100%;
  }

  .cta-tag { width: 100%; }

  .nav-toggle { display: inline-flex; }

  .footer-meta { text-align: left; }
  .footer-meta__row { justify-content: flex-start; }
}

@media (max-width: 480px) {
  .hero__plate { padding: var(--space-4) var(--space-3); }
  .hero__logo { width: clamp(110px, 30vw, 170px); height: clamp(110px, 30vw, 170px); }
}

/* ============================================================
   Toast — bottom-right offer, collapses to a corner pill
   ============================================================ */
.toast {
  position: fixed;
  right: var(--space-4);
  bottom: var(--space-4);
  z-index: 90;
  pointer-events: none;
}

.toast[data-toast-state='dismissed'] {
  display: none;
}

.toast__card,
.toast__pill {
  position: absolute;
  right: 0;
  bottom: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 550ms var(--ease-standard),
              transform 550ms var(--ease-standard);
}

.toast__card {
  width: min(27rem, calc(100vw - 2 * var(--space-4)));
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-6) var(--space-4) var(--space-4);
  box-shadow: 0 20px 48px -14px rgba(15, 42, 26, 0.42);
  transform: translateX(32px);
}

.toast__pill {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--color-primary);
  border-radius: 999px;
  padding: var(--space-3) var(--space-2) var(--space-3) var(--space-5);
  box-shadow: 0 14px 30px -10px rgba(26, 66, 41, 0.55);
  transform: scale(0.85);
}

.toast[data-toast-state='expanded'] .toast__card {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}

.toast[data-toast-state='collapsed'] .toast__pill {
  opacity: 1;
  transform: scale(1);
  pointer-events: auto;
}

.toast[data-toast-state='collapsed'] .toast__pill:hover,
.toast[data-toast-state='collapsed'] .toast__pill:focus-within {
  background: var(--color-primary-dark);
  transform: scale(1.03) translateY(-2px);
}

.toast__close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--color-muted-dark);
  font-size: 1.4rem;
  line-height: 1;
  transition: background var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}

.toast__close:hover,
.toast__close:focus-visible {
  color: var(--color-text);
  background: var(--color-surface-alt);
}

.toast__heading {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
  color: var(--color-primary);
  margin: 0 var(--space-4) var(--space-1) 0;
}

.toast__body {
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: 1.4;
  margin: 0 0 var(--space-3);
}

.toast__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: var(--space-2) var(--space-4);
  background: var(--color-accent);
  color: var(--white);
  font-weight: 600;
  font-size: 1rem;
  border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
  min-height: 46px;
  transition: background var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}

.toast__cta:hover,
.toast__cta:focus-visible {
  background: var(--color-accent-dark);
  transform: translateY(-2px) scale(1.02);
  box-shadow: 0 10px 24px -8px rgba(31, 110, 114, 0.55),
              inset 0 1px 0 rgba(255, 255, 255, 0.2);
}

.toast__cta:active {
  transform: translateY(0) scale(0.99);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15);
}

.toast__pill-reopen {
  padding: var(--space-2) 0;
  font-weight: 600;
  font-size: 1rem;
  color: var(--white);
  white-space: nowrap;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.toast__pill-close {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.85);
  font-size: 1.25rem;
  line-height: 1;
  transition: background var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}

.toast__pill-close:hover,
.toast__pill-close:focus-visible {
  background: rgba(255, 255, 255, 0.3);
  color: var(--white);
}

/* Bottom-right is too tight on a phone: the card goes bottom-anchored
   and near-full-width instead. The pill stays corner-anchored at
   every width — it's small enough not to need the same treatment. */
@media (max-width: 560px) {
  /* The card switches to fixed positioning here (rather than absolute
     within `.toast`, which is only a right/bottom-anchored 0×0 point)
     so left/right insets resolve against the actual viewport and it
     can span near-full-width. The pill is untouched — it stays
     absolute within `.toast` and corner-anchored. */
  .toast__card {
    position: fixed;
    left: var(--space-3);
    right: var(--space-3);
    bottom: var(--space-3);
    width: auto;
    transform: translateY(16px);
  }

  .toast[data-toast-state='expanded'] .toast__card {
    transform: translateY(0);
  }
}
