/* ==========================================================================
   Self-hosted fonts

   These are the same two variable families the original loaded from Google
   Fonts (Inter Tight and Inter, latin plus latin-ext). Serving them from this
   origin removes a render-blocking stylesheet on fonts.googleapis.com and a
   second connection to fonts.gstatic.com from the critical path, and lets the
   two latin files be preloaded. font-display: swap keeps text visible while
   they arrive, as the Google stylesheet did.
   ========================================================================== */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/inter-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/inter-tight-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/assets/fonts/inter-tight-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ==========================================================================
   Connect 2 Power — static behaviour layer

   assets/index.css (the original compiled Tailwind sheet) supplies every bit
   of appearance. This file only replaces the behaviour that used to come from
   React: hero crossfade, service tabs, accordions, mobile nav, carousel and
   scroll reveal — all of it in CSS so the page works with JavaScript off.

   Palette, taken from the compiled sheet:
     cream-50/95 #fdfbf7f2   cream-100 #f7f4ee   cream-200 #efe9de
     charcoal-100 #d6d6d6    charcoal-200 #a3a3a3
     charcoal-300 #6b6b6b    charcoal-400 #404040   charcoal-500 #1a1a1a
     navy-500 #1e2a3a        navy-600 #16202d
     accent #ef4000          gold #C7995E          warm #474544
     ease-cinematic cubic-bezier(.25, .46, .45, .94)
   ========================================================================== */

/* --------------------------------------------------------------------------
   A few utilities the original build never used.
   assets/index.css was compiled against the original markup, so Tailwind
   purged everything it did not see. These are the handful the rebuild needs
   that were not in that set: display:contents for the carousel arrow groups,
   and the sizing/spacing used by thank-you.html.
   -------------------------------------------------------------------------- */
.contents {
  display: contents;
}

.min-h-screen {
  min-height: 100vh;
}

.w-14 {
  width: 3.5rem;
}

.h-16 {
  height: 4rem;
}

.px-8 {
  padding-left: 2rem;
  padding-right: 2rem;
}

.py-3\.5 {
  padding-top: 0.875rem;
  padding-bottom: 0.875rem;
}

@media (min-width: 768px) {
  .md\:px-12 {
    padding-left: 3rem;
    padding-right: 3rem;
  }
}

/* --------------------------------------------------------------------------
   Quote button pressed state.
   The button now uses charcoal text on the brand gold (6.75:1 at rest, 5.13:1
   on hover). The original pressed colour #9A7240 is too dark for dark text at
   4.02:1, so the press lightens slightly to #A67D4D instead — 4.69:1, and still
   a visible change under the finger. Tailwind purged to the original markup, so
   this arbitrary value needs declaring by hand.
   -------------------------------------------------------------------------- */
.active\:bg-\[\#A67D4D\]:active {
  --tw-bg-opacity: 1;
  background-color: rgb(166 125 77 / var(--tw-bg-opacity, 1));
}

/* --------------------------------------------------------------------------
   The hidden attribute must win over display utilities. Tailwind's `flex` and
   friends are declared after the UA sheet and would otherwise reveal the
   confirmation panels that ship hidden inside each form card.
   -------------------------------------------------------------------------- */
[hidden] {
  display: none !important;
}

/* --------------------------------------------------------------------------
   Scroll reveal
   Visible by default, so content renders with JavaScript off. Where
   scroll-driven animations exist, replay the original fade-and-rise.
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 1;
  transform: none;
  transition: none;
}

@keyframes reveal-rise {
  from {
    opacity: 0;
    transform: translateY(1.5rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .reveal {
      animation: reveal-rise 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
      animation-timeline: view();
      animation-range: entry 5% entry 60%;
    }
  }
}

/* --------------------------------------------------------------------------
   Hero crossfade
   Five stills, 6s apart, 1.6s crossfade — a 30s loop. The first slide carries
   a negative delay so it is already at full opacity on the first paint.
   -------------------------------------------------------------------------- */
.hero-slide {
  opacity: 0;
}

.hero-slide:first-child {
  opacity: 1;
}

@keyframes hero-fade {
  0% {
    opacity: 0;
  }
  5.3333% {
    opacity: 1;
  }
  20% {
    opacity: 1;
  }
  25.3333% {
    opacity: 0;
  }
  100% {
    opacity: 0;
  }
}

/* The cycle only runs once the later stills have actually been fetched, which
   assets/enhance.js does after load — they are not on the critical path, and
   fading to a still that has not arrived would show an empty box. With no
   scripting the hero simply holds on the first still. */
@media (prefers-reduced-motion: no-preference) {
  .hero-cycle .hero-slide {
    animation: hero-fade 30s linear infinite;
  }
  .hero-cycle .hero-slide:nth-child(1) {
    animation-delay: -1.6s;
  }
  .hero-cycle .hero-slide:nth-child(2) {
    animation-delay: 4.4s;
  }
  .hero-cycle .hero-slide:nth-child(3) {
    animation-delay: 10.4s;
  }
  .hero-cycle .hero-slide:nth-child(4) {
    animation-delay: 16.4s;
  }
  .hero-cycle .hero-slide:nth-child(5) {
    animation-delay: 22.4s;
  }
}

