/* iVybe — shared site styles.
   Built on the locked Design System (Notion → Design → Design System, v0.3).
   Every token here has a counterpart in apps/mobile/lib/core/config/. When the
   two disagree, the Design System wins and this file is wrong. */

@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT@0,9..144,100..900,0..100;1,9..144,100..900,0..100&family=Outfit:wght@200;300;400;500&display=swap');

:root {
  /* §1 Brand gradient — the DNA strand. One gradient, never three discrete colors. */
  --brand-pink: #ff2ec8;
  --brand-pink-violet: #c850ff;
  --brand-violet: #9c40ff;
  --brand-violet-blue: #4a7eff;
  --brand-cyan: #00cfff;
  --brand-gradient: linear-gradient(90deg,
    var(--brand-pink) 0%,
    var(--brand-pink-violet) 32%,
    var(--brand-violet) 50%,
    var(--brand-violet-blue) 68%,
    var(--brand-cyan) 100%);

  /* §1 Mode colors — sacred. They carry semantic load; never drift them. */
  --mode-dating: #ff2ec8;
  --mode-dating-light: #ff80e0;
  --mode-chatting: #00cfff;
  --mode-chatting-accent: #00e5ff;
  --mode-chatting-light: #80eaff;
  --mode-meeting: #ff9800;
  --mode-meeting-light: #ffcc80;

  /* §1 Surface */
  --bg-base: #050509;
  --bg-deeper: #030308;
  --surface-elevated: #0e0e18;

  /* §1 Glass alphas — the workhorse values for layered glass */
  --glass-base: rgba(255, 255, 255, 0.04);
  --glass-emphasis: rgba(255, 255, 255, 0.07);
  --glass-border: rgba(255, 255, 255, 0.13);
  --glass-specular: rgba(255, 255, 255, 0.20);
  --glass-rim: rgba(255, 255, 255, 0.40);

  /* §1 Text alphas */
  --text-primary: rgba(255, 255, 255, 1);
  --text-secondary: rgba(255, 255, 255, 0.84);
  --text-body: rgba(255, 255, 255, 0.70);
  --text-tagline: rgba(255, 255, 255, 0.62);
  --text-trust: rgba(255, 255, 255, 0.52);
  --text-muted: rgba(255, 255, 255, 0.45);
  --text-fine: rgba(255, 255, 255, 0.35);
  --text-faint: rgba(255, 255, 255, 0.24);

  /* §2 Type */
  --serif: 'Fraunces', Georgia, serif;
  --sans: 'Outfit', system-ui, -apple-system, sans-serif;

  /* §4 Motion — easings */
  --ease-standard: ease-out;
  --ease-cinematic: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-loop: ease-in-out;

  /* §4 Motion — durations */
  --dur-micro: 0.15s;
  --dur-quick: 0.55s;
  --dur-cinematic: 0.7s;

  --r-md: 14px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 100px;

  --maxw: 1120px;
  --gutter: 40px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }

/* Two registers, deliberately.
   Fraunces is the VOICE — display headings, taglines, the thesis line, button labels.
   Outfit is the INFORMATION — running paragraphs, lists, legal prose, UI labels.
   Design System §2 assigns body copy to Fraunces, which is right for the app where
   every string is short. This is a long-form marketing surface: set whole paragraphs
   in Fraunces and the page goes monotone and heavy. Splitting the two registers is a
   deliberate divergence for web, and it's what makes both fonts earn their place. */
body {
  background: var(--bg-base);
  color: var(--text-body);
  font-family: var(--sans);
  font-weight: 300;
  line-height: 1.7;
  overflow-x: hidden;
  min-height: 100vh;
  position: relative;
  -webkit-font-smoothing: antialiased;
}

/* The cosmos layer.
   §Codex → The Cosmic Metaphor: the dark cosmos is not background, it is the world.
   Ambient glows drift; stars are people; orbits are atmosphere. */

