/* ==========================================================================
   Knepper Contracting — css/current.css     "LIVE CURRENT" (build 07b)

   Ajay, 16 Sep 2026, after build 07a missed the point:
     "By the neon electricity I'm talking about, the lines that are going
      through the MIDDLE of the page. They are blue. They are green. There are
      some that are yellow, red. And it goes through the pages. Please make
      that neon. Make it like electricity. Make it flow through the website."
     "There's no hover effects on the website. The website is extremely boring."

   07a put a 34px conduit against the left EDGE of the viewport. Wrong place,
   too thin, one colour at a time. This replaces it.

   THE LINE now runs through the body of the page: it is drawn over the whole
   height of <main>, weaving left to right between the sections, behind the
   words. It is stroked with ONE gradient that runs blue -> green -> yellow ->
   red down its whole length, so every colour is on screen at once, and it is
   lit like a neon tube (a wide soft halo under a hot core). Charge rips along
   it continuously, plus a faster spark on top, so it reads as a live circuit
   rather than a decorative squiggle.

   THE HOVERS are the second half of this file: a single system applied to
   every card, figure, link, button, row and tile on the site, so nothing on
   the page is dead to the pointer.

   Everything animates transform / opacity / stroke-dashoffset / filter only.
   prefers-reduced-motion stops all travel and leaves the tube lit. With JS off
   nothing here paints — js/current.js adds .has-current — so no empty gutters.
   ========================================================================== */

:root {
  --cur: var(--lime);
  --cur-soft: rgba(168, 255, 62, .5);
  --cur-dim: rgba(168, 255, 62, .16);
  --volt-speed: 2.4s;      /* charge travel */
  --volt-spark: 1.1s;      /* the fast spark on top */
}

/* section accents still tint the per-section furniture (taps, edges, hovers) */
[data-accent^="lime"]   { --cur: var(--lime);   --cur-soft: rgba(168,255,62,.5);  --cur-dim: rgba(168,255,62,.16) }
[data-accent^="cyan"]   { --cur: var(--cyan);   --cur-soft: rgba(0,229,255,.5);   --cur-dim: rgba(0,229,255,.16) }
[data-accent^="gold"]   { --cur: var(--gold);   --cur-soft: rgba(255,197,62,.5);  --cur-dim: rgba(255,197,62,.16) }
[data-accent^="violet"] { --cur: var(--violet); --cur-soft: rgba(179,107,255,.5); --cur-dim: rgba(179,107,255,.16) }
[data-accent^="amber"]  { --cur: var(--coral);  --cur-soft: rgba(255,107,74,.5);  --cur-dim: rgba(255,107,74,.16) }
[data-accent^="green"]  { --cur: var(--mint);   --cur-soft: rgba(74,222,155,.5);  --cur-dim: rgba(74,222,155,.16) }
[data-cur="1"] { --cur: var(--cyan);   --cur-soft: rgba(0,229,255,.5);   --cur-dim: rgba(0,229,255,.16) }
[data-cur="2"] { --cur: var(--mint);   --cur-soft: rgba(74,222,155,.5);  --cur-dim: rgba(74,222,155,.16) }
[data-cur="3"] { --cur: var(--lime);   --cur-soft: rgba(168,255,62,.5);  --cur-dim: rgba(168,255,62,.16) }
[data-cur="4"] { --cur: var(--gold);   --cur-soft: rgba(255,197,62,.5);  --cur-dim: rgba(255,197,62,.16) }
[data-cur="5"] { --cur: var(--coral);  --cur-soft: rgba(255,107,74,.5);  --cur-dim: rgba(255,107,74,.16) }
[data-cur="6"] { --cur: var(--violet); --cur-soft: rgba(179,107,255,.5); --cur-dim: rgba(179,107,255,.16) }

/* ══════════════════════════════════════════════════════════════════════════
   1 · THE LINE — a neon tube running through the page
   ══════════════════════════════════════════════════════════════════════════ */
main { position: relative }

/* The tube layer must stay absolutely positioned, and it has to out-specify
   the `main > *` rule below — when that rule won, .volt became position:
   relative, the SVG took its aspect-ratio height in flow, main grew, the
   ResizeObserver rebuilt at the new height, and the page ran away to 264,000px.
   Hence the `main > .volt` selector and the :not() on its neighbour. */
