/* Murmur site: home page only (index.html). Built on site.css tokens and components. The hero phone's demo has its
   own style and script, home-anim.css (loaded after this file) and home-anim.js. The first version's home demos (live
   seal, inspector, sign-up preview, Recovery Key) are kept unchanged outside the site, in
   design/site-archive/assets/home.css and home.js; the live seal now lives in the wiki (wiki.css, wiki.js).
   Sections: hero with the phone · promises · what you can do (a bento of four tiles, a bento of seven more, and twelve
   more features) · questions · closing.

   THE HERO PHONE (.hero-phone)
   A black phone in the shape of the largest current Pro model, drawn in HTML and CSS (sharp at any size and pixel
   density, no logo, no model name). Its screen is the Murmur app, direction A, light or dark with the site theme.
   - Size: the figure's width (--hp-w); the device is 1 : 2.1. The frame (titanium ring, black bezel, side keys,
     the flush camera key on the right) is sized in % of that width (cqw of .hero-phone).
   - Screen: the app exactly as it is today (design/prototype, and the reference shots of the real app), on a
     393-point-wide iPhone. .hp__screen is a size container and every element inside is sized with
     calc(N * var(--pt)), --pt = 1/393 of the screen width: N is the prototype's own value in points, so the app keeps
     the mockups' proportions at every size and never reflows. The iOS keyboard alone (no mockup) keeps its own
     440-unit grid, --u. Icons inside the app are the prototype's (Framework7 Icons, symbols hpi-* in index.html),
     never the site's Phosphor; emoji are Apple's images (assets/emoji).
   - The conversation is bottom-aligned, as in the app: the sealed notice and "Today" at its start, then the bubbles
     (each message its own bubble, with no tail, as the app draws them since 0.9.19). The frosted bars float over it: anything taller slides
     under them instead of being cut.
   - The phone (.hp) is role="img", with an alt text that tells the demo's story; nothing inside it is focusable.
   - Motion: the phone fades in and rises 16 px once (350 ms). The demo on its screen (about 60 s with a pause after every step, once per page
     load, ending on the Chats list) is home-anim.css and home-anim.js. The screen's markup is the still, the chat
     with Maude as it ends: all there is without JavaScript, with reduced motion (and a 150 ms fade instead of the
     rise) and in print.
   - Print: the still, light whatever the theme (the dark tokens are for screens only, as in site.css), its fills kept
     even when the browser leaves out background graphics.
   - No call, video or microphone icon, ever. */


/* ------------------------------------------------------------------------------------------------- H-1 hero */
/* Clipped sideways only (the dark-theme glow is wide); the phone's shadow and glow fall freely onto the next section. */
.hero { position: relative; padding: var(--s-12) 0 var(--s-16); background: var(--hero-bg); overflow-x: clip; overflow-y: visible; }
@media (min-width: 768px) { .hero { padding: var(--s-16) 0 var(--s-20); } }
.hero__grid { display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; gap: var(--s-12); text-align: center; }
.hero__copy { max-width: 640px; }
.hero__title > span { display: block; } /* one sentence per line, at every width: "No phone number." is about 335 px at 40 px */
.hero__lead { margin: var(--s-5) auto 0; }
/* one <span class="s"> per sentence, kept whole on its line when it fits: a two-line subtitle breaks between its
   sentences, like the title (a sentence longer than the line still wraps inside itself) */
.hero__lead .s { display: inline-block; }
.hero__ctas { justify-content: center; margin-top: var(--s-8); }
@media (max-width: 399px) {
  .hero__title { font-size: min(40px, 10.6vw); line-height: 1.15; } /* 38 px at 360: still two lines */
  .hero__lead { font-size: min(18px, 4.4vw); } /* about 16 px at 360 and 17 at 390: still its two lines */
}
/* Phones: a tighter top (one 24 px step between the blocks) so the phone starts high on the first screen and shows
   the photo before any scrolling */
@media (max-width: 479px) {
  .hero { padding-top: var(--s-6); }
  .hero__grid { gap: var(--s-6); }
  .hero__ctas { margin-top: var(--s-6); }
}
@media (min-width: 600px) {
  .hero__lead { margin-top: var(--s-6); }
}
@media (min-width: 1024px) {
  .hero { padding: var(--s-12) 0; }
  .hero__grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: center; justify-items: start; gap: var(--s-8); text-align: left; }
  .hero__copy { max-width: none; }
  .hero__lead { margin-left: 0; margin-right: 0; } /* left aligned: the long line first */
  .hero__ctas { justify-content: flex-start; }
  .hero__ctas { margin-top: var(--s-10); }
  .hero-phone { justify-self: end; } /* the frame ends on the grid's right edge, under the header's "Get Murmur" */
}
/* Short desktop windows (a 1366 x 768 laptop shows about 657 px): less air above, and the phone shrinks to fit */
@media (min-width: 1024px) and (max-height: 720px) {
  .hero { padding-top: var(--s-6); }
}


/* ------------------------------------------------------------------------------------------------- The phone: device */
.hero-phone {
  --hp-w: min(78vw, 300px);
  --hp-r: 15cqw;            /* outer corner radius */
  --hp-ring: 1.5px;         /* the titanium edge */
  --hp-bezel: 3cqw;         /* the black border around the screen */
  --hp-shadow: 0 1px 2px rgb(60 42 24 / 0.10), var(--shadow-3);
  --hp-glow: 0;
  position: relative; z-index: 0; flex: none; width: var(--hp-w); margin: 0;
  container-type: inline-size; forced-color-adjust: none;
  animation: hp-in var(--dur-lg) var(--ease) both;
}
@media (min-width: 768px) { .hero-phone { --hp-w: 300px; } }
/* Desktop: 23vw (at least 280 px), but never taller than the first screen leaves room for (header 64, padding above
   and 52 px below the phone), and never smaller than 220 px or larger than 336 px. */
@media (min-width: 1024px) { .hero-phone { --hp-w: clamp(220px, min(max(23vw, 280px), (100svh - 140px) / 2.1), 336px); } }
/* Dark, on screens only (as in site.css): print takes the light tokens above */
@media screen {
  :root[data-theme="dark"] .hero-phone {
    --hp-shadow: 0 0 0 1px rgb(255 255 255 / 0.09), var(--shadow-3);
    --hp-glow: 1;
  }
}
@media screen and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .hero-phone {
    --hp-shadow: 0 0 0 1px rgb(255 255 255 / 0.09), var(--shadow-3);
    --hp-glow: 1;
  }
}
/* Dark theme: a soft wax glow behind the phone, so the black silhouette reads on the night background */
.hero-phone::before {
  content: ""; position: absolute; z-index: -2; inset: -12% -55%; pointer-events: none; opacity: var(--hp-glow);
  background: radial-gradient(closest-side, color-mix(in srgb, var(--seal) 15%, transparent), transparent);
}
@keyframes hp-in { from { opacity: 0; transform: translateY(16px); } }
@keyframes hp-fade { from { opacity: 0; } }

