/* ==========================================================================
   Kinetic — kineticai.me
   Palette mirrors the app: kinetic-mobile/client/shared/theme/colors.ts
   Type: Geist + Geist Mono (SIL OFL), self-hosted — no third-party requests.
   ========================================================================== */

/* ---------- Fonts ---------- */

@font-face {
  font-family: "Geist";
  src: url("/assets/fonts/Geist-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Geist Mono";
  src: url("/assets/fonts/GeistMono-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */

:root {
  /* Surfaces — from the app's colors.ts */
  --bg-root: #0b0b12;
  --bg: #14141f;
  --surface: #1c1c2a;
  --surface-2: #252535;

  /* Brand */
  --primary: #8b5cf6;
  --primary-deep: #7c3aed;
  --primary-light: #a78bfa;
  --primary-muted: rgba(139, 92, 246, 0.15);
  --primary-glow: rgba(139, 92, 246, 0.35);

  /* Signal */
  --success: #22c55e;
  --gold: #fbbf24;
  --warning: #f97316;
  --error: #ef4444;

  /* Text */
  --text: #ffffff;
  --text-2: #94a3b8;
  --text-3: #64748b;
  --text-4: #475569;

  /* Lines */
  --border: rgba(255, 255, 255, 0.1);
  --border-strong: rgba(255, 255, 255, 0.16);
  --separator: rgba(255, 255, 255, 0.06);

  /* Spacing scale */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;
  --s-9: 96px;
  --s-10: 128px;

  /* Radii */
  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 16px;
  --r-xl: 22px;
  --r-2xl: 28px;
  --r-full: 999px;

  /* Elevation */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 24px 64px rgba(0, 0, 0, 0.55);

  /* Motion — no springs; calm ease-out (see brand rule) */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 400ms;

  /* Layout */
  --maxw: 1180px;
  --gutter: 24px;
  --nav-h: 64px;

  /* Breakpoints, documented (CSS vars can't be used in media queries):
     1200 · 992 · 768 · 560 · 380 */
}

/* ---------- Reset ---------- */

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  color-scheme: dark;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* lets height:auto animate, used by the FAQ accordion */
  interpolate-size: allow-keywords;
}

body {
  background: var(--bg-root);
  color: var(--text);
  font-family: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  /* Sticky footer: the page is a column at least one viewport tall and the
     footer takes the slack (margin-top: auto), so short pages (account
     states, 404) pin it to the bottom without adding scroll. svh is the
     small viewport, so iOS Safari's collapsing toolbar never forces a
     scroll on an otherwise short page. */
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}

body > main {
  flex: 1 0 auto;
}

body > .footer {
  margin-top: auto;
}

img,
svg {
  max-width: 100%;
  display: block;
}

a {
  color: var(--primary-light);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

::selection {
  background: var(--primary);
  color: #fff;
}

/* ---------- Focus + skip link ---------- */

:focus-visible {
  outline: 2px solid var(--primary-light);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--primary);
  color: #fff;
  padding: 12px 20px;
  border-radius: 0 0 var(--r-sm) 0;
  font-weight: 600;
}

.skip-link:focus {
  left: 0;
  text-decoration: none;
}

/* ---------- Utilities ---------- */

.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding-inline: var(--gutter);
}

.mono {
  font-family: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.eyebrow {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--primary-light);
  margin-bottom: var(--s-4);
}

.accent {
  color: var(--primary-light);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Reveal animation ---------- */

/* ~400ms ease-out fade with a small rise. No springs, no scale — entrances
   stay calm. Desktop only; see the note in index.html. */
.reveal {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

/* Where the layout stacks, content is present from the start — never hidden,
   even for the moment before the script runs. */
@media (max-width: 992px) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

.reveal.is-in {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ==========================================================================
   Nav
   ========================================================================== */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(11, 11, 18, 0.72);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-bottom: 1px solid var(--separator);
}

.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-h);
  gap: var(--s-4);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  font-size: 17px;
  letter-spacing: 0.08em;
  color: var(--text);
  flex-shrink: 0;
}

.brand:hover {
  text-decoration: none;
}

.brand img {
  width: 28px;
  height: 28px;
  border-radius: 7px;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--s-6);
}

.nav-links a {
  color: var(--text-2);
  font-size: 15px;
  font-weight: 450;
  transition: color 180ms var(--ease);
}

.nav-links a:hover {
  color: var(--text);
  text-decoration: none;
}

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  margin-right: -10px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-sm);
}

.nav-toggle span {
  display: block;
  width: 20px;
  height: 1.5px;
  background: var(--text);
  border-radius: 2px;
  transition: transform 240ms var(--ease), opacity 180ms var(--ease);
}

.nav-toggle span + span {
  margin-top: 5px;
}

body.nav-open .nav-toggle span:nth-child(1) {
  transform: translateY(6.5px) rotate(45deg);
}

body.nav-open .nav-toggle span:nth-child(2) {
  opacity: 0;
}

body.nav-open .nav-toggle span:nth-child(3) {
  transform: translateY(-6.5px) rotate(-45deg);
}

/* Mobile sheet */
.nav-sheet {
  display: none;
  position: fixed;
  inset: var(--nav-h) 0 0;
  z-index: 40;
  background: var(--bg-root);
  padding: var(--s-6) var(--gutter) calc(var(--s-8) + env(safe-area-inset-bottom));
  flex-direction: column;
  gap: var(--s-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity 240ms var(--ease);
}

.nav-sheet a {
  color: var(--text);
  font-size: 20px;
  font-weight: 500;
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--separator);
}

.nav-sheet a:hover {
  text-decoration: none;
  color: var(--primary-light);
}

body.nav-open .nav-sheet {
  opacity: 1;
  pointer-events: auto;
}

body.nav-open {
  overflow: hidden;
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.hero::before {
  content: "";
  position: absolute;
  inset: -20% -10% auto -10%;
  height: 640px;
  background: radial-gradient(
    ellipse 60% 55% at 30% 40%,
    rgba(139, 92, 246, 0.18) 0%,
    transparent 70%
  );
  z-index: -1;
  pointer-events: none;
}

/* Grid/flex children default to min-width:auto, which lets wide content
   (images, tables, mono strings) force the whole page wider than the phone.
   Reset it everywhere we lay out. */
.hero-inner > *,
.pillar > *,
.proof-grid > *,
.social-grid > * {
  min-width: 0;
}

.hero-inner {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  align-items: center;
  gap: var(--s-7);
  padding: clamp(32px, 4.5vw, 60px) 0 clamp(40px, 5.5vw, 72px);
}

.hero h1 {
  font-size: clamp(40px, 6.4vw, 68px);
  font-weight: 600;
  line-height: 1.04;
  letter-spacing: -0.032em;
  margin-bottom: var(--s-5);
  text-wrap: balance;
}

.hero .sub {
  font-size: clamp(17px, 2vw, 20px);
  line-height: 1.55;
  color: var(--text-2);
  max-width: 30em;
  margin-bottom: var(--s-6);
}

/* Hero artwork — bleeds, no frame. The source PNG is already near-black,
   so a mask lets it dissolve into the page instead of reading as a card. */
.hero-art {
  position: relative;
  justify-self: center;
  width: 100%;
  max-width: 470px;
}

/* <picture> is inline by default, so `img { width: 100% }` would resolve
   against the image's intrinsic 896px instead of the column — which blows the
   page out to 506px on phones. Make it a block. */
.hero-art picture {
  display: block;
  width: 100%;
}

/* The artwork carries a real alpha channel (luminance baked to alpha at build
   time), so the black canvas is genuinely transparent. No blend mode, no mask
   — it composites cleanly over the page or over the mobile frame, with no
   seam where the image box ends. */
.hero-art img {
  width: 100%;
  height: auto;
}

/* ---------- Store CTA ---------- */

.store-cta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
}

.store-badge {
  display: inline-block;
  border-radius: 9px;
  transition: transform 200ms var(--ease), opacity 200ms var(--ease);
}

.store-badge img {
  height: 54px;
  width: auto;
}