html.has-current main > .volt {
  position: absolute; inset: 0;
  pointer-events: none;
  display: block; overflow: visible;
  height: auto;

  /* Ajay, 16 Sep: "it should be connecting from section to section, why do
     some sections have it and others don't?"
     Because the tube was BEHIND the sections (z-index 0), so any section with
     its own background painted straight over it — 4 of 14 on /about and 8 of
     16 on /services, which is exactly the on-again-off-again he saw. The tube
     now sits ABOVE the sections and blends in screen mode, so it adds light
     over whatever is underneath and runs unbroken from the first section to
     the last. Screen only ever brightens, so nothing underneath is obscured
     and the copy stays readable. */
  z-index: 5;
  mix-blend-mode: screen;
}
.volt { display: none }

/* sections keep a stacking position so their own internals still layer, but
   they no longer out-paint the tube */
html.has-current main > *:not(.volt) { position: relative; z-index: 1 }

.volt__svg { width: 100%; height: 100%; display: block; overflow: visible }

/* the dark tube the light lives in */
.volt__pipe {
  fill: none; stroke: rgba(238, 242, 255, .07);
  stroke-width: 9; stroke-linecap: round; stroke-linejoin: round;
}

/* the halo: the same path, fat and blurred, in the gradient */
.volt__halo {
  fill: none; stroke: url(#voltGrad);
  stroke-width: 14; stroke-linecap: round; stroke-linejoin: round;
  opacity: .22; filter: blur(9px);
}

/* the glass: a continuous lit tube at low power */
.volt__glass {
  fill: none; stroke: url(#voltGrad);
  stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round;
  opacity: .45;
}

/* the charge: long bright segments ripping along the tube, forever */
.volt__flow {
  fill: none; stroke: url(#voltGrad);
  stroke-width: 5; stroke-linecap: round; stroke-linejoin: round;
  opacity: .95;
  stroke-dasharray: 120 520;
  animation: volt-run var(--volt-speed) linear infinite;
}
@keyframes volt-run { to { stroke-dashoffset: -640 } }

/* a hot white core inside the charge, slightly shorter, so it looks like
   current rather than a coloured worm */
.volt__core {
  fill: none; stroke: #FFFFFF;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  opacity: .9;
  stroke-dasharray: 70 570;
  animation: volt-run var(--volt-speed) linear infinite;
}

/* a fast spark that overtakes the charge every second or so */
.volt__spark {
  fill: none; stroke: #FFFFFF;
  stroke-width: 2.5; stroke-linecap: round;
  opacity: .75;
  stroke-dasharray: 8 1200;
  filter: drop-shadow(0 0 7px rgba(255, 255, 255, .95));
  animation: volt-spark var(--volt-spark) linear infinite;
}
@keyframes volt-spark { to { stroke-dashoffset: -1208 } }

/* taps where the tube passes a section */
.volt__tap {
  fill: var(--ink); stroke: rgba(238, 242, 255, .35); stroke-width: 1.5;
  transition: fill .4s var(--ease), stroke .4s var(--ease);
}
.volt__tap.is-live { fill: var(--cur); stroke: var(--cur); filter: drop-shadow(0 0 9px var(--cur-soft)) }

/* ══════════════════════════════════════════════════════════════════════════
   2 · SECTION RESPONSE — the section the line is passing lights up
   ══════════════════════════════════════════════════════════════════════════ */
html.has-current main .lsec, html.has-current main .sec { position: relative }
html.has-current main .lsec::before, html.has-current main .sec::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--cur), transparent);
  opacity: 0; transition: opacity .7s var(--ease);
  pointer-events: none; z-index: 2;
}
html.has-current main .lsec.is-live::before,
html.has-current main .sec.is-live::before { opacity: .75 }

/* hairline rules carry a travelling sheen */
.curline, .lsec > .wrap > hr, .sec > .wrap > hr {
  position: relative; height: 1px; border: 0;
  background: rgba(238, 242, 255, .12); overflow: hidden;
}
.curline::after, .lsec > .wrap > hr::after, .sec > .wrap > hr::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--cur), transparent);
  transform: translateX(-100%); animation: cur-sweep 4s linear infinite;
}
@keyframes cur-sweep { to { transform: translateX(100%) } }

/* ══════════════════════════════════════════════════════════════════════════
   3 · HOVERS — nothing on this site should be dead to the pointer
   ══════════════════════════════════════════════════════════════════════════ */
