/* LOOP stylesheet. Built from src/styles/tokens.css + src/styles/app.css. */

/* ============================================================
   LOOP: BRAND TOKENS
   ------------------------------------------------------------
   ⟵ THIS IS THE BRANDING SWAP POINT.

   Colours, typography and rhythm for the whole site. Change a
   value here and every section follows automatically.

   The logo mark itself lives in:
       src/components/ui/Logo.jsx
   ============================================================ */

:root {
  /* ---------- Brand colours ----------
     Sampled off the official mark: bright magenta at the top of the
     bubble, deep violet in the foot.

     --brand is the one that carries text and UI. It sits at 6.9:1
     on white, so it is safe for links and small labels, not just
     for large type. --brand-2 and --brand-3 are the ends of the
     mark's gradient and are decorative, except --brand-3, which is
     also used for text and clears 11.5:1 on white. */
  --brand:   #8A11CC;   /* primary   (buttons, links, icons) */
  --brand-2: #C918FF;   /* highlight (top of the logo gradient) */
  --brand-3: #560590;   /* depth     (the mark's foot, flat) */

  /* The logo gradient, reused for the few places that should feel
     like the mark itself (the in-keyboard AI button, the favicon). */
  --brand-grad: linear-gradient(150deg,
    var(--brand-2) 0%, var(--brand) 48%, var(--brand-3) 100%);

  /* Washes: the brand at very low strength, for tinted panels.
     --brand-tint fills the "With LOOP" card and the closing band;
     --brand-line is the hairline those panels are drawn with. */
  --brand-tint:   #F7EEFD;
  --brand-tint-2: #EFDFFB;
  --brand-line:   rgba(138, 17, 204, 0.18);
  --brand-soft:   rgba(138, 17, 204, 0.07);

  /* Card tints for the three "conversations that matter" cards.
     Kept desaturated so they read as paper, not as UI states. */
  --tint-blue:   #EEF3FF;
  --tint-violet: #F3EFFE;
  --tint-pink:   #FDEEF4;

  /* ---------- Surfaces ----------
     Two greys only. White is the page; #F5F5F7 separates one band
     from the next and fills cards. Sections are told apart by tone
     rather than by borders, which is what keeps the page quiet. */
  --bg:         #FFFFFF;
  --bg-soft:    #F5F5F7;
  --surface:    #F5F5F7;
  --surface-2:  #EBEBEF;
  --hairline:   rgba(0, 0, 0, 0.08);
  --hairline-2: rgba(0, 0, 0, 0.14);

  /* Dark band (the privacy section and the nav's store button). */
  --dark:      #0B0B0C;
  --dark-2:    #17171A;
  --dark-line: rgba(255, 255, 255, 0.10);
  --dark-ink:  rgba(255, 255, 255, 0.62);

  /* ---------- Text ----------
     Four steps, all of which clear WCAG AA (4.5:1) on both white
     and #F5F5F7, so nothing on the page is hard to read. */
  --ink:   #1D1D1F;
  --ink-2: #424245;
  --ink-3: #5B5B60;
  --ink-4: #6E6E73;

  /* ---------- Shadows ----------
     Used sparingly: a white card on a grey band, and the hardware
     mockups. Everything else separates by tone alone. */
  --lift:   0 1px 2px rgba(0, 0, 0, 0.04), 0 10px 30px -16px rgba(0, 0, 0, 0.14);
  --lift-2: 0 1px 3px rgba(0, 0, 0, 0.05), 0 22px 50px -22px rgba(0, 0, 0, 0.18);
  --lift-3: 0 2px 6px rgba(0, 0, 0, 0.06), 0 40px 80px -30px rgba(0, 0, 0, 0.24);

  /* ---------- Typeface ----------
     Uses the system UI font so it renders as SF Pro on Apple
     devices and Segoe UI on Windows. Fast, with no webfont request.
     Swap in the brand typeface here if one is supplied. */
  --font: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text',
          'Segoe UI Variable', 'Segoe UI', Inter, system-ui, Roboto, sans-serif;

  /* ---------- Layout rhythm ----------
     Narrower container and tighter vertical rhythm than the previous
     build: the design centres short headings over wide cards, which
     needs less width and more air above each band than below it. */
  --container: 1080px;
  --gutter: clamp(20px, 5vw, 40px);
  --section-y: clamp(64px, 8vw, 104px);

  /* ---------- Radii ----------
     The design leans on large, evenly-rounded rectangles. */
  --r-xs: 10px;
  --r-sm: 14px;
  --r: 18px;
  --r-lg: 24px;
  --r-xl: 30px;
  --r-2xl: 36px;
  --r-pill: 999px;

  /* ---------- Motion ---------- */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}


/* ============================================================
   LOOP: Component styles
   Brand tokens live in tokens.css (the branding swap point).

   Design notes for whoever picks this up next:

   • The page is white. Sections are told apart by tone, not by
     borders: a white band, then a #F5F5F7 band, and so on. Add
     `section--alt` to a <section> to put it on grey.
   • Cards follow the band they sit in. Each section sets
     --card-bg and --card-shadow, so a card is grey on a white
     band and white (with a whisper of a shadow) on a grey one.
     Card rules just read the variables; nothing needs to know
     where it is on the page.
   • Colour is used sparingly, and almost always as one accent on
     an otherwise neutral surface. The full brand gradient is
     reserved for the logo and the in-keyboard AI button.
   • Headings are short and centred over wide, softly-rounded
     cards. Where a section needs emphasis it gets a tint, not a
     border.
   ============================================================ */

/* ---------- Reset / base ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* the hero's soft wash is intentionally wider than the screen; clip it
     here too so it can never widen the layout viewport on phones */
  overflow-x: hidden;
  /* the header is fixed, so anchored sections need somewhere to land */
  scroll-padding-top: 84px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.6;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, video, svg { display: block; max-width: 100%; }
/* `hidden` has to beat the display rules further down: the inactive
   feature panels are hidden with the attribute, and .sp__panel sets
   display:grid, which would otherwise override it. */
[hidden] { display: none !important; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: 6px;
}

::selection { background: var(--brand-tint-2); color: var(--ink); }

/* body scroll lock, applied while the mobile menu is open */
body.is-locked { overflow: hidden; }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  background: var(--brand);
  color: #fff;
  padding: 12px 18px;
  border-radius: 0 0 10px 0;
  font-weight: 600;
}
.skip:focus { left: 0; }

/* ---------- Layout primitives ---------- */
.wrap {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* ------------------------------------------------------------
   Band variables.

   Each band publishes how the things inside it should look, so no
   card rule ever has to know which band it landed in:

     --card-bg      fill for a card sitting in this band
     --card-shadow  its resting shadow
     --inset        fill for a panel nested *inside* such a card

   Note the inversion: on a white band, cards are grey and the
   panels inside them go back to white. On a grey band, cards are
   white and their inner panels are grey. Two greys, alternating
   by depth, is the whole system.

   The shadows default to `0 0 #0000` rather than `none` so rules
   can append a ring: `none` is not a legal member of a
   comma-separated shadow list, but a transparent shadow is.
   ------------------------------------------------------------ */
:root {
  --card-bg: var(--bg-soft);
  --card-bg-hover: var(--surface-2);
  --card-shadow: 0 0 #0000;
  --card-shadow-hover: 0 0 #0000;
  --inset: #fff;
}

.section {
  padding-block: var(--section-y);
  position: relative;
}
.section--tight { padding-block: clamp(48px, 6vw, 76px); }

.section--alt {
  background: var(--bg-soft);
  --card-bg: #fff;
  --card-bg-hover: #fff;
  --card-shadow: var(--lift);
  --card-shadow-hover: var(--lift-2);
  --inset: var(--bg-soft);
}

/* ---------- Type scale ----------
   Weights sit around 600. Heavier than that starts to look like a
   headline set in a UI font, which is exactly what it is. */
.display {
  font-size: clamp(2.5rem, 5.4vw, 3.9rem);
  line-height: 1.06;
  letter-spacing: -0.035em;
  font-weight: 640;
}

.h2 {
  font-size: clamp(1.7rem, 3.2vw, 2.35rem);
  line-height: 1.14;
  letter-spacing: -0.028em;
  font-weight: 640;
}

.h3 {
  font-size: clamp(1.22rem, 2vw, 1.45rem);
  line-height: 1.28;
  letter-spacing: -0.02em;
  font-weight: 600;
}

.lede {
  font-size: clamp(1rem, 1.35vw, 1.1rem);
  line-height: 1.55;
  color: var(--ink-4);
  letter-spacing: -0.012em;
}

.small { font-size: 0.875rem; color: var(--ink-4); }

/* The accent word in a headline. Solid brand, not a gradient: the
   gradient belongs to the logo, and one flat accent colour on a white
   page reads considerably calmer. Class name kept so the components
   don't need to change. */
.grad-text { color: var(--brand); }

.eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 14px;
}