/* --------------------------------------------------------------------------
   Service tabs — radio inputs drive both the tab list and the panels
   -------------------------------------------------------------------------- */
.svc-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
}

.svc-tab {
  background-color: #f7f4ee; /* cream-100 */
  cursor: pointer;
}

.svc-tab:hover {
  background-color: rgb(255 255 255 / 0.6);
}

.svc-bar {
  background-color: transparent;
}

.svc-tab-icon,
.svc-tab-label {
  color: #404040; /* charcoal-400 */
}

.svc-tab:hover .svc-tab-icon,
.svc-tab:hover .svc-tab-label {
  color: #1a1a1a; /* charcoal-500 */
}

.svc-panel {
  display: none;
}

#svc-r0:checked ~ .svc-tablist label[for="svc-r0"],
#svc-r1:checked ~ .svc-tablist label[for="svc-r1"],
#svc-r2:checked ~ .svc-tablist label[for="svc-r2"],
#svc-r3:checked ~ .svc-tablist label[for="svc-r3"] {
  background-color: #fff;
}

#svc-r0:checked ~ .svc-tablist label[for="svc-r0"] .svc-bar,
#svc-r1:checked ~ .svc-tablist label[for="svc-r1"] .svc-bar,
#svc-r2:checked ~ .svc-tablist label[for="svc-r2"] .svc-bar,
#svc-r3:checked ~ .svc-tablist label[for="svc-r3"] .svc-bar {
  background-color: #ef4000;
}

#svc-r0:checked ~ .svc-tablist label[for="svc-r0"] .svc-tab-icon,
#svc-r1:checked ~ .svc-tablist label[for="svc-r1"] .svc-tab-icon,
#svc-r2:checked ~ .svc-tablist label[for="svc-r2"] .svc-tab-icon,
#svc-r3:checked ~ .svc-tablist label[for="svc-r3"] .svc-tab-icon {
  color: #ef4000;
}

#svc-r0:checked ~ .svc-tablist label[for="svc-r0"] .svc-tab-label,
#svc-r1:checked ~ .svc-tablist label[for="svc-r1"] .svc-tab-label,
#svc-r2:checked ~ .svc-tablist label[for="svc-r2"] .svc-tab-label,
#svc-r3:checked ~ .svc-tablist label[for="svc-r3"] .svc-tab-label {
  color: #1a1a1a;
}

#svc-r0:checked ~ #svc-p0,
#svc-r1:checked ~ #svc-p1,
#svc-r2:checked ~ #svc-p2,
#svc-r3:checked ~ #svc-p3 {
  display: block;
}

#svc-r0:focus-visible ~ .svc-tablist label[for="svc-r0"],
#svc-r1:focus-visible ~ .svc-tablist label[for="svc-r1"],
#svc-r2:focus-visible ~ .svc-tablist label[for="svc-r2"],
#svc-r3:focus-visible ~ .svc-tablist label[for="svc-r3"] {
  outline: 2px solid #ef4000;
  outline-offset: -2px;
}

/* --------------------------------------------------------------------------
   Accordions — <details>/<summary> in place of the React disclosures
   -------------------------------------------------------------------------- */
.acc > summary {
  cursor: pointer;
  list-style: none;
}

.acc > summary::-webkit-details-marker {
  display: none;
}

.acc > summary::marker {
  content: "";
}

.acc > summary:focus-visible {
  outline: 2px solid #ef4000;
  outline-offset: 2px;
}

/* FAQ list */
.faq-icon {
  border-color: rgb(214 214 214 / 0.6); /* charcoal-100/60 */
  color: #404040;
}

.faq-item > summary:hover .faq-icon {
  border-color: #ef4000;
  color: #ef4000;
}

.faq-item[open] .faq-icon {
  transform: rotate(45deg);
  border-color: #6b6b6b; /* charcoal-300 */
  color: #1a1a1a;
}

.faq-item[open] .faq-panel {
  padding-bottom: 1.75rem;
}

/* Service sub-list */
.svc-acc-label {
  color: #1a1a1a;
}

.svc-acc-icon {
  color: #6b6b6b;
}

.svc-acc > summary:hover .svc-acc-label,
.svc-acc[open] .svc-acc-label {
  color: #ef4000;
}

.svc-acc > summary:hover .svc-acc-icon {
  color: #ef4000;
}

.svc-acc[open] .svc-acc-icon {
  color: #ef4000;
  transform: rotate(45deg);
}

/* Animate the open/close where the browser can interpolate to auto height. */
@supports selector(::details-content) {
  @media (prefers-reduced-motion: no-preference) {
    :root {
      interpolate-size: allow-keywords;
    }

    .acc::details-content {
      block-size: 0;
      overflow: clip;
      opacity: 0;
      transition:
        block-size 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94),
        opacity 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94),
        content-visibility 0.4s allow-discrete;
    }

    .acc[open]::details-content {
      block-size: auto;
      opacity: 1;
    }
  }
}