.cosmos {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

/* Cosmos rings — the sign-in screen's composition, carried to the web.
   Three big mode-colour arcs cropped into the edges (magenta top-left, amber
   right, cyan bottom-right) plus small violet accent ringlets. Ported from
   SignInRingsPainter in apps/mobile/lib/core/cosmos/cosmic_rings.dart, with the
   layered stroke recipe from Design System §5 (wash / mid glow / crisp stroke /
   inner highlight / inner ghost) and radii scaled from the 390x844 phone frame
   to a landscape canvas. Low group opacity on purpose: big enough to fill the
   canvas with atmosphere, faint enough to stay background.

   It lives here rather than in each page's markup so one definition serves all
   four pages. */
.cosmos::before {
  content: '';
  position: absolute;
  inset: -5%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 900' preserveAspectRatio='xMidYMid slice'%3E%3Cg opacity='.30' fill='none'%3E%3Ccircle cx='150' cy='180' r='340' stroke='%23ff2ec8' stroke-width='31' opacity='.07'/%3E%3Ccircle cx='150' cy='180' r='340' stroke='%23ff2ec8' stroke-width='12' opacity='.22'/%3E%3Ccircle cx='150' cy='180' r='340' stroke='%23ff2ec8' stroke-width='3.9'/%3E%3Ccircle cx='150' cy='180' r='287' stroke='%23ff80e0' stroke-width='1.5' opacity='.55'/%3E%3Ccircle cx='150' cy='180' r='224' stroke='%23ff2ec8' stroke-width='1' opacity='.3'/%3E%3C/g%3E%3Cg opacity='.22' fill='none'%3E%3Ccircle cx='1450' cy='430' r='300' stroke='%23ff9800' stroke-width='27' opacity='.07'/%3E%3Ccircle cx='1450' cy='430' r='300' stroke='%23ff9800' stroke-width='10.5' opacity='.22'/%3E%3Ccircle cx='1450' cy='430' r='300' stroke='%23ff9800' stroke-width='3.4'/%3E%3Ccircle cx='1450' cy='430' r='250' stroke='%23ffcc80' stroke-width='1.3' opacity='.42'/%3E%3C/g%3E%3Cg opacity='.24' fill='none'%3E%3Ccircle cx='1330' cy='880' r='400' stroke='%2300cfff' stroke-width='36' opacity='.07'/%3E%3Ccircle cx='1330' cy='880' r='400' stroke='%2300cfff' stroke-width='14' opacity='.22'/%3E%3Ccircle cx='1330' cy='880' r='400' stroke='%2300cfff' stroke-width='4.5'/%3E%3Ccircle cx='1330' cy='880' r='335' stroke='%2380eaff' stroke-width='1.6' opacity='.5'/%3E%3Ccircle cx='1330' cy='880' r='265' stroke='%2300cfff' stroke-width='1.1' opacity='.3'/%3E%3C/g%3E%3Cg fill='none' stroke='%239c40ff'%3E%3Ccircle cx='1080' cy='130' r='26' stroke-width='2' opacity='.45'/%3E%3Ccircle cx='300' cy='520' r='22' stroke-width='1.6' opacity='.32'/%3E%3Ccircle cx='1180' cy='640' r='20' stroke-width='1.6' opacity='.35'/%3E%3C/g%3E%3C/svg%3E");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  /* §4 choreography: rings fade in at 0.3s over 0.9s, after the ambient glows. */
  opacity: 0;
  animation: mount-fade 0.9s var(--ease-standard) 0.3s forwards;
}

/* Ambient glow — §5. Radial, low alpha, always asymmetric placement. */
.glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
}
.glow-magenta {
  top: -12%; left: -8%;
  width: 62vw; height: 62vw;
  background: radial-gradient(circle, rgba(255, 46, 200, 0.13) 0%, transparent 68%);
  animation: drift-a 15s var(--ease-loop) infinite;
}
.glow-cyan {
  bottom: -16%; right: -10%;
  width: 58vw; height: 58vw;
  background: radial-gradient(circle, rgba(0, 207, 255, 0.12) 0%, transparent 68%);
  animation: drift-b 17s var(--ease-loop) infinite;
}
.glow-violet {
  top: 34%; left: 46%;
  width: 46vw; height: 46vw;
  background: radial-gradient(circle, rgba(156, 64, 255, 0.11) 0%, transparent 70%);
  animation: drift-c 13s var(--ease-loop) infinite;
}

