/* ============================================================================
   Karmanya — motion, typography and glass layers.
   Loaded after site.css. Kept separate so the base page renders correctly on
   its own and this file is purely additive polish.
   ========================================================================= */

/* Typography now lives in site.css so that every page shares it, including the
   four that do not load this file. Only the glass tokens remain here. */
:root {
  --glass: rgba(255, 255, 255, 0.045);
  --glass-line: rgba(255, 255, 255, 0.09);
}
/* ---------------------------------------------------------------- shader
   Sits above the CSS mesh and below the content. Fades in only once the WebGL
   context is actually live, so a failed shader shows the mesh rather than a
   black rectangle. */
#hero-shader {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  border: 0;
  opacity: 0;
  transition: opacity 1.1s ease;
  pointer-events: none;
  z-index: 0;
}
#hero-shader.is-live { opacity: 1; }

.hero { position: relative; isolation: isolate; }
.hero > .wrap { position: relative; z-index: 1; }

/* A soft horizon line where the shader dissolves into the page. */
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px; height: 180px;
  background: linear-gradient(to bottom, transparent, var(--ink-900));
  pointer-events: none;
  z-index: 0;
}

/* ---------------------------------------------------------------- word split */
[data-split] .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  /* Descenders get clipped by overflow:hidden without a little breathing room. */
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}
[data-split] .w > i { display: inline-block; font-style: inherit; }

/* ---------------------------------------------------------------- glass panels */
.glass {
  background: var(--glass);
  border: 1px solid var(--glass-line);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  border-radius: var(--radius-lg);
}

/* Cursor-following highlight. --mx/--my are written by motion.js; the fallback
   centre keeps it sane before the first pointer event and on touch devices. */
.card, .col, .shot { --mx: 50%; --my: 0%; }
.card::before, .col::before, .shot::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    340px circle at var(--mx) var(--my),
    rgba(142, 123, 239, 0.16),
    transparent 60%
  );
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
  z-index: 0;
}
.card:hover::before, .col:hover::before, .shot:hover::before { opacity: 1; }
.card, .col, .shot { position: relative; }
.card > *, .col > *, .shot > * { position: relative; z-index: 1; }

/* ---------------------------------------------------------------- marquee
   Two copies of the same track scrolling as one, so the loop has no seam.
   Duration is set from the measured width in motion.js. */
.marquee {
  overflow: hidden;
  position: relative;
  padding: 14px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  /* Fade both ends so words enter and leave rather than being cut off. */
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee-track {
  display: flex;
  gap: 42px;
  width: max-content;
  animation: marquee 40s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-item {
  display: inline-flex; align-items: center; gap: 42px;
  font-family: var(--font-display);
  font-size: clamp(20px, 2.6vw, 30px);
  color: var(--text-faint);
  white-space: nowrap;
}
.marquee-item b { color: var(--indigo-80); font-weight: 600; }
.marquee-item span { color: var(--saffron); opacity: 0.55; }
@keyframes marquee { to { transform: translateX(-50%); } }

.quote-rail {
  overflow: hidden;
  padding: 22px 0;
  border-top: 1px solid rgba(255,255,255,.06);
  border-bottom: 1px solid rgba(255,255,255,.06);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.quote-rail-track {
  display: flex;
  width: max-content;
  gap: 0;
  animation: marquee 90s linear infinite;
}
.quote-rail:hover .quote-rail-track { animation-play-state: paused; }
.quote-rail-item {
  display: inline-flex;
  align-items: center;
  gap: 36px;
  padding-right: 36px;
  white-space: nowrap;
}
.quote-rail q {
  font-family: var(--font-serif);
  font-size: clamp(15px, 1.7vw, 20px);
  font-style: italic;
  color: var(--text-dim);
  quotes: none;
}
.quote-rail q::before { content: "“"; color: var(--saffron); margin-right: 4px; }
.quote-rail q::after { content: "”"; color: var(--saffron); margin-left: 2px; opacity: .7; }

/* ---------------------------------------------------------------- phone rail */
.rail-wrap { overflow: hidden; padding: 8px 0 4px; }
.shots { will-change: transform; }

/* ---------------------------------------------------------------- number ticker */
.stats-row {
  display: grid; gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  margin-top: 44px;
}
.stat { padding: 22px; text-align: center; }
.stat b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(30px, 4.4vw, 46px);
  line-height: 1;
  background: linear-gradient(120deg, var(--indigo-80), var(--saffron));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.stat span { display: block; margin-top: 8px; color: var(--text-faint); font-size: 14px; }

/* ---------------------------------------------------------------- reduced motion
   The single most important block in this file: everything above is decoration,
   and a reader who has asked for stillness gets stillness. */
@media (prefers-reduced-motion: reduce) {
  #hero-shader { display: none; }
  .marquee-track { animation: none; transform: none; }
  .quote-rail-track { animation: none; transform: none; }
  [data-split] .w > i { transform: none !important; opacity: 1 !important; }
  .card::before, .col::before, .shot::before { display: none; }
}

/* ---------------------------------------------------------------- skip link
   Keyboard users need a way past the nav; it stays out of sight until focused. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--indigo-40); color: #fff;
  padding: 12px 18px; border-radius: 0 0 12px 0; text-decoration: none;
}
.skip-link:focus { left: 0; }

/* A store button whose URL is not live yet: still readable, clearly not ready. */
.btn.is-pending { position: relative; }
.btn.is-pending::after {
  content: "soon";
  margin-left: 8px; padding: 2px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  background: rgba(255, 255, 255, 0.16);
}

/* The screenshot rail is wider than the page and drifts, so it needs room to
   move without triggering a horizontal scrollbar on the document. */
.rail-wrap { margin: 0 -24px; padding-left: 24px; padding-right: 24px; }

/* ---------------------------------------------------------------- rail layout
   The screenshot row is a *rail*, not a grid: motion.js drifts it sideways, so
   it has to stay on one line. site.css lays .shots out as auto-fit grid columns,
   which wrapped the 5th phone onto its own row and left a large dead gap. Flex
   with non-shrinking children keeps all five on one line and lets the row be
   wider than the viewport, which is the effect. */
.rail-wrap .shots {
  display: flex;
  gap: 18px;
  grid-template-columns: none;
  justify-content: center;
}
.rail-wrap .shot { flex: 0 0 clamp(150px, 17vw, 208px); }

@media (max-width: 860px) {
  /* On narrow screens a centred 5-up row is unreadable, so let it scroll
     horizontally instead and drop the drift (motion.js parallax on a scrollable
     rail fights the user's own swipe). */
  .rail-wrap .shots { justify-content: flex-start; overflow-x: auto; scroll-snap-type: x mandatory; padding-bottom: 10px; }
  .rail-wrap .shot { flex: 0 0 46vw; scroll-snap-align: center; }
}
