/* ==========================================================================
   Cadence — marketing site
   "Asteroid City" + "Golden hour" + "The Table", ported from the app.

   Every token below is lifted from src/constants/theme.ts rather than eyeballed,
   so the site and the product are the same object. Two rules from the app carry
   over verbatim because the whole material system leans on them:

   1. Instrument Serif has TWO jobs and the split is load-bearing. UPRIGHT is the
      voice of a standalone number. ITALIC (.hand) is reserved exclusively for
      words a partner actually typed. Site copy never renders in the italic.
   2. Icons are SVG, never text glyphs or emoji. Emoji in *content* is fine.

   Colour: module `ink` values are the AA-safe text variants, measured against the
   harder of each scheme's two neutral surfaces. Never use `main` for text.
   ========================================================================== */

/* --------------------------------------------------------------- tokens -- */
:root {
  color-scheme: light dark;

  --ink: #22332f;
  --sand: #f5efdf;
  --cream: #fcf8ec;
  --muted: #eae2cc;
  --ink-2: #6d6b54;
  --ink-tint: #5f5d49;
  --label-ink: #57553f;
  --accent: #2a6f68;
  --accent-soft: #d8e9e4;
  --line: #e0d7be;
  --line-control: #8a8267;
  --success: #75943f;
  --danger: #b33a1c;
  --on-accent: #ffffff;
  --paper: #fcf8ec;

  /* Dusk is a fixed brand surface: identical in both schemes, exactly as in the
     app, because the cat art is keyed to composite onto this one value. */
  --dusk: #132f32;
  --dusk-deep: #0d2225;
  --dusk-ink: #f5efdf;
  --dusk-ink-soft: #a9c0bb;
  --dusk-line: #2c4744;

  --m-daily: #297770;
  --m-checkin: #9e5839;
  --m-decide: #ba4223;
  --m-goals: #5b7331;
  --m-lists: #816830;
  --m-together: #9a5b3c;
  --m-personal: #55707a;
  --m-budget: #826643;

  --m-daily-soft: #dcede9;
  --m-checkin-soft: #f2e0d3;
  --m-decide-soft: #f6ddd2;
  --m-goals-soft: #e5ead2;
  --m-lists-soft: #f0e6cc;
  --m-together-soft: #efdfd2;
  --m-personal-soft: #dee7ea;
  --m-budget-soft: #efe4d2;

  --shadow-card: 0 3px 12px rgba(90, 70, 40, 0.07);
  --shadow-float: 0 6px 18px rgba(90, 70, 40, 0.14);
  /* The Table's light law: one lamp upper-left, so a cast shadow offsets down AND
     right, never symmetrically. Only paper casts one. */
  --shadow-paper: 3px 7px 10px rgba(34, 51, 47, 0.13);
  --shadow-paper-dusk: 2px 5px 8px rgba(8, 22, 24, 0.45);

  --r-chip: 12px;
  --r-md: 14px;
  --r-lg: 16px;
  --r-card: 20px;
  --r-panel: 24px;
  --r-panel-lg: 28px;
  --r-pill: 999px;

  --f-display: 'Nunito', ui-rounded, 'Segoe UI', system-ui, sans-serif;
  --f-body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --f-serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;

  --gutter: clamp(16px, 5vw, 40px);
  --wrap: 1140px;
  --section-y: clamp(64px, 9vw, 128px);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --ink: #f1ecda;
    --sand: #161f1e;
    --cream: #1d2927;
    --muted: #25332f;
    --ink-2: #93917f;
    --ink-tint: #b9b7a2;
    --label-ink: #a3a18d;
    --accent: #54b3a6;
    --accent-soft: #1c3531;
    --line: #2c3a36;
    --line-control: #6e8078;
    --success: #8fae5a;
    --danger: #e4714f;
    /* A filled accent button in dark mode is a BRIGHT teal, so its label flips to
       dark ink. White on #54B3A6 measures 2.51:1. This is 6.7:1. */
    --on-accent: #10201e;
    --paper: #202b29;

    --m-daily: #3aa79e;
    --m-checkin: #c67d5d;
    --m-decide: #e36b4c;
    --m-goals: #7b9847;
    --m-lists: #b99444;
    --m-together: #b3846d;
    --m-personal: #7b949d;
    --m-budget: #ac895e;

    --m-daily-soft: #17302c;
    --m-checkin-soft: #33231b;
    --m-decide-soft: #34201a;
    --m-goals-soft: #242b18;
    --m-lists-soft: #2e2718;
    --m-together-soft: #2e211a;
    --m-personal-soft: #20302f;
    --m-budget-soft: #2e2619;

    --shadow-card: 0 3px 12px rgba(0, 0, 0, 0.3);
    --shadow-float: 0 6px 18px rgba(0, 0, 0, 0.42);
    --shadow-paper: 3px 7px 12px rgba(0, 0, 0, 0.42);
  }
}

:root[data-theme='dark'] {
  --ink: #f1ecda;
  --sand: #161f1e;
  --cream: #1d2927;
  --muted: #25332f;
  --ink-2: #93917f;
  --ink-tint: #b9b7a2;
  --label-ink: #a3a18d;
  --accent: #54b3a6;
  --accent-soft: #1c3531;
  --line: #2c3a36;
  --line-control: #6e8078;
  --success: #8fae5a;
  --on-accent: #10201e;
  --danger: #e4714f;
  --paper: #202b29;

  --m-daily: #3aa79e;
  --m-checkin: #c67d5d;
  --m-decide: #e36b4c;
  --m-goals: #7b9847;
  --m-lists: #b99444;
  --m-together: #b3846d;
  --m-personal: #7b949d;
  --m-budget: #ac895e;

  --m-daily-soft: #17302c;
  --m-checkin-soft: #33231b;
  --m-decide-soft: #34201a;
  --m-goals-soft: #242b18;
  --m-lists-soft: #2e2718;
  --m-together-soft: #2e211a;
  --m-personal-soft: #20302f;
  --m-budget-soft: #2e2619;

  --shadow-card: 0 3px 12px rgba(0, 0, 0, 0.3);
  --shadow-float: 0 6px 18px rgba(0, 0, 0, 0.42);
  --shadow-paper: 3px 7px 12px rgba(0, 0, 0, 0.42);
}

/* ---------------------------------------------------------------- base -- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--sand);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 17px;
  line-height: 1.65;
  font-weight: 450;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
svg {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a:hover {
  text-decoration: none;
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection {
  background: var(--accent-soft);
  color: var(--ink);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--accent);
  color: var(--on-accent);
  padding: 12px 20px;
  border-radius: 0 0 var(--r-md) 0;
  font-family: var(--f-display);
  font-weight: 700;
}

.skip:focus {
  left: 0;
}

.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ----------------------------------------------------------- typography -- */
h1,
h2,
h3,
h4 {
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0 0 0.4em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(38px, 6.2vw, 66px);
  line-height: 1.06;
  letter-spacing: -0.03em;
}

h2 {
  font-size: clamp(28px, 4.2vw, 44px);
  line-height: 1.12;
}

h3 {
  font-size: clamp(20px, 2.4vw, 25px);
  line-height: 1.25;
  font-weight: 700;
}

h4 {
  font-size: 18px;
  line-height: 1.3;
  font-weight: 700;
}

p {
  margin: 0 0 1.1em;
  text-wrap: pretty;
}

p:last-child {
  margin-bottom: 0;
}

.lede {
  font-size: clamp(18px, 2.1vw, 21px);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 54ch;
}

.dim {
  color: var(--ink-2);
}

.eyebrow {
  font-family: var(--f-body);
  font-weight: 600;
  font-size: 12px;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--label-ink);
  margin: 0 0 14px;
  display: block;
}

