/* TOVELU sales page — V2 identity layer, 11 August 2026.
 *
 * Loaded after sales-m3.css, which stays the base: it owns the M3 tokens, the
 * phone-preview engine and the `.ui` block that is a straight copy of the app's
 * own stylesheet. None of that is touched here — the previews have to keep
 * looking like the product, not like a sales page's idea of it.
 *
 * What this file does is lift the page AROUND the previews, and it fixes the
 * things a phone actually trips over. Where it restates a base selector it does
 * so at the same specificity and simply wins on order, rather than escalating
 * with !important — so the base file stays readable and this one stays the only
 * place to look for the newer treatment.
 *
 *   1. type      — optical sizing, a fluid scale, balanced headings
 *   2. depth     — hairline + ambient shadow instead of flat fills
 *   3. surface   — a ground that shifts between sections rather than banding
 *   4. mobile    — 48px targets, safe areas, fluid gutters, anchor offsets
 *   5. motion    — one staggered reveal, spring-eased, off when asked
 */

/* ============================================================ typography */

/* Roboto Flex is variable on both weight and optical size. The base file loads
   it but never drives `opsz`, so display type was being rendered with the same
   letterfit as 12px captions — the single biggest reason the old page read as
   "web template" rather than "product". */
.m3s {
  font-optical-sizing: auto;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
}

.m3s h1, .m3s h2, .m3s h3, .m3s h4 {
  font-variation-settings: "opsz" 96;
  text-wrap: balance;
}
.m3s p, .m3s li { text-wrap: pretty; }

/* Digits that sit in columns or get compared must not shimmy as they change. */
.strip-cell b, .est-lead .big, .effort .big, .ui .bignum b, .ui .qty, .ui .val {
  font-variant-numeric: tabular-nums;
}

.hero h1 {
  font-size: clamp(2.25rem, 8.4vw, 4.25rem);
  line-height: 1.02;
  letter-spacing: -.038em;
  font-weight: 700;
}
.head h2 {
  font-size: clamp(1.75rem, 6.2vw, 2.875rem);
  line-height: 1.08;
  letter-spacing: -.032em;
}
.hero-sub {
  font-size: clamp(1.0625rem, 4.3vw, 1.3125rem);
  line-height: 1.55;
  letter-spacing: -.006em;
}
.lede {
  font-size: clamp(1rem, 4vw, 1.1875rem);
  line-height: 1.62;
}

/* The chapter eyebrow. Small caps carry a page like this only if they are
   genuinely small and genuinely spaced — at .75rem/.02em it just looked like
   shrunken body text. */
.kick {
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  gap: .5rem;
}
.kick::before {
  content: "";
  width: 1.5rem;
  height: 1px;
  background: currentColor;
  opacity: .55;
}
.head-mid .kick::after {
  content: "";
  width: 1.5rem;
  height: 1px;
  background: currentColor;
  opacity: .55;
}
.head-mid .kick { justify-content: center; }

::selection { background: color-mix(in srgb, var(--primary) 28%, transparent); }

/* ================================================================= depth */

/* One shadow ramp, warmed toward the brand green rather than neutral black —
   a grey shadow under a green-tinted surface is what makes a page look
   assembled from a component library. */
.m3s {
  --lift-1: 0 1px 2px rgba(10, 38, 24, .05), 0 1px 3px rgba(10, 38, 24, .04);
  --lift-2: 0 2px 4px rgba(10, 38, 24, .05), 0 8px 20px -6px rgba(10, 38, 24, .10);
  --lift-3: 0 4px 8px rgba(10, 38, 24, .06), 0 18px 40px -12px rgba(10, 38, 24, .16);
  --hair: color-mix(in srgb, var(--outline-variant) 62%, transparent);
}
@media (prefers-color-scheme: dark) {
  .m3s {
    --lift-1: 0 1px 2px rgba(0, 0, 0, .5);
    --lift-2: 0 2px 6px rgba(0, 0, 0, .45), 0 10px 24px -8px rgba(0, 0, 0, .5);
    --lift-3: 0 6px 14px rgba(0, 0, 0, .5), 0 24px 48px -14px rgba(0, 0, 0, .6);
    --hair: color-mix(in srgb, var(--outline-variant) 55%, transparent);
  }
}

.panel, .goal, .freestep, .cmp tr, .est, .fit-col, .trust, .effort {
  box-shadow: var(--lift-1);
}
.panel, .goal, .freestep {
  border: 1px solid var(--hair);
  transition: transform .32s cubic-bezier(.2, .8, .2, 1), box-shadow .32s cubic-bezier(.2, .8, .2, 1);
}
@media (hover: hover) {
  .panel:hover, .goal:hover, .freestep:hover {
    transform: translateY(-3px);
    box-shadow: var(--lift-2);
  }
}

/* =============================================================== surface */

/* The base file alternates whole sections between two flat fills, which bands
   the page into stripes. A soft vertical wash inside the alternate sections
   reads as one continuous surface catching light instead. */
