/* ==========================================================================
   Prime Assist — motion
   Beam, Gooey and Orbs, ported to plain CSS. The site has no build step, so
   nothing here may depend on React, a bundler or an external script.

   Restraint is the design rule: motion is red-on-brand only, it never moves
   content the reader is trying to read, and every effect switches off under
   prefers-reduced-motion.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. BEAM — a travelling highlight around an edge.
   Used on the primary CTA and on service-card hover. Brand red only: a
   rainbow beam reads as a template, one colour reads as a brand.
   -------------------------------------------------------------------------- */
@property --pa-beam-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

@keyframes pa-beam-spin {
  to { --pa-beam-angle: 360deg; }
}

.pa-beam {
  position: relative;
  isolation: isolate;
}

.pa-beam::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(
    from var(--pa-beam-angle),
    rgba(204, 0, 0, 0)    0deg,
    rgba(204, 0, 0, 0)  190deg,
    rgba(204, 0, 0, 0.55) 250deg,
    #ff2d2d              300deg,
    rgba(204, 0, 0, 0.55) 340deg,
    rgba(204, 0, 0, 0)   360deg
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  animation: pa-beam-spin 4.5s linear infinite;
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
  z-index: 2;
}

.pa-beam:hover::before,
.pa-beam:focus-visible::before,
.pa-beam.pa-beam-on::before { opacity: 1; }

/* The primary CTA carries the beam permanently — it is the one thing on the
   page we want the eye to return to. */
.cta-btn.pa-beam::before,
a.btn-red.pa-beam::before { opacity: 0.85; }

/* --------------------------------------------------------------------------
   2. ORBS — soft drifting light, sitting behind hero content.
   Pure CSS gradients; no canvas, no images, no request.
   -------------------------------------------------------------------------- */
.pa-orbs {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.pa-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  will-change: transform;
  opacity: 0.5;
}

.pa-orb--red {
  width: 46vmax; height: 46vmax;
  top: -18vmax; left: -10vmax;
  background: radial-gradient(circle at 50% 50%,
              rgba(204, 0, 0, 0.34), rgba(204, 0, 0, 0) 68%);
  animation: pa-drift-a 26s ease-in-out infinite;
}

.pa-orb--warm {
  width: 38vmax; height: 38vmax;
  bottom: -14vmax; right: -8vmax;
  background: radial-gradient(circle at 50% 50%,
              rgba(255, 92, 60, 0.22), rgba(255, 92, 60, 0) 70%);
  animation: pa-drift-b 32s ease-in-out infinite;
}

.pa-orb--cool {
  width: 30vmax; height: 30vmax;
  top: 32%; left: 44%;
  background: radial-gradient(circle at 50% 50%,
              rgba(120, 120, 150, 0.18), rgba(120, 120, 150, 0) 72%);
  animation: pa-drift-c 38s ease-in-out infinite;
}

@keyframes pa-drift-a {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(6vmax, 4vmax, 0) scale(1.12); }
}
@keyframes pa-drift-b {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); }
  50%      { transform: translate3d(-5vmax, -5vmax, 0) scale(1); }
}
@keyframes pa-drift-c {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(-7vmax, 3vmax, 0); }
}

/* --------------------------------------------------------------------------
   3. GOOEY — blobs that merge as they meet.
   An SVG filter does the merge; the movement is CSS. The filter is defined
   once in the markup (see the gooey defs block in index.html).
   -------------------------------------------------------------------------- */
.pa-gooey { filter: url(#pa-goo); }

.pa-blob {
  position: absolute;
  border-radius: 50%;
  background: var(--accent-red, #CC0000);
  will-change: transform;
}

.pa-blob--a { width: 74px; height: 74px; animation: pa-blob-a 7s ease-in-out infinite; }
.pa-blob--b { width: 52px; height: 52px; animation: pa-blob-b 7s ease-in-out infinite; }
.pa-blob--c { width: 40px; height: 40px; animation: pa-blob-c 9s ease-in-out infinite; }

@keyframes pa-blob-a {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(34px, 16px); }
}
@keyframes pa-blob-b {
  0%, 100% { transform: translate(58px, 40px); }
  50%      { transform: translate(14px, 6px); }
}
@keyframes pa-blob-c {
  0%, 100% { transform: translate(28px, 84px); }
  50%      { transform: translate(64px, 52px); }
}

/* --------------------------------------------------------------------------
   4. Shared interaction polish
   -------------------------------------------------------------------------- */
.pa-lift {
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.28s ease,
              border-color 0.28s ease;
}
.pa-lift:hover {
  transform: translateY(-4px);
  box-shadow: 0 18px 40px -18px rgba(14, 14, 14, 0.28);
}

[data-theme="dark"] .pa-lift:hover {
  box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.7);
}

/* A quiet red edge that grows on hover — cheaper than a full beam on a grid
   of nine cards, where nine simultaneous beams would be noise. */
.pa-edge { position: relative; }
.pa-edge::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  height: 2px; width: 0;
  background: var(--accent-red, #CC0000);
  transition: width 0.36s cubic-bezier(0.22, 1, 0.36, 1);
}
.pa-edge:hover::after { width: 100%; }

/* --------------------------------------------------------------------------
   5. Accessibility — motion is decoration, never information.
   Everything stops for users who ask for less movement.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .pa-beam::before,
  .pa-orb,
  .pa-blob,
  .pa-lift,
  .pa-edge::after {
    animation: none !important;
    transition: none !important;
  }
  .pa-beam::before { opacity: 0 !important; }
  .pa-orb { opacity: 0.28; }
  .pa-lift:hover { transform: none; }
  .pa-edge:hover::after { width: 0; }
}

/* Orbs are expensive to composite; drop the third one on small screens. */
@media (max-width: 700px) {
  .pa-orb--cool { display: none; }
  .pa-orb { filter: blur(44px); }
}

/* --- Sections that host orbs ---
   An orb layer is absolutely positioned, so its parent needs a positioning
   context and clipping. Scoped to the sections that actually contain orbs so
   nothing else on the page changes. */
.services-section,
.final-cta-section,
.hero { position: relative; }

.services-section,
.final-cta-section { overflow: hidden; }

.hero > .pa-orbs { border-radius: 0; }

/* Inside a short hero the vmax sizing is too large; scale the orbs down. */
.hero .pa-orb--red  { width: 32vmax; height: 32vmax; top: -14vmax; left: -6vmax; }
.hero .pa-orb--warm { width: 26vmax; height: 26vmax; bottom: -12vmax; right: -6vmax; }
.hero .pa-orb--cool { width: 20vmax; height: 20vmax; top: 20%; left: 50%; }

/* Content must sit above the orb layer. */
.services-section > *:not(.pa-orbs),
.final-cta-section > *:not(.pa-orbs),
.hero > *:not(.pa-orbs) { position: relative; z-index: 1; }
