/* =====================================================================
   Effects layer (2026-10-31). Ported by hand to plain CSS/JS from Mason's
   UI libraries (react-bits, uiverse-galaxy). Source list: qa/redesign-1031/EFFECTS.md.
   Rules kept: nothing is tied to scroll position (enter-view once, autoplay,
   hover or tap only), no images follow the cursor, no 3D spinners, no sticky
   bars. Hidden start states exist only under html.js:not(.rm), so no-JS and
   reduced motion get the finished page. Ambient loops run only while their
   block is on screen (.fx-live, set by js/fx.js).
   ===================================================================== */

/* ---------- Section flow: soft edges between dark and light ---------- */
main > .sec > .wrap { position: relative; z-index: 1; }
main > .sec--light::before,
main > .sec:not(.sec--light):not(.sec-hero)::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: calc(var(--sec-y) * 0.85);
  z-index: 0;
  pointer-events: none;
}
main > .sec--light::before { background: linear-gradient(to bottom, #1c1612 0%, rgba(28, 22, 18, 0.55) 35%, rgba(243, 238, 230, 0) 100%); }
main > .sec:not(.sec--light):not(.sec-hero)::before { background: linear-gradient(to bottom, var(--c-field) 0%, rgba(243, 238, 230, 0.5) 30%, rgba(20, 16, 13, 0) 100%); }
/* light sections that touch a light neighbour keep a clean edge */
main > .sec--light + .sec--light::before { display: none; }

/* ---------- Grain on the dark ambient layer (react-bits Noise, static + slow jitter) ---------- */
.st-ambient::after {
  content: "";
  position: absolute;
  inset: -40%;
  opacity: 0.075;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: fx-grain 1.1s steps(6) infinite;
}
@keyframes fx-grain {
  0% { transform: translate(0, 0); } 17% { transform: translate(-3%, 2%); } 33% { transform: translate(2%, -3%); }
  50% { transform: translate(-2%, -1%); } 67% { transform: translate(3%, 3%); } 83% { transform: translate(-1%, 2%); } 100% { transform: translate(0, 0); }
}
html.rm .st-ambient::after, html.lowp .st-ambient::after { animation: none; }

/* ---------- Aurora (react-bits Aurora, CSS port: soft drifting colour fields) ---------- */
.fx-aurora { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent 100%); mask-image: linear-gradient(to bottom, #000 55%, transparent 100%); }
.fx-aurora i { position: absolute; display: block; border-radius: 50%; will-change: transform; }
.fx-aurora i:nth-child(1) { width: min(70vw, 900px); height: min(46vw, 620px); left: -12%; top: -10%; background: radial-gradient(closest-side, rgba(211, 180, 131, 0.30), rgba(211, 180, 131, 0) 100%); }
.fx-aurora i:nth-child(2) { width: min(60vw, 800px); height: min(50vw, 640px); right: -14%; top: 4%; background: radial-gradient(closest-side, rgba(176, 108, 78, 0.30), rgba(176, 108, 78, 0) 100%); }
.fx-aurora i:nth-child(3) { width: min(56vw, 760px); height: min(36vw, 480px); left: 28%; bottom: -8%; background: radial-gradient(closest-side, rgba(107, 74, 45, 0.55), rgba(107, 74, 45, 0) 100%); }
.fx-aurora--soft i:nth-child(1) { opacity: 0.7; }
.fx-aurora--soft i:nth-child(2) { opacity: 0.6; }
.fx-live.fx-aurora i:nth-child(1) { animation: fx-drift-a 22s ease-in-out infinite alternate; }
.fx-live.fx-aurora i:nth-child(2) { animation: fx-drift-b 27s ease-in-out infinite alternate; }
.fx-live.fx-aurora i:nth-child(3) { animation: fx-drift-c 31s ease-in-out infinite alternate; }
@keyframes fx-drift-a { to { transform: translate3d(14%, 10%, 0) scale(1.12); } }
@keyframes fx-drift-b { to { transform: translate3d(-16%, 8%, 0) scale(0.92); } }
@keyframes fx-drift-c { to { transform: translate3d(-12%, -12%, 0) scale(1.18); } }
html.rm .fx-aurora i, html.lowp .fx-aurora i { animation: none !important; }
@media (max-width: 768px) { .fx-aurora i:nth-child(3) { display: none; } .fx-aurora i { width: 120vw !important; height: 80vw !important; } }

/* ---------- Particles (react-bits Particles, canvas port) ---------- */
.fx-particles { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
html.lowp .fx-particles { display: none; }

/* ---------- Hero: laptop plus phone ---------- */
.hero-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
@media (max-width: 1023px) { .hero-grid { grid-template-columns: minmax(0, 1fr); } }
.sec-hero { flex-direction: column; justify-content: center; align-items: center; gap: clamp(2.5rem, 5vw, 4rem); }
.sec-hero > .hero-grid { width: var(--content-w); }
main > .sec-hero { padding-bottom: calc(var(--sec-y) * 0.55); }
.hero-stage { --phone-w: auto; width: 100%; }
.hero-devices {
  position: relative;
  width: 100%;
  max-width: 40rem;
  margin-inline: auto;
  padding-bottom: 6%;
  transform: perspective(1400px) rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
  transition: transform 450ms var(--ease-out);
}
.hero-laptop { display: block; width: 86%; }
.hero-lid {
  display: block;
  padding: 2.2% 2.2% 2.6%;
  border-radius: 14px 14px 4px 4px;
  background: #0d0b09;
  border: 1px solid rgba(244, 236, 223, 0.18);
  box-shadow: 0 50px 80px -30px rgba(0, 0, 0, 0.9), 0 0 0 1px rgba(0, 0, 0, 0.6);
}
.hero-lscreen { position: relative; display: block; aspect-ratio: 16 / 10; border-radius: 5px; overflow: hidden; background: #0c0a08; }
.hero-base { display: block; height: clamp(8px, 1.5vw, 14px); margin-inline: -4%; border-radius: 0 0 16px 16px; background: linear-gradient(#2b241d, #120f0c); box-shadow: 0 24px 30px -18px rgba(0, 0, 0, 0.85), inset 0 1px 0 rgba(244, 236, 223, 0.12); }
.hero-phone {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 25%;
  padding: clamp(3px, 0.55vw, 6px);
  border-radius: clamp(14px, 3vw, 30px);
  box-shadow: 0 40px 60px -24px rgba(0, 0, 0, 0.95), 0 0 0 1px rgba(0, 0, 0, 0.6);
}
.hero-screen { border-radius: clamp(11px, 2.4vw, 24px); }

/* Entrance: devices rise and settle once, then the phone drifts */
html.js:not(.rm) .hero-devices:not(.is-in) .hero-laptop,
html.js:not(.rm) .hero-devices:not(.is-in) .hero-phone { opacity: 0; }
html.js:not(.rm) .hero-devices.is-in .hero-laptop { animation: dev-laptop 1200ms var(--ease-out) both; transform-origin: 50% 100%; }
html.js:not(.rm) .hero-devices.is-in .hero-phone { animation: dev-phone 1100ms cubic-bezier(0.34, 1.35, 0.64, 1) 420ms both, dev-float 7s ease-in-out 1.7s infinite; }
@keyframes dev-laptop { from { opacity: 0; transform: translateY(70px) rotateX(26deg) scale(0.9); } to { opacity: 1; transform: none; } }
@keyframes dev-phone { from { opacity: 0; transform: translate(80px, 70px) rotate(9deg) scale(0.82); } to { opacity: 1; transform: none; } }
@keyframes dev-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
html.js:not(.rm) .hero-dots, html.js:not(.rm) .hero-cap { animation: fx-fade 800ms var(--ease-out) 900ms both; }
@keyframes fx-fade { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* Glare sweep on hover (react-bits GlareHover) */
.hero-lscreen::after, .hero-screen::after, .pick-desk::after, .pick-phone::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(-45deg, transparent 56%, rgba(255, 255, 255, 0.26) 68%, transparent 80%) no-repeat;
  background-size: 260% 260%;
  background-position: -110% -110%;
  transition: background-position 750ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .hero-laptop:hover .hero-lscreen::after, .hero-phone:hover .hero-screen::after,
  .pick-laptop:hover .pick-desk::after, .pick-phone:hover::after { background-position: 210% 210%; }
}

/* ---------- Rotating word (react-bits RotatingText) ---------- */
.rw { position: relative; display: inline-block; white-space: nowrap; font-style: italic; color: var(--c-brass); padding-bottom: 0.12em; margin-bottom: -0.12em; clip-path: inset(-0.05em -0.08em 0 -0.08em); }
.rw-ghost { visibility: hidden; }
.rw-layer { position: absolute; inset: 0 auto auto 0; display: block; }
.rw-c { display: inline-block; transition: transform 640ms var(--ease-out), opacity 480ms var(--ease-std); transition-delay: calc(var(--ci) * 26ms); }
.rw-c.is-pre { transform: translateY(115%); opacity: 0; transition: none; }
.rw-c.is-out { transform: translateY(-115%); opacity: 0; }
.rw.is-sized { transition: width 560ms var(--ease-out); }
.rw-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* ---------- Split / blur text reveals (react-bits BlurText) ---------- */
.fx-w { display: inline-block; }
html.js:not(.rm) .fx-split:not(.fx-in) .fx-w { opacity: 0; filter: blur(10px); transform: translateY(0.4em); }
html.js:not(.rm) .fx-split.fx-in .fx-w { transition: opacity 760ms var(--ease-out), filter 760ms var(--ease-out), transform 820ms var(--ease-out); transition-delay: calc(var(--wi) * 70ms); }

/* ---------- Shiny text (react-bits ShinyText) ---------- */
.fx-shiny {
  background-image: linear-gradient(110deg, var(--c-brass) 38%, #fff6df 50%, var(--c-brass) 62%);
  background-size: 250% 100%;
  background-position: 120% 0;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.fx-shiny::before { -webkit-text-fill-color: initial; }
.fx-shiny--ink { background-image: linear-gradient(110deg, var(--c-brass-ink) 38%, #f1d9a6 50%, var(--c-brass-ink) 62%); }
.fx-live.fx-shiny { animation: fx-shine 4.2s linear infinite; }
@keyframes fx-shine { from { background-position: 120% 0; } to { background-position: -120% 0; } }
html.rm .fx-shiny { animation: none; background-image: none; -webkit-text-fill-color: currentColor; background-clip: border-box; }

/* ---------- Marquee (react-bits LogoLoop, CSS port) ---------- */
.fx-marquee { position: relative; z-index: 1; width: 100%; overflow: hidden; border-block: 1px solid var(--c-hair); padding-block: var(--sp-5); -webkit-mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent); mask-image: linear-gradient(to right, transparent, #000 10%, #000 90%, transparent); }
.fx-marquee-track { display: flex; width: max-content; }
.fx-marquee-list { display: flex; flex: none; align-items: center; gap: clamp(1.5rem, 3vw, 2.75rem); padding-right: clamp(1.5rem, 3vw, 2.75rem); }
.fx-marquee-list li { position: relative; white-space: nowrap; font-family: var(--font-serif); font-variation-settings: "opsz" 48; font-size: var(--fs-2xl); line-height: 1.2; color: var(--c-fg-2); }
.fx-marquee-list li:nth-child(even) { font-family: var(--font-sans); font-size: var(--fs-xs); letter-spacing: 0.14em; text-transform: uppercase; color: var(--c-brass); }
.fx-marquee-list li::after { content: ""; position: absolute; right: calc(-0.5 * clamp(1.5rem, 3vw, 2.75rem)); top: 50%; width: 4px; height: 4px; background: var(--c-brass-dim); transform: translate(50%, -50%) rotate(45deg); }
.fx-live .fx-marquee-track { animation: fx-marq 58s linear infinite; }
@keyframes fx-marq { to { transform: translateX(-50%); } }
@media (hover: hover) and (pointer: fine) { .fx-marquee:hover .fx-marquee-track { animation-play-state: paused; } }
html.rm .fx-marquee { -webkit-mask-image: none; mask-image: none; }
html.rm .fx-marquee-track { width: auto; justify-content: center; animation: none; }
html.rm .fx-marquee-list { flex-wrap: wrap; justify-content: center; row-gap: var(--sp-3); }
html.rm .fx-marquee-list[aria-hidden="true"] { display: none; }

/* ---------- Enter-view rise and animated list (react-bits FadeContent, AnimatedList) ---------- */
html.js:not(.rm) .fx-r:not(.fx-in) { opacity: 0; transform: translateY(28px); }
html.js:not(.rm) .fx-r.fx-in { transition: opacity 760ms var(--ease-out), transform 860ms var(--ease-out); transition-delay: calc(var(--fi, 0) * 90ms); }
html.js:not(.rm) .fx-r.fx-list:not(.fx-in) { transform: translateY(26px) scale(0.96); }

/* ---------- Spotlight card (react-bits SpotlightCard) ---------- */
.fx-spot { --spot: rgba(211, 180, 131, 0.16); }
.sec--light .fx-spot, .price-card.fx-spot { --spot: rgba(122, 90, 46, 0.13); }
.fx-spot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 420ms var(--ease-std);
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%), var(--spot), transparent 62%);
}
@media (hover: hover) and (pointer: fine) { .fx-spot:hover::after { opacity: 1; } }
.fx-spot.spot-on::after { opacity: 1; }
.tile.fx-spot > .tile-btn, .tile.fx-spot > .tile-d { position: relative; z-index: 1; }

/* ---------- Animated star border on the price card (react-bits StarBorder + uiverse Cards/roroland_heavy-horse-27) ---------- */
@property --fx-ang { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.price-card > .fx-star-line {
  position: absolute;
  inset: -1px;
  padding: 2px;
  border-radius: inherit;
  pointer-events: none;
  background: conic-gradient(from var(--fx-ang), rgba(122, 90, 46, 0) 0 70%, rgba(122, 90, 46, 0.95) 88%, #e9c98e 94%, rgba(122, 90, 46, 0) 100%);
  -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 exclude, linear-gradient(#000 0 0);
}
.fx-live > .fx-star-line { animation: fx-spin 7s linear infinite; }
@keyframes fx-spin { to { --fx-ang: 360deg; } }
html.rm .price-card > .fx-star-line { animation: none; }

/* ---------- Buttons: magnet + ripple (react-bits Magnet, uiverse Buttons/cssbuttons-io_weak-firefox-5) ---------- */
.btn { position: relative; overflow: hidden; isolation: isolate; }
.btn[data-magnet], .btn[data-magnet]:hover { transform: translate(var(--mgx, 0px), var(--mgy, 0px)); transition: transform 260ms var(--ease-out), box-shadow var(--dur-hover) var(--ease-std); }
.fx-ripple { position: absolute; z-index: -1; border-radius: 50%; pointer-events: none; background: currentColor; opacity: 0.22; transform: scale(0); animation: fx-ripple 650ms var(--ease-out) forwards; }
@keyframes fx-ripple { to { transform: scale(1); opacity: 0; } }

/* ---------- Form: growing underline, valid tick (uiverse Inputs/0xnihilism_calm-baboon-55, Checkboxes/JulanDeAlb_tall-swan-6) ---------- */
.cta-field { position: relative; }
input.cta-input {
  background: #fff linear-gradient(var(--c-brass-ink), var(--c-brass-ink)) no-repeat 50% 100% / 0% 2px;
  transition: border-color var(--dur-ui) var(--ease-std), box-shadow var(--dur-ui) var(--ease-std), background-size 420ms var(--ease-out);
}
input.cta-input:focus { background-size: 100% 2px; }
.fx-tick { position: absolute; right: 16px; width: 22px; height: 22px; pointer-events: none; opacity: 0; transform: scale(0.4); transition: opacity 240ms var(--ease-std), transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1); color: #3f7a4f; }
.fx-tick svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.fx-tick path { stroke-dasharray: 24; stroke-dashoffset: 24; transition: stroke-dashoffset 420ms var(--ease-out) 120ms; }
.cta-field.is-ok .fx-tick { opacity: 1; transform: scale(1); }
.cta-field.is-ok .fx-tick path { stroke-dashoffset: 0; }
.cta-field.is-ok input.cta-input { padding-right: 46px; }
html.rm .fx-tick, html.rm .fx-tick path { transition: none; }

/* ---------- Phone: lighter ---------- */
@media (max-width: 768px) {
  .fx-marquee-list li { font-size: var(--fs-xl); }
  .fx-live .fx-marquee-track { animation-duration: 46s; }
  .hero-devices { max-width: 24rem; }
  .hero-phone { width: 27%; }
  .hero-laptop { width: 84%; }
}
@media (prefers-reduced-motion: reduce) {
  .fx-live .fx-marquee-track, .fx-live.fx-aurora i, .fx-live.fx-shiny, .fx-live > .fx-star-line { animation: none; }
}
