/* ====================================================================
 * modolab site — styles
 * Type hierarchy: Geist Light (300) display · Regular (400) body ·
 * Semibold (600) labels, accents, buttons. Geist Mono for eyebrows.
 *
 * Theming: vibrant mesh pages (home / about / team) run white text on
 * the gradient; the product page is the bright white/blue one and runs
 * dark text. Both themes are driven by the variables on body below.
 * ================================================================== */
:root {
  --accent: #ff5a1e;
  --cyan: #1ec3ff;
  --ink: #16150f;
  /* shadcn (Lyra): hard-square corners everywhere */
  --radius-card: 0px;
  --radius-ui: 0px;
  --pad-x: clamp(20px, 4.5vw, 64px);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

/* Dark (vibrant-gradient) theme — the default */
body {
  --fg: #ffffff;
  --fg-soft: rgba(255, 255, 255, 0.84);
  --fg-faint: rgba(255, 255, 255, 0.62);
  --line-c: rgba(255, 255, 255, 0.28);
  --line-strong: rgba(255, 255, 255, 0.5);
  --eyebrow-c: #ffffff;
  --em-c: #ffffff;
  --card-bg: rgba(255, 255, 255, 0.14);
  --card-border: rgba(255, 255, 255, 0.32);
  --pill-bg: rgba(255, 255, 255, 0.14);
  --pill-bg-hover: rgba(255, 255, 255, 0.26);
  --pill-border: rgba(255, 255, 255, 0.5);
  --pill-fg: #ffffff;
  --lm-ink: #ffffff;
  --lm-accent: #ffffff;
  /* roles the themes swap: full-strength text, inverted solid fills,
     form fields, and small-type accent (orange needs lifting on ink) */
  --error-fg: #ff8a80;
  --ink-strong: #ffffff;
  --solid: #ffffff;
  --solid-fg: var(--ink);
  --field-bg: rgba(255, 255, 255, 0.14);
  --accent-fg: var(--accent);
}

/* Light theme — about + products (bright white/blue gradients) */
body[data-page="about"],
body[data-page="product"] {
  --fg: var(--ink);
  --fg-soft: #5d5a52;
  --fg-faint: #8a877e;
  --line-c: rgba(22, 21, 15, 0.12);
  --line-strong: rgba(22, 21, 15, 0.22);
  --eyebrow-c: var(--ink);
  --em-c: var(--accent);
  --card-bg: rgba(255, 255, 255, 0.6);
  --card-border: rgba(255, 255, 255, 0.72);
  --pill-bg: rgba(255, 255, 255, 0.4);
  --pill-bg-hover: rgba(255, 255, 255, 0.75);
  --pill-border: rgba(22, 21, 15, 0.3);
  --pill-fg: var(--ink);
  --lm-ink: #242424;
  --lm-accent: #ff5a1e;
  --error-fg: #b42318; /* deep enough to clear 4.5:1 on the bright gradients */
  --ink-strong: var(--ink);
  --solid: var(--ink);
  --solid-fg: #ffffff;
  --field-bg: rgba(255, 255, 255, 0.85);
  --accent-fg: var(--accent);
}

/* Products in dark — driven by the toggle inside the embedded dashboard.
   Same role list as the light block, scoped one attribute tighter so it
   wins on specificity, with the ground flipped to brand ink. */
body[data-page="product"][data-theme="dark"] {
  --fg: #ffffff;
  --fg-soft: rgba(255, 255, 255, 0.82);
  --fg-faint: rgba(255, 255, 255, 0.6);
  --line-c: rgba(255, 255, 255, 0.18);
  --line-strong: rgba(255, 255, 255, 0.34);
  --eyebrow-c: #ffffff;
  --em-c: #ffffff;
  --card-bg: rgba(255, 255, 255, 0.07);
  --card-border: rgba(255, 255, 255, 0.16);
  --pill-bg: rgba(255, 255, 255, 0.1);
  --pill-bg-hover: rgba(255, 255, 255, 0.2);
  --pill-border: rgba(255, 255, 255, 0.42);
  --pill-fg: #ffffff;
  --lm-ink: #ffffff;
  --lm-accent: #ffffff;
  --error-fg: #ff8a80; /* red reads as red on ink only if it's lifted */
  --ink-strong: #ffffff;
  --solid: #ffffff;
  --solid-fg: var(--ink);
  --field-bg: rgba(255, 255, 255, 0.08);
  --accent-fg: #ff7a45; /* 10px mono needs more than #ff5a1e gives on ink */
  background: #242424;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
body {
  font-family: "Geist", system-ui, sans-serif;
  font-weight: 400;
  color: var(--fg);
  background: #fff;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }

/* ---------- Gradient background ---------- */
#gradient {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* ---------- Shell ---------- */
.shell {
  position: fixed;
  inset: 0;
  display: grid;
  /* topbar + viewport only — the footer scrolls at the end of each page */
  grid-template-rows: auto 1fr;
  z-index: 1;
}

/* ---------- Top bar: nav left · logomark centre · CTA right ---------- */
.topbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  padding: 20px var(--pad-x);
}
.topbar nav {
  display: flex;
  gap: clamp(18px, 3vw, 40px);
  justify-self: start;
}
.logomark {
  justify-self: center;
  display: block;
  line-height: 0;
  transition: opacity 0.35s ease;
}
/* hidden while the intro loader owns the logo; fades in on handoff */
body.is-loading .logomark { opacity: 0; }
.logomark svg { height: 26px; width: auto; display: block; }
.lm-ink { fill: var(--lm-ink); transition: fill 0.6s ease; }
.lm-accent { fill: var(--lm-accent); transition: fill 0.6s ease; }
.topbar nav a {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg);
  position: relative;
  padding: 4px 0;
  transition: color 0.6s ease;
}
/* underline sweeps in from the left when a page is selected */
.topbar nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -3px;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  opacity: 0.35;
  transition: transform 0.5s var(--ease-out), opacity 0.3s ease;
}
.topbar nav a:hover::after { transform: scaleX(1); }
.topbar nav a.active::after { transform: scaleX(1); opacity: 1; }
.top-cta {
  justify-self: end;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg);
  padding: 4px 0;
  border-bottom: 1.5px solid var(--line-strong);
  transition: color 0.3s ease, border-color 0.3s ease;
}
.top-cta:hover { border-color: currentColor; }