@media (hover: hover) and (pointer: fine) {

  /* --- panels, cards, tiles, rows: lift, edge lights, inner glow --------- */
  html.has-current .card, html.has-current .icard, html.has-current .liftcard,
  html.has-current .glass, html.has-current .stop, html.has-current .tile,
  html.has-current .shot, html.has-current .band, html.has-current .split__media,
  html.has-current .fan > *, html.has-current .town, html.has-current .spec li,
  html.has-current .ba figure, html.has-current .roles li, html.has-current figure[data-lightbox] {
    transition: transform .3s var(--ease), box-shadow .3s var(--ease),
                border-color .3s var(--ease), filter .3s var(--ease);
  }
  html.has-current .card:hover, html.has-current .icard:hover, html.has-current .liftcard:hover,
  html.has-current .glass:hover, html.has-current .stop:hover, html.has-current .tile:hover,
  html.has-current .shot:hover, html.has-current .band:hover, html.has-current .split__media:hover,
  html.has-current .fan > *:hover, html.has-current .town:hover, html.has-current .spec li:hover,
  html.has-current .ba figure:hover, html.has-current .roles li:hover,
  html.has-current figure[data-lightbox]:hover {
    transform: translateY(-5px);
    border-color: var(--cur);
    box-shadow: 0 18px 44px -22px rgba(0, 0, 0, .9),
                0 0 0 1px var(--cur-dim),
                0 0 30px -6px var(--cur-dim);
  }

  /* the photo inside a frame pushes in, the frame never moves */
  html.has-current .shot, html.has-current figure[data-lightbox],
  html.has-current .split__media, html.has-current .ba figure { overflow: hidden }
  html.has-current .shot img, html.has-current figure[data-lightbox] img,
  html.has-current .split__media img, html.has-current .ba figure img {
    transition: transform .55s var(--ease), filter .55s var(--ease);
  }
  html.has-current .shot:hover img, html.has-current figure[data-lightbox]:hover img,
  html.has-current .split__media:hover img, html.has-current .ba figure:hover img {
    transform: scale(1.055); filter: saturate(1.12) brightness(1.06);
  }

  /* --- buttons: the fill wipes in from the left ------------------------- */
  html.has-current .btn {
    position: relative; overflow: hidden; isolation: isolate;
    transition: transform .22s var(--ease), box-shadow .3s var(--ease),
                color .25s var(--ease), border-color .25s var(--ease);
  }
  html.has-current .btn::after {
    content: ''; position: absolute; inset: 0; z-index: -1;
    background: var(--cur); transform: scaleX(0); transform-origin: left center;
    transition: transform .34s var(--ease);
  }
  html.has-current .btn:hover, html.has-current .btn:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 12px 30px -14px var(--cur-soft), 0 0 22px -6px var(--cur-dim);
  }
  html.has-current .btn--wire:hover::after,
  html.has-current .btn--wire:focus-visible::after { transform: scaleX(1) }
  html.has-current .btn--wire:hover, html.has-current .btn--wire:focus-visible {
    color: var(--ink); border-color: var(--cur);
  }
  /* solid buttons deepen and throw light rather than swapping colour */
  html.has-current .btn--lime:hover, html.has-current .btn--violet:hover,
  html.has-current .btn--lime:focus-visible, html.has-current .btn--violet:focus-visible {
    filter: brightness(1.12) saturate(1.1);
    box-shadow: 0 14px 34px -14px rgba(168, 255, 62, .55), 0 0 30px -8px rgba(168, 255, 62, .4);
  }

  /* --- in-copy links: an underline that grows from the left ------------- */
  html.has-current main p a:not(.btn),
  html.has-current main li a:not(.btn),
  html.has-current .ulink {
    position: relative; text-decoration: none;
    background-image: linear-gradient(90deg, var(--cur), var(--cur));
    background-repeat: no-repeat; background-position: 0 100%;
    background-size: 0% 2px;
    transition: background-size .32s var(--ease), color .25s var(--ease);
    padding-bottom: 2px;
  }
  html.has-current main p a:not(.btn):hover,
  html.has-current main li a:not(.btn):hover,
  html.has-current .ulink:hover,
  html.has-current main p a:not(.btn):focus-visible,
  html.has-current main li a:not(.btn):focus-visible {
    background-size: 100% 2px; color: var(--cur);
  }

  /* --- nav: the current flows under the item ---------------------------- */
  html.has-current .hdr__nav a { position: relative; transition: color .25s var(--ease) }
  html.has-current .hdr__nav a::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px;
    background: var(--lime); transform: scaleX(0); transform-origin: left center;
    transition: transform .3s var(--ease);
  }
  html.has-current .hdr__nav a:hover::after,
  html.has-current .hdr__nav a:focus-visible::after { transform: scaleX(1) }
  html.has-current .hdr__nav a:hover { color: var(--lime) }

  /* --- headings answer the pointer with a light sweep ------------------- */
  html.has-current .h2, html.has-current .dh { transition: filter .35s var(--ease) }
  html.has-current .lsec:hover .h2, html.has-current .sec:hover .dh {
    filter: drop-shadow(0 0 18px var(--cur-dim));
  }

  /* --- arrows travel ---------------------------------------------------- */
  html.has-current .arrow { display: inline-block; transition: transform .28s var(--ease) }
  html.has-current a:hover .arrow, html.has-current button:hover .arrow { transform: translateX(5px) }

  /* --- the dock buttons pulse their own colour -------------------------- */
  html.has-current .dock a { transition: transform .25s var(--ease), box-shadow .3s var(--ease) }
  html.has-current .dock a:hover { transform: translateX(-4px); box-shadow: 0 0 26px -6px var(--cur-soft) }
}