/* The label device of The Table: small, tracked, uppercase, display face. It
   appears as a hero eyebrow, a section masthead, and a chart axis, nowhere else. */
.label {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--label-ink);
}

/* Upright serif: the voice of every standalone number in the app. */
.num {
  font-family: var(--f-serif);
  font-weight: 400;
  letter-spacing: -0.01em;
  font-variant-numeric: lining-nums tabular-nums;
}

/* Italic serif: ONLY words a partner actually typed. Never site copy. */
.hand {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 1.12em;
  line-height: 1.45;
  letter-spacing: 0.005em;
}

/* --------------------------------------------------------------- layout -- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap--narrow {
  max-width: 760px;
}

.wrap--mid {
  max-width: 920px;
}

.section {
  padding-block: var(--section-y);
}

.section--tight {
  padding-block: clamp(44px, 6vw, 84px);
}

.section--flush-top {
  padding-top: 0;
}

.center {
  text-align: center;
}

.center .lede,
.center .stack {
  margin-inline: auto;
}

.stack > * + * {
  margin-top: 18px;
}

.head {
  max-width: 62ch;
  margin-bottom: clamp(36px, 5vw, 60px);
}

.center .head {
  margin-inline: auto;
}

.rule {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 0;
}

/* --------------------------------------------------------------- buttons -- */
.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--on-accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 14px 28px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 16px;
  line-height: 1;
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.16s ease, box-shadow 0.16s ease, background 0.16s ease;
  box-shadow: var(--shadow-card);
}

.btn:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-float);
}

.btn:active {
  transform: translateY(0) scale(0.985);
}

.btn svg {
  flex: none;
}

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  box-shadow: none;
  border: 1.5px solid var(--line-control);
}

.btn--ghost:hover {
  background: var(--muted);
  box-shadow: none;
  transform: translateY(-2px);
}

.btn--on-dusk {
  --btn-bg: var(--dusk-ink);
  --btn-fg: var(--dusk);
}

.btn--ghost-dusk {
  --btn-bg: transparent;
  --btn-fg: var(--dusk-ink);
  border: 1.5px solid rgba(245, 239, 223, 0.42);
  box-shadow: none;
}

.btn--ghost-dusk:hover {
  background: rgba(245, 239, 223, 0.1);
  box-shadow: none;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.center .btn-row {
  justify-content: center;
}

.btn-note {
  font-size: 14px;
  color: var(--ink-2);
  margin: 14px 0 0;
}

.dusk .btn-note {
  color: var(--dusk-ink-soft);
}

/* ---------------------------------------------------------------- chips -- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  background: var(--muted);
  color: var(--ink-tint);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.2;
}

.chip svg {
  flex: none;
  color: var(--accent);
}

.chip--dusk {
  background: rgba(245, 239, 223, 0.1);
  color: var(--dusk-ink);
  border: 1px solid rgba(245, 239, 223, 0.16);
}

.chip--dusk svg {
  color: var(--dusk-ink-soft);
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* ---------------------------------------------------------------- cards -- */
.card {
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: clamp(22px, 3vw, 30px);
}

.card--flat {
  box-shadow: none;
}

.card h3 {
  margin-bottom: 8px;
}

.card p {
  color: var(--ink-2);
  font-size: 16px;
}

/* Paper carries words a partner wrote. It is the only thing that casts a shadow,
   and its edges are torn rather than cut. */
.paper {
  position: relative;
  /* Paper carries page ink wherever it lies. Without this it inherits the dusk
     band's cream text colour and renders cream on cream. */
  color: var(--ink);
  background: var(--paper);
  border-radius: 3px;
  padding: clamp(24px, 3.4vw, 36px);
  box-shadow: var(--shadow-paper);
  /* The tear is a MASK, not a coloured background image. A baked fill would stay
     light cream on a dark sheet the moment the site flips scheme, so the shape is
     punched out of `--paper` instead and follows the surface automatically.
     The path must run the full 240px of its tile and end at the height it
     starts, 4.2. The first version stopped at 200, so every sheet on the site
     had a 40px hole in its torn edge every 240px. */
  --tear: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='9' viewBox='0 0 240 9' preserveAspectRatio='none'%3E%3Cpath d='M0 9V4.2c8-.5 12 1.3 20 .9s12-2.6 20-2.4 12 2.9 20 2.6 12-3.1 20-3 12 2.4 20 2.2 12-2.7 20-2.5 12 3 20 3.1 12-2.3 20-2.6 12 2.2 20 2.4 12-1.8 20-1.4 12 2.6 20 2.3 12-2.2 20-1.6V9z' fill='%23000'/%3E%3C/svg%3E");
}

.paper::before,
.paper::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 9px;
  background: var(--paper);
  -webkit-mask: var(--tear) repeat-x;
  mask: var(--tear) repeat-x;
  -webkit-mask-size: 240px 9px;
  mask-size: 240px 9px;
}

.paper::before {
  top: -8px;
  transform: scaleY(-1);
}

.paper::after {
  bottom: -8px;
}

.dusk .paper {
  box-shadow: var(--shadow-paper-dusk);
}

/* Ledger carries goals, money and schedules. No container, no radius, no tint.
   Colour is permitted in a data mark only, never a row background. */
.ledger {
  margin: 0;
}

.ledger__rule {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 8px;
  margin-bottom: 4px;
}

.ledger__row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 20px;
  align-items: baseline;
  padding: 15px 0;
  border-bottom: 1px solid var(--line);
}

.ledger__row:last-child {
  border-bottom: 0;
}

.ledger__label {
  font-weight: 600;
  font-size: 16px;
}

.ledger__sub {
  grid-column: 1 / -1;
  color: var(--ink-2);
  font-size: 15px;
  margin: 2px 0 0;
  max-width: 60ch;
}

.ledger__figure {
  font-family: var(--f-serif);
  font-size: 21px;
  line-height: 1;
  color: var(--ink);
  white-space: nowrap;
  font-variant-numeric: lining-nums tabular-nums;
}

/* A figure is normally a number and never wraps. /privacy puts a short phrase in
   that slot, and on a phone nowrap pushed it 18px past the screen edge. A number
   has no spaces, so letting the slot wrap on small screens only ever moves words. */
@media (max-width: 560px) {
  .ledger__figure {
    white-space: normal;
    text-align: right;
  }
}

.ledger__mark {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-right: 9px;
  vertical-align: 1px;
}

/* ----------------------------------------------------------------- dusk -- */
/* The dusk panel's bottom edge is SQUARE and full bleed, with no shadow, so it
   reads as the surface the page rests on rather than a banner that ended. */
.dusk {
  position: relative;
  background: var(--dusk);
  color: var(--dusk-ink);
}

.dusk h1,
.dusk h2,
.dusk h3,
.dusk h4 {
  color: var(--dusk-ink);
}

.dusk .lede,
.dusk .dim {
  color: var(--dusk-ink-soft);
}

.dusk .eyebrow,
.dusk .label {
  color: var(--dusk-ink-soft);
}

.dusk a {
  color: var(--dusk-ink);
}

/* A button is a button first. Without this, the blanket link colour above wins
   on specificity and paints a cream label onto a cream pill. */
.dusk a.btn,
.footer a.btn,
.cta a.btn {
  color: var(--btn-fg);
}

.dusk .rule {
  border-color: var(--dusk-line);
}

.dusk--deep {
  background: var(--dusk-deep);
}

/* One object may lap over the square seam and drop its shadow on the dark. It
   sits AFTER the dusk section, not inside it, so the dark edge it laps is a real
   edge and the shadow it drops lands on the dark rather than on its own surface. */
.seam {
  position: relative;
  z-index: 2;
  margin-top: -72px;
}

@media (max-width: 720px) {
  .seam {
    margin-top: -48px;
  }
}

