/* PULSE marketing motion layer — shared across app/*.html
   All hidden-by-default states are scoped under html.pm-on, which pulse-motion.js
   adds ONLY when prefers-reduced-motion is not set. No JS / reduced motion => content
   renders in its final visible state with no animation.

   Loaded via <link> at the END of <head>, so it wins over each page's inline
   <style> at equal specificity. Keep non-.pm-on rules to a minimum for that reason. */

/* ---- keyframes (names match app/login.html so the surfaces stay consistent) ---- */
@keyframes ekgDraw   { to { stroke-dashoffset: 0; } }
@keyframes ekgSettle { to { opacity: 0.10; } }
@keyframes fadeUp    { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes pmRing    { 0% { transform: scale(1); opacity: 0.55; } 100% { transform: scale(3.2); opacity: 0; } }
@keyframes pmBreathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } }
@keyframes pmBarGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }

/* ---- hero EKG backdrop ---- */
.hero-ekg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 0; opacity: 1;
}
html.pm-on .hero-ekg { animation: ekgSettle 1.2s ease-out 2.7s forwards; }
.hero-ekg polyline {
  fill: none; stroke: #D4982A; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 0 8px rgba(212,152,42,0.7));
}
html:not(.pm-on) .hero-ekg { opacity: 0.10; }
html.pm-on .hero-ekg polyline {
  stroke-dasharray: 100; stroke-dashoffset: 100;
  animation: ekgDraw 2.4s ease-in-out 0.25s forwards;
}

/* ---- hero entrance stagger ----
   The pages do not share one hero wrapper: most use .hero-text, industries/about
   use .hero-content, contact/resources only have .hero-inner. Cover all three or
   those pages stagger their buttons while the headline sits still. An element
   matched by several of these selectors still gets one animation. */
html.pm-on .hero-text h1,
html.pm-on .hero-content h1,
html.pm-on .hero-inner h1            { animation: fadeUp 0.6s ease-out 0.15s both; }
html.pm-on .hero-text .subtitle,
html.pm-on .hero-content .subtitle,
html.pm-on .hero-inner .subtitle     { animation: fadeUp 0.6s ease-out 0.30s both; }
html.pm-on .hero-actions             { animation: fadeUp 0.6s ease-out 0.45s both; }
html.pm-on .hero-visual              { animation: fadeUp 0.7s ease-out 0.55s both; }

/* ---- hero chart bars grow on load ---- */
html.pm-on .dash-chart-bar {
  transform-origin: bottom center;
  animation: pmBarGrow 0.6s cubic-bezier(0.22, 0.7, 0.35, 1) both;
}

/* ---- scroll reveals ---- */
html.pm-on [data-reveal] {
  opacity: 0; transform: translateY(14px);
  transition: opacity 0.5s ease-out, transform 0.5s cubic-bezier(0.22, 0.7, 0.35, 1);
}
html.pm-on [data-reveal].pm-in { opacity: 1; transform: none; }

/* ---- nav scroll state ---- */
/* Pages set their own .nav border-bottom inline; this file loads after that
   <style> block, so the hairline starts transparent and fades in past 24px. */
.nav {
  border-bottom: 1px solid transparent;
  transition: background 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
}
.nav.pm-scrolled {
  background: rgba(6, 22, 37, 0.97);
  border-bottom-color: rgba(255, 255, 255, 0.08);
  box-shadow: 0 1px 20px rgba(0, 0, 0, 0.35);
}

/* ---- brand pulse dot (signature 1.8s cadence) ---- */
.pm-dot {
  position: relative; display: inline-block;
  width: 7px; height: 7px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #EDBE57, #D4982A 72%);
  box-shadow: 0 0 10px rgba(212, 152, 42, 0.5);
  flex: 0 0 auto;
}
html.pm-on .pm-dot { animation: pmBreathe 1.8s ease-in-out infinite; }
.pm-dot::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid #D4982A;
}
html.pm-on .pm-dot::after { animation: pmRing 1.8s cubic-bezier(0.2, 0.6, 0.3, 1) infinite; }
html:not(.pm-on) .pm-dot::after { display: none; }

/* ---- section eyebrows carry the brand cadence ----
   Each page declares .section-tag as inline-block; this file loads after that
   inline <style>, so the flex context for the leading .pm-dot lands here rather
   than in 21 duplicated edits. */
.section-tag { display: inline-flex; align-items: center; gap: 7px; }

/* ---- card icon tiles react to their card's hover ----
   The cards already lift on hover but their colored icon tile sat inert. */
.feature-icon, .solution-icon, .pain-icon, .deliv-icon, .int-strip-icon {
  transition: transform 0.2s ease, filter 0.2s ease;
}
.feature-card:hover .feature-icon,
.solution-card:hover .solution-icon,
.pain-card:hover .pain-icon,
.deliv-card:hover .deliv-icon,
.int-strip-card:hover .int-strip-icon {
  transform: scale(1.06); filter: saturate(1.15);
}

/* ---- belt-and-braces: kill everything if the OS says so ---- */
@media (prefers-reduced-motion: reduce) {
  .hero-ekg { animation: none; opacity: 0.10; }
  .hero-ekg polyline { animation: none; stroke-dashoffset: 0; }
  .hero-text h1, .hero-content h1, .hero-inner h1,
  .hero-text .subtitle, .hero-content .subtitle, .hero-inner .subtitle,
  .hero-actions, .hero-visual,
  .dash-chart-bar, [data-reveal], .pm-dot, .pm-dot::after {
    animation: none !important; transition: none !important;
    opacity: 1 !important; transform: none !important;
  }
  .nav { transition: none; }
  .feature-icon, .solution-icon, .pain-icon, .deliv-icon, .int-strip-icon {
    transition: none;
  }
  .feature-card:hover .feature-icon,
  .solution-card:hover .solution-icon,
  .pain-card:hover .pain-icon,
  .deliv-card:hover .deliv-icon,
  .int-strip-card:hover .int-strip-icon { transform: none; filter: none; }
}
