/* Knock — the app's own palette. Linen by day, Dusk by night, following the
   visitor's system setting exactly as the app does. */
:root {
  --bg: #F4F5F2; --card: #FFFFFF; --line: #E2E5DF;
  --ink: #24291F; --muted: #7C8377; --accent: #5F8266;
  --wash: rgba(95, 130, 102, .07);
  --shadow: rgba(31, 38, 30, .13);
  --shadow-deep: rgba(31, 38, 30, .22);
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #171A2B; --card: #222741; --line: #323852;
    --ink: #F2EEE6; --muted: #9AA0BC; --accent: #F2A65A;
    --wash: rgba(242, 166, 90, .08);
    --shadow: rgba(0, 0, 0, .45);
    --shadow-deep: rgba(0, 0, 0, .6);
  }
}
* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font: 17px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* A single soft wash behind the hero, so the page has somewhere to start
     rather than being a flat sheet with a phone dropped on it. */
  background-image: radial-gradient(120% 60% at 50% -10%, var(--wash), transparent 70%);
  background-repeat: no-repeat;
}
header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; max-width: 780px; margin: 0 auto; padding: 22px 24px;
}
.brand { display: flex; align-items: center; gap: 11px; text-decoration: none; color: var(--ink); font-weight: 600; }
.brand img { border-radius: 11px; }
nav a { color: var(--muted); text-decoration: none; margin-left: 18px; font-size: 15px; }
nav a:hover { color: var(--accent); }
.lang-switch {
  margin-left: 18px; padding: 5px 26px 5px 12px;
  font: inherit; font-size: 13.5px; color: var(--muted);
  background: var(--card); border: 1px solid var(--line); border-radius: 999px;
  appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='%23888'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
.lang-switch:hover { color: var(--accent); border-color: var(--accent); }
main { max-width: 780px; margin: 0 auto; padding: 0 24px 64px; }
h1 { font-size: clamp(2.1rem, 7vw, 2.9rem); line-height: 1.1; letter-spacing: -0.025em; margin: 30px 0 14px; }
h2 { font-size: 1.35rem; letter-spacing: -0.01em; margin: 40px 0 10px; }
h3 { font-size: 1.05rem; margin: 28px 0 6px; }
p { margin: 0 0 14px; }
.lede { font-size: 1.16rem; color: var(--muted); max-width: 34ch; }
.points ul { list-style: none; padding: 0; margin: 52px 0 0;
             display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.points li {
  background: var(--card); border: 1px solid var(--line); border-radius: 20px; padding: 22px;
  transition: transform .25s ease, box-shadow .25s ease;
}
.points li:hover { transform: translateY(-3px); box-shadow: 0 14px 34px var(--shadow); }
.points h3 { margin: 0 0 6px; }
.points p { margin: 0; color: var(--muted); font-size: 15px; }
.promise-title { margin-top: 44px; }
.promise-body { color: var(--muted); margin-bottom: 0; }
.doc h2 { border-top: 1px solid var(--line); padding-top: 26px; }
.doc p { color: var(--muted); }
.doc .updated { font-size: 14px; }
a { color: var(--accent); }
footer { max-width: 780px; margin: 0 auto; padding: 28px 24px 56px;
         border-top: 1px solid var(--line); }
.langs { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.langs a { color: var(--muted); text-decoration: none; font-size: 14px; }
.langs a:hover { color: var(--accent); }
.fine { color: var(--muted); font-size: 13px; margin-top: 14px; }


/* ── The stage: a phone, a widget, and one thing to do ────────────────────
   Everything here is markup rather than a screenshot. A pale app captured
   from a simulator reads as a washed-out rectangle on a web page; drawn as
   real elements it stays crisp, follows the visitor's light/dark setting the
   way the app follows the phone's, and can actually be tapped. */
.stage { margin: 44px 0 10px; display: grid; justify-items: center; }

/* ⚠️ THE BEZEL IS DARK IN BOTH THEMES, on purpose.
   It used to be a pale gradient of --line and --card, which on a pale page
   meant the "phone" had almost no edge — the mockup read as a floating white
   card and the whole point (this is your Home Screen) was lost. Phones are
   dark objects. Giving it a real frame is what makes the widget inside it
   read as a widget rather than as a website panel. */
/* ── The device, taken seriously (asked for: "a high-quality, photorealistic
   device render"). Still pure CSS — a bitmap would blur on retina, ignore
   dark mode, and freeze the interactive demo inside it — but the frame now
   carries the details that make an iPhone read as METAL AND GLASS rather
   than a rounded rectangle: a brushed titanium band with a machined edge
   highlight, side buttons, a true black bezel between band and display, a
   camera in the island, a diagonal glass reflection, and a grounded
   two-layer floor shadow. */
.phone {
  /* A real iPhone body is ~2.08:1 with an outer radius near 15.5% of its
     width. The frame was 310×~505 (1.63:1) at radius 58 (18.7%) — squat and
     over-rounded, "a bit too square" per the field note. Height comes from
     the aspect ratio; the screen absorbs it via flex (see .phone-screen),
     never as an empty void under the dock. */
  width: 264px; padding: 11px; border-radius: 42px;
  aspect-ratio: 1 / 2.08;
  background:
    linear-gradient(115deg, rgba(255,255,255,.16), rgba(255,255,255,0) 28%),
    linear-gradient(165deg, #4A5164, #171B26 48%, #232A3C 78%, #3B4358);
  box-shadow:
    0 46px 90px -18px var(--shadow-deep),
    0 16px 34px rgba(0,0,0,.20),
    0 1.5px 1px rgba(255,255,255,.30) inset,
    0 -1.5px 1.5px rgba(0,0,0,.55) inset,
    0 0 0 1px rgba(0,0,0,.55);
  position: relative;
}
/* Volume buttons, machined into the left edge — one element, its twin drawn
   by the box-shadow (same size, so the trick is invisible). */
.phone::before {
  /* Upper third of the taller body, not the upper quarter it was tuned for
     at the short frame. */
  content: ""; position: absolute; left: -2.5px; top: 142px;
  width: 3px; height: 33px; border-radius: 2px;
  background: linear-gradient(90deg, #2A3040, #10131B);
  box-shadow:
    0 43px 0 0 #1A1E29,
    1px 0 1px rgba(255,255,255,.14) inset;
}
/* The side button, right edge. */
.phone::after {
  content: ""; position: absolute; right: -2.5px; top: 176px;
  width: 3px; height: 54px; border-radius: 2px;
  background: linear-gradient(270deg, #2A3040, #10131B);
  box-shadow: -1px 0 1px rgba(255,255,255,.14) inset;
}
.phone-screen {
  position: relative; overflow: hidden;
  /* Concentric with the 48px frame: outer minus the 12px band. Change the
     matching radius on ::after in lockstep or the glass clips wrong. */
  border-radius: 31px; padding: 26px 14px 14px;
  background: var(--bg);
  /* Fill the taller frame; the dock pins to the bottom and the app grid
     floats between (margin-top: auto on both splits the slack), so the
     added height reads as a Home Screen, not as padding. */
  height: 100%;
  display: flex; flex-direction: column;
  box-sizing: border-box;
  /* The true-black bezel every real display sits inside — the one line
     that separates "screenshot in a box" from "a screen". */
  box-shadow: 0 0 0 5px #05060B, 0 0 0 5.75px rgba(255,255,255,.06);
}
/* Glass: a diagonal sheet of light lying ON the display. Pointer-events
   off, so the demo underneath stays tappable; barely-there by design. */
.phone-screen::after {
  content: ""; position: absolute; inset: 0; z-index: 4; pointer-events: none;
  background: linear-gradient(118deg,
    rgba(255,255,255,.085) 0%, rgba(255,255,255,.03) 24%,
    rgba(255,255,255,0) 38%, rgba(255,255,255,0) 74%,
    rgba(255,255,255,.04) 92%);
  border-radius: 31px;   /* lockstep with .phone-screen */
}
/* The Dynamic Island. Small, but it is the single detail that makes a
   rounded rectangle read as an iPhone at a glance. */
.island {
  position: absolute; top: 22px; left: 50%; transform: translateX(-50%);
  width: 78px; height: 21px; border-radius: 999px; background: #0B0D13;
  box-shadow: 0 .5px 1px rgba(255,255,255,.10) inset;
  /* Above the screen, which comes later in the DOM and would otherwise paint
     straight over it — the island is ON the display, not behind it. */
  z-index: 2;
}
/* The camera, off-centre in the island, with a glint — the detail a close
   look expects to find. */
.island::after {
  content: ""; position: absolute; right: 5px; top: 50%;
  width: 11px; height: 11px; border-radius: 50%;
  transform: translateY(-50%);
  background: radial-gradient(circle at 35% 32%,
    #3A4A63 0%, #131B2B 42%, #05070C 78%);
}

.tile {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 26px; padding: 20px 16px 16px; text-align: center;
  box-shadow: 0 6px 18px rgba(0,0,0,.10);
}
.knock-face {
  position: relative; display: grid; place-items: center;
  width: 112px; height: 112px; margin: 0 auto;
  border: 0; border-radius: 50%; cursor: pointer;
  background: color-mix(in srgb, var(--accent) 10%, var(--card));
  transition: transform .32s cubic-bezier(.2,.9,.3,1), background .5s ease;
  -webkit-tap-highlight-color: transparent;
}
.knock-face:focus-visible { outline: 3px solid var(--accent); outline-offset: 6px; }
.knock-face .glyph { font-size: 48px; line-height: 1; user-select: none; }
.knock-face.lit { background: color-mix(in srgb, var(--accent) 32%, var(--card)); }

/* ── "There is something to do here" ──────────────────────────────────────
   A tappable thing that never moves is indistinguishable from a picture of a
   tappable thing. This ring breathes outward until the visitor has tapped
   once, and then stops for good — an invitation, not a permanent animation. */
.knock-face::after {
  content: ""; position: absolute; inset: -9px;
  border-radius: 50%; border: 2px solid var(--accent);
  opacity: 0; pointer-events: none;
  animation: invite 2.8s ease-out infinite .8s;
}
.knock-face.touched::after { animation: none; }
@keyframes invite {
  0%   { transform: scale(.94); opacity: 0; }
  22%  { opacity: .5; }
  100% { transform: scale(1.3); opacity: 0; }
}

/* Gather, then throw — the same shape as the app: in first, then past rest. */
.knock-face.go { animation: knock-press .5s cubic-bezier(.2,.9,.3,1); }
@keyframes knock-press {
  0% { transform: scale(1); } 16% { transform: scale(.9); }
  46% { transform: scale(1.13); } 100% { transform: scale(1); }
}

.ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 2px solid var(--accent); opacity: 0; pointer-events: none;
}
.go .r1 { animation: ring-out 1s ease-out .06s; }
.go .r2 { animation: ring-out 1s ease-out .18s; }
.go .r3 { animation: ring-out 1s ease-out .30s; }
@keyframes ring-out {
  0% { transform: scale(.94); opacity: .85; }
  100% { transform: scale(2.2); opacity: 0; }
}

/* Eight leaves thrown outward on their own axes. */
.burst { position: absolute; inset: 0; pointer-events: none; }
.burst i {
  position: absolute; top: 50%; left: 50%; margin: -10px 0 0 -10px;
  width: 20px; height: 20px; font-style: normal; font-size: 19px;
  line-height: 20px; text-align: center; opacity: 0;
}
.burst i::before { content: "🌿"; }
.burst i:nth-child(1) { --a: 0deg; }   .burst i:nth-child(2) { --a: 45deg; }
.burst i:nth-child(3) { --a: 90deg; }  .burst i:nth-child(4) { --a: 135deg; }
.burst i:nth-child(5) { --a: 180deg; } .burst i:nth-child(6) { --a: 225deg; }
.burst i:nth-child(7) { --a: 270deg; } .burst i:nth-child(8) { --a: 315deg; }
.go .burst i { animation: fly .9s cubic-bezier(.16,.9,.3,1) .04s; }
@keyframes fly {
  0%   { opacity: .95; transform: rotate(var(--a)) translateX(10px) scale(.5); }
  100% { opacity: 0;   transform: rotate(var(--a)) translateX(120px) scale(1.05); }
}

.tile-name { font-weight: 600; margin: 14px 0 2px; }
.tile-status { color: var(--muted); font-size: 14px; margin: 0; min-height: 20px; }
.tile-status.live { color: var(--accent); }

/* ── The apps it sits among ───────────────────────────────────────────────
   ⚠️ THESE USED TO BE EIGHT IDENTICAL GREY SQUARES, and they read exactly
   like what a grid of identical grey squares always reads like: images that
   failed to load. That is a bad first impression on the one screenshot the
   whole page is built around.

   They are now softly coloured and very slightly blurred — which is the
   trick, because blur is unmistakably DELIBERATE. Out-of-focus icons say
   "other apps, not the point"; sharp empty ones say "broken". They stay
   muted, because the entire argument of this page is that the one tile above
   them is the thing worth looking at. */
.apps {
  /* auto margins, not fixed: with the frame at a real iPhone ratio the
     screen is taller than its content, and the grid floating evenly between
     tile and dock is what absorbs the difference. */
  margin-top: auto; display: grid; grid-template-columns: repeat(4, 1fr); gap: 13px;
}
.apps span {
  aspect-ratio: 1; border-radius: 27%;
  background: linear-gradient(155deg, var(--i1), var(--i2));
  filter: blur(.7px); opacity: .62;
  box-shadow: 0 2px 6px rgba(0,0,0,.14);
}
.apps span:nth-child(1) { --i1: hsl(212 48% 66%); --i2: hsl(212 44% 52%); }
.apps span:nth-child(2) { --i1: hsl(18 55% 68%);  --i2: hsl(18 50% 55%); }
.apps span:nth-child(3) { --i1: hsl(150 30% 62%); --i2: hsl(150 28% 48%); }
.apps span:nth-child(4) { --i1: hsl(45 58% 66%);  --i2: hsl(45 52% 53%); }
.apps span:nth-child(5) { --i1: hsl(280 28% 67%); --i2: hsl(280 26% 54%); }
.apps span:nth-child(6) { --i1: hsl(0 45% 68%);   --i2: hsl(0 42% 55%); }
.apps span:nth-child(7) { --i1: hsl(192 40% 63%); --i2: hsl(192 38% 49%); }
.apps span:nth-child(8) { --i1: hsl(96 26% 63%);  --i2: hsl(96 24% 50%); }

/* A dock. Without one the grid floats and the screen stops looking like iOS. */
.dock {
  margin-top: auto; padding: 9px; border-radius: 24px;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 13px;
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  backdrop-filter: blur(6px);
}
.dock span {
  aspect-ratio: 1; border-radius: 27%;
  background: linear-gradient(155deg, var(--i1), var(--i2));
  filter: blur(.7px); opacity: .62;
}
.dock span:nth-child(1) { --i1: hsl(122 34% 62%); --i2: hsl(122 32% 47%); }
.dock span:nth-child(2) { --i1: hsl(205 46% 65%); --i2: hsl(205 42% 51%); }
.dock span:nth-child(3) { --i1: hsl(32 56% 66%);  --i2: hsl(32 50% 53%); }
.dock span:nth-child(4) { --i1: hsl(258 30% 66%); --i2: hsl(258 28% 52%); }

/* ── The one instruction on the page ──────────────────────────────────────
   ⚠️ This used to be grey caption text under the phone, which is where a
   page puts things it does not mean. It is the only call to action above the
   fold and the only thing the visitor is asked to do, so it is now shaped
   like something you press, coloured like the app's own accent, and it
   points at the face it is talking about. */
.try {
  display: inline-flex; align-items: center; gap: 9px;
  margin: 22px 0 0; padding: 10px 18px 10px 15px;
  border-radius: 999px; font-size: 15px; font-weight: 600;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
}
.try::before {
  content: "↑"; font-size: 17px; line-height: 1;
  animation: nudge 2.4s ease-in-out infinite;
}
@keyframes nudge {
  0%, 100% { transform: translateY(1px); }
  50%      { transform: translateY(-3px); }
}
.try.done { color: var(--muted); background: transparent; border-color: transparent; }
.try.done::before { content: ""; animation: none; }

.demo-after { margin: 10px 0 0; color: var(--accent); font-weight: 600; }
.home-caption {
  max-width: 44ch; margin: 30px auto 0; text-align: center; color: var(--muted);
}

/* ── The notification, drawn rather than screenshotted ─────────────────── */
.notif { margin-top: 60px; text-align: center; }
.banner {
  display: flex; align-items: center; gap: 12px; text-align: left;
  max-width: 380px; margin: 22px auto 0; padding: 14px 16px;
  background: var(--card); border: 1px solid var(--line); border-radius: 20px;
  box-shadow: 0 12px 34px var(--shadow);
}
.banner-icon {
  font-size: 26px; width: 42px; height: 42px; display: grid; place-items: center;
  background: var(--bg); border-radius: 11px; flex: none;
}
.banner-text { flex: 1; font-size: 15px; line-height: 1.35; }
.banner-time { color: var(--muted); font-size: 13px; }
.notif-body { max-width: 46ch; margin: 20px auto 0; color: var(--muted); }

/* ── Price, at the bottom, stated once ─────────────────────────────────── */
.pricing { margin-top: 60px; padding: 28px; text-align: center;
           background: var(--card); border: 1px solid var(--line); border-radius: 22px; }
.pricing h2 { margin-top: 0; }
.pricing p { color: var(--muted); max-width: 46ch; margin: 0 auto; }

@media (prefers-reduced-motion: reduce) {
  .knock-face, .ring, .burst i, .knock-face::after, .try::before {
    animation: none !important;
  }
  .knock-face { transition: background .3s ease; }
  .points li:hover { transform: none; }
}

/* ── Section rhythm ───────────────────────────────────────────────────────
   A page of same-sized paragraphs under same-sized headings reads as a
   document, not a product. The eyebrow gives every section a small anchor and
   lets the h2 stop doing two jobs at once. */
.eyebrow {
  margin: 0 0 6px; font-size: 12px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--accent);
}
main > section { scroll-margin-top: 20px; }

/* ── How it works ─────────────────────────────────────────────────────── */
.steps { margin-top: 60px; }
.steps ol { list-style: none; margin: 26px 0 0; padding: 0; display: grid; gap: 14px; }
.steps li {
  display: flex; gap: 16px; align-items: flex-start;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 18px; padding: 18px 20px;
}
.step-n {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center; font-size: 14px; font-weight: 700;
  color: var(--bg); background: var(--accent);
}
.steps h3 { margin: 3px 0 4px; font-size: 1rem; }
.steps p { margin: 0; color: var(--muted); font-size: 15px; }

/* ── Behind their face, and you can actually draw on it ───────────────── */
.draw { margin-top: 60px; }
.draw-stage {
  display: flex; gap: 22px; align-items: center; justify-content: center;
  flex-wrap: wrap; margin: 26px 0 0;
}
.mini {
  width: 168px; padding: 18px 14px 14px; text-align: center;
  background: var(--card); border: 1px solid var(--line); border-radius: 26px;
  box-shadow: 0 12px 30px var(--shadow);
  /* The canvas is bigger than the face on purpose, so ink runs past the
     portrait — but it stops at the tile, exactly as it does on a widget. */
  overflow: hidden;
}
.mini p { margin: 12px 0 0; font-weight: 600; font-size: 14px; }
.mini-face {
  position: relative; width: 108px; height: 108px; margin: 0 auto;
  border-radius: 50%; display: grid; place-items: center;
  background: color-mix(in srgb, var(--accent) 10%, var(--card));
}
.mini-glyph { font-size: 42px; }
/* ⚠️ The canvas OVERFLOWS the circle, exactly as the app's does — the canvas
   is a square and the face is round, and clipping it to the face would throw
   away most of what anybody draws. */
#draw-canvas {
  position: absolute; inset: -22px; width: calc(100% + 44px); height: calc(100% + 44px);
  touch-action: none; cursor: crosshair;
}
.draw-tools { display: grid; gap: 10px; justify-items: center; max-width: 260px; }
.draw-try { margin: 0; font-size: 14px; color: var(--muted); text-align: center; }
.draw-picker { display: flex; flex-wrap: wrap; gap: 7px; justify-content: center; }
.tool {
  width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
  font-size: 18px; line-height: 1; border: 1px solid var(--line);
  background: var(--card); color: var(--ink);
  transition: transform .18s ease, border-color .18s ease;
}
.tool:hover { transform: translateY(-2px); }
.tool.is-on { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 40%, transparent); }
.draw-clear {
  border: 0; background: none; cursor: pointer; padding: 4px 8px;
  color: var(--muted); font-size: 14px; text-decoration: underline;
}
.draw-clear:hover { color: var(--accent); }
.draw-body { max-width: 46ch; margin: 26px auto 0; color: var(--muted); text-align: center; }

/* ── Why it stays small ───────────────────────────────────────────────── */
.points { margin-top: 60px; }
.points li { position: relative; padding-top: 26px; }
.pt-mark {
  position: absolute; top: 22px; left: 22px;
  width: 22px; height: 3px; border-radius: 2px; background: var(--accent); opacity: .55;
}

/* ── The deal ─────────────────────────────────────────────────────────── */

.pricing { margin-top: 60px; }

@media (min-width: 620px) {
  .steps ol { grid-template-columns: 1fr; }
  .steps li { padding: 20px 24px; }
}

/* ── The hold ────────────────────────────────────────────────────────────
   The one gesture people get wrong by default: they read "hold for longer"
   as "shout louder". A ring that fills while four sentences go by under the
   finger says what the paragraph underneath then only has to confirm. */
.hold { margin-top: 60px; }
.hold-stage { display: grid; justify-items: center; gap: 14px; margin-top: 26px; }
.hold-face {
  position: relative; width: 132px; height: 132px; padding: 0;
  border: 0; border-radius: 50%; cursor: pointer;
  background: var(--card); box-shadow: 0 14px 34px var(--shadow);
  display: grid; place-items: center;
  transition: transform .18s ease;
  -webkit-tap-highlight-color: transparent;
  touch-action: none;              /* a hold must not become a page scroll */
  user-select: none; -webkit-user-select: none;
}
.hold-face:active { transform: scale(1.06); }
.hold-emoji { font-size: 52px; line-height: 1; pointer-events: none; }
.hold-ring {
  position: absolute; inset: -7px; border-radius: 50%;
  border: 3px solid var(--accent);
  opacity: 0;                      /* grows and brightens with the charge */
  transform: scale(.86);
  pointer-events: none;
}
.hold-word {
  margin: 0; font-size: 19px; font-weight: 600; color: var(--fg);
  text-align: center; min-height: 1.4em;
}
.hold-try { margin: 0; font-size: 14px; color: var(--muted); text-align: center; }
.hold-body { max-width: 46ch; margin: 26px auto 0; color: var(--muted); text-align: center; }

/* The tap and the hold end the same way: it went, and it buzzed once. */
.hold-try.hold-sent { color: var(--accent); font-weight: 600; }
.hold-face.hold-burst { animation: hold-burst .45s ease-out; }
@keyframes hold-burst {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.14); box-shadow: 0 0 0 12px color-mix(in srgb, var(--accent) 22%, transparent); }
  100% { transform: scale(1); box-shadow: 0 14px 34px var(--shadow); }
}
@media (prefers-reduced-motion: reduce) {
  .hold-face.hold-burst { animation: none; }
}

/* The one route from the page to the app. */
.cta { margin: 22px 0 0; text-align: center; }
.cta-link {
  display: inline-block; padding: 13px 26px; border-radius: 999px;
  background: var(--accent); color: var(--bg);
  font-weight: 600; font-size: 16px; text-decoration: none;
}
.cta-link:hover { opacity: .9; }

/* ── The thought-clouds, in CSS — inside the .notif section since build 40
   (the recipient's phone is ONE moment: banner, then the reply). A
   scalloped cloud is a border-radius chain away; the trail of circles is
   what makes them read as THOUGHT rather than chat — this app has no
   chat. */
.words-title {
  margin: 44px 0 0; font-size: 21px; font-weight: 650; color: var(--ink);
}
.words-stage {
  display: flex; flex-direction: column; align-items: center; gap: 18px;
  margin: 26px auto 18px; max-width: 420px;
}
.cloud {
  position: relative; max-width: 260px; padding: 14px 20px;
  background: var(--card); border: 1.5px solid var(--line);
  border-radius: 26px 30px 28px 24px;
  box-shadow: 0 6px 18px rgba(0,0,0,.08);
  font-size: 15px; color: var(--ink);
}
.cloud-theirs { align-self: flex-start; }
.cloud-mine {
  align-self: flex-end;
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: color-mix(in srgb, var(--accent) 8%, var(--card));
}
.cloud-badge {
  position: absolute; top: -10px; left: -8px;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; font-size: 13px;
  background: var(--card); border: 1px solid var(--line);
}
.cloud-badge.badge-mine { left: auto; right: -8px; }
.cloud-trail {
  position: absolute; border-radius: 50%;
  background: var(--card); border: 1.5px solid var(--line);
}
.cloud-theirs .cloud-trail { border-color: var(--line); }
.cloud-mine .cloud-trail {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: color-mix(in srgb, var(--accent) 8%, var(--card));
}
.t1 { width: 10px; height: 10px; right: -16px; bottom: -4px; }
.t2 { width: 6px; height: 6px; right: -26px; bottom: -12px; }
.m1 { width: 10px; height: 10px; left: -16px; top: -4px; }
.m2 { width: 6px; height: 6px; left: -26px; top: -12px; }

/* Reveal-on-scroll: knock.js stamps .reveal on load and .in as each section
   enters the viewport. Without JS nothing is stamped and everything simply
   shows; with Reduce Motion the transition is dropped. */
.reveal main > section { opacity: 0; transform: translateY(16px);
  transition: opacity .6s ease, transform .6s ease; }
.reveal main > section.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal main > section { opacity: 1; transform: none; transition: none; }
}
