/*
 * AERSOMA marketing site.
 *
 * The palette is the app's own (src/theme/tokens.ts), used the way the app uses it and not
 * inverted: Breath cream is the ground, Midnight Ink is the type, Deep Indigo is the action,
 * and the Dawn -> Midnight gradient appears where the app itself appears - behind the orb and
 * behind the phones. A visitor who downloads the app should recognise the thing they just saw.
 *
 * Type is Zalando Sans / Zalando Sans Expanded throughout. The app pairs Zalando with Founders
 * Grotesk, but the Founders licence covers embedding in the app and not serving from a website
 * (assets/fonts/README.md), so the site stays on the family that is OFL.
 */

:root {
  /* Brand (src/theme/tokens.ts) */
  --ink: #0a0b14; /* Midnight Ink */
  --dawn: #a8b8cc; /* Dawn */
  --cream: #e8e4dc; /* Breath */
  --indigo: #292d4a; /* Deep Indigo */
  --indigo-soft: #5b63a6;
  --live: #3dbe74;

  /* Paper: the page ground, one step lighter than a Breath card so cards read as cards. */
  --paper: #f2efe8;
  --paper-card: #e8e4dc;
  --paper-sunk: #dcd7cb;

  /* Type on paper */
  --text: #0a0b14;
  --text-soft: #3a4050;
  --text-muted: #5b6170;

  /* Type on the dark gradient */
  --on-dark: #f5f1e6;
  --on-dark-muted: #a9aec9;

  --line: rgba(10, 11, 20, 0.12);
  --line-soft: rgba(10, 11, 20, 0.07);
  --line-dark: rgba(245, 241, 230, 0.16);

  /* The app's background, verbatim: horizontal Dawn -> Midnight Ink. Used on small
     surfaces that read as a device screen. */
  --gradient: linear-gradient(100deg, #a8b8cc 0%, #7c88a2 28%, #2a2f45 68%, #0a0b14 100%);
  /* Same hue path, started lower, for full-width bands that carry text: cream on the
     Dawn end does not hold contrast. */
  --gradient-band: linear-gradient(100deg, #57637d 0%, #3b4358 32%, #1a1f2d 70%, #0a0b14 100%);

  --measure: 60ch;
  --page: 1320px;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --section: clamp(3.25rem, 5vw, 5rem);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family:
    'Zalando Sans',
    ui-sans-serif,
    system-ui,
    -apple-system,
    'Segoe UI',
    sans-serif;
  font-size: 17px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1,
h2,
h3,
.display {
  font-family: 'Zalando Sans Expanded', 'Zalando Sans', system-ui, sans-serif;
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.03em;
  text-wrap: balance;
  margin: 0;
}

h1 {
  font-size: clamp(2.85rem, 6.6vw, 5.1rem);
}
h2 {
  font-size: clamp(1.95rem, 3.9vw, 3rem);
}
h3 {
  font-family: 'Zalando Sans', system-ui, sans-serif;
  font-size: 1.1rem;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

p {
  margin: 0;
}

/*
 * The browser gives <figure> a 40px side margin by default. Every figure on this site sits in a
 * grid cell that already positions it, so that margin only ever pushed photographs out of line
 * with the headings above them - which is exactly how it looked. Reset once, here, rather than
 * patched per block.
 */
figure {
  margin: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

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

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

/* ---------------------------------------------------------------- primitives */

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

.section {
  padding-block: var(--section);
}

.eyebrow {
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 1.1rem;
}

.lede {
  font-size: clamp(1.05rem, 1.7vw, 1.25rem);
  color: var(--text-soft);
  max-width: var(--measure);
  line-height: 1.58;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  height: 52px;
  padding-inline: 1.9rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-family: inherit;
  font-size: 0.98rem;
  font-weight: 500;
  cursor: pointer;
  transition:
    transform 0.18s var(--ease),
    background-color 0.18s var(--ease),
    border-color 0.18s var(--ease);
}

.btn:active {
  transform: scale(0.985);
}

.btn-primary {
  background: var(--indigo);
  color: var(--cream);
}

.btn-primary:hover {
  background: #1f2238;
}

.btn-ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--line);
}

.btn-ghost:hover {
  border-color: rgba(10, 11, 20, 0.28);
}

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

/* ---------------------------------------------------------------- top bar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(242, 239, 232, 0.82);
  backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid transparent;
  transition:
    border-color 0.25s var(--ease),
    background-color 0.25s var(--ease);
}

.topbar.is-stuck {
  border-bottom-color: var(--line);
}

.topbar .shell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 74px;
}

/*
 * The real wordmark, not type set to look like it. The file is fill="currentColor", so painting
 * it as a mask over the current text colour makes one asset work on paper and on Midnight Ink
 * without a second file or a hard-coded fill.
 */
.wordmark {
  display: block;
  width: 142px;
  height: 16px;
  background-color: currentColor;
  -webkit-mask: url('/wordmark.svg') no-repeat center / contain;
  mask: url('/wordmark.svg') no-repeat center / contain;
}

.foot .wordmark {
  width: 168px;
  height: 19px;
}

.topnav {
  display: flex;
  gap: 1.9rem;
  font-size: 0.93rem;
  color: var(--text-soft);
}

.topnav a:hover {
  color: var(--text);
}

.topbar .btn {
  height: 42px;
  padding-inline: 1.3rem;
  font-size: 0.9rem;
}

@media (max-width: 900px) {
  .topnav {
    display: none;
  }
}

/* ---------------------------------------------------------------- hero */

.hero {
  padding-top: clamp(3rem, 6vw, 5rem);
  padding-bottom: var(--section);
}

.hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}

.hero-copy h1 {
  margin-bottom: 1.5rem;
}

.hero-copy .lede {
  margin-bottom: 2.2rem;
}

.live-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0.9rem 0.4rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.72rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 1.6rem;
}

.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--live);
  box-shadow: 0 0 0 4px rgba(61, 190, 116, 0.16);
}