.sec-head { max-width: 640px; }
.sec-head--center { margin-inline: auto; text-align: center; }
.sec-head .lede { margin-top: 12px; }

/* ---------- Buttons ---------- */
.btn {
  --h: 52px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: var(--h);
  padding: 0 24px;
  border-radius: var(--r-pill);
  font-weight: 560;
  letter-spacing: -0.012em;
  white-space: nowrap;
  transition: background 0.22s var(--ease), color 0.22s var(--ease),
              transform 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.btn:active { transform: scale(0.985); }

/* The primary: a black pill, as on the design. */
.btn--dark {
  background: var(--dark);
  color: #fff;
  padding: 0 26px 0 22px;
}
.btn--dark:hover { background: #000; box-shadow: 0 10px 24px -12px rgba(0, 0, 0, 0.55); }
.btn--dark .btn__ico { width: 17px; height: 20px; flex: none; margin-top: -2px; }
.btn--dark .btn__arrow { width: 15px; height: 15px; flex: none; opacity: 0.55; margin-left: 2px; }
.btn__one { font-size: 0.95rem; }

/* Two-line "Download on the / App Store" lockup. */
.btn--dark .btn__txt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.05;
}
.btn--dark .btn__txt small { font-size: 0.66rem; opacity: 0.72; letter-spacing: 0; }
.btn--dark .btn__txt strong { font-size: 1.05rem; font-weight: 560; letter-spacing: -0.02em; }

/* Outlined, for the secondary card and the dark band. */
.btn--outline {
  background: transparent;
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--hairline-2);
}
.btn--outline:hover { background: rgba(0, 0, 0, 0.045); }
.btn--outline .btn__ico { width: 15px; height: 18px; flex: none; margin-top: -2px; }

/* On the dark privacy band the outline has to invert. */
.priv .btn--outline {
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.28);
}
.priv .btn--outline:hover { background: rgba(255, 255, 255, 0.1); }

.btn--brand { background: var(--brand); color: #fff; }
.btn--brand:hover { background: #7A0FB5; }

.btn--ghost { background: rgba(0, 0, 0, 0.05); color: var(--ink); }
.btn--ghost:hover { background: rgba(0, 0, 0, 0.085); }

.btn--sm { --h: 42px; font-size: 0.9rem; padding: 0 18px; }
.btn--sm.btn--dark { padding: 0 16px 0 14px; }
.btn--sm .btn__one { font-size: 0.86rem; }
.btn--block { width: 100%; }

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}
.cta-row--center { justify-content: center; }

.cta-note {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  font-size: 0.85rem;
  color: var(--ink-4);
}
.cta-note svg { width: 15px; height: 15px; flex: none; }
.cta-note--center { justify-content: center; }

/* ---------- Logo ---------- */
.logo { display: inline-flex; align-items: center; flex: none; color: var(--ink); }
/* The lockup is one SVG with the brand's own mark-to-wordmark
   spacing baked in, so height is the only size to set. 34px is what
   the mark needs before the fold in the bubble reads as a fold
   rather than as a nick out of the shape; the wordmark follows it
   and takes the colour set above. */
.logo__lockup {
  display: block;
  height: 34px;
  width: auto;
}
/* The icon on its own, wherever a size isn't given by the caller. */
.logo__mark {
  width: 24px;
  height: auto;
  aspect-ratio: 1168 / 1622;
}

/* ============================================================
   HEADER
   ============================================================ */
.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  /* The hairline under the bar is always there, so the header reads as
     its own strip instead of floating over the top of the hero. It is a
     shadow rather than a border because a shadow costs no layout height,
     which keeps `scroll-padding-top: 84px` exact. */
  box-shadow: 0 1px 0 var(--hairline);
  transition: background 0.3s var(--ease), box-shadow 0.3s var(--ease),
              backdrop-filter 0.3s var(--ease);
}
/* Once the page moves, the bar earns a surface as well as the line, so
   whatever scrolls underneath stays legible behind it. */
.nav.is-stuck {
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(180%) blur(18px);
  box-shadow: 0 1px 0 var(--hairline-2);
}

.nav__inner {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding: 14px var(--gutter);
  display: flex;
  align-items: center;
  gap: 20px;
}

/* Links are centred in the bar, independent of how wide the mark and
   the button happen to be, which is what the design shows. */
.nav__links {
  position: absolute;
  left: 50%;
  translate: -50% 0;
  display: flex;
  gap: 4px;
}
.nav__links a {
  padding: 8px 14px;
  border-radius: var(--r-pill);
  font-size: 0.92rem;
  color: var(--ink-3);
  transition: color 0.2s, background 0.2s;
}
.nav__links a:hover { color: var(--ink); background: rgba(0, 0, 0, 0.045); }

.nav__cta { flex: none; margin-left: auto; }

.nav__burger {
  display: none;
  margin-left: auto;
  padding: 10px;
  border-radius: 10px;
}
.nav__burger span {
  display: block;
  width: 20px;
  height: 1.8px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform 0.3s var(--ease), opacity 0.2s;
}
.nav__burger span + span { margin-top: 4.5px; }
.nav.is-open .nav__burger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav.is-open .nav__burger span:nth-child(2) { opacity: 0; }
.nav.is-open .nav__burger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.nav__sheet {
  background: rgba(255, 255, 255, 0.97);
  backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--hairline);
  padding: 14px var(--gutter) 26px;
  max-height: calc(100dvh - 68px);
  overflow-y: auto;
}
.nav__sheet a {
  display: block;
  padding: 13px 2px;
  font-size: 1.05rem;
  font-weight: 520;
  border-bottom: 1px solid var(--hairline);
}
.nav__sheet .btn { margin-top: 20px; width: 100%; }

@media (max-width: 900px) {
  .nav__links, .nav__cta { display: none; }
  .nav__burger { display: block; }
}

/* ============================================================
   HERO
   ============================================================ */
.hero {
  position: relative;
  padding-top: clamp(92px, 10vw, 124px);
  padding-bottom: clamp(36px, 5vw, 60px);
  overflow: hidden;
}
.hero__glow {
  position: absolute;
  z-index: -1;
  top: -22%;
  right: -10%;
  width: min(900px, 90vw);
  aspect-ratio: 1;
  pointer-events: none;
  background: radial-gradient(circle, var(--brand-tint) 0%, transparent 62%);
}

.hero__grid {
  display: grid;
  gap: clamp(36px, 5vw, 56px);
  align-items: center;
}
@media (min-width: 900px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr); }
}

.hero__text .lede { margin-top: 20px; max-width: 40ch; }
.hero__text .cta-row { margin-top: 30px; }

.hero__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin-top: 26px;
}
.hero__chips li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.83rem;
  color: var(--ink-4);
}
.hero__chips svg { width: 15px; height: 15px; flex: none; color: var(--ink-3); }

/* The hero handset's width lives HERE rather than on the .device itself,
   because the pointer note is a sibling of the phone and needs to read it
   to sit a constant distance from the phone's right edge. Custom
   properties only inherit downwards, so declaring it on the shared parent
   is what lets both of them use it. The size tiers further down override
   this one value and everything follows. */
.hero__visual {
  --hero-dev: clamp(232px, 21vw, 278px);
  position: relative;
  display: flex;
  justify-content: center;
}
.hero .device--hero { --dev-w: var(--hero-dev); }

/* The pointer note beside the phone. Hidden below 1180px, where there
   isn't room for it to sit clear of the handset — overlapping the screen
   is worse than not having it. */
