/* ===================================================================
   Mystikon Studios — landing page
   Same palette and component language as the PVLK documentation site
   (pvlkdocs.mystikonstudios.com), reshaped into a single modern
   landing page with a sticky 16:9 hero background.
   =================================================================== */

:root {
  /* Tells the browser this page themes itself. Without it, Chromium's
     "auto dark theme" (on by default in some mobile browsers, e.g. Brave)
     re-tints our colors and the theme toggle appears not to work. */
  color-scheme: light;
  --bg: #f5f6f8;
  --panel: #ffffff;
  --panel-glass: rgba(255, 255, 255, 0.72);  /* frosted header once scrolled */
  --text: #1c2733;
  --text-dim: #374654;
  --accent: #2d7dd2;
  --accent-soft: #e3eefb;
  --border: #a8c1e1;
  --glow-rgb: 45, 125, 210;   /* card glow edge color (r, g, b) */
}

[data-theme="dark"] {
  color-scheme: dark;
  --bg: #15171a;
  --panel: #1d2126;
  --panel-glass: rgba(29, 33, 38, 0.72);
  --text: #e8e6e1;
  --text-dim: #c1ccd8;
  --accent: #3878c2;
  --accent-soft: #1b2c40;
  --border: #2d5788;
  --glow-rgb: 120, 200, 255;  /* card glow edge color (r, g, b) */
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.65;
  font-size: 16px;
}

/* Every hyperlink stays the accent color in every state (including
   visited) — on a landing page a purple visited CTA would look broken. */
a, a:link, a:visited, a:active { color: var(--accent); }
a:hover { color: #469af3; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

::selection { background: var(--accent); color: #fff; }

/* ===================================================================
   HEADER
   Fixed on top of everything. While the hero image is behind it the
   header is transparent with light text; once the page scrolls (the
   "scrolled" class from js/site.js) it becomes a frosted glass panel
   using the theme colors — a modern take on the docs site's header.
   =================================================================== */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  display: flex; align-items: center; gap: 18px;
  padding: 14px 5%;
  color: #fff;                          /* over the hero image */
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background 300ms ease, border-color 300ms ease,
              color 300ms ease, padding 300ms ease, box-shadow 300ms ease;
}
.site-header.scrolled {
  color: var(--text);
  background: var(--panel-glass);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  backdrop-filter: blur(12px) saturate(140%);
  border-bottom: 1px solid var(--border);
  padding: 10px 5%;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
}

.site-header .brand {
  display: flex; align-items: center; gap: 10px;
  text-decoration: none; font-weight: 600; font-size: 18px;
}
.site-header .brand,
.site-header .brand:link, .site-header .brand:visited { color: inherit; }
.site-header .brand img {
  height: 34px; width: 34px; border-radius: 50%; object-fit: cover;
}

.site-header .spacer { flex: 1; }

.header-link {
  text-decoration: none; font-size: 15px; font-weight: 600;
  padding: 6px 12px; border-radius: 8px;
}
.header-link, .header-link:link, .header-link:visited { color: inherit; }
.header-link:hover { color: inherit; background: rgba(128, 160, 200, 0.18); }

.theme-toggle {
  display: inline-flex; align-items: center; gap: 8px;
  background: none; border: 1px solid rgba(255, 255, 255, 0.45); border-radius: 8px;
  color: inherit; padding: 6px 12px; cursor: pointer; font-size: 14px;
  font-family: inherit;
  transition: border-color 200ms ease;
}
.site-header.scrolled .theme-toggle { border-color: var(--border); }
.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }
.theme-toggle img { height: 18px; width: auto; display: block; }

/* ===================================================================
   HERO — the sticky 16:9 background
   The section is pinned (position: sticky, top: 0) so the image holds
   the top of the page while the .sheet below scrolls up over it.
   Height honors the image's 16:9 ratio (56.25vw) on wide screens,
   capped at one viewport and floored so phones still get a real hero.

   --hp is the scroll progress (0 = page top, 1 = hero fully covered),
   written by initHeroParallax() in js/site.js. It drives:
     - a slow zoom on the image        (feels like depth)
     - the darkening layer .hero-dim   (image recedes as content arrives)
     - the content fade / lift         (title floats away a bit faster)
   =================================================================== */
.hero {
  position: sticky; top: 0; z-index: 0;
  height: min(max(56.25vw, 560px), 100vh);
  height: min(max(56.25vw, 560px), 100svh);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  --hp: 0;
}

.hero-media { position: absolute; inset: 0; }

.hero-bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  transform: scale(calc(1 + var(--hp) * 0.08));
  will-change: transform;
}

/* Legibility gradient: gently darker at the top (under the header) and
   the bottom (under the title/buttons), regardless of the image. */
.hero-scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg,
      rgba(8, 10, 14, 0.55) 0%,
      rgba(8, 10, 14, 0.15) 30%,
      rgba(8, 10, 14, 0.15) 55%,
      rgba(8, 10, 14, 0.72) 100%);
}