.hero-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.6rem;
  margin-top: 2.2rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--line-soft);
  font-size: 0.9rem;
  color: var(--text-muted);
}

.hero-facts span {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.hero-facts span::before {
  content: '';
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--indigo-soft);
}

@media (max-width: 940px) {
  .hero-inner {
    grid-template-columns: 1fr;
    gap: 3rem;
  }
}

/* ---------------------------------------------------------------- phone */

/*
 * A device, not a rounded rectangle. The frame is built the way the hardware reads: a titanium
 * rim catching light, a black bezel inside it, then the screen. The buttons are drawn with the
 * element's own pseudo-elements so six phones on the page cost no extra markup.
 *
 * What is inside is a recording of the app running in a simulator, or a photograph of it - never
 * a drawing, and never an animation laid over a still.
 */
.phone {
  position: relative;
  /* The phone is a size container and the frame is drawn ON the screen image (border = bezel,
     box-shadow = rings), so every measurement follows the phone's own width (22.09.2026). The old
     fixed 9px bezel + 44px corner looked like a thick slab on the 190px phones of the shots grid.
     Fixed values stay as the fallback where container units are unknown. */
  container-type: inline-size;
}

/* Volume pair and the silent switch, left edge. */
.phone::before {
  content: '';
  position: absolute;
  left: -6px;
  top: 17%;
  width: 3px;
  height: 22%;
  border-radius: 2px;
  background: linear-gradient(
    180deg,
    #6b7180 0 14%,
    transparent 14% 22%,
    #6b7180 22% 58%,
    transparent 58% 66%,
    #6b7180 66% 100%
  );
}

/* Side button, right edge. */
.phone::after {
  content: '';
  position: absolute;
  right: -6px;
  top: 27%;
  width: 3px;
  height: 13%;
  border-radius: 2px;
  background: #6b7180;
}

.phone img,
.phone video {
  display: block;
  box-sizing: border-box;
  width: 100%;
  height: auto;
  border: 9px solid #07080c;
  border-width: 2.4cqw;
  border-radius: 44px;
  border-radius: 14cqw;
  background: #0a0b14;
  box-shadow:
    inset 0 0 0 1px rgba(245, 241, 230, 0.06),
    0 0 0 2px #14161d,
    0 0 0 4px #565b66,
    0 0 0 5px #2b2e36,
    0 2px 4px rgba(10, 11, 20, 0.12),
    0 26px 52px -18px rgba(10, 11, 20, 0.45),
    0 60px 90px -55px rgba(10, 11, 20, 0.5);
}

/* An explicit width, not just a cap: .phone is a size container, and a size container has no
   width of its own. Centred in the .phone-glow grid with only max-width, it collapsed to 0px and
   the hero showed nothing but the glow (found 30.09.2026, live since the 22.09 bezel change). */
.phone-hero {
  width: 100%;
  max-width: 340px;
  margin-inline: auto;
}

/* A soft breath of the app's gradient behind the hero phone. */
.phone-glow {
  position: relative;
  display: grid;
  place-items: center;
}