/* ----------------------------------------------------------------- nav -- */
.nav {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(19, 47, 50, 0.93);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease;
}

.nav[data-stuck='true'] {
  border-bottom-color: var(--dusk-line);
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 18px;
  min-height: 70px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  color: var(--dusk-ink);
  font-family: var(--f-display);
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -0.02em;
  margin-right: auto;
}

.brand img {
  width: 34px;
  height: 34px;
  border-radius: 9px;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 4px;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* :not(.btn) on both of these is load-bearing. A nav link rule is two classes
   deep, so it outranks .btn--on-dusk and would paint the call to action's label
   in dusk-ink-soft on its own cream pill, at about 1.6:1. */
.nav__links a:not(.btn) {
  display: inline-block;
  padding: 9px 14px;
  border-radius: var(--r-pill);
  color: var(--dusk-ink-soft);
  text-decoration: none;
  font-size: 15px;
  font-weight: 600;
  transition: color 0.15s ease, background 0.15s ease;
}

.nav__links a:not(.btn):hover,
.nav__links a:not(.btn)[aria-current='page'] {
  color: var(--dusk-ink);
  background: rgba(245, 239, 223, 0.09);
}

.nav .btn {
  min-height: 44px;
  padding: 11px 20px;
  font-size: 15px;
}

.nav__toggle,
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(245, 239, 223, 0.2);
  background: transparent;
  color: var(--dusk-ink);
  cursor: pointer;
  flex: none;
}

.nav__toggle:hover,
.theme-toggle:hover {
  background: rgba(245, 239, 223, 0.1);
}

.nav__toggle {
  display: none;
}

.theme-toggle .icon-moon {
  display: none;
}

:root[data-theme='dark'] .theme-toggle .icon-moon {
  display: block;
}

:root[data-theme='dark'] .theme-toggle .icon-sun {
  display: none;
}

@media (max-width: 900px) {
  .nav__toggle {
    display: inline-flex;
  }

  .nav__links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 10px var(--gutter) 22px;
    background: var(--dusk);
    border-bottom: 1px solid var(--dusk-line);
    display: none;
  }

  .nav[data-open='true'] .nav__links {
    display: flex;
  }

  .nav__links a:not(.btn) {
    padding: 13px 14px;
    font-size: 17px;
  }

  .nav__cta {
    display: none;
  }

  .nav__links .btn {
    margin-top: 10px;
    width: 100%;
  }
}

/* ----------------------------------------------------------------- hero -- */
.hero {
  position: relative;
  padding-block: clamp(52px, 7vw, 92px) clamp(120px, 13vw, 190px);
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(28px, 5vw, 64px);
  align-items: center;
}

.hero__art {
  position: relative;
}

.hero__art img {
  width: 100%;
  max-width: 560px;
  margin-inline: auto;
}

.hero h1 {
  margin-bottom: 0.32em;
}

.hero .lede {
  color: var(--dusk-ink-soft);
  max-width: 46ch;
  margin-bottom: 30px;
}

.hero__stars {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.55;
}

@media (max-width: 880px) {
  .hero__grid {
    grid-template-columns: 1fr;
    text-align: center;
  }

  .hero .lede {
    margin-inline: auto;
  }

  .hero .btn-row {
    justify-content: center;
  }

  .hero__art {
    order: -1;
  }

  .hero__art img {
    max-width: 380px;
  }
}

/* --------------------------------------------------------------- proof -- */
.proof {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 12px;
  padding-block: 0 clamp(40px, 5vw, 64px);
}

/* --------------------------------------------------------------- grids -- */
.grid {
  display: grid;
  gap: clamp(14px, 1.8vw, 22px);
}

.grid--2 {
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
}

.grid--3 {
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}

.grid--4 {
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
}

/* ---------------------------------------------------------- module card -- */
/* Cupla-style colour coding: each module owns a hue, used as an eyebrow, a left
   border strip and a tinted plate behind its art. Never as body-text colour. */
.mod {
  --mod: var(--accent);
  --mod-soft: var(--accent-soft);
  position: relative;
  background: var(--cream);
  border: 1px solid var(--line);
  border-left: 3px solid var(--mod);
  border-radius: var(--r-card);
  padding: clamp(20px, 2.6vw, 28px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.mod:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-card);
}

.mod__plate {
  border-radius: var(--r-lg);
  background: var(--mod-soft);
  overflow: hidden;
  aspect-ratio: 16 / 9;
}

.mod__plate img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.mod .eyebrow {
  color: var(--mod);
  margin: 0;
}

.mod h3 {
  margin: 0;
}

.mod p {
  margin: 0;
  color: var(--ink-2);
  font-size: 15.5px;
  line-height: 1.6;
}

.mod[data-mod='daily'] { --mod: var(--m-daily); --mod-soft: var(--m-daily-soft); }
.mod[data-mod='checkin'] { --mod: var(--m-checkin); --mod-soft: var(--m-checkin-soft); }
.mod[data-mod='decide'] { --mod: var(--m-decide); --mod-soft: var(--m-decide-soft); }
.mod[data-mod='goals'] { --mod: var(--m-goals); --mod-soft: var(--m-goals-soft); }
.mod[data-mod='lists'] { --mod: var(--m-lists); --mod-soft: var(--m-lists-soft); }
.mod[data-mod='together'] { --mod: var(--m-together); --mod-soft: var(--m-together-soft); }
.mod[data-mod='personal'] { --mod: var(--m-personal); --mod-soft: var(--m-personal-soft); }
.mod[data-mod='budget'] { --mod: var(--m-budget); --mod-soft: var(--m-budget-soft); }

/* --------------------------------------------------------------- split -- */
/* Every auto-fit grid caps its minimum track at 100%. A bare minmax(320px)
   cannot fit a 320px phone, whose content box is 288px, and it widened the page. */
.split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: clamp(28px, 5vw, 72px);
  align-items: center;
}

.split--reverse .split__art {
  order: -1;
}

.split__art {
  position: relative;
}

.split__plate {
  border-radius: var(--r-panel);
  overflow: hidden;
  background: var(--dusk);
  border: 1px solid var(--dusk-line);
}

.split__plate img {
  width: 100%;
}

.split__plate--sand {
  background: var(--sand);
  border-color: var(--line);
}

@media (max-width: 760px) {
  .split--reverse .split__art {
    order: 0;
  }
}

/* --------------------------------------------------------------- steps -- */
.steps {
  counter-reset: step;
  display: grid;
  gap: clamp(16px, 2vw, 24px);
  grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}

.steps li {
  position: relative;
  padding-top: 58px;
}

.steps li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  top: 0;
  left: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--f-serif);
  font-size: 22px;
  line-height: 1;
}

.dusk .steps li::before {
  background: rgba(245, 239, 223, 0.12);
  color: var(--dusk-ink);
}

.steps h3 {
  margin-bottom: 6px;
}

.steps p {
  color: var(--ink-2);
  font-size: 16px;
  margin: 0;
}

.dusk .steps p {
  color: var(--dusk-ink-soft);
}

/* ------------------------------------------------------------ the demo -- */
/* The reveal is the product's core mechanic, so the site performs it instead of
   describing it: both answers stay sealed until the visitor has "answered" too. */
.reveal {
  display: grid;
  gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
  margin-top: 30px;
}

.reveal__card {
  position: relative;
  min-height: 190px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 10px;
}

.reveal__who {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-tint);
}

.reveal__dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--m-daily);
}

.reveal__dot--b {
  background: var(--m-checkin);
}

.reveal__text {
  margin: 0;
  color: var(--ink);
}

.reveal__sealed {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 12px;
  flex: 1;
  color: var(--ink-2);
  font-size: 15px;
}