/* touch devices get the resting state, never a stuck hover */
@media (hover: none) {
  html.has-current .card, html.has-current .icard, html.has-current .liftcard { transform: none }
}

/* ══════════════════════════════════════════════════════════════════════════
   4 · the homepage cable takes the same travelling charge
   ══════════════════════════════════════════════════════════════════════════ */
.run__charge {
  fill: none; stroke: var(--lime); stroke-width: 2.5; vector-effect: non-scaling-stroke;
  stroke-linecap: round; stroke-dasharray: 26 92; opacity: .9;
  filter: drop-shadow(0 0 7px rgba(168, 255, 62, .8));
  animation: volt-run var(--volt-speed) linear infinite;
}

/* ══════════════════════════════════════════════════════════════════════════
   5 · narrow screens and reduced motion
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 760px) {
  .volt__halo { stroke-width: 10; opacity: .18 }
  .volt__flow { stroke-width: 3.5 }
  .volt__pipe { stroke-width: 6 }
  .volt__tap { display: none }
}

@media (prefers-reduced-motion: reduce) {
  .volt__flow, .volt__core, .volt__spark, .run__charge,
  .curline::after, .lsec > .wrap > hr::after, .sec > .wrap > hr::after { animation: none }
  .volt__flow { stroke-dasharray: none; opacity: .5 }
  .volt__core, .volt__spark { display: none }
  .volt__glass { opacity: .7 }
  .curline::after, .lsec > .wrap > hr::after, .sec > .wrap > hr::after { transform: none; opacity: .45 }
  html.has-current .card, html.has-current .icard, html.has-current .liftcard,
  html.has-current .btn, html.has-current .shot img { transition: none }
}

/* ══════════════════════════════════════════════════════════════════════════
   6 · THE SERVICES DROP-DOWN (Ajay, 16 Sep: "add a drop down to services")
   The trigger is still a real link to /services, so it works with JS off and
   for anyone who taps straight through. js/site.js only adds open/close.
   ══════════════════════════════════════════════════════════════════════════ */
.navdrop { position: relative; display: inline-flex }
.navdrop__t { display: inline-flex; align-items: center; gap: 7px }
.navdrop__c {
  width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid currentColor; opacity: .7; transition: transform .25s var(--ease);
}
.navdrop.is-open .navdrop__c { transform: rotate(180deg) }

