@font-face {
  font-family: 'Bricolage Grotesque';
  src: url('fonts/bricolage.woff2') format('woff2');
  font-weight: 300 800;
  font-display: swap;
}

:root {
  --bg: oklch(1 0 0);
  --surface: oklch(0.97 0 0);
  --ink: oklch(0.19 0.03 340);
  --muted: oklch(0.50 0.03 340);
  --line: oklch(0.90 0.015 340);
  --accent: oklch(0.60 0.24 352);          /* hot pink */
  --accent-deep: oklch(0.50 0.22 352);
  --accent-wash: oklch(0.96 0.045 352);
  --butter: oklch(0.90 0.16 100);          /* the second brand colour */
  --butter-deep: oklch(0.80 0.17 95);
  --mint: oklch(0.88 0.11 175);
  --accent-ink: oklch(0.99 0 0);

  /* Artifact only. Never used for brand chrome. */
  --ios-blue: #007AFF;
  --ios-gray: #E9E9EB;

  --sans: 'Bricolage Grotesque', -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif;
  --apple: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', Helvetica, Arial, sans-serif;

  --pad: clamp(1.25rem, 5vw, 3rem);
  --gap: clamp(3.5rem, 11vh, 8rem);
  --radius: 20px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);        /* ease-out-quart */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);   /* Emil's ease-out */

  --z-sticky: 100;
  --z-toast: 300;
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 {
  margin: 0;
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.02;
  text-wrap: balance;
}

h1 { font-size: clamp(2.6rem, 7.5vw, 5.5rem); }
h2 { font-size: clamp(1.9rem, 4.2vw, 3rem); letter-spacing: -0.03em; }
h3 { font-size: clamp(1.15rem, 2vw, 1.4rem); letter-spacing: -0.02em; }

p { margin: 0; text-wrap: pretty; }

a { color: inherit; }

.wrap { max-width: 1100px; margin: 0 auto; padding-inline: var(--pad); }
.prose { max-width: 34rem; }

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

.hero {
  padding-block: clamp(3rem, 9vh, 6.5rem) var(--gap);
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.5rem, 6vw, 4.5rem);
  align-items: center;
}

@media (min-width: 940px) {
  .hero { grid-template-columns: 1.05fr 0.95fr; }
}

.mark {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.03em;
  margin-bottom: clamp(2rem, 6vh, 3.5rem);
}

.mark i {
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--accent);
  font-style: normal;
}

.lede {
  margin-top: 1.4rem;
  font-size: clamp(1.05rem, 1.7vw, 1.3rem);
  color: var(--muted);
  max-width: 30rem;
}

.lede b { color: var(--ink); font-weight: 600; }

/* ------------------------------------------------------------ controls */

.cta-row {
  margin-top: 2.25rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem 1.25rem;
}

.btn {
  appearance: none;
  border: 0;
  font: inherit;
  font-weight: 650;
  letter-spacing: -0.015em;
  padding: 0.95rem 1.6rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  cursor: pointer;
  transition: transform 160ms var(--ease), background 160ms var(--ease);
}

