/* ==========================================================================
   icg-polish.css — motion + consistency layer (checklist C1, 2026-08-20)
   Sole owner: worker-C. Loaded sitewide via A5 injection.
   Motion-guard map:
     - All transitions below are neutralized under reduced motion by the
       global prefers-reduced-motion:reduce kill-switch (section 5).
     - Hover-motion rules (card lift, image zoom) sit inside @media (hover:hover).
     - .reveal hidden state + smooth scroll exist ONLY inside
       @media (prefers-reduced-motion: no-preference).
     - Carousel rules (section 11) carry the .icg-carousel ancestor prefix to
       out-specify the homepage's LATER inline #icg-credibility-css block, so
       this file is the single effective owner of the carousel's computed
       visuals (fix 2026-08-20).
   ========================================================================== */

/* (9) MPA cross-fade — self-gating, no-op where unsupported */
@view-transition {
  navigation: auto;
}

/* (1) Card transitions (.ow-card / .ow-card__media / .ow-ph confirmed in
   dist/our-work markup by C3; parents already ship overflow:hidden in the
   page inline CSS — restated here as a guard for the img zoom) */
.ow-card {
  transition: border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}
.ow-card__media img,
.ow-ph img {
  transition: transform .4s ease;
}
.ow-card__media,
.ow-ph {
  overflow: hidden;
}

/* (2) Buttons — kills the off-brand Bootstrap #286090 hover flash */
.btn {
  transition: background-color .2s ease, box-shadow .2s ease;
}
.btn-primary:hover,
.btn-primary:focus {
  background-color: #0a457b;
}

/* (3) Nav / footer / top-row link color transitions */
#top-row a,
nav a,
footer a {
  transition: color .2s ease;
}

/* (7) Hover-motion rules — only on devices that truly hover */
@media (hover: hover) {
  .ow-card:hover {
    box-shadow: 0 8px 24px rgba(27, 58, 95, .12);
    transform: translateY(-3px);
  }
  .ow-card:hover .ow-card__media img {
    transform: scale(1.04);
  }
  .ow-ph:hover img {
    transform: scale(1.04);
  }
}

/* (4) Visible focus ring */
a:focus-visible,
.btn:focus-visible,
.ow-card:focus-visible,
.ow-chip:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: 2px solid #1B3A5F;
  outline-offset: 2px;
}
/* Override the outline-stripping chip rule shipped in the our-work inline CSS
   (.ow-filter:focus-visible+.ow-chips .ow-chip{outline:none}) — same
   specificity, this sheet loads later in the cascade */
.ow-filter:focus-visible + .ow-chips .ow-chip {
  outline: 2px solid #1B3A5F;
  outline-offset: 2px;
}

/* (5) Global reduced-motion kill-switch */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* (6)+(8) Motion opt-in — smooth scroll and the .reveal hidden state exist
   ONLY for no-preference users, so content is never hidden under reduced
   motion (and never hidden at all without JS: only JS adds .reveal) */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
  .reveal {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity .5s ease, transform .5s ease;
  }
  .reveal.in {
    opacity: 1;
    transform: none;
  }
  /* cascade guard: .reveal.in{transform:none} ties specificity with the
     .ow-card:hover lift and would win by file order — re-assert the lift for
     revealed cards (D3 loop-back fix, live-verified 2026-08-20) */
  @media (hover: hover) {
    .ow-card.reveal.in:hover {
      transform: translateY(-3px);
    }
  }
}

/* (10) Interior-page header fix — spacing gets ONE owner.
   Derived from dist/wp-content/themes/custom/css/style.css (read 2026-08-20):
     line 3:   body.page-template-default, body.single-community { padding-top: 150px; }
     line 57:  #top-row { position: fixed; top: 0; ... }
     line 122: .navbar-fixed-top { background: #fff; top: 40px; }
   All children of <header> are position:fixed on interior pages, so header
   offsetHeight collapses to 0 and the body padding magic number owns the
   space. Override: header itself owns an explicit 150px (40px top-row band
   per the navbar's top:40px + 110px fixed navbar band, totalling the theme's
   own 150px reservation) and the body padding is zeroed.
   Per-breakpoint: style.css's responsive blocks (@media 1200/992/767/450px,
   lines 622-687) contain NO override of the interior 150px reservation
   (the only padding-top override there, 138px @767px, targets
   body.page-template-front-page — the homepage), so 150px is the derived
   explicit height at every breakpoint; nothing is invented.
   Homepage is untouched: its body classes are
   "home page-template page-template-front-page ..." — never
   page-template-default — so neither rule can match a page with #logo. */