/* ---------- Pages ---------- */
.viewport {
  position: relative;
  min-height: 0;
  /* scrolling content fades out under the nav and footer instead of
     cropping hard at the viewport edges */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 32px, #000 calc(100% - 32px), transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 32px, #000 calc(100% - 32px), transparent 100%);
}
.page {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  visibility: hidden;
  display: flex;
  flex-direction: column;
}
.page.is-active { visibility: visible; }
.inner {
  /* fill the space above the footer — pages whose content fits the
     viewport (home) show the footer without any scroll */
  flex: 1 0 auto;
  max-width: 1320px;
  margin: 0 auto;
  padding: clamp(20px, 4vh, 48px) var(--pad-x) clamp(28px, 5vh, 56px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(18px, 3vh, 32px);
  transition: opacity 0.45s ease, transform 0.5s var(--ease-out);
}
.inner--center { align-items: flex-start; }

/* Leaving pages dissolve into the gradient while it morphs */
.page.is-leaving .inner {
  opacity: 0;
  transform: translateY(-28px);
}

/* ---------- Type ---------- */
.eyebrow {
  font: 500 11px "Geist Mono", monospace;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--eyebrow-c);
  display: flex;
  align-items: center;
  gap: 10px;
}
.eyebrow::before { content: ""; width: 22px; height: 1px; background: var(--eyebrow-c); }