.hp { position: relative; aspect-ratio: 10 / 21; }
.hp-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.hp__frame {
  position: absolute; inset: 0; border-radius: var(--hp-r);
  background: linear-gradient(155deg, #4A4B50 0%, #3A3B40 45%, #2B2C30 100%);
  box-shadow: var(--hp-shadow);
}
.hp__frame::before { /* the black glass border inside the titanium ring */
  content: ""; position: absolute; inset: var(--hp-ring); border-radius: calc(var(--hp-r) - var(--hp-ring)); background: #0A0A0C;
}
.hp__key { /* side keys: slim slabs of the edge color, just proud of the frame */
  position: absolute; z-index: -1; width: 2cqw; border-radius: 0.8cqw;
  background: linear-gradient(90deg, #2B2C30, #4A4B50 50%, #2B2C30);
}
.hp__key--action, .hp__key--up, .hp__key--down { left: -0.9cqw; }
.hp__key--side { right: -0.9cqw; }
.hp__key--action { top: 17.2%; height: 4.6%; }
.hp__key--up { top: 24.6%; height: 7.4%; }
.hp__key--down { top: 33.4%; height: 7.4%; }
.hp__key--side { top: 26%; height: 11.6%; }
.hp__key--camera { /* the camera key: lower on the right, nearly flush, a darker glass face in an edge-colored ring */
  right: -0.45cqw; top: 58.4%; height: 7.2%; width: 1.6cqw; border-radius: 0.6cqw;
  background: linear-gradient(90deg, #26272B, #34353A 50%, #26272B); box-shadow: inset 0 0 0 0.25cqw #45464B;
}


/* ------------------------------------------------------------------------------------------------- The phone: screen */
/* The app on the mockups' iPhone: 393 points wide. --pt is one point (1/393 of the screen), and every value below is
   the prototype's own, in points (src/ui/tokens.css, src/app/app.css, src/ui/ui.css, src/modules/chat/chat.css).
   --u, 1/440 of the screen, is the iOS keyboard's grid only (home-anim.js). */
.hp__screen {
  --u: calc(100cqw / 440);
  --pt: calc(100cqw / 393);
  position: absolute; inset: calc(var(--hp-ring) + var(--hp-bezel)); z-index: 1;
  border-radius: calc(var(--hp-r) - var(--hp-ring) - var(--hp-bezel));
  display: flex; flex-direction: column; overflow: hidden; isolation: isolate; container-type: inline-size;
  background: var(--bg); color: var(--text); font-family: var(--font-ui); text-align: left;
  -webkit-user-select: none; user-select: none;
}
/* On screens, an opaque mask makes the screen one surface, cut by its own rounded corners: whatever moves on it stays
   inside them (Chrome could draw a moving layer's square corner onto the black border, in the dark theme at 3x), and
   its frosted bars and blurs take in only the screen, never the black border around it. Not in print (no need). */
@media screen { .hp__screen { -webkit-mask-image: linear-gradient(#000, #000); mask-image: linear-gradient(#000, #000); } }
.hp__screen svg { display: block; flex: none; fill: currentColor; }

/* The app's tokens the site does not have (the prototype's src/ui/tokens.css), light, then dark on screens only
   (print takes the light ones, as in site.css). Its other colors are the site's own, which are the app's. */
.hp__screen {
  --app-bar: rgb(251 248 243 / 0.80);            /* --bar-material: nav bar, pinned bar, composer, tab bar */
  --app-bar-hair: rgb(31 35 41 / 0.16);          /* --bar-hairline */
  --app-thick: rgb(255 255 255 / 0.82);          /* --material-thick: action sheet */
  --app-menu: rgb(251 248 243 / 0.97);           /* --material-menu: context menu, reactions */
  --app-sep: rgb(31 35 41 / 0.12);               /* --menu-separator */
  --app-sep-thick: rgb(31 35 41 / 0.07);         /* --menu-separator-thick */
  --app-sheet-dim: rgb(26 20 14 / 0.28);
  --app-push-dim: rgb(31 35 41 / 0.10);
  --app-press: rgb(31 35 41 / 0.12);             /* --press-strong */
  --app-wash: color-mix(in srgb, var(--bg) 30%, transparent); /* the context menu's backdrop */
  --app-card: var(--surface);                    /* the sealed notice */
  --app-card-shadow: 0 1px 2px rgb(60 42 24 / 0.05), 0 0 0 calc(0.5 * var(--pt)) rgb(60 42 24 / 0.04);
  --app-field: var(--surface);                   /* --field-bg */
  --app-field-edge: #E3DCD0;                     /* --field-border (the app's --input-border) */
  --app-field-focus: color-mix(in srgb, #8E877E 55%, #E3DCD0);
  --app-dot: var(--text-3);                      /* --typing-dot */
  --app-pill: rgb(239 233 224 / 0.86);           /* --pill-material: the date */
  --app-more: var(--container);                  /* the reactions' "+" disc */
  --app-lift: 0 calc(2 * var(--pt)) calc(10 * var(--pt)) rgb(60 42 24 / 0.10), 0 0 0 calc(0.5 * var(--pt)) rgb(60 42 24 / 0.05);
  --app-page-edge: calc(-0.5 * var(--pt)) 0 0 rgb(0 0 0 / 0.05), calc(-10 * var(--pt)) 0 calc(30 * var(--pt)) rgb(0 0 0 / 0.10);
  --app-brand: linear-gradient(135deg, #D45A40 0%, #B4412C 55%, #8A2C1B 100%); /* --brand-gradient */
  --app-hero: radial-gradient(calc(600 * var(--pt)) calc(420 * var(--pt)) at 50% 0%, rgb(180 65 44 / 0.10), rgb(180 65 44 / 0) 70%), linear-gradient(#FFFDF9, #FBF8F3);
  --app-seal-shadow: rgb(156 54 34 / 0.25);
  --app-emoji-mix: 16%;                          /* an emoji avatar's tint */
  --app-mark-l: inline;                          /* the wax seal, light; the dark wax seal in dark */
  --app-row-pinned: color-mix(in srgb, var(--container) 55%, var(--bg)); /* a pinned chat's row (app.css) */
  --app-mark-d: none;
}
@media screen {
  :root[data-theme="dark"] .hp__screen {
    --app-bar: rgb(18 19 22 / 0.78); --app-bar-hair: rgb(242 238 232 / 0.14); --app-thick: rgb(36 39 44 / 0.86);
    --app-menu: rgb(36 39 44 / 0.94); --app-sep: rgb(242 238 232 / 0.12); --app-sep-thick: rgb(0 0 0 / 0.25);
    --app-sheet-dim: rgb(0 0 0 / 0.46); --app-push-dim: rgb(0 0 0 / 0.32); --app-press: rgb(242 238 232 / 0.12);
    --app-wash: rgb(0 0 0 / 0.35); --app-card: var(--container); --app-card-shadow: none;
    --app-field: var(--container); --app-field-edge: #30333A; --app-field-focus: color-mix(in srgb, #98938B 55%, #30333A);
    --app-dot: var(--text-2); --app-pill: rgb(36 39 44 / 0.86); --app-more: var(--container-2);
    --app-lift: 0 calc(2 * var(--pt)) calc(12 * var(--pt)) rgb(0 0 0 / 0.45);
    --app-page-edge: calc(-0.5 * var(--pt)) 0 0 rgb(255 255 255 / 0.04), calc(-10 * var(--pt)) 0 calc(30 * var(--pt)) rgb(0 0 0 / 0.45);
    --app-brand: linear-gradient(135deg, #F4A088 0%, #F08B6E 50%, #C9583E 100%);
    --app-hero: radial-gradient(calc(600 * var(--pt)) calc(420 * var(--pt)) at 50% 0%, rgb(240 139 110 / 0.14), rgb(240 139 110 / 0) 70%), #121316;
    --app-seal-shadow: rgb(0 0 0 / 0.5); --app-emoji-mix: 32%; --app-mark-l: none; --app-mark-d: inline;
    --app-row-pinned: color-mix(in srgb, var(--container) 42%, var(--bg));
  }
}
@media screen and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .hp__screen {
    --app-bar: rgb(18 19 22 / 0.78); --app-bar-hair: rgb(242 238 232 / 0.14); --app-thick: rgb(36 39 44 / 0.86);
    --app-menu: rgb(36 39 44 / 0.94); --app-sep: rgb(242 238 232 / 0.12); --app-sep-thick: rgb(0 0 0 / 0.25);
    --app-sheet-dim: rgb(0 0 0 / 0.46); --app-push-dim: rgb(0 0 0 / 0.32); --app-press: rgb(242 238 232 / 0.12);
    --app-wash: rgb(0 0 0 / 0.35); --app-card: var(--container); --app-card-shadow: none;
    --app-field: var(--container); --app-field-edge: #30333A; --app-field-focus: color-mix(in srgb, #98938B 55%, #30333A);
    --app-dot: var(--text-2); --app-pill: rgb(36 39 44 / 0.86); --app-more: var(--container-2);
    --app-lift: 0 calc(2 * var(--pt)) calc(12 * var(--pt)) rgb(0 0 0 / 0.45);
    --app-page-edge: calc(-0.5 * var(--pt)) 0 0 rgb(255 255 255 / 0.04), calc(-10 * var(--pt)) 0 calc(30 * var(--pt)) rgb(0 0 0 / 0.45);
    --app-brand: linear-gradient(135deg, #F4A088 0%, #F08B6E 50%, #C9583E 100%);
    --app-hero: radial-gradient(calc(600 * var(--pt)) calc(420 * var(--pt)) at 50% 0%, rgb(240 139 110 / 0.14), rgb(240 139 110 / 0) 70%), #121316;
    --app-seal-shadow: rgb(0 0 0 / 0.5); --app-emoji-mix: 32%; --app-mark-l: none; --app-mark-d: inline;
    --app-row-pinned: color-mix(in srgb, var(--container) 42%, var(--bg));
  }
}

/* The iPhone: the Dynamic Island, the home indicator, the status bar (app/chrome.tsx, app.css "System chrome") */
.hp-island {
  position: absolute; z-index: 5; top: calc(11 * var(--pt)); left: 50%; width: calc(126 * var(--pt)); height: calc(37 * var(--pt));
  margin-left: calc(-63 * var(--pt)); border-radius: calc(18.5 * var(--pt)); background: #000;
}
.hp-home {
  position: absolute; z-index: 5; left: 50%; bottom: calc(8 * var(--pt)); width: calc(134 * var(--pt)); height: calc(5 * var(--pt));
  margin-left: calc(-67 * var(--pt)); border-radius: calc(3 * var(--pt)); background: var(--text); opacity: 0.92;
}
.hp-status {
  position: relative; display: flex; align-items: center; justify-content: space-between;
  height: calc(54 * var(--pt)); padding-top: calc(5 * var(--pt)); color: var(--text);
}
.hp-status__time {
  display: flex; justify-content: center; width: calc(134 * var(--pt)); padding-left: calc(4 * var(--pt));
  font-size: calc(17 * var(--pt)); line-height: calc(22 * var(--pt)); font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.hp-status__icons { display: flex; align-items: center; justify-content: center; gap: calc(6 * var(--pt)); width: calc(134 * var(--pt)); padding-right: calc(2 * var(--pt)); }
.hp__screen .sb-bars { width: calc(18 * var(--pt)); height: calc(12 * var(--pt)); }
.hp__screen .sb-wifi { width: calc(16 * var(--pt)); height: calc(12 * var(--pt)); fill: none; }
.hp__screen .sb-battery { width: calc(27 * var(--pt)); height: calc(13 * var(--pt)); fill: none; }

/* The chat's navigation bar (modules/chat/Header.tsx): the status bar, then a 60-point bar (taller in a chat: its
   44-point row starts 2 points under the status bar), one frosted material over the conversation. In the row: the
   back chevron alone on the 16-point margin, the avatar (36) at 48 points, the name at 94 and under it the status,
   "online" in green or "typing" in wax (Last Seen & Online), and the lock at the far right in its 44-point target:
   grey until both people have marked the security code as verified. Its hairline, and the pinned bar under it, are
   in home-anim.css. */
.hp-top {
  position: absolute; z-index: 3; top: 0; left: 0; right: 0;
  background: var(--app-bar);
  -webkit-backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt))); backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt)));
}
.hp-head { position: relative; height: calc(44 * var(--pt)); margin: calc(2 * var(--pt)) 0 calc(14 * var(--pt)); }
.hp-head__back { position: absolute; left: calc(8 * var(--pt)); top: 0; display: flex; align-items: center; width: calc(36 * var(--pt)); height: 100%; padding-left: calc(8 * var(--pt)); color: var(--link); }
.hp__screen .hp-head__back svg { width: calc(13 * var(--pt)); height: calc(21 * var(--pt)); fill: none; }
.hp-avatar {
  position: absolute; left: calc(48 * var(--pt)); top: calc(4 * var(--pt));
  display: grid; place-items: center; width: calc(36 * var(--pt)); height: calc(36 * var(--pt)); border-radius: 50%;
  background: linear-gradient(180deg, color-mix(in srgb, var(--avatar-1) 78%, #FFFFFF 22%) 0%, var(--avatar-1) 100%);
  color: var(--on-avatar); font-size: calc(14 * var(--pt)); line-height: 1; font-weight: 600; letter-spacing: 0.01em;
}
.hp-head__who { position: absolute; left: calc(94 * var(--pt)); right: calc(56 * var(--pt)); top: calc(4 * var(--pt)); display: flex; flex-direction: column; min-width: 0; }
.hp-head__name { font-size: calc(16 * var(--pt)); line-height: calc(20 * var(--pt)); font-weight: 600; letter-spacing: -0.011em; white-space: nowrap; }
.hp-head__sub { display: flex; align-items: center; font-size: calc(13 * var(--pt)); line-height: calc(16 * var(--pt)); letter-spacing: -0.003em; color: var(--success); white-space: nowrap; }
.hp-head__lock { position: absolute; right: calc(1 * var(--pt)); top: 0; display: grid; place-items: center; width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); color: var(--text-3); }
.hp__screen .hp-head__lock svg { width: calc(24 * var(--pt)); height: calc(24 * var(--pt)); }

/* The conversation: bottom-aligned above the composer (app.css "Conversation: timeline") */
.hp-chat { position: relative; flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; justify-content: flex-end; padding-bottom: calc(10 * var(--pt)); }
/* The sealed notice at the start of every chat (ui/security.tsx, SealedNotice): the seal on its disc, two lines, a chevron */
.hp-notice {
  position: relative; display: flex; align-items: center; gap: calc(12 * var(--pt));
  margin: calc(8 * var(--pt)) calc(16 * var(--pt)) calc(6 * var(--pt)); padding: calc(12 * var(--pt)) calc(36 * var(--pt)) calc(12 * var(--pt)) calc(12 * var(--pt));
  border-radius: calc(16 * var(--pt)); background: var(--app-card); box-shadow: var(--app-card-shadow);
}
.hp-notice__mark { display: grid; place-items: center; flex: none; width: calc(36 * var(--pt)); height: calc(36 * var(--pt)); border-radius: 50%; background: var(--accent-container); color: var(--seal); }
.hp__screen .hp-notice__mark svg { width: calc(22 * var(--pt)); height: calc(22 * var(--pt)); }
.hp-notice__text { display: flex; flex-direction: column; gap: calc(2 * var(--pt)); min-width: 0; }
.hp-notice__text b { font-size: calc(15 * var(--pt)); line-height: calc(20 * var(--pt)); font-weight: 600; letter-spacing: -0.009em; }
.hp-notice__text span { font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt)); letter-spacing: -0.003em; color: var(--text-2); }
.hp__screen .hp-notice__go { position: absolute; right: calc(16 * var(--pt)); top: 50%; width: calc(14 * var(--pt)); height: calc(14 * var(--pt)); margin-top: calc(-7 * var(--pt)); color: var(--text-3); opacity: 0.55; }
/* The date over the day's first message: 16 points under the notice, 8 over the message */
.hp-day { display: flex; justify-content: center; margin-top: calc(10 * var(--pt)); }
.hp-day > span {
  padding: calc(3 * var(--pt)) calc(10 * var(--pt)); border-radius: calc(11 * var(--pt)); background: var(--app-pill);
  color: var(--system-text); font-size: calc(12 * var(--pt)); line-height: calc(16 * var(--pt)); font-weight: 600; letter-spacing: 0.01em;
}

/* Messages (app.css "Bubbles"): every message is its own bubble, with no tail, 8 points from the next one, on
   the 16-point margins, never combined with the one before. A bubble is at most 76 % of the row (274 points), its
   corners 18 but 7.8 on the photo's side (the VIP square's corner, where the tail grew until 0.9.18). The time (11 points, a little paler) sits at the end of the last line: an
   invisible copy of it (::after) keeps its room. Read checks keep their full colour. */
.hp-group { position: relative; display: flex; flex-direction: column; gap: calc(8 * var(--pt)); margin-top: calc(8 * var(--pt)); padding: 0 calc(16 * var(--pt)); }
.hp-group--in { align-items: flex-start; }
.hp-group--out { align-items: flex-end; }
.hp-b {
  position: relative; isolation: isolate; max-width: calc(274.36 * var(--pt)); margin: 0;
  padding: calc(6 * var(--pt)) calc(12 * var(--pt)) calc(7 * var(--pt)); border-radius: calc(18 * var(--pt));
  background: var(--bubble-in); color: var(--bubble-in-text);
  font-size: calc(16 * var(--pt)); line-height: calc(22 * var(--pt)); letter-spacing: -0.011em; overflow-wrap: anywhere;
}
.hp-b::after, .hp-b__cap::after, .hp-rx::after {
  content: "0:00 AM"; display: inline-block; visibility: hidden; margin-left: calc(8 * var(--pt));
  font-size: calc(11 * var(--pt)); line-height: calc(13 * var(--pt)); letter-spacing: 0; font-variant-numeric: tabular-nums;
}
/* French times are written 9 h 41 (index-fr.html): the room kept for them follows */
:root[lang^="fr"] .hp-b:not(.hp-b--photo, .hp-b--rx)::after, :root[lang^="fr"] :is(.hp-rx, .hp-b__cap)::after { content: "0 h 00"; }
.hp-group--out .hp-b { background: var(--bubble-out); color: var(--bubble-out-text); }
.hp-group--out :is(.hp-b, .hp-rx)::after { padding-right: calc(18 * var(--pt)); } /* the checks */
.hp-b--pin::after { padding-left: calc(14 * var(--pt)); }                         /* the pin */
.hp-group--in .hp-b { border-bottom-left-radius: calc(7.8 * var(--pt)); }
.hp-group--out .hp-b { border-bottom-right-radius: calc(7.8 * var(--pt)); }
/* Time and checks: 10 points from the bubble's right edge, 6 from its bottom */
.hp-meta {
  position: absolute; right: calc(10 * var(--pt)); bottom: calc(6 * var(--pt)); display: inline-flex; align-items: center; gap: calc(3 * var(--pt));
  font-size: calc(11 * var(--pt)); line-height: calc(13 * var(--pt)); letter-spacing: 0; font-variant-numeric: tabular-nums; white-space: nowrap;
  color: color-mix(in srgb, var(--bubble-in-meta) 68%, transparent);
}
.hp-group--out .hp-meta { color: color-mix(in srgb, var(--bubble-out-meta) 68%, transparent); }
.hp__screen .hp-tick { width: calc(15 * var(--pt)); height: calc(10 * var(--pt)); margin-right: calc(-2 * var(--pt)); color: var(--tick-read); fill: none; }
.hp__screen .hp-mpin { width: calc(11 * var(--pt)); height: calc(11 * var(--pt)); color: var(--bubble-in-meta); }
/* A photo with its caption (app.css "Photos"): a 3-point frame of the bubble's color, the photo 240 x 180 with corners
   of 15 (6 over the caption), the caption under it, its time on the caption's last line */
.hp-b--photo { padding: calc(3 * var(--pt)); }
.hp-b--photo::after { content: none; }
.hpa-ph { display: block; width: calc(240 * var(--pt)); height: calc(180 * var(--pt)); overflow: hidden; border-radius: calc(15 * var(--pt)) calc(15 * var(--pt)) calc(6 * var(--pt)) calc(6 * var(--pt)); background: var(--container-2); }
.hpa-ph img { display: block; width: 100%; height: 100%; object-fit: cover; }
.hp-b__cap { display: block; width: calc(240 * var(--pt)); padding: calc(5 * var(--pt)) calc(9 * var(--pt)) calc(4 * var(--pt)); }
/* A reaction (app.css "Reactions", like Telegram's): inside the bubble, on a row of its own under the text, a pill
   tinted with the bubble's accent holding the emoji and the face of who reacted; the time and checks move onto that
   row, at its right */
.hp-b--rx { padding: 0; }
.hp-b--rx::after { content: none; }
.hp-b__t { display: block; padding: calc(6 * var(--pt)) calc(12 * var(--pt)) calc(5 * var(--pt)); }
.hp-rx { display: flex; align-items: center; padding: calc(2 * var(--pt)) calc(10 * var(--pt)) calc(7 * var(--pt)) calc(8 * var(--pt)); }
.hp-rx__chip {
  display: inline-flex; align-items: center; height: calc(24 * var(--pt)); padding: 0 calc(6 * var(--pt)); border-radius: calc(12 * var(--pt));
  background: color-mix(in srgb, var(--link) 10%, transparent); font-size: calc(15 * var(--pt)); line-height: 1;
}
.hp-rx__chip img.emoji { width: calc(15 * var(--pt)); height: calc(15 * var(--pt)); margin: 0 calc(6 * var(--pt)) 0 calc(2.5 * var(--pt)); vertical-align: 0; }
.hp-rx__av {
  display: grid; place-items: center; width: calc(18 * var(--pt)); height: calc(18 * var(--pt)); border-radius: 50%;
  background: linear-gradient(180deg, color-mix(in srgb, var(--avatar-1) 78%, #FFFFFF 22%) 0%, var(--avatar-1) 100%);
  color: var(--on-avatar); font-size: calc(7 * var(--pt)); line-height: 1; font-weight: 600;
}
.hp-b--rx > .hp-meta { bottom: calc(12 * var(--pt)); }
/* Until the French phase, index-fr.html keeps the earlier phone markup (its still only): a photo's time on the photo
   itself, and the lock that once stood before the @username, which the app no longer shows */
.hp-meta--photo {
  right: calc(9 * var(--pt)); bottom: calc(9 * var(--pt)); padding: calc(2 * var(--pt)) calc(6 * var(--pt)); border-radius: calc(9 * var(--pt));
  background: rgb(0 0 0 / 0.42); color: #FFFFFF; -webkit-backdrop-filter: blur(calc(6 * var(--pt))); backdrop-filter: blur(calc(6 * var(--pt)));
}
.hp__screen .hp-head__sub > svg { display: none; }
/* A notice in the conversation: "You pinned a message" */
.hp-sys { display: flex; justify-content: center; margin: calc(8 * var(--pt)) 0 calc(4 * var(--pt)); padding: 0 calc(24 * var(--pt)); }
.hp-sys > span {
  display: inline-block; max-width: 100%; padding: calc(4 * var(--pt)) calc(12 * var(--pt)); border-radius: calc(13 * var(--pt));
  background: var(--system-bg); color: var(--system-text); white-space: nowrap;
  font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt)); font-weight: 500; letter-spacing: -0.003em;
}
/* the pin's ink on the pill's padding, as the app's Icon pull="start" places it */
.hp__screen .hp-sys svg { display: inline-block; width: calc(14 * var(--pt)); height: calc(14 * var(--pt)); margin: 0 calc(5 * var(--pt)) 0 calc(-3.5 * var(--pt)); vertical-align: calc(-2.5 * var(--pt)); }
/* Maude typing: a bubble of its own under the last message (app/chat/notices.tsx, TypingRow). Only in the demo. */
.hp-typing {
  position: absolute; left: calc(16 * var(--pt)); bottom: calc(10 * var(--pt)); isolation: isolate;
  display: flex; align-items: center; gap: calc(4 * var(--pt)); height: calc(38 * var(--pt)); padding: 0 calc(14 * var(--pt));
  border-radius: calc(18 * var(--pt)) calc(18 * var(--pt)) calc(18 * var(--pt)) calc(7.8 * var(--pt)); background: var(--bubble-in);
  opacity: 0; transform-origin: 0 100%;
}
.hp-typing i { width: calc(7 * var(--pt)); height: calc(7 * var(--pt)); border-radius: 50%; background: var(--app-dot); opacity: 0.35; }

/* The composer (app.css "Conversation: composer" and chat/composer.css): three shapes on one line, as in Telegram's
   bar: the "+" disc, the 36-point field and, at its right, the "+"'s twin, a round button with the microphone that
   turns into Send (the wax disc) while there is text. Both discs are 36 points, each in a 44-point target, 2 points
   from the field; the discs end 18 points from the screen's edges (the app's --composer-edge on a 393-point iPhone),
   22 points under the hairline and 22 above the screen's bottom */
.hp-composer {
  flex: none; position: relative; z-index: 2; display: flex; align-items: flex-end; gap: calc(2 * var(--pt));
  padding: calc(22 * var(--pt)) calc(14 * var(--pt)) calc(22 * var(--pt)) calc(14 * var(--pt));
  background: var(--app-bar); border-top: calc(0.5 * var(--pt)) solid var(--app-bar-hair);
  -webkit-backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt))); backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt)));
}
.hp-plus, .hp-act { position: relative; display: grid; place-items: center; flex: none; width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); margin: calc(-4 * var(--pt)) 0; }
.hp-plus > span, .hp-act__disc { display: grid; place-items: center; width: calc(36 * var(--pt)); height: calc(36 * var(--pt)); border-radius: 50%; background: var(--container); color: var(--text-2); }
.hp__screen .hp-plus svg { width: calc(20 * var(--pt)); height: calc(20 * var(--pt)); }
.hp__screen .hp-act__disc svg { width: calc(22 * var(--pt)); height: calc(22 * var(--pt)); }
/* Dark: the field and the two discs share one fill, so the discs carry the field's 1-point rim, their glyphs the text's colour */
:root[data-theme="dark"] .hp__screen :is(.hp-plus > span, .hp-act__disc) { box-shadow: inset 0 0 0 calc(1 * var(--pt)) var(--app-field-edge); color: var(--text); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .hp__screen :is(.hp-plus > span, .hp-act__disc) { box-shadow: inset 0 0 0 calc(1 * var(--pt)) var(--app-field-edge); color: var(--text); } }
.hp-field {
  position: relative; flex: 1; min-width: 0; height: calc(36 * var(--pt)); border-radius: calc(18 * var(--pt));
  background: var(--app-field); box-shadow: inset 0 0 0 calc(1 * var(--pt)) var(--app-field-edge);
}
.hp-field__ph {
  position: absolute; left: calc(14 * var(--pt)); top: calc(7 * var(--pt)); white-space: nowrap;
  font-size: calc(17 * var(--pt)); line-height: calc(22 * var(--pt)); letter-spacing: -0.013em; color: var(--text-3);
}


