/* ============================================================================
   SIMPLE SOLUTIONS IT — "MIRROR" motion layer                     (2026-09-16)
   A managed service provider whose two promises are "your screen mirrors our
   work" and "we never charge for travel." So the page reports like a monitored
   system: things arrive, nothing bounces, the accent reads like a status light.
   ========================================================================== */

/* --- 1. headings report in: a scan bar passes once, then the text holds --- */
.term { position: relative; display: block }
.js .term { opacity: 0; transform: translateY(10px); transition: opacity .5s linear, transform .5s cubic-bezier(.2,.8,.3,1) }
.js .term.in { opacity: 1; transform: none }
.js .term::before {
  content: ""; position: absolute; left: -.2em; right: -.2em; top: 0; height: 100%;
  background: linear-gradient(90deg, transparent, rgba(18,169,126,.22), transparent) no-repeat;
  background-size: 45% 100%; background-position: -60% 0; pointer-events: none; opacity: 0;
}
.js .term.in::before { animation: scan .9s cubic-bezier(.2,.8,.3,1) .1s forwards }
@keyframes scan { 0% { opacity: 1; background-position: -60% 0 } 100% { opacity: 0; background-position: 160% 0 } }

/* the accent phrase carries a terminal underscore that blinks, then holds */
.y { position: relative; white-space: nowrap }
.y::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -.06em; height: .08em;
  background: var(--acc); transform: scaleX(0); transform-origin: left;
}
.js .term.in .y::after { animation: rule .5s cubic-bezier(.2,.8,.3,1) .6s forwards, blink 1s steps(1,end) 1.1s 3 }
@keyframes rule  { to { transform: scaleX(1) } }
@keyframes blink { 0%,49% { opacity: 1 } 50%,100% { opacity: .25 } }
.hero__h .y::after { bottom: -.02em }

/* --- 2. content reports in. Linear opacity, short move, no overshoot ------ */
.js .fx { opacity: 0; transform: translateY(8px); transition: opacity .28s linear, transform .32s cubic-bezier(.2,.8,.3,1) }
.js .fx.in { opacity: 1; transform: none }
.js .fx.d1 { transition-delay: .07s } .js .fx.d2 { transition-delay: .14s }
.js .fx.d3 { transition-delay: .21s } .js .fx.d4 { transition-delay: .28s }

/* --- 3. the motif: a network of nodes finding each other ------------------ */
.motif path, .motif circle { stroke-dasharray: 300; stroke-dashoffset: 300 }
.js .motif.in .m1 { animation: mdraw 1.2s cubic-bezier(.2,.8,.3,1) .1s forwards }
.js .motif.in .m2 { animation: mdraw 1s   cubic-bezier(.2,.8,.3,1) .5s forwards }
.js .motif.in .m3 { animation: mdraw .9s  cubic-bezier(.2,.8,.3,1) .8s forwards }
@keyframes mdraw { to { stroke-dashoffset: 0 } }

/* --- 4. read-outs snap in like a monitor refresh -------------------------- */
.js .stat { opacity: 0 }
.js .stat.in { animation: readout .3s steps(3,end) forwards }
.js .stat.d1.in { animation-delay: .1s } .js .stat.d2.in { animation-delay: .2s } .js .stat.d3.in { animation-delay: .3s }
@keyframes readout { from { opacity: 0 } to { opacity: 1 } }
.js .stat::after { content: ""; position: absolute; left: 0; top: -2px; height: 2px; width: 0; background: var(--acc); transition: width .55s cubic-bezier(.2,.8,.3,1) .25s }
.js .stat.in::after { width: 100% }

/* --- 5. the service tape rolls like a status ticker ------------------------ */
.tape__track { animation: tape 42s linear infinite }
.tape:hover .tape__track { animation-play-state: paused }
@keyframes tape { to { transform: translateX(-50%) } }

/* --- 6. the pinned status board ------------------------------------------- */
.status .stage { opacity: .38; transition: opacity .35s linear, transform .35s cubic-bezier(.2,.8,.3,1) }
.status .stage.is-on { opacity: 1 }
.status .stage.is-done { opacity: .62 }
.status .stage.is-done .stage__n { color: var(--acc) }
.status .stage.is-on .stage__n { color: var(--acc) }
.status .stage__n { transition: color .3s }
.status.is-flat .stage { opacity: 1 }
.status.is-flat .stage.is-on h3 { color: var(--acc) }

/* --- 7. rows and cards connect on hover: a lead draws to them ------------- */
.svc, .bg li, .way, .town { position: relative; transition: transform .2s cubic-bezier(.2,.8,.3,1), border-color .2s, background .2s }
.svc::before, .way::before { content: ""; position: absolute; left: -1px; top: 50%; width: 0; height: 1px; background: var(--acc); transition: width .28s cubic-bezier(.2,.9,.3,1) }
.svc:hover::before, .way:hover::before { width: 14px; left: -15px }
.svc:hover, .way:hover { transform: translateX(3px) }
.bg li:hover { color: #fff; transform: translateX(4px) }
.bg li:hover::before { box-shadow: 0 0 10px rgba(18,169,126,.8) }
.town:hover { background: rgba(18,169,126,.12) }

/* --- reduced motion: everything present, nothing moving ------------------- */
@media (prefers-reduced-motion: reduce) {
  .js .term, .js .term.in { opacity: 1; transform: none; transition: none }
  .js .term::before, .js .term.in::before { animation: none; opacity: 0 }
  .y::after, .js .term.in .y::after { transform: scaleX(1); animation: none }
  .js .fx { opacity: 1; transform: none; transition: none }
  .motif path, .motif circle { stroke-dashoffset: 0; animation: none }
  .js .stat, .js .stat.in { opacity: 1; animation: none }
  .js .stat::after { width: 100%; transition: none }
  .tape__track { animation: none }
  .status .stage { opacity: 1 }
  .svc:hover, .way:hover, .bg li:hover { transform: none }
}
@media (max-width: 760px) {
  .svc:hover, .way:hover, .bg li:hover { transform: none }
}