.phone-glow::before {
  content: '';
  position: absolute;
  inset: -12% -6%;
  background: radial-gradient(60% 50% at 50% 45%, rgba(168, 184, 204, 0.55), transparent 70%);
  filter: blur(28px);
  z-index: 0;
}

.phone-glow .phone {
  position: relative;
  z-index: 1;
}

.shots {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3.5vw, 2.75rem);
  margin-top: clamp(2rem, 3.5vw, 2.75rem);
}

.shot figcaption {
  margin-top: 1.4rem;
}

.shot h3 {
  margin-bottom: 0.4rem;
}

.shot p {
  font-size: 0.94rem;
  color: var(--text-muted);
  line-height: 1.55;
}

@media (max-width: 860px) {
  .shots {
    grid-template-columns: 1fr;
    max-width: 400px;
    margin-inline: auto;
  }
}

/* ---------------------------------------------------------------- section head */

/*
 * A heading capped at a narrow measure inside a 1320px container leaves the block looking
 * wider than its own contents, which is exactly how it read. Where there is a heading and a
 * supporting line, they sit as one row that spans the container: statement left, detail right,
 * aligned on their baselines.
 */
.section-head {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(1.5rem, 5vw, 4rem);
  align-items: end;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.section-head h2 {
  max-width: 18ch;
}

.section-head .lede {
  max-width: 44ch;
  padding-bottom: 0.35rem;
}

/* A head with nothing beside it keeps the whole row to itself. */
.section-head-solo {
  display: block;
}

.section-head-solo h2 {
  max-width: 24ch;
}

@media (max-width: 860px) {
  .section-head {
    grid-template-columns: 1fr;
    gap: 1.1rem;
    align-items: start;
  }
}

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 5.5rem);
  align-items: start;
}

.split-narrow {
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: center;
}

@media (max-width: 940px) {
  .split,
  .split-narrow {
    grid-template-columns: 1fr;
    gap: 3rem;
  }
}

/* ---------------------------------------------------------------- dark panel */

.band {
  background: var(--gradient-band);
  color: var(--on-dark);
}

.band .eyebrow {
  color: var(--on-dark-muted);
}

.band .lede {
  color: rgba(245, 241, 230, 0.86);
}

/*
 * The band used to be three zones of different widths - a 1224 row, then a 720 island of
 * phones - which is what made it read as unfinished. Everything now sits on one grid: the
 * phones pair with their captions and span the same measure as the row above them.
 */
.orb-panel {
  border: 1px solid rgba(245, 241, 230, 0.14);
  border-radius: 26px;
  padding: clamp(1.5rem, 3vw, 2.25rem) clamp(1.25rem, 2.5vw, 2rem) clamp(1.75rem, 3vw, 2.5rem);
  background: rgba(10, 11, 20, 0.18);
  text-align: center;
}

.orb-panel .live-tag {
  margin-bottom: clamp(1.25rem, 2.5vw, 2rem);
}

.band-shots {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
  margin: clamp(2.25rem, 4vw, 3.25rem) 0 0;
}

.band-shots figure {
  display: grid;
  grid-template-columns: clamp(140px, 15vw, 190px) minmax(0, 1fr);
  gap: clamp(1.25rem, 2.5vw, 1.75rem);
  align-items: center;
  margin: 0;
}

.band-shots figcaption {
  margin-top: 0;
  font-size: 0.9rem;
  color: rgba(245, 241, 230, 0.78);
  line-height: 1.5;
}

.band-shots b {
  display: block;
  font-weight: 500;
  color: var(--on-dark);
  margin-bottom: 0.3rem;
}

@media (max-width: 860px) {
  .band-shots {
    grid-template-columns: 1fr;
  }
}

/* A band that carries one statement rather than two columns. */
.band-center {
  text-align: center;
}

.band-center .head,
.band-center .lede {
  margin-inline: auto;
}

/* On a band the tag can sit over the light end of the gradient, so it brings its own ground. */
.band .live-tag {
  background: rgba(10, 11, 20, 0.5);
  border-color: rgba(245, 241, 230, 0.22);
  color: var(--on-dark);
}

/* ---------------------------------------------------------------- orb */

/*
 * The orb is src/components/PacerOrb.tsx rebuilt in CSS, not an impression of it. The app draws
 * it on a 200-unit viewBox: a glow across the whole circle (cream at 0.5, 0.14 at 55%, 0 at the
 * edge), a ring at r=96, a second at r=64, and a core dot at r=8. Those become percentages here.
 *
 * The engine scales .orb, so the whole assembly grows and shrinks together the way it does on a
 * phone - previously only the middle moved, which is a different gesture entirely.
 */