/* ------------------------------------------------------------------------------------------------- H-2 promises */
/* Below 1024: one column of cards, the icon to the left of the words. 1024 and up: three cards side by side. */
.promise-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
.promise { display: flex; align-items: flex-start; gap: var(--s-4); }
.promise__body { display: flex; flex-direction: column; align-items: flex-start; flex: 1; min-width: 0; }
.promise__title { font-size: 20px; line-height: 26px; }
.promise__title > span { white-space: nowrap; } /* each sentence whole: a title that needs two lines breaks between them ("No phone number. / No email." at 360 px) */
/* Where the three cards sit side by side, each title takes two short lines, the same in all three; below 1024 a card
   is a full-width row and its title runs on one line. */
@media (min-width: 1024px) { .promise__title > span { display: block; } }
.promise__text { margin-top: var(--s-2); color: var(--text-2); }
.promise__link { margin-top: var(--s-4); font-size: 15px; }
@media (max-width: 599px) {
  .promise { padding: var(--s-5); }
  .promise__title { font-size: 18px; line-height: 24px; margin-top: 2px; }
  .promise__link { margin-top: var(--s-3); }
}
@media (min-width: 600px) {
  .promise { gap: var(--s-5); }
}
@media (min-width: 1024px) {
  /* the three cards share four rows (icon, title, text, link), so titles, texts and links line up across them.
     The link: 10 px of margin, then 10 px of padding above and below its words and 8 px on each side, so the keyboard
     focus ring sits evenly around the words and the link is 48 px tall; the negative margins (-8 px on the sides,
     -10 px at the bottom) keep the words on the card's inner edges. The words stay 20 px under the text, as before. */
  .promise-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: repeat(4, auto); column-gap: var(--s-6); row-gap: 0; }
  .promise { display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; justify-items: start; }
  .promise__body { display: contents; }
  .promise__title { margin-top: var(--s-5); }
  .promise__link { margin: 10px -8px -10px; padding: 10px 8px; align-self: end; }
}


/* ------------------------------------------------------------------------------------------------- H-3 what you can do */
/* A bento of four tiles, a second bento of seven (.ft-six, see "Seven more tiles"), then a panel of twelve more features.
   Each tile: its title and sentence on top, then a small, still piece of the app (.ft-stage) on the chat's paper,
   drawn as the approved mockups draw it (design/prototype), with the site tokens, so light and dark follow the theme.
   - Layout: one column below 600 px; two from 600 (Chats, then Photos and Devices side by side, then Replies); from
     1024, Chats tall on the left, Photos and Devices on top, Replies wide under them. From 1024 the tiles share rows
     (subgrid), so their titles and pictures line up.
   - More features (.ft-more): one panel like the tiles, with no title, twelve features in a list divided by hairlines
     across its whole width (one column below 600, two from 600, three from 1024). Never one box per feature.
   - Motion: the site's reveal brings the tiles in; on the reply tile, the reactions bar opens and the two reactions
     settle once (none with reduced motion). No script. */
.ft-bento { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); }
@media (min-width: 600px) {
  .ft-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-areas: "chats chats" "photos devices" "replies replies"; gap: var(--s-5); }
  .ft-tile--chats { grid-area: chats; } .ft-tile--photos { grid-area: photos; }
  .ft-tile--devices { grid-area: devices; } .ft-tile--replies { grid-area: replies; }
}
@media (min-width: 1024px) {
  .ft-bento { grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr) minmax(0, 1fr); grid-template-areas: "chats photos devices" "chats replies replies"; gap: var(--s-6); }
}

/* ---------------------------------------------------------------- Tile */
/* The app's own materials, which the site's tokens do not have (design/prototype/src/ui/tokens.css), light then dark:
   the bars' translucent paper and hairline, the menus' material and line, the emoji avatars' tint, the grouped lists'
   shadow, the "+" disc of the reactions bar, the composer's field. */
.ft-tile {
  --ft-wall: radial-gradient(120% 90% at 50% 0%, rgb(255 255 255 / 0.9), rgb(255 255 255 / 0) 70%), var(--bg);
  --ft-bar: rgb(251 248 243 / 0.80); --ft-hair: rgb(31 35 41 / 0.16);
  --ft-menu: rgb(251 248 243 / 0.97); --ft-menu-line: rgb(31 35 41 / 0.12); --ft-menu-shadow: rgb(0 0 0 / 0.14);
  --ft-emoji-tint: 16%; --ft-grouped: 0 1px 2px rgb(60 42 24 / 0.05), 0 0 0 0.5px rgb(60 42 24 / 0.04); --ft-more-disc: var(--container);
  --ft-field: var(--surface); --ft-field-edge: #E3DCD0; /* the composer's field: --field-bg, --field-border */
  display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  border-radius: var(--r-sheet); background: var(--surface);
  box-shadow: 0 0 0 1px var(--card-edge), var(--shadow-1);
}
@media screen {
  :root[data-theme="dark"] .ft-tile {
    --ft-wall: radial-gradient(120% 90% at 50% 0%, rgb(240 139 110 / 0.07), rgb(240 139 110 / 0) 70%), var(--bg);
    --ft-bar: rgb(18 19 22 / 0.78); --ft-hair: rgb(242 238 232 / 0.14);
    --ft-menu: rgb(36 39 44 / 0.94); --ft-menu-line: rgb(242 238 232 / 0.12);
    --ft-emoji-tint: 32%; --ft-grouped: none; --ft-more-disc: var(--container-2);
    --ft-field: var(--container); --ft-field-edge: #30333A;
  }
}
@media screen and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ft-tile {
    --ft-wall: radial-gradient(120% 90% at 50% 0%, rgb(240 139 110 / 0.07), rgb(240 139 110 / 0) 70%), var(--bg);
    --ft-bar: rgb(18 19 22 / 0.78); --ft-hair: rgb(242 238 232 / 0.14);
    --ft-menu: rgb(36 39 44 / 0.94); --ft-menu-line: rgb(242 238 232 / 0.12);
    --ft-emoji-tint: 32%; --ft-grouped: none; --ft-more-disc: var(--container-2);
    --ft-field: var(--container); --ft-field-edge: #30333A;
  }
}

.ft-stage {
  position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s-3);
  min-height: 248px; padding: var(--s-6) var(--s-5); background: var(--ft-wall);
  box-shadow: inset 0 1px 0 var(--divider);
  font-family: var(--font-ui); text-align: left; -webkit-user-select: none; user-select: none;
}
.ft-stage svg { display: block; flex: none; }
.ft-copy { order: -1; padding: var(--s-6) var(--s-6) var(--s-5); }
.ft-title { font-size: 18px; line-height: 24px; }
/* The tiles' short texts follow the site's rule for paragraphs (site.css): each line runs to the column's edge, and
   site.js keeps the last two words together, so no word is left alone on a last line. */
.ft-text { margin-top: 6px; font-size: 15px; line-height: 23px; color: var(--text-2); }
@media (min-width: 1024px) {
  .ft-copy { padding: var(--s-7) var(--s-7) var(--s-6); }
  .ft-title { font-size: 20px; line-height: 26px; }
}

/* ---------------------------------------------------------------- Pieces of the app */
/* Each piece copies the app's own values (design/prototype/src: app/app.css, ui/ui.css, modules/chat/chat.css,
   modules/settings/settings.css), in app points: calc(N * var(--pt)), one point being 0.9 px (0.86 on phones), so a
   piece keeps the mockups' proportions. The group's window and the reply tile's conversation are screens: always
   393 pt wide like the mockups' iPhone, so where the tile is narrower their point shrinks (container units) and the
   messages break where the app breaks them. Icons are the app's own glyphs (the ft- symbols at the top of the
   section), emoji are Apple's images (assets/emoji). */
.ft-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.ft-stage { --pt: 0.9px; }
@media (max-width: 599px) { .ft-stage { --pt: 0.86px; } }
.ft-win, .ft-convo { container-type: inline-size; }
.ft-win > *, .ft-convo > * { --pt: calc(100cqw / 393); }
.ft-stage svg { fill: currentColor; }

