/* Self-hosted variable fonts (latin subset), served from this site.
   No visitor request goes to Google. */

@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 200 800;
  font-stretch: normal;
  font-display: swap;
  src: url("fonts/newsreader-var-latin.woff2") format("woff2");
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("fonts/ibmplexsans-var-latin.woff2") format("woff2");
}

/* Loopsu — Loopsu Pty Ltd
   Tokens. Change these, not the rules below. */

:root {
  --ground:      #EEF1F0;   /* cool paper, faintly green — not cream */
  --surface:     #FBFCFB;
  --ink:         #16201D;
  --ink-soft:    #59635F;
  --ink-faint:   #8A928E;
  --rule:        #D3D9D6;
  --signal:      #33417F;   /* the pacer line, links, focus */
  --signal-soft: #98A0C4;   /* the heart line */

  --measure: 60rem;         /* one left edge for every section */
  --prose: 40rem;           /* running text: ~75 characters at body size */
  --gutter: clamp(1.25rem, 5vw, 3rem);

  --serif: "Newsreader", Georgia, "Times New Roman", serif;
  --sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
}

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--serif);
  font-size: clamp(1.0625rem, 0.98rem + 0.42vw, 1.1875rem);
  line-height: 1.62;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
}

/* ---------- shared structure ---------- */

.wrap {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap--wide { max-width: var(--measure); }

/* Running text keeps a readable measure inside the wider column, so every
   section shares one left edge without any paragraph running too long. */
.wrap > h1, .wrap > h2, .wrap > p, .wrap > form { max-width: var(--prose); }
.ceiling-row p, .part p, .status dd { max-width: none; }
form { max-width: 26rem; }

section { padding-block: clamp(3rem, 7vw, 5.25rem); }

hr.rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: 0;
}

h1, h2, h3 {
  font-weight: 400;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.25rem, 1.5rem + 3.6vw, 3.75rem);
  line-height: 1.08;
  margin: 0 0 1.1rem;
}

h2 {
  font-size: clamp(1.5rem, 1.24rem + 1.15vw, 2rem);
  line-height: 1.18;
  margin: 0 0 1.25rem;
}

h3 {
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.005em;
  margin: 0 0 0.4rem;
}

p { margin: 0 0 1.1rem; }
p:last-child { margin-bottom: 0; }