.store-badge:hover {
  transform: translateY(-1px);
}

/* Unreleased state: still focusable and announced, unlike a stripped <a>. */
.store-badge[aria-disabled="true"] {
  opacity: 0.75;
  cursor: default;
}

.store-badge[aria-disabled="true"]:hover {
  transform: none;
}

.coming-soon {
  display: none;
  align-items: center;
  gap: var(--s-2);
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primary-light);
  background: var(--primary-muted);
  border: 1px solid rgba(139, 92, 246, 0.28);
  border-radius: var(--r-full);
  padding: 5px 14px;
}

.store-cta.is-coming-soon .coming-soon {
  display: inline-flex;
}

.store-cta [hidden] {
  display: none !important;
}

/* TestFlight beta button. Apple's App Store badge may only link to the App
   Store, so the beta gets a first-party button in the app's palette instead. */
.tf-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  height: 54px;
  padding: 0 var(--s-5) 0 var(--s-4);
  border-radius: var(--r-full);
  background: var(--primary);
  color: var(--text);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 8px 24px var(--primary-glow);
  transition: transform 200ms var(--ease), background 200ms var(--ease), box-shadow 200ms var(--ease);
}

.tf-btn svg {
  width: 18px;
  height: 18px;
  flex: none;
}

.tf-btn:hover {
  background: var(--primary-deep);
  transform: translateY(-1px);
  box-shadow: 0 10px 28px var(--primary-glow);
}

.tf-btn:focus-visible {
  outline: 2px solid var(--primary-light);
  outline-offset: 3px;
}

.tf-note {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--text-3);
}

.coming-soon::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary-light);
  box-shadow: 0 0 8px var(--primary-glow);
}

/* ==========================================================================
   Sections
   ========================================================================== */

.section {
  padding: clamp(64px, 10vw, 128px) 0;
}

.section + .section {
  border-top: 1px solid var(--separator);
}

.section-head {
  max-width: 660px;
  margin-bottom: var(--s-8);
}

.section-head.center {
  margin-inline: auto;
  text-align: center;
}

.section-head h2 {
  font-size: clamp(28px, 4.2vw, 44px);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.028em;
  margin-bottom: var(--s-4);
  text-wrap: balance;
}

.section-head p {
  font-size: clamp(16px, 1.8vw, 18px);
  color: var(--text-2);
  line-height: 1.6;
}

/* ---------- Pillar rows ---------- */

.pillar {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: clamp(40px, 6vw, 88px);
}

.pillar.reverse .pillar-media {
  order: -1;
}

.pillar-copy h2 {
  font-size: clamp(26px, 3.6vw, 40px);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.026em;
  margin-bottom: var(--s-4);
  text-wrap: balance;
}

/* Must exclude .eyebrow and .note: `.pillar-copy > p` (0,1,1) outranks the
   plain `.eyebrow` class (0,1,0) and was forcing both to 16px. */
.pillar-copy > p:not(.eyebrow):not(.note) {
  font-size: clamp(16px, 1.8vw, 18px);
  color: var(--text-2);
  margin-bottom: var(--s-6);
}

.pillar-media {
  display: flex;
  justify-content: center;
  min-width: 0;
}

/* Checklist */
.checks {
  list-style: none;
  display: grid;
  gap: var(--s-3);
}

.checks li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: var(--s-3);
  align-items: start;
  font-size: 16px;
  color: var(--text-2);
}

.checks li strong {
  color: var(--text);
  font-weight: 500;
}

.checks .tick {
  width: 22px;
  height: 22px;
  margin-top: 2px;
  border-radius: 50%;
  background: var(--primary-muted);
  border: 1px solid rgba(139, 92, 246, 0.3);
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.checks .tick svg {
  width: 12px;
  height: 12px;
  stroke: var(--primary-light);
  stroke-width: 2.5;
  fill: none;
}

/* Not-yet-shipped capability: visually softer, and always labelled. */
.checks .tick.soon {
  background: rgba(148, 163, 184, 0.1);
  border-color: rgba(148, 163, 184, 0.25);
}

.checks .tick.soon svg {
  stroke: var(--text-3);
}

.soon-tag {
  display: inline-block;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-3);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  padding: 2px 8px;
  margin-left: 6px;
  vertical-align: 1px;
  white-space: nowrap;
}

.note {
  margin-top: var(--s-5);
  font-size: 14px;
  color: var(--text-3);
  line-height: 1.55;
}

/* ==========================================================================
   Phone mockup — hand-built app UI (no screenshots, no real user data)
   ========================================================================== */

.phone {
  position: relative;
  width: 300px;
  max-width: 100%;
  aspect-ratio: 300 / 620;
  background: #05050a;
  border: 1px solid var(--border-strong);
  border-radius: 42px;
  padding: 9px;
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(255, 255, 255, 0.04) inset,
    0 40px 90px -30px var(--primary-glow);
  flex-shrink: 0;
}

.phone-screen {
  position: relative;
  height: 100%;
  background: var(--bg);
  border-radius: 34px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Dynamic island */
.phone-screen::before {
  content: "";
  position: absolute;
  top: 9px;
  left: 50%;
  transform: translateX(-50%);
  width: 78px;
  height: 22px;
  background: #05050a;
  border-radius: var(--r-full);
  z-index: 5;
}

.status-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px 6px;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  color: var(--text);
  flex-shrink: 0;
}

.status-bar .bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 9px;
}

.status-bar .bars i {
  width: 2.5px;
  background: var(--text);
  border-radius: 1px;
}

.status-bar .bars i:nth-child(1) { height: 30%; }
.status-bar .bars i:nth-child(2) { height: 55%; }
.status-bar .bars i:nth-child(3) { height: 78%; }
.status-bar .bars i:nth-child(4) { height: 100%; }

.status-bar .batt {
  width: 20px;
  height: 10px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 3px;
  position: relative;
  padding: 1.5px;
}

.status-bar .batt::after {
  content: "";
  display: block;
  height: 100%;
  width: 72%;
  background: var(--text);
  border-radius: 1px;
}

.app-sub {
  font-size: 10.5px;
  color: var(--text-3);
}

/* Stats strip inside the app */
.stat-strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background: var(--surface);
  border: 1px solid var(--separator);
  border-radius: var(--r-md);
  overflow: hidden;
}

.stat-strip div {
  padding: 9px 6px;
  text-align: center;
}

.stat-strip div + div {
  border-left: 1px solid var(--separator);
}

.stat-strip .k {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-4);
}

.stat-strip .v {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  margin-top: 2px;
}

/* Exercise card + set rows */
.ex-card {
  background: var(--surface);
  border: 1px solid var(--separator);
  border-radius: var(--r-md);
  padding: 10px;
}

.ex-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: 9px;
}

/* Session header — mirrors the app's Duration / Volume / Sets bar */
.sess-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  padding-bottom: 9px;
}

.sess-title {
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  flex: 1;
}

.sess-date {
  font-size: 9.5px;
  color: var(--text-3);
  margin-top: 1px;
}

.btn-finish {
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  background: var(--primary);
  border-radius: var(--r-full);
  padding: 5px 14px;
  white-space: nowrap;
}

.metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-block: 1px solid var(--separator);
  padding: 8px 0;
}

.metrics > div {
  text-align: center;
}

.metrics .k {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 8px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
}

.metrics .v {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 600;
  margin-top: 2px;
}

.metrics .v small {
  font-size: 11px;
  color: var(--text-3);
  font-weight: 400;
}

/* Rest pill replaces the middle metric while a rest timer runs */
.rest-pill {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1.5px solid var(--primary);
  border-radius: var(--r-full);
  padding: 4px 8px;
  color: var(--primary-light);
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 13px;
  font-weight: 600;
}

.rest-pill span {
  font-size: 9.5px;
  color: var(--text-3);
  font-weight: 400;
}

.ex-sub {
  font-size: 9.5px;
  color: var(--text-3);
  margin-top: 1px;
}

/* Set grid — completed sets get a green wash and outlined inputs */
.set-cols {
  display: grid;
  grid-template-columns: 22px 1fr 1fr 26px;
  gap: 6px;
  align-items: center;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 8px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-3);
  padding: 6px 0;
}