.reveal__sealed svg {
  color: var(--line-control);
}

.reveal__card[data-state='open'] .reveal__sealed {
  display: none;
}

.reveal__card[data-state='sealed'] .reveal__body {
  display: none;
}

.reveal__body {
  animation: rise 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ----------------------------------------------------------------- faq -- */
.faq {
  border-top: 1px solid var(--line);
}

.faq details {
  border-bottom: 1px solid var(--line);
}

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: clamp(17px, 2vw, 19px);
  line-height: 1.35;
  color: var(--ink);
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: '';
  flex: none;
  width: 13px;
  height: 13px;
  border-right: 2px solid var(--ink-2);
  border-bottom: 2px solid var(--ink-2);
  transform: rotate(45deg) translateY(-3px);
  transition: transform 0.2s ease;
}

.faq details[open] summary::after {
  transform: rotate(225deg) translateY(-3px);
}

.faq__body {
  padding: 0 0 24px;
  max-width: 68ch;
  color: var(--ink-2);
}

.faq__body p {
  margin-bottom: 0.8em;
}

/* ---------------------------------------------------------------- band -- */
.band {
  position: relative;
  overflow: hidden;
}

.band__img {
  width: 100%;
  display: block;
  object-fit: cover;
  max-height: 46vh;
}

.band--walk {
  background: #2a4650;
}

/* A generated band never lands on the exact brand colour, so where one meets a
   flat surface it gets a short fade into it rather than a visible step. This is
   the same move the app makes at the bottom of its home hero. */
.band--fade-to-dusk::after,
.band--fade-to-sand::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 34%;
  pointer-events: none;
}

.band--fade-to-dusk::after {
  background: linear-gradient(to bottom, rgba(19, 47, 50, 0), var(--dusk));
}

.band--fade-to-sand::after {
  background: linear-gradient(to bottom, rgba(245, 239, 223, 0), var(--sand));
}

:root[data-theme='dark'] .band--fade-to-sand::after {
  background: linear-gradient(to bottom, rgba(22, 31, 30, 0), var(--sand));
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) .band--fade-to-sand::after {
    background: linear-gradient(to bottom, rgba(22, 31, 30, 0), var(--sand));
  }
}

/* ---------------------------------------------------------------- quote -- */
.note {
  display: grid;
  gap: 14px;
}

.note__meta {
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-tint);
}

/* ---------------------------------------------------------------- prose -- */
.prose {
  font-size: 17px;
}

.prose h2 {
  font-size: clamp(23px, 2.6vw, 28px);
  margin-top: 2em;
  margin-bottom: 0.5em;
  color: var(--accent);
}

.prose h2:first-of-type {
  margin-top: 1em;
}

.prose h3 {
  font-size: 19px;
  margin-top: 1.7em;
  margin-bottom: 0.4em;
}

.prose ul,
.prose ol {
  padding-left: 1.3em;
  margin: 0 0 1.2em;
}

.prose li {
  margin-bottom: 0.55em;
}

.prose li::marker {
  color: var(--accent);
}

.prose strong {
  font-weight: 650;
  color: var(--ink);
}

.prose > p,
.prose li {
  color: var(--ink-2);
}

.prose blockquote {
  margin: 1.4em 0;
  padding: 18px 22px;
  border-left: 3px solid var(--accent);
  background: var(--cream);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}

.prose blockquote p {
  margin: 0;
}

.toc {
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: 22px 26px;
  margin-bottom: 36px;
}

.toc ol {
  margin: 0;
  padding-left: 1.2em;
  columns: 2;
  column-gap: 32px;
}

.toc li {
  margin-bottom: 6px;
  break-inside: avoid;
}

@media (max-width: 560px) {
  .toc ol {
    columns: 1;
  }
}

/* --------------------------------------------------------------- footer -- */
.footer {
  background: var(--dusk-deep);
  color: var(--dusk-ink);
  padding-block: clamp(48px, 6vw, 76px) 36px;
}

.footer a {
  color: var(--dusk-ink-soft);
  text-decoration: none;
}

.footer a:hover {
  color: var(--dusk-ink);
  text-decoration: underline;
}

.footer__top {
  display: grid;
  grid-template-columns: minmax(240px, 1.4fr) repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: 36px 28px;
  padding-bottom: 40px;
}

/* auto-fit always keeps at least one 150px track beside the 240px brand
   column, so below about 420px that grid cannot fit at all, and on a phone it
   pushed every page 60px wider than the screen. Two plain columns instead. */
@media (max-width: 640px) {
  .footer__top {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 30px 20px;
  }

  .footer__brand {
    grid-column: 1 / -1;
  }
}

.footer__brand p {
  color: var(--dusk-ink-soft);
  font-size: 15px;
  max-width: 34ch;
  margin-top: 14px;
}

.footer h4 {
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--dusk-ink-soft);
  margin-bottom: 14px;
  font-weight: 700;
}

.footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
  font-size: 15px;
}

.footer__bottom {
  border-top: 1px solid var(--dusk-line);
  padding-top: 28px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  color: var(--dusk-ink-soft);
}

/* ------------------------------------------------------------- reveal on
   scroll. It must degrade to "visible" if the script never runs: the app
   learned this the hard way when a web animation left elements permanently
   hidden. Two guards make that true here.

   1. The hidden state only applies under html.js, which a one-line inline
      script in each page's head sets, so a page with scripts off shows
      everything.
   2. Under html.js but BEFORE site.js has run (html:not(.motion-ready)), a
      zero-length failsafe animation fires at 2.5s and pins everything visible.
      site.js adds .motion-ready the moment it starts, which removes the
      failsafe and hands control to the scroll observer. If site.js is blocked,
      slow or throws on load, the page still appears.

   Motion uses the individual translate and scale properties, never transform,
   so it composes with the pointer tilt, which owns transform. -- */
@keyframes failsafe-show {
  to {
    opacity: 1;
    translate: none;
    scale: none;
  }
}

.js [data-rise],
.js [data-enter] {
  opacity: 0;
  translate: 0 22px;
  transition: opacity 0.8s cubic-bezier(0.2, 0.7, 0.2, 1), translate 0.9s cubic-bezier(0.2, 0.7, 0.2, 1),
    scale 0.9s cubic-bezier(0.2, 0.7, 0.2, 1);
}

html.js:not(.motion-ready) [data-rise],
html.js:not(.motion-ready) [data-enter] {
  animation: failsafe-show 0s 2.5s forwards;
}

.js [data-rise='left'] {
  translate: -26px 0;
}

.js [data-rise='right'] {
  translate: 26px 0;
}

.js [data-rise='scale'] {
  translate: 0 30px;
  scale: 0.94;
}

.js [data-rise].is-in,
.js [data-enter].is-in {
  opacity: 1;
  translate: none;
  scale: none;
}

@media (prefers-reduced-motion: reduce) {
  .js [data-rise],
  .js [data-enter] {
    opacity: 1;
    translate: none;
    scale: none;
  }
}

/* --------------------------------------------------------------- phones -- */
.phone {
  position: relative;
  border-radius: 40px;
  padding: 10px;
  background: linear-gradient(160deg, #2f4a48, #101f22);
  box-shadow: var(--shadow-float);
  width: 100%;
  max-width: 300px;
}

.phone img {
  width: 100%;
  border-radius: 31px;
  display: block;
  background: var(--sand);
}

.phone::after {
  content: '';
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  width: 34%;
  height: 22px;
  border-radius: var(--r-pill);
  background: #101f22;
}

.phones {
  display: flex;
  gap: clamp(14px, 2.5vw, 26px);
  justify-content: center;
  align-items: flex-start;
}

/* The stagger is a margin, not a transform: transform belongs to the pointer
   tilt, and translate to the scroll reveal. */
.phones .phone:nth-child(even) {
  margin-top: 36px;
}

@media (max-width: 620px) {
  .phones {
    flex-wrap: wrap;
  }

  .phones .phone:nth-child(even) {
    margin-top: 0;
  }
}

/* ------------------------------------------------------------- cta band -- */
.cta {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding-block: clamp(64px, 8vw, 110px);
}

.cta__art {
  width: min(320px, 70%);
  margin: 0 auto 26px;
}

/* ------------------------------------------------------------- stat row -- */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: clamp(18px, 3vw, 36px);
}

