/* Ironline Towing & Recovery — the bits Tailwind utilities can't express,
   plus the motion layer: view transitions, scroll reveals, pointer-tracked
   glows, a shine sweep and the dispatch ticker. */

[x-cloak] {
  display: none !important;
}

/* Router: views are visible in the HTML so the page still reads with JS off. */
.view.is-hidden {
  display: none !important;
}

/* Each view eases in when the router swaps it. */
.view:not(.is-hidden) {
  animation: view-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes view-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* The router focuses each view's heading so screen readers land on the new page.
   tabindex="-1" keeps it out of the tab order, so no keyboard user can reach it
   and no real focus indicator is lost. */
[tabindex="-1"]:focus {
  outline: none;
}

/* ---------------------------------------------------------------
   Page scroll progress
   --------------------------------------------------------------- */
.scroll-progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 100;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, #4d7c0f, #a3e635 45%, #ecfccb);
  box-shadow: 0 0 12px rgba(163, 230, 53, 0.55);
  pointer-events: none;
}

/* ---------------------------------------------------------------
   Hero glow — tracks the pointer
   --------------------------------------------------------------- */
.hero-glow {
  background:
    radial-gradient(36rem 30rem at var(--gx, 12%) var(--gy, 0%), rgba(132, 204, 22, 0.22), transparent 62%),
    radial-gradient(50% 70% at 96% 18%, rgba(58, 122, 214, 0.16), transparent 66%);
}

/* ---------------------------------------------------------------
   Hero background photograph — a dim, wide scene behind the headline
   so the section reads as a place rather than a flat colour. The
   gradient on top keeps the copy at full contrast and fades the
   image out into the stats strip below.

   It sits at the bottom of the hero's own stacking order: the pseudo
   element paints first, then the pointer-tracked glow, then content,
   so nothing else needs a z-index.
   --------------------------------------------------------------- */
.hero-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(180deg, rgba(6, 10, 18, 0.62) 0%, rgba(6, 10, 18, 0.94) 62%, #060a12 100%),
    url("assets/background-2.jpg");
  background-size: auto, cover;
  background-position: center center, center center;
  background-repeat: no-repeat, no-repeat;
  pointer-events: none;
}

/* ---------------------------------------------------------------
   Inner page heroes — Services, Service area and Why us each carry
   their own photograph behind the headline. The gradient on top
   keeps the copy at full contrast and fades the image down into the
   page underneath, so the strip reads as a place rather than a flat
   colour.

   The pseudo element paints first; the inner wrapper in the markup
   carries `relative` so the heading and intro sit above it.
   --------------------------------------------------------------- */
.page-hero {
  position: relative;
  isolation: isolate;
}

.page-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-repeat: no-repeat, no-repeat;
  background-size: auto, cover;
  background-position: center center, center center;
  pointer-events: none;
}