.kg-chip {
  background: #221f38;
  border-radius: 5px;
  padding: 3px 0;
  text-align: center;
  color: var(--primary-light);
  font-size: 8px;
  letter-spacing: 0.1em;
}

.srow {
  display: grid;
  grid-template-columns: 22px 1fr 1fr 26px;
  gap: 6px;
  align-items: center;
  padding: 5px 0;
}

.srow.ok {
  background: rgba(34, 197, 94, 0.09);
}

/* Grid, not text-align — the global `svg { display:block }` rule would
   otherwise left-align the PR medal inside this cell. */
.srow .n {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  color: var(--primary-light);
  display: grid;
  place-items: center;
  height: 100%;
}

.srow.ok .n {
  color: var(--success);
}

.srow .box {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  font-weight: 500;
  text-align: center;
  padding: 5px 0;
  border-radius: 6px;
  color: var(--text);
}

.srow.ok .box {
  border: 1px solid rgba(34, 197, 94, 0.4);
  background: rgba(34, 197, 94, 0.06);
}

.srow.todo .box {
  color: var(--text-4);
}

.srow .tick-c {
  width: 19px;
  height: 19px;
  border-radius: 50%;
  border: 1.5px solid var(--border-strong);
  justify-self: center;
  display: grid;
  place-items: center;
}

.srow.ok .tick-c {
  background: var(--success);
  border-color: var(--success);
}

.srow .tick-c svg {
  width: 10px;
  height: 10px;
  stroke: #06210f;
  stroke-width: 3.5;
  fill: none;
}

.srow.todo .tick-c svg {
  display: none;
}

.add-set {
  text-align: center;
  font-size: 10px;
  color: var(--text-3);
  padding: 7px 0 2px;
  border-top: 1px solid var(--separator);
  margin-top: 5px;
}

/* Floating coach button, bottom-right of the session screen */
.coach-fab {
  position: absolute;
  right: 12px;
  bottom: 12px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: #2a1f4d;
  border: 1px solid rgba(139, 92, 246, 0.5);
  box-shadow: 0 0 18px var(--primary-glow);
  display: grid;
  place-items: center;
  font-size: 15px;
}

.ex-name {
  font-size: 12px;
  font-weight: 550;
  color: var(--primary-light);
  line-height: 1.2;
}

.set-head,
.set-row {
  display: grid;
  grid-template-columns: 20px 1fr 34px 30px 22px;
  gap: 6px;
  align-items: center;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 10.5px;
}

.set-head {
  font-size: 8.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-4);
  padding-bottom: 5px;
  border-bottom: 1px solid var(--separator);
  margin-bottom: 5px;
}

.set-row {
  padding: 5px 4px;
  border-radius: 6px;
  color: var(--text-2);
  margin-inline: -4px;
}

.set-row .prev {
  color: var(--text-4);
}

.set-row .val {
  color: var(--text);
  font-weight: 500;
}

.set-row.warm .idx {
  color: var(--warning);
}

.set-row .check {
  width: 16px;
  height: 16px;
  border-radius: 5px;
  border: 1px solid var(--border-strong);
  display: grid;
  place-items: center;
  justify-self: end;
}

.set-row .check svg {
  width: 9px;
  height: 9px;
  stroke: #05140a;
  stroke-width: 3;
  fill: none;
}

.rest-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--primary-muted);
  border: 1px solid rgba(139, 92, 246, 0.28);
  border-radius: var(--r-sm);
  padding: 7px 10px;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10.5px;
  color: var(--primary-light);
}

/* ---------- Charts inside the phone ---------- */

.chart-card {
  background: var(--surface);
  border: 1px solid var(--separator);
  border-radius: var(--r-md);
  padding: 11px;
}

.chart-card .ct {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-4);
  font-family: "Geist Mono", ui-monospace, monospace;
}

.chart-card .cv {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-top: 3px;
}

.delta {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10.5px;
  color: var(--success);
}

.delta.down {
  color: var(--warning);
}

/* MEV/MRV landmark bar */
.landmark {
  margin-top: 4px;
}

.landmark-track {
  position: relative;
  height: 8px;
  border-radius: var(--r-full);
  background: var(--surface-2);
  overflow: hidden;
}

.landmark-zone {
  position: absolute;
  inset-block: 0;
  left: 32%;
  width: 40%;
  background: rgba(34, 197, 94, 0.4);
}

.landmark-mark {
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: 56%;
  width: 2px;
  background: var(--text);
  border-radius: 1px;
}

.landmark-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 5px;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 8.5px;
  letter-spacing: 0.08em;
  color: var(--text-4);
  text-transform: uppercase;
}

/* Muscle readiness rows */
.ready-row {
  display: grid;
  grid-template-columns: 52px 1fr 26px;
  gap: 7px;
  align-items: center;
  font-size: 10px;
  color: var(--text-2);
}

.ready-row + .ready-row {
  margin-top: 7px;
}

.ready-track {
  height: 5px;
  border-radius: var(--r-full);
  background: var(--surface-2);
  overflow: hidden;
}

.ready-fill {
  height: 100%;
  border-radius: var(--r-full);
  background: var(--success);
}

.ready-fill.mid {
  background: var(--gold);
}

.ready-fill.low {
  background: var(--warning);
}

.ready-row .pct {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 9.5px;
  color: var(--text-3);
  text-align: right;
}

/* ---------- Coach chat ---------- */

.memory-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  font-size: 9.5px;
  font-family: "Geist Mono", ui-monospace, monospace;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-3);
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--r-full);
  padding: 4px 10px;
}

.memory-chip svg {
  width: 10px;
  height: 10px;
  stroke: var(--primary-light);
  stroke-width: 2;
  fill: none;
}

/* ==========================================================================
   Rank ladder

   Was an 11-box grid: uniform weight for Rookie and Immortal, and a lone
   orphan card on the last row. A ladder is ordered and escalating, so it is
   drawn as one continuous rail — badges grow as you climb, the track warms
   from steel to gold, and the two best taglines bookend the journey.
   ========================================================================== */

/* The ladder is the last thing in this section, so its own bottom margin
   would sit on top of the section's padding and make the space below
   "Everyone starts here" ~96px deeper than the space above the eyebrow.
   (It existed to clear the "How XP works" table, which is hidden — and that
   block carries its own top margin anyway, so this was always redundant.) */
.ladder {
  margin-top: var(--s-7);
  margin-bottom: 0;
}

.ladder-rail {
  list-style: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-2);
  position: relative;
}

/* The track, pinned to the shared centre-line of every badge cradle. */
.ladder-rail::before {
  content: "";
  position: absolute;
  left: 2%;
  right: 2%;
  top: 43px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(
    90deg,
    #475569 0%,
    #34d399 18%,
    var(--primary) 52%,
    #e879f9 72%,
    var(--gold) 100%
  );
  opacity: 0.45;
}

.rung {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1 1 0;
  min-width: 0;
  text-align: center;
  position: relative;
}

/* Fixed-height cradle so badges of different sizes still share one axis. */
.rung-badge {
  height: 86px;
  display: grid;
  place-items: center;
  position: relative;
}

.rung-badge::before {
  content: "";
  position: absolute;
  width: calc(var(--sz) + 22px);
  height: calc(var(--sz) + 22px);
  border-radius: 50%;
  background: var(--bg-root);
  box-shadow: inset 0 0 0 1px var(--separator);
}

.rung-badge svg {
  width: var(--sz);
  height: var(--sz);
  position: relative;
  transition: transform 260ms var(--ease);
}

.rung:hover .rung-badge svg {
  transform: translateY(-3px) scale(1.06);
}

.rung-name {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-top: var(--s-3);
}

.rung-lvl {
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-4);
  margin-top: 4px;
}

/* Reserved space, revealed on hover — 11 permanent XP figures read as clutter
   next to 11 names and 11 levels. The 336,600 line below tells the same story. */
.rung-xp {
  font-size: 10.5px;
  color: var(--primary-light);
  opacity: 0;
  margin-top: 3px;
  transition: opacity 200ms var(--ease);
}

