/* =====================================================================
   Spottune Colombia · fx: canvas layer, cursor glow, reveals, keyframes
   All motion is slow, small, monochrome and honours prefers-reduced-motion
   (base.css kills every animation/transition when the user asks for it).
   ===================================================================== */

/* --- sound-field canvas (hero) ---------------------------------------
   Markup (01-hero.html): <section id="hero" class="sec ..."> <div id="fx-bg" aria-hidden="true"><canvas id="fx-canvas"></canvas></div> <div class="wrap">…</div> */
#hero{position:relative}
#hero > .wrap{position:relative;z-index:1}
#fx-bg{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none;contain:strict}
#fx-canvas{position:absolute;inset:0;width:100%;height:100%;display:block}

/* --- cursor glow: removed (client decision, round 5 — the soft disc that followed the pointer read as a
   smudge under the mouse). The markup hook stays inert so any leftover element can never paint. --- */
#cursor-glow{display:none!important}

/* --- reveal on scroll: .rv → .rv.in (stagger with --i) ---
   The gate is `html.rv-on`, added by main.js itself (NOT the inline `js` class from head.html):
   if main.js never runs, nothing is hidden and the 21 sections stay visible. main.js also carries a
   timer that reveals everything when the IntersectionObserver never fires. */
html.rv-on .rv{opacity:0;transform:translateY(10px);transition:opacity .32s var(--ease),transform .32s var(--ease);transition-delay:calc(var(--i,0) * 35ms);will-change:opacity,transform}
html.rv-on .rv.in{opacity:1;transform:none}
html.rv-on .rv.in.done{will-change:auto;transition-delay:0s}
@media (prefers-reduced-motion:reduce){html.rv-on .rv{opacity:1;transform:none}}

/* --- word-by-word statement reveal: .w-reveal > span (split by main.js) --- */
.w-reveal{--w-delay:34ms}
html.rv-on .w-reveal .w{display:inline-block;opacity:0;transform:translateY(.55em)}
html.rv-on .w-reveal.in .w{animation:wordUp .42s var(--ease) forwards;animation-delay:calc(var(--i,0) * var(--w-delay))}
@keyframes wordUp{to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){html.rv-on .w-reveal .w{opacity:1;transform:none}}

/* --- generic keyframes (used by components) --- */
@keyframes fadeUp{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes marquee{to{transform:translateX(-50%)}}
@keyframes ledBlink{0%,49%{opacity:1}50%,100%{opacity:.18}}
@keyframes ripple{0%{transform:scale(.4);opacity:.5}100%{transform:scale(2.2);opacity:0}}
@keyframes toastIn{from{opacity:0;transform:translate(-50%,12px)}to{opacity:1;transform:translate(-50%,0)}}

/* --- marquee motion (structure in components.css) --- */
.marquee .track{animation:marquee 40s linear infinite;will-change:transform}
.marquee:hover .track,.marquee:focus-within .track{animation-play-state:paused}
.marquee.slow .track{animation-duration:60s}
.marquee.reverse .track{animation-direction:reverse}

/* --- tilt (.card / .prod / .tilt): main.js drives the transform; CSS provides the rest state --- */
.tilt,.card,.prod{transition:transform .5s var(--ease),border-color var(--dur) var(--ease),background-color var(--dur) var(--ease)}
.tilt.tilting,.card.tilting,.prod.tilting{transition:transform .12s ease-out,border-color var(--dur) var(--ease);will-change:transform}

/* --- sliding tab underline (positioned by main.js through --tab-x / --tab-w) --- */
.tabs{--tab-x:0px;--tab-w:0px}
.tabs::after{content:"";position:absolute;left:0;bottom:-1px;height:2px;width:var(--tab-w);transform:translateX(var(--tab-x));background:var(--st-black);border-radius:2px;transition:transform .35s var(--ease),width .35s var(--ease);pointer-events:none}
.sec-dark .tabs::after{background:var(--st-cream)}
.tabs:not(.js) .tab.active{box-shadow:inset 0 -2px 0 currentColor}
.tabs.js::after{opacity:1}
.tabs:not(.js)::after{display:none}

/* --- panel entrance --- */
.tab-panel.show{animation:fadeUp .4s var(--ease)}

/* --- hero parallax hook (hero author moves .parallax via JS; keep GPU friendly) --- */
.parallax{will-change:transform;transition:transform .6s var(--ease-out)}

/* --- magnetic buttons (.btn-primary + .btn-wa): transform is inline from main.js; make it smooth --- */
html.js .btn-primary,html.js .btn-wa{transition:transform .35s var(--ease),background-color var(--dur) var(--ease),border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease),color var(--dur) var(--ease)}

/* --- marquee under reduced motion --------------------------------------
   base.css kills the animation, so a frozen `overflow:hidden;white-space:nowrap` ribbon would crop 6 of the
   8 technical facts with no way to reach them (WCAG 1.4.10 / 2.2.2). Here the ribbon becomes a wrapped,
   static list: same content, no motion. The clones main.js appends are aria-hidden, so they drop out. */
@media (prefers-reduced-motion:reduce){
  .marquee{white-space:normal;overflow:visible;-webkit-mask-image:none;mask-image:none}
  .marquee .track{animation:none;flex-wrap:wrap;width:auto;justify-content:center;will-change:auto}
  .marquee .track > *[aria-hidden="true"]{display:none}
  .marquee .track > *:last-child::after{display:none}
}

/* --- section separators (client decision, round 5) ------------------------
   Every section on the home page carries a hairline at its top edge with a light that travels
   across it once, when the section enters the viewport. The rule is drawn on the section itself
   (::before) so it never disturbs layout, and the sweep is driven by `.sec-sep.in`, which main.js
   adds with the same IntersectionObserver that runs the reveals.
   Dark sections get a bright sweep, light sections a dark one. */
.sec-sep{position:relative}
.sec-sep::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;pointer-events:none;z-index:3;
  background:var(--sep-line,rgba(40,40,40,.10));
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent)}
/* The sweep moves a 34%-wide gradient as background-position inside a full-width layer. It used to be a 34%-wide
   box moved with transform:translateX(320%) and kept there (forwards); invisible, but its right edge ended at 143%
   of the section width, and iOS WebKit counted it, so every phone could pinch-zoom out to a white strip.
   Background positions never create overflow. -52% / 152% put the gradient just outside each edge. */
.sec-sep::after{
  content:"";position:absolute;top:0;left:0;right:0;height:1px;pointer-events:none;z-index:4;opacity:0;
  background:linear-gradient(90deg,transparent,var(--sep-glow,rgba(40,40,40,.55)),transparent) no-repeat;
  background-size:34% 100%;background-position:-52% 0}
html.rv-on .sec-sep.in::after{animation:secSweep 1.5s var(--ease-out) .05s forwards}
@keyframes secSweep{
  0%{opacity:0;background-position:-52% 0}
  12%{opacity:1}
  88%{opacity:1}
  100%{opacity:0;background-position:152% 0}}
/* dark bands: a bright line instead of a dark one */
.sec-dark.sec-sep,.s-hero.sec-sep{--sep-line:rgba(245,239,231,.16);--sep-glow:rgba(255,255,255,.85)}
.sec-cream.sec-sep{--sep-line:rgba(40,40,40,.10);--sep-glow:rgba(40,40,40,.45)}
.sec-white.sec-sep{--sep-line:rgba(40,40,40,.08);--sep-glow:rgba(40,40,40,.42)}
@media (prefers-reduced-motion:reduce){
  .sec-sep::after{display:none}
}