/* §4 Drift — 9–17s, translate ±10–18px. Everything breathes; nothing blinks. */
@keyframes drift-a {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(16px, 12px); }
}
@keyframes drift-b {
  0%, 100% { transform: translate(0, 0); }
  50%      { transform: translate(-14px, -16px); }
}
@keyframes drift-c {
  0%, 100% { transform: translate(-50%, -50%); }
  50%      { transform: translate(calc(-50% + 12px), calc(-50% - 10px)); }
}

/* Stars are people. Faint mode-colored specks — other Vybers sensed from distance. */
.star {
  position: absolute;
  width: 2px; height: 2px;
  border-radius: 50%;
  opacity: 0.55;
  animation: pulse-star 2.4s var(--ease-loop) infinite;
}
.star.dating   { background: var(--mode-dating);   box-shadow: 0 0 5px var(--mode-dating); }
.star.chatting { background: var(--mode-chatting); box-shadow: 0 0 5px var(--mode-chatting); }
.star.meeting  { background: var(--mode-meeting);  box-shadow: 0 0 5px var(--mode-meeting); }
.star.violet   { background: var(--brand-violet);  box-shadow: 0 0 5px var(--brand-violet); }

@keyframes pulse-star {
  0%, 100% { opacity: 0.30; transform: scale(1); }
  50%      { opacity: 0.75; transform: scale(1.3); }
}

/* Orbits are atmosphere — tiny outline ringlets, drifting at the edges.
   §Codex restraint: 2–3 per screen, no more. Accents, not a field. */
.orbit {
  position: absolute;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.05);
  animation: float-orbit 20s linear infinite;
}

@keyframes float-orbit {
  0%   { transform: translateY(0) rotate(0deg); opacity: 0; }
  12%  { opacity: 0.7; }
  88%  { opacity: 0.7; }
  100% { transform: translateY(-420px) rotate(120deg); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  /* Anything that starts at opacity 0 and is revealed by an animation must be
     forced visible here, or with animations off it never appears. */
  .mount, .mount-fade { opacity: 1 !important; transform: none !important; }
  .cosmos::before { opacity: 1 !important; }
}

/* §4 Mount choreography — "the curtain rises."
   Elements declare a delay; the sequence runs once on load. */
.mount {
  opacity: 0;
  transform: translateY(12px);
  animation: mount-in var(--dur-quick) var(--ease-cinematic) forwards;
}
.mount-fade {
  opacity: 0;
  animation: mount-fade var(--dur-cinematic) var(--ease-standard) forwards;
}
@keyframes mount-in {
  to { opacity: 1; transform: translateY(0); }
}
@keyframes mount-fade {
  to { opacity: 1; }
}
.d1 { animation-delay: 0.10s; }
.d2 { animation-delay: 0.25s; }
.d3 { animation-delay: 0.40s; }
.d4 { animation-delay: 0.55s; }
.d5 { animation-delay: 0.70s; }
.d6 { animation-delay: 0.85s; }
.d7 { animation-delay: 1.00s; }

/* Layout */
.shell { position: relative; z-index: 2; }

.band {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 120px var(--gutter) 0;
}

/* §2 Typography */
h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 300;
  color: var(--text-primary);
  line-height: 1.1;
}

h1 {
  font-size: clamp(40px, 6vw, 68px);
  font-variation-settings: 'opsz' 144, 'SOFT' 50, 'WONK' 0;
  letter-spacing: 0.02em;
}

h2 {
  font-size: clamp(30px, 4vw, 46px);
  font-variation-settings: 'opsz' 144, 'SOFT' 50, 'WONK' 0;
  letter-spacing: 0.01em;
}

h3 {
  font-size: 21px;
  font-variation-settings: 'opsz' 36, 'SOFT' 50, 'WONK' 0;
  letter-spacing: 0.01em;
  line-height: 1.3;
}

p {
  font-family: var(--sans);
  color: var(--text-body);
  font-size: 16.5px;
  font-weight: 300;
  line-height: 1.75;
  letter-spacing: 0.005em;
  max-width: 68ch;
}

li { font-family: var(--sans); font-weight: 300; }

strong { color: var(--text-primary); font-weight: 500; }