.orb-stage {
  position: relative;
  width: min(260px, 62vw);
  aspect-ratio: 1;
  margin-inline: auto;
}

.orb {
  position: absolute;
  inset: 0;
  will-change: transform;
}

.orb-glow {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(
    circle at 50% 50%,
    rgba(232, 228, 220, 0.5) 0%,
    rgba(232, 228, 220, 0.14) 55%,
    rgba(232, 228, 220, 0) 100%
  );
}

/* r = 96 of 100 */
.orb-ring {
  position: absolute;
  inset: 2%;
  border: 1px solid rgba(232, 228, 220, 0.28);
  border-radius: 50%;
}

/* r = 64 of 100 */
.orb-ring.inner {
  inset: 18%;
  border-color: rgba(232, 228, 220, 0.18);
}

/* r = 8 of 100 */
.orb-dot {
  position: absolute;
  left: 46%;
  top: 46%;
  width: 8%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: rgba(232, 228, 220, 0.55);
}

.hero-wash {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 118%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(245, 241, 230, 0.18), transparent 62%);
  filter: blur(16px);
  pointer-events: none;
}

/* The count sits under the circle, not on top of it, so it stays legible at every phase. */
.orb-read {
  margin-top: 1.25rem;
  text-align: center;
}

.orb-phase {
  font-family: 'Zalando Sans Expanded', system-ui, sans-serif;
  font-size: 1.45rem;
  letter-spacing: -0.01em;
}

.orb-count {
  font-family: 'Zalando Sans Expanded', system-ui, sans-serif;
  font-size: 3.1rem;
  line-height: 1.1;
  color: rgba(245, 241, 230, 0.92);
}

/* ---------------------------------------------------------------- rhythm player */

.player {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
  margin-top: clamp(2rem, 3.5vw, 2.75rem);
}

.player-stage {
  background: var(--gradient);
  border-radius: 28px;
  padding: 2.5rem 2rem 2.25rem;
  color: var(--on-dark);
  text-align: center;
}

.player-stage .orb-stage {
  width: min(240px, 60vw);
}

.player-stage .orb-phase {
  font-size: 1.15rem;
}

.player-stage .orb-count {
  font-size: 2.4rem;
}

.player-name {
  font-family: 'Zalando Sans Expanded', system-ui, sans-serif;
  font-size: 1.2rem;
  margin-top: 1.6rem;
}

.player-figures {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.4rem 1.2rem;
  margin-top: 0.7rem;
  font-size: 0.85rem;
  color: var(--on-dark-muted);
}

.player-figures b {
  color: var(--on-dark);
  font-weight: 500;
}

.player-overview {
  margin-top: 1rem;
  font-size: 0.94rem;
  color: rgba(245, 241, 230, 0.8);
  line-height: 1.55;
}

.rhythm-list {
  display: flex;
  flex-direction: column;
}

.rhythm-btn {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 1.25rem;
  width: 100%;
  padding: 1.15rem 1.25rem;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line-soft);
  border-radius: 14px;
  font-family: inherit;
  font-size: 1rem;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.18s var(--ease);
}

.rhythm-btn:hover {
  background: rgba(10, 11, 20, 0.04);
}

.rhythm-btn[aria-pressed='true'] {
  background: var(--paper-card);
}

.rhythm-btn .num {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
  color: var(--text-soft);
  font-size: 0.92rem;
}

.rhythm-btn .cat {
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  min-width: 5.5rem;
  text-align: right;
}

.player-note {
  margin-top: 1.4rem;
  padding-left: 1.25rem;
  font-size: 0.88rem;
  color: var(--text-muted);
  max-width: 46ch;
}

@media (max-width: 940px) {
  .player {
    grid-template-columns: 1fr;
  }
  .rhythm-btn .cat {
    display: none;
  }
}

/* ---------------------------------------------------------------- cards */

.cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
  margin-top: clamp(2rem, 3.5vw, 2.75rem);
}

.card {
  background: var(--paper-card);
  border: 1px solid rgba(10, 11, 20, 0.07);
  border-radius: 22px;
  padding: 1.85rem 1.75rem;
  display: flex;
  flex-direction: column;
}

.card .eyebrow {
  margin-bottom: 0.9rem;
}

.card h3 {
  margin-bottom: 0.7rem;
}