body.page-template-default {
  padding-top: 0;
}
body.page-template-default header {
  height: 150px;
}

/* (11) Testimonials carousel visuals — retargeted 2026-08-20 to the REAL
   B3-shipped homepage markup (dist/index.html lines 273-339):
     .icg-carousel [role=region][aria-roledescription=carousel]
       > .icg-car-track (scroller) > 8x .icg-car-slide[role=group] (cards)
       > .icg-car-controls > .icg-car-prev / .icg-car-dots / .icg-car-next
   (no bare .icg-car class exists anywhere in dist — the earlier .icg-car
   selectors were dead).
   CASCADE OWNERSHIP: the homepage's inline #icg-credibility-css block
   (dist/index.html line 207) loads AFTER this sheet and styles the same
   elements at (0,1,0) specificity, so every rule below carries the
   .icg-carousel ancestor prefix (>= (0,2,0)) and covers EVERY declaration
   that block sets on the track / slides / controls / buttons / dots —
   this file is therefore the single effective owner of the carousel's
   computed visuals regardless of load order.
   Tokens: Poppins / navy #1B3A5F / gold #C8A44D (from build-homepage-credibility.py) */
.icg-carousel .icg-car-track {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding: 4px 4px 18px; /* shorthand also overrides the inline padding-bottom:8px */
  scrollbar-width: thin;
}
.icg-carousel .icg-car-track [role=group] {
  flex: 0 0 auto; /* beats the inline flex:0 0 88% AND its @768/@1100 flex-basis overrides */
  min-width: clamp(280px, 85vw, 340px);
  max-width: 340px;
  scroll-snap-align: start;
  box-sizing: border-box;
}
.icg-carousel .icg-car-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 18px;
}
.icg-carousel .icg-car-prev,
.icg-carousel .icg-car-next {
  min-width: 24px;
  min-height: 24px;
  width: 44px;
  height: 44px;
  border: 0;
  background: #1B3A5F; /* white glyph on #1B3A5F = 11.5:1, over the 3:1 bar */
  color: #fff;
  font-family: 'Poppins', sans-serif;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color .2s ease;
}
.icg-carousel .icg-car-prev:hover,
.icg-carousel .icg-car-next:hover {
  background: #0a457b;
}
.icg-carousel .icg-car-dots {
  display: flex;
  align-items: center;
  gap: 4px;
}
.icg-carousel .icg-car-dots button {
  min-width: 24px;
  min-height: 24px; /* >=24x24 hit area */
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.icg-carousel .icg-car-dots button::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #c3cedb;
  transition: background-color .2s ease;
}
.icg-carousel .icg-car-dots button[aria-current="true"]::before {
  width: 12px;
  height: 12px;
  background: #C8A44D; /* gold active vs gray inactive — distinct state */
}
.icg-carousel .icg-car-prev:focus-visible,
.icg-carousel .icg-car-next:focus-visible,
.icg-carousel .icg-car-dots button:focus-visible {
  outline: 2px solid #1B3A5F;
  outline-offset: 2px;
}

/* (12) Mobile tap targets — Apple HIG minimum 44x44.
   Measured live 2026-08-22 under real device emulation (DPR 3, touch, iOS 17
   Safari UA) at 375 / 390 / 430: the click-to-call link was 98x20 and the
   hamburger 42x32. Both are under the 44x44 minimum, and the phone link is both
   the highest-intent action on a builder's mobile site AND the element wired to
   the GA4 contact_phone_click event.

   The hit area is grown with PADDING and cancelled again with equal NEGATIVE
   MARGIN, so the touch target reaches 44px without changing the visual layout —
   #top-row is only 40px tall and the fixed navbar is offset against it with
   top:40px, so growing that row would shift the whole header. Bootstrap 3 sets
   box-sizing:border-box globally, so min-height maps directly to the measured
   border box. Scoped to the mobile breakpoint; desktop is untouched. */