/* Emphasis switches register rather than weight — §2: no mid-sentence bolding. */
em {
  font-family: var(--serif);
  font-style: italic;
  font-variation-settings: 'opsz' 36, 'SOFT' 50, 'WONK' 0;
  color: var(--text-secondary);
}

a { color: var(--mode-chatting-light); text-decoration-color: rgba(128, 234, 255, 0.35); }
a:hover { text-decoration-color: var(--mode-chatting-light); }

/* §2 type/eyebrow — Outfit owns small-caps. Never Fraunces. */
.eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 300;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  color: var(--text-fine);
  display: block;
}

.eyebrow-center { text-align: center; }

/* §2 type/caplet */
.caplet {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 300;
  letter-spacing: 0.45em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Wordmark. The real neon artwork lives in assets/logo-wordmark.png; the slot reserves
   its space so replacing the art never moves the composition around it. */
.wordmark-slot {
  display: block;
  width: min(560px, 84vw);
  margin: 0 auto;
}

/* The source art was exported on black with no alpha. It carries a real alpha channel
   now, derived from luminance and un-premultiplied (see assets/README.md), so it
   composites over the cosmos with no blend-mode tricks. */
.wordmark-art {
  display: block;
  width: 100%;
  height: auto;
}

/* §6 Wordmark line */
.wordmark-line {
  width: 52px;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(156, 64, 255, 0.7), transparent);
  margin: 18px auto 14px;
}

/* §5 Brand halo — ties the mark block visually into one unit */
.brand-halo {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 420px; height: 260px;
  background: radial-gradient(ellipse at center, rgba(156, 64, 255, 0.12), transparent 60%);
  filter: blur(20px);
  pointer-events: none;
  z-index: -1;
}

/* §5 iVybe Glass — the GlassSurface primitive.
   Two-light glass: warm direct light above, cool reflected light below, clear centre.
   Second law: glass is RESERVED, not the default surface. One featured surface per
   view — everything else is plain, or the page reads inert. */
.glass {
  position: relative;
  border-radius: var(--r-xl);
  border: 1px solid var(--glass-rim);
  background:
    linear-gradient(180deg,
      rgba(255, 128, 224, 0.20) 0%,
      transparent 40%,
      transparent 60%,
      rgba(74, 126, 255, 0.10) 100%);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  box-shadow:
    0 6px 24px rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.10);
  overflow: hidden;
}

/* The top light line — the wordmark brushstroke flattened and pinned to the top edge.
   Craft note from the Glass Session: single biggest contributor to the premium read. */
.glass::before {
  content: '';
  position: absolute;
  top: 0; left: 12%; right: 12%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
}

/* Plain surface — the default. Not glass. Recedes. */
.plain {
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

/* Nav */
.nav {
  position: relative;
  z-index: 3;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 30px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.nav-brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  font-family: var(--serif);
  font-variation-settings: 'opsz' 36, 'SOFT' 50, 'WONK' 0;
  font-size: 19px;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--text-primary);
}
.nav-brand img { display: block; }

.nav-links { display: flex; gap: 26px; align-items: center; }

.nav-links a {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 300;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--text-fine);
  text-decoration: none;
  transition: color var(--dur-micro) var(--ease-standard);
}
.nav-links a:hover { color: var(--mode-chatting-light); }

/* Buttons — §6 GlassButton.
   Primary = Glow Up (matte interior, brand-gradient stroke, outer bloom).
   Secondary = iVybe Glass. Active surfaces rise and light up. */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--serif);
  font-variation-settings: 'opsz' 14, 'SOFT' 50, 'WONK' 0;
  font-size: 15px;
  font-weight: 400;
  letter-spacing: 0.01em;
  text-decoration: none;
  padding: 17px 32px;
  border-radius: var(--r-pill);
  color: var(--text-primary);
  border: 1px solid var(--glass-border);
  background: var(--glass-base);
  transition: transform var(--dur-micro) var(--ease-standard),
              box-shadow var(--dur-micro) var(--ease-standard),
              border-color var(--dur-micro) var(--ease-standard);
}
.btn:hover { transform: translateY(-2px); border-color: var(--glass-rim); }
.btn:active { transform: scale(0.97); }