/* Avatars: initials on the person's colour, or a group's emoji on a tint of it */
.ft-av {
  --av: 36; --avf: 14; --avc: var(--avatar-5);
  display: inline-grid; place-items: center; flex: none; width: calc(var(--av) * var(--pt)); height: calc(var(--av) * var(--pt)); border-radius: 50%;
  background: linear-gradient(180deg, color-mix(in srgb, var(--avc) 78%, #FFFFFF) 0%, var(--avc) 100%);
  color: var(--on-avatar); font-size: calc(var(--avf) * var(--pt)); line-height: 1; font-weight: 600; font-style: normal; letter-spacing: 0.01em;
}
.ft-av--msg { --av: 30; --avf: 11; }
.ft-av--emoji { background: color-mix(in srgb, var(--avc) var(--ft-emoji-tint), var(--surface)); }
.ft-av--emoji .emoji { width: 60%; height: 60%; margin: 0; vertical-align: 0; }

/* Messages: rows 2 pt apart inside a group, 8 pt between groups; bubbles of 18 pt (6 pt inside a group, 7.8 pt on the
   photo's side of the last one, ft-b--end: no tail, as in the app since 0.9.19); the time (and ticks) in the bubble's corner, with room kept for it on the last line (.ft-sp). */
.ft-thread { display: flex; flex-direction: column; padding: calc(4 * var(--pt)) 0 calc(10 * var(--pt)); }
.ft-m { display: flex; align-items: flex-end; padding: 0 calc(16 * var(--pt)); margin-top: calc(2 * var(--pt)); }
.ft-m--first { margin-top: calc(8 * var(--pt)); }
.ft-m--out { justify-content: flex-end; }
.ft-m--av { padding-left: calc(10 * var(--pt)); }
.ft-m--av > .ft-av { margin-right: calc(8 * var(--pt)); }
.ft-b {
  position: relative; display: flow-root; max-width: 76%; min-width: 0; border-radius: calc(18 * var(--pt));
  background: var(--bubble-in); color: var(--bubble-in-text);
}
.ft-m--out .ft-b { background: var(--bubble-out); color: var(--bubble-out-text); }
.ft-m--in .ft-b--cont { border-top-left-radius: calc(6 * var(--pt)); }
.ft-m--in .ft-b--more { border-bottom-left-radius: calc(6 * var(--pt)); }
.ft-m--in .ft-b--end { border-bottom-left-radius: calc(7.8 * var(--pt)); }
.ft-m--out .ft-b--cont { border-top-right-radius: calc(6 * var(--pt)); }
.ft-m--out .ft-b--more { border-bottom-right-radius: calc(6 * var(--pt)); }
.ft-m--out .ft-b--end { border-bottom-right-radius: calc(7.8 * var(--pt)); }
.ft-from {
  display: block; padding: calc(8 * var(--pt)) calc(12 * var(--pt)) 0; font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt));
  font-weight: 600; letter-spacing: -0.003em; color: var(--sc); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ft-t {
  padding: calc(6 * var(--pt)) calc(12 * var(--pt)) calc(7 * var(--pt)); font-size: calc(16 * var(--pt)); line-height: calc(22 * var(--pt));
  letter-spacing: -0.011em; overflow-wrap: anywhere;
}
.ft-from + .ft-t { padding-top: calc(1 * var(--pt)); }
.ft-q + .ft-t { padding-top: calc(4 * var(--pt)); }
.ft-meta {
  position: absolute; right: calc(10 * var(--pt)); bottom: calc(6 * var(--pt)); display: inline-flex; align-items: center; gap: calc(3 * var(--pt));
  font-size: calc(11 * var(--pt)); line-height: calc(13 * var(--pt)); letter-spacing: 0; color: color-mix(in srgb, var(--bubble-in-meta) 68%, transparent);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ft-m--out .ft-meta { color: color-mix(in srgb, var(--bubble-out-meta) 68%, transparent); }
.ft-meta i { font-style: normal; margin-right: calc(2 * var(--pt)); }
.ft-sp { display: inline-flex; visibility: hidden; margin-left: calc(8 * var(--pt)); vertical-align: baseline; line-height: 1; }
.ft-sp .ft-meta { position: static; }
.ft-tick { width: calc(15 * var(--pt)); height: calc(10 * var(--pt)); margin-right: calc(-2 * var(--pt)); color: var(--tick-read); }
.ft-pie { width: calc(12 * var(--pt)); height: calc(12 * var(--pt)); opacity: 0.9; }
.ft-nw { white-space: nowrap; } /* a last word and its emoji: never an emoji alone on a line */

/* Chats and groups: the Weekend Hike chat as Karim sees it (its bar: back, the group's emoji, name and members; its
   last messages), and the group size. Below 1024 px the window is as tall as its last four messages (three on phones,
   .ft-m--extra hidden). From 1024, where the tile runs down both rows and the right column sets its height, the window
   is the whole chat screen of mockup 092 and takes the height the group size leaves (see the 1024 rules below). */
.ft-tile--chats .ft-stage { gap: var(--s-6); }
.ft-win {
  width: 100%; max-width: calc(393 * var(--pt)); overflow: hidden; border-radius: calc(22 * var(--pt));
  background: var(--bg); box-shadow: 0 0 0 1px var(--card-edge), var(--shadow-2);
}
.ft-bar {
  position: relative; display: flex; align-items: center; height: calc(60 * var(--pt)); padding: 0 calc(56 * var(--pt)) 0 calc(16 * var(--pt));
  background: var(--ft-bar); border-bottom: 0.5px solid var(--ft-hair);
}
.ft-tile--chats :is(.ft-early, .ft-pin, .ft-compose) { display: none; }
/* The pinned message under the bar (chat.css "Pinned messages", as Karim sees Maude's pin: no Unpin button): the
   2 pt wax track, "Pinned Message" and the message on one line, 16 pt in from both sides, 48 pt tall */
.ft-pin { align-items: center; gap: calc(10 * var(--pt)); height: calc(48 * var(--pt)); padding: 0 calc(16 * var(--pt)); }
.ft-pin > i { flex: none; width: calc(2 * var(--pt)); height: calc(32 * var(--pt)); border-radius: calc(1 * var(--pt)); background: var(--brand); }
.ft-pin__text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ft-pin__text b { font-size: calc(13 * var(--pt)); line-height: calc(17 * var(--pt)); font-weight: 600; letter-spacing: -0.003em; color: var(--brand); }
.ft-pin__text span {
  font-size: calc(15 * var(--pt)); line-height: calc(20 * var(--pt)); letter-spacing: -0.009em; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* The composer (app.css "Conversation: composer" and chat/composer.css, on a computer: no home zone): the 36 pt "+"
   disc, the 36 pt field and the round microphone, the "+"'s twin, 6 pt from the field on both sides, 7 pt under the
   hairline and 4 pt above the window's edge */
.ft-compose {
  flex: none; align-items: flex-end; gap: calc(6 * var(--pt));
  padding: calc(7 * var(--pt)) calc(12 * var(--pt)) calc(4 * var(--pt)) calc(12 * var(--pt));
  background: var(--ft-bar); border-top: 0.5px solid var(--ft-hair);
}
.ft-compose__plus, .ft-compose__act {
  display: grid; place-items: center; flex: none; width: calc(36 * var(--pt)); height: calc(36 * var(--pt));
  border-radius: 50%; background: var(--container); color: var(--text-2);
}
.ft-compose__plus svg { width: calc(20 * var(--pt)); height: calc(20 * var(--pt)); }
.ft-compose__act svg { width: calc(22 * var(--pt)); height: calc(22 * var(--pt)); }
:root[data-theme="dark"] :is(.ft-compose__plus, .ft-compose__act) { box-shadow: inset 0 0 0 calc(1 * var(--pt)) var(--ft-field-edge); color: var(--text); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) :is(.ft-compose__plus, .ft-compose__act) { box-shadow: inset 0 0 0 calc(1 * var(--pt)) var(--ft-field-edge); color: var(--text); } }
.ft-compose__field {
  flex: 1; min-width: 0; height: calc(36 * var(--pt)); padding: calc(7 * var(--pt)) calc(14 * var(--pt)) calc(8 * var(--pt));
  border-radius: calc(18 * var(--pt)); background: var(--ft-field); box-shadow: inset 0 0 0 calc(1 * var(--pt)) var(--ft-field-edge);
  font-size: calc(16 * var(--pt)); line-height: calc(21 * var(--pt)); letter-spacing: -0.011em; color: var(--text-3); white-space: nowrap;
}
/* Sophie's photo with its caption (app.css "Photos"): the 3 pt frame, her name over the photo, 6 pt corners on the
   photo under a name and over a caption, the 240 pt photo setting the bubble's width, the time under the caption */
.ft-b--cap { width: calc(246 * var(--pt)); }
.ft-b--cap .ft-media { border-radius: calc(6 * var(--pt)); }
.ft-b--cap > .ft-from { padding: calc(4 * var(--pt)) calc(9 * var(--pt)) calc(3 * var(--pt)); }
.ft-b--cap > .ft-t { padding: calc(5 * var(--pt)) calc(9 * var(--pt)) calc(4 * var(--pt)); }
.ft-bar__back { width: calc(13 * var(--pt)); height: calc(21 * var(--pt)); margin-right: calc(19 * var(--pt)); color: var(--link); }
.ft-bar > .ft-av { margin-right: calc(10 * var(--pt)); }
.ft-bar__who { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ft-bar__who > * { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ft-bar__who b { font-size: calc(16 * var(--pt)); line-height: calc(20 * var(--pt)); font-weight: 600; letter-spacing: -0.011em; color: var(--text); }
.ft-bar__who span { font-size: calc(13 * var(--pt)); line-height: calc(16 * var(--pt)); letter-spacing: -0.003em; color: var(--text-2); }
.ft-bar__lock { position: absolute; right: calc(1 * var(--pt)); top: calc(8 * var(--pt)); display: grid; place-items: center; width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); color: var(--text-3); }
.ft-bar__lock svg { width: calc(24 * var(--pt)); height: calc(24 * var(--pt)); }
.ft-size { display: flex; flex-direction: column; align-items: center; gap: var(--s-3); }
/* the crowd: rows of avatar dots fading at both ends, never wider than the window, so it ends under its corners */
.ft-crowd {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 5px; width: 100%; max-width: calc(393 * var(--pt)); height: 58px; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent); mask-image: linear-gradient(90deg, transparent, #000 22%, #000 78%, transparent);
}
.ft-crowd i { width: 16px; height: 16px; border-radius: 50%; background: linear-gradient(180deg, color-mix(in srgb, var(--avc) 78%, #FFFFFF) 0%, var(--avc) 100%); }
.ft-big { display: flex; align-items: baseline; flex-wrap: wrap; justify-content: center; gap: 0 10px; white-space: nowrap; }
.ft-big__pre, .ft-big__u { font-size: 17px; line-height: 24px; font-weight: 500; color: var(--text-2); }
.ft-big__n {
  font-family: var(--font-display); font-variation-settings: var(--display-variation); font-weight: 600;
  font-size: 64px; line-height: 1; letter-spacing: -0.035em; color: var(--seal); font-variant-numeric: lining-nums;
}
@media (max-width: 599px) {
  .ft-m--extra { display: none; } /* phones: three messages are enough */
  .ft-big__n { font-size: 52px; }
}
@media (min-width: 720px) and (max-width: 1023px) {
  /* the wide tile: the window and the number side by side, from where the window keeps its whole 393 pt */
  .ft-tile--chats .ft-stage { flex-direction: row; gap: var(--s-8); }
  .ft-tile--chats .ft-win { flex: 1 1 340px; }
  .ft-tile--chats .ft-size { flex: 1 1 220px; }
  .ft-crowd { max-width: 260px; }
}
/* where "Up to 1,000 members" would break after the number (720 to 1199 px), it stands on three centred lines */
@media (min-width: 720px) and (max-width: 1199px) {
  .ft-big { flex-direction: column; align-items: center; gap: 6px; }
}
@media (min-width: 1024px) {
  /* The tile runs down both rows, so its height comes from the right column and changes with the width. The window is
     a phone's chat screen that grows into that height (its flex basis is 0, so it never makes the rows taller): the
     frosted header (the bar and the pinned message, one material, one hairline) floats over the messages, which sit
     at the bottom above the composer and go up under the header, clipped by the window. Its height has a ceiling,
     644 of its own points (the stage is a container, so 100cqw / 393 is the window's point until it reaches its
     393 pt): at that height the header's edge crosses Sophie's photo 8 pt below the photo's top, and any lower
     window only moves the edge further down the photo (about 125 of its 180 pt at most, at 1199 px), so the edge never
     cuts a line of text, at any width. Today the ceiling holds only at 1024 and 1025 px (less than a pixel left, above
     the group size); it stays as the guard if a tile on the right grows. */
  .ft-tile--chats .ft-stage { container-type: inline-size; justify-content: center; gap: var(--s-10); padding-top: var(--s-8); padding-bottom: var(--s-8); }
  .ft-tile--chats .ft-win {
    position: relative; flex: 1 1 0; display: flex; flex-direction: column;
    max-height: calc(644 * min(100cqw / 393, var(--pt)));
  }
  .ft-tile--chats .ft-head {
    position: absolute; z-index: 2; top: 0; left: 0; right: 0;
    border-top-left-radius: inherit; border-top-right-radius: inherit; /* its blur stays inside the window's corners */
    background: var(--ft-bar); border-bottom: 0.5px solid var(--ft-hair);
    -webkit-backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt))); backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt)));
  }
  .ft-tile--chats .ft-head > .ft-bar { background: none; border-bottom: 0; }
  .ft-tile--chats :is(.ft-pin, .ft-compose, .ft-early) { display: flex; }
  /* above the composer the app keeps 18 pt under the last message: the timeline's 10 pt and the 8 pt its screen keeps
     over the composer (ui.css, .screen:has(> .screen-footer) .screen-content) */
  .ft-tile--chats .ft-thread { flex: 1 1 0; min-height: 0; overflow: hidden; justify-content: flex-end; padding-bottom: calc(18 * var(--pt)); }
  /* the group size: four rows of the crowd */
  .ft-tile--chats .ft-size { margin-top: auto; }
  .ft-tile--chats .ft-crowd { height: 79px; }
  /* rows shared by the tiles (subgrid): the titles and the pictures line up across the tiles */
  .ft-bento { grid-template-rows: min-content 1fr min-content min-content; grid-template-areas: none; }
  .ft-tile { display: grid; grid-template-rows: subgrid; grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .ft-tile--chats { grid-area: 1 / 1 / 5 / 2; }
  .ft-tile--chats .ft-stage { grid-row: 2 / 5; }
  .ft-tile--photos { grid-area: 1 / 2 / 3 / 3; } .ft-tile--devices { grid-area: 1 / 3 / 3 / 4; }
  .ft-tile--replies { grid-area: 3 / 2 / 5 / 4; }
  .ft-copy { grid-row: 1; } .ft-stage { grid-row: 2; }
  .ft-big__n { font-size: 72px; }
}

/* Voice messages and photos: the photo I sent (its location gone before it left the phone), and Maude's voice message,
   not played yet, each its own bubble, 8 pt apart, with no tail. The column is as wide as the photo's bubble and sits
   in the middle of the tile. */
.ft-sent { display: flex; flex-direction: column; width: calc(246 * var(--pt)); max-width: 100%; }
.ft-sent .ft-m { padding: 0; }
.ft-sent .ft-m:first-child { margin-top: 0; }
.ft-sent .ft-m + .ft-m { margin-top: calc(8 * var(--pt)); }
.ft-sent .ft-b { max-width: 100%; }
.ft-b--media { padding: calc(3 * var(--pt)); }
.ft-media {
  position: relative; width: calc(240 * var(--pt)); max-width: 100%; aspect-ratio: 4 / 3; overflow: hidden;
  border-radius: calc(15 * var(--pt)); background: var(--container-2);
}
.ft-m--out .ft-b--media.ft-b--end .ft-media { border-bottom-right-radius: calc(4.8 * var(--pt)); } /* 3 pt inside the bubble's 7.8 */
.ft-media img { width: 100%; height: 100%; object-fit: cover; }
/* on the photo: the app's time pill, dark glass */
.ft-meta--media {
  padding: calc(2 * var(--pt)) calc(6 * var(--pt)); border-radius: calc(9 * var(--pt)); background: rgb(0 0 0 / 0.42); color: #FFFFFF;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.ft-m--out .ft-meta--media { right: calc(9 * var(--pt)); bottom: calc(9 * var(--pt)); color: #FFFFFF; }
.ft-meta--media .ft-tick { color: rgb(255 255 255 / 0.92); }
.ft-b--file { min-width: calc(236 * var(--pt)); }
.ft-doc { display: flex; align-items: center; gap: calc(12 * var(--pt)); padding: calc(10 * var(--pt)) calc(12 * var(--pt)) calc(4 * var(--pt)) calc(10 * var(--pt)); }
.ft-doc__ic {
  display: grid; place-items: center; flex: none; width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); border-radius: calc(11 * var(--pt));
  background: var(--brand); color: var(--on-brand);
}
.ft-doc__ic svg { width: calc(24 * var(--pt)); height: calc(24 * var(--pt)); }
.ft-doc__t { display: flex; flex-direction: column; min-width: 0; }
.ft-doc__t > * { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ft-doc__t b { font-size: calc(15 * var(--pt)); line-height: calc(20 * var(--pt)); font-weight: 600; letter-spacing: -0.009em; }
.ft-doc__t span { font-size: calc(13 * var(--pt)); line-height: calc(17 * var(--pt)); letter-spacing: -0.003em; color: var(--bubble-out-meta); font-variant-numeric: tabular-nums; }
.ft-doc__foot { display: block; height: calc(22 * var(--pt)); }
/* A voice message (chat/voice/bubble.css): the 44 pt play disc in the bubble's accent (its link colour), 10 pt from the
   waveform (3 pt bars, 2 apart, round caps, 24 tall, at 32 % of the accent until it plays), and under it the length
   and the dot of a message not played yet; the time keeps its corner, on the second line's baseline */
.ft-voice { display: grid; grid-template-columns: calc(44 * var(--pt)) auto; column-gap: calc(10 * var(--pt)); align-items: center; padding: calc(8 * var(--pt)) calc(10 * var(--pt)) calc(6 * var(--pt)) calc(8 * var(--pt)); }
.ft-voice__play { display: grid; place-items: center; width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); border-radius: 50%; background: var(--bubble-in-link); color: var(--bubble-in); }
.ft-voice__play svg { width: calc(20 * var(--pt)); height: calc(20 * var(--pt)); transform: translateX(calc(1.5 * var(--pt))); }
.ft-voice__main { display: flex; flex-direction: column; gap: calc(2 * var(--pt)); min-width: 0; }
.ft-voice__wave { display: block; width: calc(148 * var(--pt)); height: calc(24 * var(--pt)); overflow: visible; }
.ft-voice__wave path { fill: none; stroke: color-mix(in srgb, var(--bubble-in-link) 32%, transparent); stroke-width: 3; stroke-linecap: round; }
.ft-voice__line { display: flex; align-items: center; height: calc(16 * var(--pt)); font-size: calc(12 * var(--pt)); line-height: calc(16 * var(--pt)); color: var(--bubble-in-meta); font-variant-numeric: tabular-nums; }
.ft-voice__line i { width: calc(6 * var(--pt)); height: calc(6 * var(--pt)); margin-left: calc(5 * var(--pt)); border-radius: 50%; background: var(--bubble-in-link); }
.ft-b--voice > .ft-meta { bottom: calc(8 * var(--pt)); }

/* Phone and computer: Settings › Devices (this iPhone, the other devices, Link a Device, then Remove All Other Devices
   under it, a red button of the same height and shape, as in the app since 12 Nov 2026) */
.ft-set { width: 100%; max-width: calc(361 * var(--pt)); }
.ft-set__h {
  padding: 0 calc(16 * var(--pt)) calc(8 * var(--pt)); font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt));
  font-weight: 600; letter-spacing: 0.005em; color: var(--text-2); white-space: nowrap;
}
.ft-set__group + .ft-set__h { margin-top: calc(24 * var(--pt)); }
.ft-set__group { overflow: hidden; border-radius: calc(12 * var(--pt)); background: var(--surface); box-shadow: var(--ft-grouped); }
.ft-set__row { display: flex; align-items: center; padding-left: calc(16 * var(--pt)); }
.ft-dev {
  display: grid; place-items: center; flex: none; width: calc(40 * var(--pt)); height: calc(40 * var(--pt)); margin-right: calc(12 * var(--pt));
  border-radius: 28%; background: var(--container); color: var(--text);
}
.ft-dev.is-me { background: var(--accent-container); color: var(--seal); }
.ft-dev svg { width: calc(22 * var(--pt)); height: calc(22 * var(--pt)); }
.ft-set__body {
  position: relative; flex: 1; display: flex; align-items: center; gap: calc(6 * var(--pt)); min-width: 0;
  padding: calc(9 * var(--pt)) calc(16 * var(--pt)) calc(9 * var(--pt)) 0;
}
.ft-set__row + .ft-set__row .ft-set__body::before { content: ""; position: absolute; top: 0; left: 0; right: 0; border-top: 0.5px solid var(--divider); }
.ft-set__t { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.ft-set__t > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ft-set__t > span:first-child { font-size: calc(17 * var(--pt)); line-height: calc(22 * var(--pt)); letter-spacing: -0.013em; color: var(--text); }
.ft-set__t > span + span { margin-top: calc(1 * var(--pt)); font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt)); letter-spacing: -0.003em; color: var(--text-2); }
.ft-chev { width: calc(14 * var(--pt)); height: calc(14 * var(--pt)); color: var(--text-3); opacity: 0.55; }
.ft-btn {
  display: flex; align-items: center; justify-content: center; height: calc(50 * var(--pt)); margin-top: calc(24 * var(--pt)); padding: 0 calc(20 * var(--pt));
  border-radius: calc(12 * var(--pt)); background: var(--primary); color: var(--on-primary);
  font-size: calc(17 * var(--pt)); line-height: calc(22 * var(--pt)); font-weight: 600; letter-spacing: -0.013em; white-space: nowrap;
}
/* the app's stacked buttons, 12 pt apart (--space-stack), the removal in the kit's red (.btn-destructive) */
.ft-btn + .ft-btn { margin-top: calc(12 * var(--pt)); }
.ft-btn--danger { background: var(--error-container); color: var(--on-error-container); }

