/* tendgratitude.app — the landing page.
 *
 * Light theme only, by decision: this is a brand surface, not the app, and its
 * ground is the app's light `surface` — the same value as the app icon's
 * background, so the icon sits on the page without a seam. Every value below
 * comes from the Material 3 palette generated from seed #63A002; the seed
 * itself never appears (docs/design-ask-web/README.md).
 */

:root {
  --surface: #f9faef;      /* page ground — light surface, also the icon ground */
  --on-surface: #1a1c16;   /* body text */
  --muted: #44483d;        /* onSurfaceVariant */
  --accent: #4c662b;       /* primary — the CTA owns this */
  --surface-raised: #eeefe3; /* the app's light surfaceContainer — quiet cards */
  --hairline: #c5c8ba;     /* outlineVariant */
  --phone-ground: #12140e; /* dark surface, only ever inside captures */

  /* 4pt scale */
  --s4: 4px; --s8: 8px; --s12: 12px; --s16: 16px;
  --s24: 24px; --s32: 32px; --s48: 48px; --s64: 64px;

  --serif: Georgia, "Times New Roman", serif;
  --sans: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
  --measure: 34rem;

  /* The project's arrival curve (DESIGN.md · Motion): critically damped,
   * no bounce on anything the user did not throw with a finger. */
  --ease-arrive: cubic-bezier(0.32, 0.72, 0, 1);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--surface);
  color: var(--on-surface);
  font: 16px/1.55 var(--sans);
}

img { max-width: 100%; height: auto; display: block; }

/* ——— shared type ——— */

h1, h2, .support, .loop-sentence, .accumulation, blockquote, .gloss {
  font-family: var(--serif);
}

/* Georgia at its regular weight — the app's own voice. Bold serif reads
 * as a newspaper; regular reads as Tend. */
h1 {
  font-weight: 400;
  font-size: clamp(2.4rem, 9.5vw, 3.4rem);
  line-height: 1.1;
  margin: var(--s12) 0 0;
  text-wrap: balance;
  letter-spacing: -0.01em;
}

h2 {
  font-weight: 400;
  font-size: clamp(1.7rem, 6.5vw, 2.4rem);
  line-height: 1.18;
  margin: var(--s12) 0 0;
  text-wrap: balance;
  letter-spacing: -0.01em;
}

/* One word per headline carries the argument's weight — and it is that
 * viewport's entire accent budget. */
.accent-word {
  font-style: italic;
  color: var(--accent);
}

.opener {
  font-family: var(--sans);
  font-size: 0.95rem;
  color: var(--muted);
  margin: 0;
}

.section-title { margin-top: 0; }

.aside, .fine {
  color: var(--muted);
  max-width: var(--measure);
  margin-left: auto;
  margin-right: auto;
}

.fine { font-size: 0.85rem; }

a { color: var(--accent); }

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

/* ——— layout: every section is one centered column ——— */

.hero, main > section {
  padding: var(--s48) var(--s24);
  max-width: 44rem;
  margin: 0 auto;
  text-align: center;
}

.hero { padding-top: var(--s32); }

/* The hairline is a pseudo-element rather than a border so it can draw
 * itself in as its section arrives — structure keeping pace with scroll. */
main > section { position: relative; }

main > section::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--s24);
  right: var(--s24);
  height: 1px;
  background: var(--hairline);
  transform-origin: left center;
}

/* ——— hero ——— */

.lockup {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s12);
  padding-bottom: var(--s24);
  border-bottom: 1px solid var(--hairline);
  margin-bottom: var(--s32);
}

.lockup-icon { border-radius: 10px; }

.lockup-name {
  text-align: left;
  line-height: 1.25;
}

.lockup-name strong {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.25rem;
  display: block;
}

.lockup-name span {
  font-size: 0.8rem;
  color: var(--muted);
}

.support {
  font-size: clamp(1.05rem, 4vw, 1.25rem);
  color: var(--on-surface);
  max-width: var(--measure);
  margin: var(--s16) auto 0;
}

.cta { margin-top: var(--s32); }

.badge-link { display: inline-block; }

.badge-link img { width: 180px; height: 60px; }

.cta-note {
  font-size: 0.85rem;
  color: var(--muted);
  margin: var(--s8) 0 0;
}

/* ——— Android: honesty instead of a dead-end store link ——— */

.android-note {
  color: var(--muted);
  margin: 0 0 var(--s12);
}

