/* nocaps, mobile first. Desktop is the enhancement, not the source. */

@font-face {
  font-family: 'Clash Display';
  src: url('/assets/fonts/clash-display-600.woff2') format('woff2');
  font-weight: 600; font-display: swap; font-style: normal;
}
@font-face {
  font-family: 'Clash Display';
  src: url('/assets/fonts/clash-display-700.woff2') format('woff2');
  font-weight: 700; font-display: swap; font-style: normal;
}
@font-face {
  font-family: 'Satoshi';
  src: url('/assets/fonts/satoshi-variable.woff2') format('woff2-variations');
  font-weight: 300 900; font-display: swap; font-style: normal;
}
@font-face {
  font-family: 'Space Mono';
  src: url('/assets/fonts/space-mono-400-latin.woff2') format('woff2');
  font-weight: 400; font-display: swap; font-style: normal;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2212, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Mono';
  src: url('/assets/fonts/space-mono-700-latin.woff2') format('woff2');
  font-weight: 700; font-display: swap; font-style: normal;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2212, U+FEFF, U+FFFD;
}

:root {
  --grape: #3B1E6E;
  --cream: #FFF6EA;
  --bone: #F0E9DC;
  --plum: #1B0E2B;
  --pink: #FF2E63;
  --lime: #D6F84C;
  /* sanctioned secondaries, ground and fill only, no meaning */
  --yellow: #FFD166;
  --blue: #4CC9F0;
  --lavender: #B191FF;
  --orange: #FF6B35;

  --display: 'Clash Display', 'Arial Black', sans-serif;
  --body: 'Satoshi', system-ui, -apple-system, sans-serif;
  --mono: 'Space Mono', ui-monospace, monospace;

  --pad: 20px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

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

body {
  background: var(--bone);
  color: var(--plum);
  font-family: var(--body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
::selection { background: var(--lime); color: var(--plum); }
:focus-visible { outline: 3px solid var(--plum); outline-offset: 3px; }

/* Several components set display explicitly, which would otherwise beat the
   hidden attribute and leave empty error pills and confirmations on the page. */
[hidden] { display: none !important; }

img, svg { display: block; }
.mug { flex: none; }
.icon { flex: none; }

/* ── sticker kit ──────────────────────────────────────────────────
   3px outline, 6px hard offset shadow, ±1.2° tilt. Everything that
   is a card, chip, bubble or button wears it. */
.sticker {
  border: 3px solid var(--plum);
  box-shadow: 6px 6px 0 var(--plum);
  background: var(--cream);
}
.tilt-l { transform: rotate(-1.2deg); }
.tilt-r { transform: rotate(1.2deg); }
.tilt-l-sm { transform: rotate(-0.7deg); }
.tilt-r-sm { transform: rotate(0.6deg); }

.pill {
  border-radius: 999px;
  border: 3px solid var(--plum);
  box-shadow: 5px 5px 0 var(--plum);
  background: var(--cream);
}


/* ══ Clash Display tracking scale ═══════════════════════════════════════
   Negative tracking is an optical correction, so it has to come off as the
   type gets smaller. One value across every size is exactly what makes Clash
   read welded below about 80px.

     96px and above  -0.05em
     64 to 95px      -0.035em
     40 to 63px      -0.02em
     below 40px       0
     wordmark        -0.035em at any size (exempt from the scale)

   Declared here rather than per element, so it survives every reflow. The
   media queries fire exactly where each clamp() crosses a band boundary,
   which is arithmetic, not taste: .d1 is clamp(52px,6vw,78px) so 6vw hits
   64px at a 1067px viewport, and .close-mark is clamp(72px,11vw,110px) so
   11vw hits 96px at 873px.

   Every Clash element also carries word-spacing 0.16em. Clash has a narrow
   space glyph and tight tracking closes it completely, welding words into
   each other. Mobile is where both rules matter most: the hero headline
   drops from ~78px to 46px, which no single fixed value can serve. */
.d1, .d2, .d3, .d4, .d3-sec, .close-mark, .bio h3, .consent-title, .bar-txt b {
  font-family: var(--display);
  word-spacing: 0.16em;
}
/* below 40px */
.d3, .d4, .d3-sec, .bio h3, .consent-title, .bar-txt b { letter-spacing: 0; }
/* 40 to 63px */
.d1 { letter-spacing: -0.02em; }
/* .d2 is 38px on mobile, so it starts in the bottom band */
.d2 { letter-spacing: 0; }
/* 64 to 95px */
.close-mark { letter-spacing: -0.035em; }

/* The lockup is exempt and stays identical from a 14px footer to a
   billboard, which is what keeps NOCAPS and say more. reading as one pair. */
.wordmark, .ftr-mark .w, .receipt-card .foot .w, .thread-hdr .w {
  font-family: var(--display); font-weight: 700; letter-spacing: -0.035em; word-spacing: normal;
}
.tagline, .ftr-mark .t, .receipt-card .foot .t {
  font-family: var(--display); font-weight: 600; letter-spacing: -0.02em; word-spacing: 0.13em;
}

/* ── type ── */
.d1 { font: 700 46px/0.94 var(--display); text-wrap: balance; }
.d2 { font: 700 38px/0.98 var(--display); text-wrap: balance; }
.d3 { font: 700 23px/1.05 var(--display); }
.d4 { font: 700 19px/1.2 var(--display); }
.lede { font: 500 17px/1.55 var(--body); color: rgba(27, 14, 43, 0.82); text-wrap: pretty; }
.body { font: 500 15px/1.55 var(--body); }
/* 1.35 inside a card, 1.55 in running text */
.card .body, .bio .body, .bubble .body { line-height: 1.35; }
.small { font: 500 13px/1.55 var(--body); color: rgba(27, 14, 43, 0.78); }
.mono { font: 400 10.5px/1.4 var(--mono); text-transform: uppercase; letter-spacing: 0.14em; color: rgba(27, 14, 43, 0.7); }

.on-dark { color: var(--cream); }
.on-dark .lede, .lede.on-dark { color: rgba(255, 246, 234, 0.85); }
.on-dark .small, .small.on-dark { color: rgba(255, 246, 234, 0.7); }

/* ── layout ── */
section { padding: 44px var(--pad); }
.band-cream { background: var(--bone); }
.band-yellow { background: var(--yellow); border-top: 4px solid var(--plum); border-bottom: 4px solid var(--plum); }
.band-plum { background: var(--plum); }
.band-lavender { background: var(--lavender); border-top: 4px solid var(--plum); border-bottom: 4px solid var(--plum); }
.band-grape { background: var(--grape); border-bottom: 4px solid var(--plum); }
.band-lime { background: var(--lime); border-top: 4px solid var(--plum); }

.stack { display: flex; flex-direction: column; }
.gap-12 { gap: 12px; } .gap-14 { gap: 14px; } .gap-16 { gap: 16px; }
.mt-8 { margin-top: 8px; } .mt-12 { margin-top: 12px; } .mt-14 { margin-top: 14px; }
.mt-16 { margin-top: 16px; } .mt-20 { margin-top: 20px; } .mt-22 { margin-top: 22px; }
.mt-26 { margin-top: 26px; } .mt-30 { margin-top: 30px; }

/* ── header ── */
.hdr {
  position: sticky; top: 0; z-index: 40;
  background: var(--bone);
  padding: 14px var(--pad) 12px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
/* Scoped to the wordmark only, `.hdr > a` would also catch the join pill and
   strip the padding that gives it its shape. */
.hdr-mark { display: block; padding: 4px 0; margin: -4px 0; }
.wordmark { font: 700 22px/1 var(--display); letter-spacing: -0.035em; }
.tagline { margin-top: 2px; font: 600 12px/1 var(--display); letter-spacing: -0.02em; word-spacing: 0.13em; color: rgba(27, 14, 43, 0.75); }

/* ── buttons ── */
.btn {
  display: block; width: 100%; text-align: center; cursor: pointer;
  border-radius: 999px; border: 3px solid var(--plum);
  box-shadow: 5px 5px 0 var(--plum);
  padding: 19px 22px;
  font: 700 17px/1 var(--body); color: var(--plum);
  background: var(--lime);
  transform: rotate(-1deg);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
  -webkit-appearance: none; appearance: none;
}
.btn:active { transform: rotate(-1deg) translate(3px, 3px); box-shadow: 2px 2px 0 var(--plum); }
.btn-dark { background: var(--plum); color: var(--cream); box-shadow: 5px 5px 0 var(--grape); }
.btn-dark:active { box-shadow: 2px 2px 0 var(--grape); }
.btn-say { background: var(--plum); color: var(--cream); box-shadow: 4px 4px 0 var(--lavender); padding: 17px 24px; font-size: 16px; }
.btn-say:active { box-shadow: 1px 1px 0 var(--lavender); }
.btn[disabled] { opacity: 0.55; cursor: default; }
.btn-sm {
  display: inline-block; width: auto; cursor: pointer;
  border-radius: 999px; border: 3px solid var(--plum); box-shadow: 3px 3px 0 var(--plum);
  background: var(--lime); padding: 12px 16px; font: 700 13px/1 var(--body);
  transform: rotate(-2deg);
}

.field {
  display: block; width: 100%;
  background: var(--cream);
  border: 3px solid var(--plum); border-radius: 999px;
  box-shadow: 5px 5px 0 var(--plum);
  padding: 19px 22px;
  font: 600 17px/1 var(--body); color: var(--plum);
  -webkit-appearance: none; appearance: none;
}
.field::placeholder { color: rgba(27, 14, 43, 0.45); }
.field:focus { outline: none; box-shadow: 5px 5px 0 var(--grape); }

.note-err {
  display: inline-block; margin-top: 12px;
  background: var(--orange); border: 2.5px solid var(--plum); border-radius: 999px;
  padding: 9px 14px; font: 600 13.5px/1 var(--body); color: var(--plum);
  animation: nc-in 0.3s ease both;
}

/* ── hero ── */
.hero { padding: 14px var(--pad) 0; }
.avatars { display: flex; align-items: center; }
.avatars .mug + .mug { margin-left: -8px; }
.by { display: flex; align-items: center; gap: 11px; margin-top: 18px; }

/* the thread. On mobile it *is* the page, full width, no bezel, and no phone
   chrome: a phone mock inside a phone is the one thing this layout must not do. */
.thread { margin-top: 30px; padding: 0 var(--pad) 44px; display: flex; flex-direction: column; gap: 16px; }
.thread-hdr { display: none; }
.bubble {
  position: relative; border-radius: 22px;
  border: 3px solid var(--plum); box-shadow: 5px 5px 0 var(--plum);
  background: var(--cream); padding: 14px;
}
/* Lavender is the writer's own words (D-075). The live demo held grape
   through the fake-door test so that restyling the conversion mechanic
   mid-test could not contaminate the read; the test is over and the app is
   live, so it adopts lavender as CLAUDE.md always said it would. */
.bubble-you { background: var(--lavender); color: var(--plum); padding: 16px 14px; }
.bubble-cast { margin-left: 18px; padding: 13px 13px 13px 30px; }
.bubble-cast .mug { position: absolute; left: -25px; top: 11px; z-index: 2; }
.who { font: 700 12px/1 var(--body); }
.who span { font-weight: 500; color: rgba(27, 14, 43, 0.78); }
.said { margin-top: 6px; font: 600 15.5px/1.35 var(--body); }
/* Plum, because the bubble is lavender now and cream on lavender is unreadable. */
.said-you { margin-top: 6px; font: 600 17px/1.35 var(--body); letter-spacing: -0.01em; color: var(--plum); }
.stamp {
  position: absolute; top: -13px; left: 14px;
  background: var(--lime); border: 2.5px solid var(--plum); border-radius: 999px;
  padding: 5px 10px; font: 700 10.5px/1 var(--body); color: var(--plum);
  transform: rotate(-4deg);
}
.head-row { display: flex; align-items: center; gap: 8px; }
.head-row .who { font-size: 12px; }

/* ── demo ── */
.demo-card {
  background: var(--cream); border: 3px solid var(--plum); border-radius: 26px;
  box-shadow: 6px 6px 0 var(--plum); padding: 16px 16px 14px;
}
.demo-input {
  display: block; width: 100%; min-height: 84px; resize: none; border: 0; outline: none;
  background: transparent; font: 600 18px/1.35 var(--body); color: var(--plum);
  padding: 0; -webkit-appearance: none; appearance: none;
}
.demo-input::placeholder { color: rgba(27, 14, 43, 0.42); }
.demo-foot {
  border-top: 2.5px solid rgba(27, 14, 43, 0.16); padding-top: 13px; margin-top: 8px;
  display: flex; flex-direction: column; gap: 12px;
}
.count { font: 400 10.5px/1.4 var(--mono); letter-spacing: 0.13em; color: rgba(27, 14, 43, 0.55); }
.count.over { color: var(--orange); font-weight: 700; }

/* rows scroll sideways rather than wrapping to three lines */
.rail {
  margin-top: 12px;
  display: flex; gap: 12px;
  overflow-x: auto; overflow-y: hidden;
  padding: 6px var(--pad) 12px;
  margin-left: calc(var(--pad) * -1); margin-right: calc(var(--pad) * -1);
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { flex: none; scroll-snap-align: start; }

.chip {
  cursor: pointer; white-space: nowrap;
  background: var(--cream); border: 3px solid var(--plum); border-radius: 999px;
  box-shadow: 4px 4px 0 var(--plum); padding: 15px 20px;
  font: 600 16px/1 var(--body); color: var(--plum);
  transform: rotate(-1deg);
  -webkit-appearance: none; appearance: none;
}
.chip:nth-child(2) { transform: rotate(0.8deg); }
.chip:nth-child(3) { transform: rotate(-0.6deg); }
.chip[aria-pressed='true'] { background: var(--lime); }

.out { margin-top: 26px; scroll-margin-top: 76px; display: flex; flex-direction: column; gap: 16px; }
.out:empty { display: none; }
.typing { display: flex; align-items: center; gap: 10px; margin-left: 16px; animation: nc-in 0.3s ease both; }
.dots {
  display: flex; align-items: center; gap: 5px;
  background: var(--cream); border: 3px solid var(--plum); border-radius: 999px; padding: 12px 15px;
}
.dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--plum); animation: nc-dot 1.1s ease-in-out infinite; }
.dots i:nth-child(2) { animation-delay: 0.15s; }
.dots i:nth-child(3) { animation-delay: 0.3s; }
.typing-name { font: 500 13px/1 var(--body); color: rgba(27, 14, 43, 0.75); }

.arrived { animation: nc-in 0.4s ease both; }

/* Margo's receipt, inside a reply. Cream and mono, with the visitor's own
   words behind pink. This is the second and last pink on the page: the first
   is the highlight in the 9:16 receipt card, and it only appears when Margo
   fires, which is the one moment that earns it. */
.receipt-inline {
  margin-top: 11px; background: var(--cream);
  border: 2.5px solid var(--plum); border-radius: 16px; padding: 12px 13px;
  transform: rotate(1.2deg);
}
.receipt-inline q {
  font: 400 15px/1.5 var(--mono); quotes: '"' '"';
  background: var(--pink); padding: 2px 4px;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
}
.receipt-inline .when { margin-top: 7px; font: 400 10.5px/1 var(--mono); text-transform: uppercase; letter-spacing: 0.14em; color: rgba(27, 14, 43, 0.82); }

/* ── how it goes ── */
.card {
  border: 3px solid var(--plum); border-radius: 28px; box-shadow: 7px 7px 0 var(--plum);
  padding: 20px 18px; background: var(--cream);
}
.card-ico {
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--cream); border: 3px solid var(--plum);
  display: flex; align-items: center; justify-content: center; color: var(--plum);
}

/* ── cast ── */
.cast-rail { margin-top: 22px; }
/* color is set because a button does not inherit it, and the default is pure
   black. Nothing in the mug uses currentColor today, but ink is plum here. */
.cast-btn {
  cursor: pointer; background: var(--cream); color: var(--plum);
  border: 3px solid var(--plum); border-radius: 22px; box-shadow: 5px 5px 0 var(--plum);
  padding: 11px; transform: rotate(-1.2deg);
  -webkit-appearance: none; appearance: none;
}
.cast-btn:nth-child(even) { transform: rotate(0.9deg); }
.cast-btn[aria-pressed='true'] { background: var(--lime); }
.bio { padding: 20px 18px; }
.bio h3 { font: 700 25px/1 var(--display); }
.bio h3 span { font: 500 13.5px/1 var(--body); color: rgba(27, 14, 43, 0.78); }
.bio .line { margin-top: 14px; font: 600 18px/1.35 var(--body); letter-spacing: -0.01em; }

/* ── the receipt ── */
.chip-rare {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--cream); border: 3px solid var(--plum); border-radius: 999px;
  padding: 8px 14px; transform: rotate(-2deg); color: var(--plum);
  font: 700 12.5px/1 var(--body);
}
.receipt-card {
  margin: 14px auto 0; width: min(292px, 100%); aspect-ratio: 9 / 16;
  background: var(--cream); border: 4px solid var(--plum); border-radius: 28px;
  box-shadow: 8px 8px 0 var(--plum); padding: 22px 18px;
  display: flex; flex-direction: column; justify-content: space-between; gap: 16px;
  transform: rotate(-1.4deg);
}
.receipt-card .when { font: 400 10.5px/1 var(--mono); letter-spacing: 0.14em; color: rgba(27, 14, 43, 0.55); }
.receipt-card .quote { font: 400 19px/1.5 var(--mono); }
.receipt-card .hit {
  background-image: linear-gradient(var(--pink), var(--pink));
  background-repeat: no-repeat; background-size: 0% 100%;
  padding: 2px 4px;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
  transition: background-size 0.9s cubic-bezier(0.4, 0, 0.2, 1) 0.28s;
}
.receipt-card.seen .hit { background-size: 100% 100%; }
.receipt-card .age { font: 700 34px/0.94 var(--mono); letter-spacing: -0.03em; }
.receipt-card .foot { margin-top: 13px; padding-top: 12px; border-top: 3px solid var(--plum); display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.receipt-card .foot .w { font: 700 19px/1 var(--display); letter-spacing: -0.035em; }
.receipt-card .foot .t { font: 600 10.5px/1 var(--display); letter-spacing: -0.02em; word-spacing: 0.13em; color: rgba(27, 14, 43, 0.7); }
.shot { margin-top: 11px; font: 400 10.5px/1.4 var(--mono); letter-spacing: 0.14em; color: rgba(255, 246, 234, 0.65); text-align: center; }

/* ── close ── */
.close-mark { font: 700 72px/0.86 var(--display); text-align: center; }

/* ── footer ── */
.ftr { background: var(--plum); padding: 24px var(--pad) 34px; display: flex; flex-direction: column; gap: 14px; }
.ftr-mark { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.ftr-mark .w { font: 700 21px/1 var(--display); letter-spacing: -0.035em; color: var(--cream); }
.ftr-mark .t { font: 600 11.5px/1 var(--display); letter-spacing: -0.02em; word-spacing: 0.13em; color: var(--lime); }
.ftr-nav { display: flex; align-items: center; gap: 18px; font: 500 12.5px/1 var(--body); color: rgba(255, 246, 234, 0.7); margin: -15px -6px; }
/* Padding-plus-negative-margin gets these to a 44px thumb target without
   moving anything: at 12.5px type the text box alone is 13px tall, which is
   unhittable on the device nearly all of this traffic arrives on. */
.ftr-nav a { display: inline-block; padding: 15px 6px; }
.ftr-nav a:hover { color: var(--lime); }

/* ── sticky bar ── */
.bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: var(--lime); border-top: 4px solid var(--plum);
  padding: 13px 18px calc(13px + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: 12px;
  transform: translateY(110%); transition: transform 0.28s cubic-bezier(0.2, 0.9, 0.25, 1);
}
.bar.up { transform: translateY(0); }
.bar-txt { flex: 1 1 auto; min-width: 0; }
.bar-txt b { display: block; font: 700 18px/1.12 var(--display); }
.bar-txt span { display: block; margin-top: 3px; font: 500 12px/1.2 var(--body); color: rgba(27, 14, 43, 0.72); }
.bar a {
  flex: none; background: var(--plum); color: var(--cream);
  border: 3px solid var(--plum); border-radius: 999px; box-shadow: 4px 4px 0 var(--grape);
  padding: 15px 19px; font: 700 15px/1 var(--body);
}

/* ── legal pages ── */
.wrap-narrow { max-width: 1000px; margin: 0 auto; }
.tag {
  display: inline-block; border: 3px solid var(--plum); border-radius: 999px;
  padding: 8px 15px; font: 700 12.5px/1 var(--body); transform: rotate(-2deg);
}
.prose { display: flex; flex-direction: column; gap: 34px; }
.d3-sec { font: 700 24px/1 var(--display); }
.prose p { margin-top: 14px; font: 500 16.5px/1.6 var(--body); color: rgba(27, 14, 43, 0.86); max-width: 680px; text-wrap: pretty; }
.prose .small { color: rgba(27, 14, 43, 0.78); }
.callout {
  margin-top: 18px; max-width: 680px;
  background: var(--lime); border: 3px solid var(--plum); border-radius: 22px;
  box-shadow: 5px 5px 0 var(--plum); padding: 18px 20px;
  font: 600 16px/1.5 var(--body); transform: rotate(-0.4deg);
}

/* ── utility ── */
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.only-desktop { display: none; }
.only-mobile { display: block; }

/* ── the App Store badge ──
   Apple's marketing guidelines (read 31 Aug 2026) forbid recreating,
   cropping, angling or animating this artwork, so it is the one object on
   the page that does NOT wear the sticker kit's tilt or its plum outline.
   Their minimum on screen is 40px tall; ours is 56. The margin below is the
   required clear space, a quarter of the badge height, which nothing else
   may sit inside. */
.store-badge {
  display: inline-block; line-height: 0;
  margin: 0 14px 14px 0;
  border-radius: 8px;
}
.store-badge img { height: 56px; width: auto; display: block; }
/* The press feels like the rest of the kit without touching the artwork:
   the badge moves, it does not deform. */
.store-badge:active { transform: translate(2px, 2px); }
.store-badge:focus-visible {
  outline: 3px solid var(--plum); outline-offset: 4px;
}
/* Centred in the closing section, where everything else is centred. */
#close .store-badge { margin: 0 0 14px; }

/* ── consent ──
   Only ever rendered for EU and UK visitors. Same sticker kit as everything
   else, so it reads as part of the page rather than a legal overlay bolted on
   top. Both answers are the same size and shape: a refuse button that is
   harder to press than the accept button is not consent. */
.consent {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 80;
  padding: 12px var(--pad) calc(12px + env(safe-area-inset-bottom));
  display: flex; justify-content: center;
  transform: translateY(115%);
  transition: transform 0.34s cubic-bezier(0.2, 0.9, 0.25, 1);
  pointer-events: none;
}
.consent.up { transform: translateY(0); }
.consent-card {
  pointer-events: auto;
  width: min(460px, 100%);
  background: var(--cream);
  border: 3px solid var(--plum); border-radius: 26px;
  box-shadow: 6px 6px 0 var(--plum);
  padding: 18px 18px 16px;
  transform: rotate(-0.7deg);
}
.consent-title { display: block; font: 700 20px/1.15 var(--display); }
.consent-copy { margin-top: 8px; font: 500 14px/1.35 var(--body); color: rgba(27, 14, 43, 0.82); }
.consent-btns { margin-top: 14px; display: flex; gap: 10px; }
.consent-btn {
  flex: 1 1 0; cursor: pointer; -webkit-appearance: none; appearance: none;
  background: var(--cream); color: var(--plum);
  border: 3px solid var(--plum); border-radius: 999px;
  box-shadow: 3px 3px 0 var(--plum);
  padding: 14px 12px; font: 700 15px/1 var(--body);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.consent-btn:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--plum); }
.consent-yes { background: var(--lime); }
.consent-more {
  display: inline-block; margin-top: 12px;
  font: 500 12.5px/1 var(--body); color: rgba(27, 14, 43, 0.7);
  text-decoration: underline; text-underline-offset: 3px;
  padding: 6px 2px;
}
/* The sticky price bar and the consent card must never stack on top of each
   other. Consent asks first; the bar returns once it is answered. */
.has-consent-bar .bar { display: none; }

@media (prefers-reduced-motion: reduce) {
  .consent { transition: none; transform: translateY(0); }
}

/* ── reveal ── */
.rev { opacity: 0; transform: translateY(34px); transition: opacity 0.7s cubic-bezier(0.2, 0.9, 0.25, 1), transform 0.8s cubic-bezier(0.2, 0.9, 0.25, 1); }
.rev.seen { opacity: 1; transform: none; }

@keyframes nc-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes nc-dot { 0%, 80%, 100% { transform: translateY(0); opacity: 0.45; } 40% { transform: translateY(-5px); opacity: 1; } }
@keyframes nc-float { from { transform: translateY(0); } to { transform: translateY(-9px); } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
  .rev { opacity: 1; transform: none; }
  .receipt-card .hit { background-size: 100% 100%; }
}

/* ══ desktop ══════════════════════════════════════════════════════
   Below 760px nothing is ever side by side. Above it, the landing
   file's two-column layout takes over. */
@media (min-width: 760px) {
  :root { --pad: 5vw; }
  section { padding: clamp(48px, 8vw, 80px) var(--pad); }
  .wrap { max-width: 1240px; margin: 0 auto; }
  .d1 { font-size: clamp(52px, 6vw, 78px); line-height: 0.92; }
  .d2 { font-size: clamp(34px, 4vw, 50px); }
  .d3 { font-size: 24px; }
  .d4 { font-size: 18px; line-height: 1.2; }
  .lede { font-size: 19px; line-height: 1.5; }

  .hdr { padding: 26px var(--pad); }
  .hdr .wordmark { font-size: 28px; }
  .hdr .tagline { font-size: 15px; }
  .btn-sm { padding: 14px 20px; font-size: 14px; box-shadow: 4px 4px 0 var(--plum); }

  .hero { padding: clamp(16px, 4vw, 34px) var(--pad) clamp(48px, 7vw, 80px); }
  .hero-grid { display: flex; align-items: flex-start; justify-content: space-between; gap: clamp(36px, 5vw, 56px); flex-wrap: wrap; }
  .hero-copy { flex: 1 1 460px; min-width: min(320px, 100%); max-width: 620px; }

  /* Desktop only: the thread gets phone chrome. On mobile the thread IS the
     page, so this never applies there, no phone mock inside a phone. */
  .thread {
    flex: 0 1 380px; min-width: min(300px, 100%); align-self: flex-start;
    margin: 0 auto; padding: 16px 14px 22px; width: min(340px, 100%);
    background: var(--cream); border: 4px solid var(--plum); border-radius: 44px;
    box-shadow: 14px 14px 0 var(--plum);
    animation: nc-float 4.5s ease-in-out infinite alternate;
  }
  .thread::before {
    content: ''; display: block; width: 86px; height: 8px; border-radius: 999px;
    background: var(--plum); margin: 0 auto 16px; opacity: 0.9;
  }
  .thread-hdr { display: flex; align-items: center; justify-content: space-between; padding: 0 6px 12px; border-bottom: 3px solid var(--plum); margin-bottom: 4px; }
  .thread-hdr .w { font: 700 17px/1 var(--display); letter-spacing: -0.03em; }
  .thread-hdr .t { font: 500 11px/1 var(--body); color: rgba(27, 14, 43, 0.75); }

  /* .cols rows are .stack (column) on mobile: one card per row, full width,
     because at 185px the body text drops below reading size. At 760px they
     become a real row; flex-direction must be reset explicitly or flex-basis
     would size their height instead of their width. */
  .cols { display: flex; flex-direction: row; gap: 16px; flex-wrap: wrap; }
  .cols > * { flex: 1 1 260px; }
  /* four-up rows need a narrower basis or the fourth card wraps alone and
     stretches to full width */
  .cols-4 > * { flex: 1 1 240px; }
  .rail { flex-wrap: wrap; overflow: visible; margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0; }
  .rail > * { flex: none; }
  .demo-card { max-width: 620px; }
  .demo-foot { flex-direction: row; align-items: center; justify-content: space-between; }
  .demo-foot .btn-say { flex: 1 1 150px; width: auto; max-width: 260px; }
  .out { max-width: 620px; }
  .split { display: flex; align-items: center; justify-content: space-between; gap: 48px; flex-wrap: wrap; }
  .split > * { flex: 1 1 380px; min-width: min(300px, 100%); }
  .receipt-card { width: min(348px, 100%); padding: 28px 24px; }
  .receipt-card .quote { font-size: 22px; }
  .receipt-card .age { font-size: 40px; }
  .close-mark { font-size: clamp(72px, 11vw, 110px); }
  .close-form { display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; }
  .close-form .field { flex: 1 1 280px; width: auto; max-width: 340px; }
  .close-form .btn { flex: 1 1 200px; width: auto; max-width: 300px; }
  .ftr { flex-direction: row; align-items: center; justify-content: space-between; flex-wrap: wrap; padding: 34px var(--pad); }
  .bar { display: none; }
  .only-desktop { display: block; }
  .only-mobile { display: none; }
  .d3-sec { font-size: clamp(24px, 3vw, 32px); }
  .prose { gap: 38px; }
}

@media (min-width: 1000px) {
  .cols > * { flex: 1 1 280px; }
  /* must be restated: same specificity as the rule above, so source order
     decides and the four-up basis would otherwise be overridden here */
  .cols-4 > * { flex: 1 1 240px; }
}

/* ══ Clash Display band crossings ═══════════════════════════════════════
   Each query fires exactly where that element's clamp() crosses a band
   boundary. Ordered ascending so the cascade resolves correctly. */
@media (min-width: 873px) {
  /* .close-mark clamp(72px,11vw,110px): 11vw reaches 96px here */
  .close-mark { letter-spacing: -0.05em; }
}
@media (min-width: 1000px) {
  /* .d2 clamp(34px,4vw,50px): 4vw reaches 40px here */
  .d2 { letter-spacing: -0.02em; }
}
@media (min-width: 1067px) {
  /* .d1 clamp(52px,6vw,78px): 6vw reaches 64px here */
  .d1 { letter-spacing: -0.035em; }
}

/* ══ native-feeling touch ═══════════════════════════════════════════════
   Buttons should behave like buttons, not like text: no grey flash on tap,
   no text selection, no long-press callout, and no 300ms click delay. Scoped
   to controls only, so body copy, the demo box and quoted entries stay
   selectable. */
button,
a,
.chip,
.cast-btn,
.btn,
.btn-sm,
[role='button'] {
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
}

/* ── the cast pages ───────────────────────────────────────────────
   /cast and /cast/<name>. These are the search pages (LOG D-222) and
   nothing here is loaded by the homepage's layout, only by its
   stylesheet, so every selector below is scoped to a class that only
   those pages use. */

/* Two more section grounds, from the sanctioned secondaries. They carry
   no meaning: each character's page simply wears their own fill. */
.band-blue { background: var(--blue); border-top: 4px solid var(--plum); border-bottom: 4px solid var(--plum); }
.band-orange { background: var(--orange); border-top: 4px solid var(--plum); border-bottom: 4px solid var(--plum); }

.cast-hero { padding-top: 18px; }

.crumbs { font: 500 13px/1.55 var(--body); color: rgba(27, 14, 43, 0.72); }
.crumbs a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }

.cast-head { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.cast-face {
  border: 4px solid var(--plum); border-radius: 30px; box-shadow: 8px 8px 0 var(--plum);
  background: var(--cream); padding: 10px; line-height: 0;
  transform: rotate(-1.2deg);
}

/* A card that is a link. The tilt and the shadow come from .card; this
   only has to stop the browser underlining the whole thing. */
.cast-card { display: block; color: inherit; text-decoration: none; }
.cast-card .d3 { text-decoration: underline; text-underline-offset: 4px; }

/* The exchange: the same bubbles the homepage uses, without the phone
   chrome .thread puts round them at 760px and up. No phone mock inside a
   phone, and no phone mock on a page that is not the demo either.
   The left padding is room for the mug, which sits 25px outside its
   bubble on purpose. */
.exchange { display: flex; flex-direction: column; gap: 16px; padding-left: 8px; max-width: 600px; }

/* The rest of the cast, edge to edge on a phone. .rail already pulls
   itself out to the screen margins; these are just the faces in it. */
.face-link {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  text-decoration: none; color: var(--plum);
  border: 3px solid var(--plum); border-radius: 22px; box-shadow: 5px 5px 0 var(--plum);
  background: var(--cream); padding: 12px 14px 10px;
  font: 700 13px/1 var(--body);
  transform: rotate(-1.2deg);
}
.face-link:nth-child(even) { transform: rotate(1.2deg); }

.rules { list-style: none; display: flex; flex-direction: column; gap: 14px; max-width: 640px; }
.rules li {
  font: 500 17px/1.55 var(--body); color: rgba(255, 246, 234, 0.88);
  padding-left: 18px; position: relative;
}
.rules li::before {
  content: ''; position: absolute; left: 0; top: 10px;
  width: 8px; height: 8px; border-radius: 2px; background: var(--lime);
}

@media (min-width: 760px) {
  .cast-hero { padding-top: 26px; }
  .cast-head { gap: 30px; flex-wrap: nowrap; }
}

/* An inline link inside running text. The global rule is
   `a { text-decoration: none }`, which is right for the buttons and cards
   that make up most of the site and wrong for a link inside a sentence:
   without it the link is the same colour and weight as the words round it
   and nobody can see it. Scoped to a class rather than to `a` so the
   homepage and the legal pages are not touched. */
.link {
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 2px; font-weight: 700;
}

/* The "pick them if" and "pick nocaps if" lists on the comparison pages.
   Same shape as .rules, on lime rather than plum, so the marker is plum
   rather than lime. */
.picks { list-style: none; display: flex; flex-direction: column; gap: 14px; max-width: 660px; }
.picks li {
  font: 500 17px/1.55 var(--body); color: var(--plum);
  padding-left: 18px; position: relative;
}
.picks li::before {
  content: ''; position: absolute; left: 0; top: 10px;
  width: 8px; height: 8px; border-radius: 2px; background: var(--plum);
}

/* An inline link on a dark ground. */
.link.on-dark { color: var(--cream); }

/* The breadcrumb on a dark hero. Plum at 72% on grape is two dark colours
   on top of each other and is not readable; caught on /vs/ai-companion. */
.crumbs.on-dark { color: rgba(255, 246, 234, 0.78); }
.crumbs.on-dark a { color: rgba(255, 246, 234, 0.92); }

/* The footer nav went from four items to six when the cast and the
   comparison pages needed a way in from every page. Without wrapping, flex
   shrank each item until "get the app" broke across three lines and the
   last one ran off the screen. Items now keep their words together and the
   row wraps instead. The 44px thumb target from the padding above is
   untouched, and row-gap stays at 0 because that padding is already the
   spacing. */
.ftr-nav { flex-wrap: wrap; row-gap: 0; }
.ftr-nav a { white-space: nowrap; }

/* Pine, the second dark (LOG D-133). A dark hero that is not plum and not
   grape, so the comparison pages can rotate through six grounds without
   repeating one. Sanctioned secondary, carries no meaning. */
.band-pine { background: #2E5E4E; border-top: 4px solid var(--plum); border-bottom: 4px solid var(--plum); }