.stat__figure {
  font-family: var(--f-serif);
  font-size: clamp(36px, 5vw, 52px);
  line-height: 1;
  display: block;
  margin-bottom: 8px;
  font-variant-numeric: lining-nums tabular-nums;
}

.stat__label {
  font-size: 15px;
  color: var(--ink-2);
  line-height: 1.45;
}

.dusk .stat__label {
  color: var(--dusk-ink-soft);
}

/* --------------------------------------------------------------- misc -- */
.pill-note {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 9px 18px 9px 12px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 22px;
}

.dusk .pill-note {
  background: rgba(245, 239, 223, 0.12);
  color: var(--dusk-ink);
}

.pill-note svg {
  flex: none;
}

.callout {
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-card) var(--r-card) 0;
  background: var(--cream);
  padding: 22px 26px;
}

.callout p:last-child {
  margin-bottom: 0;
}

/* ==========================================================================
   Page-level compositions
   ========================================================================== */

/* --------------------------------------------------------- launch form -- */
/* There is no waitlist backend, so the "form" is a mailto. It keeps the shape a
   visitor expects without pretending to store an address it cannot store. */
.launch {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-top: 26px;
}

.store-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 20px;
  border-radius: var(--r-pill);
  border: 1px solid var(--dusk-line);
  background: var(--dusk-deep);
  color: var(--dusk-ink-soft);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: -0.01em;
}

.store-pill svg {
  flex: none;
}

/* ------------------------------------------------------------- ticker -- */
/* The live Together counter is the most screenshot-worthy thing in the product,
   so the page runs one rather than describing it. The date is a fixed demo, never
   the visitor's clock, and the strip is labelled as a demo. */
.ticker {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: clamp(22px, 3vw, 34px) 0;
}

.ticker__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 8px 18px;
}

.ticker__figure {
  font-family: var(--f-serif);
  font-size: clamp(30px, 5vw, 46px);
  line-height: 1.1;
  font-variant-numeric: lining-nums tabular-nums;
  white-space: nowrap;
}

.ticker__word {
  font-family: var(--f-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--label-ink);
}