button.button {
  border: 0;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

button.button:disabled {
  background: var(--surface-raised);
  color: var(--muted);
  cursor: default;
}

.is-android .badge-link,
.is-android .sticky-bar,
.is-android .plan-plus .button {
  display: none;
}

/* ——— the phones: devices, not rectangles ———
 *
 * Every capture sits in a black bezel with deep corners — a phone set down
 * on the page. The three body captures share one 9/16 box so no screen
 * outweighs another; only the hero is taller, and only it and the
 * reflection are set down at a slight angle. */

/* The ratio lives on the IMG, not the padded figure: engines disagree on
 * whether aspect-ratio wraps the border box or the content box, and that
 * disagreement was shifting the visible crop between browsers. An image has
 * no padding, so every engine computes the same window. */
.phone {
  margin: var(--s32) auto 0;
  width: min(340px, 84vw);
  position: relative;
  overflow: hidden;
  background: #000;
  padding: 10px;
  border-radius: 42px;
  box-shadow: 0 24px 52px rgba(26, 28, 22, 0.2);
}

.phone img {
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border-radius: 32px;
  background: var(--phone-ground);
}

/* Hero: tall, tilted — the question and options big, the screen dimming
 * into the device before "Type your own". */
/* Tilts alternate strictly down the page: hero +2, transformation -1.5,
 * reflection +1.5, practice -1.5 — every phone leans away from its
 * neighbor. */
.phone--tall {
  transform: rotate(2deg);
  margin-top: var(--s48);
}

.phone--tall img {
  aspect-ratio: 3 / 5;
  object-position: 50% 5%;
}

.phone--tall::after {
  content: "";
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 10px;
  height: 26%;
  border-radius: 0 0 32px 32px;
  background: linear-gradient(to bottom, rgba(18, 20, 14, 0), var(--phone-ground) 92%);
}

/* The transformation: status bar trimmed, the keep-choice kept, and a
 * whisper of the accent's light behind it — a dark phone on the dark band
 * needs its own glow to be an object. */
.proof--focal .phone {
  transform: rotate(-1.5deg);
}

.proof--focal .phone img { object-position: 50% 78%; }

/* The reflection: headroom above the quote, the meadow, the app's own tab
 * bar at the foot — set down at the answering angle to the hero. */
.phone--crop { transform: rotate(1.5deg); }

.phone--crop img { object-position: 50% 100%; }

/* ——— proof sections ——— */

.proof .aside { margin-top: var(--s24); }

/* The dark bands: Tend's own dark theme as the page's second ground —
 * the two grounds are the app's two themes, nothing invented. The
 * transformation, the privacy promise, and the founder's sentence live
 * there: the page goes dark where it gets intimate. */
.band-dark {
  background: var(--phone-ground);
  box-shadow: 0 0 0 100vmax var(--phone-ground);
  clip-path: inset(0 -100vmax);
  color: #e2e3d8;
}

.band-dark::before { display: none; }

/* A band is its own separator; the hairline would double it. */
.band-dark + section::before { display: none; }

.band-dark .opener { color: #b1d18a; }

.band-dark h2 { color: #e2e3d8; }

.band-dark .aside,
.band-dark .foot-line,
section.band-dark blockquote cite { color: #c5c8ba; }

.band-dark a { color: #b1d18a; }

.band-dark .accent-word { color: #b1d18a; }

.band-dark .phone {
  border: 1px solid rgba(226, 227, 216, 0.16);
  box-shadow:
    0 24px 48px rgba(0, 0, 0, 0.5),
    0 0 110px rgba(177, 209, 138, 0.28);
}

/* ——— the loop ——— */

.loop-list {
  list-style: none;
  margin: 0 0 var(--s24);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s16);
  text-align: left;
  max-width: var(--measure);
  margin-left: auto;
  margin-right: auto;
}

.loop-list li {
  display: flex;
  gap: var(--s16);
  align-items: baseline;
}

.loop-list i {
  font-family: var(--serif);
  font-style: italic;
  font-size: 1.35rem;
  color: var(--accent);
  flex: 0 0 4.5rem;
}

.loop-list span {
  font-size: 0.95rem;
  color: var(--muted);
  line-height: 1.45;
}

/* The sentence sums up the list above it — it belongs to the words, not to
 * the screenshot below, so it sits close and the figure keeps its distance. */
.loop-sentence {
  font-size: clamp(1.15rem, 4.5vw, 1.45rem);
  line-height: 1.4;
  max-width: var(--measure);
  margin: var(--s8) auto 0;
  text-wrap: balance;
}

/* The Practice screen — the one capture that hints at what else is here:
 * Today's line, Shift, Themes, down to the app's own tab bar. */
.phone--practice { transform: rotate(-1.5deg); }

.phone--practice img {
  aspect-ratio: 11 / 20;
  object-position: 50% 100%;
}

/* ——— pricing ——— */

.plans {
  display: grid;
  gap: var(--s16);
  margin: var(--s24) 0 var(--s16);
  text-align: left;
}

.plan {
  border: 1px solid var(--hairline);
  border-radius: 18px;
  padding: var(--s24);
}

.plan h3 {
  font-family: var(--serif);
  font-weight: normal;
  font-size: 1.3rem;
  margin: 0 0 var(--s8);
}

.plan p { margin: 0 0 var(--s8); }

/* Raised paper, not the palette's lime container — that tone is the app's,
 * but on this earthy page it read as neon. The green stays in the button. */
.plan-plus {
  background: var(--surface-raised);
  border-color: var(--surface-raised);
}

.price { font-size: 0.95rem; }

.button {
  display: inline-block;
  background: var(--accent);
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  padding: 14px 24px;
  border-radius: 999px;
  margin-top: var(--s8);
}

.button-small { padding: 9px 18px; font-size: 0.9rem; margin: 0; }

/* ——— privacy ——— */

.foot-line {
  color: var(--muted);
  font-size: 0.95rem;
  margin: var(--s12) 0 0;
}

.privacy .aside { margin-top: var(--s24); }

/* ——— science ——— */

.science p { max-width: var(--measure); margin-left: auto; margin-right: auto; }

/* ——— founder ——— */

.founder { padding-top: calc(var(--s64) + var(--s24)); padding-bottom: calc(var(--s64) + var(--s24)); }

.founder blockquote { margin: 0; }

.founder p {
  font-size: clamp(1.4rem, 5.5vw, 1.9rem);
  line-height: 1.3;
  margin: 0;
  text-wrap: balance;
}

.founder cite {
  display: block;
  font-family: var(--sans);
  font-style: normal;
  font-size: 0.9rem;
  color: var(--muted);
  margin-top: var(--s16);
}

/* ——— the gloss + close ——— */

.gloss { margin-bottom: var(--s32); }

.gloss p { margin: 0; }

.gloss-entry { font-size: 1.3rem; }

.gloss-entry i { font-weight: bold; }

.gloss-pos { color: var(--muted); font-size: 1rem; }

.gloss-def { font-size: 1.15rem; margin-top: var(--s4); }

.gloss-lede {
  color: var(--accent);
  font-size: 1.15rem;
  font-style: italic;
  margin-top: var(--s16);
}

/* ——— footer ——— */

footer {
  border-top: 1px solid var(--hairline);
  padding: var(--s32) var(--s24) calc(var(--s64) + var(--s32));
  text-align: center;
  font-size: 0.85rem;
  color: var(--muted);
}

footer nav {
  display: flex;
  justify-content: center;
  gap: var(--s16);
  flex-wrap: wrap;
}

footer a { color: var(--muted); }

footer p { margin: var(--s12) 0 0; }

/* ——— sticky store bar (mobile-first; JS removes [hidden] once armed) ——— */

.sticky-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  gap: var(--s12);
  padding: var(--s12) var(--s16);
  padding-bottom: calc(var(--s12) + env(safe-area-inset-bottom));
  background: rgba(249, 250, 239, 0.95);
  border-top: 1px solid var(--hairline);
  transform: translateY(120%);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.sticky-bar[hidden] { display: none; }

.sticky-bar.is-shown {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}

.sticky-bar img { border-radius: 6px; }

.sticky-bar span {
  font-family: var(--serif);
  font-size: 1.05rem;
  flex: 1;
  text-align: left;
}

/* ——— motion ———————————————————————————————————————————————————————————
 *
 * The page moves the way the product does: quick taps, then an unhurried
 * pause. Every routine arrival is brief and critically damped; exactly one
 * moment — the transformation proof — takes its time. Nothing here reenacts
 * the transformation itself; the page only borrows its temperament.
 *
 * All entrances are compositor-only. Content is fully visible without JS,
 * and the JS watchdog reveals instantly (no transition), so no audit or
 * fast scroll can ever catch text mid-fade.
 */

/* Hero load-in: transform only, so the LCP paints at full opacity from the
 * first frame. Two beats — the words, then the phone. Runs without JS. */
@keyframes hero-rise {
  from { transform: translateY(12px); }
  to   { transform: none; }
}

.hero-copy { animation: hero-rise 0.55s var(--ease-arrive) backwards; }

/* The tilt must survive the entrance, so the hero phone has its own keyframes. */
@keyframes hero-rise-tilt {
  from { transform: translateY(12px) rotate(2deg); }
  to   { transform: rotate(2deg); }
}

.hero .phone { animation: hero-rise-tilt 0.55s var(--ease-arrive) 0.12s backwards; }

/* Scroll arrivals: each section choreographs its own children — the line
 * of argument first, the evidence after — rather than sliding as one slab. */
.is-armed > * {
  opacity: 0;
  transform: translateY(18px);
  will-change: transform, opacity;
}

.is-revealed > * {
  opacity: 1;
  transform: none;
  will-change: auto;
  transition:
    transform 0.42s var(--ease-arrive),
    opacity 0.32s ease-out;
}

.is-revealed > *:nth-child(2) { transition-delay: 0.07s; }
.is-revealed > *:nth-child(3) { transition-delay: 0.14s; }
.is-revealed > *:nth-child(n + 4) { transition-delay: 0.21s; }

/* The hairline draws with its section. */
.is-armed::before { transform: scaleX(0); }

.is-revealed::before {
  transform: scaleX(1);
  transition: transform 0.6s var(--ease-arrive);
}

/* The focal moment: the transformation proof arrives the way the pause
 * behaves — later, slower, and with more weight than anything around it.
 * Its resting tilt survives the entrance. */
.proof--focal.is-armed .phone {
  transform: translateY(28px) scale(0.965) rotate(-1.5deg);
}

.proof--focal.is-revealed .phone {
  transform: rotate(-1.5deg);
  transition:
    transform 0.7s var(--ease-arrive) 0.18s,
    opacity 0.4s ease-out 0.18s;
}

.proof--focal.is-revealed .phone {
  animation: focal-bloom 0.9s var(--ease-arrive) 0.18s backwards;
}

@keyframes focal-bloom {
  from {
    box-shadow:
      0 8px 16px rgba(0, 0, 0, 0.3),
      0 0 110px rgba(177, 209, 138, 0);
  }
  to {
    box-shadow:
      0 24px 48px rgba(0, 0, 0, 0.5),
      0 0 110px rgba(177, 209, 138, 0.28);
  }
}

/* The tilted phones keep their resting angle through the reveal — the slide
 * arrives into the tilt rather than flattening it. */
.is-armed .phone--crop { transform: translateY(18px) rotate(1.5deg); }

.is-revealed .phone--crop { transform: rotate(1.5deg); }

.is-armed .phone--practice { transform: translateY(18px) rotate(-1.5deg); }

.is-revealed .phone--practice { transform: rotate(-1.5deg); }

/* The loop appears as the list it is. */
.loop.is-revealed .loop-list li {
  animation: hero-rise 0.4s var(--ease-arrive) backwards;
}

.loop.is-revealed .loop-list li:nth-child(2) { animation-delay: 0.06s; }
.loop.is-revealed .loop-list li:nth-child(3) { animation-delay: 0.12s; }
.loop.is-revealed .loop-list li:nth-child(4) { animation-delay: 0.18s; }

/* A JS watchdog or a pre-scrolled load reveals with no transition at all —
 * never a half-faded frame. */
.is-instant > *,
.is-instant::before,
.is-instant .phone,
.is-instant .loop-list li {
  transition: none !important;
  animation: none !important;
}

/* Feedback on press, not release (DESIGN.md · Motion). */
.badge-link, .button {
  transition: transform 0.12s ease-out;
}

.badge-link:active, .button:active {
  transform: scale(0.97);
}

@media (prefers-reduced-motion: reduce) {
  /* Movement is replaced by a short cross-fade, never a slower slide. */
  .hero-copy, .hero .phone,
  .loop.is-revealed .loop-list li,
  .proof--focal.is-revealed .phone {
    animation: none;
  }
  .is-armed > *, .proof--focal.is-armed .phone { transform: none; }
  .is-armed .phone--crop, .is-revealed .phone--crop { transform: rotate(1.5deg); }
  .is-armed .phone--practice, .is-revealed .phone--practice { transform: rotate(-1.5deg); }
  .proof--focal.is-armed .phone, .proof--focal.is-revealed .phone { transform: rotate(-1.5deg); }
  .hero .phone--tall { animation: none; transform: rotate(2deg); }
  .is-armed::before { transform: none; }
  .is-revealed > *, .proof--focal.is-revealed .phone {
    transition: opacity 0.18s ease-out;
    transition-delay: 0s;
  }
  .is-revealed::before { transition: none; }
  .sticky-bar { transition: opacity 0.18s ease-out; transform: none; }
  .badge-link, .button { transition: none; }
  .badge-link:active, .button:active { transform: none; }
}

/* ——— wider screens: the adaptation, never the origin ——— */

@media (min-width: 700px) {
  /* Plus is the first card and the bigger one — the columns follow the DOM. */
  .plans { grid-template-columns: 1.3fr 1fr; }
  .hero {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    grid-template-areas: "lockup lockup" "copy phone";
    align-items: center;
    column-gap: var(--s48);
    max-width: 58rem;
    text-align: left;
  }
  .lockup { grid-area: lockup; justify-content: flex-start; }
  .hero-copy { grid-area: copy; }
  .hero .support { margin-left: 0; }
  .hero .phone { grid-area: phone; margin-top: 0; }
  .sticky-bar {
    left: auto;
    right: var(--s24);
    bottom: var(--s24);
    width: auto;
    max-width: max-content;
    border: 1px solid var(--hairline);
    border-radius: 999px;
    padding: var(--s8) var(--s8) var(--s8) var(--s16);
  }
  footer { padding-bottom: var(--s48); }
}

/* ——— desktop ≥1000px: copy beside device, sides alternating with the
 * tilts. Same DOM, same blocks — the grid places each child, spacer rows
 * center the copy against the phone. Nothing below 1000px changes. ——— */

@media (min-width: 1000px) {
  main > section { padding-top: var(--s64); padding-bottom: var(--s64); }

  section.proof {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    grid-template-rows: 1fr auto auto auto 1fr;
    grid-template-areas:
      ".      phone"
      "opener phone"
      "h2     phone"
      "aside  phone"
      ".      phone";
    column-gap: var(--s64);
    max-width: 62rem;
    text-align: left;
  }

  section.proof > .opener { grid-area: opener; }
  section.proof > h2 { grid-area: h2; }
  section.proof > .aside { grid-area: aside; margin-left: 0; margin-right: 0; }
  section.proof > .phone {
    grid-area: phone;
    align-self: center;
    justify-self: center;
    margin: 0;
  }

  section.proof--alt {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    grid-template-areas:
      "phone ."
      "phone opener"
      "phone h2"
      "phone aside"
      "phone .";
  }

  /* Desktop devices size from the viewport's HEIGHT, not their width — a
   * short, wide browser window must still fit a section on one screen.
   * aspect-ratio derives the width from the capped height. */
  section.proof .phone { width: fit-content; }

  section.proof .phone img {
    width: auto;
    height: min(560px, 72vh);
  }

  .hero .phone--tall {
    width: fit-content;
    margin-top: 0;
    justify-self: center;
  }

  .hero .phone--tall img {
    width: auto;
    height: min(600px, 74vh);
  }

  /* The loop reads left to right: the four words, then their sum. */
  section.loop {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: center;
    column-gap: var(--s64);
    max-width: 60rem;
    text-align: left;
  }

  section.loop .loop-list { margin: 0; }

  section.loop .loop-sentence { margin: 0; }
}

/* ——— desktop ≥1200px: the hero fills its room ——— */

@media (min-width: 1200px) {
  .hero {
    max-width: 64rem;
    column-gap: var(--s64);
    padding-top: var(--s48);
  }

  .hero h1 { font-size: 4rem; }
}

/* ——— fallback: browsers without aspect-ratio support ———
 *
 * The device crops are windows: a fixed-aspect figure over a taller
 * screenshot, object-position choosing the visible span. Without
 * aspect-ratio the figure collapses to natural flow and the "window"
 * becomes nonsense. In that case, show the whole screen instead of a
 * broken crop — longer, but correct. */

@supports not (aspect-ratio: 9 / 16) {
  .phone img {
    aspect-ratio: auto !important;
    height: auto !important;
    object-fit: fill;
  }

  .phone--tall::after { display: none; }
}