.hero__pointer {
  display: none;
  position: absolute;
  top: 4%;
  right: 0;
  width: 168px;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--ink-3);
  font-style: italic;
  letter-spacing: -0.01em;
}
/* The note sits to the RIGHT of the handset, so the arrow has to sweep
   down and to the LEFT to land on it. The path is drawn that way already
   (it ends in an arrowhead at its bottom-left), so it must not be
   mirrored — a scaleX(-1) here points it out into empty space, which is
   only hard to spot while the phone is large enough to sit right under
   it. Aligned left within the note so the head reaches toward the phone. */
.hero__pointer svg {
  width: 84px;
  height: 54px;
  margin-top: 8px;
  margin-right: auto;
  color: var(--ink-4);
  opacity: 0.7;
}
/* Above 1180px the hero gets a wider measure so the phone and the note
   can sit side by side without either being squeezed. */
@media (min-width: 1180px) {
  .hero .wrap { max-width: 1200px; }
  .hero__visual { justify-content: flex-start; }
  /* offset from the phone's own width, so the arrow keeps landing on the
     handset when the size tiers shrink it */
  .hero__pointer {
    display: block;
    left: calc(var(--hero-dev) + 26px);
    right: auto;
  }
}

/* ------------------------------------------------------------
   Short screens.

   A full-height iPhone is ~2.17x as tall as it is wide, so on a
   laptop with 700-800px of viewport the hero couldn't show the
   headline, the button AND the whole handset at once — the
   keyboard fell below the fold and the page looked cut off.

   These two tiers trade a little size for a complete first
   screen. They key off viewport HEIGHT, so a tall monitor still
   gets the full-size treatment and nothing changes on phones,
   where the layout is stacked anyway.
   ------------------------------------------------------------ */
@media (min-width: 900px) and (max-height: 860px) {
  .hero { padding-top: 96px; padding-bottom: 32px; }
  .hero__visual { --hero-dev: clamp(220px, 18vw, 258px); }
  .hero__text .cta-row { margin-top: 24px; }
  .hero__chips { margin-top: 20px; }
}

@media (min-width: 900px) and (max-height: 720px) {
  .hero { padding-top: 76px; padding-bottom: 20px; }
  .hero__visual { --hero-dev: clamp(194px, 15.6vw, 222px); }
  .hero__text .lede { margin-top: 14px; }
  .hero__text .cta-row { margin-top: 20px; }
  .hero__chips { margin-top: 16px; }
}

/* ============================================================
   THE PHONE MOCKUP'S CONTENTS
   ------------------------------------------------------------
   Drawn in CSS rather than dropped in as a screenshot, so it stays
   sharp at any size and can be re-worded from content.js.

   Everything is sized in cqw (percentages of the screen's own width)
   so the whole mock scales with the handset instead of needing a
   media query per element.
   ============================================================ */
/* NOTE: the container itself is .device__screen, not .mock. An element
   that establishes a container can't use its own container units for its
   own properties — they'd resolve against the next container up, and with
   none present they fall back to the viewport, which blows every size in
   here up to ~15x. The container has to be the ancestor. */
.mock {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fff;
  color: var(--ink);
  text-align: left;
  font-size: 3.4cqw;
  line-height: 1.35;
  letter-spacing: -0.01em;
}