.ticker__demo {
  font-size: 12px;
  color: var(--ink-2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* -------------------------------------------------------- paper sheets -- */
/* Two registers meet here. A sheet holds words a person wrote, so it is the only
   thing that tilts and the only thing that casts a shadow. */
.sheets {
  display: grid;
  gap: 18px;
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
}

.sheet {
  position: relative;
}

.sheet--tilt-l {
  transform: rotate(-1.5deg);
}

.sheet--tilt-r {
  transform: rotate(2deg);
}

.sheet__cap {
  display: block;
  margin-top: 14px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.dusk .sheet__cap {
  color: var(--dusk-ink-soft);
}

.sheet__sealed {
  display: flex;
  align-items: center;
  gap: 11px;
  color: var(--ink-2);
  font-size: 15px;
}

.sheet__sealed svg {
  flex: none;
  color: var(--line-control);
}

/* ------------------------------------------------------------ dusk band -- */
.band-dusk {
  position: relative;
  background: var(--dusk);
  color: var(--dusk-ink);
  overflow: hidden;
}

.band-dusk__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: clamp(26px, 5vw, 60px);
  align-items: center;
}

@media (max-width: 820px) {
  .band-dusk__grid {
    grid-template-columns: 1fr;
  }
}

/* The seam: sand above, dusk below, so a section can arrive rather than start. */
.seam-band {
  height: clamp(54px, 7vw, 92px);
  background: linear-gradient(to bottom, var(--sand), var(--dusk));
}

.seam-band--up {
  background: linear-gradient(to bottom, var(--dusk), var(--sand));
}

/* ------------------------------------------------------------ the loop -- */
.loop {
  --dot: 46px;
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: beat;
}

/* The rail: a hairline through the centre of every number, and a teal fill
   that site.js grows as the reader moves through the week. */
.loop::before,
.loop__fill {
  content: '';
  position: absolute;
  left: calc(var(--dot) / 2 - 1px);
  /* site.js measures the first and last dot centres into these. */
  top: var(--rt, 40px);
  bottom: var(--rb, 40px);
  width: 2px;
  border-radius: 2px;
  background: var(--line);
}

.loop__fill {
  background: var(--accent);
  transform-origin: top;
  transform: scaleY(var(--fill, 0));
}

.loop li {
  position: relative;
  display: grid;
  grid-template-columns: var(--dot) 1fr;
  gap: 4px 22px;
  align-items: center;
  padding: 18px 0;
}

.loop li::before {
  counter-increment: beat;
  content: counter(beat);
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--sand);
  border: 1.5px solid var(--line);
  font-family: var(--f-serif);
  font-size: 24px;
  line-height: 1;
  color: var(--accent);
  transition: background 0.4s ease, color 0.4s ease, border-color 0.4s ease, scale 0.4s cubic-bezier(0.3, 1.6, 0.5, 1);
}

.loop li.is-active::before,
.loop li.is-past::before {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.loop li.is-active::before {
  scale: 1.12;
}

.loop h3 {
  margin: 0 0 4px;
  font-size: 19px;
}

.loop p {
  margin: 0;
  color: var(--ink-2);
  font-size: 16px;
  max-width: 64ch;
}

@media (max-width: 560px) {
  .loop {
    --dot: 38px;
  }

  .loop li {
    gap: 4px 14px;
  }

  .loop li::before {
    font-size: 20px;
  }
}

/* ------------------------------------------------------- module groups -- */
.mod-group + .mod-group {
  margin-top: clamp(40px, 5vw, 64px);
}

.mod-group__head {
  display: flex;
  align-items: center;
  gap: 16px;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 12px;
  margin-bottom: 22px;
}

.mod-group__mark {
  width: 54px;
  height: 36px;
  border-radius: 9px;
  overflow: hidden;
  flex: none;
  border: 1px solid var(--line);
}

.mod-group__mark img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.mod-group__head h3 {
  margin: 0;
  font-size: clamp(21px, 2.6vw, 27px);
}

.mod-group__head .dim {
  margin-left: auto;
  font-size: 14px;
  text-align: right;
}

.tile {
  --mod: var(--accent);
  background: var(--cream);
  border: 1px solid var(--line);
  border-left: 3px solid var(--mod);
  border-radius: var(--r-card);
  padding: 20px 22px;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.tile:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-card);
}

.tile h4 {
  margin: 0 0 6px;
  font-size: 17px;
}

.tile p {
  margin: 0;
  color: var(--ink-2);
  font-size: 14.5px;
  line-height: 1.55;
}

.tile[data-mod='daily'] { --mod: #3AA79E; }
.tile[data-mod='checkin'] { --mod: #BE6A45; }
.tile[data-mod='decide'] { --mod: #DE4F2A; }
.tile[data-mod='goals'] { --mod: #75943F; }
.tile[data-mod='lists'] { --mod: #B99444; }
.tile[data-mod='together'] { --mod: #9A5B3C; }
.tile[data-mod='personal'] { --mod: #5E7C88; }
.tile[data-mod='budget'] { --mod: #A98457; }
.tile[data-mod='home'] { --mod: #2A6F68; }

/* ------------------------------------------------------- closing lines -- */
.oneline {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(26px, 4vw, 40px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: clamp(30px, 4vw, 46px) 0 0;
}

/* ------------------------------------------------------------- figures -- */
figure {
  margin: 0;
}

figcaption {
  margin-top: 14px;
  font-size: 14px;
  color: var(--ink-2);
  max-width: 52ch;
}

.dusk figcaption {
  color: var(--dusk-ink-soft);
}

/* --------------------------------------------------------- press facts -- */
.facts dt {
  font-weight: 650;
  font-size: 15px;
}

.facts dd {
  margin: 0 0 16px;
  color: var(--ink-2);
  font-size: 15px;
}

@media (min-width: 640px) {
  .facts {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 0 28px;
  }

  .facts dt {
    padding: 13px 0;
    border-bottom: 1px solid var(--line);
  }

  .facts dd {
    margin: 0;
    padding: 13px 0;
    border-bottom: 1px solid var(--line);
  }
}

/* ------------------------------------------------------------ spotlight -- */
/* The tab showcase. An earlier draft was twenty-six identical cards in a grid,
   which read as a generated inventory rather than a product, and told a visitor
   everything before they had any reason to care. This shows four screens and a
   few highlights each, and says out loud that there is more inside. */
.spot {
  padding-block: clamp(38px, 5.5vw, 72px);
  border-top: 1px solid var(--line);
}

.spot:first-of-type {
  border-top: 0;
  padding-top: 0;
}

.spot__head {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: clamp(22px, 3vw, 36px);
}

.spot__name {
  font-family: var(--f-display);
  font-weight: 800;
  font-size: clamp(25px, 3.4vw, 36px);
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--spot, var(--accent));
}

.spot__rule {
  flex: 1;
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--spot, var(--accent));
  opacity: 0.35;
}

.spot__meta {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
}

/* On a 320px phone the nowrap label pushed the page 29px wide. */
@media (max-width: 420px) {
  .spot__meta {
    white-space: normal;
    text-align: right;
  }
}

.spot__more {
  margin-top: 20px;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--ink-2);
  padding-left: 14px;
  border-left: 2px solid var(--spot, var(--accent));
}

.spot h3 {
  margin-bottom: 10px;
}

.spot .ledger__row:first-child {
  padding-top: 0;
}

.spot[data-spot='daily'] { --spot: var(--m-daily); }
.spot[data-spot='goals'] { --spot: var(--m-goals); }
.spot[data-spot='together'] { --spot: var(--m-together); }
.spot[data-spot='personal'] { --spot: var(--m-personal); }

/* The phone sits a touch smaller here: it is evidence beside the words, not the
   hero of its own section. */
.spot .phone {
  max-width: 264px;
}

/* ==========================================================================
   Motion and interaction
   --------------------------------------------------------------------------
   The rules for this layer, so it keeps matching the product:
   - Calm before clever. The app's own motion is a fade, a press-scale and a
     little confetti on a reveal. Nothing here bounces for attention.
   - Every effect decorates a page that is complete without it. No content is
     reachable only through an animation, and a page with the script blocked
     shows everything (see the failsafe in the reveal-on-scroll block above).
   - prefers-reduced-motion switches all of it off. site.js checks the same
     query before it starts anything that follows the scroll or the pointer.
   - Individual transform properties do the moving and never collide: translate
     for reveals and parallax, transform for the pointer tilt, rotate for paper
     settling, scale for presses.
   ========================================================================== */

/* ------------------------------------------------------------ headline words
   Each word rises out of its own clipping box. The padding and the matching
   negative margin give descenders room, so a g or a y is never cut off. */
.w {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.w__i {
  display: inline-block;
  translate: 0 108%;
  transition: translate 1s cubic-bezier(0.2, 0.75, 0.15, 1);
  transition-delay: calc(var(--wi, 0) * 50ms + var(--wd, 0ms));
}

.is-in .w__i,
.w-in .w__i {
  translate: none;
}

/* A hero headline is split into words by site.js before it is shown, so it is
   held back until then, under the same 2.5s failsafe as everything else. */
.js [data-words]:not(.is-split) {
  opacity: 0;
}

html.js:not(.motion-ready) [data-words] {
  animation: failsafe-show 0s 2.5s forwards;
}

/* --------------------------------------------------------------- ledger rules
   A ledger is lines on a page, so the lines draw themselves, left to right, one
   after another. The real border stays in place for no-script and is swapped
   for a scaled line only once site.js has armed the row. */
.ledger__row.rule-armed {
  position: relative;
  border-bottom-color: transparent !important;
}

.ledger__row.rule-armed::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--line);
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 1.1s cubic-bezier(0.2, 0.7, 0.2, 1);
  transition-delay: calc(var(--ri, 0) * 85ms + 150ms);
}

.dusk .ledger__row.rule-armed::after {
  background: var(--dusk-line);
}

.ledger.is-drawn .ledger__row.rule-armed::after {
  transform: none;
}

/* A figure in a ledger counts up to itself the first time it is seen. The width
   is held so the row never reflows while the digits change. */
.ledger__figure[data-count] {
  display: inline-block;
  min-width: 2.2ch;
  text-align: right;
}

/* -------------------------------------------------------------- nav progress */
.nav__progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: linear-gradient(90deg, #3aa79e, #b99444 55%, #c67d5d);
  transform-origin: left;
  transform: scaleX(var(--p, 0));
  pointer-events: none;
}

/* --------------------------------------------------------------------- stars
   A few faint points of light on every dusk surface. They are placed by a
   seeded random, so they land in the same place on every visit, and they sit
   behind the content in a layer of their own. */
.stars {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.dusk > .wrap {
  position: relative;
  z-index: 1;
}

.star {
  position: absolute;
  width: var(--s, 2px);
  height: var(--s, 2px);
  border-radius: 50%;
  background: var(--c, #f5efdf);
  opacity: var(--o, 0.5);
  animation: twinkle var(--d, 4s) ease-in-out var(--dl, 0s) infinite;
}

.star--spark {
  border-radius: 0;
  background: none;
  width: calc(var(--s, 2px) * 4);
  height: calc(var(--s, 2px) * 4);
}

.star--spark::before,
.star--spark::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  background: var(--c, #f5efdf);
  border-radius: 2px;
}

.star--spark::before {
  height: 1.5px;
}

.star--spark::after {
  width: 1.5px;
}

@keyframes twinkle {
  0%,
  100% {
    opacity: calc(var(--o, 0.5) * 0.3);
    scale: 0.75;
  }
  50% {
    opacity: var(--o, 0.5);
    scale: 1;
  }
}

/* ---------------------------------------------------------------------- tilt
   Phones and plates lean toward the pointer, a few degrees at most. */
[data-tilt] {
  transform: perspective(1100px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1);
}

[data-tilt].is-tilting {
  transition: transform 0.15s linear;
}

/* A phone can both rise into view and lean toward the pointer, so its
   transition list has to name all four properties or one would drop the other. */
.js [data-rise][data-tilt] {
  transition: opacity 0.8s cubic-bezier(0.2, 0.7, 0.2, 1), translate 0.9s cubic-bezier(0.2, 0.7, 0.2, 1),
    scale 0.9s cubic-bezier(0.2, 0.7, 0.2, 1), transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.js [data-rise][data-tilt].is-tilting {
  transition: opacity 0.8s cubic-bezier(0.2, 0.7, 0.2, 1), translate 0.9s cubic-bezier(0.2, 0.7, 0.2, 1),
    scale 0.9s cubic-bezier(0.2, 0.7, 0.2, 1), transform 0.15s linear;
}

/* ------------------------------------------------------------ paper that lands
   Sheets are dropped onto the page the way paper actually falls: a little
   high, a little more rotated than where it ends up, then settled. */
.js [data-drop] {
  opacity: 0;
}

html.js:not(.motion-ready) [data-drop] {
  animation: failsafe-show 0s 2.5s forwards;
}

.js [data-drop].is-in {
  animation: paper-drop 1.15s cubic-bezier(0.2, 0.7, 0.2, 1) both;
  animation-delay: var(--drop-delay, 0ms);
}

@keyframes paper-drop {
  0% {
    opacity: 0;
    translate: 0 -54px;
    rotate: var(--drop-rot, -5deg);
  }
  45% {
    opacity: 1;
  }
  62% {
    translate: 0 5px;
    rotate: calc(var(--drop-rot, -5deg) * -0.22);
  }
  82% {
    translate: 0 -2px;
    rotate: calc(var(--drop-rot, -5deg) * 0.06);
  }
  100% {
    opacity: 1;
    translate: none;
    rotate: none;
  }
}

.sheet .paper {
  transition: transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.5s ease;
}

@media (hover: hover) and (pointer: fine) {
  .sheet:hover .paper {
    transform: translateY(-5px) rotate(0.7deg);
    box-shadow: 5px 14px 18px rgba(8, 22, 24, 0.24);
  }
}

/* ---------------------------------------------------------------- hero loop
   The hero cats breathe. A five second generated clip is laid exactly over the
   still (the fit is measured, see tools/loop-mask.js) and played through the
   still's own grown silhouette, so the clip's slightly different background
   never shows as a box. The still stays underneath the whole time. */
.hero__still {
  position: relative;
  max-width: 560px;
  margin-inline: auto;
}

.hero__still img {
  width: 100%;
}

.hero__motion {
  position: absolute;
  inset: 0;
  /* The clip is larger than the still it sits on. The mask hides the excess,
     but only overflow stops it widening the page on a phone. */
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.6s ease;
  -webkit-mask: url('../motion/hero-mask.png') center / 100% 100% no-repeat;
  mask: url('../motion/hero-mask.png') center / 100% 100% no-repeat;
}

.hero__motion.is-playing {
  opacity: 1;
}

.hero__motion video {
  position: absolute;
  left: -12.663%;
  top: -6.854%;
  width: 125.32%;
  height: 113.7%;
  max-width: none;
  /* The colour match, see GRADE in site.js. Where a browser cannot apply an
     SVG filter to video it simply plays ungraded, a few points bluer. */
  filter: url('#hero-grade');
}

@media (max-width: 880px) {
  .hero__still {
    max-width: 380px;
  }
}

/* ------------------------------------------------------------ the reveal demo */
.reveal__card {
  transform-style: preserve-3d;
}

.reveal__q {
  display: inline-block;
  transition: opacity 0.35s ease, translate 0.35s ease;
}

.reveal__q.is-swapping {
  opacity: 0;
  translate: 0 6px;
}

.reveal__reactions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
}

.reveal__reactions[hidden] {
  display: none;
}

.reveal__reactions .label {
  margin-right: 6px;
}

.react {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(245, 239, 223, 0.24);
  background: rgba(245, 239, 223, 0.06);
  /* The emoji draw in their own colours, but a monochrome fallback glyph would
     use this, and the browser default is black on dusk. */
  color: var(--dusk-ink);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  transition: scale 0.25s cubic-bezier(0.3, 1.6, 0.5, 1), background 0.2s ease, border-color 0.2s ease;
}

.react:hover {
  scale: 1.1;
  background: rgba(245, 239, 223, 0.14);
}

.react:active {
  scale: 0.92;
}

.react[aria-pressed='true'] {
  background: rgba(245, 239, 223, 0.2);
  border-color: rgba(245, 239, 223, 0.6);
}

/* The reaction lands on the corner of Sam's sheet, the way it does in the app. */
.reveal__badge {
  position: absolute;
  top: -16px;
  right: 16px;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: 2px 4px 8px rgba(8, 22, 24, 0.32);
  font-size: 20px;
  line-height: 1;
  z-index: 2;
  animation: badge-pop 0.5s cubic-bezier(0.3, 1.6, 0.5, 1) both;
}

@keyframes badge-pop {
  from {
    scale: 0.2;
    opacity: 0;
  }
  to {
    scale: 1;
    opacity: 1;
  }
}

/* Confetti and floating hearts are thrown from a fixed layer so they can leave
   their section without being clipped by it. */
.fx-layer {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 60;
  overflow: hidden;
}

.fx-bit {
  position: absolute;
  left: 0;
  top: 0;
  width: 7px;
  height: 11px;
  border-radius: 2px;
}

.fx-bit--dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.fx-heart {
  position: absolute;
  left: 0;
  top: 0;
  width: 22px;
  height: 22px;
  color: #de4f2a;
}

/* ------------------------------------------------------ the tab showcase stage
   On a wide screen the four tabs share one phone that stays put while the words
   scroll past it, with a copy of the app's own floating tab bar that tracks
   where you are and can be tapped. Below 980px, or with the script blocked, each
   tab keeps its own inline screenshot, which is the markup as written. */
.stage {
  display: none;
}

@media (min-width: 980px) {
  .spots.is-staged {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: clamp(48px, 6vw, 104px);
  }

  .spots.is-staged > .spot {
    grid-column: 1;
    min-height: min(86vh, 780px);
    display: flex;
    flex-direction: column;
    justify-content: center;
    border-top: 0;
    padding-block: 6vh;
  }

  .spots.is-staged > .spot .split {
    display: block;
  }

  .spots.is-staged > .spot .split__art {
    display: none;
  }

  .spots.is-staged > .stage {
    display: block;
    grid-column: 2;
    grid-row: 1 / span 4;
  }

  /* The phone can only stay pinned while the column it lives in is still on
     screen. Extra room under the last tab lets it hold still for that tab too,
     instead of being pushed up under the nav while you read it. */
  .spots.is-staged > .spot--last {
    min-height: calc(min(86vh, 780px) + 16vh);
    padding-bottom: 22vh;
  }
}

.stage {
  --sh: min(620px, calc(100vh - 150px));
}

.stage__sticky {
  position: sticky;
  top: calc(35px + 50vh - var(--sh) / 2 - 11px);
}

.stage__phone {
  position: relative;
  width: calc(var(--sh) * 390 / 844 + 22px);
  padding: 11px;
  border-radius: 48px;
  background: linear-gradient(160deg, #2f4a48, #101f22);
  box-shadow: var(--shadow-float), 0 34px 60px -24px rgba(19, 47, 50, 0.5);
}

.stage__phone::after {
  content: '';
  position: absolute;
  top: 22px;
  left: 50%;
  transform: translateX(-50%);
  width: 32%;
  height: 24px;
  border-radius: var(--r-pill);
  background: #101f22;
  z-index: 3;
}

.stage__screen {
  position: relative;
  height: var(--sh);
  border-radius: 37px;
  overflow: hidden;
  background: #f5efdf;
}

.stage__shot {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  max-width: none;
  opacity: 0;
  translate: 0 22px;
  scale: 1.03;
  transition: opacity 0.55s ease, translate 0.8s cubic-bezier(0.2, 0.7, 0.2, 1), scale 0.8s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.stage__shot.is-on {
  opacity: 1;
  translate: none;
  scale: none;
}

.stage__shot.is-gone {
  translate: 0 -16px;
}

/* The floating pill tab bar, rebuilt from src/components/floating-tab-bar.tsx.
   It always shows the light app, because every screenshot inside it is. */
.tabbar {
  position: absolute;
  left: 50%;
  bottom: 14px;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 5px;
  border-radius: var(--r-pill);
  background: #fcf8ec;
  box-shadow: 0 6px 18px rgba(90, 70, 40, 0.2);
  z-index: 2;
}

.tabbar__pill {
  position: absolute;
  top: 5px;
  bottom: 5px;
  left: 0;
  width: 44px;
  border-radius: var(--r-pill);
  background: #eae2cc;
  transition: translate 0.55s cubic-bezier(0.3, 1.2, 0.45, 1), width 0.55s cubic-bezier(0.3, 1.2, 0.45, 1);
}

.tabbar__tab {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 44px;
  height: 40px;
  padding: 0 11px;
  border: 0;
  border-radius: var(--r-pill);
  background: none;
  color: #6d6b54;
  font-family: var(--f-body);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}

.tabbar__tab svg {
  flex: none;
}

.tabbar__tab span {
  display: none;
}

.tabbar__tab[aria-current='true'] {
  color: var(--tab-ink);
}

.tabbar__tab[aria-current='true'] span {
  display: inline;
}

.tabbar__tab:focus-visible {
  outline: 2px solid #2a6f68;
  outline-offset: 1px;
}

/* In the staged layout the rule beside each tab's name fills out while that
   tab is the one on the phone. */
.spot__rule {
  transform-origin: left;
  transition: opacity 0.6s ease, transform 0.9s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.spots.is-staged .spot__rule {
  transform: scaleX(0.3);
}

.spots.is-staged .spot.is-active .spot__rule {
  transform: none;
  opacity: 0.85;
}

/* ------------------------------------------------------------------ a heart */
.love {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 16px;
  min-height: 44px;
  padding: 9px 18px 9px 14px;
  border-radius: var(--r-pill);
  border: 1.5px solid var(--line-control);
  background: transparent;
  color: var(--ink);
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 15px;
  cursor: pointer;
  transition: background 0.2s ease, scale 0.2s ease;
}

.love:hover {
  background: var(--muted);
}

.love:active {
  scale: 0.96;
}

.love svg {
  color: var(--m-decide);
  transition: scale 0.35s cubic-bezier(0.3, 1.8, 0.5, 1);
}

.love.is-sent svg {
  scale: 1.35;
}

/* --------------------------------------------------------------- budget demo
   Two phones, one set of rows. Mark a row private on yours and it leaves
   theirs, and their total is worked out without it. It stays in the ledger
   register: ruled rows, serif figures, colour only in the small data mark. */
.bdg {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: clamp(26px, 4vw, 56px);
  margin-top: clamp(34px, 4vw, 52px);
}

.bdg__col > .label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 9px;
  margin: 0;
  border-bottom: 1px solid var(--ink);
}

.bdg__col > .label svg {
  flex: none;
}

.bdg__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.bdg__row {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 12px;
  min-height: 56px;
  max-height: 80px;
  border-bottom: 1px solid var(--line);
  transition: max-height 0.6s cubic-bezier(0.2, 0.7, 0.2, 1), min-height 0.6s cubic-bezier(0.2, 0.7, 0.2, 1),
    opacity 0.4s ease, border-color 0.4s ease;
}

.bdg__col--mine .bdg__row {
  grid-template-columns: 9px minmax(0, 1fr) auto 50px;
}

.bdg__col--theirs .bdg__row.is-away {
  min-height: 0;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  border-bottom-color: transparent;
}

.bdg__mark {
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.bdg__name {
  font-weight: 600;
  font-size: 15.5px;
  line-height: 1.3;
  padding-block: 8px;
}

.bdg__name small {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.bdg__amt {
  font-family: var(--f-serif);
  font-size: 21px;
  line-height: 1;
  font-variant-numeric: lining-nums tabular-nums;
}

.bdg__total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding-top: 16px;
}

.bdg__total > span:first-child {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-2);
}

.bdg__total .num {
  font-size: 34px;
  line-height: 1;
}

.bdg__note {
  margin: 10px 0 0;
  font-size: 14px;
  color: var(--ink-2);
  min-height: 3em;
}

/* The switch: a real button with role="switch" and 44px of hit area. */
.sw {
  position: relative;
  width: 50px;
  height: 44px;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  border-radius: var(--r-pill);
}

.sw::before {
  content: '';
  position: absolute;
  left: 2px;
  right: 2px;
  top: 11px;
  bottom: 11px;
  border-radius: var(--r-pill);
  background: var(--muted);
  border: 1.5px solid var(--line-control);
  transition: background 0.25s ease, border-color 0.25s ease;
}

.sw::after {
  content: '';
  position: absolute;
  top: 16px;
  left: 7px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--line-control);
  transition: translate 0.35s cubic-bezier(0.3, 1.4, 0.5, 1), background 0.25s ease;
}

.sw[aria-checked='true']::before {
  background: var(--accent);
  border-color: var(--accent);
}

.sw[aria-checked='true']::after {
  translate: 24px 0;
  background: var(--on-accent);
}

.bdg__head {
  display: flex;
  justify-content: flex-end;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0;
  padding: 10px 0 0;
}

/* ------------------------------------------------------------- the night walk
   The band is a touch wider than the viewport and drifts sideways while the
   page scrolls, so the couple walks as you read. */
.band--walk .band__img {
  scale: 1.12;
  translate: var(--wx, 0px) 0;
}

/* --------------------------------------------------------- pairing steps
   The three steps are joined by a line that draws itself as they come into
   view, and each number fills as the line reaches it. */
.steps {
  position: relative;
}

.steps__line {
  position: absolute;
  z-index: 0;
  background: var(--line);
  border-radius: 2px;
  pointer-events: none;
}

.steps__line i {
  position: absolute;
  inset: 0;
  border-radius: 2px;
  background: var(--accent);
  transform-origin: left top;
  transform: scale(0, 1);
  transition: transform 1.8s cubic-bezier(0.45, 0, 0.2, 1) 0.2s;
}

.steps__line--v i {
  transform: scale(1, 0);
}

.steps.is-joined .steps__line i {
  transform: none;
}

.steps li::before {
  z-index: 1;
  transition: background 0.45s ease, color 0.45s ease, scale 0.45s cubic-bezier(0.3, 1.6, 0.5, 1);
}

.steps li.is-lit::before {
  background: var(--accent);
  color: var(--on-accent);
  scale: 1.1;
}

/* ------------------------------------------------------------------ the faq
   site.js sets overflow only for the length of the animation, so the summary's
   focus ring is never clipped at rest. */
.faq summary::after {
  transition: transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ------------------------------------------------------------- theme change
   A circular wipe from the toggle where the browser has view transitions.
   Everywhere else the colours simply change. */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}

::view-transition-new(root) {
  z-index: 2;
}

/* --------------------------------------------------------------- magnetic */
.btn[data-magnetic] {
  translate: var(--mx, 0px) var(--my, 0px);
  transition: transform 0.16s ease, box-shadow 0.16s ease, background 0.16s ease,
    translate 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ------------------------------------------------------------ reduced motion */
@media (prefers-reduced-motion: reduce) {
  .w__i {
    translate: none;
  }

  .ledger__row.rule-armed::after,
  .steps__line i {
    transform: none;
  }

  .star {
    animation: none;
  }

  .js [data-drop],
  .js [data-drop].is-in {
    opacity: 1;
    animation: none;
  }

  .band--walk .band__img {
    translate: none;
  }

  .hero__motion {
    display: none;
  }

  .stage__shot {
    translate: none;
    scale: none;
  }
}

/* ----------------------------------------------------------------- print
   Paper never waits for a scroll. */
@media print {
  .js [data-rise],
  .js [data-enter],
  .js [data-drop],
  .js [data-words] {
    opacity: 1 !important;
    translate: none !important;
    animation: none !important;
  }

  .w__i {
    translate: none !important;
  }

  .stars,
  .nav__progress,
  .hero__motion,
  .fx-layer {
    display: none !important;
  }
}