.sect-alt {
  background:
    radial-gradient(120% 60% at 50% 0%, color-mix(in srgb, var(--primary) 6%, transparent), transparent 70%),
    var(--s-low);
}

/* An ambient bloom behind the hero handset, so the phone sits in the page
   rather than on it. Pure decoration, hence aria-hidden's job is already done
   by the element it hangs off. */
.hero {
  position: relative;
  overflow: clip;
}
.hero::before {
  content: "";
  position: absolute;
  inset: -20% -10% auto 30%;
  height: 46rem;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--primary) 16%, transparent), transparent);
  pointer-events: none;
  z-index: 0;
}
.hero-in { position: relative; z-index: 1; }

@media (max-width: 62rem) {
  /* On a phone the bloom would sit behind the headline and dirty the text. */
  .hero::before { inset: auto -30% -10% -30%; height: 30rem; }
}

.hero-stage .phone { box-shadow: var(--lift-3); }

/* ============================================================== controls */

/* 48px is the floor for anything a thumb has to hit. The base file's small CTA
   was 42px and the FAQ rows were whatever their text happened to be. */
.cta {
  min-height: 3.25rem;
  padding: 0 1.75rem;
  font-weight: 600;
  letter-spacing: -.005em;
  box-shadow: var(--lift-2);
  transition: transform .2s cubic-bezier(.2, .8, .2, 1), box-shadow .2s ease, filter .2s ease;
}
.cta:hover { box-shadow: var(--lift-3); }
.cta-sm { min-height: 2.75rem; padding: 0 1.25rem; }
.cta-lg { min-height: 3.75rem; padding: 0 2.25rem; font-size: 1.0625rem; }

.faq-q { min-height: 3.5rem; }
.est-units button { min-height: 2.75rem; }

.m3s :focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

/* ================================================================ topbar */

.topbar {
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: saturate(1.6) blur(16px);
  -webkit-backdrop-filter: saturate(1.6) blur(16px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s ease, box-shadow .3s ease;
}
/* Set by the page script once the visitor has left the hero, so the bar only
   grows an edge when there is content sliding under it. */
.topbar.stuck {
  border-bottom-color: var(--hair);
  box-shadow: var(--lift-1);
}
.topbar-in { height: 4rem; }
.topnav a {
  position: relative;
  padding: .5rem 0;
  transition: color .2s ease;
}
.topnav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: .125rem;
  height: 2px;
  border-radius: 2px;
  background: var(--primary);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .28s cubic-bezier(.2, .8, .2, 1);
}
.topnav a:hover::after { transform: scaleX(1); }

/* Anchor targets must clear the sticky bar. Without this every in-page link —
   including the ones the legal pages point at — parked its heading underneath
   the header. */
:where(#why, #app, #goals, #possible, #compare, #free, #faq, #top) {
  scroll-margin-top: 5rem;
}

/* ============================================================ fact strip */

.strip {
  background: linear-gradient(180deg, color-mix(in srgb, var(--primary) 9%, var(--s-cont)), var(--s-cont));
}
.strip-cell b { letter-spacing: -.035em; }

/* The base file takes .grid3 straight from one column to three at 56rem, which
   left a tablet showing three full-width cards in a very tall stack. Two across
   is the shape that middle actually wants. */
@media (min-width: 40rem) and (max-width: 55.99rem) {
  .grid3 { grid-template-columns: repeat(2, 1fr); gap: 1rem; }
  /* An odd last card centred under two is tidier than one hanging left. */
  .grid3 > :last-child:nth-child(odd) { grid-column: 1 / -1; max-width: 34rem; margin-inline: auto; }
}

/* ================================================================ mobile */

/* Gutters, rhythm and anything that can push the document sideways. Ordered
   from widest breakpoint down so the phone case is the last word. */

.m3s { overflow-x: clip; }

@media (max-width: 48rem) {
  .m3s { --gut: 1.25rem; --sec-y: 3.25rem; }

  .hero { padding-top: 2.25rem; }
  .hero-cta { max-width: none; }
  .hero-cta .cta { width: 100%; }

  /* Two big numbers a row reads better than four cramped ones. */
  .strip-cell { padding: 1.125rem .75rem; }
  .strip-cell b { font-size: 1.5rem; }

  .head h2 { letter-spacing: -.028em; }
  .grid3, .grid4, .goals, .fit, .freebox { gap: .75rem; }
  .panel, .goal, .freestep, .fit-col { padding: 1.25rem; }

  /* The timeline's fixed 3.75rem gutter left the body text a 200px column. */
  .tl-row { grid-template-columns: 3rem 1fr; gap: .75rem; }

  .trust { border-radius: var(--r-xxl); }
  .final-box { border-radius: var(--r-xxl); }

  /* Long strings that have no space to break at — an email address in the
     footer, a URL in the legal line — are the classic source of a phone's
     horizontal scrollbar. */
  .foot-legal, .guarantee, .trust .sign span { overflow-wrap: anywhere; }
}