.card p {
  font-size: 0.94rem;
  color: var(--text-muted);
  line-height: 1.58;
}

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

.device-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

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

/* ----------------------------------------------------------------- photography */

/*
 * Where a lifestyle photograph does the work, it gets the whole card and the words get out of
 * the way. Portraits are locked to 3:4 and cropped, so three different source images still line
 * up as one row.
 */
.photo-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
  margin-top: clamp(2rem, 3.5vw, 2.75rem);
}

.photo-card figure,
.photo-card {
  overflow: visible;
}

.photo-card img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: 50% 30%;
  border-radius: 20px;
  transition: transform 0.6s var(--ease);
}

.photo-card:hover img {
  transform: scale(1.02);
}

.photo-card figcaption {
  padding-top: 1.35rem;
}

.photo-card .eyebrow {
  margin-bottom: 0.55rem;
}

.photo-card h3 {
  margin-bottom: 0.5rem;
}

.photo-card figcaption p:last-child {
  font-size: 0.94rem;
  color: var(--text-muted);
  line-height: 1.55;
}

@media (max-width: 860px) {
  .photo-cards {
    grid-template-columns: 1fr;
    max-width: 420px;
    margin-inline: auto;
  }
}

.device-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

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

/* ---------------------------------------------------------------- feature list */

.feature-list {
  display: grid;
  gap: 1.5rem;
  margin-top: 2.25rem;
  padding: 0;
  list-style: none;
}

.feature-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}

.feature-list b {
  display: block;
  font-weight: 500;
  margin-bottom: 0.2rem;
}

.feature-list p {
  font-size: 0.94rem;
  color: var(--text-muted);
  line-height: 1.55;
}

.dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--indigo);
  margin-top: 0.55rem;
}

.band .feature-list p {
  color: rgba(245, 241, 230, 0.78);
}

.band .dot {
  background: var(--dawn);
}

/* A ghost button on the dark band: cream text, not the light-page ink. */
.band .btn-ghost {
  color: var(--on-dark);
  border-color: var(--line-dark);
}

.band .btn-ghost:hover {
  border-color: rgba(245, 241, 230, 0.5);
}

.together-cta {
  margin-top: 2.25rem;
}

/* ---------------------------------------------------------------- device */

.device-specs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* A benefit should read as a thing, not as a line of grey text. Icon carries the weight. */
.device-specs li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.85rem;
  padding: 1.1rem 1.15rem;
  background: var(--paper-card);
  border: 1px solid rgba(10, 11, 20, 0.07);
  border-radius: 16px;
  font-size: 0.95rem;
  color: var(--text);
  transition:
    transform 0.25s var(--ease),
    border-color 0.25s var(--ease);
}

.device-specs li:hover {
  transform: translateY(-2px);
  border-color: rgba(10, 11, 20, 0.16);
}

.spec-icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 11px;
  background: rgba(41, 45, 74, 0.08);
  color: var(--indigo);
}

.spec-icon svg {
  width: 20px;
  height: 20px;
}

.device-status {
  padding: 1.6rem 1.75rem;
  border: 1px solid var(--line);
  border-radius: 18px;
}

.device-status h3 {
  margin-bottom: 0.6rem;
}

.device-status p {
  font-size: 0.94rem;
  color: var(--text-muted);
  line-height: 1.58;
  max-width: 52ch;
}

@media (max-width: 620px) {
  .device-specs {
    grid-template-columns: 1fr;
  }
}

/* ---------------------------------------------------------------- waitlist */

.waitlist {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1.8rem;
}

.waitlist input {
  flex: 1 1 16rem;
  height: 52px;
  padding-inline: 1.2rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: #fff;
  font-family: inherit;
  font-size: 0.98rem;
  color: var(--text);
}

.waitlist input::placeholder {
  color: rgba(10, 11, 20, 0.38);
}

.band .waitlist input {
  background: rgba(245, 241, 230, 0.1);
  border-color: var(--line-dark);
  color: var(--on-dark);
}

.band .waitlist input::placeholder {
  color: rgba(245, 241, 230, 0.5);
}

/* Honeypot field: off-screen for people, still in the form for bots. Not display:none - some bots
   skip fields they can tell are hidden that way. */
.waitlist .hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}

.form-note {
  margin-top: 1rem;
  font-size: 0.86rem;
  color: var(--text-muted);
  max-width: 46ch;
}

.band .form-note {
  color: var(--on-dark-muted);
}