.btn:hover { background: var(--accent-deep); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn.ghost {
  background: transparent;
  color: var(--ink);
  border: 1.5px solid var(--line);
  font-weight: 600;
}

.btn.ghost:hover { border-color: var(--ink); background: transparent; }

.btn:focus-visible, .drop:focus-visible, a:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

/* The one place the voice goes completely flat. */
.promise {
  font-size: 0.95rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.promise svg { flex: none; }

/* ------------------------------------------------------- screenshot panel */

.panel {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px oklch(0.19 0.03 340 / 0.05),
              0 12px 32px -8px oklch(0.19 0.03 340 / 0.12),
              0 40px 80px -30px oklch(0.19 0.03 340 / 0.16);
  overflow: hidden;
}

.panel-head {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  padding: 12px 16px 10px;
  text-align: center;
}

.avatar {
  width: 46px; height: 46px; line-height: 46px;
  border-radius: 50%;
  background: oklch(0.72 0.01 250);
  color: #fff;
  font: 500 17px var(--apple);
  display: inline-block;
}

.panel-name { font: 500 13px var(--apple); margin-top: 5px; color: #000; }

.thread { padding: 6px 14px 20px; font-family: var(--apple); }

.divider {
  text-align: center;
  margin: 18px 0 10px;
  font: 600 11px var(--apple);
  color: #8E8E93;
}
.divider span { font-weight: 400; }

.row { margin-top: 8px; }
.row.tight { margin-top: 2px; }
.row.me { text-align: right; }

.bub {
  display: inline-block;
  max-width: 74%;
  padding: 7px 13px;
  font-size: 17px;
  line-height: 1.32;
  text-align: left;
  word-break: break-word;
  background: var(--ios-gray);
  color: #000;
  border-radius: 18px 18px 18px 4px;
}

.me .bub {
  background: var(--ios-blue);
  color: #fff;
  border-radius: 18px 18px 4px 18px;
}

.who { margin: 8px 0 2px 14px; font: 400 11px var(--apple); color: #8E8E93; }

/* ------------------------------------------------------------- sections */

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

.eyebrow {
  color: var(--accent);
  font-weight: 700;
  font-size: 0.95rem;
  margin-bottom: 0.75rem;
}

.steps {
  margin-top: clamp(2rem, 5vw, 3rem);
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

@media (min-width: 780px) { .steps { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1000px) { .steps.eight { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 600px) and (max-width: 999px) { .steps.eight { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 599px) { .steps.eight { grid-template-columns: 1fr; } }

.steps.eight .step { padding: clamp(1.1rem, 2.2vw, 1.5rem); }
.steps.eight .step h3 { font-size: 1.05rem; margin-bottom: 0.45rem; }
.steps.eight .step p { font-size: 0.9rem; }
.steps.eight .emoji { font-size: 1.6rem; display: block; margin-bottom: 0.5rem; line-height: 1; }

.step { background: var(--bg); padding: clamp(1.5rem, 3vw, 2.1rem); }
.step b { display: block; font-size: 2rem; font-weight: 800; color: var(--accent); letter-spacing: -0.04em; }
.step h3 { margin: 0.4rem 0 0.5rem; }
.step p { color: var(--muted); font-size: 0.97rem; }

kbd {
  font-family: var(--sans);
  font-weight: 650;
  font-size: 0.9em;
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 6px;
  padding: 0.1em 0.45em;
  color: var(--ink);
}

/* ------------------------------------------------------------ drop zone */

.drop {
  margin-top: clamp(2rem, 5vw, 3rem);
  border: 2px dashed var(--line);
  border-radius: var(--radius);
  padding: clamp(2.5rem, 7vw, 4.5rem) var(--pad);
  text-align: center;
  background: var(--bg);
  transition: border-color 180ms var(--ease), background 180ms var(--ease);
  cursor: pointer;
}

.drop:hover { border-color: oklch(0.78 0.14 352); }
.drop.over { border-color: var(--accent); background: var(--accent-wash); }
.drop h3 { margin-bottom: 0.4rem; }
.drop p { color: var(--muted); }

/* -------------------------------------------------------------- counter */

.counter { display: none; text-align: center; padding-block: clamp(2rem, 6vw, 3.5rem); }
.counter.on { display: block; }

.tick {
  font-size: clamp(2.6rem, 8vw, 5rem);
  font-weight: 800;
  letter-spacing: -0.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.tick-label { color: var(--muted); margin-top: 0.6rem; }

.bar {
  max-width: 22rem;
  margin: 1.75rem auto 0;
  height: 4px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}

.bar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width 300ms var(--ease); }

/* --------------------------------------------------------------- result */

.result { display: none; }
.result.on { display: block; }

.reveal { animation: rise 420ms var(--ease-out) both; }
/* Shuffle is the most repeated action in the product. A 420ms panel rise on
   every swap reads as sluggish, so repeats get opacity only. */
.reveal.again { animation: fadein 180ms var(--ease-out) both; }

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }

.memory-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.75rem 1.5rem; margin-bottom: 1.5rem; }
.memory-head .ago { color: var(--accent); font-weight: 700; }
.memory-head .meta { color: var(--muted); font-size: 0.95rem; }

.result-grid { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 940px) { .result-grid { grid-template-columns: 1fr 380px; align-items: start; } }

/* ----------------------------------------------------------- stats card */

.card {
  background: var(--card, var(--accent));
  color: var(--card-ink, var(--accent-ink));
  transition: background 300ms var(--ease-out), color 300ms var(--ease-out);
  border-radius: var(--radius);
  padding: clamp(1.75rem, 4vw, 2.5rem);
}

.card h3 { font-size: 1.1rem; opacity: 0.75; font-weight: 650; }
.card dl { margin: 1.5rem 0 0; display: grid; gap: 1.25rem; }
.card dt { font-size: 0.9rem; opacity: 0.75; font-weight: 600; }
.card dd {
  margin: 0.1rem 0 0;
  font-size: clamp(1.7rem, 3.5vw, 2.3rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.card .btn { background: var(--card-ink, var(--accent-ink)); color: var(--card, var(--accent)); margin-top: 1.75rem; width: 100%; }
.card .btn:hover { background: var(--card-ink, var(--accent-ink)); opacity: 0.9; }

footer {
  border-top: 1px solid var(--line);
  padding-block: 2.5rem 4rem;
  color: var(--muted);
  font-size: 0.92rem;
}

.err {
  display: none;
  margin-top: 1.25rem;
  padding: 1rem 1.25rem;
  border-radius: 12px;
  background: var(--accent-wash);
  color: var(--accent-deep);
  font-weight: 600;
}
.err.on { display: block; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* The contact name is user-supplied: chat.db has no names, so this is
   editable and should look it. */
[data-name] {
  outline: none;
  border-bottom: 1px dashed var(--line);
  cursor: text;
  min-width: 4ch;
  display: inline-block;
}
[data-name]:hover, [data-name]:focus { border-bottom-color: var(--accent); }

/* Participant naming for group threads */
.namer { display: none; margin-bottom: 1.1rem; }
.namer.on { display: block; }
.namer-hint { color: var(--muted); font-size: 0.95rem; margin-bottom: 0.7rem; max-width: 42rem; }

.chip {
  display: inline-block;
  margin: 0 0.4rem 0.4rem 0;
  padding: 0.3rem 0.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.92rem;
  background: var(--bg);
  transition: border-color 150ms var(--ease), background 150ms var(--ease);
}
.chip [contenteditable] { outline: none; min-width: 3ch; display: inline-block; }
.chip:focus-within { border-color: var(--accent); }
.chip.named { background: var(--butter); border-color: var(--butter-deep); font-weight: 650; }

.export-note { margin-top: 0.6rem; font-size: 0.9rem; color: var(--muted); }

/* ------------------------------------------------- onboarding: the three */

.onboard { display: none; }
.onboard.on { display: block; }

.people { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line);
          border-radius: var(--radius); overflow: hidden; margin-top: clamp(1.5rem,4vw,2.5rem); }
@media (min-width: 800px) { .people { grid-template-columns: repeat(3, 1fr); } }

.person { background: var(--bg); padding: clamp(1.4rem, 3vw, 1.9rem); }
.person .count { font-size: clamp(1.9rem, 3.4vw, 2.5rem); font-weight: 800;
                 letter-spacing: -0.04em; color: var(--accent); line-height: 1; font-variant-numeric: tabular-nums; }
.person .count small { display: block; font-size: 0.8rem; font-weight: 600; color: var(--muted);
                       letter-spacing: 0; margin-top: 0.35rem; }
.person .handle { font-size: 0.85rem; color: var(--muted); margin: 0.9rem 0 0.3rem; }

.person input[type=text] {
  width: 100%; font: inherit; font-weight: 650; font-size: 1.05rem;
  padding: 0.55rem 0.7rem; border: 1.5px solid var(--line); border-radius: 10px;
  background: var(--bg); color: var(--ink);
}
.person input[type=text]::placeholder { color: oklch(0.72 0.01 40); font-weight: 400; }
.person input[type=text]:focus { outline: none; border-color: var(--accent); }

.rels { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.7rem; }
.rel {
  font: inherit; font-size: 0.85rem; font-weight: 550;
  padding: 0.3rem 0.7rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: var(--bg); color: var(--muted);
  transition: all 140ms var(--ease);
}
.rel:hover { border-color: var(--accent); color: var(--ink); }
.rel[aria-pressed="true"] { background: var(--accent); border-color: var(--accent);
                            color: var(--accent-ink); font-weight: 650; }

/* ------------------------------------------------------------ categories */

.cats { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-bottom: 1.4rem; }
.cats .spacer { flex: 1 1 auto; min-width: 0.5rem; }
.cats .btn { padding: 0.5rem 1.15rem; font-size: 0.95rem; }
.cat {
  font: inherit; font-size: 0.95rem; font-weight: 600;
  padding: 0.5rem 1rem; border-radius: 999px; cursor: pointer;
  border: 1.5px solid var(--line); background: var(--bg); color: var(--ink);
  transition: all 150ms var(--ease);
}
.cat:hover { border-color: var(--accent); }
.cat[aria-pressed="true"] { background: var(--accent); border-color: var(--accent);
                            color: var(--accent-ink); }
.cat .e { margin-right: 0.35rem; }
.cat.locked { opacity: 0.45; cursor: not-allowed; }
.cat.locked:hover { border-color: var(--line); }

.summary {
  margin: 0 0 1.2rem; padding: 1rem 1.2rem;
  background: var(--butter); border-radius: 14px;
  font-size: 1.02rem; line-height: 1.55; color: var(--ink);
}
.summary.empty { display: none; }

.expand { margin-top: 0.8rem; }
.expand button {
  font: inherit; font-size: 0.92rem; font-weight: 600; color: var(--accent);
  background: none; border: 0; cursor: pointer; padding: 0.4rem 0;
}
.expand button:hover { color: var(--accent-deep); text-decoration: underline; }

/* ---------------------------------------- onboarding: who is this person? */

.peek { margin: 0.9rem 0 1rem; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; }

.peek-bar {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--surface); border-bottom: 1px solid var(--line);
  padding: 0.3rem 0.4rem; font-size: 0.78rem; font-weight: 650; color: var(--muted);
}
.peek-nav {
  font: inherit; font-size: 1.15rem; line-height: 1; font-weight: 400;
  background: none; border: 0; cursor: pointer; color: var(--muted);
  padding: 0.1rem 0.5rem; border-radius: 6px;
}
.peek-nav:hover { color: var(--accent); background: var(--bg); }

.peek-thread { padding: 0.55rem 0.5rem; background: var(--bg); min-height: 6.5rem; }
.peek-row { margin-bottom: 3px; }
.peek-row.me { text-align: right; }
.peek-row span {
  display: inline-block; max-width: 88%;
  padding: 3px 8px; border-radius: 11px;
  font: 400 12px/1.35 var(--apple);
  background: var(--ios-gray); color: #000;
  text-align: left; word-break: break-word;
}
.peek-row.me span { background: var(--ios-blue); color: #fff; }

.peek-dots { display: flex; gap: 4px; justify-content: center; padding: 0 0 0.45rem; }
.peek-dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
.peek-dots i.on { background: var(--accent); }

/* Cards stretch to the tallest in the row; push the name field to the bottom
   of each so the three inputs line up regardless of preview length. */
.person { display: flex; flex-direction: column; }
.person input[type=text] { margin-top: auto; }

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

/* 1 — the once-ever moment. Cards carrying "101,719 messages" should not
       teleport; this is where the delight budget belongs. */
.person { animation: cardin 320ms var(--ease-out) both; }
.person:nth-child(2) { animation-delay: 70ms; }
.person:nth-child(3) { animation-delay: 140ms; }
@keyframes cardin { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* 3 — carousel paging carries a direction; the motion should say so. */
.peek-thread { animation: slidein 200ms var(--ease-out) both; }
.peek-thread.back { animation-name: slideinback; }
@keyframes slidein     { from { opacity: 0; transform: translateX(8px);  } to { opacity: 1; transform: none; } }
@keyframes slideinback { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: none; } }

/* 4 — reveal the newly expanded rows, not the whole thread. Capped so a
       400-message day does not run 400 staggered animations. */
.row.fresh { animation: fadein 240ms var(--ease-out) both; }
.row.fresh:nth-child(-n+12) { animation-delay: calc(8ms * var(--i, 0)); }

/* 5 — the result section arriving */
.result.on { animation: fadein 260ms var(--ease-out) both; }

/* 6 — press feedback where it was missing */
.cat, .rel, .peek-nav { transition: transform 140ms var(--ease-out),
                                    background 140ms var(--ease-out),
                                    border-color 140ms var(--ease-out),
                                    color 140ms var(--ease-out); }
.cat:active, .rel:active, .peek-nav:active { transform: scale(0.96); }

@media (prefers-reduced-motion: reduce) {
  /* Gentler, not zero: everything crossfades in place. */
  .person, .peek-thread, .row.fresh, .result.on, .reveal, .reveal.again {
    animation: fadein 1ms both !important;
  }
}

/* ------------------------------------------------- mood-coloured pills */

.cat { --c: var(--accent); --ci: #fff; }
.cat:hover { border-color: var(--c); }
.cat[aria-pressed="true"] {
  background: var(--c); border-color: var(--c); color: var(--ci);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--c) 22%, transparent);
}

/* ------------------------------------------------------- shuffle is not
   a tab. It is the thing you press over and over, so it gets its own band. */
.shuffle-bar {
  display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap;
  padding: 1rem 1.25rem; margin-bottom: 1.5rem;
  border: 1px solid var(--line); border-radius: 16px;
  background: color-mix(in oklch, var(--mood, var(--accent)) 8%, var(--bg));
}
.shuffle-hint { color: var(--muted); font-size: 0.95rem; }

/* -------------------------------------------- buttons, coloured by job */

.btn.go   { background: oklch(0.86 0.24 130); color: #0d1a05; }
.btn.go:hover   { background: oklch(0.80 0.24 130); }
.btn.save { background: oklch(0.82 0.15 200); color: #04222b; }
.btn.save:hover { background: oklch(0.76 0.15 200); }
.btn.big  { font-size: 1.08rem; padding: 1.05rem 1.9rem; }

/* ------------------------------------------------ onboarding confirm */

/* Same pill language as every other control on the page. */
.person .confirm {
  margin-top: 0.85rem;
  align-self: flex-start;
  padding: 0.6rem 1.3rem;
  font-size: 0.95rem;
  background: var(--bg);
  color: var(--muted);
  border: 1.5px solid var(--line);
}
.person .confirm:not(:disabled):hover {
  background: var(--bg); color: var(--ink); border-color: var(--ink);
  transform: translateY(-1px);
}
.person .confirm:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

.person.done .confirm,
.person.done .confirm:hover {
  background: oklch(0.86 0.16 165);
  border-color: oklch(0.86 0.16 165);
  color: #032018;
  animation: pop 300ms var(--ease-out);
}
.person.done .confirm .tick {
  display: inline-block;
  font-size: 0.85em;                 /* was inheriting full button size */
  margin-right: 0.4em;
  animation: tickin 260ms var(--ease-out) both;
}
@keyframes pop  { 0% { transform: scale(1); } 45% { transform: scale(1.04); } 100% { transform: scale(1); } }
@keyframes tickin { from { opacity: 0; transform: scale(0.55); } to { opacity: 1; transform: none; } }

/* ------------------------------------------- relationship, colour-coded */

.rel { --c: var(--accent); --ci: #fff; }
.rel .e { margin-right: 0.3rem; font-size: 0.95em; }
.rel:hover { border-color: var(--c); color: var(--ink); }
.rel[aria-pressed="true"] {
  background: var(--c); border-color: var(--c); color: var(--ci); font-weight: 650;
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--c) 22%, transparent);
}

/* ------------------------------------------ the file step, made gentler */

.step em { font-style: normal; font-weight: 650; color: var(--ink); }
.step code {
  font-family: var(--sans); font-weight: 650; font-size: 0.92em;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 6px; padding: 0.08em 0.4em;
}

.copy {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font: inherit; cursor: pointer;
  background: var(--bg); border: 1.5px solid var(--line);
  border-radius: 999px; padding: 0.3rem 0.4rem 0.3rem 0.6rem;
  margin: 0 0.3rem 0.35rem 0;
  transition: border-color 150ms var(--ease-out), transform 150ms var(--ease-out);
}
.copy:hover { border-color: var(--accent); }
.copy:active { transform: scale(0.97); }
.copy code { background: none; border: 0; padding: 0; }
.copy-label {
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em;
  background: var(--accent); color: var(--accent-ink);
  border-radius: 999px; padding: 0.2rem 0.6rem;
}
.copy.done .copy-label { background: oklch(0.86 0.16 165); color: #032018; }

.help {
  margin-top: 1.5rem; border: 1px solid var(--line); border-radius: 14px;
  padding: 0.9rem 1.2rem; background: var(--bg); max-width: 46rem;
}
.help summary { cursor: pointer; font-weight: 650; }
.help summary::marker { color: var(--accent); }
.help p { margin-top: 0.8rem; color: var(--muted); font-size: 0.97rem; }

/* ======================================================================
   Touch and small screens.
   Measured at 320-430px: no horizontal overflow anywhere, so the layout
   itself holds. What failed was touch — carousel arrows at 20x22px, pills
   at 33px, all under the 44px minimum — and nine mood pills wrapping into
   a wall on a 390px screen.
   ====================================================================== */

/* Hover belongs to devices that have a pointer. On touch these fire on tap
   and stick, which reads as a stuck state. */
@media (hover: none) {
  .btn:hover, .cat:hover, .rel:hover, .who:hover, .chip:hover,
  .drop:hover, .copy:hover, .peek-nav:hover, .person .confirm:not(:disabled):hover {
    transform: none;
    background: inherit;
  }
}

@media (pointer: coarse) {
  .cat, .rel, .who, .copy, .btn {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .peek-nav { min-width: 44px; min-height: 44px; }
  .help summary { padding: 0.55rem 0; }
  .chip { padding: 0.55rem 0.9rem; }
  .rels { gap: 0.5rem; }
}

/* On a phone, a wrapping pill wall is worse than a swipeable strip. Both rows
   become one horizontal lane with snap points and the scrollbar hidden. */
@media (max-width: 720px) {
  .cats, .who-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 0.35rem;
    /* bleed to the screen edge so the strip reads as scrollable */
    margin-inline: calc(var(--pad) * -1);
    padding-inline: var(--pad);
  }
  .cats::-webkit-scrollbar, .who-row::-webkit-scrollbar { display: none; }
  .cat, .who { flex: 0 0 auto; scroll-snap-align: start; }
  .who-label { flex: 0 0 auto; }

  .shuffle-bar { padding: 0.85rem 1rem; }
  .shuffle-bar .btn { flex: 1 1 auto; }
  .shuffle-hint { display: none; }

  /* Bubbles can run wider when the screen is narrow. */
  .bub { max-width: 84%; }
  .memory-head { gap: 0.35rem 1rem; }
}

/* Notches and home indicators. */
@media (max-width: 720px) {
  .wrap { padding-inline: max(var(--pad), env(safe-area-inset-left)); }
  footer { padding-bottom: max(4rem, calc(2rem + env(safe-area-inset-bottom))); }
}

@media (pointer: coarse) {
  /* The expand control is a text button; give it a real tap area. */
  .expand button { min-height: 44px; padding-inline: 0.25rem; }

  /* The contact name is editable but lives inside the faux screenshot, which
     has to keep looking like a real one. Grow the hit area, not the type. */
  .panel-name { padding: 0.5rem 0.9rem; }
}

/* The editable name is inline-block so its underline hugs the text; that made
   it flow beside the avatar. Force the avatar onto its own line instead. */
.panel-head .avatar { display: block; margin: 0 auto; }

/* ------------------------------------------------ the logo and wordmark */

.mark { gap: 0.55rem; }
.logo { flex: none; display: block; }

/* --------------------------------------------- the fill-it-in-yourself card */

.person.custom { border-left: 0; background: var(--surface); }
.person.custom .count { color: var(--muted); }
.person.custom .count small { color: var(--muted); }
.custom-note { margin-top: 0.6rem; font-size: 0.88rem; color: var(--muted); }
.person.custom.miss #customhandle,
.person.custom.miss input[type=text] { border-color: var(--accent); }
.person.custom .custom-rest[hidden] { display: none; }
.person.custom #customhandle { margin-top: 0; }

/* ---------------------------------------------------------- the sentence */

.headline {
  font-size: clamp(1.35rem, 2.6vw, 1.95rem);
  font-weight: 650;
  letter-spacing: -0.025em;
  line-height: 1.2;
  margin-bottom: 0.45rem;
  text-wrap: balance;
}
.headline b { font-weight: 800; }
.headline em { font-style: normal; color: var(--accent); font-weight: 750; }
.headline .gap {
  display: block;
  font-size: 0.62em;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0;
  margin-top: 0.3rem;
}

.memory-head { margin-bottom: 1.35rem; }
.memory-head .ago { display: none; }   /* the sentence carries this now */

@media (max-width: 720px) {
  .who-row { margin-inline: calc(var(--pad) * -1); padding-inline: var(--pad); }
  .who { padding: 0.7rem 0.85rem; }
}

/* ======================================================================
   The picker.
   Same pill everywhere; the *container* does the distinguishing, not the
   control. Two labelled boxes, one per question: who, and what mood.
   ====================================================================== */

.picker { display: grid; gap: 0.75rem; margin-bottom: 1.25rem; }

.picker-box {
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 0.95rem 1.15rem 1.05rem;
}
.picker-box[hidden] { display: none; }

.picker-label {
  font-size: 0.95rem;
  font-weight: 750;
  letter-spacing: -0.01em;
  color: var(--muted);
  margin-bottom: 0.7rem;
}

/* People: a cool, quiet container. Mood: tinted by whatever is selected, so
   the box itself confirms the choice. */
.box-people {
  background: color-mix(in oklch, oklch(0.62 0.14 250) 11%, var(--bg));
  border-color: color-mix(in oklch, oklch(0.62 0.14 250) 34%, var(--line));
}
.box-people .picker-label { color: oklch(0.45 0.10 250); }

.box-mood {
  background: color-mix(in oklch, var(--mood, var(--accent)) 8%, var(--bg));
  border-color: color-mix(in oklch, var(--mood, var(--accent)) 25%, var(--line));
  transition: background 260ms var(--ease-out), border-color 260ms var(--ease-out);
}
.box-mood .picker-label { color: color-mix(in oklch, var(--mood, var(--accent)) 70%, var(--ink)); }

/* One pill, used twice. */
.who {
  font: inherit; font-size: 0.95rem; font-weight: 600;
  padding: 0.5rem 1rem 0.5rem 0.55rem;
  border-radius: 999px; cursor: pointer;
  border: 1.5px solid var(--line);
  background: var(--bg); color: var(--ink);
  display: inline-flex; align-items: center; gap: 0.45rem;
  transition: transform 140ms var(--ease-out), background 140ms var(--ease-out),
              border-color 140ms var(--ease-out), color 140ms var(--ease-out);
}
.who:hover { border-color: oklch(0.62 0.14 250); }
.who:active { transform: scale(0.96); }
.who .e { font-size: 1em; }
.who .av {
  width: 22px; height: 22px; border-radius: 50%;
  background: oklch(0.86 0.05 250); color: oklch(0.34 0.09 250);
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.01em;
  display: inline-flex; align-items: center; justify-content: center;
}
.who[aria-pressed="true"] {
  background: oklch(0.42 0.14 250); border-color: oklch(0.42 0.14 250); color: #fff;
  box-shadow: 0 0 0 4px color-mix(in oklch, oklch(0.42 0.14 250) 18%, transparent);
}
.who[aria-pressed="true"] .av { background: rgba(255,255,255,0.25); color: #fff; }

.who-row, .cats { margin-bottom: 0; }
.cats { margin-bottom: 0; }

@media (min-width: 900px) {
  .picker { grid-template-columns: minmax(240px, 0.9fr) 2.1fr; align-items: start; }
}
@media (max-width: 720px) {
  .picker-box { padding: 0.85rem 0 0.9rem; border-radius: 16px; }
  .picker-label { padding-inline: var(--pad); }
  .who-row, .cats { margin-inline: 0; padding-inline: 0.9rem; }
}

/* ===================================================================== */
/* Passive background: message bubbles drifting up, very slowly.          */
/* Thematic rather than decorative, and cheap — 14 elements, transform    */
/* and opacity only, never hit-testable.                                  */
/* ===================================================================== */

.bg {
  position: fixed; inset: 0; z-index: -1;
  pointer-events: none; overflow: hidden;
  contain: strict;
}
.bg i {
  position: absolute;
  display: block;
  width: 90px; height: 44px;
  border-radius: 22px 22px 22px 6px;
  background: color-mix(in oklch, var(--accent) 12%, transparent);
  opacity: 0;
  animation: drift linear infinite;
  will-change: transform, opacity;
}
.bg i:nth-child(even) {
  border-radius: 22px 22px 6px 22px;
  background: color-mix(in oklch, var(--ios-blue) 9%, transparent);
}

@keyframes drift {
  0%   { transform: translate3d(0, 20vh, 0) scale(0.9); opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translate3d(var(--dx, 40px), -110vh, 0) scale(1.05); opacity: 0; }
}

.bg i:nth-child(1)  { left:  4%; width: 70px;  height: 36px; animation-duration: 64s; animation-delay:  -2s; --dx:  30px; }
.bg i:nth-child(2)  { left: 13%; width: 110px; height: 50px; animation-duration: 82s; animation-delay: -30s; --dx: -40px; }
.bg i:nth-child(3)  { left: 22%; width: 60px;  height: 32px; animation-duration: 71s; animation-delay: -55s; --dx:  50px; }
.bg i:nth-child(4)  { left: 31%; width: 130px; height: 56px; animation-duration: 95s; animation-delay: -12s; --dx: -25px; }
.bg i:nth-child(5)  { left: 40%; width: 80px;  height: 40px; animation-duration: 76s; animation-delay: -68s; --dx:  35px; }
.bg i:nth-child(6)  { left: 49%; width: 100px; height: 46px; animation-duration: 88s; animation-delay: -40s; --dx: -55px; }
.bg i:nth-child(7)  { left: 57%; width: 66px;  height: 34px; animation-duration: 69s; animation-delay: -20s; --dx:  20px; }
.bg i:nth-child(8)  { left: 65%; width: 120px; height: 52px; animation-duration: 91s; animation-delay: -75s; --dx: -30px; }
.bg i:nth-child(9)  { left: 73%; width: 74px;  height: 38px; animation-duration: 79s; animation-delay:  -8s; --dx:  45px; }
.bg i:nth-child(10) { left: 81%; width: 95px;  height: 44px; animation-duration: 86s; animation-delay: -50s; --dx: -35px; }
.bg i:nth-child(11) { left: 88%; width: 62px;  height: 32px; animation-duration: 73s; animation-delay: -62s; --dx:  25px; }
.bg i:nth-child(12) { left: 94%; width: 105px; height: 48px; animation-duration: 99s; animation-delay: -35s; --dx: -45px; }
.bg i:nth-child(13) { left: 36%; width: 58px;  height: 30px; animation-duration: 66s; animation-delay: -85s; --dx:  38px; }
.bg i:nth-child(14) { left: 68%; width: 88px;  height: 42px; animation-duration: 93s; animation-delay: -18s; --dx: -20px; }

/* Motion in the periphery is the least welcome kind. Freeze it, don't hide it. */
@media (prefers-reduced-motion: reduce) {
  .bg i { animation: none; opacity: 0.5; transform: translate3d(0, 30vh, 0); }
}

/* ------------------------------------------------- desktop-only notice */

.desktop-only {
  margin-top: 0.85rem;
  font-size: 0.88rem;
  color: color-mix(in oklch, var(--ink) 42%, transparent);
  letter-spacing: 0.005em;
  display: flex; align-items: baseline; gap: 0.45rem;
}
.desktop-only .dot {
  flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: var(--butter-deep); transform: translateY(-1px);
}

.mobile-gate {
  position: fixed; inset: 0; z-index: var(--z-toast);
  background: color-mix(in oklch, var(--ink) 55%, transparent);
  backdrop-filter: blur(6px);
  display: grid; place-items: center; padding: var(--pad);
  animation: fadein 240ms var(--ease-out) both;
}
.mobile-gate[hidden] { display: none; }
.mobile-gate-inner {
  background: var(--bg); border-radius: 22px;
  padding: 2rem 1.6rem 1.6rem; max-width: 25rem; text-align: center;
  color: var(--accent);
  animation: rise 340ms var(--ease-out) both;
}
.mobile-gate-inner h3 { color: var(--ink); margin: 0.8rem 0 0.6rem; }
.mobile-gate-inner p { color: var(--muted); font-size: 0.97rem; margin-bottom: 1.3rem; }
.mobile-gate-inner b { color: var(--ink); }

/* --------------------------- a card that is done should take up less room */

.person .peek {
  max-height: 320px;
  opacity: 1;
  transition: max-height 380ms var(--ease-out), opacity 240ms var(--ease-out),
              margin 380ms var(--ease-out);
}
.person.done .peek {
  max-height: 0;
  opacity: 0;
  margin-block: 0;
  overflow: hidden;
  border-color: transparent;
}
.person.done .rels { display: none; }          /* the choice is made */
.person.done input[type=text] {
  border-color: transparent;
  background: transparent;
  padding-inline: 0;
  font-size: 1.15rem;
  font-weight: 750;
}
.person.done .handle { opacity: 0.55; }

/* The counter hands off to the onboarding rather than blinking out. */
.counter { transition: opacity 280ms var(--ease-out), transform 280ms var(--ease-out); }
.counter.leaving { opacity: 0; transform: translateY(-16px); }

/* A collapsed card should shrink from the bottom, not strand its content
   there — the auto margin that aligns the un-added cards must not apply. */
.person.done input[type=text] { margin-top: 0.4rem; }
.person.done { justify-content: flex-start; }

/* Four cards in a three-column grid left two empty cells showing the grid
   background. The custom card spans the row instead, which also makes it
   harder to miss. */
.person.custom { grid-column: 1 / -1; }
@media (min-width: 800px) {
  .person.custom { display: grid; grid-template-columns: auto 1fr; gap: 0 1.6rem; align-items: start; }
  .person.custom .count { grid-row: 1; }
  .person.custom .handle { grid-row: 2; align-self: start; margin-top: 0; }
  .person.custom #customhandle,
  .person.custom .custom-note { grid-column: 2; }
  .person.custom #customhandle { grid-row: 1; margin-top: 0.2rem; max-width: 22rem; }
  .person.custom .custom-note { grid-row: 2; margin-top: 0.2rem; }
  .person.custom .custom-rest { grid-column: 1 / -1; }
}

/* --------------------------------------------- the privacy shield, green */

.promise {
  display: flex; align-items: flex-start; gap: 0.6rem;
  color: oklch(0.52 0.14 158);
  font-size: 0.95rem; line-height: 1.5;
  max-width: 32rem; margin-top: 0.2rem;
}
.promise .shield { flex: none; margin-top: 0.1rem; }
.promise b { color: oklch(0.40 0.13 158); font-weight: 700; }
.promise .caveat { display: block; color: var(--muted); margin-top: 0.2rem; font-size: 0.9rem; }

.foot-row { display: flex; align-items: flex-start; gap: 0.65rem; }
.foot-row .shield { flex: none; color: oklch(0.52 0.14 158); margin-top: 0.05rem; }
.foot-row b { color: var(--ink); font-weight: 700; }

/* ------------------------------------------------------- the AI summary */

.summary {
  position: relative;
  padding: 1.15rem 1.3rem 1.15rem 3rem;
  background: linear-gradient(180deg,
    color-mix(in oklch, var(--butter) 55%, var(--bg)),
    color-mix(in oklch, var(--butter) 25%, var(--bg)));
  border: 1px solid color-mix(in oklch, var(--butter-deep) 40%, transparent);
  border-radius: 16px;
  font-size: 1rem; line-height: 1.6;
}
.summary::before {
  content: '✨';
  position: absolute; left: 1.05rem; top: 1.05rem;
  font-size: 1.15rem; line-height: 1;
}
.summary p { margin: 0 0 0.6rem; }
.summary p:last-child { margin-bottom: 0; }
.summary b { font-weight: 750; color: var(--ink); }
.summary em { font-style: italic; color: oklch(0.42 0.16 30); }

/* ===================================================================== */
/* Contact glyph.                                                        */
/* A neutral silhouette in the relationship's colour rather than initials */
/* or a guess at who someone is. Drawn as a mask so one shape tints any   */
/* number of ways.                                                       */
/* ===================================================================== */

.avatar, .who .av {
  --glyph: oklch(0.72 0.02 340);
  background: color-mix(in oklch, var(--glyph) 26%, oklch(0.97 0 0));
  color: transparent;
  position: relative;
  overflow: hidden;
}
.avatar::after, .who .av::after {
  content: '';
  position: absolute; inset: 0;
  background: var(--glyph);
  -webkit-mask: var(--person) center/contain no-repeat;
          mask: var(--person) center/contain no-repeat;
}

:root {
  --person: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath d='M24 23.6a7.6 7.6 0 1 0 0-15.2 7.6 7.6 0 0 0 0 15.2Zm0 3.4c-7.6 0-14 4.3-14 9.6 0 1.2.4 2.2 1 3.1a23.6 23.6 0 0 0 26 0c.6-.9 1-1.9 1-3.1 0-5.3-6.4-9.6-14-9.6Z' fill='white'/%3E%3C/svg%3E");
}

/* the six relationship tints, plus a neutral */
.avatar[data-av="partner"], .who .av[data-av="partner"] { --glyph: oklch(0.62 0.20 350); }
.avatar[data-av="mom"],     .who .av[data-av="mom"]     { --glyph: oklch(0.66 0.15 35);  }
.avatar[data-av="dad"],     .who .av[data-av="dad"]     { --glyph: oklch(0.58 0.12 195); }
.avatar[data-av="sibling"], .who .av[data-av="sibling"] { --glyph: oklch(0.58 0.18 300); }
.avatar[data-av="best"],    .who .av[data-av="best"]    { --glyph: oklch(0.62 0.18 130); }
.avatar[data-av="close"],   .who .av[data-av="close"]   { --glyph: oklch(0.64 0.15 85);  }
.avatar[data-av="other"],   .who .av[data-av="other"]   { --glyph: oklch(0.58 0.04 340); }

.who .av { width: 24px; height: 24px; }
.who[aria-pressed="true"] .av { --glyph: #fff; background: rgba(255,255,255,0.22); }

/* ======================================================================
   First load.
   Not a spinner — there is nothing to wait for. An entrance, and the one
   the product suggests: the conversation arrives the way a conversation
   arrives. Everything below is visible by default; `.intro` only plays it.
   ====================================================================== */

.intro .mark            { animation: liftin 520ms var(--ease-out) both; }
.intro .hero h1         { animation: liftin 620ms var(--ease-out) 90ms both; }
.intro .hero .lede      { animation: liftin 560ms var(--ease-out) 260ms both; }
.intro .hero .cta-row   { animation: liftin 560ms var(--ease-out) 360ms both; }
.intro .desktop-only    { animation: liftin 520ms var(--ease-out) 460ms both; }
.intro .hero .panel     { animation: panelin 720ms var(--ease-out) 180ms both; }
.intro .bg              { animation: fadein 1400ms var(--ease-out) 700ms both; }

@keyframes liftin  { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes panelin { from { opacity: 0; transform: translateY(22px) scale(0.985); }
                     to   { opacity: 1; transform: none; } }

/* The thread fills in one message at a time, alternating sides, with the small
   scale-up an arriving iMessage has. Eleven bubbles at 95ms lands at ~1.5s —
   long enough to read as a conversation, short enough not to be a wait. */
.intro .hero .panel .divider,
.intro .hero .panel .row { animation: msgin 300ms var(--ease-out) both; }

@keyframes msgin {
  from { opacity: 0; transform: translateY(9px) scale(0.94); }
  to   { opacity: 1; transform: none; }
}

.intro .hero .panel .thread > *:nth-child(1)  { animation-delay: 560ms; }
.intro .hero .panel .thread > *:nth-child(2)  { animation-delay: 655ms; }
.intro .hero .panel .thread > *:nth-child(3)  { animation-delay: 750ms; }
.intro .hero .panel .thread > *:nth-child(4)  { animation-delay: 845ms; }
.intro .hero .panel .thread > *:nth-child(5)  { animation-delay: 940ms; }
.intro .hero .panel .thread > *:nth-child(6)  { animation-delay: 1035ms; }
.intro .hero .panel .thread > *:nth-child(7)  { animation-delay: 1130ms; }
.intro .hero .panel .thread > *:nth-child(8)  { animation-delay: 1225ms; }
.intro .hero .panel .thread > *:nth-child(9)  { animation-delay: 1320ms; }
.intro .hero .panel .thread > *:nth-child(10) { animation-delay: 1415ms; }
.intro .hero .panel .thread > *:nth-child(11) { animation-delay: 1510ms; }
.intro .hero .panel .thread > *:nth-child(12) { animation-delay: 1605ms; }

/* The arrow draws itself, so the mark resolves rather than simply appearing. */
.intro .logo .arrow {
  stroke-dasharray: 22;
  stroke-dashoffset: 22;
  animation: draw 620ms var(--ease-out) 240ms both;
}
@keyframes draw { to { stroke-dashoffset: 0; } }

/* Nothing above applies without .intro, which is only set when motion is
   welcome — so reduced-motion users get the finished page immediately. */

.btn.share { background: var(--ios-blue); color: #fff; }
.btn.share:hover { background: #0063d1; }

.custom-find { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.custom-find input[type=text] { flex: 1 1 16rem; margin-top: 0; }
.custom-find .btn { flex: none; padding: 0.7rem 1.4rem; font-size: 0.95rem; }