@media (max-width: 767px) {
  header #top-row a[href^="tel:"] {
    display: inline-block;
    min-height: 44px;
    min-width: 44px;
    padding-top: 12px;
    padding-bottom: 12px;
    margin-top: -12px;
    margin-bottom: -12px;
  }
  .navbar-toggle {
    min-height: 44px;
    min-width: 44px;
  }
}

/* (13) Sticky nav — solid white at rest, glassy once scrolled.
   Founder ruling 2026-08-22: "70% is obviously glassy. fade, after a threshold
   like 100px, All pages".

   At rest we add NOTHING: the theme's own solid white
   (style.css:122 — .navbar-fixed-top { background: #fff; top: 40px; }) stays the
   resting state untouched. Only the scrolled state is ours, applied via the
   .icg-nav-scrolled class that icg-polish.js toggles past 100px of scroll.

   Specificity: .navbar-fixed-top.icg-nav-scrolled is 0-2-0 against the theme's
   0-1-0, and icg-polish.css is the last stylesheet on every page, so this wins
   WITHOUT !important.

   backdrop-filter is what makes 70% read as intentional frosted glass rather
   than a washed-out bar; where it is unsupported the rule degrades to a plain
   70% white, which is still the requested look.

   Reduced motion needs no rule here — the global kill-switch in section (5)
   already clamps transition-duration to .01ms, so those users get the
   translucency instantly with no fade. */
.navbar-fixed-top {
  transition: background-color .25s ease;
}
.navbar-fixed-top.icg-nav-scrolled {
  background-color: rgba(255, 255, 255, 0.7);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

/* (14) Contact page — stop the form spanning the whole page.
   Founder 2026-08-22: "I still don't see the form having changed at all. It's
   still spread across the page. It should be a nice square box... off to the
   left-hand side with some text next to it."
   Measured before this rule: the form was 1410px wide inside a 1440px viewport.

   Two columns: invitation copy left, the form in a contained card right. The
   whole shell is capped at 1080px and centred. Below 768px it stacks, copy
   first, so mobile reads naturally. scripts/build-contact-form.py emits the
   .icg-contact-wrap / .icg-contact-intro / .icg-contact-card markup. */
.icg-contact-wrap {
  display: flex;
  flex-wrap: wrap;
  gap: 48px;
  align-items: flex-start;
  max-width: 1080px;
  margin: 0 auto 20px;
  padding: 0 15px;
}
.icg-contact-intro {
  flex: 1 1 300px;
  min-width: 280px;
}
.icg-contact-intro h2 {
  margin-top: 0;
}
.icg-contact-intro p {
  max-width: 46ch;   /* comfortable measure — long lines are what looked "spread out" */
}
.icg-contact-facts {
  list-style: none;
  padding: 0;
  margin: 24px 0 0;
}
.icg-contact-facts li {
  padding: 6px 0;
  border-top: 1px solid #e6e9ee;
}
.icg-contact-facts li strong {
  display: inline-block;
  min-width: 122px;
  color: #1B3A5F;
}
.icg-contact-card {
  flex: 1 1 420px;
  min-width: 300px;
  max-width: 560px;
  background: #fff;
  border: 1px solid #e6e9ee;
  border-radius: 6px;
  padding: 28px;
  box-shadow: 0 2px 14px rgba(27, 58, 95, .07);
}
.icg-contact-card .wpcf7-form-control.form-control,
.icg-contact-card textarea.form-control {
  width: 100%;
}
/* The legacy Contact Form 7 response div renders as an empty cream alert bar.
   It was invisible on the old full-width layout but shows as a stray block
   inside the white card, so hide it until CF7 actually puts text in it. Our own
   handler writes #iw-form-msg instead and is unaffected. */
.icg-contact-card .wpcf7-response-output:empty {
  display: none;
}
@media (max-width: 767px) {
  .icg-contact-wrap { gap: 28px; }
  .icg-contact-card { padding: 20px; }
}