.rung:hover .rung-xp,
.rung:focus-within .rung-xp {
  opacity: 0.85;
}

.rung-xp::after {
  content: " XP";
  color: var(--text-4);
}

.ladder-ends {
  display: flex;
  justify-content: space-between;
  gap: var(--s-5);
  margin-top: var(--s-4);
  font-size: 14.5px;
  font-style: italic;
  color: var(--text-3);
}

.ladder-ends span:last-child {
  text-align: right;
  color: var(--gold);
  opacity: 0.85;
}

/* The XP figure inside the section intro */
.section-head p strong.mono {
  color: var(--text);
  font-weight: 600;
}

/* Swipe affordance — only shown where the rail actually scrolls. */
.swipe-hint {
  display: none;
  margin-top: var(--s-3);
  text-align: right;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
}

/* XP table */
.xp-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: var(--s-6);
  font-size: 15px;
}

.xp-table th,
.xp-table td {
  text-align: left;
  padding: var(--s-3) var(--s-2);
  border-bottom: 1px solid var(--separator);
}

.xp-table th {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
  font-weight: 500;
}

.xp-table td:last-child,
.xp-table th:last-child {
  text-align: right;
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.xp-table td:first-child {
  color: var(--text);
}

.xp-table td:last-child {
  color: var(--success);
  font-weight: 500;
}

.xp-table td.minus:last-child {
  color: var(--warning);
}

/* ==========================================================================
   Social cards
   ========================================================================== */

.social-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-4);
}

.card {
  background: var(--surface);
  border: 1px solid var(--separator);
  border-radius: var(--r-lg);
  padding: var(--s-5);
}

.card-title {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
  margin-bottom: var(--s-4);
}

/* Carousel affordance — mobile only, where .social-grid actually scrolls. */
.social-hint {
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  margin-top: var(--s-4);
}

.social-hint i {
  width: 22px;
  height: 3px;
  border-radius: 2px;
  background: var(--border);
  transition: background 200ms var(--ease);
}

.social-hint i.on {
  background: var(--primary);
}

.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 600;
  color: #fff;
  flex-shrink: 0;
  background: linear-gradient(135deg, var(--primary), var(--primary-deep));
}

.avatar.b {
  background: linear-gradient(135deg, #38bdf8, #0284c7);
}

.avatar.c {
  background: linear-gradient(135deg, #fb923c, #ea580c);
}

/* Training activity — mirrors the app: a violet ring for whoever is training
   right now, a green ring for anyone who trained today, dimmed for the rest.
   The colour variety and the timestamps are what give it life; no synthetic
   face photos, and the app itself is mostly letter avatars anyway. */

.g-violet { background: linear-gradient(140deg, #a78bfa, #7c3aed); }
.g-amber  { background: linear-gradient(140deg, #fbbf24, #ea580c); }
.g-teal   { background: linear-gradient(140deg, #5eead4, #0d9488); }

@keyframes livePulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* Ring colour is a status, not decoration: violet = training right now,
   green = trained today. It must match this person's row in the strip above. */
.avatar.ring-live {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--primary),
    0 0 12px rgba(139, 92, 246, 0.45);
}

.avatar.ring-recent {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--success);
}

.post-metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: var(--s-4) 0 0;
  border-top: 1px solid var(--separator);
}

.post-metrics > div {
  padding: var(--s-3) 0 var(--s-2);
}

.post-metrics > div + div {
  border-left: 1px solid var(--separator);
  padding-left: var(--s-4);
}

.post-metrics dt {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-4);
}

.post-metrics dd {
  font-size: 19px;
  font-weight: 550;
  letter-spacing: -0.02em;
  margin-top: 3px;
  color: var(--text);
}

.post-metrics dd small {
  font-size: 11px;
  color: var(--text-4);
  margin-left: 2px;
  font-weight: 400;
}

.post-metrics dd.up {
  color: var(--success);
}

.cheer-me {
  margin-left: auto;
  font-size: 12px;
  color: var(--primary-light);
  border: 1px solid rgba(139, 92, 246, 0.3);
  background: var(--primary-muted);
  border-radius: var(--r-full);
  padding: 4px 14px;
}

.post-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-2);
  margin: var(--s-3) 0;
}

.post-stats.four {
  grid-template-columns: repeat(4, 1fr);
}

.post-stats div {
  background: var(--bg);
  border-radius: var(--r-sm);
  padding: var(--s-2);
  text-align: center;
}

.post-stats .k {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-4);
}

.post-stats .v {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 14px;
  font-weight: 500;
  margin-top: 2px;
}

.pr-flag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 550;
  color: var(--gold);
  background: rgba(251, 191, 36, 0.12);
  border: 1px solid rgba(251, 191, 36, 0.28);
  border-radius: var(--r-full);
  padding: 5px 12px;
}

.pr-flag svg {
  width: 13px;
  height: 13px;
  fill: var(--gold);
  stroke: none;
}

/* ==========================================================================
   Volume tiers
   ========================================================================== */

.tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-3);
}

.tier {
  background: var(--surface);
  border: 1px solid var(--separator);
  border-radius: var(--r-lg);
  padding: var(--s-5) var(--s-4);
  text-align: center;
}

/* Geist FIRST, emoji fonts as the fall-through. The other order makes latin
   glyphs resolve in the emoji font, which spaces them out badly. */
.tier .emoji,
.tier .tb,
.pr-flag {
  font-family: "Geist", "Apple Color Emoji", "Segoe UI Emoji",
    "Noto Color Emoji", sans-serif;
}

.tier .emoji {
  font-size: 30px;
  line-height: 1;
  margin-bottom: var(--s-3);
}

.tier .tn {
  font-size: 14px;
  font-weight: 550;
}

.tier .tw {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--text-4);
  margin-top: 3px;
}

.tier .tb {
  font-size: 12px;
  color: var(--primary-light);
  margin-top: var(--s-2);
}

/* ==========================================================================
   Trust band
   ========================================================================== */

/* ==========================================================================
   Community / feature voting
   ========================================================================== */

.build-band {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}

.build-band > * {
  min-width: 0;
}

.build-band h2 {
  font-size: clamp(25px, 3.4vw, 38px);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.026em;
  margin-bottom: var(--s-4);
  text-wrap: balance;
}

.build-band > div > p {
  font-size: clamp(15.5px, 1.7vw, 17.5px);
  color: var(--text-2);
}

.votes {
  list-style: none;
  display: grid;
  gap: var(--s-3);
}

.votes li {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  background: var(--surface);
  border: 1px solid var(--separator);
  border-radius: var(--r-md);
  padding: var(--s-4);
}

/* Vote affordance only — deliberately no counts. Kinetic has no user base yet,
   so a number here would be invented social proof. */
.v-count {
  width: 34px;
  height: 30px;
  display: grid;
  place-items: center;
  font-size: 15px;
  font-weight: 600;
  color: var(--primary-light);
  background: var(--primary-muted);
  border: 1px solid rgba(139, 92, 246, 0.26);
  border-radius: var(--r-sm);
  flex-shrink: 0;
}

.v-count svg {
  width: 14px;
  height: 14px;
  stroke: var(--primary-light);
  stroke-width: 2.5;
  fill: none;
}

.votes-note {
  margin-top: var(--s-3);
  font-size: 12.5px;
  color: var(--text-4);
  text-align: right;
}

.v-label {
  font-size: 15px;
  color: var(--text);
}

.votes li.dim {
  border-style: dashed;
  background: none;
}

.votes li.dim .v-count {
  color: var(--text-3);
  background: none;
  border-color: var(--border);
}

.votes li.dim .v-label {
  color: var(--text-3);
}

/* ==========================================================================
   Final CTA
   ========================================================================== */

.cta {
  position: relative;
  text-align: center;
  overflow: hidden;
}

.cta::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 50% 60% at 50% 55%,
    rgba(139, 92, 246, 0.14) 0%,
    transparent 70%
  );
  pointer-events: none;
}

.cta > .container {
  position: relative;
}

