/* ============================================================
   DashCode — landing page, in the Dash Flow system
   (docs/design-references/dash-flow.md).

   Two token sets live on this page:
   - the page's own (below): white and warm paper, alpha-black text, light serif display,
     Inter for everything else, every control a pill;
   - the app's (site.css), used only inside the demo window, so the demo still looks like
     the real DashCode.
   ============================================================ */

html { scroll-behavior: smooth; scroll-padding-top: 24px; scrollbar-color: var(--paper-strong) transparent; }

/* ============================== HERO ============================== */
.hero {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  align-items: center;
  gap: clamp(40px, 5vw, 80px);
  width: min(100% - 2 * var(--gutter), var(--max));
  margin: 0 auto;
  padding-top: 32px;
}
.hero__copy { max-width: 37rem; padding: 24px 0; }

.hero h1 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 200;
  font-size: clamp(44px, 1.2rem + 3.4vw, 72px);
  line-height: 1;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.hero__lead {
  margin: 24px 0 0;
  max-width: 34em;
  font-size: 16px;
  line-height: 24px;
  letter-spacing: -0.011em;
  color: var(--text-2);
}
.hero__cta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 36px; }
.hero__note { margin: 12px 0 0; font-size: 13px; line-height: 20px; color: var(--text-2); }
.hero__release::before { content: '·'; margin: 0 8px; }

/* ============================== STAGE (demo on its gradient card) ============================== */
/* The window sits inset from the card's top and left and runs flush into its right and bottom
   edges, so it reads as a photograph of the app cropped by the card. */
.stage {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 48px 0 0 48px;
  border-radius: 32px;
  background: var(--mesh-base);
}
.stage__mesh { position: absolute; inset: 0; z-index: -1; opacity: var(--mesh-alpha); pointer-events: none; }
.stage__mesh i {
  position: absolute;
  display: block;
  width: 80%;
  aspect-ratio: 1;
  border-radius: 50%;
  will-change: transform;
}
.stage__mesh i:nth-child(1) { left: -22%; top: -30%; background: radial-gradient(closest-side, var(--mesh-amber), transparent); animation: drift-a 28s var(--ease) infinite alternate; }
.stage__mesh i:nth-child(2) { right: -26%; top: -24%; background: radial-gradient(closest-side, var(--mesh-blue), transparent); animation: drift-b 34s var(--ease) infinite alternate; }
.stage__mesh i:nth-child(3) { left: -8%; bottom: -46%; width: 64%; background: radial-gradient(closest-side, var(--mesh-amber-2), transparent); opacity: .75; animation: drift-b 31s var(--ease) infinite alternate-reverse; }
.stage__mesh i:nth-child(4) { right: -18%; bottom: -40%; width: 70%; background: radial-gradient(closest-side, var(--mesh-blue-2), transparent); opacity: .6; animation: drift-a 37s var(--ease) infinite alternate-reverse; }
/* film grain over the mesh */
.stage__mesh::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: var(--grain-alpha);
  mix-blend-mode: multiply;
  background-image: var(--grain);
}
@media (prefers-color-scheme: dark) {
  .stage__mesh::after { filter: invert(1); mix-blend-mode: soft-light; }
}

/* the window itself: the app's own look (css/app-ui.css) sits on the stage card, its left top
   corner rounded, flush into the card's right and bottom edges */
.app {
  border-radius: 14px 0 0 0;
  box-shadow: var(--window-shadow);
}

/* "not a screenshot", in the card's top margin above the window; the takeover fades it with the copy */
.stage__hint {
  position: absolute;
  top: 0;
  left: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  margin: 0;
  font-size: 12px;
  color: var(--text-2);
}

/* ============================== TOUR (phones) ============================== */
/* Under 640px the window isn't squeezed into the card: it keeps its real layout (1024 × 640) and a
   pinned frame shows part of it at a time. Scrolling through the stage moves a camera over it:
   the sidebar's marks, Claude waiting on an answer, the header's controls, then the whole window
   (js/index.js › tour). Wider screens never see these wrappers: they lay out as if absent. */
.tour__pin, .tour__frame { display: contents; }
.tour__text { display: none; }

