/* ==========================================================================
   ROSFlow — Landing page
   Loaded only on the public surface (home, login, register).

   The console stylesheet is deliberately restrained: a dashboard that drifts
   while you read a number is a dashboard you stop trusting. The landing page
   has the opposite job — it has about four seconds to look like something
   worth an evening of a restaurant's time. So the expressive motion lives
   here, and never ships to a terminal.

   Inherits every token from ros.css. Adds no colours of its own.
   ========================================================================== */

/* ==========================================================================
   1 · Atmosphere
   ========================================================================== */

/* Aurora: slow, offset gradient fields. Reads as light in a room rather than
   as an animation, because nothing ever arrives anywhere. */
.aurora {
  position: absolute; inset: -30% -10%;
  pointer-events: none; z-index: 0;
  filter: blur(70px);
}
.aurora span {
  position: absolute; border-radius: 50%; opacity: .5;
  animation: drift 26s var(--ease-in-out) infinite alternate;
  will-change: transform;
}
.aurora span:nth-child(1) {
  width: 46vw; height: 46vw; left: 6%; top: 4%;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--accent) 42%, transparent), transparent 68%);
}
.aurora span:nth-child(2) {
  width: 38vw; height: 38vw; right: 4%; top: 22%;
  background: radial-gradient(circle, rgba(126,155,196,.34), transparent 68%);
  animation-duration: 34s; animation-delay: -8s;
}
.aurora span:nth-child(3) {
  width: 30vw; height: 30vw; left: 38%; top: 46%;
  background: radial-gradient(circle, rgba(127,187,163,.22), transparent 68%);
  animation-duration: 40s; animation-delay: -16s;
}

@keyframes drift {
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(4%, -6%, 0) scale(1.12); }
  100% { transform: translate3d(-5%, 5%, 0) scale(.95); }
}

/* A faint ruled grid behind the hero. Gives the black some architecture
   without ever becoming a visible pattern. */
.grid-field {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: .5;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 88px 88px;
  mask-image: radial-gradient(70% 60% at 50% 30%, #000, transparent 78%);
  -webkit-mask-image: radial-gradient(70% 60% at 50% 30%, #000, transparent 78%);
}

/* ==========================================================================
   2 · Chrome
   ========================================================================== */

.scroll-progress {
  position: fixed; top: 0; left: 0; height: 2px; z-index: 60; width: 0;
  background: linear-gradient(90deg, transparent, var(--accent));
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 50%, transparent);
}

/* The nav shell condenses on scroll — set by JS toggling .is-stuck. */
.nav-shell { border: 1px solid transparent; transition: all var(--t-base) var(--ease-out); }
.nav-shell.is-stuck {
  background: var(--nav-stuck);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  border-color: var(--line-strong);
  box-shadow: var(--sh-2);
}

/* Underline that grows from the left on hover. */
.nav-link { position: relative; }
.nav-link::after {
  content: ''; position: absolute; left: 0; bottom: -6px; height: 1px; width: 0;
  background: var(--accent); transition: width var(--t-base) var(--ease-out);
}
.nav-link:hover::after { width: 100%; }

/* ==========================================================================
   3 · Type in motion
   ========================================================================== */

/* Headline words rise in sequence, once. */
.word {
  display: inline-block;
  opacity: 0; transform: translateY(.5em) rotate(1.5deg);
}
.word.in {
  opacity: 1; transform: none;
  transition: opacity .8s var(--ease-out), transform .8s var(--ease-out);
}

/* A hairline that draws itself when its section arrives. */
.rule-draw { transform: scaleX(0); transform-origin: left; }
.rule-draw.in { transform: scaleX(1); transition: transform 1.1s var(--ease-out); }

.ticker { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   4 · Objects
   ========================================================================== */

.float { animation: float 7s var(--ease-in-out) infinite alternate; }
@keyframes float { from { transform: translateY(0); } to { transform: translateY(-14px); } }

/* Pointer tilt. Small angles — this is a screenshot of a working tool, not a
   carousel. */
.tilt {
  transform-style: preserve-3d;
  transition: transform var(--t-base) var(--ease-out);
  will-change: transform;
}
.tilt-inner { transform: translateZ(40px); }

/* Gradient border that survives a border-radius. */
.edge-gold { position: relative; }
.edge-gold::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(140deg, var(--accent), transparent 42%,
                                       transparent 62%, var(--accent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: .5; pointer-events: none;
}

/* Feature card: the icon lifts, the edge warms. */
.feature {
  transition: transform var(--t-base) var(--ease-out),
              border-color var(--t-base) var(--ease-out),
              box-shadow var(--t-base) var(--ease-out);
}
.feature:hover {
  transform: translateY(-4px);
  border-color: var(--line-gold);
  box-shadow: var(--sh-2);
}
.feature-icon { transition: transform var(--t-base) var(--ease-out); }
.feature:hover .feature-icon { transform: translateY(-3px) scale(1.06); }

/* Cursor-following sheen on a card. Coordinates come from JS. */
.sheen { position: relative; overflow: hidden; }
.sheen::before {
  content: ''; position: absolute; inset: 0; opacity: 0;
  transition: opacity var(--t-base) var(--ease-out);
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--accent) 10%, transparent), transparent 60%);
}
.sheen:hover::before { opacity: 1; }

.marquee-track { animation: marquee 42s linear infinite; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* ==========================================================================
   5 · Landing-only typography scale
   The console caps its measure at 68ch for legibility under pressure. Marketing
   copy is read once, slowly, and wants a slightly tighter column.
   ========================================================================== */

.lede { font-size: clamp(1rem, 1.4vw, 1.125rem); line-height: 1.7; max-width: 60ch; }
.landing-section { padding-block: clamp(5rem, 9vw, 7.5rem); }

/* ==========================================================================
   6 · Reduced motion
   Everything above degrades to a still, fully legible page.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .aurora span, .float, .marquee-track { animation: none !important; }
  .word { opacity: 1; transform: none; }
  .rule-draw { transform: none; }
  .tilt { transform: none !important; }
  .feature:hover { transform: none; }
}

/* ==========================================================================
   7 · Light skin — the landing-only pieces
   ==========================================================================
   The tokens live in ros.css, because they apply to the whole application. What
   is here is the handful of marketing effects that need re-weighting rather
   than re-colouring: at dark opacities on ivory they turn to grey haze instead
   of light in a room.
   ========================================================================== */

:root[data-skin="light"] .aurora { filter: blur(90px); }
:root[data-skin="light"] .aurora span { opacity: .3; }
:root[data-skin="light"] .aurora span:nth-child(2) {
  background: radial-gradient(circle, rgba(66, 100, 143, .22), transparent 68%);
}
:root[data-skin="light"] .aurora span:nth-child(3) {
  background: radial-gradient(circle, rgba(59, 122, 95, .17), transparent 68%);
}

/* The ruled grid gives the black some architecture. On ivory it needs to be
   fainter or it reads as graph paper. */
:root[data-skin="light"] .grid-field { opacity: .55; }

/* A shimmer built for light text on black flattens on ivory. */
/* The shimmer is clipped to text. Its dark-theme stops run pale-to-paler, which
   vanishes on ivory — on light it has to run through the darker end of the
   champagne to stay a word you can read. */
:root[data-skin="light"] .shimmer {
  background-image: linear-gradient(100deg,
    var(--accent) 20%, var(--gold-500) 42%, var(--accent) 60%, var(--accent) 75%);
}