.display {
  font-size: clamp(36px, 6.2vw, 92px);
  font-weight: 300;
  line-height: 1.02;
  letter-spacing: -0.045em;
  max-width: 14em;
}
.headline {
  font-size: clamp(30px, 4.2vw, 58px);
  font-weight: 300;
  line-height: 1.06;
  letter-spacing: -0.035em;
  max-width: 18em;
}
.display em, .headline em {
  font-style: normal;
  font-weight: 600;
  color: var(--em-c);
}
.lede {
  font-size: clamp(15px, 1.8vw, 19px);
  font-weight: 400;
  line-height: 1.55;
  color: var(--fg-soft);
  max-width: 44ch;
}
.body {
  font-size: clamp(14px, 1.5vw, 16px);
  line-height: 1.6;
  color: var(--fg-soft);
  max-width: 56ch;
}
/* about reads in full ink, matching the products callout body */
#about .body { color: var(--ink); }
.side-note {
  font-size: 13px;
  line-height: 1.55;
  color: var(--fg-soft);
  max-width: 30ch;
}
.col-label {
  font: 500 10.5px "Geist Mono", monospace;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-faint);
}
/* eyebrow + title pairing — one consistent gap on every core page */
.head-block {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ---------- Split-word mask reveal ---------- */
.split .w {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.split .wi {
  display: inline-block;
  transform: translateY(115%);
  transition: transform 1s var(--ease-out);
  transition-delay: var(--wd, 0ms);
}
.page.is-shown .split .wi { transform: none; }

[data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.7s ease, transform 0.85s var(--ease-out);
  transition-delay: var(--d, 0ms);
}
.page.is-shown [data-reveal] { opacity: 1; transform: none; }

/* ---------- Buttons — Modolab liquid glass (no shadow, no lift) ---------- */
.cta-row { display: flex; gap: 12px; flex-wrap: wrap; }
.pill {
  position: relative;
  display: inline-flex;
  align-items: center;
  overflow: hidden;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
  border-radius: 0;
  border: 1.5px solid var(--pill-border);
  padding: 13px 26px;
  color: var(--pill-fg);
  background: var(--pill-bg);
  cursor: pointer;
  backdrop-filter: blur(12px) saturate(1.3);
  -webkit-backdrop-filter: blur(12px) saturate(1.3);
  transition: background 0.45s var(--ease-out), border-color 0.45s ease,
              backdrop-filter 0.45s ease, -webkit-backdrop-filter 0.45s ease;
}
.pill:hover {
  background: var(--pill-bg-hover);
  border-color: var(--fg);
  backdrop-filter: blur(22px) saturate(1.8);
  -webkit-backdrop-filter: blur(22px) saturate(1.8);
  transition-duration: 0.9s;
}
/* a pill that is itself a reveal target needs both transition sets,
   otherwise the pill's own transition list wins and the reveal snaps */
.pill[data-reveal] {
  transition: opacity 0.7s ease var(--d, 0ms),
              transform 0.85s var(--ease-out) var(--d, 0ms),
              background 0.45s var(--ease-out), border-color 0.45s ease,
              backdrop-filter 0.45s ease, -webkit-backdrop-filter 0.45s ease;
}
/* cursor-tracked light blob, morphing like liquid glass */
.blob {
  position: absolute;
  z-index: 0;
  width: 170px;
  height: 170px;
  left: var(--mx, 50%);
  top: var(--my, 50%);
  margin: -85px 0 0 -85px;
  filter: blur(26px);
  background: radial-gradient(circle, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.25) 55%, transparent 78%);
  opacity: 0;
  transform: scale(0.7);
  border-radius: 58% 42% 38% 62% / 62% 44% 56% 38%;
  transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out);
  mix-blend-mode: screen;
  pointer-events: none;
}
body[data-page="about"] .pill .blob,
body[data-page="product"] .pill .blob { mix-blend-mode: overlay; }
.pill:hover .blob,
.signup .go:hover .blob {
  opacity: 0.45;
  transform: scale(1);
  transition-duration: 0.9s;
  animation: blobmorph 3.6s cubic-bezier(0.45, 0, 0.55, 1) infinite alternate;
}
@keyframes blobmorph {
  0% { border-radius: 58% 42% 38% 62% / 62% 44% 56% 38%; }
  50% { border-radius: 42% 58% 62% 38% / 38% 62% 44% 56%; }
  100% { border-radius: 50% 50% 42% 58% / 58% 42% 50% 50%; }
}
.btn-content {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
/* Lucide arrow-right inside CTAs */
.pill .icon,
.signup .go .icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  transition: transform 0.6s var(--ease-out);
}
.pill:hover .icon,
.signup .go:hover .icon { transform: translateX(5px); }

/* ---------- Glass cards ---------- */
.card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: var(--radius-card);
  backdrop-filter: blur(20px) saturate(1.25);
  -webkit-backdrop-filter: blur(20px) saturate(1.25);
  box-shadow: 0 10px 28px -20px rgba(22, 21, 15, 0.35);
}

/* ---------- Home ---------- */
.lede strong { font-weight: 600; color: var(--fg); }
.hero-foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px;
  flex-wrap: wrap;
  width: 100%;
  border-top: 1px solid var(--line-c);
  padding-top: clamp(16px, 2.6vh, 28px);
  margin-top: clamp(4px, 1vh, 12px);
}

/* ---------- About ---------- */
.about-grid {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(28px, 4vw, 72px);
  align-items: center;
}
.about-left { display: flex; flex-direction: column; gap: clamp(16px, 2.6vh, 26px); }
.about-left .pill { align-self: flex-start; }
/* headline highlights run ink on the light pages */
#about .headline em,
#product .headline em { color: var(--ink-strong); }
.about-right { display: flex; flex-direction: column; gap: 14px; }
/* Problem cards: staggered glass panes over the mesh. Each pane rests at
   its own slight angle and offset (--rz set per card) and carries an
   oversized ghost of its icon bleeding off the corner. */