a { color: var(--signal); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

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

.lede {
  font-size: 1.15em;
  line-height: 1.5;
  color: var(--ink);
}

.quiet { color: var(--ink-soft); }

.small {
  font-family: var(--sans);
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* ---------- masthead ---------- */

.masthead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.5rem var(--gutter) 0;
  max-width: var(--measure);
  margin-inline: auto;
  font-family: var(--sans);
  font-size: 0.9375rem;
}

.masthead a { text-decoration: none; }
.masthead a:hover { text-decoration: underline; }

.wordmark {
  font-family: var(--serif);
  font-size: 1.25rem;
  letter-spacing: 0.01em;
  color: var(--ink);
}

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

.hero { padding-block: clamp(2rem, 5vw, 3.5rem) clamp(3rem, 7vw, 5rem); }

.wavefield {
  position: relative;
  height: clamp(112px, 19vw, 170px);
  overflow: hidden;
  margin-block: clamp(1.75rem, 4vw, 2.75rem) clamp(1.5rem, 3vw, 2rem);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}

.wavefield svg {
  position: absolute;
  inset: 0;
  height: 100%;
  width: 200%;
  animation: drift 43.64s linear infinite; /* 4 breath cycles at 5.5 per minute */
}

@keyframes drift { to { transform: translateX(-50%); } }

/* On a narrow screen the same waveform is stretched over less width, so show
   fewer cycles rather than a steeper, busier line. The travel distance is the
   same fraction, so the breath rate the animation depicts does not change. */
@media (max-width: 46rem) {
  .wavefield svg { width: 400%; }
}

.wave-pacer {
  fill: none;
  stroke: var(--signal);
  stroke-width: 1.25;
  vector-effect: non-scaling-stroke;
}

.wave-heart {
  fill: none;
  stroke: var(--signal-soft);
  stroke-width: 1;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.wave-key {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.5rem;
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin-top: 0;
}

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

.swatch {
  width: 18px;
  height: 0;
  border-top: 1.5px solid currentColor;
  flex: none;
}

.swatch--pacer { color: var(--signal); }
.swatch--heart { color: var(--signal-soft); }

/* ---------- call to action ---------- */

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  margin-top: 1.75rem;
}

.button {
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1;
  padding: 0.85rem 1.4rem;
  border: 1px solid var(--signal);
  border-radius: 2px;
  background: var(--signal);
  color: #fff;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}

.button:hover { background: #26326A; border-color: #26326A; }

/* ---------- the two parts ---------- */

.parts {
  display: grid;
  gap: 0;
  border-top: 1px solid var(--rule);
}

.part {
  border-bottom: 1px solid var(--rule);
  padding-block: 1.6rem;
  display: grid;
  gap: 0.15rem 2rem;
}

@media (min-width: 46rem) {
  .part { grid-template-columns: 8.5rem 1fr; }
  .part h3 { margin-top: 0.28rem; }
}

.part p { font-size: 0.9375em; }

.part-status {
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: var(--ink-faint);
  margin-top: 0.5rem;
}

/* ---------- ceiling table ---------- */

.ceiling { border-top: 1px solid var(--ink); }

.ceiling-row {
  border-bottom: 1px solid var(--rule);
  padding-block: 1.15rem;
  display: grid;
  gap: 0.3rem 1.75rem;
}

@media (min-width: 46rem) {
  .ceiling-row { grid-template-columns: 11rem 1fr 1fr; align-items: start; }
}

.technique {
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.4;
}

.say, .dont {
  font-size: 0.9375rem;
  line-height: 1.5;
  margin: 0;
}

.say { color: var(--ink); }
.dont { color: var(--ink-soft); }

@media (max-width: 45.99rem) {
  .say::before, .dont::before {
    font-family: var(--sans);
    font-size: 0.75rem;
    color: var(--ink-faint);
    display: block;
  }
  .say::before { content: "We say"; }
  .dont::before { content: "We don't say"; margin-top: 0.4rem; }
}

.ceiling-head {
  display: none;
  font-family: var(--sans);
  font-size: 0.75rem;
  color: var(--ink-faint);
  padding-bottom: 0.55rem;
}

@media (min-width: 46rem) {
  .ceiling-head {
    display: grid;
    grid-template-columns: 11rem 1fr 1fr;
    gap: 1.75rem;
  }
}

/* ---------- status list ---------- */

.status { border-top: 1px solid var(--rule); margin-top: 1.5rem; }

.status div {
  border-bottom: 1px solid var(--rule);
  padding-block: 1rem;
  display: grid;
  gap: 0.2rem 2rem;
}

@media (min-width: 46rem) {
  .status div { grid-template-columns: 8.5rem 1fr; }
}

.status dt {
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
}

.status dd { margin: 0; font-size: 0.9375rem; line-height: 1.5; }

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

.waitlist { background: var(--surface); border-block: 1px solid var(--rule); }

.field { display: grid; gap: 0.45rem; margin-bottom: 1.1rem; }

label {
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: 500;
}

input[type="email"] {
  font: inherit;
  font-family: var(--sans);
  font-size: 1rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--rule);
  border-radius: 2px;
  background: #fff;
  color: var(--ink);
  width: 100%;
}

input[type="email"]:focus { border-color: var(--signal); }

.consent {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  font-family: var(--sans);
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-bottom: 1.35rem;
  font-weight: 400;
}

.consent input { margin-top: 0.25rem; flex: none; width: 1rem; height: 1rem; accent-color: var(--signal); }

.form-note {
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: var(--ink-soft);
  margin-top: 1rem;
}

.form-message {
  font-family: var(--sans);
  font-size: 0.9375rem;
  line-height: 1.5;
  margin-top: 1rem;
  padding: 0.85rem 1rem;
  border-left: 2px solid var(--signal);
  background: rgba(51, 65, 127, 0.05);
}

.form-message[hidden] { display: none; }

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

footer { padding-block: clamp(2.5rem, 6vw, 4rem) 3.5rem; }

footer p { font-size: 0.875rem; line-height: 1.6; color: var(--ink-soft); font-family: var(--sans); }

.footer-links { display: flex; flex-wrap: wrap; gap: 1.25rem; margin-bottom: 1.5rem; font-family: var(--sans); font-size: 0.875rem; }

/* ---------- legal / privacy document ---------- */

.doc h2 { font-size: 1.375rem; margin-top: 2.5rem; }
.doc h2:first-of-type { margin-top: 1.5rem; }
.doc ul { padding-left: 1.15rem; margin: 0 0 1.1rem; }
.doc li { margin-bottom: 0.5rem; }
.doc .updated { font-family: var(--sans); font-size: 0.875rem; color: var(--ink-soft); }

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

@media (prefers-reduced-motion: reduce) {
  .wavefield svg { animation: none; }
  * { transition-duration: 0.01ms !important; }
}

/* ---------- photographs and renders ---------- */
/* Two images, neither above the fold, both lazy. The widths are not arbitrary:
   --measure gives a 960px column with the gutter inside it, so a full-column
   image renders 864px wide at desktop. Full-column assets ship at 1408px,
   about 1.6x that; the masters stop at 1536px and are never upscaled, so 2x
   needs a new master. The hero also ships a 704px srcset candidate, and its
   sizes attribute in index.html states the rendered width — change it
   whenever --measure changes. Captions are page text inside a <figcaption>, never a title or an
   alt attribute: alt describes the image to someone who cannot see it, and
   the caption tells everyone that the thing depicted does not exist yet.
   Those are two different jobs and one cannot do the other's.
   No animation here; the hero waveform stays the site's only motion. */

.shot {
  display: block;
  margin: 2rem 0;
  max-width: var(--measure);
}

/* About 60 per cent of the column. The band render is a portrait 4:5 and at
   full width it would dominate a section whose argument is a refusal. */
.shot--narrow { max-width: 420px; }

.shot img {
  display: block;
  width: 100%;
  height: auto;
  /* The renders sit on #EEF1F0; matching it keeps the reflow quiet. */
  background: var(--ground);
}

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

/* ---------- resonance figure ---------- */
/* Static schematic in "The rate is yours". The two axis labels and the tick
   numerals are HTML, not SVG <text>: text inside a scaled viewBox would grow
   and shrink with the drawing (about 2x between a 320px and a 544px column),
   so keeping them outside is the only way they hold one type size. The SVG
   carries geometry only, and its x-domain runs 3.5-7.5 breaths per minute
   across the full box, which puts 4/5/6/7 at 12.5/37.5/62.5/87.5 per cent —
   the same centres a four-cell flex row gives the numerals below it.
   No animation here on purpose: the hero waveform stays the only motion. */

.resonance {
  margin: 1.75rem 0;
  max-width: var(--prose);
}

.resonance-plot { display: grid; gap: 0.45rem; }

.resonance-ylabel,
.resonance-xlabel,
.resonance-ticks {
  font-family: var(--sans);
  font-size: 0.8125rem;
  line-height: 1.4;
  color: var(--ink-soft);
  margin: 0;
}

.resonance-curve {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;   /* the y axis sits on x=0; its hairline is centred there */
}

.resonance-axes {
  fill: none;
  stroke: var(--rule);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.resonance-line {
  fill: none;
  stroke: var(--signal);
  stroke-width: 1.25;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.resonance-ticks { display: flex; margin-top: 0.3rem; }
.resonance-ticks span { flex: 1 1 0; text-align: center; }

.resonance-xlabel { margin-top: 0.2rem; }

/* the caption reuses .small; it only needs the gap a <figcaption> lacks */
.resonance figcaption { margin-top: 0.9rem; }

/* Wide enough for the y label to stand on its side beside the plot. Below
   this it stacks above the drawing, still worded, still without numbers. */
@media (min-width: 46rem) {
  .resonance-plot { grid-template-columns: auto 1fr; align-items: center; }
  .resonance-ylabel {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    white-space: nowrap;
    justify-self: start;
  }
}