.navdrop__p {
  position: absolute; top: calc(100% + 14px); left: 50%; transform: translateX(-50%);
  width: min(94vw, 420px); z-index: 90;
  background: #0C1236; border: 1px solid rgba(238, 242, 255, .14); border-radius: 10px;
  box-shadow: 0 32px 70px -28px rgba(0, 0, 0, .95), 0 0 0 1px rgba(168, 255, 62, .08);
  padding: 8px; display: grid; gap: 2px;
}
.navdrop__p[hidden] { display: none }
/* a lit edge along the top, the same current as the rest of the site */
.navdrop__p::before {
  content: ''; position: absolute; left: 14px; right: 14px; top: 0; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--cyan), var(--mint), var(--lime), var(--gold), var(--coral));
}
.navdrop__p a {
  display: grid; gap: 2px; padding: 10px 12px; border-radius: 7px;
  text-decoration: none; color: var(--on); border: 1px solid transparent;
  transition: background .2s var(--ease), border-color .2s var(--ease), transform .2s var(--ease);
}
.nd__k { font-family: var(--display); font-weight: 700; font-size: 16px; letter-spacing: .01em; text-transform: uppercase }
.nd__s { font-size: 13px; color: var(--on-faint); line-height: 1.45 }
.navdrop__p a:hover, .navdrop__p a:focus-visible {
  background: rgba(168, 255, 62, .08); border-color: rgba(168, 255, 62, .35); transform: translateX(3px);
}
.navdrop__p a:hover .nd__k, .navdrop__p a:focus-visible .nd__k { color: var(--lime) }
.nd__all {
  margin-top: 4px; border-top: 1px solid rgba(238, 242, 255, .1) !important;
  border-radius: 0 0 7px 7px !important;
  font-family: var(--mono); font-size: 12.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--lime) !important;
}

/* on a phone the nav is a stacked sheet, so the panel sits in flow */
@media (max-width: 900px) {
  .navdrop { display: block; width: 100% }
  .navdrop__p {
    position: static; transform: none; width: 100%; margin-top: 8px;
    box-shadow: none; background: rgba(238, 242, 255, .04);
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   7 · #services — the panel schedule on the homepage
   A directory card off a panel door: numbered circuits, one per service, each
   row taking its own colour from the van-wrap palette. Distinct from #drops
   below it, which draws the same nine as devices on a wall.
   ══════════════════════════════════════════════════════════════════════════ */
.sched__list {
  list-style: none; margin: clamp(26px, 3.4vw, 46px) 0 0; padding: 0;
  border-top: 1px solid rgba(238, 242, 255, .12);
}
.sched__row { border-bottom: 1px solid rgba(238, 242, 255, .12) }
.sched__row > a {
  display: grid; grid-template-columns: 62px 1fr 34px; align-items: center;
  gap: clamp(12px, 2vw, 26px); padding: clamp(15px, 1.9vw, 22px) 6px;
  text-decoration: none; color: var(--on); position: relative;
  transition: background .28s var(--ease), padding-left .28s var(--ease);
}
/* the live edge that lights on hover, in this circuit's own colour */
.sched__row > a::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--c, var(--lime)); transform: scaleY(0); transform-origin: center top;
  transition: transform .3s var(--ease);
}
.sched__n {
  font-family: var(--mono); font-size: 14px; letter-spacing: .14em;
  color: var(--c, var(--lime)); opacity: .85;
}
.sched__b { display: grid; gap: 4px; min-width: 0 }
.sched__k {
  font-family: var(--display); font-weight: 800; text-transform: uppercase;
  font-size: clamp(1.35rem, 2.6vw, 2.1rem); line-height: 1; letter-spacing: -.01em;
  transition: color .25s var(--ease);
}
.sched__s { font-size: clamp(14px, 1.2vw, 15.5px); color: var(--on-faint); line-height: 1.5 }
.sched__go {
  font-size: 22px; color: var(--c, var(--lime)); opacity: 0; justify-self: end;
  transition: opacity .28s var(--ease), transform .28s var(--ease);
  transform: translateX(-6px);
}

@media (hover: hover) and (pointer: fine) {
  .sched__row > a:hover, .sched__row > a:focus-visible {
    background: linear-gradient(90deg, color-mix(in srgb, var(--c, #A8FF3E) 10%, transparent), transparent 62%);
    padding-left: 20px;
  }
  .sched__row > a:hover::before, .sched__row > a:focus-visible::before { transform: scaleY(1) }
  .sched__row > a:hover .sched__k, .sched__row > a:focus-visible .sched__k { color: var(--c, var(--lime)) }
  .sched__row > a:hover .sched__go, .sched__row > a:focus-visible .sched__go { opacity: 1; transform: translateX(0) }
}
/* browsers without color-mix still get the edge, the colour and the arrow */
@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .sched__row > a:hover { background: rgba(238, 242, 255, .05) }
}

@media (max-width: 620px) {
  .sched__row > a { grid-template-columns: 44px 1fr; gap: 12px }
  .sched__go { display: none }
}

@media (prefers-reduced-motion: reduce) {
  .sched__row > a, .sched__row > a::before, .sched__go, .sched__k { transition: none }
}