.cta h2 {
  font-size: clamp(30px, 4.6vw, 48px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.03em;
  margin-bottom: var(--s-4);
  text-wrap: balance;
}

.cta p {
  font-size: clamp(16px, 1.9vw, 19px);
  color: var(--text-2);
  margin-bottom: var(--s-7);
  max-width: 34em;
  margin-inline: auto;
}

.cta .store-cta {
  align-items: center;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer {
  border-top: 1px solid var(--separator);
  padding: var(--s-8) 0 var(--s-7);
}

.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: var(--s-7);
  margin-bottom: var(--s-8);
}

.footer-about {
  font-size: 14px;
  color: var(--text-3);
  max-width: 30em;
  margin-top: var(--s-4);
  line-height: 1.6;
}

.footer-col h4 {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-4);
  font-weight: 500;
  margin-bottom: var(--s-4);
}

.footer-col ul {
  list-style: none;
  display: grid;
  gap: var(--s-3);
}

.footer-col a {
  color: var(--text-2);
  font-size: 14.5px;
}

.footer-col a:hover {
  color: var(--text);
  text-decoration: none;
}

.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  padding-top: var(--s-5);
  border-top: 1px solid var(--separator);
  font-size: 13.5px;
  color: var(--text-4);
  flex-wrap: wrap;
}

/* ==========================================================================
   Legal / prose pages
   ========================================================================== */

.prose {
  width: 100%; /* definite, so the flex-column body doesn't shrink-wrap short pages */
  max-width: 780px;
  margin: 0 auto;
  padding: clamp(48px, 7vw, 80px) var(--gutter) clamp(72px, 10vw, 112px);
}

.prose h1 {
  font-size: clamp(30px, 4.6vw, 42px);
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.12;
  margin-bottom: var(--s-2);
}

.prose .updated {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: var(--text-4);
  margin-bottom: var(--s-7);
}

.prose h2 {
  font-size: clamp(20px, 2.6vw, 25px);
  font-weight: 600;
  letter-spacing: -0.018em;
  margin: var(--s-8) 0 var(--s-4);
  scroll-margin-top: calc(var(--nav-h) + 16px);
}

.prose h3 {
  font-size: 17px;
  font-weight: 550;
  margin: var(--s-6) 0 var(--s-3);
  color: var(--text);
}

.prose p,
.prose li {
  color: var(--text-2);
  font-size: 16px;
  line-height: 1.72;
}

.prose p {
  margin-bottom: var(--s-4);
}

.prose ul,
.prose ol {
  margin: 0 0 var(--s-4) var(--s-5);
}

.prose li {
  margin-bottom: var(--s-2);
}

.prose strong {
  color: var(--text);
  font-weight: 550;
}

.prose .card {
  margin: var(--s-5) 0;
}

.prose .card p:last-child {
  margin-bottom: 0;
}

/* Highlighted legal callout */
.prose .callout {
  background: var(--primary-muted);
  border: 1px solid rgba(139, 92, 246, 0.28);
  border-radius: var(--r-md);
  padding: var(--s-5);
  margin: var(--s-5) 0;
}

.prose .callout p:last-child {
  margin-bottom: 0;
}

/* Unfilled legal values must be impossible to miss */
.placeholder {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 0.92em;
  color: #0b0b12;
  background: var(--gold);
  border-radius: 4px;
  padding: 1px 6px;
  font-weight: 600;
  white-space: nowrap;
}

/* Legal tables */
.prose table {
  width: 100%;
  border-collapse: collapse;
  margin: var(--s-5) 0;
  font-size: 14.5px;
}

.prose th,
.prose td {
  text-align: left;
  vertical-align: top;
  padding: var(--s-3);
  border: 1px solid var(--separator);
  color: var(--text-2);
}

.prose th {
  background: var(--surface);
  color: var(--text);
  font-weight: 550;
  font-size: 13px;
}

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* ---------- Support page FAQ ----------
   Native <details>/<summary>: collapses without JavaScript, is keyboard
   operable, and screen readers announce the expanded state for free. */

.faq {
  border-bottom: 1px solid var(--separator);
}

.faq:first-of-type {
  border-top: 1px solid var(--separator);
}

.faq summary {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-5) 0;
  cursor: pointer;
  list-style: none;
  /* comfortably past the 44px touch target */
  min-height: 56px;
  transition: color 180ms var(--ease);
}

/* Hide the platform disclosure triangles */
.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::marker {
  content: "";
}

.faq summary h3 {
  margin: 0;
  flex: 1;
  font-size: 16.5px;
  font-weight: 550;
  line-height: 1.35;
  color: var(--text);
}

.faq summary:hover h3 {
  color: var(--primary-light);
}

.faq-chev {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  stroke: var(--text-3);
  stroke-width: 2;
  fill: none;
  transition: transform 260ms var(--ease), stroke 180ms var(--ease);
}

.faq[open] .faq-chev {
  transform: rotate(180deg);
  stroke: var(--primary-light);
}

.faq summary:hover .faq-chev {
  stroke: var(--primary-light);
}

.faq summary:focus-visible {
  outline: 2px solid var(--primary-light);
  outline-offset: 2px;
  border-radius: 6px;
}

.faq-body {
  padding-bottom: var(--s-5);
}

.faq-body p:last-child {
  margin-bottom: 0;
}

/* Progressive enhancement: browsers that support ::details-content animate the
   open/close. Everywhere else it simply snaps, which is fine. */
@supports selector(details::details-content) {
  .faq::details-content {
    block-size: 0;
    overflow: hidden;
    opacity: 0;
    transition: content-visibility 300ms allow-discrete, opacity 260ms var(--ease),
      block-size 300ms var(--ease);
  }

  .faq[open]::details-content {
    block-size: auto;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .faq-chev {
    transition: none;
  }

  @supports selector(details::details-content) {
    .faq::details-content,
    .faq[open]::details-content {
      transition: none;
    }
  }
}

/* ==========================================================================
   Responsive — 1200 / 992 / 768 / 560 / 380
   ========================================================================== */

@media (max-width: 1200px) {
  :root {
    --gutter: 20px;
  }
}

@media (max-width: 992px) {
  .hero-inner {
    grid-template-columns: 1fr;
    text-align: center;
    gap: var(--s-5);
  }

  /* Stacked, the runner floated loose and read as unanchored — so on phones
     only it gets a deliberate frame. Desktop keeps the plain artwork. */
  .hero-art {
    order: -1;
    max-width: 380px;
    padding: 12% 5%;
    border: 1px solid var(--border);
    border-radius: 30px;
    background: radial-gradient(
        ellipse 76% 66% at 50% 46%,
        rgba(139, 92, 246, 0.15) 0%,
        transparent 72%
      ),
      linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.005));
    box-shadow: 0 34px 80px -34px rgba(139, 92, 246, 0.5),
      inset 0 1px 0 rgba(255, 255, 255, 0.06);
  }

  /* The artwork's bright mass sits right of its geometric centre (the long
     motion trails on the left are faint but wide). The crop is already shifted
     as far right as the source allows, so the last correction happens here —
     nudged left within the frame's padding so the figure reads centred. */
  .hero-art img {
    transform: translateX(-4%);
  }

  .hero-inner {
    padding-top: var(--s-5);
  }

  .hero .sub {
    margin-inline: auto;
  }

  .hero .store-cta {
    align-items: center;
  }

  /* Stacked, the mockup used to come first — the screen arrived before the
     reader knew what section they were in, and the headline sat a full screen
     down. Reorder to claim -> evidence -> detail: eyebrow, headline and intro,
     then the phone, then the bullets. `display: contents` lets the copy's own
     children join the pillar grid so the media can slot between them without
     restructuring the markup. */
  .pillar,
  .pillar.reverse {
    grid-template-columns: 1fr;
    gap: 0;
  }

  .pillar-copy {
    display: contents;
  }

  .pillar-copy > p.eyebrow {
    order: 1;
  }

  .pillar-copy > h2 {
    order: 2;
  }

  .pillar-copy > p:not(.eyebrow):not(.note) {
    order: 3;
  }

  .pillar-copy > .checks {
    order: 5;
  }

  .pillar-copy > p.note {
    order: 6;
  }

  .build-band {
    grid-template-columns: 1fr;
    gap: var(--s-6);
  }

  .pillar .pillar-media,
  .pillar.reverse .pillar-media {
    order: 4;
    margin: var(--s-3) 0 var(--s-7);
  }

  .section-head {
    margin-inline: auto;
    text-align: center;
  }

  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-6);
  }

  .footer-about {
    grid-column: 1 / -1;
  }
}