.problem {
  position: relative;
  overflow: hidden;
  padding: 22px 26px 26px;
  background: rgba(255, 255, 255, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(22px) saturate(1.3);
  -webkit-backdrop-filter: blur(22px) saturate(1.3);
  color: var(--ink);
  transform: rotate(var(--rz, 0deg));
  box-shadow: 0 18px 40px -30px rgba(22, 21, 15, 0.35);
  transition: background 0.5s ease, border-color 0.5s ease;
}
.problem:nth-child(1) { margin-right: 13%; }
.problem:nth-child(2) { margin-left: 13%; }
.problem:nth-child(3) { margin-left: 6%; margin-right: 6%; }
.problem:hover {
  background: rgba(255, 255, 255, 0.68);
  border-color: rgba(255, 90, 30, 0.4);
}
/* reveal keeps each card's resting angle */
.problem[data-reveal] {
  opacity: 0;
  transform: translateY(34px) rotate(var(--rz, 0deg));
  transition: opacity 0.7s ease var(--d, 0ms),
              transform 0.85s var(--ease-out) var(--d, 0ms),
              background 0.5s ease, border-color 0.5s ease;
}
.page.is-shown .problem[data-reveal] {
  opacity: 1;
  transform: rotate(var(--rz, 0deg));
}
.phead { margin-bottom: 12px; }
.pico {
  display: block;
  width: 46px;
  height: 46px;
  color: var(--accent);
}
.pbig {
  position: absolute;
  right: -30px;
  bottom: -36px;
  width: 150px;
  height: 150px;
  color: var(--ink);
  opacity: 0.05;
  pointer-events: none;
  transform: rotate(-10deg);
  transition: opacity 0.5s ease, color 0.5s ease;
}
.problem:hover .pbig { opacity: 0.1; color: var(--accent); }
.problem h3 { font-size: 17px; font-weight: 600; letter-spacing: -0.015em; margin-bottom: 6px; color: var(--ink); position: relative; }
.problem p { font-size: 14px; line-height: 1.55; color: #4f4c45; max-width: 44ch; position: relative; }

/* ---------- Team ---------- */
/* team runs a step smaller and airier than the other pages */
#team .inner { gap: clamp(28px, 5.5vh, 60px); }
#team .headline { font-size: clamp(22px, 2.9vw, 40px); max-width: none; }
/* Intro is a simple left-aligned vertical stack — headline, body note,
   CTA — at every width. It lives inside .inner, so it inherits the same
   left/right padding as every other page and can never crop. The gaps
   match the about page's headline / body / CTA rhythm. */
.team-intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(16px, 2.6vh, 26px);
}
.team-intro > div { display: flex; flex-direction: column; gap: 14px; }
/* > .team-side so the note-to-CTA gap beats the 14px eyebrow rule above
   and matches the about page's rhythm exactly */
.team-intro > .team-side {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(16px, 2.6vh, 26px);
}
/* the note reads as ordinary body copy, not a cramped side caption —
   full container width, wrapping naturally like the headline above it */
.team-intro .side-note {
  text-align: left;
  font-size: clamp(14px, 1.5vw, 16px);
  line-height: 1.6;
  max-width: none;
}
/* Portrait belt: photo-led cards on the near-black stage. The wrapper
   escapes the page column to bleed the full viewport width. */
.team-belt-wrap {
  width: 100%;
  flex-shrink: 0; /* keep natural height — overflow scrolls, never squashes */
  overflow: hidden;
  cursor: grab;
  touch-action: pan-y;
  margin-bottom: clamp(28px, 5vh, 56px); /* room to breathe above the footer */
}
.team-belt-wrap.dragging { cursor: grabbing; }
.team-belt {
  display: flex;
  gap: 8px;
  width: max-content;
  padding: 8px 0 12px;
  user-select: none;
  -webkit-user-select: none;
  will-change: transform;
}
.tcard {
  position: relative;
  width: clamp(230px, 21vw, 310px);
  aspect-ratio: 3 / 4;
  flex-shrink: 0;
  overflow: hidden;
  background: #101010;
  border: 1px solid rgba(255, 255, 255, 0.16);
  transition: border-color 0.5s ease;
  container-type: inline-size;
}
/* stroke brightens to white on hover */
.tcard:hover { border-color: rgba(255, 255, 255, 0.85); }
/* photo fills the whole card; halftone-style placeholder until the
   real portraits are dropped in as <img> */
.tphoto {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 50% 34%, #e8e8e8 0%, #e8e8e8 16%, transparent 16.6%),
    radial-gradient(115% 62% at 50% 104%, #d9d9d9 0%, #d9d9d9 44%, transparent 45%),
    linear-gradient(160deg, #f5f5f5 0%, #cfcfcf 55%, #a8a8a8 100%);
}
.tphoto::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(12, 12, 10, 0.8) 0.9px, transparent 1.15px);
  background-size: 4px 4px;
  opacity: 0.3;
}
.tphoto img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.06);
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}
.tmeta {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 48px 14px 16px;
  background: linear-gradient(180deg, rgba(8, 8, 6, 0) 0%, rgba(8, 8, 6, 0.9) 72%);
  pointer-events: none;
}
.tmeta h3 { font-size: 17px; font-weight: 600; letter-spacing: -0.015em; color: #fff; }
/* role always fits on one line: sized against the card's own width */
.tmeta p {
  font-size: clamp(9.5px, calc(4.7cqw + 0.8px), 12px);
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.75);
  margin-top: 2px;
}
.team-cta { display: flex; }

