/* Static replacements for behaviour the dc-runtime used to do in React.
   The source Nav branched on window.innerWidth < 980 in JS, so a pre-render at a
   single viewport would freeze one branch and lose the other. The build instead
   bakes BOTH bars into the DOM and switches them here, in CSS. */

.kgd-desktop-bar { display: block; }
.kgd-mobile-bar  { display: none; }

@media (max-width: 979px) {
  .kgd-desktop-bar { display: none; }
  .kgd-mobile-bar  { display: block; }
}

/* Panels are in the DOM but closed until scripted open. Using [hidden] keeps them
   out of the a11y tree and out of tab order with no JS required for the closed state. */
.kgd-nav [hidden] { display: none !important; }

/* The original marked the current page with a small orange dot appended inside the
   link. aria-current carries the same meaning to assistive tech, and ::after draws
   the dot — so the marker survives without per-page nav variants.

   aria-current is set in the mobile menu too (screen readers benefit either way), but
   the dot is drawn only in the desktop bar, which is the only place the design had one. */
.kgd-desktop-bar [aria-current="page"]::after,
.kgd-desktop-bar [aria-current="true"]::after {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #E8501F;
  display: inline-block;
  flex: 0 0 auto;
}

/* Photos that have not been shot yet. The build emits a real <img> for every slot;
   until a file is dropped in, this keeps the layout intact instead of showing a
   broken-image glyph. */
.kgd-img { display: block; width: 100%; height: 100%; object-fit: cover; }