@media (max-width: 768px) {
  .nav-links {
    display: none;
  }

  /* A vertical list of 11 rungs runs to ~1,050px on a phone. Keep the rail
     horizontal and let it scroll instead: ~150px tall, and you have to swipe
     to reach Immortal — which is rather the point of a ladder. */
  .ladder-rail {
    justify-content: flex-start;
    gap: 0;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 0 var(--s-2) var(--s-2);
    -webkit-mask-image: linear-gradient(90deg, #000 86%, transparent 100%);
    mask-image: linear-gradient(90deg, #000 86%, transparent 100%);
  }

  .ladder-rail::-webkit-scrollbar {
    display: none;
  }

  .ladder-rail::before {
    left: 42px;
    right: 8px;
    top: 38px;
  }

  .rung {
    flex: 0 0 auto;
    width: 84px;
  }

  .rung-badge {
    height: 76px;
  }

  .rung-badge svg {
    width: calc(var(--sz) * 0.74);
    height: calc(var(--sz) * 0.74);
  }

  .rung-badge::before {
    width: calc(var(--sz) * 0.74 + 18px);
    height: calc(var(--sz) * 0.74 + 18px);
  }

  .rung-name {
    font-size: 12.5px;
    margin-top: var(--s-2);
  }

  .rung-lvl {
    font-size: 9.5px;
  }

  .rung-xp {
    display: none;
  }

  .swipe-hint {
    display: block;
  }

  /* The bookend taglines only carry meaning when they sit at the two ends of a
     horizontal rail. Stacked on a phone they lose that and just add words. */
  .ladder-ends {
    display: none;
  }

  .nav-toggle {
    display: flex;
  }

  .nav-sheet {
    display: flex;
  }

  .proof-grid {
    grid-template-columns: repeat(2, 1fr);
  }

}

@media (max-width: 560px) {
  :root {
    --gutter: 18px;
  }

  /* The explanation stays ON — bare 3-5 word labels assert a feature without
     ever saying what it does. But the FULL desktop sentence is too much on a
     phone, so each detail carries its own droppable tail in .det-more: what
     remains is a true prefix of the same sentence, chosen to still land on
     its own. One copy of the text, two lengths. */
  .checks .det {
    display: inline;
    font-size: 14.5px;
  }

  /* Droppable tails, wherever they appear. */
  .checks .det-more,
  .more {
    display: none;
  }

  .checks li {
    font-size: 15.5px;
    line-height: 1.5;
    align-items: flex-start;
  }

  /* The tick sits on the first line, not the middle of a wrapped block. */
  .checks .tick {
    margin-top: 2px;
  }

  .checks li strong {
    font-weight: 500;
    color: var(--text);
  }

  .checks {
    gap: var(--s-4);
  }

  /* Four stacked reassurance cards with body copy is a lot of scroll. The
     headings are the message; the detail lives in the Privacy Policy. */

  /* Stacked, the head-to-head card was invisible until you'd scrolled past a
     full feed card. As a snap carousel both are reachable in one gesture, and
     the peeking edge of the next card is what tells you it's there. */
  .social-grid {
    display: flex;
    grid-template-columns: none;
    gap: var(--s-3);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    /* Bleed to the screen edges so the peek reaches the very edge. */
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    scroll-padding-inline: var(--gutter);
  }

  .social-grid::-webkit-scrollbar {
    display: none;
  }

  .social-grid > .card,
  .social-grid > .phone {
    flex: 0 0 88%;
    scroll-snap-align: start;
    /* Without this the shorter card is stretched to match the taller one,
       leaving ~150px of dead space under the feed. Each card takes its own
       natural height instead. */
    align-self: flex-start;
  }

  /* Both cards were 792px against ~780px of usable viewport, so neither could
     ever be seen in one frame. The savings below come out of layout, not
     content — nothing is removed and nothing is tightened to the point of
     feeling cramped. */

  /* The gap figure had a line to itself above the bar. Lift it onto the values
     row it belongs to — same information, one row instead of two, ~24px saved
     on each of three duels. CSS-only, so the desktop layout is unchanged. */

  .vs-score {
    margin-bottom: var(--s-4);
  }

  .social-hint {
    display: flex;
  }

  .post-metrics dd {
    font-size: 17px;
  }

  /* Everything — framed art, headline, sub, badge and pill — has to share one
     844px screen, so the art carries the compromise and the spacing stays
     generous. Shrinking the art is what buys the breathing room. */
  .hero-art {
    max-width: 320px;
    border-radius: 26px;
  }

  .hero h1 {
    font-size: clamp(32px, 8.6vw, 42px);
    margin-bottom: var(--s-5);
  }

  .hero .sub {
    font-size: 16.5px;
    line-height: 1.5;
    margin-bottom: var(--s-6);
  }

  .hero-inner {
    padding: var(--s-5) 0 var(--s-7);
    gap: var(--s-6);
  }

  .store-cta {
    gap: var(--s-4);
  }

  .section-head p,
  .pillar-copy > p:not(.eyebrow):not(.note) {
    font-size: 16px;
  }

  .tiers {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-grid {
    grid-template-columns: 1fr;
  }

  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-3);
  }

  .prose table {
    font-size: 13.5px;
  }

  .phone {
    width: 280px;
  }
}

@media (max-width: 380px) {
  :root {
    --gutter: 16px;
  }

  .proof-item {
    padding: var(--s-5) var(--s-2);
  }

  .tiers {
    grid-template-columns: 1fr;
  }

  .rung-xp {
    display: none;
  }

  .phone {
    width: 262px;
  }

  .store-badge img {
    height: 48px;
  }

  .tf-btn {
    height: 48px;
    font-size: 15px;
  }

  .tf-note {
    text-align: center;
  }
}

/* ==========================================================================
   Start — the import beam
   The plane is skewed by an isometric matrix so the dashed rails read as
   diagonals and the tiles sit on a receding surface. Everything inside the
   <g> shares one transform, so geometry stays authored square.
   ========================================================================== */

.beam-card {
  max-width: 960px;
  margin: 0 auto;
  background: #08080D;
  border: 1px solid var(--border);
  border-radius: 28px;
  overflow: hidden;
}

.beam-copy {
  max-width: 560px;
  padding: clamp(26px, 4vw, 38px) clamp(22px, 4vw, 38px) 0;
  margin: 0;
  font-size: clamp(15.5px, 1.5vw, 17px);
  line-height: 1.5;
  font-weight: 500;
  color: var(--text-3);
}

.beam-copy strong {
  color: var(--text);
  font-weight: 600;
}

.beam-stage {
  padding: clamp(18px, 3vw, 30px) clamp(10px, 2vw, 22px) clamp(14px, 2.5vw, 26px);
}

.beam-svg {
  width: 100%;
  height: auto;
  display: block;
}

/* Two compositions, not one scaled down: the wide isometric plane would put
   the tiles at ~45px on a phone. The tall one flows top-to-bottom instead. */
.beam-m { display: none; }

@media (max-width: 720px) {
  .beam-w { display: none; }
  .beam-m { display: block; }
}

/* One short dash travelling each wire — the four sources land, then the
   result leaves. Calm and linear; no springs. */
.beam-pulse {
  stroke-dasharray: 34 760;
  stroke-dashoffset: 794;
  stroke-linecap: round;
  animation: beam-travel 4.4s linear infinite;
}

.beam-pulse.b1 { animation-delay: 0s; }
.beam-pulse.b2 { animation-delay: 0.4s; }
.beam-pulse.b3 { animation-delay: 0.8s; }
.beam-pulse.b4 { animation-delay: 1.2s; }
.beam-pulse.b5 { animation-delay: 1.9s; animation-duration: 3.4s; }

@keyframes beam-travel {
  to { stroke-dashoffset: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .beam-pulse {
    animation: none;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    opacity: 0.35;
  }
}

/* ==========================================================================
   Wire diagram tiles
   ========================================================================== */

/* A 1px highlight along the top inner edge — the card grammar's lit edge.
   No glow, no drop-shadow: this palette turns both to mud. */

/* ==========================================================================
   Compete — the feed and the head-to-head, two phones side by side
   ========================================================================== */

/* Two 1fr columns each ~590px wide put a 300px phone in the middle of its
   own half, leaving a canyon between them. Size the tracks to the phones and
   centre the pair instead. */
.social-grid {
  grid-template-columns: repeat(2, max-content);
  justify-content: center;
  align-items: start;
  gap: clamp(18px, 2.6vw, 34px);
}

.social-hint { margin-top: var(--s-5); }

@media (max-width: 860px) {
  .social-grid {
    grid-template-columns: max-content;
  }
}

/* ==========================================================================
   Compete — overflow and carousel corrections
   ========================================================================== */

@media (max-width: 560px) {
  /* A phone has a fixed width and an aspect ratio; stretching it to 88% of the
     viewport would change its height too. Snap each one centred at its own
     size instead. */
  /* start, not center: centring leaves half of each phone showing on both
     sides. Snapping to the gutter shows one whole phone with the next
     peeking in — which is what tells you there is a second one. */
  .social-grid > .phone {
    flex: 0 0 auto;
    scroll-snap-align: start;
  }

  /* The desktop rule that pulls the two phones together sets
     justify-content: center. On a horizontally SCROLLING flex container that
     centres the overflow instead of the content: the first item's start
     becomes unreachable and the rail rests between the two phones, which is
     why neither was ever fully visible. Carousel mode must start at the edge. */
  .social-grid {
    justify-content: flex-start;
  }
}

/* ==========================================================================
   Start — the two remaining paths, anchored
   Below the beam card these were two unanchored blocks of prose. Each now
   opens with the same tile the diagram uses — gradient fill, hairline, lit
   top edge — so the three ways in read as one family.
   ========================================================================== */

/* The coach tile carries the hub's violet, tying it to the diagram's centre. */

/* ==========================================================================
   Start — icon beside its label on mobile, not above it
   ========================================================================== */

/* .way-k is itself a <p>, so a bare `.way p` rule (0,1,1) outranks `.way-k`
   (0,1,0) and drops the eyebrow into the copy cell — the two then render on
   top of each other. Both selectors have to name the element. */

/* ==========================================================================
   Log — one short band
   Logging speed is a hygiene claim. As a full section with a centred head it
   spent ~400px of header on ~200px of content; as five stacked rows on a
   phone it was taller still. Headline left, features as wrapped chips right,
   no supporting sentences — the labels are the information.
   ========================================================================== */

.section.band {
  padding-block: clamp(44px, 5.5vw, 76px);
}

.band-inner {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  align-items: center;
  gap: clamp(28px, 5vw, 72px);
}

.band-copy h2 {
  font-size: clamp(24px, 2.7vw, 33px);
  line-height: 1.12;
  letter-spacing: -0.025em;
  font-weight: 600;
  margin-bottom: var(--s-3);
  text-wrap: balance;
}

.band-copy p {
  color: var(--text-2);
  font-size: 15.5px;
  line-height: 1.6;
  max-width: 42ch;
}

@media (max-width: 860px) {
  .band-inner {
    grid-template-columns: 1fr;
    gap: var(--s-5);
  }
}

/* ==========================================================================
   Account pages (/verify-email, /reset-password)
   The only forms on the site. Inputs are 16px so iOS Safari doesn't zoom on
   focus. Everything else (headings, buttons, cards, the store CTA) comes
   from the rules above.
   ========================================================================== */

[hidden] {
  display: none !important;
}

.account-state .eyebrow {
  margin-top: 0;
}

/* The script moves focus to the heading when a state appears so screen
   readers announce it; the heading is not interactive, so no focus ring. */
.account-state h1:focus,
.account-state h1:focus-visible {
  outline: none;
}

.account-form {
  max-width: 440px;
  margin-top: var(--s-6);
}

.field {
  margin-bottom: var(--s-5);
}

.field-input {
  position: relative;
}

/* Room for the eye button inside the password field. */
.field-input input {
  padding-right: 48px;
}

.field label {
  display: block;
  font-size: 14px;
  font-weight: 550;
  color: var(--text);
  margin-bottom: var(--s-2);
}

.field input {
  width: 100%;
  height: 48px;
  padding: 0 var(--s-4);
  font: inherit;
  font-size: 16px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  -webkit-appearance: none;
  appearance: none;
  transition: border-color 160ms var(--ease), box-shadow 160ms var(--ease);
}

.field input::placeholder {
  color: var(--text-4);
}

.field input:focus {
  outline: none;
  border-color: var(--primary-light);
  box-shadow: 0 0 0 3px var(--primary-muted);
}

.field input[aria-invalid="true"] {
  border-color: var(--error);
}

/* Chrome paints a light background on autofilled inputs; keep the dark surface. */
.field input:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--surface) inset;
  -webkit-text-fill-color: var(--text);
  caret-color: var(--text);
}