/* ---------- Product ---------- */
/* title stacked above the demo ask — one left-aligned column */
.product-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}
.product-head > div {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  width: 100%;
}
.product-head .side-note { text-align: right; flex-shrink: 0; }
/* products runs at the same compact scale as the team page */
#product .inner {
  gap: clamp(14px, 2.4vh, 22px);
  padding-top: clamp(14px, 2.6vh, 26px);
  padding-bottom: clamp(16px, 2.8vh, 28px);
}
/* Match the team intro: the title always wraps inside the padded page
   container, preserving both gutters as the viewport narrows. */
#product .headline { font-size: clamp(22px, 3vw, 42px); max-width: none; }

/* modosignal wordmark leading the page */
.product-live {
  display: flex;
  align-items: center;
}
.product-mark {
  display: block;
  height: clamp(31px, 3.1vw, 42px); /* 10% up on desktop */
  width: auto;
}
/* mono timing tag, reused by the roadmap strip */
.tl-when {
  font: 500 9.5px "Geist Mono", monospace;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-faint);
  white-space: nowrap;
}

/* the rest of the lifecycle — a forward-looking timeline; the two
   future products carry the visual weight, dates mark the line */
.roadmap {
  padding-top: 0;
  margin-top: clamp(4px, 0.8vh, 10px);
}
.roadmap-label {
  display: block;
  font: 400 10.5px "Geist", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin-bottom: 22px;
}
.roadmap-track {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(28px, 5vw, 80px);
}
/* the timeline rule + markers */
.roadmap-track::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--line-strong);
}
.roadmap-item {
  position: relative;
  padding-top: 26px;
  min-width: 0;
}
.roadmap-item::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 11px;
  height: 11px;
  background: #fff;
  border: 1.5px solid var(--ink);
}
.roadmap-date {
  display: block;
  font: 500 10.5px "Geist Mono", monospace;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-fg);
  margin-bottom: 12px;
}
/* per-logo heights tuned so both wordmarks share one cap size */
.roadmap-logo { display: block; width: auto; margin-bottom: 12px; }
.roadmap-logo--flow { height: 22px; }
.roadmap-logo--pulse { height: 28px; }
.roadmap-item p {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--fg-soft);
  max-width: 42ch;
}
/* small standing call for early partners under each roadmap item */
.roadmap-beta {
  display: inline-block;
  margin-top: 14px;
  padding: 5px 10px;
  font: 500 10px "Geist Mono", monospace;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-fg);
  border: 1px solid currentColor;
}

/* ---------- modosignal editorial feature — framed in the page grid ---------- */

/* copy and numbers share the row in even halves; stacks on mobile.
   top-aligned so the numerals sit flush with the title */
.signal-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(24px, 3.5vw, 64px);
  align-items: start;
  margin: clamp(30px, 5vh, 64px) 0 clamp(14px, 2.2vh, 24px);
}
.signal-split > * { min-width: 0; }

/* huge editorial numerals — no boxes, no dividers */
.signal-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 2.2vw, 36px);
}
.signal-stats .stat { padding: 0; }
/* the numeral's cap sits level with the headline's first line */
.signal-stats .stat strong { margin-top: -0.12em; }
.signal-stats .stat strong {
  display: block;
  font-size: clamp(56px, 7vw, 120px);
  font-weight: 300;
  letter-spacing: -0.05em;
  line-height: 1;
  color: var(--ink-strong);
  font-variant-numeric: tabular-nums;
}
.signal-stats .stat span {
  display: block;
  margin-top: 12px;
  font: 400 10.5px "Geist", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-strong);
}