/* Replies and reactions: the timer notice, the reactions bar of a long press (my thumbs-up chosen), Maude's message
   with my thumbs-up, and my reply to it (its quote, "edited", her heart, as on the phone at the top of the page) */
.ft-convo { width: 100%; max-width: calc(393 * var(--pt)); padding: 0; }
/* phones: the conversation's own 16 pt margins stand for most of the tile's side padding, so its screen stays large */
@media (max-width: 599px) { .ft-tile--replies .ft-stage { padding-inline: var(--s-2); } }
.ft-sysrow { display: flex; justify-content: center; padding: 0 calc(24 * var(--pt)); }
/* the app's notice pill: centred text that wraps rather than overflow, its lines full as in the app (.sys-pill) */
.ft-sys {
  display: inline-block; max-width: 100%; padding: calc(4 * var(--pt)) calc(12 * var(--pt)); border-radius: calc(13 * var(--pt));
  background: var(--system-bg); color: var(--system-text); font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt));
  font-weight: 500; letter-spacing: -0.003em; text-align: center;
}
.ft-sys svg {
  display: inline-block; width: calc(14 * var(--pt)); height: calc(14 * var(--pt)); margin: 0 calc(5 * var(--pt)) 0 calc(-1 * var(--pt));
  vertical-align: calc(-2.5 * var(--pt));
}
.ft-rxbar {
  align-self: flex-start; display: flex; align-items: center; height: calc(52 * var(--pt)); margin: calc(12 * var(--pt)) calc(16 * var(--pt)) 0;
  padding: 0 calc(6 * var(--pt)); border-radius: calc(26 * var(--pt)); background: var(--ft-menu);
  -webkit-backdrop-filter: blur(30px); backdrop-filter: blur(30px);
  box-shadow: 0 calc(8 * var(--pt)) calc(30 * var(--pt)) var(--ft-menu-shadow), 0 0 0 0.5px var(--ft-menu-line);
}
.ft-rxbar > span {
  display: grid; place-items: center; flex: none; width: calc(44 * var(--pt)); height: calc(44 * var(--pt)); border-radius: calc(22 * var(--pt));
  font-size: calc(27 * var(--pt)); line-height: 1;
}
.ft-rxbar > .is-on { background: var(--accent-container); }
.ft-rxbar > .ft-rxbar__more { width: calc(34 * var(--pt)); height: calc(34 * var(--pt)); margin-left: calc(4 * var(--pt)); background: var(--ft-more-disc); color: var(--text-2); }
.ft-rxbar__more svg { width: calc(20 * var(--pt)); height: calc(20 * var(--pt)); }
.ft-rxbar .emoji, .ft-rx .emoji { margin: 0; vertical-align: 0; }
/* reactions inside the bubble, the time at the end of their row */
.ft-b--rx .ft-t { padding-bottom: calc(5 * var(--pt)); }
.ft-rxs { display: flex; flex-wrap: wrap; align-items: center; gap: calc(4 * var(--pt)); padding: calc(2 * var(--pt)) calc(10 * var(--pt)) calc(7 * var(--pt)) calc(8 * var(--pt)); }
.ft-b--rx > .ft-meta { bottom: calc(12 * var(--pt)); }
.ft-rx {
  display: inline-flex; align-items: center; height: calc(24 * var(--pt)); padding: 0 calc(6 * var(--pt)); border-radius: calc(12 * var(--pt));
  background: color-mix(in srgb, var(--link) 10%, transparent); font-size: calc(15 * var(--pt)); line-height: 1;
}
.ft-rx .emoji { width: calc(15 * var(--pt)); height: calc(15 * var(--pt)); margin: 0 calc(6 * var(--pt)) 0 calc(2.5 * var(--pt)) !important; }
.ft-rx.is-mine { background: color-mix(in srgb, var(--brand) 15%, transparent); box-shadow: inset 0 0 0 calc(1 * var(--pt)) color-mix(in srgb, var(--brand) 45%, transparent); }
.ft-rx__av {
  display: grid; place-items: center; width: calc(18 * var(--pt)); height: calc(18 * var(--pt)); border-radius: 50%;
  background: linear-gradient(180deg, color-mix(in srgb, var(--avc) 78%, #FFFFFF) 0%, var(--avc) 100%);
  color: var(--on-avatar); font-size: calc(7 * var(--pt)); line-height: 1; font-weight: 600; font-style: normal;
}
/* the reply's quote of Maude's message, in her colour */
.ft-q {
  position: relative; display: flex; flex-direction: column; min-width: 0; margin: calc(6 * var(--pt)) calc(6 * var(--pt)) 0; overflow: hidden;
  padding: calc(6 * var(--pt)) calc(10 * var(--pt)) calc(5 * var(--pt)) calc(12 * var(--pt)); border-radius: calc(12 * var(--pt));
  background: color-mix(in srgb, var(--q) 12%, transparent); font-size: calc(15 * var(--pt)); line-height: calc(20 * var(--pt)); letter-spacing: -0.009em;
}
.ft-q::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: calc(3 * var(--pt)); background: var(--q); }
.ft-q > * { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ft-q b { font-size: calc(13 * var(--pt)); line-height: calc(17 * var(--pt)); font-weight: 600; color: var(--q); }
.ft-q span { color: color-mix(in srgb, var(--bubble-out-text) 72%, transparent); }
/* as the tile comes in: the bar opens, then the two reactions settle, once */
.reveal-ready .ft-tile--replies:not(.is-in) :is(.ft-rxbar, .ft-rx) { opacity: 0; }
.ft-tile--replies.is-in .ft-rxbar { transform-origin: 0 100%; animation: ft-bar 380ms var(--ease-spring) 450ms both; }
.ft-tile--replies.is-in .ft-rx { animation: ft-pop 520ms var(--ease-spring) 760ms both; }
.ft-tile--replies.is-in .ft-m--out .ft-rx { animation-delay: 900ms; }
@keyframes ft-bar { from { opacity: 0; transform: scale(0.6) translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes ft-pop { from { opacity: 0; transform: scale(0.4); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .reveal-ready .ft-tile--replies:not(.is-in) :is(.ft-rxbar, .ft-rx) { opacity: 1; }
  .ft-tile--replies.is-in :is(.ft-rxbar, .ft-rx) { animation: none; }
}

/* ---------------------------------------------------------------- Seven more tiles */
/* Under the bento, a second bento of seven tiles in the same family (the founder's notes of 9 Nov 2026: fewer lines in
   the panel, more pictures; "the boxes not equal, like the ones above"; then location sharing "in a big box, with
   design and pictures"). Each picture is a still piece of the final app as ship-1109 draws it (captures of the real
   app): Location sharing (a map drawn for the site, Maude's live pin, her Live Location card in Karim's chat and her
   phone's Location sheet under the action sheet of Share Live Location), Vault, the shared Todo List card, Waiting Messages, Chat Background's photos, App Icon (its three
   designs drawn here; the name under the icon stays Murmur) and the Profile Photo picker (eight of the app's own
   ready-made pictures, round; twelve where its stage is wide).
   - Layout, from 1024: the bento's own columns (1.12fr 1fr 1fr), so the page reads as one grid, and its mirror:
     Location sharing, the biggest, across the first two columns, with Vault (the chat as a phone's screen) as tall
     beside it on the right; then Todo lists, Scheduled messages and Backgrounds; then App icon, and Profile pictures
     wide on the right (my picture and its buttons beside the ready-made pictures). 600 to 1023: two columns, Location
     sharing across both, Todo lists and Scheduled messages, then Backgrounds and App icon on the left with Vault tall
     beside them, then Profile pictures wide. Below 600: one column, each tile as tall as its picture.
   - From 600 every tile takes its rows of the grid (subgrid: the title's, then the picture's), so titles and pictures
     line up across a row. Vault's window grows into the height the tiles beside it give (its flex basis is 0, so it
     never makes a row taller); Waiting Messages' screen grows to its neighbour's height, as a screen does.
   - The point grows with the tile (the drawings' own width in points, below), up to 0.9 px from 600, the top four's
     point, so both bentos draw at one scale (1 px below 600, where every picture fills its tile): a picture fills
     its tile and still fits a narrow one. Location sharing and Vault have their own point (see them). The grid is a
     container, so the first row can take the height Vault's window needs (see Location sharing). */
.ft-six { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-4); margin-top: var(--s-4); container-type: inline-size; }
@media (min-width: 600px) {
  .ft-six { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-5); margin-top: var(--s-5); }
  .ft-six > .ft-tile { display: grid; grid-template-rows: subgrid; grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .ft-six .ft-copy { grid-row: 1; } .ft-six .ft-stage { grid-row: 2; }
  .ft-tile--loc { grid-area: 1 / 1 / 3 / 3; }
  .ft-tile--todo { grid-area: 3 / 1 / 5 / 2; } .ft-tile--sched { grid-area: 3 / 2 / 5 / 3; }
  .ft-tile--bgs { grid-area: 5 / 1 / 7 / 2; } .ft-tile--icons { grid-area: 7 / 1 / 9 / 2; }
  .ft-tile--vault { grid-area: 5 / 2 / 9 / 3; } .ft-six .ft-tile--vault .ft-stage { grid-row: 2 / 5; }
  .ft-tile--pics { grid-area: 9 / 1 / 11 / 3; }
}
@media (min-width: 1024px) {
  .ft-six { grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr) minmax(0, 1fr); gap: var(--s-6); margin-top: var(--s-6); }
  .ft-tile--loc { grid-area: 1 / 1 / 3 / 3; } .ft-tile--vault { grid-area: 1 / 3 / 3 / 4; } .ft-six .ft-tile--vault .ft-stage { grid-row: 2; }
  .ft-tile--todo { grid-area: 3 / 1 / 5 / 2; } .ft-tile--sched { grid-area: 3 / 2 / 5 / 3; } .ft-tile--bgs { grid-area: 3 / 3 / 5 / 4; }
  .ft-tile--icons { grid-area: 5 / 1 / 7 / 2; } .ft-tile--pics { grid-area: 5 / 2 / 7 / 4; }
}
.ft-six .ft-stage { min-height: 0; container-type: inline-size; }
.ft-six .ft-stage > * { --pt: min(1px, calc(100cqw / 290)); }
@media (min-width: 600px) { .ft-six .ft-stage > * { --pt: min(0.9px, calc(100cqw / 290)); } }
.ft-tile { --ft-card: var(--surface); --ft-card-shadow: 0 1px 2px rgb(60 42 24 / 0.06), 0 0 0 0.5px rgb(60 42 24 / 0.07), 0 8px 24px -12px rgb(60 42 24 / 0.16); --ft-wax: linear-gradient(135deg, #D45A40 0%, #B4412C 55%, #8A2C1B 100%); }

/* Location sharing (the founder's note of 9 Nov 2026: "a big box, with design and pictures"): the final app's
   location sharing, as Karim sees Maude come to the market where they meet. The stage is a map drawn for the site
   (never real map tiles: invented streets, a park, a lake, a square and their names, in light and dark), with Maude's
   live pin, her photo with a soft pulse (no trail: the app keeps only the latest position, never a route); over it,
   Karim's chat with her Live Location card ("Updated just now", the time left and its ring; the card's map is the
   same drawing, smaller), and her phone (ADR-0023, section 2): the Location sheet of the chat's "+" (her map, Send My
   Current Location, "Accurate to 12 m", Share Live Location, "Updates as you move"), dimmed under the action sheet
   that Share Live Location opens, with its line for Karim and 15 Minutes, 1 Hour, 8 Hours or Until I Stop.
   - The map is drawn in stage points: (0, 0) is the stage's top left, the pin is at (165, 120), and the map runs to
     1200 by 1320 (its svg: 1240 by 1360 from (-40, -40); change its viewBox and its size here together), so a bigger
     stage shows more of the town and every stage is covered: on phones the stage is up to about 1160 points tall
     (1 px), and from 600 to 1023 px up to 975 px wide (0.9 px, about 1120 points). Its colours are the --map- tokens
     below.
   - Below 600 px: the map's top 190 pt, then the chat, then her phone. From 600: side by side at the bottom, the map
     above and between them (300 pt each; the point is the stage over 640, at most 0.9 px); her phone, about 670 pt
     tall in English and French, sets the drawing's height. It must stay under 700 pt, or from 1024 the row grows
     (and Vault's window with it). From 1024 the tile shares
     its row with Vault, and its stage sets the row's height: 700 points of the Chats window (the Chats tile's stage
     over 393, at most 0.9 px), computed from the grid's width (100cqw of .ft-six). Vault's window and this drawing
     use that point too, so the row and the Chats window above read at one zoom (the drawing is about 830 by 700 pt
     at every width from 1024).
   - Motion: the pulse runs once the tile is in; none with reduced motion (a still halo). */
.ft-tile--loc {
  --map-land: #F2EDE4; --map-lot: #E8E1D5; --map-plaza: #ECE2CF; --map-road: #FFFFFF; --map-casing: #DCD3C5;
  --map-ave: #FFF2D4; --map-ave-casing: #E6CC98; --map-park: #D2E4C0; --map-tree: #BDD7A7; --map-path: #F7F3EA;
  --map-water: #B7D5EC; --map-text: #6B675F; --map-park-text: #47763A; --map-water-text: #42739B; --map-poi: #D47A2A; --map-poi-text: #A85A17;
  --ft-dim: rgb(26 20 14 / 0.28); /* the app's --sheet-dim, under an action sheet */
}
@media screen {
  :root[data-theme="dark"] .ft-tile--loc {
    --map-land: #1B1D21; --map-lot: #23262B; --map-plaza: #29282A; --map-road: #33363C; --map-casing: #131416;
    --map-ave: #403B31; --map-ave-casing: #131416; --map-park: #1D2C21; --map-tree: #253929; --map-path: #31443A;
    --map-water: #172A3B; --map-text: #A19B92; --map-park-text: #8FBB8D; --map-water-text: #84A9CA; --map-poi: #D98A47; --map-poi-text: #E2A36D;
    --ft-dim: rgb(0 0 0 / 0.46);
  }
}
@media screen and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ft-tile--loc {
    --map-land: #1B1D21; --map-lot: #23262B; --map-plaza: #29282A; --map-road: #33363C; --map-casing: #131416;
    --map-ave: #403B31; --map-ave-casing: #131416; --map-park: #1D2C21; --map-tree: #253929; --map-path: #31443A;
    --map-water: #172A3B; --map-text: #A19B92; --map-park-text: #8FBB8D; --map-water-text: #84A9CA; --map-poi: #D98A47; --map-poi-text: #E2A36D;
    --ft-dim: rgb(0 0 0 / 0.46);
  }
}
.ft-six .ft-tile--loc .ft-stage { background: var(--map-land); }
.ft-loc__map { position: absolute; inset: 0; overflow: hidden; }
.ft-stage .ft-loc__svg { position: absolute; left: calc(-40 * var(--pt)); top: calc(-40 * var(--pt)); width: calc(1240 * var(--pt)); max-width: none; height: calc(1360 * var(--pt)); }
.ft-loc__labels text {
  font-family: var(--font-ui); font-size: 11.5px; font-weight: 600; letter-spacing: 0.02em; fill: var(--map-text);
  paint-order: stroke; stroke: var(--map-land); stroke-width: 3px; stroke-linejoin: round;
}
.ft-loc__labels .is-park { font-size: 12.5px; fill: var(--map-park-text); stroke: var(--map-park); }
.ft-loc__labels .is-small { font-size: 11px; }
.ft-loc__labels .is-water { font-size: 14.5px; font-weight: 500; font-style: italic; letter-spacing: 0.06em; fill: var(--map-water-text); stroke: var(--map-water); }
.ft-loc__labels .is-road { font-size: 10px; font-weight: 500; letter-spacing: 0.03em; stroke: var(--map-road); stroke-width: 2px; }
.ft-loc__labels .is-poi { font-size: 11.5px; fill: var(--map-poi-text); }
/* Maude's pin, as the app draws it (ADR-0023, section 4): her photo in a ring of her colour, with a point down to
   where she is and a small dot there. The pin's box is that spot; while she shares, two soft rings of her colour go
   out from her photo. The same pin, smaller (--sm), in her card and on her own Location sheet. */
.ft-loc__pin { --ph: 54; --pp: 10; --pd: 10; position: absolute; left: calc(165 * var(--pt)); top: calc(120 * var(--pt)); width: 0; height: 0; }
.ft-loc__pin > * { position: absolute; left: 0; top: 0; }
.ft-loc__head {
  display: grid; place-items: center; width: calc(var(--ph) * var(--pt)); height: calc(var(--ph) * var(--pt)); border-radius: 50%;
  background: var(--avc); transform: translate(-50%, calc(-100% - var(--pp) * var(--pt)));
  filter: drop-shadow(0 calc(3 * var(--pt)) calc(5 * var(--pt)) rgb(0 0 0 / 0.26));
}
.ft-loc__head::after {
  content: ""; position: absolute; left: 50%; top: calc(100% - 4 * var(--pt)); transform: translateX(-50%);
  border-style: solid; border-color: var(--avc) transparent transparent; border-width: calc((var(--pp) + 4) * var(--pt)) calc(var(--ph) * 0.14 * var(--pt)) 0;
}
.ft-loc__head > .ft-av { --avc: inherit; --av: 44; --avf: 16; box-shadow: 0 0 0 calc(2 * var(--pt)) #FFFFFF; }
.ft-loc__dot {
  width: calc(var(--pd) * var(--pt)); height: calc(var(--pd) * var(--pt)); border-radius: 50%; background: var(--avc); transform: translate(-50%, -50%);
  box-shadow: 0 0 0 calc(2 * var(--pt)) #FFFFFF, 0 calc(1 * var(--pt)) calc(4 * var(--pt)) rgb(0 0 0 / 0.3);
}
.ft-loc__pin > i {
  top: calc(-1 * (var(--pp) + var(--ph) / 2) * var(--pt)); width: calc(var(--ph) * var(--pt)); height: calc(var(--ph) * var(--pt)); border-radius: 50%;
  background: color-mix(in srgb, var(--avc) 28%, transparent); transform: translate(-50%, -50%) scale(1.6);
}
.ft-loc__pin > i + i { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .ft-tile--loc.is-in .ft-loc__pin > i { display: block; animation: ft-pulse 2.8s cubic-bezier(0.2, 0.6, 0.35, 1) infinite both; }
  .ft-tile--loc.is-in .ft-loc__pin > i + i { animation-delay: 1.4s; }
}
@keyframes ft-pulse { from { opacity: 0.9; transform: translate(-50%, -50%) scale(1); } to { opacity: 0; transform: translate(-50%, -50%) scale(2.5); } }
.ft-loc__pin--sm { --ph: 36; --pp: 7; --pd: 7; left: 50%; top: 64%; }
.ft-loc__pin--sm .ft-loc__head > .ft-av { --av: 28; --avf: 11; box-shadow: 0 0 0 calc(1.5 * var(--pt)) #FFFFFF; }
.ft-loc__pin--sm .ft-loc__dot { box-shadow: 0 0 0 calc(1.5 * var(--pt)) #FFFFFF, 0 calc(1 * var(--pt)) calc(3 * var(--pt)) rgb(0 0 0 / 0.3); }
/* the chat and Maude's phone: one under the other on phones, under the map's top; side by side at the bottom from 600,
   where her phone sets the drawing's height and the map shows above the chat and between them */
.ft-six .ft-tile--loc .ft-stage > * { --pt: min(1px, calc(100cqw / 300)); }
.ft-loc { position: relative; z-index: 1; display: flex; flex-direction: column; gap: calc(14 * var(--pt)); width: 100%; padding-top: calc(190 * var(--pt)); }
.ft-stage .ft-loc > * { width: 100%; }
@media (min-width: 600px) {
  .ft-six .ft-tile--loc .ft-stage > * { --pt: min(0.9px, calc(100cqw / 640)); }
  .ft-loc { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: calc(40 * var(--pt)); padding-top: calc(36 * var(--pt)); }
  .ft-stage .ft-loc > * { flex: none; width: calc(300 * var(--pt)); }
}
@media (min-width: 1024px) {
  .ft-six .ft-tile--loc .ft-stage { min-height: calc(700 * min(0.9px, ((100cqw - 2 * var(--s-6)) * 1.12 / 3.12 - 2 * var(--s-5)) / 393) + 2 * var(--s-6)); }
  /* the same point, from the stage's own width (two columns and a gap: one column is (100cqw + 40 - 24) / 2.12) */
  .ft-six .ft-tile--loc .ft-stage > * { --pt: min(0.9px, ((100cqw + 2 * var(--s-5) - var(--s-6)) * 1.12 / 2.12 - 2 * var(--s-5)) / 393); }
  .ft-loc { flex: 1 1 auto; padding-top: 0; }
}
.ft-mini.ft-loc__chat { box-shadow: 0 0 0 1px var(--card-edge), var(--shadow-3); }
.ft-loc__chat .ft-bar__who b { font-size: calc(16 * var(--pt)); }
/* her Live Location card: the map (the same drawing, smaller, her spot a little under the middle so her photo shows
   whole), then the card's three lines and the ring of time left */
.ft-b--live { width: calc(246 * var(--pt)); max-width: 100%; padding: calc(3 * var(--pt)); }
.ft-live__map { position: relative; display: block; height: calc(150 * var(--pt)); overflow: hidden; border-radius: calc(3 * var(--pt)) calc(15 * var(--pt)) calc(6 * var(--pt)) calc(6 * var(--pt)); background: var(--map-land); }
.ft-stage .ft-live__map svg { width: 100%; height: 100%; }
.ft-live { display: flex; align-items: center; gap: calc(10 * var(--pt)); padding: calc(7 * var(--pt)) calc(10 * var(--pt)) calc(6 * var(--pt)) calc(9 * var(--pt)); }
.ft-live__t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ft-live__t > * { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ft-live__t b { font-size: calc(15 * var(--pt)); line-height: calc(20 * var(--pt)); font-weight: 600; letter-spacing: -0.009em; }
.ft-live__t span { font-size: calc(13 * var(--pt)); line-height: calc(17 * var(--pt)); letter-spacing: -0.003em; color: var(--bubble-in-meta); }
.ft-live__t em { font-size: calc(13 * var(--pt)); line-height: calc(17 * var(--pt)); font-style: normal; font-weight: 600; letter-spacing: -0.003em; color: var(--bubble-in-link); font-variant-numeric: tabular-nums; }
.ft-stage .ft-live__ring { width: calc(30 * var(--pt)); height: calc(30 * var(--pt)); }
.ft-live__ring circle { fill: none; stroke: color-mix(in srgb, var(--bubble-in-link) 20%, transparent); stroke-width: 3; }
.ft-live__ring circle + circle { stroke: var(--bubble-in-link); stroke-linecap: round; }
/* Maude's phone (ADR-0023, section 2): the Location sheet of the chat's "+" (its grabber, Cancel and its title, a map
   centred on her with her pin, Send My Current Location and Share Live Location in the app's grouped list), dimmed
   under the action sheet that Share Live Location opens (app.css "Alerts and action sheets": 8 pt from the sides and
   the bottom, the title and message, the four durations, then Cancel on its own). Nothing is chosen: a tap on a
   duration starts sharing. Below 600 px the sheet's map is left out: the tile's map, with the same pin, is just above. */
.ft-loc__phone { position: relative; display: flex; flex-direction: column; overflow: hidden; border-radius: calc(22 * var(--pt)); background: var(--bg); box-shadow: 0 0 0 1px var(--card-edge), var(--shadow-3); }
.ft-loc__phone::after { content: ""; position: absolute; inset: 0; z-index: 1; background: var(--ft-dim); }
.ft-loc__sheet { padding-bottom: calc(12 * var(--pt)); }
.ft-loc__grab { display: block; width: calc(36 * var(--pt)); height: calc(5 * var(--pt)); margin: calc(6 * var(--pt)) auto 0; border-radius: calc(3 * var(--pt)); background: color-mix(in srgb, var(--text) 20%, transparent); }
.ft-loc__bar { position: relative; display: flex; align-items: center; justify-content: center; height: calc(42 * var(--pt)); padding: 0 calc(16 * var(--pt)); }
.ft-loc__bar > span { position: absolute; left: calc(18 * var(--pt)); top: 0; bottom: 0; display: flex; align-items: center; font-size: calc(16 * var(--pt)); letter-spacing: -0.011em; color: var(--link); }
.ft-loc__bar > b { font-size: calc(16 * var(--pt)); line-height: calc(20 * var(--pt)); font-weight: 600; letter-spacing: -0.011em; color: var(--text); }
.ft-loc__mine { position: relative; display: block; height: calc(110 * var(--pt)); overflow: hidden; background: var(--map-land); box-shadow: inset 0 0.5px 0 var(--ft-hair), inset 0 -0.5px 0 var(--ft-hair); }
.ft-stage .ft-loc__mine svg { width: 100%; height: 100%; }
.ft-loc__mine .ft-loc__pin--sm { top: 55%; }
@media (max-width: 599px) { .ft-loc__mine { display: none; } }
.ft-loc__sheet .ft-set__group { margin: calc(10 * var(--pt)) calc(10 * var(--pt)) 0; }
.ft-loc__row .ft-set__t > span:first-child { font-size: calc(15 * var(--pt)); line-height: calc(21 * var(--pt)); letter-spacing: -0.009em; }
.ft-loc__ic { display: grid; place-items: center; flex: none; width: calc(28 * var(--pt)); height: calc(28 * var(--pt)); margin-right: calc(10 * var(--pt)); border-radius: 50%; background: var(--brand); color: var(--on-brand); }
.ft-stage .ft-loc__ic svg { width: calc(17 * var(--pt)); height: calc(17 * var(--pt)); }
.ft-loc__row .ft-set__body { padding-block: calc(8 * var(--pt)); padding-right: calc(12 * var(--pt)); }
.ft-as { position: relative; z-index: 2; display: flex; flex-direction: column; gap: calc(8 * var(--pt)); margin: calc(8 * var(--pt)) calc(8 * var(--pt)) calc(8 * var(--pt)); }
.ft-as__group { display: flex; flex-direction: column; overflow: hidden; border-radius: calc(14 * var(--pt)); background: var(--ft-menu); }
.ft-as__head { padding: calc(14 * var(--pt)) calc(16 * var(--pt)); text-align: center; }
.ft-as__head > * { display: block; font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt)); letter-spacing: -0.003em; color: var(--text-2); }
.ft-as__head > b { font-weight: 600; }
.ft-as__head > span { margin-top: calc(2 * var(--pt)); }
.ft-as__item {
  display: block; height: calc(50 * var(--pt)); border-top: 0.5px solid var(--ft-menu-line);
  font-size: calc(19 * var(--pt)); line-height: calc(50 * var(--pt)); letter-spacing: -0.016em; text-align: center; color: var(--text); white-space: nowrap;
}
.ft-as__group > .ft-as__item:first-child { border-top: 0; }
.ft-as__item.is-cancel { font-weight: 600; }

/* Todo Lists (modules/todo/todo.css): the card centred in the chat, its tile (the app's checklist glyph: two checks and
   a ring beside three lines) and title, "2 of 6 done", the Options button (0.9.7 and 0.9.8: iOS's "more" button, a
   32 pt disc tinted like the tile with three dots in the accent, 16 pt from the right edge, lined up with the tile and
   centred like it on the title and its count; it is the only way into the card's menu), the progress line, the items
   (a ring, or the face of who checked it with the wax check badge, the text struck through), and the time alone at
   the foot, on the right (.td-foot): the final app has no Add Item row, a list changes through Options, then Edit List.
   The card has the colour of a received bubble (0.9.6, --bubble-in, light and dark), and keeps it once done (0.9.9).
   The tile and Options are tinted 13 % in light, 18 % in dark, as in the app.
   The card runs across its tile, up to 340 pt (the app's card spans the chat, 16 pt in from each side). */
.ft-todo { --ft-todo-bg: var(--bubble-in); --ft-todo-tint: 13%; width: 100%; max-width: calc(340 * var(--pt)); overflow: hidden; border-radius: calc(18 * var(--pt)); background: var(--ft-todo-bg); box-shadow: var(--ft-card-shadow); }
.ft-todo__head { display: grid; grid-template-columns: calc(32 * var(--pt)) minmax(0, 1fr) calc(32 * var(--pt)); column-gap: calc(12 * var(--pt)); align-items: center; padding: calc(14 * var(--pt)) calc(16 * var(--pt)) calc(12 * var(--pt)); }
.ft-todo__tile { display: grid; place-items: center; width: calc(32 * var(--pt)); height: calc(32 * var(--pt)); border-radius: calc(9 * var(--pt)); background: color-mix(in srgb, var(--brand) var(--ft-todo-tint), transparent); color: var(--brand); }
.ft-stage .ft-todo__tile svg { width: calc(20 * var(--pt)); height: calc(20 * var(--pt)); }
.ft-todo__opt { display: grid; place-items: center; width: calc(32 * var(--pt)); height: calc(32 * var(--pt)); border-radius: 50%; background: color-mix(in srgb, var(--brand) var(--ft-todo-tint), transparent); color: var(--brand); }
.ft-stage .ft-todo__opt svg { width: calc(17 * var(--pt)); height: calc(4 * var(--pt)); }
.ft-todo__t { min-width: 0; display: flex; flex-direction: column; }
.ft-todo__t b { font-size: calc(17 * var(--pt)); line-height: calc(22 * var(--pt)); font-weight: 600; letter-spacing: -0.013em; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ft-todo__t span { font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt)); letter-spacing: -0.003em; color: var(--text-2); font-variant-numeric: tabular-nums; }
.ft-todo__prog { height: calc(3 * var(--pt)); margin: 0 calc(16 * var(--pt)) calc(4 * var(--pt)); border-radius: calc(1.5 * var(--pt)); background: color-mix(in srgb, var(--text) 9%, transparent); overflow: hidden; }
.ft-todo__prog i { display: block; width: 33.3%; height: 100%; border-radius: inherit; background: var(--brand); }
.ft-todo__item { position: relative; display: grid; grid-template-columns: calc(32 * var(--pt)) minmax(0, 1fr); column-gap: calc(12 * var(--pt)); align-items: center; padding: 0 calc(16 * var(--pt)); }
.ft-todo__item { min-height: calc(42 * var(--pt)); }
.ft-todo__item + .ft-todo__item::before { content: ""; position: absolute; left: calc(60 * var(--pt)); right: calc(16 * var(--pt)); top: 0; border-top: 0.5px solid color-mix(in srgb, var(--text) 11%, transparent); }
.ft-todo__box { position: relative; width: calc(24 * var(--pt)); height: calc(24 * var(--pt)); margin: 0 auto; }
.ft-todo__box::before { content: ""; position: absolute; inset: calc(1 * var(--pt)); border-radius: 50%; box-shadow: inset 0 0 0 calc(1.5 * var(--pt)) color-mix(in srgb, var(--text) 30%, transparent); }
.ft-todo__item.is-checked .ft-todo__box::before { display: none; }
.ft-av--todo { --av: 24; --avf: 9; position: absolute; inset: 0; letter-spacing: 0; }
.ft-todo__badge { position: absolute; right: calc(-5 * var(--pt)); bottom: calc(-4 * var(--pt)); display: grid; place-items: center; width: calc(12 * var(--pt)); height: calc(12 * var(--pt)); border-radius: 50%; background: var(--brand); color: var(--on-brand); box-shadow: 0 0 0 calc(1.5 * var(--pt)) var(--ft-todo-bg); }
.ft-stage .ft-todo__badge svg { width: calc(9 * var(--pt)); height: calc(9 * var(--pt)); }
.ft-todo__text { min-width: 0; font-size: calc(16 * var(--pt)); line-height: calc(21 * var(--pt)); letter-spacing: -0.011em; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ft-todo__item.is-checked .ft-todo__text { color: var(--text-3); text-decoration: line-through; text-decoration-thickness: calc(1.5 * var(--pt)); }
.ft-todo__foot { display: flex; justify-content: flex-end; align-items: center; min-height: calc(24 * var(--pt)); padding: calc(2 * var(--pt)) calc(16 * var(--pt)) calc(9 * var(--pt)); }
.ft-todo__time { font-size: calc(11 * var(--pt)); line-height: calc(13 * var(--pt)); color: var(--text-3); opacity: 0.75; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Vault (Vault.tsx, app.css): the chat as a phone's screen, drawn as the group's window in Chats and groups: its bar
   (the navy disc with the vault, "Only you", the green lock), the things I kept, oldest at the top (where I parked,
   the lake photo, the cabin's booking, its Wi-Fi, the view from the trail with its caption, the trail map), and the
   composer. No checks: nobody else reads Vault. Every note fits one line at the narrowest screen (250 pt),
   and file names never need their "...". Below 600 px the screen is 330 pt wide, its point shrinking with a narrower
   tile, and the window is as tall as its last three things (.ft-early and the composer hidden). From 600, where
   the tile runs down two rows (600 to 1023) or shares Location sharing's row (from 1024), it grows into the height
   the tiles beside it give: the bar floats, frosted, over the things, which sit at the bottom above the composer and
   go up under the bar, clipped by the window. */
.ft-six .ft-tile--vault .ft-win { --pt: min(1px, calc(100cqw / 330)); max-width: calc(330 * var(--pt)); }
.ft-tile--vault .ft-win > * { --pt: calc(100cqw / 330); }
.ft-tile--vault :is(.ft-early, .ft-compose) { display: none; }
.ft-bar--mini { padding-right: calc(48 * var(--pt)); }
.ft-av--vault { --avc: #3A4766; }
.ft-stage .ft-av--vault svg { width: calc(20 * var(--pt)); height: calc(20 * var(--pt)); color: #FFFFFF; }
.ft-bar__lock.is-green { color: var(--verified); }
/* my photo with its caption: the photo keeps its 6 pt corners above the caption, the small corner is the bubble's */
.ft-m--out .ft-b--media.ft-b--cap .ft-media { border-bottom-right-radius: calc(6 * var(--pt)); }
@media (min-width: 600px) {
  .ft-tile--vault .ft-win { position: relative; flex: 1 1 0; display: flex; flex-direction: column; }
  .ft-tile--vault .ft-head {
    position: absolute; z-index: 2; top: 0; left: 0; right: 0;
    border-top-left-radius: inherit; border-top-right-radius: inherit;
    background: var(--ft-bar); border-bottom: 0.5px solid var(--ft-hair);
    -webkit-backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt))); backdrop-filter: saturate(1.8) blur(calc(20 * var(--pt)));
  }
  .ft-tile--vault .ft-head > .ft-bar { background: none; border-bottom: 0; }
  .ft-tile--vault :is(.ft-early, .ft-compose) { display: flex; }
  .ft-tile--vault .ft-thread { flex: 1 1 0; min-height: 0; overflow: hidden; justify-content: flex-end; padding-bottom: calc(18 * var(--pt)); }
  /* The window is always 700 of its points tall: the stage is a size container (its rows come from the tiles beside
     it), and the point is the stage's height over 700 (at most 1 px), so the screen's width changes instead, from
     250 pt to 393 (the mockups' iPhone; a wider tile leaves room on the sides). The bar's edge then always falls at
     the same place in the things I kept, across the lake photo, about 35 to 80 px below its top from 600 to 1920 px
     wide, so it never cuts a line of text and the window is never empty at the top. From 1024 the row's height is
     set by Location sharing so that this point is the Chats window's (at most 0.9 px): the two phones read at one
     zoom, and the window keeps 345 of its points or more in width. If you change a thing in the window, check that
     again from 600 to 1920 px. */
  .ft-six .ft-tile--vault .ft-stage { container-type: size; }
  .ft-six .ft-tile--vault .ft-win { --pt: min(1px, 100cqh / 700); max-width: calc(393 * var(--pt)); }
  .ft-tile--vault .ft-win > * { --pt: min(1px, 100cqh / 700, 100cqw / 250); }
  .ft-tile--vault .ft-b--media { max-width: 100%; }
  .ft-tile--vault .ft-b--file { min-width: 0; width: calc(236 * var(--pt)); }
}

/* Waiting Messages (chat/WaitingMessages.tsx, waiting.css): "Scheduled", my birthday message for tomorrow with its
   clock and time where checks would be, and its own wax send arrow; then "Saved for Later" and a message kept for later.
   The screen grows to the height of the tile beside it, its list at the top, as a screen does. */
.ft-mini { width: calc(280 * var(--pt)); max-width: 100%; overflow: hidden; border-radius: calc(22 * var(--pt)); background: var(--bg); box-shadow: 0 0 0 1px var(--card-edge), var(--shadow-2); }
.ft-tile--sched .ft-mini { flex: 1 0 auto; width: calc(320 * var(--pt)); }
.ft-wait { display: flex; flex-direction: column; padding: calc(2 * var(--pt)) calc(14 * var(--pt)) calc(4 * var(--pt)); }
/* The bar: flat, on the screen's own paper, with "‹ Back" and the title centred on the screen; when "‹ Retour" leaves
   too little room, the title moves right instead of touching it, as iOS does (the first column keeps the back button's
   width, the last one gives up its share). */
.ft-bar--title { display: grid; grid-template-columns: minmax(max-content, 1fr) auto minmax(0, 1fr); column-gap: calc(8 * var(--pt)); padding: 0 calc(16 * var(--pt)); height: calc(52 * var(--pt)); background: none; border-bottom: 0; }
.ft-bar--title > b { font-size: calc(16 * var(--pt)); line-height: calc(20 * var(--pt)); font-weight: 600; letter-spacing: -0.011em; color: var(--text); white-space: nowrap; }
.ft-bar__backlbl { justify-self: start; display: flex; align-items: center; gap: calc(5 * var(--pt)); font-size: calc(16 * var(--pt)); line-height: calc(20 * var(--pt)); color: var(--link); white-space: nowrap; }
.ft-bar__backlbl .ft-bar__back { margin-right: 0; width: calc(11 * var(--pt)); height: calc(18 * var(--pt)); }
.ft-wait .ft-sysrow { margin: calc(6 * var(--pt)) 0 calc(2 * var(--pt)); }
.ft-pill { display: inline-block; padding: calc(3 * var(--pt)) calc(10 * var(--pt)); border-radius: calc(10 * var(--pt)); background: var(--system-bg); color: var(--system-text); font-size: calc(12 * var(--pt)); line-height: calc(16 * var(--pt)); font-weight: 600; white-space: nowrap; }
.ft-wait__row { display: flex; align-items: flex-end; justify-content: flex-end; gap: calc(6 * var(--pt)); margin: calc(8 * var(--pt)) 0 calc(10 * var(--pt)); }
.ft-b--wait { max-width: calc(224 * var(--pt)); background: var(--bubble-out); color: var(--bubble-out-text); border-radius: calc(18 * var(--pt)) calc(18 * var(--pt)) calc(7.8 * var(--pt)) calc(18 * var(--pt)); } /* the app's small corner, as every bubble since 0.9.19 */
.ft-b--wait .ft-t:not(:last-child) { padding-bottom: calc(1 * var(--pt)); }
.ft-wait__when { display: flex; align-items: center; justify-content: flex-end; gap: calc(3 * var(--pt)); padding: 0 calc(12 * var(--pt)) calc(7 * var(--pt)); font-size: calc(11 * var(--pt)); line-height: calc(13 * var(--pt)); color: color-mix(in srgb, var(--bubble-out-meta) 68%, transparent); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ft-stage .ft-wait__when svg { width: calc(11 * var(--pt)); height: calc(11 * var(--pt)); }
.ft-wait__send { display: grid; place-items: center; flex: none; width: calc(30 * var(--pt)); height: calc(30 * var(--pt)); border-radius: 50%; background: var(--ft-wax); color: var(--on-brand); box-shadow: inset 0 -1px 0 rgb(0 0 0 / 0.12), inset 0 1px 0 rgb(255 255 255 / 0.18); }
.ft-stage .ft-wait__send svg { width: calc(17 * var(--pt)); height: calc(17 * var(--pt)); }

/* Backgrounds: Chat Background (look/Screen.tsx): the four sections, Photos chosen, and six of its photos, each with
   the two bars of its thumbnail and its name under it, three by two, 320 pt wide like the screen and App Icon, so
   the pictures' left edges line up down a column */
.ft-bgs { width: calc(320 * var(--pt)); max-width: 100%; }
.ft-seg { display: flex; padding: calc(2 * var(--pt)); margin-bottom: calc(12 * var(--pt)); border-radius: calc(9 * var(--pt)); background: var(--container); }
.ft-seg > span { flex: 1 1 auto; min-width: 0; padding-inline: calc(5 * var(--pt)); border-radius: calc(7 * var(--pt)); font-size: calc(12 * var(--pt)); line-height: calc(26 * var(--pt)); font-weight: 500; letter-spacing: -0.003em; text-align: center; color: var(--text); white-space: nowrap; }
.ft-seg > .is-on { background: var(--surface); font-weight: 600; box-shadow: 0 calc(1 * var(--pt)) calc(3 * var(--pt)) rgb(0 0 0 / 0.12), 0 0 0 0.5px rgb(0 0 0 / 0.04); }
.ft-bgs__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: calc(10 * var(--pt)) calc(9 * var(--pt)); }
.ft-bgs__cell { display: flex; flex-direction: column; align-items: center; gap: calc(5 * var(--pt)); min-width: 0; }
.ft-bgs__pic {
  --c1: var(--g1); --c2: var(--g2); --c3: var(--g3); --in: rgb(255 255 255 / 0.92); --out: rgb(255 255 255 / 0.55);
  position: relative; width: 100%; aspect-ratio: 0.74; overflow: hidden; border-radius: calc(10 * var(--pt));
  background: linear-gradient(var(--ga), var(--c1) 0%, var(--c2) 52%, var(--c3) 100%); box-shadow: 0 0 0 0.5px rgb(0 0 0 / 0.06);
}
.ft-bgs__pic > i { position: absolute; height: calc(8 * var(--pt)); border-radius: calc(4 * var(--pt)); }
.ft-bgs__pic > i:first-of-type { left: 8%; bottom: 34%; width: 52%; background: var(--in); }
.ft-bgs__pic > i:last-of-type { right: 8%; bottom: 18%; width: 46%; background: var(--out); }
/* The Photos tab: the app's own photos (beta/public/assets/bg/v1/thumb, light and .dark), one shown per theme, framed
   like look.css (object-position 50% 18%). Each photo's two bars take the bubble colours it brings, as the app's
   Thumb.tsx draws them with Matching Colors on (look/catalog.generated.ts PALETTES.walls, light then dark). */
.ft-bgs__pic--ph { --in: var(--in-l); --out: var(--out-l); background: var(--container); }
.ft-bgs__pic--maple { --in-l: #FBF5EE; --out-l: #F6D7B8; --in-d: #2B211B; --out-d: #7A3818; }
.ft-bgs__pic--harbour { --in-l: #F6F8FA; --out-l: #F6DFB4; --in-d: #1E2C3D; --out-d: #5A3D1A; }
.ft-bgs__pic--aurora { --in-l: #F4FAF8; --out-l: #C2EBD4; --in-d: #2B3A46; --out-d: #0E5550; }
.ft-bgs__pic--pink-blossom { --in-l: #F9FBFD; --out-l: #F8D8E2; --in-d: #1E272D; --out-d: #7A3552; }
.ft-bgs__pic--alpine { --in-l: #F8FAF3; --out-l: #C5E8E0; --in-d: #1B241B; --out-d: #125654; }
.ft-bgs__pic--sunset-beach { --in-l: #FDF8EE; --out-l: #F8DDAE; --in-d: #201C18; --out-d: #5E2A12; }
.ft-bgs__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 18%; }
.ft-bgs__img--d { display: none; }
.ft-bgs__name { max-width: 100%; font-size: calc(11 * var(--pt)); line-height: calc(14 * var(--pt)); letter-spacing: 0.005em; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Profile pictures: the Profile Photo sheet (settings, avatar picker): my letters on my colour, Take Photo, Choose Photo
   and Text (.ft-pick__me), then "Choose a Profile Picture" and eight of the twenty ready-made pictures on their pastel
   discs (.ft-pick__all). One under the other below 600 px, 320 pt wide like the pictures above it; side by side in
   the wide tile from 600 (560 pt), and twelve pictures where its stage is wide (see below). */
.ft-pick { width: calc(320 * var(--pt)); max-width: 100%; display: flex; flex-direction: column; align-items: center; }
.ft-pick__me, .ft-pick__all { display: contents; }
@media (min-width: 600px) {
  .ft-six .ft-tile--pics .ft-stage > * { --pt: min(0.9px, calc(100cqw / 570)); }
  .ft-tile--pics .ft-pick { width: calc(560 * var(--pt)); flex-direction: row; gap: calc(28 * var(--pt)); }
  .ft-pick__me { display: flex; flex: none; flex-direction: column; align-items: center; }
  .ft-pick__all { display: block; flex: 1; min-width: 0; }
  .ft-pick__all .ft-pick__h { margin-top: 0; }
}
.ft-av--big { --av: 76; --avf: 29; }
.ft-pick__btns { display: flex; justify-content: center; gap: calc(14 * var(--pt)); margin-top: calc(14 * var(--pt)); }
.ft-pick__btn { display: flex; flex-direction: column; align-items: center; gap: calc(6 * var(--pt)); width: calc(80 * var(--pt)); font-size: calc(12 * var(--pt)); line-height: calc(15 * var(--pt)); letter-spacing: -0.003em; color: var(--text); text-align: center; }
.ft-pick__btn > span { display: grid; place-items: center; width: calc(48 * var(--pt)); height: calc(48 * var(--pt)); border-radius: 50%; background: var(--ft-card); color: var(--brand); box-shadow: var(--ft-grouped), 0 0 0 0.5px rgb(60 42 24 / 0.08); }
.ft-stage .ft-pick__btn svg { width: calc(22 * var(--pt)); height: calc(22 * var(--pt)); }
.ft-pick__btn b { font-size: calc(18 * var(--pt)); line-height: 1; font-weight: 400; letter-spacing: 0; }
.ft-pick__h { align-self: stretch; margin-top: calc(14 * var(--pt)); padding: 0 calc(4 * var(--pt)) calc(8 * var(--pt)); }
.ft-pick__grid { align-self: stretch; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: calc(10 * var(--pt)); padding: calc(12 * var(--pt)); border-radius: calc(12 * var(--pt)); background: var(--ft-card); box-shadow: var(--ft-grouped); }
.ft-pick__grid > span { display: block; aspect-ratio: 1; border-radius: 50%; overflow: hidden; }
/* The app's own ready-made pictures (beta/public/assets/avatars/v1/thumb, 192 px), made for Murmur: shown round, as in the picker. */
.ft-pick__grid img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Where the stage is wide (640 px or more inside it: from about 730 px in two columns, and from about 1150 px beside
   App icon), twelve pictures, two rows of six at the same size (52.5 pt), a little more room around Karim's buttons,
   705 pt in all: the drawing then fills about 83% of its stage from 1280 px (65 to 93% in two columns, against 52 to
   75% with eight), and the row keeps its height. Both show the picker's first pictures in its own order
   (settings/avatar-catalog.generated.ts PRESETS): the Sealed Letter first, then Tulip, Whale, Cat, Cherry Branch,
   Sun, Mushroom, Swan, and from 640 px Hummingbird, Moon, Strawberry and Mountain. */
.ft-pick__grid > span:nth-child(n + 9) { display: none; }
@container (min-width: 640px) {
  .ft-six .ft-tile--pics .ft-stage > * { --pt: min(0.9px, calc(100cqw / 715)); }
  .ft-tile--pics .ft-pick { width: calc(705 * var(--pt)); gap: calc(40 * var(--pt)); }
  .ft-tile--pics .ft-pick__btns { gap: calc(18 * var(--pt)); }
  .ft-pick__grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .ft-pick__grid > span:nth-child(n + 9) { display: block; }
}

/* App icon (look/AppIcon.tsx, look.css "App Icon"): the top of the screen, its Murmur and Weather sections, each a
   grouped card of three, Automatic, Light and Dark, in the app's own pictures (beta/public/assets/app-icons/v1, the
   iOS outline, 180 px, in assets/img/app-icons). Automatic shows the dark picture on its lower right half. Murmur's
   Automatic is the one in use, with the look cards' ring 2 pt outside it and the wax check. The pictures are the
   same in light and dark, as in the app; only the cards and words follow the theme. Timer and the footer are lower
   on the screen, out of the drawing. Below 1024 px and in one column the point is the tile's; from 1024 it is 0.8 px,
   so the row beside Profile pictures stays calm. */
.ft-icons { width: calc(361 * var(--pt)); max-width: 100%; }
.ft-icons > .ft-set__h { padding-left: calc(16 * var(--pt)); }
.ft-icons__group + .ft-set__h { margin-top: calc(24 * var(--pt)); }
.ft-icons__group { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); justify-items: center; padding: calc(18 * var(--pt)) 0 calc(14 * var(--pt)); border-radius: calc(12 * var(--pt)); background: var(--ft-card); box-shadow: var(--ft-grouped); }
.ft-icons__tile { display: flex; flex-direction: column; align-items: center; gap: calc(7 * var(--pt)); }
.ft-icons__frame { position: relative; display: block; width: calc(64 * var(--pt)); height: calc(64 * var(--pt)); border-radius: 22.37%; }
.ft-ico { position: relative; display: block; width: 100%; height: 100%; overflow: hidden; border-radius: 22.37%; box-shadow: 0 0 0 0.5px rgb(31 35 41 / 0.12); }
.ft-ico > img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.ft-ico > img.is-dark-half { clip-path: polygon(100% 0, 100% 100%, 0 100%); }
.ft-icons__tile.is-on .ft-icons__frame::after { content: ""; position: absolute; inset: calc(-4 * var(--pt)); border-radius: 27%; box-shadow: 0 0 0 calc(2 * var(--pt)) var(--brand); }
.ft-icons__check { position: absolute; z-index: 1; top: calc(-6 * var(--pt)); right: calc(-6 * var(--pt)); display: grid; place-items: center; width: calc(22 * var(--pt)); height: calc(22 * var(--pt)); border-radius: 50%; background: var(--brand); color: var(--on-brand); box-shadow: 0 calc(1 * var(--pt)) calc(3 * var(--pt)) rgb(0 0 0 / 0.22); }
.ft-stage .ft-icons__check svg { width: calc(13 * var(--pt)); height: calc(13 * var(--pt)); }
.ft-icons__name { font-size: calc(13 * var(--pt)); line-height: calc(18 * var(--pt)); letter-spacing: -0.003em; color: var(--text-2); white-space: nowrap; }
.ft-icons__tile.is-on .ft-icons__name { font-weight: 600; color: var(--text); }
@media (min-width: 1024px) { .ft-six .ft-tile--icons .ft-stage > * { --pt: min(0.8px, calc(100cqw / 380)); } }
@media screen {
  :root[data-theme="dark"] .ft-tile { --ft-card: var(--container); --ft-card-shadow: 0 0 0 0.5px rgb(242 238 232 / 0.07), 0 8px 24px -12px rgb(0 0 0 / 0.5); --ft-wax: linear-gradient(135deg, #F4A088 0%, #F08B6E 50%, #C9583E 100%); }
  :root[data-theme="dark"] .ft-bgs__pic { --c1: var(--d1); --c2: var(--d2); --c3: var(--d3); --in: rgb(52 55 62 / 0.92); --out: rgb(255 255 255 / 0.22); }
  :root[data-theme="dark"] .ft-bgs__pic--ph { --in: var(--in-d); --out: var(--out-d); }
  :root[data-theme="dark"] .ft-bgs__img--l { display: none; } :root[data-theme="dark"] .ft-bgs__img--d { display: block; }
  :root[data-theme="dark"] .ft-seg > .is-on { background: var(--container-2); }
  :root[data-theme="dark"] .ft-todo { --ft-todo-tint: 18%; }
  :root[data-theme="dark"] .ft-ico { box-shadow: 0 0 0 0.5px rgb(242 238 232 / 0.18); }
}
@media screen and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ft-tile { --ft-card: var(--container); --ft-card-shadow: 0 0 0 0.5px rgb(242 238 232 / 0.07), 0 8px 24px -12px rgb(0 0 0 / 0.5); --ft-wax: linear-gradient(135deg, #F4A088 0%, #F08B6E 50%, #C9583E 100%); }
  :root:not([data-theme="light"]) .ft-bgs__pic { --c1: var(--d1); --c2: var(--d2); --c3: var(--d3); --in: rgb(52 55 62 / 0.92); --out: rgb(255 255 255 / 0.22); }
  :root:not([data-theme="light"]) .ft-bgs__pic--ph { --in: var(--in-d); --out: var(--out-d); }
  :root:not([data-theme="light"]) .ft-bgs__img--l { display: none; } :root:not([data-theme="light"]) .ft-bgs__img--d { display: block; }
  :root:not([data-theme="light"]) .ft-seg > .is-on { background: var(--container-2); }
  :root:not([data-theme="light"]) .ft-todo { --ft-todo-tint: 18%; }
  :root:not([data-theme="light"]) .ft-ico { box-shadow: 0 0 0 0.5px rgb(242 238 232 / 0.18); }
}

/* ----------------------------------------------------------------- More features: one panel, twelve small features */
/* One surface like the tiles, with no title of its own (the section's title covers it), and the twelve features in a
   list across its whole width: an icon, a name and one line each, divided by hairlines. Columns: one below 600 px,
   two from 600, three from 1024. The panel's padding plus an item's padding is the same on top and at the bottom. */
.ft-more {
  margin-top: var(--s-4); padding: var(--s-2) var(--s-6);
  border-radius: var(--r-sheet); background: var(--surface); box-shadow: 0 0 0 1px var(--card-edge), var(--shadow-1);
}
@media (min-width: 600px) { .ft-more { margin-top: var(--s-5); padding: var(--s-3) var(--s-7); } }
@media (min-width: 1024px) { .ft-more { margin-top: var(--s-6); padding: var(--s-3) var(--s-8); } }
.ft-more__list { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 600px) { .ft-more__list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--s-8); } }
@media (min-width: 1024px) { .ft-more__list { grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--s-12); } }
/* Below 1280 px the three columns are narrow: a smaller gap keeps each line on two lines at most, so the rows stay even. */
@media (min-width: 1024px) and (max-width: 1279px) { .ft-more__list { column-gap: var(--s-8); } }
.ft-more__item { display: flex; align-items: flex-start; gap: var(--s-3); padding: var(--s-4) 0; border-top: 1px solid var(--divider); }
.ft-more__item:first-child { border-top: 0; }
@media (min-width: 600px) { .ft-more__item:nth-child(2) { border-top: 0; } }
@media (min-width: 1024px) {
  .ft-more__item { padding: var(--s-5) 0; }
  .ft-more__item:nth-child(3) { border-top: 0; }
}
.ft-more__ic { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: 10px; background: var(--accent-container); color: var(--seal); }
.ft-more__ic .i { width: 20px; height: 20px; }
.ft-more__t { display: flex; flex-direction: column; min-width: 0; padding-top: 1px; }
.ft-more__name { font-family: var(--font-ui); font-size: 16px; line-height: 22px; font-weight: 600; letter-spacing: -0.005em; white-space: nowrap; }
.ft-more__text { margin-top: 2px; font-size: 14.5px; line-height: 21px; color: var(--text-2); }
@media print { .ft-stage { -webkit-print-color-adjust: exact; print-color-adjust: exact; } }


/* ------------------------------------------------------------------------------------------------- H-4 questions */
.faq__list { border-top: 1px solid var(--divider); }
.faq .qa__q { font-size: 18px; line-height: 26px; }
@media (min-width: 768px) { .faq .qa__q { font-size: 20px; line-height: 28px; } }
.faq .qa__a .link--arrow { font-size: 15px; }
.faq__more { margin-top: var(--s-8); text-align: center; color: var(--text-2); }
.faq__more .link--arrow { margin-left: 4px; }


/* ------------------------------------------------------------------------------------------------- H-5 closing */
.closing { overflow: hidden; background: radial-gradient(640px 420px at 50% 100%, color-mix(in srgb, var(--seal) 9%, transparent), transparent 70%); }
/* The questions and the closing share the paper background, so their two paddings read as one gap: from 768, a
   shorter top here (the seal's own 32 px of air sits above the mark) */
@media (min-width: 768px) { .faq + .closing { padding-top: var(--s-12); } }
.closing__inner { display: flex; flex-direction: column; align-items: center; text-align: center; }
.closing__seal { position: relative; display: grid; place-items: center; width: 160px; height: 160px; margin-bottom: var(--s-4); }
.closing__halo { position: absolute; inset: 0; border-radius: 50%; background: radial-gradient(closest-side, color-mix(in srgb, var(--seal) 18%, transparent), transparent); }
.closing__seal .mark { position: relative; filter: drop-shadow(0 10px 18px rgb(94 29 16 / 0.28)); }
.closing__seal::after { content: ""; position: absolute; left: 50%; top: 50%; width: 104px; height: 104px; margin: -52px 0 0 -52px; border-radius: 50%; border: 2px solid color-mix(in srgb, var(--seal) 40%, transparent); opacity: 0; }
.reveal-ready .closing__seal[data-stamp]:not(.is-in) { opacity: 1; transform: none; }
.reveal-ready .closing__seal[data-stamp]:not(.is-in) .mark { opacity: 0; transform: translateY(-14px) scale(1.25); }
.closing__seal.is-in .mark { animation: mm-stamp 620ms var(--ease) both; }
.closing__seal.is-in::after { animation: mm-ring 900ms 260ms var(--ease-out) both; }
@keyframes mm-stamp { 0% { opacity: 0; transform: translateY(-14px) scale(1.25); } 55% { opacity: 1; transform: translateY(0) scale(0.94); } 78% { transform: scale(1.02); } 100% { opacity: 1; transform: none; } }
@keyframes mm-ring { 0% { opacity: 0.9; transform: scale(0.9); } 100% { opacity: 0; transform: scale(1.6); } }
.closing__body { margin-top: var(--s-5); }
.closing__ctas { margin-top: var(--s-8); } /* the App Store and Google Play badges (site.css, "Store badges") */
.closing__more { margin-top: var(--s-6); }
.closing__more .link--arrow { font-size: 15px; }
/* French only (index-fr.html): Apple's French badge, « Télécharger dans l’App Store », is 8 px wider than the English
   one; under 375 px both badges step down to 46 px so they still share a row at 360, as in English (with the same
   16 px between them). */
@media (max-width: 374px) { :root[lang^="fr"] .closing .store-badge { --sb-h: 46px; } }
/* French only: the questions' title and the line under them stay on one line on phones, as the English ones do. */
@media (max-width: 374px) { :root[lang^="fr"] #faq h2 { font-size: 30px; line-height: 36px; } }
@media (max-width: 419px) { :root[lang^="fr"] .faq__more { font-size: min(16px, 3.9vw); } }


/* ------------------------------------------------------------------------------------------------- Motion and print */
@media (prefers-reduced-motion: reduce) {
  /* the phone: a short fade only (its demo does not run: the still, home-anim.css) */
  .hero-phone { animation-name: hp-fade; animation-duration: 150ms !important; animation-timing-function: linear; }
  .reveal-ready .closing__seal[data-stamp]:not(.is-in) .mark { transform: none; }
  .closing__seal.is-in .mark { animation-name: hp-fade; animation-duration: 150ms !important; }
  .closing__seal.is-in::after { animation: none; }
}
/* Print: the phone still (its demo's still, home-anim.css), in the light tokens; its frame, bubbles and bars keep
   their fills even when the browser leaves out background graphics, as Chrome does by default. The frosted bars
   (header, pinned message) print opaque: a printer gets no backdrop blur, and the messages under them would show. */
@media print {
  .hero-phone { animation: none; }
  .hero-phone .hp__screen { --app-bar: var(--bg); }
  .hero-phone .hp { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