.btn-primary {
  background: var(--bg-base);
  border: none;
  padding: 0;
}
.btn-primary .btn-inner {
  display: block;
  margin: 1.5px;
  padding: 15.5px 30.5px;
  border-radius: var(--r-pill);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.11), rgba(255, 255, 255, 0.02)),
    var(--bg-base);
}
.btn-primary {
  background-image: var(--brand-gradient);
  box-shadow: 0 0 32px rgba(156, 64, 255, 0.28);
}
.btn-primary:hover { box-shadow: 0 0 46px rgba(156, 64, 255, 0.42); }

/* §6 Sparkle divider — ceremonial. Lifts a trust statement out of fine print. */
.sparkle-divider {
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: 280px;
  margin: 0 auto;
}
.sparkle-divider .line {
  flex: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.20), transparent);
}

/* §6 Pulse dot — live-signal indicator beside trust statements */
.pulse-dot {
  display: inline-block;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--mode-chatting-accent);
  box-shadow: 0 0 6px rgba(0, 229, 255, 0.9);
  animation: pulse-dot 2s var(--ease-loop) infinite;
  flex-shrink: 0;
}
@keyframes pulse-dot {
  0%, 100% { opacity: 0.55; transform: scale(1); }
  50%      { opacity: 1;    transform: scale(1.35); }
}

/* Footer */
.site-footer { position: relative; z-index: 2; margin-top: 140px; }
.site-footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 44px var(--gutter);
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  align-items: center;
  justify-content: space-between;
}
.site-footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--serif);
  font-variation-settings: 'opsz' 36, 'SOFT' 50, 'WONK' 0;
  font-size: 16px;
  font-weight: 400;
  color: var(--text-secondary);
}
.site-footer-tag {
  font-family: var(--serif);
  font-style: italic;
  font-variation-settings: 'opsz' 14, 'SOFT' 50, 'WONK' 0;
  font-size: 13px;
  color: var(--text-fine);
  margin-top: 6px;
}
.site-footer-links { display: flex; gap: 24px; flex-wrap: wrap; }
.site-footer-links a {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 300;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--text-fine);
  text-decoration: none;
  transition: color var(--dur-micro) var(--ease-standard);
}
.site-footer-links a:hover { color: var(--mode-chatting-light); }
.site-footer-legal {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter) 44px;
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 300;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Legal / prose pages */
.doc {
  position: relative;
  z-index: 2;
  max-width: 780px;
  margin: 0 auto;
  padding: 30px var(--gutter) 0;
}
.doc-head { margin-bottom: 52px; text-align: center; }
.doc-head h1 { margin: 22px 0 18px; }
.doc-meta {
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 300;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.doc h2 {
  font-size: 24px;
  font-variation-settings: 'opsz' 48, 'SOFT' 50, 'WONK' 0;
  color: var(--text-primary);
  margin: 52px 0 18px;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.doc h3 {
  font-size: 17px;
  font-variation-settings: 'opsz' 24, 'SOFT' 50, 'WONK' 0;
  color: var(--text-secondary);
  margin: 30px 0 12px;
}
.doc p { margin-bottom: 18px; max-width: none; }
.doc ul { margin: 18px 0; padding-left: 22px; }
.doc li { margin-bottom: 12px; line-height: 1.7; }
.doc li::marker { color: var(--brand-violet); }
.doc hr { border: none; height: 1px; background: rgba(255, 255, 255, 0.06); margin: 48px 0 0; }

.doc-intro {
  padding: 30px 34px;
  border-radius: var(--r-lg);
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: var(--surface-elevated);
  margin-bottom: 44px;
}
.doc-intro p { margin-bottom: 0; }

/* Focus visibility */
a:focus-visible, .btn:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 2px solid var(--mode-chatting-light);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Responsive */
@media (max-width: 860px) {
  :root { --gutter: 24px; }
  .band { padding-top: 88px; }
  .nav-links { gap: 16px; }
  .nav-links a { letter-spacing: 0.2em; }
  .site-footer { margin-top: 96px; }
}

@media (max-width: 560px) {
  .nav { flex-wrap: wrap; gap: 14px; }
  .doc h2 { font-size: 21px; }
}