.signal-copy {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 520px;
  min-width: 0;
}
/* the copy half fills its column — no width caps forcing early breaks */
.signal-copy--full { max-width: none; }
.signal-copy--full .signal-head,
.signal-copy--full .body { max-width: none; }
.signal-head {
  font-size: clamp(22px, 2.1vw, 30px);
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.signal-head strong { font-weight: 600; }
/* body under the modosignal title reads in full ink, matching the title */
.signal-copy .body { color: var(--ink-strong); }

/* ---------- Insights dashboard embed: the real, interactive UI ---------- */
/* Framed and floating over the page — full content width. The iframe
   renders at a fixed desktop design size and script.js scales it to fit
   the frame, so the app keeps its true proportions at any width while
   staying fully interactive. */
.insights-embed { width: 100%; }
.insights-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 1280 / 800; /* the iframe's design size */
  overflow: hidden;
  /* no frame, no floor — the app dissolves into the page background,
     the same fade language the site uses at its viewport edges */
  -webkit-mask-image: linear-gradient(180deg, #000 58%, transparent 98%);
  mask-image: linear-gradient(180deg, #000 58%, transparent 98%);
}
.insights-frame iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 1280px;
  height: 800px;
  border: 0;
  transform-origin: 0 0; /* script.js sets transform: scale(...) */
  background: #fff;
}

.signup {
  display: flex;
  align-items: center;
  gap: 16px;
  justify-content: space-between;
  flex-wrap: wrap;
}
/* demo ask hugs the title — left-aligned column of heading, line, form —
   and the dashboard below gets room to breathe */
.product-head .signup {
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  width: auto;
  margin-top: clamp(10px, 1.8vh, 20px);
}
.insights-embed { margin-top: clamp(6px, 1.6vh, 20px); }
/* one sentence — the ask carries the emphasis in semibold */
.signup .cta-copy strong { font-weight: 600; color: var(--ink-strong); }
/* reads as ordinary body copy, not a caption — and stays unbolded */
.signup .cta-copy p {
  font-size: clamp(14px, 1.5vw, 16px);
  line-height: 1.6;
  font-weight: 400;
  color: var(--fg-soft);
  margin-top: 4px;
}
.signup .cta-copy p a { font-weight: 400; }
.signup form { display: flex; gap: 8px; flex-wrap: wrap; }
.signup input {
  font: 400 13.5px "Geist", sans-serif;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-ui);
  padding: 10px 18px;
  width: clamp(150px, 16vw, 230px);
  background: var(--field-bg);
  color: var(--fg);
  outline: none;
  transition: border-color 0.2s ease, background 0.6s ease, color 0.6s ease;
}
.signup input::placeholder { color: var(--fg-faint); }
.signup input:focus { border-color: var(--accent); }
/* full-width flex line, so the message wraps under the field rather than
   squeezing in beside it — and outranks :focus while the error stands */
.signup .field-error {
  flex: 0 0 100%;
  font: 400 12px "Geist", sans-serif;
  line-height: 1.4;
  color: var(--error-fg);
  transition: color 0.6s ease; /* rides the theme cross-fade */
}
.signup form.has-error input { border-color: var(--error-fg); }
.signup .go {
  position: relative;
  overflow: hidden;
  font: 600 13.5px "Geist", sans-serif;
  color: #fff;
  background: var(--accent);
  border: none;
  border-radius: var(--radius-ui);
  padding: 10px 20px;
  cursor: pointer;
  transition: background 0.3s ease;
}
.signup .go .blob { mix-blend-mode: screen; }
.signup form.is-done input { opacity: 0.5; pointer-events: none; }
.signup form.is-done .go { background: var(--solid); color: var(--solid-fg); pointer-events: none; }

/* ---------- Bottom bar: legal left · page indicator right ---------- */
/* in normal flow at the end of the active page's scroll content;
   extra bottom padding keeps the text clear of the viewport fade mask */
/* copyright left · legal links dead-centre · icons right — equal side
   columns keep the links truly centred whatever the sides measure */