/* Extra darkening tied to scroll — the image calmly recedes. */
.hero-dim {
  position: absolute; inset: 0;
  background: #0a0c10;
  opacity: calc(var(--hp) * 0.55);
}

/* Placeholder note, only visible when assets/hero-background.png is
   missing (the "no-image" class is set by initHeroFallback in site.js). */
.hero-hint { display: none; }
.hero.no-image .hero-bg { display: none; }
.hero.no-image .hero-media {
  background:
    radial-gradient(90vw 60vh at 70% 10%, rgba(56, 120, 194, 0.35), transparent 60%),
    radial-gradient(70vw 50vh at 15% 80%, rgba(45, 125, 210, 0.22), transparent 55%),
    #101318;
}
.hero.no-image .hero-hint {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
  padding: 6px 14px; border: 1px dashed rgba(255, 255, 255, 0.4); border-radius: 8px;
  color: rgba(255, 255, 255, 0.65); font-size: 13px; white-space: nowrap;
}
.hero-hint code { font-family: Consolas, "Courier New", monospace; font-size: 12px; }

/* Hero content — always light text (the scrim guarantees contrast in
   both themes, since it sits on the image, not the page background). */
.hero-inner {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center;
  text-align: center; padding: 72px 24px 96px; /* bottom padding keeps the CTA clear of the scroll cue */
  color: #fff;
  opacity: calc(1 - min(var(--hp) * 1.5, 1));
  transform: translateY(calc(var(--hp) * -46px));
}

.hero-mark {
  width: 96px; height: 96px; border-radius: 50%; object-fit: cover;
  margin-bottom: 22px;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.22),
    0 0 48px rgba(var(--glow-rgb), 0.45);
}

.hero-title {
  font-size: clamp(42px, 7vw, 84px);
  font-weight: 700; line-height: 1.05; letter-spacing: -0.02em;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.45);
}
.hero-title .grad {
  background: linear-gradient(92deg, #bde2fd 0%, #469af3 55%, #3780cd 100%);
  /* background: radial-gradient(circle at top,#bde2fd 0%,#037bfb 100%); */
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero-tag {
  margin-top: 14px;
  font-size: clamp(17px, 2.2vw, 22px);
  color: rgba(255, 255, 255, 0.88);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.5);
}

.hero-cta { display: flex; gap: 14px; margin-top: 34px; flex-wrap: wrap; justify-content: center; }

/* Bouncing scroll cue at the bottom of the hero; fades out immediately
   once scrolling starts (tied to --hp). */
.scroll-cue {
  position: absolute; left: 50%; bottom: 26px; z-index: 1;
  transform: translateX(-50%);
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  color: rgba(255, 255, 255, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: rgba(10, 12, 16, 0.25);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: calc(1 - min(var(--hp) * 4, 1));
  animation: cue-bob 2.2s ease-in-out infinite;
}
.scroll-cue:hover { border-color: rgba(255, 255, 255, 0.7); color: #fff; }
/* very short windows (small laptops, landscape phones): the cue would
   crowd the CTA buttons, so let it go */
@media (max-height: 560px) { .scroll-cue { display: none; } }
@keyframes cue-bob {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(7px); }
}

/* ===================================================================
   BUTTONS
   =================================================================== */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 24px; border-radius: 10px;
  font-size: 16px; font-weight: 600; text-decoration: none;
  transition: transform 180ms ease, box-shadow 180ms ease,
              background 180ms ease, border-color 180ms ease;
}
.btn .btn-arrow { transition: transform 180ms ease; }
.btn:hover .btn-arrow { transform: translateX(3px); }

.btn-primary,
.btn-primary:link, .btn-primary:visited { color: #fff; }
.btn-primary {
  background: linear-gradient(135deg, #3d8de0, #2d7dd2);
  box-shadow: 0 4px 18px rgba(var(--glow-rgb), 0.35);
}
.btn-primary:hover {
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 8px 28px rgba(var(--glow-rgb), 0.5);
}

.btn-ghost,
.btn-ghost:link, .btn-ghost:visited { color: #fff; }
.btn-ghost {
  border: 1px solid rgba(255, 255, 255, 0.45);
  background: rgba(10, 12, 16, 0.25);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.btn-ghost:hover { color: #fff; border-color: #fff; transform: translateY(-2px); }

/* ===================================================================
   SHEET — the content layer that slides over the pinned hero.
   Rounded top corners + a faint accent hairline along the top edge
   make it read as a physical sheet passing over the image.
   =================================================================== */
.sheet {
  position: relative; z-index: 2;
  background: var(--bg);
  border-radius: 26px 26px 0 0;
  margin-top: -26px;
  box-shadow: 0 -24px 60px rgba(0, 0, 0, 0.35);
}
.sheet::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  border-radius: 26px 26px 0 0;
  background: linear-gradient(90deg,
    transparent 5%, rgba(var(--glow-rgb), 0.55) 50%, transparent 95%);
}

.section {
  max-width: 1060px;
  margin: 0 auto;
  padding: 84px 5% 24px;
}

.section-head { max-width: 640px; }
.section h2 { font-size: clamp(26px, 3.4vw, 36px); margin: 10px 0 4px; }
.lede { font-size: 18px; color: var(--text-dim); margin-top: 8px; }

.badge {
  display: inline-block; background: var(--accent-soft); color: var(--accent);
  border-radius: 20px; padding: 2px 12px; font-size: 13px; font-weight: 600;
  margin-bottom: 8px;
}

/* ===================================================================
   CARDS — same construction as the docs site (panel, border, radius,
   accent heading, mouse-responsive glow), scaled up for a landing page.
   =================================================================== */
.card-grid {
  display: grid; grid-template-columns: 1.6fr 1fr;
  gap: 16px; margin: 34px 0 0;
}

.card {
  display: block; position: relative;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 14px; padding: 28px;
  text-decoration: none; color: var(--text);
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}
.card, .card:link, .card:visited { color: var(--text); }
.card h3 { margin: 4px 0 10px; color: var(--accent); font-size: 21px; }
.card p { margin: 0; font-size: 15px; color: var(--text-dim); }
a.card:hover {
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.22);
}

.card-logo { height: 44px; width: auto; display: block; margin-bottom: 14px; }

.card-link {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 18px; font-weight: 600; font-size: 15px; color: var(--accent);
}
a.card:hover .card-link .btn-arrow { transform: translateX(3px); }
.card-link .btn-arrow { transition: transform 180ms ease; }

/* "Coming soon" card: intentionally quieter, with a soft pulsing dot. */
.card-soon { border-style: dashed; }
.card-soon h3 { color: var(--text-dim); }
.soon-dot {
  position: absolute; top: 30px; right: 26px;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--accent);
  animation: soon-pulse 2.4s ease-in-out infinite;
}
@keyframes soon-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--glow-rgb), 0.5); }
  50%      { box-shadow: 0 0 0 9px rgba(var(--glow-rgb), 0); }
}