.pw-toggle {
  position: absolute;
  top: 0;
  right: 0;
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-3);
  border-radius: var(--r-md);
}

.pw-toggle:hover {
  color: var(--text);
}

.pw-toggle svg {
  width: 20px;
  height: 20px;
}

/* Eye when hidden, crossed eye when the password is showing. */
.pw-toggle .pw-eye-off,
.pw-toggle[aria-pressed="true"] .pw-eye {
  display: none;
}

.pw-toggle[aria-pressed="true"] .pw-eye-off {
  display: inline;
}

.form-msg {
  font-size: 14.5px;
  line-height: 1.5;
  padding: var(--s-3) var(--s-4);
  border: 1px solid;
  border-radius: var(--r-md);
  margin: 0 0 var(--s-4);
}

.form-msg.is-error {
  color: var(--error);
  background: rgba(239, 68, 68, 0.1);
  border-color: rgba(239, 68, 68, 0.3);
}

.form-msg.is-success {
  color: var(--success);
  background: rgba(34, 197, 94, 0.1);
  border-color: rgba(34, 197, 94, 0.3);
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3);
  margin-top: var(--s-4);
}

button.tf-btn {
  border: 0;
}

.tf-btn[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Secondary action inside an account state (e.g. "Didn't get it? Resend"):
   outlined, no glow, so the primary CTA above it stays the loud one. */
.tf-btn.tf-btn-quiet,
.tf-btn.tf-btn-quiet[disabled]:hover {
  background: transparent;
  color: var(--text-2);
  border: 1px solid var(--border-strong);
  box-shadow: none;
}

.tf-btn.tf-btn-quiet:hover {
  background: var(--surface-2);
  color: var(--text);
  transform: none;
}

.tf-btn[disabled]:hover {
  background: var(--primary);
  transform: none;
  box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .field input {
    transition: none;
  }
}

/* ==========================================================================
   Start — three ways into a program
   The import beam is the showpiece; the other two paths sit under it in the
   same material, so all three read as one set. Deliberately NO hairlines
   here: a rule in --separator is this site's "new section" signal, and using
   it between siblings inside a section reads as a false boundary.
   ========================================================================== */

/* The hero is .hero, not .section, so `.section + .section` never fires on
   the first section — it had no top edge at all once its head was removed. */
.hero + .section {
  border-top: 1px solid var(--separator);
}

.ways {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(14px, 1.8vw, 22px);
  max-width: 960px;
  margin: clamp(16px, 2vw, 24px) auto 0;
}

.ways > * {
  min-width: 0;
}

.way {
  background: #08080D;
  border: 1px solid var(--border);
  border-radius: 22px;
  padding: clamp(22px, 2.6vw, 30px);
}

.way-top {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: var(--s-4);
}

.way-ico {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background: linear-gradient(180deg, #24232E 0%, #0C0C11 100%);
  border: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07);
  color: var(--text-2);
  flex-shrink: 0;
}

/* The coach tile carries the hub's violet, tying it to the diagram above. */
.way-ico.coach {
  background: linear-gradient(180deg, #38306A 0%, #171331 100%);
  border-color: rgba(167, 139, 250, 0.45);
  box-shadow: inset 0 1px 0 rgba(167, 139, 250, 0.28);
  color: #C4B5FD;
}

.way-ico svg {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.way h3 {
  font-size: clamp(17px, 1.7vw, 19px);
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.25;
  margin: 0;
}

.way p {
  color: var(--text-2);
  font-size: 15px;
  line-height: 1.62;
  margin: 0;
}

@media (max-width: 760px) {
  .ways {
    grid-template-columns: 1fr;
  }

  .way {
    border-radius: 20px;
  }

  .way-top {
    gap: 12px;
    margin-bottom: var(--s-3);
  }

  .way-ico {
    width: 42px;
    height: 42px;
    border-radius: 13px;
  }
}

/* ==========================================================================
   Built in the open — the request board
   Mirrors the real in-app object (Canny-style: submit, vote ±1, moderator
   status). Deliberately NO vote counts anywhere: Kinetic has no user base
   yet and inventing numbers is the one thing this page must never do. The
   affordance carries the idea; the status chip carries the proof.
   ========================================================================== */

.board {
  max-width: 720px;
  margin: var(--s-7) auto 0;
  background: #08080D;
  border: 1px solid var(--border);
  border-radius: 20px;
  overflow: hidden;
}

.req-list {
  list-style: none;
}

/* Two columns of one-line rows. Six rows carrying a title AND a sentence
   ran the section past a screen on both desktop and mobile; the titles say
   enough on their own. */
.req-list {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 0;
}

.req {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
  border-top: 1px solid var(--separator);
  min-width: 0;
}

/* The first row of each column opens the card, so it takes no rule. */
.req:nth-child(1),
.req:nth-child(2) {
  border-top: 0;
}

/* A hairline between the columns, not around every cell. */
.req:nth-child(odd) {
  border-right: 1px solid var(--separator);
}

.req-vote {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: rgba(139, 92, 246, 0.12);
  border: 1px solid rgba(139, 92, 246, 0.28);
}

.req-vote svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--primary-light);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.req-done .req-vote {
  background: rgba(34, 197, 94, 0.10);
  border-color: rgba(34, 197, 94, 0.26);
}

.req-done .req-vote svg {
  stroke: var(--success);
}

.req-text {
  min-width: 0;
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.req-chip {
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--r-full);
  white-space: nowrap;
}

.req-open {
  color: var(--text-3);
  border: 1px solid var(--border);
}

.req-review {
  color: var(--primary-light);
  border: 1px solid rgba(139, 92, 246, 0.35);
  background: rgba(139, 92, 246, 0.09);
}

.req-shipped {
  color: var(--success);
  border: 1px solid rgba(34, 197, 94, 0.32);
  background: rgba(34, 197, 94, 0.08);
}

.board-add {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 18px;
  border-top: 1px dashed rgba(139, 92, 246, 0.35);
  font-size: 15px;
  font-weight: 500;
  color: var(--primary-light);
  transition: background 180ms var(--ease);
}

.board-add:hover {
  background: rgba(139, 92, 246, 0.06);
  text-decoration: none;
}

.board-plus {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  border: 1px dashed rgba(139, 92, 246, 0.45);
  font-size: 19px;
  line-height: 1;
}

.votes-note {
  max-width: 720px;
  margin: var(--s-4) auto 0;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-4);
}

@media (max-width: 760px) {
  /* One column: two columns of truncated titles is worse than a taller list. */
  .req-list {
    grid-template-columns: 1fr;
  }

  .req:nth-child(odd) {
    border-right: 0;
  }

  .req:nth-child(2) {
    border-top: 1px solid var(--separator);
  }

  .req,
  .board-add {
    padding: 12px 14px;
  }

  .req-text {
    font-size: 14px;
  }
}

/* ==========================================================================
   The deal — a plain-English terms sheet, not four icon cards
   These are four flat statements about what Kinetic does NOT do. Boxes with
   an icon on top is the shape every generated landing page reaches for, and
   it made the claims feel like decoration. Numbered clauses on hairlines
   read like terms — which is what the eyebrow already calls them — and the
   sentences stay visible on a phone, because "No ads, no trackers" alone is
   an assertion while the sentence under it is checkable.
   ========================================================================== */

.deal-inner {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(32px, 6vw, 88px);
  align-items: start;
}

.deal-lede h2 {
  font-size: clamp(26px, 3.4vw, 38px);
  line-height: 1.1;
  letter-spacing: -0.028em;
  font-weight: 600;
  margin-bottom: var(--s-4);
  text-wrap: balance;
}

.deal-lede > p {
  color: var(--text-2);
  font-size: 16px;
  line-height: 1.6;
  max-width: 34ch;
}

.deal-list {
  list-style: none;
  counter-reset: deal;
}

.deal-list > li {
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 18px;
  padding: 20px 0;
  border-top: 1px solid var(--separator);
}

.deal-list > li:first-child {
  border-top: 0;
  padding-top: 0;
}

.deal-list > li:last-child {
  padding-bottom: 0;
}

.deal-n {
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--text-4);
  padding-top: 3px;
}