.bottombar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  max-width: 1320px;
  margin: 0 auto;
  width: 100%;
  flex-shrink: 0; /* flex child of the page — never squashed to fit */
  padding: 26px var(--pad-x) 48px;
  border-top: 1px solid var(--line-c);
  transition: color 0.6s ease;
}
.bottombar .legal { justify-self: start; }
.bottombar .legal-links { justify-self: center; }
.bottombar .footer-icons { justify-self: end; }
.legal {
  display: flex;
  align-items: center;
  gap: 12px;
  font: 400 11px "Geist Mono", monospace;
  letter-spacing: 0.04em;
  color: var(--fg-faint);
}
.legal-links {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.5vw, 28px);
}
.legal-links a {
  font: 400 11px "Geist Mono", monospace;
  letter-spacing: 0.04em;
  color: var(--fg-faint);
  transition: color 0.3s ease;
}
.legal-links a:hover { color: var(--fg); }
.footer-icons {
  display: flex;
  align-items: center;
  gap: 16px;
}
.bottombar .footer-icons { margin-left: auto; }
.footer-icons a {
  display: inline-flex;
  color: var(--fg-faint);
  cursor: pointer;
  transition: color 0.3s ease;
}
.footer-icons a:hover { color: var(--fg); }
.footer-icons svg { width: 17px; height: 17px; }

/* ---------- Mobile menu (burger + full-screen overlay) ---------- */
.menu-burger {
  display: none; /* desktop hides it; the 720 query shows it */
  justify-self: end;
  color: var(--fg);
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
  transition: color 0.6s ease;
}
.menu-burger svg { width: 24px; height: 24px; display: block; }

/* No painted background of its own: opening the menu morphs the live
   mesh gradient itself to pure white (script.js setPalette) — the same
   bleed the intro loader and page transitions use. The menu UI simply
   settles in over the whitening field. */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 200;
  visibility: hidden;
  pointer-events: none;
  /* stay visible while the UI fades out on close */
  transition: visibility 0s linear 0.45s;
}
.mobile-menu .menu-inner {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 14px 20px calc(22px + env(safe-area-inset-bottom, 0px));
  color: var(--ink);
  opacity: 0;
  transition: opacity 0.25s ease;
}
.menu-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 34px;
}
.menu-logomark { line-height: 0; }
.menu-logomark svg { height: 22px; width: auto; display: block; }
.menu-close {
  color: var(--ink);
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px;
}
.menu-close svg { width: 24px; height: 24px; display: block; }

.menu-nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
}
.menu-nav a {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 16px 0;
  font-size: clamp(30px, 8.8vw, 46px);
  font-weight: 300;
  letter-spacing: -0.03em;
  color: var(--ink);
  border-bottom: 1px solid rgba(22, 21, 15, 0.1);
  /* content slides up as the menu opens (staggered via inline delay) */
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.5s ease, transform 0.6s var(--ease-out);
}
.menu-nav a span {
  font: 500 12px "Geist Mono", monospace;
  letter-spacing: 0.1em;
  color: #8a877e;
}
.menu-nav a.active { color: var(--accent); }
.menu-nav a.active span { color: var(--accent); }

/* demo CTA: part of the stack but clearly the action, not a page */
.menu-nav .menu-demo {
  align-items: center;
  gap: 12px;
  font-size: clamp(19px, 5.6vw, 24px);
  font-weight: 400;
  color: var(--accent);
  border-bottom: none;
  margin-top: 10px;
}
.menu-nav .menu-demo .icon { width: 20px; height: 20px; }