/* ============================== TAKEOVER ============================== */
/* Scrolling past the hero copy carries the window to the middle of the screen while the card's
   light opens out to fill it; it holds there, then scrolls away with the page. The script switches
   this on (`.is-live`, wide screens with motion allowed) and drives it frame by frame; without it
   the hero is the plain split above. While live, the card's crop moves from `overflow` to a
   `clip-path` the script opens to the viewport, and the ground and grain are painted
   viewport-sized (`--frame-*`) so only the clip decides how much of them shows. */
.scene.is-live .scene__pin { position: sticky; top: 0; height: 100vh; height: 100svh; }
.scene.is-live .hero__copy { will-change: transform, opacity; }
.scene.is-live .stage { overflow: visible; background: none; clip-path: inset(0 round 32px); }
.scene.is-live .stage::before,
.scene.is-live .stage::after {
  content: "";
  position: absolute;
  left: var(--frame-x, 0);
  top: var(--frame-y, 0);
  width: var(--frame-w, 100%);
  height: var(--frame-h, 100%);
  pointer-events: none;
}
.scene.is-live .stage::before { z-index: -2; background: var(--mesh-base); }
/* the grain, lifted out of the mesh so it isn't stretched when the mesh scales */
.scene.is-live .stage::after {
  z-index: -1;
  opacity: calc(var(--grain-alpha) * var(--mesh-alpha));
  mix-blend-mode: multiply;
  background-image: var(--grain);
}
.scene.is-live .stage__mesh { transform-origin: 0 0; will-change: transform; }
.scene.is-live .stage__mesh::after { display: none; }
.scene.is-live .app { transform-origin: 0 0; }
/* the highlights row after the scene, drawn up under the hero and pushed back down by the card (js/index.js › takeover) */
/* (never a scroll anchor: it moves with the scroll) */
.scene.is-live + .strip { position: relative; will-change: transform; overflow-anchor: none; }
@media (prefers-color-scheme: dark) {
  .scene.is-live .stage::after { filter: invert(1); mix-blend-mode: soft-light; }
}

/* ============================== STRIP ============================== */
/* the things it does, where the reference keeps its logo row: a centred grid, four columns of two
   (two columns on narrower screens), each column as wide as its longest label */
.strip {
  display: grid;
  grid-template-columns: repeat(4, auto);
  justify-content: center;
  gap: 16px 56px;
  width: min(100% - 2 * var(--gutter), var(--max));
  margin: 64px auto 0;
  padding: 0;
  list-style: none;
}
.strip li { display: inline-flex; align-items: center; gap: 10px; color: var(--text-2); }
.strip svg { width: 16px; height: 16px; flex: none; color: var(--text-3); }

/* ============================== ON BOARD ============================== */
.onboard {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: 48px 64px;
  width: min(100% - 2 * var(--gutter), var(--max));
  margin: 0 auto;
  padding-top: 144px;
}
.onboard__head { position: sticky; top: 40px; align-self: start; max-width: 30rem; }
.onboard h2 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 200;
  font-size: clamp(34px, 1.4rem + 1.4vw, 48px);
  line-height: 1;
  letter-spacing: -0.03em;
}
.onboard__lede { margin: 18px 0 0; font-size: 16px; line-height: 24px; color: var(--text-2); }
.onboard__notes { display: grid; gap: 16px; margin-top: 40px; }
.onboard__notes p { margin: 0; color: var(--text-2); }
.onboard__notes b { color: var(--text); font-weight: 500; }
.onboard__notes a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--paper-strong);
  text-underline-offset: 3px;
  transition: color 150ms var(--ease), text-decoration-color 150ms var(--ease);
}
.onboard__notes a:hover { color: var(--link-hover); text-decoration-color: currentColor; }
.onboard kbd, .onboard code {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0;
  color: var(--text);
  background: var(--paper);
  border-radius: 6px;
  padding: 1px 6px;
}
.onboard kbd { font-size: 11.5px; }