.deal-body b {
  display: block;
  font-size: 16.5px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--text);
  margin-bottom: 5px;
}

.deal-body p {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-2);
  max-width: 52ch;
}

.deal-body a {
  color: var(--primary-light);
}

@media (max-width: 900px) {
  .deal-inner {
    grid-template-columns: 1fr;
    gap: var(--s-6);
  }

  .deal-lede > p {
    max-width: 46ch;
  }
}

@media (max-width: 560px) {
  .deal-list > li {
    grid-template-columns: 26px 1fr;
    gap: 12px;
    padding: 16px 0;
  }

  .deal-body b {
    font-size: 15.5px;
  }

  .deal-body p {
    font-size: 14px;
  }
}

/* ==========================================================================
   Real screenshots — the pillar and compete phones show App Store captures
   (assets/shots, built by scripts/build-shots.mjs). The image sets the
   phone's height, so the frame never letterboxes or crops. The captures have
   their own status bar painted out; .shot-bar draws the clean 9:41 one.
   ========================================================================== */

.phone.has-shot {
  aspect-ratio: auto;
}

.has-shot .phone-screen {
  display: block;
  height: auto;
  background: #000;
}

.shot {
  display: block;
  width: 100%;
  height: auto;
}

.shot-bar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 4;
}

/* ---- Jimmy peeking over the coach phone ----
   Artwork is the app's own (kinetic-mobile shared/ui/jimmy/jimmyArtwork.ts),
   inlined. He sits behind the phone so its top edge hides his lower half. */
.jimmy-stage {
  position: relative;
  display: inline-block;
  padding-top: 70px;
}

.jimmy-stage .phone {
  z-index: 1;
}

.jimmy-peek {
  position: absolute;
  top: 0;
  right: 34px;
  width: 132px;
  z-index: 0;
  overflow: visible;
}

.jimmy-peek .j-shadow {
  display: none;
}

.jimmy g {
  transform-box: view-box;
}

.jimmy .j-float {
  animation: j-float 4.2s ease-in-out infinite;
}

.jimmy .j-eyes {
  transform-origin: 180px 178px;
  animation: j-blink 5.6s infinite;
}

@keyframes j-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-12px); }
}

@keyframes j-blink {
  0%, 92%, 100% { transform: scaleY(1); }
  95% { transform: scaleY(0.1); }
}

@media (prefers-reduced-motion: reduce) {
  .jimmy .j-float,
  .jimmy .j-eyes {
    animation: none;
  }
}

@media (max-width: 380px) {
  .jimmy-stage {
    padding-top: 60px;
  }

  .jimmy-peek {
    width: 112px;
    right: 26px;
  }
}