/* ---------------------------------------------------------------- manifesto teaser */

.teaser {
  text-align: center;
  padding-block: clamp(3.5rem, 7vw, 5.5rem);
}

.teaser p {
  font-family: 'Zalando Sans Expanded', system-ui, sans-serif;
  font-size: clamp(1.35rem, 2.6vw, 2rem);
  line-height: 1.28;
  letter-spacing: -0.02em;
  max-width: 24ch;
  margin: 0 auto 2rem;
}

/* ---------------------------------------------------------------- footer */

.foot {
  background: var(--ink);
  color: var(--on-dark);
  padding-block: clamp(3.5rem, 6vw, 5rem) 2.5rem;
}

.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: 2.5rem;
}

.foot h4 {
  margin: 0 0 1.1rem;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--on-dark-muted);
}

.foot ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.65rem;
  font-size: 0.94rem;
  color: rgba(245, 241, 230, 0.82);
}

.foot a:hover {
  color: #fff;
}

.foot-blurb {
  margin-top: 1rem;
  font-size: 0.94rem;
  color: rgba(245, 241, 230, 0.72);
  max-width: 34ch;
  line-height: 1.58;
}

.foot-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 3.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line-dark);
  font-size: 0.84rem;
  color: var(--on-dark-muted);
}

@media (max-width: 780px) {
  .foot-grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
}

/* A doc page closes on a single line, without the footer's dividing rule above it. */
.foot-bottom-bare {
  border-top: 0;
  padding-top: 0;
}

/*
 * The legal entity and its postal address, on every page rather than only in the policy:
 * the app stores and the payment provider both require them to be reachable from anywhere
 * on the site, and a person who wants to know who they are dealing with should not have to
 * open the Privacy Policy to find out.
 */
.foot-legal {
  margin-top: 0.9rem;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--on-dark-muted);
}

/* ---------------------------------------------------------------- doc pages */

/*
 * A reading column belongs at a comfortable measure, but centring that column inside a 1320px
 * shell while the heading above it is left-aligned puts the page on two axes at once - which is
 * what made these pages read as unfinished. The column is now anchored to the same left edge as
 * everything else, and the elements that are allowed to break out of it do so deliberately.
 */
.doc-hero {
  padding-bottom: 0;
}

.doc-hero h1 {
  max-width: 16ch;
  margin-bottom: 0;
}

.doc-body {
  max-width: var(--page);
  padding-block: clamp(2rem, 4vw, 3.25rem);
}

.doc-body > p,
.doc-body > h2,
.doc-body > h3,
.doc-body > ul {
  max-width: 62ch;
}

.doc p {
  margin-bottom: 1.35rem;
  color: var(--text-soft);
}

.doc h2 {
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 1.2rem;
  font-size: clamp(1.5rem, 2.6vw, 2rem);
}

.doc h3 {
  margin: 2.25rem 0 0.7rem;
}

.doc-lead {
  font-size: clamp(1.1rem, 1.8vw, 1.3rem);
  color: var(--text);
  line-height: 1.55;
}

/* The pull quote breaks the measure on purpose: it is the one line meant to be read alone. */
.doc-pull {
  font-family: 'Zalando Sans Expanded', system-ui, sans-serif;
  font-size: clamp(1.4rem, 2.8vw, 2.1rem);
  line-height: 1.28;
  letter-spacing: -0.02em;
  color: var(--text);
  max-width: 26ch;
  margin: clamp(2.5rem, 5vw, 3.5rem) 0;
  padding-left: 1.75rem;
  border-left: 2px solid var(--indigo);
}

/* Photographs take the whole measure, so the prose has somewhere to breathe. */
.doc-figure {
  margin: clamp(2.5rem, 5vw, 4rem) 0;
}

.doc-figure img {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  object-position: 50% 42%;
  border-radius: 24px;
}

.doc-rule {
  border: 0;
  border-top: 1px solid var(--line);
  margin: clamp(2.5rem, 5vw, 3.5rem) 0;
  max-width: 62ch;
}

.doc-note {
  font-size: 0.9rem;
  color: var(--text-muted);
}

.doc ul {
  margin: 0 0 1.35rem;
  padding-left: 1.2rem;
  color: var(--text-soft);
}

.doc li {
  margin-bottom: 0.5rem;
}

.support-cta {
  justify-content: flex-start;
  margin-top: 2rem;
}

/* ---------------------------------------------------------------- motion */