.mock__bar {
  display: flex;
  align-items: center;
  gap: 2.2cqw;
  padding: 12cqw 4cqw 3cqw;
  border-bottom: 1px solid var(--hairline);
  flex: none;
}
.mock__back { width: 4cqw; height: 4cqw; flex: none; color: var(--ink-4); transform: scaleX(-1); }
.mock__avatar {
  width: 8cqw;
  height: 8cqw;
  flex: none;
  border-radius: 50%;
  background: var(--brand-grad);
}
.mock__who { display: flex; flex-direction: column; line-height: 1.2; }
.mock__who b { font-size: 3.6cqw; font-weight: 620; }
.mock__who i { font-size: 2.7cqw; font-style: normal; color: #2FA84F; }
.mock__acts { margin-left: auto; display: flex; gap: 2cqw; }
.mock__acts span {
  width: 5.4cqw;
  height: 5.4cqw;
  border-radius: 50%;
  background: var(--bg-soft);
}

/* Bottom-aligned, the way a real thread sits: the latest messages rest on
   top of the keyboard and the empty room is above them, under the header.
   Top-aligning left a large white void between the messages and the
   keyboard, which read as a rendering fault rather than as a quiet chat. */
.mock__thread {
  flex: 1;
  min-height: 0;
  /* clipped rather than scrolled: this is a picture of a chat, and a
     stray scrollbar inside the handset would give the game away */
  overflow: hidden;
  padding: 4cqw;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 2.4cqw;
  background: #fff;
}
.mock__msg { display: flex; flex-direction: column; max-width: 82%; }
.mock__msg--them { align-self: flex-start; align-items: flex-start; }
.mock__msg--me { align-self: flex-end; align-items: flex-end; }

.mock__bubble {
  padding: 2.6cqw 3.4cqw;
  border-radius: 4.6cqw;
  background: var(--bg-soft);
  color: var(--ink);
}
.mock__msg--them .mock__bubble { border-bottom-left-radius: 1.4cqw; }
.mock__msg--me .mock__bubble {
  background: var(--brand-tint);
  color: var(--brand-3);
  border-bottom-right-radius: 1.4cqw;
}
.mock__meta { margin-top: 1cqw; font-size: 2.4cqw; color: var(--ink-4); }

/* ---- the keyboard half ---- */
.mock__kb {
  flex: none;
  padding: 3cqw 2.4cqw 2.6cqw;
  background: #F2F2F4;
  border-top: 1px solid var(--hairline);
}
.mock__kbhead {
  display: flex;
  align-items: center;
  gap: 1.8cqw;
  font-size: 2.7cqw;
  font-weight: 640;
  letter-spacing: -0.02em;
  color: var(--ink-3);
  margin-bottom: 2.4cqw;
}
.mock__logo {
  width: 3.4cqw;
  height: 3.4cqw;
  border-radius: 1cqw;
  background: var(--brand-grad);
}

.mock__tabs {
  display: flex;
  gap: 1.4cqw;
  margin-bottom: 2.6cqw;
}
.mock__tab {
  flex: 1;
  text-align: center;
  padding: 1.8cqw 0;
  border-radius: 2.4cqw;
  font-size: 2.5cqw;
  color: var(--ink-4);
  background: rgba(255, 255, 255, 0.7);
}
.mock__tab.is-on {
  background: #fff;
  color: var(--brand);
  font-weight: 620;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.mock__panel {
  background: #fff;
  border-radius: 3cqw;
  padding: 2.6cqw;
  margin-bottom: 3cqw;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
.mock__panelhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 2.5cqw;
  color: var(--ink-4);
  margin-bottom: 2cqw;
}
.mock__tone {
  padding: 0.6cqw 2cqw;
  border-radius: 99px;
  background: var(--brand-tint);
  color: var(--brand);
  font-weight: 600;
}
.mock__panelbody { display: flex; align-items: center; gap: 2cqw; }
.mock__paneltext { flex: 1; font-size: 3cqw; color: var(--ink-2); }
.mock__insert {
  flex: none;
  padding: 1.2cqw 3cqw;
  border-radius: 99px;
  background: var(--brand);
  color: #fff;
  font-size: 2.5cqw;
  font-weight: 600;
}

/* ---- the letter rows ----
   Four rows have to fit in the space one row used to, so the keys are
   shorter and the gaps tighter than the standalone keyboard section. */
.mock__keys { display: grid; gap: 1.4cqw; }
.mock__krow { display: flex; gap: 1.2cqw; }
/* the A–L row is inset either side, as on a real iOS keyboard */
.mock__krow--in { padding-inline: 4.5%; }

.mock__krow span {
  flex: 1;
  text-align: center;
  padding: 2.4cqw 0;
  border-radius: 1.4cqw;
  background: #fff;
  font-size: 2.9cqw;
  line-height: 1;
  color: var(--ink);
  box-shadow: 0 0.5px 0 rgba(0, 0, 0, 0.18);
}

/* shift and backspace are wider and sit on the darker key fill */
.mock__k--wide { flex: 1.5 !important; background: #C7C9CE !important; font-size: 2.6cqw !important; }
/* 123 / globe / return */
.mock__k--fn { flex: 1.4 !important; background: #C7C9CE !important; font-size: 2.3cqw !important; }
.mock__k--go { flex: 2.2 !important; }
.mock__k--space { flex: 4 !important; font-size: 2.5cqw !important; color: var(--ink-4) !important; }

.mock__kglobe { width: 3cqw; height: 3cqw; margin-inline: auto; color: var(--ink-2); }

/* home indicator */
.mock__home {
  display: block;
  width: 34%;
  height: 0.9cqw;
  margin: 2.6cqw auto 0;
  border-radius: 99px;
  background: rgba(0, 0, 0, 0.32);
}

/* ============================================================
   iPHONE MOCKUP  (the hardware)
   ------------------------------------------------------------
   Proportions follow a real handset, expressed as fractions of the
   device width so the frame scales cleanly at any size:
     outer corner radius  13.8%
     titanium rail          1.0%
     black bezel            2.9%
   ============================================================ */
.device {
  --dev-w: 318px;
  --rail: calc(var(--dev-w) * 0.010);
  --bezel: calc(var(--dev-w) * 0.029);
  --r-outer: calc(var(--dev-w) * 0.138);

  position: relative;
  width: var(--dev-w);
  flex: none;
  padding: var(--rail);
  border-radius: var(--r-outer);

  /* brushed titanium rail: alternating light and dark bands read as
     machined metal catching light from different angles */
  background: linear-gradient(
    118deg,
    #7d7f88 0%, #2a2c31 9%, #a6a8b0 19%, #3a3c42 30%,
    #8e9099 42%, #26282d 55%, #9b9da5 68%, #313338 80%,
    #adafb7 90%, #44464c 100%
  );
  box-shadow:
    0 2px 6px rgba(0, 0, 0, 0.08),
    0 44px 80px -34px rgba(0, 0, 0, 0.34);
  transition: transform 0.7s var(--ease-out);
}

/* black bezel between rail and glass */
.device__bezel {
  position: relative;
  padding: var(--bezel);
  border-radius: calc(var(--r-outer) - var(--rail));
  background: #050507;
  box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.9) inset;
}

.device__screen {
  position: relative;
  overflow: hidden;
  /* the query container for the CSS chat mock (.mock), so everything
     drawn on the screen scales in cqw with the handset */
  container-type: inline-size;
  border-radius: calc(var(--r-outer) - var(--rail) - var(--bezel));
  background: #000;
  /* defaults to a real iPhone display ratio so every mockup on the page
     is the same, correct handset shape */
  aspect-ratio: var(--ratio, 1179 / 2556);
}
.device__screen video,
.device__screen img {
  width: 100%;
  height: 100%;
  display: block;
}
/* fill the screen, trimming the source's own dead bands */
.device--fit-cover .device__screen video,
.device--fit-cover .device__screen img { object-fit: cover; }
/* show the whole capture. Used for screenshots that are a different shape
   from a phone screen: their dark UI makes the letterbox invisible against
   the black screen, and nothing gets cropped. */
.device--fit-contain .device__screen video,
.device--fit-contain .device__screen img { object-fit: contain; }

/* Dynamic Island. Sized and placed from real iPhone measurements:
   125/393 wide, 37pt tall, 11pt from the top of the display. */
.device__island {
  position: absolute;
  z-index: 4;
  top: 1.3%;
  left: 50%;
  translate: -50% 0;
  width: 31.8%;
  aspect-ratio: 3.38;
  background: #000;
  border-radius: 99px;
}

/* faint diagonal sheen across the glass */
.device__gloss {
  position: absolute;
  inset: var(--bezel);
  border-radius: calc(var(--r-outer) - var(--rail) - var(--bezel));
  pointer-events: none;
  background: linear-gradient(
    102deg,
    rgba(255, 255, 255, 0.10) 0%,
    rgba(255, 255, 255, 0.035) 14%,
    rgba(255, 255, 255, 0) 34%,
    rgba(255, 255, 255, 0) 100%
  );
}

/* ---- side buttons ---- */
.device__btn {
  position: absolute;
  z-index: 1;
  width: calc(var(--dev-w) * 0.009);
  background: linear-gradient(180deg, #55575e, #9fa1a9 30%, #3e4045 70%, #6f7178);
  border-radius: 2px;
}
/* left edge: action button, then the volume rocker */
.device__btn--action {
  left: calc(var(--dev-w) * -0.008);
  top: 18.5%;
  height: 4.6%;
  border-radius: 2px 0 0 2px;
}
.device__btn--vol-up {
  left: calc(var(--dev-w) * -0.008);
  top: 27%;
  height: 7.6%;
  border-radius: 2px 0 0 2px;
}
.device__btn--vol-down {
  left: calc(var(--dev-w) * -0.008);
  top: 36.5%;
  height: 7.6%;
  border-radius: 2px 0 0 2px;
}
/* right edge: power */
.device__btn--power {
  right: calc(var(--dev-w) * -0.008);
  top: 30%;
  height: 10.5%;
  border-radius: 0 2px 2px 0;
}

/* ---- sizes ---- */
.device--lg { --dev-w: clamp(268px, 30vw, 340px); }
.device--md { --dev-w: clamp(248px, 27vw, 310px); }
/* Deliberately smaller than the demo handset below it. The hero phone is
   a supporting illustration beside the headline, and at full size it
   pushed the call to action and the trust chips below the fold on short
   laptop screens. Everything inside scales in cqw, so shrinking the frame
   shrinks the mock with it. */
/* .device--hero takes its width from --hero-dev, set on .hero__visual. */

/* ---- optional 3D tilt, as used on premium app landing pages. ---- */
@media (min-width: 980px) {
  .device--tilt-left {
    transform: perspective(1500px) rotateY(9deg) rotateX(2deg) rotate(1.2deg);
  }
  .device--tilt-right {
    transform: perspective(1500px) rotateY(-9deg) rotateX(2deg) rotate(-1.2deg);
  }
  /* straighten on hover so a visitor can read the screen comfortably */
  .device--tilt-left:hover,
  .device--tilt-right:hover {
    transform: perspective(1500px) rotateY(0deg) rotateX(0deg) rotate(0deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .device--tilt-left,
  .device--tilt-right { transform: none; }
}

/* ============================================================
   THE REAL DEMO
   ============================================================ */
.demo .sec-head { margin-bottom: clamp(32px, 4vw, 48px); }

.demo__grid {
  display: grid;
  gap: clamp(30px, 4vw, 54px);
  align-items: center;
  justify-items: center;
}
@media (min-width: 860px) {
  .demo__grid { grid-template-columns: auto minmax(0, 1fr); justify-items: start; }
}

.demo__stage { display: flex; flex-direction: column; align-items: center; }

.demo__cap {
  margin-top: 20px;
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 0.83rem;
  color: var(--ink-4);
  text-align: center;
}
.dot-live {
  width: 6px;
  height: 6px;
  flex: none;
  border-radius: 50%;
  background: var(--brand);
  animation: pulse 2s var(--ease) infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* The timeline beside the video. The rule down the left is drawn on the
   list, not on each item, so it doesn't break between rows. */
.demo__steps {
  position: relative;
  display: grid;
  gap: 26px;
  padding-left: 26px;
  max-width: 400px;
}
.demo__steps::before {
  content: '';
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(var(--brand-line), var(--brand-tint-2));
}
.demo__steps li { position: relative; }
.demo__steps li::before {
  content: '';
  position: absolute;
  left: -26px;
  top: 7px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 2.5px var(--brand);
}
.demo__time {
  display: block;
  font-size: 0.76rem;
  font-weight: 640;
  letter-spacing: 0.04em;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}
.demo__what { display: block; margin-top: 3px; color: var(--ink-2); font-size: 0.98rem; }

/* ============================================================
   WHY LOOP IS FASTER
   ============================================================ */
.cmp {
  display: grid;
  gap: 18px;
  margin-top: clamp(34px, 4vw, 48px);
  align-items: start;
}
@media (min-width: 800px) { .cmp { grid-template-columns: 1fr 1fr; } }

.cmp__card {
  border-radius: var(--r-xl);
  padding: clamp(24px, 3vw, 32px);
  background: var(--card-bg);
  box-shadow: var(--card-shadow);
}
/* The "with LOOP" card is tinted, which is the whole comparison:
   one card is paper, the other is the brand. */
.cmp__card--good {
  background: var(--brand-tint);
  box-shadow: inset 0 0 0 1px var(--brand-line);
}

.cmp__tag {
  font-size: 0.94rem;
  font-weight: 620;
  letter-spacing: -0.015em;
  color: var(--ink-3);
  margin-bottom: 20px;
}
.cmp__tag--good { color: var(--brand-3); }

.cmp__list { display: grid; gap: 13px; }
.cmp__list li {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 0.97rem;
  color: var(--ink-2);
}
.cmp__list--num li { color: var(--ink-3); }

.cmp__n {
  width: 20px;
  flex: none;
  font-size: 0.8rem;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}
.cmp__tick {
  width: 19px;
  height: 19px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
}
.cmp__tick svg { width: 11px; height: 11px; }

.cmp__time {
  display: inline-block;
  margin-top: 24px;
  padding: 7px 16px;
  border-radius: var(--r-pill);
  font-size: 0.85rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cmp__time--bad { background: var(--surface-2); color: var(--ink-4); }
.cmp__time--good { background: var(--brand); color: #fff; }

.cmp__foot {
  margin-top: 22px;
  text-align: center;
  font-size: 0.85rem;
  color: var(--ink-4);
}

/* ============================================================
   PRIVACY  /  HOW YOUR TEXT MOVES
   ------------------------------------------------------------
   The one dark band on the page. It stops the scroll, which is
   what you want at the moment a visitor is deciding whether to
   trust a keyboard with what they type.
   ============================================================ */
.priv {
  border-radius: var(--r-2xl);
  background:
    radial-gradient(120% 140% at 0% 0%, #1E1524 0%, transparent 60%),
    var(--dark);
  color: #fff;
  padding: clamp(32px, 4.5vw, 56px);
  display: grid;
  gap: clamp(32px, 4vw, 48px);
  align-items: center;
}
@media (min-width: 900px) {
  .priv { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
}

.priv__shield {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: var(--r-sm);
  margin-bottom: 22px;
  color: #fff;
  background: rgba(255, 255, 255, 0.07);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.14);
}
.priv__shield svg { width: 23px; height: 23px; }

.priv__h { color: #fff; }
.priv__sub {
  margin-top: 14px;
  font-size: 1rem;
  font-weight: 600;
  color: #fff;
  letter-spacing: -0.015em;
}
.priv__lede {
  margin-top: 8px;
  margin-bottom: 26px;
  max-width: 42ch;
  font-size: 0.97rem;
  line-height: 1.6;
  color: var(--dark-ink);
}

.priv__flowlabel {
  font-size: 0.72rem;
  font-weight: 640;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.42);
  margin-bottom: 16px;
}

.priv__steps {
  display: grid;
  gap: 12px;
}
@media (min-width: 620px) {
  .priv__steps { grid-template-columns: repeat(3, 1fr); gap: 10px; }
}

.priv__steps li {
  position: relative;
  padding: 22px 16px;
  border-radius: var(--r-lg);
  text-align: center;
  background: var(--dark-2);
  box-shadow: inset 0 0 0 1px var(--dark-line);
}
.priv__ic {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  margin-bottom: 12px;
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
}
.priv__ic svg { width: 17px; height: 17px; }
.priv__steps b { display: block; font-size: 0.9rem; font-weight: 620; letter-spacing: -0.015em; }
.priv__steps p { margin-top: 5px; font-size: 0.79rem; line-height: 1.45; color: var(--dark-ink); }

/* the arrow between tiles: to the right on wide screens, below on narrow */
.priv__arrow {
  position: absolute;
  width: 16px;
  height: 16px;
  color: rgba(255, 255, 255, 0.3);
  right: -13px;
  top: 50%;
  translate: 0 -50%;
  display: none;
}
@media (min-width: 620px) { .priv__arrow { display: block; } }

/* ============================================================
   FOUR SUPERPOWERS  (tabbed)
   ============================================================ */
.sp { margin-top: clamp(30px, 4vw, 42px); }

.sp__tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  padding: 6px;
  margin-inline: auto;
  width: fit-content;
  max-width: 100%;
  border-radius: var(--r-pill);
  background: var(--inset);
  box-shadow: inset 0 0 0 1px var(--hairline);
}
.sp__tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--r-pill);
  font-size: 0.9rem;
  font-weight: 540;
  color: var(--ink-3);
  transition: background 0.25s var(--ease), color 0.25s var(--ease),
              box-shadow 0.25s var(--ease);
}
.sp__tab svg { width: 16px; height: 16px; flex: none; }
.sp__tab:hover { color: var(--ink); }
.sp__tab.is-on {
  background: var(--dark);
  color: #fff;
  box-shadow: 0 4px 12px -6px rgba(0, 0, 0, 0.5);
}

.sp__panel {
  margin-top: 26px;
  border-radius: var(--r-2xl);
  padding: clamp(26px, 3.4vw, 40px);
  background: var(--card-bg);
  box-shadow: var(--card-shadow);
  display: grid;
  gap: clamp(26px, 3.5vw, 44px);
  align-items: center;
}
@media (min-width: 860px) {
  .sp__panel { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1fr); }
}
.sp__panel:focus { outline: none; }

/* Switching feature tabs used to be a hard cut, because the inactive
   panels are hidden with the attribute and a transition can't run out
   of display:none. An animation can: it starts the moment the panel is
   displayed again, so the incoming one eases in under the tab you just
   pressed. Turned off under prefers-reduced-motion further down. */
@keyframes sp-panel-in {
  from { opacity: 0; transform: translate3d(0, 8px, 0); }
  to   { opacity: 1; transform: none; }
}
.sp__panel:not([hidden]) {
  animation: sp-panel-in 0.36s var(--ease-out) both;
}

.sp__say h3 {
  font-size: clamp(1.3rem, 2.2vw, 1.6rem);
  font-weight: 640;
  letter-spacing: -0.025em;
  line-height: 1.2;
}
.sp__say > p { margin-top: 10px; color: var(--ink-4); font-size: 0.98rem; line-height: 1.55; }

.sp__bullets { margin-top: 22px; display: grid; gap: 12px; }
.sp__bullets li {
  display: flex;
  align-items: center;
  gap: 11px;
  font-size: 0.94rem;
  color: var(--ink-2);
}
.sp__tick {
  width: 18px;
  height: 18px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
}
.sp__tick svg { width: 10px; height: 10px; }

/* the before / after pair */
.sp__demo { display: grid; justify-items: stretch; gap: 10px; }

.sp__msg {
  position: relative;
  padding: 18px 20px;
  border-radius: var(--r-lg);
  background: var(--inset);
  box-shadow: inset 0 0 0 1px var(--hairline);
}
.sp__msg p {
  font-size: 0.96rem;
  line-height: 1.5;
  color: var(--ink-2);
  padding-right: 34px;
}
.sp__msg p span { display: block; }
.sp__msg--out {
  background: var(--brand-tint);
  box-shadow: inset 0 0 0 1px var(--brand-line);
}
.sp__msg--out p { color: var(--brand-3); }

.sp__lbl {
  display: block;
  margin-bottom: 7px;
  font-size: 0.72rem;
  font-weight: 640;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.sp__msg--out .sp__lbl { color: var(--brand); }

/* the flag sits in the corner, as in the design */
.sp__flag {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 26px;
  height: auto;
  aspect-ratio: 3 / 2;
}

.sp__down {
  justify-self: center;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  color: var(--ink-4);
}
.sp__down svg { width: 17px; height: 17px; }

.flag { width: 20px; height: auto; aspect-ratio: 3 / 2; flex: none; }

/* ============================================================
   THE KEYBOARD
   ============================================================ */
.kbd { margin-top: clamp(30px, 4vw, 44px); display: flex; justify-content: center; }

.kbd__frame {
  position: relative;
  width: min(620px, 100%);
  border-radius: var(--r-2xl) var(--r-2xl) 0 0;
  padding: 20px 20px 0;
  overflow: hidden;
  background: #F2F2F4;
  box-shadow: var(--lift-3), inset 0 0 0 1px var(--hairline);
}

.kbd__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 16px;
}
.kbd__brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.86rem;
  font-weight: 660;
  letter-spacing: -0.02em;
  color: var(--ink-3);
}
.kbd__logo { width: 15px; height: 15px; border-radius: 5px; background: var(--brand-grad); }
.kbd__gear { width: 17px; height: 17px; color: var(--ink-4); }

.kbd__actions {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  padding-bottom: 18px;
}
.kbd__action {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 14px 4px;
  border-radius: var(--r-sm);
  background: #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.kbd__action:hover { transform: translateY(-2px); box-shadow: var(--lift); }
.kbd__action svg { width: 20px; height: 20px; color: var(--brand); }
.kbd__action b {
  font-size: 0.76rem;
  font-weight: 560;
  letter-spacing: -0.01em;
  color: var(--ink-2);
}

.kbd__keys { display: grid; gap: 7px; padding-bottom: 26px; }
.kbd__row { display: flex; gap: 6px; }
.kbd__row--in { padding-inline: 5%; }
.kbd__row span {
  flex: 1;
  text-align: center;
  padding: 14px 0;
  border-radius: 7px;
  background: #fff;
  font-size: 0.95rem;
  color: var(--ink);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.16);
}

/* the keyboard runs off the bottom of its own frame */
.kbd__fade {
  position: absolute;
  inset: auto 0 0;
  height: 64px;
  pointer-events: none;
  background: linear-gradient(rgba(242, 242, 244, 0), #F2F2F4 82%);
}
.section--alt .kbd__fade {
  background: linear-gradient(rgba(242, 242, 244, 0), #F2F2F4 82%);
}

@media (max-width: 520px) {
  .kbd__actions { grid-template-columns: repeat(3, 1fr); }
  .kbd__row span { padding: 11px 0; font-size: 0.82rem; }
}

/* ============================================================
   TONE
   ============================================================ */
.tonepick {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: clamp(26px, 3.4vw, 36px);
}
.tonepick__b {
  padding: 10px 20px;
  border-radius: var(--r-pill);
  font-size: 0.9rem;
  font-weight: 540;
  color: var(--ink-3);
  background: var(--inset);
  box-shadow: inset 0 0 0 1px var(--hairline);
  transition: background 0.25s var(--ease), color 0.25s var(--ease),
              box-shadow 0.25s var(--ease);
}
.tonepick__b:hover { color: var(--ink); }
.tonepick__b.is-on {
  background: var(--dark);
  color: #fff;
  box-shadow: 0 4px 12px -6px rgba(0, 0, 0, 0.5);
}

.toneshow {
  margin-top: 26px;
  display: grid;
  gap: 14px;
  align-items: center;
  justify-items: stretch;
}
@media (min-width: 760px) {
  .toneshow { grid-template-columns: 1fr auto 1fr; }
}

.toneshow__in,
.toneshow__out {
  padding: 20px 22px;
  border-radius: var(--r-lg);
  font-size: 0.98rem;
  line-height: 1.5;
}
.toneshow__in {
  background: var(--inset);
  color: var(--ink-3);
  box-shadow: inset 0 0 0 1px var(--hairline);
}
.toneshow__out {
  position: relative;
  padding-right: 52px;
  background: var(--brand-tint);
  color: var(--brand-3);
  box-shadow: inset 0 0 0 1px var(--brand-line);
  transition: opacity 0.2s var(--ease);
}
.toneshow.is-swap .toneshow__out { opacity: 0; }

.toneshow__badge {
  position: absolute;
  right: 16px;
  bottom: 16px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
}
.toneshow__badge svg { width: 14px; height: 14px; }

.toneshow__go {
  justify-self: center;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  color: var(--ink-4);
}
.toneshow__go svg { width: 20px; height: 20px; }
/* the arrow points down when the two panels stack */
@media (max-width: 759px) {
  .toneshow__go { transform: rotate(90deg); }
}

/* ============================================================
   LANGUAGES
   ============================================================ */
.langs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: clamp(26px, 3.4vw, 34px);
}
.langs li {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 18px;
  border-radius: var(--r-pill);
  font-size: 0.92rem;
  color: var(--ink-2);
  background: var(--card-bg);
  box-shadow: var(--card-shadow), inset 0 0 0 1px var(--hairline);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.langs li:hover { transform: translateY(-2px); box-shadow: var(--lift), inset 0 0 0 1px var(--hairline); }
.langs__more { color: var(--ink-4); }
.langs__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--brand);
}

/* ============================================================
   WHO IT'S FOR
   ============================================================ */
.who {
  display: grid;
  gap: 16px;
  margin-top: clamp(30px, 4vw, 42px);
}
@media (min-width: 760px) { .who { grid-template-columns: repeat(3, 1fr); } }

.who__c {
  border-radius: var(--r-xl);
  padding: clamp(26px, 3vw, 34px) clamp(22px, 2.6vw, 28px);
  text-align: center;
  transition: transform 0.3s var(--ease);
}
.who__c:hover { transform: translateY(-3px); }
.who__c--blue { background: var(--tint-blue); }
.who__c--violet { background: var(--tint-violet); }
.who__c--pink { background: var(--tint-pink); }

.who__ic {
  display: inline-grid;
  place-items: center;
  width: 42px;
  height: 42px;
  margin-bottom: 16px;
  border-radius: 50%;
  color: var(--ink-2);
  background: rgba(255, 255, 255, 0.72);
}
.who__ic svg { width: 21px; height: 21px; }

.who__c b {
  display: block;
  font-size: 1.05rem;
  font-weight: 640;
  letter-spacing: -0.02em;
}
.who__c p { margin-top: 7px; font-size: 0.9rem; line-height: 1.5; color: var(--ink-3); }

/* ============================================================
   WHERE IT WORKS
   ============================================================ */
.apps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 12px;
  margin-top: clamp(26px, 3.4vw, 34px);
}
.apps li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 20px 8px;
  border-radius: var(--r-lg);
  background: var(--card-bg);
  box-shadow: var(--card-shadow), inset 0 0 0 1px var(--hairline);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.apps li:hover { transform: translateY(-3px); box-shadow: var(--lift-2), inset 0 0 0 1px var(--hairline); }
.appmark { width: 36px; height: 36px; }
.apps li span { font-size: 0.79rem; color: var(--ink-3); text-align: center; }

.apps__foot {
  margin-top: 20px;
  text-align: center;
  font-size: 0.76rem;
  color: var(--ink-4);
}

/* ============================================================
   REVIEWS   (⚠️ placeholder content — see Testimonials.jsx)
   ============================================================ */
.revs__notice {
  margin-top: 12px;
  display: inline-block;
  padding: 5px 14px;
  border-radius: var(--r-pill);
  font-size: 0.76rem;
  font-weight: 560;
  color: #8A5A00;
  background: #FFF4DB;
  box-shadow: inset 0 0 0 1px rgba(138, 90, 0, 0.18);
}

.revs {
  display: grid;
  gap: 16px;
  margin-top: clamp(28px, 3.6vw, 38px);
}
@media (min-width: 800px) { .revs { grid-template-columns: repeat(3, 1fr); } }

.revs__c {
  border-radius: var(--r-xl);
  padding: clamp(22px, 2.6vw, 28px);
  background: var(--card-bg);
  box-shadow: var(--card-shadow);
  text-align: center;
}
.revs__stars {
  display: inline-flex;
  gap: 3px;
  margin-bottom: 14px;
  color: #F5A623;
}
.revs__stars svg { width: 15px; height: 15px; }

.revs__c blockquote {
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-2);
  letter-spacing: -0.012em;
}
.revs__c figcaption { margin-top: 14px; font-size: 0.85rem; color: var(--ink-4); }

/* ============================================================
   PRICING
   ============================================================ */
.plans {
  display: grid;
  gap: 18px;
  margin-top: clamp(30px, 4vw, 42px);
  align-items: start;
  max-width: 780px;
  margin-inline: auto;
}
@media (min-width: 760px) { .plans { grid-template-columns: 1fr 1fr; } }

.plan {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: var(--r-xl);
  padding: clamp(26px, 3vw, 34px);
  background: var(--card-bg);
  box-shadow: var(--card-shadow), inset 0 0 0 1px var(--hairline);
  text-align: center;
}
/* Pro is the recommendation, so it gets the ring and the lift. */
.plan--pro {
  background: #fff;
  box-shadow: var(--lift-2), inset 0 0 0 1.5px var(--brand-line);
}

.plan__badge {
  position: absolute;
  top: -12px;
  left: 50%;
  translate: -50% 0;
  padding: 5px 15px;
  border-radius: var(--r-pill);
  font-size: 0.72rem;
  font-weight: 640;
  letter-spacing: -0.005em;
  color: #fff;
  background: var(--brand);
  white-space: nowrap;
}

.plan__name {
  font-size: 1.02rem;
  font-weight: 620;
  letter-spacing: -0.02em;
}

.plan__price {
  margin-top: 10px;
  margin-bottom: 22px;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 6px;
}
.plan__amt {
  font-size: clamp(2.1rem, 4vw, 2.7rem);
  font-weight: 660;
  letter-spacing: -0.035em;
  line-height: 1;
}
.plan__per { font-size: 0.85rem; color: var(--ink-4); }

.plan__list {
  display: grid;
  gap: 11px;
  margin-bottom: 26px;
  text-align: left;
}
.plan__list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 0.92rem;
  color: var(--ink-2);
}
.plan__list svg {
  width: 13px;
  height: 13px;
  flex: none;
  margin-top: 5px;
  color: var(--brand);
}

.plan .btn { width: 100%; margin-top: auto; }

.plans__foot {
  text-align: center;
  margin-top: 24px;
  font-size: 0.83rem;
  color: var(--ink-4);
}

/* ---------- FAQ ---------- */
.faq { max-width: 780px; margin: clamp(32px, 4vw, 44px) auto 0; }
.qa { border-bottom: 1px solid var(--hairline); }
.qa:first-child { border-top: 1px solid var(--hairline); }
/* the question is wrapped in an h3 for document outline, so it must not
   introduce its own type scale or spacing */
.qa h3 { font-size: inherit; font-weight: inherit; line-height: inherit; }
.qa__q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 4px;
  text-align: left;
  font-size: clamp(0.98rem, 1.4vw, 1.05rem);
  font-weight: 560;
  letter-spacing: -0.017em;
  transition: color 0.2s;
}
.qa__q:hover { color: var(--brand); }
.qa__ic {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  position: relative;
  background: var(--bg-soft);
  transition: background 0.3s var(--ease), transform 0.35s var(--ease);
}
.section--alt .qa__ic { background: #fff; }
.qa__ic::before,
.qa__ic::after {
  content: '';
  position: absolute;
  background: var(--ink-3);
  border-radius: 2px;
  transition: transform 0.35s var(--ease), background 0.3s;
}
.qa__ic::before { width: 11px; height: 1.5px; }
.qa__ic::after { width: 1.5px; height: 11px; }
.qa.is-open .qa__ic { background: var(--brand); transform: rotate(90deg); }
.qa.is-open .qa__ic::before,
.qa.is-open .qa__ic::after { background: #fff; }
.qa.is-open .qa__ic::after { transform: scaleY(0); }

.qa__a {
  overflow: hidden;
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.42s var(--ease-out);
}
.qa.is-open .qa__a { grid-template-rows: 1fr; }
.qa__a > div { min-height: 0; }
.qa__a p { padding: 0 52px 24px 4px; color: var(--ink-3); font-size: 0.97rem; line-height: 1.65; }
.qa__a p + p { padding-top: 0; }

/* ============================================================
   CLOSING BAND
   ============================================================ */
.final {
  border-radius: var(--r-2xl);
  padding: clamp(28px, 3.6vw, 40px) clamp(24px, 3.4vw, 44px);
  background:
    radial-gradient(90% 160% at 0% 50%, var(--brand-tint-2) 0%, transparent 64%),
    var(--brand-tint);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 22px 28px;
}

.final__icon {
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  flex: none;
  border-radius: 18px;
  background: var(--brand-grad);
  box-shadow: 0 8px 22px -10px rgba(86, 5, 144, 0.6);
}
.final__mark { width: 26px; height: auto; aspect-ratio: 1168 / 1622; }
/* the mark is white inside its own tile, not gradient-on-gradient */
.final__mark path { fill: #fff; }

.final__say { flex: 1 1 260px; }
.final__say h2 {
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  font-weight: 640;
  letter-spacing: -0.028em;
  line-height: 1.2;
}
.final__say p { margin-top: 6px; font-size: 0.95rem; color: var(--ink-3); }

.final__act { flex: none; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.final__note { font-size: 0.78rem; color: var(--ink-4); }

@media (max-width: 640px) {
  .final { flex-direction: column; align-items: center; text-align: center; }
  /* The band's flex direction turns here, which turns `flex: 1 1 260px`
     from a width basis into a HEIGHT basis: the text block claimed 260px
     of vertical space for ~90px of copy and left a hole above the button.
     Column layout wants it sized by its content. */
  .final__say { flex: none; }
  .final__act { align-items: stretch; width: 100%; }
  .final__note { text-align: center; }
}

/* ============================================================
   FOOTER
   ============================================================ */
.foot {
  border-top: 1px solid var(--hairline);
  padding-block: 30px;
}
.foot__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 32px;
}
.foot__links { display: flex; flex-wrap: wrap; gap: 4px 8px; }
/* [role='link'] covers placeholder links whose URL isn't set yet */
.foot__links a,
.foot__links [role='link'] {
  padding: 6px 10px;
  border-radius: 8px;
  font-size: 0.87rem;
  color: var(--ink-4);
  transition: color 0.2s;
}
.foot__links a:hover { color: var(--ink); }
.foot__links [role='link'] { cursor: default; }

.foot__legal {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  font-size: 0.78rem;
  color: var(--ink-4);
  text-align: right;
}

@media (max-width: 700px) {
  .foot__inner { flex-direction: column; text-align: center; }
  .foot__links { justify-content: center; }
  .foot__legal { margin-left: 0; align-items: center; text-align: center; }
}

/* ============================================================
   MOBILE: ONE CENTRED COLUMN
   ------------------------------------------------------------
   Below 900px the page is already a single column, and the
   client asked for it to read down the middle, the mark in the
   header included. So prose centres, rows of items centre, and
   anything with a fixed width gets auto side margins.

   Two things deliberately keep their left edge: the numbered
   step lists (the old-way/with-LOOP comparison, the nine-second
   timeline) and the ticked feature lists in the plans. A list
   whose every line is centred has no edge to run your eye down,
   which reads as worse alignment rather than better.
   ============================================================ */
@media (max-width: 900px) {
  /* Header: lockup in the middle of the bar, burger still on the
     right. The burger comes out of the flex flow so the logo is
     centred on the bar itself and not on what's left beside it. */
  .nav__inner { position: relative; justify-content: center; }
  .nav__burger {
    position: absolute;
    right: var(--gutter);
    top: 50%;
    translate: 0 -50%;
    margin-left: 0;
  }
  .nav__sheet a { text-align: center; }

  /* Hero */
  .hero__text { text-align: center; }
  .hero__text .lede { margin-inline: auto; }
  .hero__text .cta-row { justify-content: center; }
  .hero__chips { justify-content: center; }

  /* Every section head, including the one section that runs its
     head flush left on desktop (the nine-second demo). */
  .sec-head { margin-inline: auto; text-align: center; }

  /* The dark privacy band: its left column and the label above
     the three steps. The steps themselves are already centred. */
  .priv__say { text-align: center; }
  .priv__shield { margin-inline: auto; }
  .priv__flowlabel { text-align: center; }
}

/* ---------- Scroll reveal ----------
   Every section arrives the same way: its contents fade in while
   travelling the last little distance into place. One curve and one
   duration for the whole page is what stops the scroll from feeling
   like fifteen separate animations.

   Variants only move three numbers, so they stay in the same family:

     --rv-y   vertical travel   (positive = rises into place)
     --rv-x   horizontal travel (negative = drifts in from the left)
     --rv-s   starting scale    (below 1 = grows into place)

   Set by the `variant` prop on <Reveal>; see src/components/ui/Reveal.jsx.
   ------------------------------------------------------------------ */
.rv {
  opacity: 0;
  /* translate3d rather than translate: it hands the element to the
     compositor, so the fade never lands on the layout thread. */
  transform: translate3d(var(--rv-x, 0px), var(--rv-y, 20px), 0) scale(var(--rv-s, 1));
}
.rv.in {
  opacity: 1;
  transform: none;
  /* Opacity finishes a touch before the movement does, so elements
     settle rather than stop. */
  transition: opacity 0.62s var(--ease-out), transform 0.8s var(--ease-out);
}

/* Supporting copy: shorter, quicker, so the heading above it leads
   and the paragraph follows instead of racing it. */
.rv--soft { --rv-y: 10px; }
.rv--soft.in { transition-duration: 0.5s, 0.6s; }

/* No travel at all, for anything already carrying its own motion. */
.rv--fade { --rv-y: 0px; }

/* Big panels and mockups: they grow the last 2% into place, which
   reads as the object settling onto the page rather than sliding up it. */
.rv--scale { --rv-y: 22px; --rv-s: 0.978; }

/* The two halves of the before/after comparison close in on each
   other, so the pair reads as one gesture assembling. */
.rv--left  { --rv-y: 8px; --rv-x: -22px; }
.rv--right { --rv-y: 8px; --rv-x: 22px; }

/* The drift only says something while the two cards are side by side.
   Once .cmp stacks (below 800px) they would be drifting in from
   nowhere, so at that width the pair just rises like everything else. */
@media (max-width: 799px) {
  .rv--left, .rv--right { --rv-x: 0px; }
}

/* ---------- Touch targets ----------
   On touch screens every control gets at least ~44px of height, which is
   Apple's recommended minimum. Done here rather than inflating the desktop
   design, where a mouse doesn't need it. */
@media (hover: none) and (pointer: coarse) {
  .logo { padding-block: 8px; }
  .foot__links a,
  .foot__links [role='link'] { padding: 11px 10px; }
  .nav__links a { padding-block: 12px; }
  .sp__tab { padding-block: 13px; }
  .tonepick__b { padding-block: 13px; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .rv { opacity: 1; transform: none; }
  .dot-live { animation: none; }
  /* The blanket rule below only clamps transitions, so anything driven
     by an @keyframes animation has to be named. */
  .sp__panel:not([hidden]) { animation: none; }
  * { transition-duration: 0.01ms !important; }
}


/* ============================================================
   STANDALONE PAGES  (Privacy, Terms, Support, Contact)
   ============================================================ */
.page-hero {
  position: relative;
  padding-top: clamp(104px, 14vw, 148px);
  padding-bottom: clamp(30px, 4vw, 46px);
  isolation: isolate;
  overflow-x: clip;
}
.page-hero__glow {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  left: 50%;
  top: -200px;
  translate: -50% 0;
  width: min(860px, 130vw);
  aspect-ratio: 1 / 0.6;
  background: radial-gradient(
    50% 50% at 50% 50%,
    color-mix(in srgb, var(--brand-2) 10%, transparent) 0%,
    transparent 70%
  );
}

.page-hero__back {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--brand);
  padding: 8px 0;
  transition: opacity 0.2s;
}
.page-hero__back:hover { opacity: 0.7; }
.page-hero__back svg { width: 16px; height: 16px; }

.page-hero__title {
  margin-top: 8px;
  font-size: clamp(2.2rem, 5.5vw, 3.4rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  font-weight: 620;
}
.page-hero__intro { margin-top: 18px; max-width: 60ch; }
.page-hero__meta {
  margin-top: 20px;
  font-size: 0.85rem;
  color: var(--ink-4);
}

/* ---------- Long-form text ---------- */
.prose {
  max-width: 700px;
  padding-bottom: clamp(56px, 8vw, 104px);
  font-size: 1.02rem;
  line-height: 1.72;
  color: var(--ink-2);
}
.prose h2 {
  margin-top: 52px;
  margin-bottom: 14px;
  font-size: clamp(1.35rem, 2.4vw, 1.6rem);
  line-height: 1.22;
  letter-spacing: -0.024em;
  font-weight: 620;
  color: var(--ink);
}
.prose h2:first-child { margin-top: 0; }
.prose h3 {
  margin-top: 32px;
  margin-bottom: 8px;
  font-size: 1.06rem;
  letter-spacing: -0.018em;
  font-weight: 600;
  color: var(--ink);
}
.prose p { margin-bottom: 16px; }
.prose a {
  color: var(--brand);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--brand) 35%, transparent);
  text-underline-offset: 3px;
  transition: text-decoration-color 0.2s;
}
.prose a:hover { text-decoration-color: var(--brand); }
.prose a.btn { color: #fff; text-decoration: none; margin-top: 8px; }
.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.88em;
  background: var(--bg-soft);
  border-radius: 6px;
  padding: 2px 6px;
}
.prose strong { color: var(--ink); font-weight: 620; }

/* bulleted and numbered lists */
.prose ul,
.prose ol {
  margin: 0 0 18px;
  padding-left: 22px;
  list-style: disc;
}
.prose ol { list-style: decimal; }
.prose li { margin-bottom: 9px; padding-left: 2px; }
.prose li::marker { color: var(--ink-4); }

/* tick list, for the reassuring summaries */
.prose .ticks { list-style: none; padding-left: 0; }
.prose .ticks li {
  position: relative;
  padding-left: 30px;
  margin-bottom: 11px;
}
.prose .ticks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 15px;
  height: 8px;
  border-left: 2px solid var(--brand);
  border-bottom: 2px solid var(--brand);
  rotate: -45deg;
  border-radius: 1px;
}

/* numbered setup steps */
.prose .steps-num {
  list-style: none;
  padding-left: 0;
  counter-reset: sn;
}
.prose .steps-num li {
  counter-increment: sn;
  position: relative;
  padding-left: 46px;
  margin-bottom: 18px;
}
.prose .steps-num li::before {
  content: counter(sn);
  position: absolute;
  left: 0;
  top: 0.05em;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 0.85rem;
  font-weight: 660;
  color: #fff;
  background: var(--brand);
}

/* ---------- Review notice ----------
   Deliberately loud. It must not survive to launch unnoticed. */
.notice {
  margin: 0 0 40px;
  padding: 18px 20px;
  border-radius: var(--r);
  background: #FFF6E3;
  border: 1px solid #F0D18A;
  font-size: 0.95rem;
  line-height: 1.6;
  color: #6B4A05;
}
.notice strong { color: #4D3403; }

/* inline marker for facts the client must supply */
.todo {
  display: inline;
  padding: 1px 7px;
  border-radius: 5px;
  background: #FFF1D3;
  border: 1px dashed #DCB25A;
  color: #6B4A05;
  font-size: 0.9em;
  font-weight: 540;
}

/* ---------- Contact cards ---------- */
.contact-grid {
  display: grid;
  gap: 14px;
  grid-template-columns: minmax(0, 1fr);
  margin-bottom: 44px;
}
@media (min-width: 700px) {
  .contact-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.contact-card {
  padding: 26px 24px;
  border-radius: var(--r-lg);
  background: var(--bg-soft);
  display: flex;
  flex-direction: column;
}
.contact-card h3 { margin: 0 0 8px; font-size: 1.03rem; font-weight: 600; color: var(--ink); }
.contact-card p { font-size: 0.93rem; color: var(--ink-3); margin-bottom: 14px; line-height: 1.6; }
.contact-card p.small { margin-top: auto; margin-bottom: 0; font-size: 0.85rem; }
.contact-card__mail {
  display: inline-block;
  margin-bottom: 14px;
  font-weight: 560;
  font-size: 0.96rem;
  color: var(--brand);
  word-break: break-all;
}
.contact-card__mail:hover { text-decoration: underline; text-underline-offset: 3px; }