.manifest { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.manifest li {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: 12px 40px;
  padding: 32px 0;
  border-bottom: 1px solid var(--rule);
}
.manifest h3 {
  margin: 0;
  font-family: var(--serif);
  font-weight: 200;
  font-size: 28px;
  line-height: 1.05;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.manifest p { margin: 0; max-width: 60ch; font-size: 14px; line-height: 22px; color: var(--text-2); }

/* ============================== GET UPDATES ============================== */
/* the popover under the header's "Get updates": centred like the nav, fixed in the top layer */
.updates {
  position: fixed;
  inset: 76px 0 auto;
  width: min(100% - 2 * var(--gutter), 360px);
  max-height: calc(100dvh - 92px);
  margin: 0 auto;
  padding: 24px;
  border: 0;
  border-radius: 24px;
  background: var(--surface);
  color: var(--text);
  box-shadow: inset 0 0 0 1px var(--paper-strong), 0 1px 2px rgba(2, 6, 23, .05), 0 16px 40px -12px rgba(2, 6, 23, .22);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 200ms var(--ease-out), transform 300ms var(--ease-out), overlay 200ms allow-discrete, display 200ms allow-discrete;
}
.updates:popover-open { opacity: 1; transform: none; }
@starting-style { .updates:popover-open { opacity: 0; transform: translateY(-6px); } }
.updates::backdrop { background: transparent; }
@media (prefers-reduced-motion: reduce) { .updates { transform: none; transition: none; } }

.updates__title {
  margin: 0;
  font-family: var(--serif);
  font-weight: 200;
  font-size: 28px;
  line-height: 1.05;
  letter-spacing: -0.03em;
}
.signup-note { margin: 8px 0 20px; font-size: 13px; line-height: 18px; color: var(--text-2); }

.signup-form { display: flex; flex-direction: column; gap: 12px; }
.signup-field { display: flex; flex-direction: column; gap: 6px; font-size: 12px; line-height: 16px; color: var(--text-2); }
.signup-field input {
  height: 40px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: inset 0 0 0 1px var(--paper-strong);
  color: var(--text);
  font: 400 14px/20px var(--sans);
  letter-spacing: -0.01em;
  outline: none;
  transition: box-shadow 150ms var(--ease);
}
.signup-field input::placeholder { color: var(--text-3); }
.signup-field input:hover { box-shadow: inset 0 0 0 1px var(--ring-hover); }
.signup-field input:focus-visible { box-shadow: inset 0 0 0 1.5px var(--text); }
.signup-form .pill { margin-top: 4px; }
.signup-form .pill[disabled] { cursor: progress; opacity: .6; }
.signup .hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

.signup-error { margin: 0; font-size: 12px; line-height: 16px; color: var(--danger); }
.signup-error[hidden] { display: none; }

.signup-success {
  display: none;
  align-items: center;
  gap: 8px;
  color: color-mix(in srgb, var(--ok) 80%, var(--text));
}
.signup-success svg { width: 16px; height: 16px; flex: none; }
.signup.done .signup-form, .signup.done .signup-note { display: none; }
.signup.done .signup-success { display: flex; margin-top: 12px; }

/* the header button's short label, for the narrowest phones */
.top__short { display: none; }

/* the telemetry readout: the clock is live */
.telemetry {
  margin: 0;
  max-width: 320px;
}
.telemetry div {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
}
.telemetry div:first-child { padding-top: 0; }
.telemetry div:last-child { border-bottom: 0; }
.telemetry dt { font-family: var(--font-mono); font-size: 11px; letter-spacing: .02em; color: var(--text-2); }
.telemetry dd { margin: 0; font-family: var(--font-mono); font-size: 12px; letter-spacing: 0; font-variant-numeric: tabular-nums; }
.telemetry .ok { display: inline-flex; align-items: center; gap: 8px; color: color-mix(in srgb, var(--ok) 80%, var(--text)); }
.telemetry .ok i { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); animation: live 2.5s ease-in-out infinite; }

/* the demo window's own rules: css/app-ui.css */

/* ============================== motion ============================== */
@keyframes live   { 0%,100% { transform: scale(1); } 50% { transform: scale(1.6); } }
@keyframes drift-a { from { transform: translate(0, 0) scale(1); } to { transform: translate(14%, 10%) scale(1.15); } }
@keyframes drift-b { from { transform: translate(0, 0) scale(1.1); } to { transform: translate(-12%, 14%) scale(.95); } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ============================== the demo at full size (wide screens) ============================== */
/* Past 1080px the window is drawn at a real app size, not shrunk to fit the card: 80vw wide, as
   tall as 80% of what the takeover can show without scaling (the screen less js/index.js ›
   takeover's MY margins, 2 × 104px). The card shows its left part, sidebar and workspace, and crops the rest;
   the takeover slides it to the middle of the screen at the same size to reveal the whole window. */
@media (min-width: 1081px) {
  .stage { min-width: 0; }
  .app { width: 80vw; }
  .shell { height: clamp(416px, calc((100vh - 208px) * .8), 40vw); height: clamp(416px, calc((100svh - 208px) * .8), 40vw); }
  /* while live the card crops with clip-path, which doesn't stop the window widening the page */
  .scene.is-live .scene__pin { overflow: clip; }
}


/* ============================== responsive ============================== */
@media (max-width: 1080px) {
  .hero { grid-template-columns: minmax(0, 1fr); gap: 48px; padding-top: 40px; }
  .hero__copy { padding: 0; }
  .stage { padding: 40px 0 0 40px; }
  .stage__hint { left: 40px; height: 40px; }
  .strip { grid-template-columns: repeat(2, auto); }
  .onboard { grid-template-columns: minmax(0, 1fr); padding-top: 112px; }
  .onboard__head { position: static; max-width: 40rem; }
}
@media (max-width: 640px) {
  .updates { inset-block-start: 68px; max-height: calc(100dvh - 84px); }
  .hero { padding-top: 24px; }
  .hero__cta .pill { flex: 1 1 auto; }
  /* the tour: no card, just the window, moved and zoomed inside a pinned frame */
  .stage { height: 360svh; margin: 0 calc(-1 * var(--gutter)); padding: 0; border-radius: 0; background: none; overflow: visible; isolation: auto; }
  .stage__mesh, .stage__hint { display: none; }
  .tour__pin {
    position: sticky;
    top: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
    height: 100vh;
    height: 100svh;
    padding: 20px 0 88px;           /* the bottom clears the floating bar */
  }
  .tour__text { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px; align-items: start; min-height: 112px; padding: 0 var(--gutter); }
  .tour__caps { display: grid; }
  .tour__cap { grid-area: 1 / 1; opacity: 0; transform: translateY(8px); transition: opacity 300ms var(--ease-out), transform 420ms var(--ease-out); }
  .tour__cap.is-on { opacity: 1; transform: none; }
  .tour__cap h2 { margin: 0; font-family: var(--serif); font-weight: 200; font-size: 26px; line-height: 1.05; letter-spacing: -0.03em; }
  .tour__cap p { margin: 8px 0 0; font-size: 14px; line-height: 20px; color: var(--text-2); }
  .tour__dots { display: flex; gap: 6px; padding-top: 10px; }
  .tour__dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--paper-strong); transition: background-color 200ms var(--ease), transform 300ms var(--ease-out); }
  .tour__dots i.is-on { background: var(--text); transform: scale(1.35); }
  /* the frame crops the window; its top and bottom edges fade so a crop reads as "it goes on" */
  .tour__frame {
    display: block;
    position: relative;
    flex: 1;
    min-height: 0;
    overflow: clip;
    -webkit-mask-image: linear-gradient(transparent, #000 20px, #000 calc(100% - 20px), transparent);
            mask-image: linear-gradient(transparent, #000 20px, #000 calc(100% - 20px), transparent);
  }
  .stage .app { position: absolute; left: 0; top: 0; width: 1024px; border-radius: 14px; transform-origin: 0 0; will-change: transform; }
  .stage .shell { height: 640px; }
  .strip { column-gap: 24px; margin-top: 48px; }
  .onboard { padding-top: 88px; }
  .manifest li { grid-template-columns: minmax(0, 1fr); padding: 28px 0; }
  .manifest h3 { font-size: 26px; }
}
@media (max-width: 400px) {
  .top__long { display: none; }
  .top__short { display: inline; }
}
