/* Animation layer for the animated copy of the site, v2.
 *
 * Motion is driven by GSAP from fx.js, with Lenis for smooth scrolling. This
 * file only holds what CSS does better: the curtain, the cursor, decorative
 * elements, and the hover effects. Nothing here hides page content on its own,
 * so if the script never runs the page is simply the normal site.
 */

:root {
  --fx-gold: 245, 197, 24;
  --fx-ease: cubic-bezier(.2, .75, .2, 1);
}

/* ── page curtain ───────────────────────────────────────────────────────── */
.fx-curtain {
  position: fixed; inset: 0; z-index: 2000; pointer-events: none;
  background:
    radial-gradient(circle at 50% 120%, rgba(var(--fx-gold), .18), transparent 55%),
    #08090d;
  display: grid; place-items: center;
  clip-path: inset(0 0 0 0);
}
.fx-curtain::after {                          /* gold edge that leads the wipe */
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: linear-gradient(90deg, transparent, #f5c518, transparent);
  box-shadow: 0 0 24px rgba(var(--fx-gold), .8);
}
.fx-curtain-logo {
  font: 900 clamp(28px, 5vw, 56px)/1 'Archivo', 'Inter', system-ui, sans-serif;
  letter-spacing: -.03em; color: #f3f5f9;
}
.fx-curtain-logo b { color: #f5c518; }
/* if the script never runs, the curtain lifts by itself instead of staying */
html:not(.fx-js) .fx-curtain { animation: fx-curtain-fallback .6s ease 2.2s forwards; }
@keyframes fx-curtain-fallback { to { opacity: 0; visibility: hidden; } }

/* ── smooth scrolling (Lenis) ───────────────────────────────────────────── */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

/* ── scroll progress + nav ──────────────────────────────────────────────── */
.fx-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 100%; z-index: 1000;
  transform-origin: 0 50%; transform: scaleX(0);
  background: linear-gradient(90deg, #f5c518, #ffe57a, #f5c518);
  box-shadow: 0 0 12px rgba(var(--fx-gold), .7); pointer-events: none;
}
.nav-wrapper { transition: background .3s ease, box-shadow .3s ease, backdrop-filter .3s ease; }
html.fx-scrolled .nav-wrapper {
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, .8), 0 1px 0 rgba(var(--fx-gold), .12);
  backdrop-filter: blur(14px) saturate(1.3);
}

/* ── split text ─────────────────────────────────────────────────────────── */
.fx-line { padding-bottom: .08em; margin-bottom: -.08em; }   /* room for descenders inside the mask */
.fx-w { display: inline-block; will-change: transform; }

/* ── hero ───────────────────────────────────────────────────────────────── */
.fx-hero { position: relative; isolation: isolate; }
.fx-hero > .fx-embers { position: absolute; inset: 0; pointer-events: none; z-index: 3; mix-blend-mode: screen; }
.fx-hero-dim {                                /* darkens the hero as it scrolls away */
  position: absolute; inset: 0; z-index: 4; pointer-events: none; background: #08090d; opacity: 0;
}

/* ── marquee of server software ─────────────────────────────────────────── */
.fx-marquee {
  position: relative; overflow: hidden; padding: 22px 0;
  border-top: 1px solid rgba(255, 255, 255, .06); border-bottom: 1px solid rgba(255, 255, 255, .06);
  background: linear-gradient(90deg, rgba(var(--fx-gold), .04), transparent 30%, transparent 70%, rgba(var(--fx-gold), .04));
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.fx-marquee-track { display: flex; width: max-content; will-change: transform; }
.fx-marquee-item {
  display: flex; align-items: center; gap: 12px; padding: 0 28px;
  font: 800 clamp(20px, 2.4vw, 30px)/1 'Archivo', 'Inter', system-ui, sans-serif;
  letter-spacing: -.02em; color: #f3f5f9; white-space: nowrap;
}
.fx-marquee-item img { width: 34px; height: 34px; object-fit: contain; image-rendering: pixelated; }
.fx-marquee-star { color: #f5c518; font-size: .7em; }
.fx-marquee-item.is-outline { color: transparent; -webkit-text-stroke: 1px rgba(255, 255, 255, .45); }

/* ── footer wordmark ────────────────────────────────────────────────────── */
.fx-wordmark {
  overflow: hidden; text-align: center; user-select: none; pointer-events: none;
  font: 900 clamp(64px, 17vw, 260px)/.82 'Archivo', 'Inter', system-ui, sans-serif; letter-spacing: -.05em;
  padding: 30px 0 0; margin-top: 10px; color: rgba(255, 255, 255, .07);
}
.fx-wordmark .fx-ch { display: inline-block; }
.fx-wordmark .fx-ch.is-gold { color: rgba(var(--fx-gold), .22); }

/* ── cards: lift, tilt and a spotlight that follows the cursor ─────────── */
.fx-card { position: relative; transition: translate .35s var(--fx-ease), rotate .35s var(--fx-ease), box-shadow .35s ease; }
.fx-card.fx-hover { translate: 0 -6px; box-shadow: 0 24px 50px -22px rgba(0, 0, 0, .9), 0 0 0 1px rgba(var(--fx-gold), .18); }
.fx-card > .fx-spot {
  position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 2;
  background: radial-gradient(420px circle at var(--fx-x, 50%) var(--fx-y, 50%), rgba(var(--fx-gold), .13), transparent 42%);
  opacity: 0; transition: opacity .3s ease;
}
.fx-card.fx-hover > .fx-spot { opacity: 1; }

/* ── buttons: shine, press ripple, magnetic pull ───────────────────────── */
.fx-btn { position: relative; overflow: hidden; isolation: isolate; transition: translate .25s var(--fx-ease); }
.fx-btn > .fx-shine {
  position: absolute; top: 0; bottom: 0; left: -60%; width: 45%; z-index: -1; pointer-events: none;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .55), transparent);
  transform: skewX(-20deg);
}
.fx-btn:hover > .fx-shine { animation: fx-shine .8s ease; }
@keyframes fx-shine { to { translate: 380% 0; } }
.fx-ripple {
  position: absolute; border-radius: 50%; pointer-events: none; z-index: -1;
  background: rgba(255, 255, 255, .45); scale: 0; animation: fx-ripple .6s ease-out forwards;
}
@keyframes fx-ripple { to { scale: 4; opacity: 0; } }

.fx-count { font-variant-numeric: tabular-nums; }

/* marks the copy so nobody mistakes it for the live site */
.fx-copy-pill {
  position: fixed; left: 14px; bottom: 14px; z-index: 900;
  font: 600 12px/1 Inter, system-ui, sans-serif; letter-spacing: .02em;
  color: #111; background: #f5c518; padding: 8px 12px; border-radius: 999px;
  text-decoration: none; box-shadow: 0 8px 24px -8px rgba(0, 0, 0, .7);
}
.fx-copy-pill:hover { background: #ffe57a; }

/* people who asked their OS for less motion get the site, not the show */
@media (prefers-reduced-motion: reduce) {
  .fx-curtain, .fx-embers { display: none !important; }
  .fx-btn:hover > .fx-shine { animation: none; }
}

/* ── dropdowns ──────────────────────────────────────────────────────────────
 * The site shows a menu by switching it from display:none to display:block,
 * which can't be animated either way. Here the menu is always rendered but
 * invisible and unclickable until it opens, so both opening and closing can
 * be transitions. The site's own centring uses `transform`; the motion uses
 * the separate `translate`/`scale` properties so the two never fight. On
 * phones the site hides these menus with !important, which still wins.
 */
.nav-dd-menu {
  display: block;
  visibility: hidden; opacity: 0; pointer-events: none;
  translate: 0 14px; scale: .94; transform-origin: 50% 0; filter: blur(6px);
  transition: opacity .18s ease, translate .22s ease, scale .22s ease, filter .18s ease, visibility 0s linear .22s;
}
.nav-dd-menu-simple { transform-origin: 100% 0; }
.nav-dd.open .nav-dd-menu {
  visibility: visible; opacity: 1; pointer-events: auto; translate: 0 0; scale: 1; filter: blur(0);
  transition: opacity .25s ease, translate .55s cubic-bezier(.2, 1.3, .3, 1), scale .55s cubic-bezier(.2, 1.3, .3, 1), filter .3s ease, visibility 0s;
}
/* the rows cascade in one after another, and drop away together on close */
.nav-dd-menu > :not(.fx-dd-glow) { opacity: 0; translate: 0 10px; transition: opacity .12s ease, translate .12s ease; }
.nav-dd.open .nav-dd-menu > :not(.fx-dd-glow) {
  opacity: 1; translate: 0 0;
  transition: opacity .35s ease calc(70ms + var(--i, 0) * 38ms), translate .5s var(--fx-ease) calc(70ms + var(--i, 0) * 38ms);
}
.nav-dd-caret { transition: transform .5s cubic-bezier(.3, 1.7, .5, 1) !important; }

/* a highlight that glides from row to row instead of each row lighting up alone */
.nav-dd-menu .nav-dd-item, .nav-dd-menu .nav-dd-link, .nav-dd-menu .nav-dd-foot { position: relative; z-index: 1; }
.nav-dd-menu .nav-dd-item:hover, .nav-dd-menu .nav-dd-link:hover, .nav-dd-menu .nav-dd-foot:hover { background: transparent; }
.fx-dd-glow {
  position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; border-radius: 10px;
  background: var(--bg-hover, #232733);
  box-shadow: inset 0 0 0 1px rgba(var(--fx-gold), .16), 0 6px 18px -10px rgba(var(--fx-gold), .5);
  opacity: 0; width: var(--gw, 0); height: var(--gh, 0); translate: var(--gx, 0) var(--gy, 0);
  transition: translate .32s var(--fx-ease), width .32s var(--fx-ease), height .32s var(--fx-ease), opacity .2s ease;
}
.fx-dd-glow.is-on { opacity: 1; }
.fx-dd-glow.is-jump { transition: opacity .2s ease; }   /* first row hovered: appear in place rather than slide from nowhere */
.nav-dd-menu .nav-dd-item:hover .nav-dd-item-price,
.nav-dd-menu .nav-dd-link:hover .nav-dd-ico { transition: translate .3s var(--fx-ease); translate: 3px 0; }

/* ── phone menu ─────────────────────────────────────────────────────────── */
.mobile-menu {
  display: flex;
  visibility: hidden; opacity: 0; pointer-events: none;
  clip-path: inset(0 0 100% 0);
  transition: clip-path .3s cubic-bezier(.5, 0, .75, 0), opacity .2s ease .1s, visibility 0s linear .3s;
}
.mobile-menu.open {
  visibility: visible; opacity: 1; pointer-events: auto;
  clip-path: inset(0 0 -60px 0);                /* the negative bottom keeps the drop shadow */
  transition: clip-path .6s cubic-bezier(.16, 1, .3, 1), opacity .15s ease, visibility 0s;
}
.mobile-menu > * { opacity: 0; translate: -16px 0; transition: opacity .12s ease, translate .12s ease; }
.mobile-menu.open > * {
  opacity: 1; translate: 0 0;
  transition: opacity .4s ease calc(90ms + var(--i, 0) * 45ms), translate .55s var(--fx-ease) calc(90ms + var(--i, 0) * 45ms);
}
/* sections inside it: smoother open, and their links slide in */
.mobile-group-body { transition: grid-template-rows .5s cubic-bezier(.16, 1, .3, 1) !important; }
.mobile-group-inner > *, .mobile-group-inner > div > a { opacity: 0; translate: -10px 0; transition: opacity .15s ease, translate .15s ease; }
.mobile-group.open .mobile-group-inner > *, .mobile-group.open .mobile-group-inner > div > a {
  opacity: 1; translate: 0 0;
  transition: opacity .35s ease calc(60ms + var(--i, 0) * 40ms), translate .45s var(--fx-ease) calc(60ms + var(--i, 0) * 40ms);
}

/* ── FAQ expanders ──────────────────────────────────────────────────────────
 * Smooth open and close where the browser supports animating to auto height
 * (current Chrome and Edge); elsewhere they open instantly as before.
 */
:root { interpolate-size: allow-keywords; }
details.faq-item::details-content, details.vps-faq-item::details-content {
  block-size: 0; overflow-y: clip; opacity: 0;
  transition: block-size .5s var(--fx-ease), opacity .35s ease, content-visibility .5s allow-discrete;
}
details.faq-item[open]::details-content, details.vps-faq-item[open]::details-content { block-size: auto; opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .nav-dd-menu, .nav-dd-menu > *, .mobile-menu, .mobile-menu > *, .mobile-group-inner > *, .fx-dd-glow { transition: none !important; filter: none !important; }
}

/* The reveal animations park elements rotated in 3D before they scroll into
   view; a rotated box is wider than the element, which gave phones a sideways
   scroll on /plans, /tos, /privacy and /buildforge. Clip (not hidden) so
   position:sticky keeps working. */
html, body { overflow-x: clip; }
@supports not (overflow-x: clip) { html, body { overflow-x: hidden; } }