.kgd-img-pending {
  background: repeating-linear-gradient(45deg, #EDF1F5, #EDF1F5 12px, #E4EAF0 12px, #E4EAF0 24px);
}

.kgd-map { display: block; width: 100%; height: 100%; border: 0; }

/* Respect users who have asked for less motion — the hero parallax is decorative. */
@media (prefers-reduced-motion: reduce) {
  [data-kgd-parallax] { transform: none !important; }
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
}

/* Keyboard focus was never styled in the source; without it a keyboard user cannot
   see where they are. */
.kgd-nav a:focus-visible,
.kgd-nav button:focus-visible {
  outline: 2px solid #E8501F;
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Tap targets.

   The stacked link columns (.kgd-linkcol — the footer's four, and the /sitemap page's
   five) render 18px tall, and the footer's legal row 16px. That is under the 24x24 CSS px
   WCAG 2.5.8 asks for, and far under the ~44px a thumb actually wants. Grow the hit area
   with padding, never with font-size, so the type is untouched.

   Those columns' inline `gap` is now 0 (see Footer.dc.html / Sitemap.dc.html), so this
   padding supplies the spacing rather than adding to it — the desktop rhythm comes out
   the same as the original 18px link + 9px gap.

   Inline links inside prose ("...a broken <a>spring</a>...") are deliberately NOT padded.
   WCAG 2.5.8 exempts targets in a sentence, and padding them would wreck the line spacing.

   These rules deliberately carry no !important. The whole design is inline-styled, and
   inline styles outrank a stylesheet — so any link that already sets its own padding
   (the "Call Now" pill, the mobile menu rows) keeps it and is skipped automatically.
   --------------------------------------------------------------------------- */
.kgd-linkcol a {
  padding-block: 4.5px; /* 18 -> 27px */
}

.kgd-flegal a,
.kgd-fcontact a,
a[href^="mailto:"],
a[href^="tel:"],
nav[aria-label="Breadcrumb"] a {
  padding-block: 4px;
}

@media (max-width: 979px) {
  .kgd-linkcol a {
    padding-block: 13px; /* 18 -> 44px, a real thumb target */
  }

  .kgd-flegal a,
  .kgd-fcontact a,
  a[href^="mailto:"],
  a[href^="tel:"],
  nav[aria-label="Breadcrumb"] a {
    padding-block: 10px;
  }

  /* The legal links sit in a wrap row; once each is taller they need room to breathe. */
  .kgd-flegal {
    gap: 4px 22px;
  }
}

/* ---------------------------------------------------------------------------
   Horizontal overflow.

   The site was authored without `box-sizing: border-box`, so padding ADDS to a
   declared width. The footer's two cards were min-width:290px + 28px padding on each
   side = 346px of box in the 280px a 320px phone actually offers — so every page on
   the site scrolled sideways on a small phone. min() lets the card fall below its
   preferred 290px when the screen cannot afford it; border-box makes the padding
   count inside that width rather than on top of it.

   Scoped to these cards on purpose. Flipping box-sizing globally would resize the 28
   other elements that combine an explicit width with padding, in a design authored
   for content-box.
   --------------------------------------------------------------------------- */
.kgd-fcard {
  box-sizing: border-box;
  min-width: min(290px, 100%);
}

/* Deliberately NOT adding `overflow-x: clip` to html/body as a catch-all. It would hide
   a sideways-scrolling page rather than fix it, and it would blind build/responsive.mjs,
   which detects overflow by measuring scrollWidth. Fix the cause; keep the detector honest. */

/* ---------------------------------------------------------------------------
   Hero floating cards — the same pre-render freeze the nav had.

   The three decorative cards over the hero (job card, tech note, 24/7 pill) were gated in
   React on `showFloaters = showFloatingCards && !isMobile`, where Home.dc.html:399 defines
   isMobile as `window.innerWidth < 1280`. So the design only ever showed them at >= 1280px.

   We pre-render at exactly 1280 — and `1280 < 1280` is false — so the runtime handed us the
   floaters-visible branch and baked it into the static HTML for EVERY width. On a phone all
   three then rendered at once, and the job card and the 24/7 pill (both ~250px, both pinned
   to the bottom) landed on top of each other.

   This restores the original rule in CSS, at the breakpoint the source actually specified.
   --------------------------------------------------------------------------- */
@media (max-width: 1279px) {
  .kgd-floater {
    /* !important is load-bearing: the 24/7 pill sets `display:inline-flex` in its inline
       style attribute, and an inline style outranks any stylesheet selector. Without this
       the other two cards hide and the pill alone stays behind. */
    display: none !important;
  }
}

/* ---------------------------------------------------------------------------
   Services dropdown (v4).

   TWO constraints shaped this block, and they pull in the same direction.

   1. build/verify.mjs asserts that every attribute inside .kgd-nav is on an allowlist
      (class/style/href/src/alt/... + aria-* + data-*). That check exists to catch a
      quote-escaping bug that once shredded the nav's style attributes. An inline <svg>
      carries viewBox / d / stroke / stroke-width — none of which are on that list — so
      six inline icons would fail the build's own verifier on all 16 pages. The vectors
      therefore live HERE, as mask-image data URIs, and the markup carries only a class.

   2. style-hover="..." compiles to a rule on the hovered element itself. It cannot reach
      a DESCENDANT, so the row-hover states (tile turns orange, icon turns white, title
      turns orange) could not be expressed inline even if we wanted them there.

   Using `mask` rather than `background-image` is what makes the hover recolour a single
   property: the SVG supplies the SHAPE, `background-color` supplies the ink.

   !important is load-bearing on exactly the properties the markup also sets inline (the
   tile's background). The site is inline-styled and an inline style beats any selector.
   --------------------------------------------------------------------------- */

.kgd-svc-ico::before {
  content: "";
  display: block;
  width: 19px;
  height: 19px;
  background-color: #16334F;
  transition: background-color 0.16s ease;
  -webkit-mask: var(--kgd-ico) center / contain no-repeat;
  mask: var(--kgd-ico) center / contain no-repeat;
}
.kgd-svc-ico { transition: background 0.16s ease, box-shadow 0.16s ease; }
.kgd-svc-t   { transition: color 0.16s ease; }

/* 24/7 Emergency is the loudest promise this company makes, so its tile is already warm
   at rest — the one row in the grid that carries colour before you touch it. */
.kgd-svc-urgent .kgd-svc-ico::before { background-color: #E8501F; }

/* Row hover. The site's interaction language is orange, not grey. */
.kgd-svc:hover .kgd-svc-ico {
  background: #E8501F !important;
  box-shadow: 0 10px 26px rgba(232, 80, 31, 0.28); /* the orange-glow token */
}
.kgd-svc:hover .kgd-svc-ico::before { background-color: #fff; }
.kgd-svc:hover .kgd-svc-t { color: #E8501F !important; }

.kgd-ico-repair     { --kgd-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z'/%3E%3C/svg%3E"); }
.kgd-ico-spring     { --kgd-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2 12h2l1.5-7 3 14 3-14 3 14 3-14 1.5 7h3'/%3E%3C/svg%3E"); }
.kgd-ico-install    { --kgd-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 21h19'/%3E%3Cpath d='M3.5 21V9.8L12 3.5l8.5 6.3V21'/%3E%3Cpath d='M8 21v-6.5h8V21M8 17.7h8'/%3E%3C/svg%3E"); }
.kgd-ico-opener     { --kgd-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.9 19.1C1 15.2 1 8.8 4.9 4.9M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5M19.1 4.9C23 8.8 23 15.2 19.1 19.1'/%3E%3Ccircle cx='12' cy='12' r='2'/%3E%3C/svg%3E"); }
.kgd-ico-emergency  { --kgd-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z'/%3E%3C/svg%3E"); }
.kgd-ico-commercial { --kgd-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.5 21h21'/%3E%3Cpath d='M3 21V6.5h18V21'/%3E%3Cpath d='M6 21v-6h4.5v6M13.5 21v-6H18v6'/%3E%3C/svg%3E"); }

/* The rail's call pill gets the same treatment — a handset, drawn in CSS. */
.kgd-callpill::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  background-color: #fff;
  -webkit-mask: var(--kgd-phone) center / contain no-repeat;
  mask: var(--kgd-phone) center / contain no-repeat;
  --kgd-phone: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.36 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.9.34 1.85.57 2.81.7A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E");
}

/* "View all services →" — the arrow steps forward rather than sitting there. */
.kgd-viewall-a { display: inline-block; transition: transform 0.16s ease; }
.kgd-viewall:hover .kgd-viewall-a { transform: translateX(3px); }

/* The beak. This is the fix for the panel reading as detached from its trigger: a 12px
   square rotated 45°, centred on the button. The panel's left edge is now the button's
   left edge, and the button is 96.4px wide, so its centre is 48.2px in — the beak's 12px
   box starts at 42px. It borrows the panel's own border on the two edges that show. */
.kgd-beak {
  position: absolute;
  top: -7px;
  left: 42px;
  width: 12px;
  height: 12px;
  background: #fff;
  border-left: 1px solid rgba(22, 51, 79, 0.07);
  border-top: 1px solid rgba(22, 51, 79, 0.07);
  border-top-left-radius: 3px;
  transform: rotate(45deg);
}

/* The trigger stays lit — in orange, not grey — for as long as its panel is open, and the
   chevron flips. site.js already maintains aria-expanded, so this needs no new state. */
.kgd-nav [data-kgd="services-btn"] .kgd-chev {
  display: inline-block;
  transition: transform 0.18s ease;
}
.kgd-nav [data-kgd="services-btn"][aria-expanded="true"] {
  background: #FDF0E9 !important;
  color: #E8501F !important;
}
.kgd-nav [data-kgd="services-btn"][aria-expanded="true"] .kgd-chev {
  transform: rotate(180deg);
  opacity: 1;
}

/* "Techs on call right now" (desktop rail) and "On call now" (mobile). A 2s breath, not a
   strobe — and the prefers-reduced-motion block above already stops it dead. */
.kgd-live {
  position: relative;
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #E8501F;
  display: inline-block;
}
.kgd-live::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #E8501F;
  animation: kgd-ping 2s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes kgd-ping {
  0%   { transform: scale(1);   opacity: 0.55; }
  70%  { transform: scale(2.6); opacity: 0; }
  100% { transform: scale(2.6); opacity: 0; }
}

/* The panel is display:none until site.js unhides it, so showing it restarts this. */
.kgd-svcpanel {
  animation: kgd-drop 0.18s cubic-bezier(0.2, 0.8, 0.25, 1) both;
  transform-origin: 48px -7px; /* the beak — it grows out of the button */
}
@keyframes kgd-drop {
  from { opacity: 0; transform: translateY(-6px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}