.menu-footer {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding-top: 20px;
  border-top: 1px solid rgba(22, 21, 15, 0.1);
  color: var(--ink);
}
.menu-legal {
  display: flex;
  align-items: center;
  gap: 20px;
}
.menu-legal a {
  font: 400 11px "Geist Mono", monospace;
  letter-spacing: 0.04em;
  color: #8a877e;
}
.menu-legal a:active { color: var(--ink); }
.menu-foot-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.menu-footer .footer-icons a { color: #8a877e; }
.menu-footer .footer-icons a:hover { color: var(--ink); }
.menu-copyright {
  font: 400 10.5px "Geist Mono", monospace;
  letter-spacing: 0.04em;
  color: #8a877e;
}

/* leaving for a legal page: everything fades to the white they live on */
/* one declaration — a second bare `body { transition }` would replace
   this shorthand wholesale rather than adding to it */
body { transition: opacity 0.3s ease, color 0.6s ease, background-color 0.6s ease; }
body.leaving { opacity: 0; pointer-events: none; }

/* open state: mesh bleeds to white underneath while the UI settles in */
body.menu-open .mobile-menu { visibility: visible; pointer-events: auto; transition: visibility 0s; }
body.menu-open .mobile-menu .menu-inner { opacity: 1; transition: opacity 0.45s ease 0.2s; }
body.menu-open .menu-nav a { opacity: 1; transform: none; transition-delay: var(--md, 0ms); }
body.menu-open .shell { opacity: 0; pointer-events: none; }
.shell { transition: opacity 0.4s ease; }

/* ---------- Products dark: surfaces and shapes tokens can't express ---------- */
/* hollow marker inverts rather than becoming a solid white dot */
body[data-page="product"][data-theme="dark"] .roadmap-item::before {
  background: #242424;
  border-color: #ffffff;
}
/* the demo's own ground shows while the lazy iframe loads, and behind
   the fade mask — its dark ground is deeper than the page's brand ink */
body[data-page="product"][data-theme="dark"] .insights-frame iframe { background: #131010; }
/* the mailto needs more than weight to read at 82% white */
body[data-page="product"][data-theme="dark"] .signup .cta-copy p a {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}
/* the full-screen menu bleeds the mesh to the page ground, so its own
   chrome follows the theme too */
body[data-page="product"][data-theme="dark"] .menu-inner,
body[data-page="product"][data-theme="dark"] .menu-close,
body[data-page="product"][data-theme="dark"] .menu-nav a,
body[data-page="product"][data-theme="dark"] .menu-footer { color: #ffffff; }
body[data-page="product"][data-theme="dark"] .menu-nav a,
body[data-page="product"][data-theme="dark"] .menu-footer { border-color: rgba(255, 255, 255, 0.14); }
body[data-page="product"][data-theme="dark"] .menu-nav a span,
body[data-page="product"][data-theme="dark"] .menu-legal a,
body[data-page="product"][data-theme="dark"] .menu-copyright,
body[data-page="product"][data-theme="dark"] .menu-footer .footer-icons a { color: rgba(255, 255, 255, 0.6); }
body[data-page="product"][data-theme="dark"] .menu-legal a:active,
body[data-page="product"][data-theme="dark"] .menu-footer .footer-icons a:hover { color: #ffffff; }

/* ---------- Entry loader ---------- */
.loader {
  position: fixed;
  inset: 0;
  z-index: 100;
  background-color: #fff;
  display: grid;
  place-items: center;
  transition: background-color 1.5s ease;
}
/* the white blends away, revealing the mesh blooming underneath, while
   the canvas logo flies to the navbar (transform set inline by JS) */
.loader.is-blending {
  background-color: rgba(255, 255, 255, 0);
  pointer-events: none;
}
.loader canvas {
  width: min(340px, 72vw);
  height: auto;
  will-change: transform;
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  [data-reveal], .split .wi, .inner { transition: none; }
  .page [data-reveal] { opacity: 1; transform: none; }
  .page .split .wi { transform: none; }
  .page .problem[data-reveal] { transform: rotate(var(--rz, 0deg)); }
}

/* ---------- Responsive ---------- */
@media (max-width: 1020px) {
  .roadmap-track { grid-template-columns: 1fr; gap: 26px; }
  .roadmap-track::before { display: none; }
  /* stacked: the numbers lead, the copy follows */
  .signal-split { grid-template-columns: 1fr; align-items: start; }
  .signal-split .signal-stats { order: -1; }
  .about-grid { grid-template-columns: 1fr; }
  .inner { justify-content: flex-start; }
}
@media (max-width: 720px) {
  /* topbar: logomark left, burger right; nav + cta live in the menu now */
  .topbar { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px; }
  .topbar nav { display: none; }
  .top-cta { display: none; }
  .logomark svg { height: 22px; }
  .menu-burger { display: inline-flex; }
  .bottombar { display: none; } /* footer moves into the mobile menu */

  .product-head .side-note { display: none; }
  /* the two numerals still fit side by side at phone widths */
  .signal-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
  .signal-stats .stat strong { font-size: clamp(40px, 12vw, 64px); }
  .tcard { width: clamp(220px, 72vw, 300px); }
  .hero-foot { flex-direction: column; align-items: flex-start; }
  .product-mark { height: clamp(36px, 11vw, 46px); }

  /* ---- Mobile typography: bold, impactful home; about, team + products
          headlines all one size ---- */
  .display { font-size: clamp(42px, 13vw, 64px); letter-spacing: -0.04em; }
  .lede { font-size: clamp(17px, 4.6vw, 20px); max-width: none; }
  #about .headline,
  #team .headline,
  #product .headline { font-size: clamp(30px, 7.8vw, 40px); max-width: none; }

  /* ---- About: CTA drops below the three cards ---- */
  .about-grid { display: flex; flex-direction: column; gap: clamp(22px, 6vw, 30px); }
  .about-left { display: contents; }
  .about-left .head-block { order: 1; }
  .about-left .body { order: 2; }
  .about-right { order: 3; }
  .about-left .pill { order: 4; align-self: flex-start; }
}