/* --------------------------------------------------------------------------
   Mobile navigation — checkbox drawer
   -------------------------------------------------------------------------- */
.nav-toggle {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
}

#mobile-menu {
  visibility: hidden;
}

#nav-toggle:checked ~ #mobile-menu {
  visibility: visible;
  --tw-translate-x: 0px;
}

#nav-toggle:checked ~ .nav-scrim {
  opacity: 1;
  pointer-events: auto;
}

#nav-toggle:focus-visible ~ header .nav-burger {
  outline: 2px solid #ef4000;
  outline-offset: 2px;
}

.nav-burger,
.nav-close,
.nav-scrim {
  cursor: pointer;
}

/* Staggered entrance for the drawer items, as in the original. */
#nav-toggle:checked ~ #mobile-menu .nav-item,
#nav-toggle:checked ~ #mobile-menu .nav-drawer-footer {
  opacity: 1;
  --tw-translate-x: 0px;
  --tw-translate-y: 0px;
}

#mobile-menu .nav-item:nth-child(1) {
  transition-delay: 120ms;
}

#mobile-menu .nav-item:nth-child(2) {
  transition-delay: 180ms;
}

#mobile-menu .nav-item:nth-child(3) {
  transition-delay: 240ms;
}

#mobile-menu .nav-drawer-footer {
  transition-delay: 300ms;
}

body:has(#nav-toggle:checked) {
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   Service area map
   The map itself is drawn by assets/map.js through the Google Maps JS API, the
   same as production, so it needs no styling here. Google's own controls and
   attribution come with it. These rules only cover the placeholder that sits in
   the box until the map paints.
   -------------------------------------------------------------------------- */
[data-map-placeholder] {
  pointer-events: none;
}

/* The <noscript> fallback shows a still of the same view. It carries Google's
   attribution as markup, since the still itself was captured without it. */
.map-noscript-still {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.map-attribution-logo {
  position: absolute;
  bottom: 0;
  left: 5px;
  line-height: 0;
}

.map-attribution-logo img {
  width: 66px;
  height: 26px;
}

.map-attribution-text {
  position: absolute;
  right: 0;
  bottom: 0;
  display: flex;
  gap: 1px;
  font: 11px / 14px Roboto, Arial, sans-serif;
  color: #1a1a1a;
  white-space: nowrap;
}

.map-attribution-text > * {
  padding: 0 5px;
  background-color: rgb(255 255 255 / 0.7);
  color: inherit;
  text-decoration: none;
}

/* --------------------------------------------------------------------------
   Our Work carousel
   Native scroll-snap does the scrolling; the dots and arrows are links, so
   they work without scripting. :target picks out the current card.
   -------------------------------------------------------------------------- */
.work-scroller {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
/* No scroll-behavior: smooth here. Scroll-snap nudges this rail during load,
   and an animated scroll makes Chrome finalise Largest Contentful Paint before
   anything has painted — the page then reports no LCP candidate at all, which
   Lighthouse scores as a failure. Clicks still scroll smoothly: enhance.js
   passes behavior: 'smooth' per click, and without scripting the dot links jump
   straight to the card. */

.work-scroller::-webkit-scrollbar {
  display: none;
}

/* Dots — card 1 reads as current until another card is targeted. */
.work-dot {
  width: 1.25rem;
  background-color: #a3a3a3; /* charcoal-200 */
}

.work-dot:hover {
  background-color: #404040; /* charcoal-400 */
}

.work-dot-1 {
  width: 2.5rem;
  background-color: #1a1a1a;
}

body:has(.work-scroller > figure:target) .work-dot-1 {
  width: 1.25rem;
  background-color: #a3a3a3;
}

body:has(#work-1:target) .work-dot-1,
body:has(#work-2:target) .work-dot-2,
body:has(#work-3:target) .work-dot-3,
body:has(#work-4:target) .work-dot-4,
body:has(#work-5:target) .work-dot-5,
body:has(#work-6:target) .work-dot-6 {
  width: 2.5rem;
  background-color: #1a1a1a;
}

/* Arrows — one prev/next pair per card, only the current pair is shown. */
.work-arrow {
  display: none;
}

.work-prev-1,
.work-next-1 {
  display: inline-flex;
}

body:has(.work-scroller > figure:target) :is(.work-prev-1, .work-next-1) {
  display: none;
}

body:has(#work-1:target) :is(.work-prev-1, .work-next-1),
body:has(#work-2:target) :is(.work-prev-2, .work-next-2),
body:has(#work-3:target) :is(.work-prev-3, .work-next-3),
body:has(#work-4:target) :is(.work-prev-4, .work-next-4),
body:has(#work-5:target) :is(.work-prev-5, .work-next-5),
body:has(#work-6:target) :is(.work-prev-6, .work-next-6) {
  display: inline-flex;
}

.work-arrow-off {
  opacity: 0.3;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Section anchors
   The original scrolled sections flush to the top of the viewport, under the
   fixed header; match that rather than inventing an offset.
   -------------------------------------------------------------------------- */