/*
 * The first pass of this was so restrained that it could not be seen at all - a 7px rise over
 * fifteen seconds is not motion, it is a rumour. Everything here is now legible while still
 * being slow: things arrive, they settle, and nothing jitters. All of it is off under
 * prefers-reduced-motion.
 */
.reveal {
  opacity: 0;
  transform: translateY(42px);
  transition:
    opacity 0.85s var(--ease),
    transform 1s var(--ease);
}

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

/* Media settles into place rather than only fading in. */
.reveal img,
.reveal .phone,
.reveal .orb-panel {
  transition: transform 1.2s var(--ease);
}

.reveal:not(.is-in) img,
.reveal:not(.is-in) .phone,
.reveal:not(.is-in) .orb-panel {
  transform: scale(0.92);
}

@media (prefers-reduced-motion: no-preference) {
  /*
   * The hero phone rides the same fifteen seconds as the rhythm: up through the inhale, held,
   * down through the long exhale. The keyframe positions are the 4-2-7-2 cycle as percentages.
   */
  .phone-hero {
    animation: breathe 15s ease-in-out infinite;
  }

  @keyframes breathe {
    0% {
      transform: translateY(10px) scale(0.994);
    }
    27% {
      transform: translateY(-12px) scale(1.006);
    }
    40% {
      transform: translateY(-12px) scale(1.006);
    }
    87% {
      transform: translateY(10px) scale(0.994);
    }
    100% {
      transform: translateY(10px) scale(0.994);
    }
  }

  /*
   * Scroll-linked parallax where the browser can do it off the main thread. Guarded, so a
   * browser without scroll-driven animations simply gets the page without it.
   */
  @supports (animation-timeline: view()) {
    .doc-figure img {
      animation: drift linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
    }

    @keyframes drift {
      from {
        transform: scale(1.08) translateY(-2%);
      }
      to {
        transform: scale(1.08) translateY(2%);
      }
    }

    .photo-card:nth-child(2) {
      animation: lag linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 40%;
    }

    @keyframes lag {
      from {
        transform: translateY(38px);
      }
      to {
        transform: none;
      }
    }
  }
}

/* Controls answer the pointer. */
.btn {
  transition:
    transform 0.18s var(--ease),
    background-color 0.18s var(--ease),
    border-color 0.18s var(--ease);
}

.btn:hover {
  transform: translateY(-2px);
}

.topnav a {
  position: relative;
  transition: color 0.2s var(--ease);
}

.topnav a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--ease);
}

.topnav a:hover::after {
  transform: scaleX(1);
}

/* ---------------------------------------------------------------- doc lists */

/* Used by the account-deletion page. The steps are the reason that page exists - Google
   requires the deletion route to be spelled out - so they get numbers you can follow, not
   a paragraph you have to parse. */

.doc-body ol.steps {
  counter-reset: step;
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.doc-body ol.steps > li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 14px;
  align-items: baseline;
}

.doc-body ol.steps > li::before {
  content: counter(step);
  font-family: 'Zalando Sans Expanded', system-ui, sans-serif;
  font-size: 0.95rem;
  color: var(--dawn);
  font-variant-numeric: tabular-nums;
}