/* -------------------------------------------------------------------
   CARD GLOW (mouse-responsive edge highlight) — ported from the docs
   site. A sliver of the card border lights up nearest the cursor,
   driven by initCardGlow() in js/site.js, which sets --mx / --my /
   --glow per card and adds "glow-on" to <html> only when the browser
   qualifies (mouse + hover, CSS masking, no reduced-motion).
   ------------------------------------------------------------------- */
html.glow-on a.card:hover { border-color: var(--border); } /* the glow IS the hover feedback */

html.glow-on .card::before,
html.glow-on .card::after {
  content: "";
  position: absolute;
  border-radius: 14px;
  pointer-events: none;
  opacity: var(--glow, 0);
}

/* edge ring: a radial gradient masked down to a 1.5px border sliver */
html.glow-on .card::before {
  inset: -1px;
  padding: 1.5px;
  background: radial-gradient(160px circle at var(--mx, 50%) var(--my, 50%),
              rgb(var(--glow-rgb)), rgba(var(--glow-rgb), 0.55) 22%, transparent 55%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
}

/* soft interior bloom near the cursor */
html.glow-on .card::after {
  inset: 0;
  background: radial-gradient(180px circle at var(--mx, 50%) var(--my, 50%),
              rgba(var(--glow-rgb), 0.06), transparent 50%);
}
/* card glow end */

/* ===================================================================
   CONTACT + FOOTER
   =================================================================== */
.contact { text-align: center; padding-bottom: 96px; }
.contact p { color: var(--text-dim); margin: 6px 0 26px; }

.site-footer {
  border-top: 1px solid var(--border);
  padding: 24px; text-align: center; font-size: 14px; color: var(--text-dim);
}
.site-footer a { color: var(--accent); }

/* ===================================================================
   SCROLL REVEAL — elements with .reveal start slightly low and
   transparent, then ease in the first time they enter the viewport
   (initReveal in js/site.js adds .in). Cards stagger via delays.
   =================================================================== */
.reveal { opacity: 0; transform: translateY(26px); }
.reveal.in {
  opacity: 1; transform: none;
  transition: opacity 650ms ease, transform 650ms cubic-bezier(0.16, 1, 0.3, 1);
}
.card-grid .reveal.in:nth-child(2) { transition-delay: 120ms; }

/* ===================================================================
   RESPONSIVE
   =================================================================== */
@media (max-width: 820px) {
  .card-grid { grid-template-columns: 1fr; }
  .header-link { display: none; }
  .theme-toggle span { display: none; }   /* icon only — the label doesn't fit */
  .theme-toggle { padding: 6px 8px; }
  .section { padding-top: 64px; }
  .hero-cta .btn { padding: 12px 20px; font-size: 15px; }
}

/* ===================================================================
   REDUCED MOTION — no parallax vars get written (site.js checks too),
   reveals appear instantly, nothing bobs or pulses.
   =================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }
  .scroll-cue, .soon-dot { animation: none; }
  .btn, .card, .btn .btn-arrow, .card-link .btn-arrow { transition: none; }
}