/* 23rem, not 26rem: at 26 this caught a 390px iPhone, which has plenty of room
   for the 1.25rem gutter and looked cramped without it. This tier is for the
   genuinely narrow — a 360px Android and below. */
@media (max-width: 23rem) {
  .m3s { --gut: 1rem; }
  .hero h1 { font-size: clamp(2rem, 9.5vw, 2.6rem); }
  .strip-in { grid-template-columns: 1fr 1fr; }
  .cta { font-size: .9375rem; padding: 0 1.25rem; }
}

/* The sticky bar has to clear the home-indicator on a modern handset, and the
   footer has to leave room for the bar. */
.sticky {
  padding-bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
  background: color-mix(in srgb, var(--surface) 90%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 -8px 24px -12px rgba(10, 38, 24, .3);
}
.foot { padding-bottom: calc(6rem + env(safe-area-inset-bottom, 0px)); }

/* ================================================================ motion */

/* One reveal, spring-eased and staggered by position within its group, rather
   than every block arriving on the same 500ms curve. The delay is capped so a
   twelve-card section never leaves the last card hanging. */
.js-reveal .reveal {
  opacity: 0;
  transform: translateY(1.25rem);
  transition:
    opacity .62s cubic-bezier(.2, .8, .2, 1),
    transform .62s cubic-bezier(.2, .8, .2, 1);
}
.js-reveal .reveal.in { opacity: 1; transform: none; }

.js-reveal .grid3 > .reveal:nth-child(2),
.js-reveal .grid4 > .reveal:nth-child(2),
.js-reveal .goals > .reveal:nth-child(2),
.js-reveal .freebox > .reveal:nth-child(2),
.js-reveal .fit > .reveal:nth-child(2) { transition-delay: .09s; }
.js-reveal .grid3 > .reveal:nth-child(3),
.js-reveal .grid4 > .reveal:nth-child(3),
.js-reveal .goals > .reveal:nth-child(3),
.js-reveal .freebox > .reveal:nth-child(3) { transition-delay: .18s; }
.js-reveal .grid4 > .reveal:nth-child(4),
.js-reveal .goals > .reveal:nth-child(4) { transition-delay: .27s; }

@media (prefers-reduced-motion: reduce) {
  .js-reveal .reveal,
  .js-reveal .grid3 > .reveal,
  .js-reveal .grid4 > .reveal,
  .js-reveal .goals > .reveal,
  .js-reveal .freebox > .reveal,
  .js-reveal .fit > .reveal {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0s;
  }
  .panel, .goal, .freestep { transition: none; }
}

/* ===================================================== V2: the raised plus */

.ui .tb-add { align-self: center; }
.ui .tb-add .pill {
  width: 2.75rem;
  height: 2.25rem;
  background: var(--primary);
  color: var(--on-primary);
  font-size: 1.5rem;
  font-weight: 300;
  line-height: 1;
  box-shadow: var(--e2);
}

/* ========================================================= V2: goal cards */

.goals { display: grid; gap: .875rem; margin-top: clamp(2rem, 6vw, 3rem); }
@media (min-width: 40rem) { .goals { grid-template-columns: repeat(2, 1fr); gap: 1rem; } }
@media (min-width: 64rem) { .goals { grid-template-columns: repeat(4, 1fr); } }

.goal {
  background: var(--s-lowest);
  border-radius: var(--r-xl);
  padding: 1.5rem;
}
.sect-alt .goal { background: var(--surface); }
.goal .ic {
  width: 2.75rem; height: 2.75rem;
  display: grid; place-items: center;
  border-radius: var(--r-full);
  background: var(--primary-container); color: var(--on-primary-container);
  font-size: 1.25rem;
}
.goal h3 { margin-top: 1rem; font-size: 1.0625rem; font-weight: 600; letter-spacing: -.015em; }
.goal p { margin-top: .5rem; font-size: .875rem; line-height: 1.58; color: var(--on-surface-variant); }

.styles { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.5rem; justify-content: center; }
.styles span {
  font-size: .8125rem; font-weight: 600;
  padding: .5rem 1rem;
  border-radius: var(--r-full);
  background: var(--s-cont); color: var(--on-surface-variant);
  border: 1px solid var(--hair);
}

/* ====================================================== V2: health preview */

.ui .sig { border-radius: var(--r-xxl); padding: 1.25rem; margin-bottom: .625rem; }
.ui .sig.watch { background: var(--s-low); }
.ui .sig.discuss { background: var(--tertiary-container); color: var(--on-tertiary-container); }
.ui .sig.soon { background: var(--ember-container); color: var(--on-ember-container); }
.ui .sig .sev {
  font-size: .6875rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; opacity: .8;
}

.ui .fact {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: .625rem 0;
  border-bottom: 1px solid var(--outline-variant);
  font-size: .875rem;
}
.ui .fact:last-child { border-bottom: 0; }
.ui .fact span:last-child { color: var(--on-surface-variant); text-align: right; }