.doc-body ul.bullets {
  margin: 4px 0 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.doc-body ul.bullets li::marker {
  color: var(--text-faint);
}

.doc-body ol.steps b,
.doc-body ul.bullets b {
  color: var(--text);
  font-weight: 500;
}

/* ---------------------------------------------------------------- motion off */

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

  .reveal,
  .reveal:not(.is-in) .phone,
  .reveal:not(.is-in) img {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .btn,
  .rhythm-btn,
  .phone,
  .phone-hero,
  .photo-card img,
  .doc-figure img,
  .device-specs li,
  .topnav a::after {
    transition: none;
    animation: none;
  }
}

/* ---------------------------------------------------------------- /global (M12) */

/*
 * The page a shared Global link lands on. The whole first screen is the rhythm: dark ground
 * (the band gradient, so cream text keeps its contrast at every width), the orb, the phase,
 * one line. Everything else waits below it.
 */
.global-page {
  background: #0a0b14;
  color: var(--on-dark);
}

.global-top {
  position: absolute;
  inset: 0 0 auto;
  display: flex;
  justify-content: center;
  padding: 1.5rem 1rem 0;
  color: var(--on-dark);
  z-index: 2;
}

.global-main {
  min-height: 100vh; /* before svh: a browser without svh drops that line, not the layout */
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(1rem, 2.5vh, 1.5rem);
  padding: 5rem 1rem 3rem;
  text-align: center;
  color: var(--on-dark);
}

.global-stage {
  width: min(320px, 72vw);
}

.global-main .orb-read {
  margin-top: 0;
}

.global-line {
  max-width: 22ch;
  margin: 0;
  font-family: 'Zalando Sans Expanded', system-ui, sans-serif;
  font-size: clamp(1.4rem, 4.5vw, 2rem);
  font-weight: 500;
  line-height: 1.25;
  color: var(--on-dark);
}

.global-sound {
  color: var(--on-dark);
  border-color: var(--line-dark);
}

.global-sound:hover,
.global-sound[data-state='on'] {
  border-color: rgba(245, 241, 230, 0.5);
}

.global-about {
  max-width: 34rem;
  margin-top: clamp(1rem, 4vh, 2.5rem);
  color: var(--on-dark);
  font-size: 1rem;
  line-height: 1.6;
}

.global-about p {
  margin: 0 0 0.9rem;
}

.global-home,
.global-foot a {
  color: var(--on-dark);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.global-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.5rem;
  padding: 1.5rem 1rem 2rem;
  color: var(--on-dark);
  font-size: 0.85rem;
  background: #0a0b14;
}

/* Google Play badge (official artwork, unmodified - Google's badge guidelines). The PNG carries its
   own transparent padding, so the height here is the visible badge plus that margin. */
.store-badge {
  display: inline-block;
  line-height: 0;
}
.store-badge img {
  height: 64px;
  width: auto;
  /* The global img { max-width: 100% } resolves against this shrink-to-fit link, whose width comes
     from the image: a cycle that collapses the badge to 0px wide. */
  max-width: none;
}
.store-badge-band {
  margin-top: 16px;
}

/* ---------------------------------------------------------------- technique pages */

/* /box-breathing, /resonance-breathing, /4-6-breathing (CMO wave 1). The pacer sits on the dark
   band; every line on it is cream (on-dark), never the muted tone, so it reads on the gradient. */

.technique-hero {
  text-align: center;
}

.technique-hero h1 {
  max-width: 20ch;
  margin: 0 auto clamp(1.5rem, 3vw, 2.25rem);
  font-size: clamp(2.1rem, 5vw, 3.6rem);
  color: var(--on-dark);
}

.pacer-options {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin: 0 auto 1.25rem;
}

.pacer-chip {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  min-height: 44px;
  padding: 0.5rem 1.1rem;
  border: 1px solid var(--line-dark);
  border-radius: 999px;
  background: transparent;
  color: var(--on-dark);
  font-family: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.pacer-chip small {
  font-size: 0.72rem;
  letter-spacing: 0.04em;
}

.pacer-chip[aria-pressed='true'] {
  background: rgba(245, 241, 230, 0.14);
  border-color: rgba(245, 241, 230, 0.55);
}

/* .doc p would paint these in the light-page grey; on the band every line is cream. */
.technique-hero p {
  color: var(--on-dark);
}

/* /deep-breathing: the correction sits on the first screen, above the pacer. */
.technique-lead {
  max-width: 46ch;
  margin: calc(-1 * clamp(0.5rem, 1.5vw, 1rem)) auto clamp(1.5rem, 3vw, 2rem);
  font-size: 1.05rem;
  line-height: 1.6;
}

.technique-hero .orb-phase,
.technique-hero .orb-count {
  margin-bottom: 0;
}

.pacer-start {
  margin-top: 1.25rem;
}

.pacer-line {
  max-width: 36ch;
  margin: 1.5rem auto 0;
  font-size: 1.1rem;
  line-height: 1.5;
  color: var(--on-dark);
}

.pacer-small {
  max-width: 44ch;
  margin: 0.75rem auto 0;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--on-dark);
}

.pacer-next {
  margin: 2rem auto 0;
  color: var(--on-dark);
}

.pacer-next p {
  margin-bottom: 0.9rem;
}

.btn-cream {
  background: var(--on-dark);
  color: var(--ink);
}

.btn-cream:hover {
  background: #ffffff;
}

.technique-diagram {
  margin: 1.5rem 0 0.75rem;
}

.technique-diagram img {
  width: 100%;
  max-width: 440px;
  height: auto;
  border-radius: 18px;
  border: 1px solid var(--line);
}

.try-rhythms {
  font-size: 0.98rem;
}

.try-rhythms a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.band .try-rhythms,
.global-about .try-rhythms {
  color: var(--on-dark);
}

.store-note {
  font-size: 0.9rem;
}