.page-hero--services::before {
  background-image:
    linear-gradient(180deg, rgba(6, 10, 18, 0.58) 0%, rgba(6, 10, 18, 0.88) 68%, #060a12 100%),
    url("assets/background-6.jpg");
}

.page-hero--coverage::before {
  background-image:
    linear-gradient(180deg, rgba(6, 10, 18, 0.58) 0%, rgba(6, 10, 18, 0.88) 68%, #060a12 100%),
    url("assets/background-3.jpg");
}

.page-hero--about::before {
  background-image:
    linear-gradient(180deg, rgba(6, 10, 18, 0.58) 0%, rgba(6, 10, 18, 0.88) 68%, #060a12 100%),
    url("assets/background.jpg");
}

.page-hero--contact::before {
  background-image:
    linear-gradient(180deg, rgba(6, 10, 18, 0.62) 0%, rgba(6, 10, 18, 0.9) 68%, #060a12 100%),
    url("assets/background-5.jpg");
}

/* ---------------------------------------------------------------
   Cards — lift and a lime spotlight that follows the cursor
   --------------------------------------------------------------- */
.js-glow.js-glow {
  position: relative;
  transition:
    transform 0.4s cubic-bezier(0.22, 1, 0.36, 1),
    border-color 0.4s ease,
    box-shadow 0.4s ease,
    opacity 0.4s ease;
}

.js-glow.js-glow:hover,
.js-glow.js-glow:focus-within {
  transform: translateY(-4px);
  box-shadow: 0 24px 52px -26px rgba(163, 230, 53, 0.6);
}

.js-glow::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    18rem 18rem at var(--mx, 50%) var(--my, 50%),
    rgba(163, 230, 53, 0.14),
    transparent 62%
  );
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
  z-index: 1;
}

.js-glow:hover::before {
  opacity: 1;
}

/* ---------------------------------------------------------------
   Photography — a slow zoom on hover, stilled when motion is reduced
   --------------------------------------------------------------- */
.photo-zoom {
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

.group:hover .photo-zoom,
.group:focus-within .photo-zoom {
  transform: scale(1.06);
}

@media (prefers-reduced-motion: reduce) {
  .group:hover .photo-zoom,
  .group:focus-within .photo-zoom {
    transform: none;
  }
}

/* ---------------------------------------------------------------
   Solid lime buttons — a light sweeps across on hover or focus
   --------------------------------------------------------------- */
.js-shine {
  position: relative;
  overflow: hidden;
}

.js-shine::after {
  content: "";
  position: absolute;
  top: -20%;
  bottom: -20%;
  left: -70%;
  width: 48%;
  z-index: 2;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.6), transparent);
  transform: skewX(-18deg);
  transition: left 0.65s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
}

.js-shine:hover::after,
.js-shine:focus-visible::after {
  left: 130%;
}

/* Breathing ring on the hero call button. */
.js-pulse {
  animation: cta-pulse 2.6s ease-in-out infinite;
}

@keyframes cta-pulse {
  0%,
  100% {
    box-shadow:
      0 0 0 0 rgba(163, 230, 53, 0.55),
      0 14px 34px -16px rgba(163, 230, 53, 0.5);
  }
  50% {
    box-shadow:
      0 0 0 14px rgba(163, 230, 53, 0),
      0 18px 44px -16px rgba(163, 230, 53, 0.8);
  }
}

/* ---------------------------------------------------------------
   Scroll reveals (classes added by script.js)
   --------------------------------------------------------------- */
.js-reveal {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.6s ease,
    transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js-reveal.is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* ---------------------------------------------------------------
   Animated sheen on the big headline accent
   --------------------------------------------------------------- */
@keyframes shimmer {
  to {
    background-position: -250% 0;
  }
}

main h1 .shimmer-text {
  background: linear-gradient(
    100deg,
    #a3e635 0%,
    #ecfccb 28%,
    #a3e635 52%,
    #d9f99d 76%,
    #a3e635 100%
  );
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer 6s linear infinite;
}

/* ---------------------------------------------------------------
   Dispatch ticker under the hero
   --------------------------------------------------------------- */
.ticker {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(6, 10, 18, 0.85);
  padding: 0.85rem 0;
  font-family: "Barlow Condensed", system-ui, sans-serif;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(226, 232, 240, 0.72);
}

/* The scrolling banner is capped at the same measure as the page content
   (max-w-7xl, 80rem) with the same responsive gutters, so the marquee lines
   up with every other section instead of running edge to edge. The dark
   strip behind it still spans the full width. */
.ticker-viewport {
  max-width: 80rem;
  margin: 0 auto;
  padding: 0 1rem;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

@media (min-width: 640px) {
  .ticker-viewport {
    padding: 0 1.5rem;
  }
}

@media (min-width: 1024px) {
  .ticker-viewport {
    padding: 0 2rem;
  }
}

.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker-scroll 34s linear infinite;
}

.ticker:hover .ticker-track {
  animation-play-state: paused;
}

.ticker-group {
  display: flex;
  flex: none;
  align-items: center;
  gap: 1.75rem;
  padding-right: 1.75rem;
}

.ticker-sep {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: #a3e635;
  box-shadow: 0 0 10px rgba(163, 230, 53, 0.85);
}

@keyframes ticker-scroll {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(-50%);
  }
}

/* ---------------------------------------------------------------
   "Dispatch open now" badge — a short, snappy squash-and-stretch
   hop every few seconds. Long dead time between hops keeps it a
   wink rather than a twitch.
   --------------------------------------------------------------- */
.dispatch-badge {
  transform-origin: 50% 100%;
  animation: dispatch-bounce 3s cubic-bezier(0.36, 0.07, 0.19, 0.97) infinite;
  will-change: transform;
}

@keyframes dispatch-bounce {
  0%,
  84%,
  100% {
    transform: none;
  }
  86% {
    transform: translateY(-8px) scaleY(1.07) scaleX(0.95);
  }
  89% {
    transform: translateY(0) scaleY(0.9) scaleX(1.07);
  }
  92% {
    transform: translateY(-4px) scaleY(1.04) scaleX(0.97);
  }
  95% {
    transform: translateY(0) scaleY(0.97) scaleX(1.02);
  }
  97.5% {
    transform: none;
  }
}

/* ---------------------------------------------------------------
   "Dispatch open now" pulse
   --------------------------------------------------------------- */
.pulse-dot {
  animation: pulse-dot 1.8s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse-dot {
  0%,
  100% {
    opacity: 0.7;
    transform: scale(1);
  }
  50% {
    opacity: 0;
    transform: scale(2.6);
  }
}

::selection {
  background: #84cc16;
  color: #060a12;
}

@media (prefers-reduced-motion: reduce) {
  .pulse-dot,
  .dispatch-badge,
  .js-pulse,
  .shimmer-text,
  .ticker-track,
  .view:not(.is-hidden) {
    animation: none;
  }

  .js-reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .js-glow.js-glow:hover,
  .js-glow.js-glow:focus-within {
    transform: none;
  }

  .js-shine::after {
    display: none;
  }

  html {
    scroll-behavior: auto;
  }
}
