/* Spectral, self-hosted (Google Fonts v15 files, latin and latin-ext subsets, SIL OFL: fonts/OFL-Spectral.txt).
   The page uses 300 (answers), 400 (small lines) and 500 (the logotype). Production, 2026-11-05. */
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 300; font-display: swap;
  src: url("/fonts/Spectral-Light-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 300; font-display: swap;
  src: url("/fonts/Spectral-Light-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("/fonts/Spectral-Regular-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 400; font-display: swap;
  src: url("/fonts/Spectral-Regular-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("/fonts/Spectral-Medium-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Spectral"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("/fonts/Spectral-Medium-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
/* Luciole (Laurent Bourcellier and Jonathan Perez, CC BY 4.0: fonts/LICENCE-Luciole.txt). */
@font-face {
  font-family: "Luciole";
  src: url("/fonts/Luciole-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
:root {
  /* Mockup 34:68 values. */
  --ink: #1c1c1a;
  --faint: #99968f;
  /* Untitled text grays, for the conversation. */
  --text: #29313a;
  --text-3: #69727b;
  /* dmcg.co curve. */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --move: .9s;
  --chat-h: 52px; /* set by script from the composer's real height */
  --chat-bottom: calc(38vh - 200px); /* the composer's bottom edge at rest, desktop */
  --ar: 0.7742; /* box height / width: the clip window's, set again by applyWindow() */
  --bh: calc(62vh + 68px); /* figure box height on desktop */
}
/* Run 26: on PC the clip window's aspect from the start (applyWindow's value, 1.0 * 768 / (0.62 * 1344)), so the
   figure box never changes size when the module arrives. Was set by an inline script; production (2026-11-05)
   has no inline script (content security policy). */
@media (min-width: 761px) { :root { --ar: 0.9217; } }
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overscroll-behavior: none; }
body {
  background: #fff;
  color: var(--ink);
  font-family: "Luciole", "Spectral", serif;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
#mist { position: fixed; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }

/* Silhouette, the hero: box from 104 px (under the top band), 62vh tall
   (about 994 x 558 at 1440 x 900). Its dissolving bottom ends 44 px above the
   chat box. In a conversation it rises and shrinks to make room.
   WebGL draws it; this box only holds its place, the shader follows it. */
.silhouette {
  position: fixed; left: 50%; top: 96px;
  width: calc(var(--bh) / var(--ar)); transform: translateX(-50%);
  pointer-events: none;
  transition: top var(--move) var(--ease), width var(--move) var(--ease);
}
.silhouette img {
  width: 100%; height: auto; display: block; aspect-ratio: 1 / var(--ar); object-fit: cover; object-position: 53% 0;
  -webkit-mask-image: linear-gradient(to bottom, #000 62%, transparent 100%), linear-gradient(to right, transparent 8%, #000 26%, #000 80%, transparent 94%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to bottom, #000 62%, transparent 100%), linear-gradient(to right, transparent 8%, #000 26%, #000 80%, transparent 94%);
  mask-composite: intersect;
  mix-blend-mode: multiply; filter: brightness(1.12) contrast(1.08);
}
.gl .silhouette img { visibility: hidden; }

/* Edge dissolve, after dmcg.co: a fixed 112 px band at top and bottom.
   Three backdrop blurs (1.5, 5, 14 px), each masked by a gradient shifted
   25 percent, so blur grows toward the edge; a white veil on top.
   The bottom band is the top band flipped. Chrome sits above the bands. */
.edge { position: fixed; left: 0; right: 0; height: 112px; pointer-events: none; z-index: 20; }
.edge.top { top: 0; }
.edge.bottom { bottom: 0; transform: scaleY(-1); }
.edge i { position: absolute; inset: 0; }
.edge .b1 {
  -webkit-backdrop-filter: blur(1.5px); backdrop-filter: blur(1.5px);
  -webkit-mask-image: linear-gradient(to bottom, #000 25%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 25%, transparent 100%);
}
.edge .b2 {
  -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 75%);
  mask-image: linear-gradient(to bottom, #000 0%, transparent 75%);
}
.edge .b3 {
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 50%);
  mask-image: linear-gradient(to bottom, #000 0%, transparent 50%);
}
.edge .veil {
  background: linear-gradient(to bottom,
    #fff 0%, rgba(255,255,255,.88) 22%, rgba(255,255,255,.55) 52%,
    rgba(255,255,255,.18) 80%, rgba(255,255,255,0) 100%);
}

/* Sidebar, 232 wide. */
.sidebar { position: fixed; left: 0; top: 0; bottom: 0; width: 232px; z-index: 30; }
/* Run 23: the menu icon stays above the open panel (scrim 55, panel 60) and closes it. */
.sidebar { z-index: 70; }
.sidebar .icon {
  position: absolute; top: 20px; width: 36px; height: 36px; opacity: .7;
  display: grid; place-items: center; background: none; border: 0; padding: 0; cursor: pointer;
  border-radius: 8px; transition: opacity .2s ease, background-color .2s ease;
}
.sidebar .icon:hover, .sidebar .icon:focus-visible { opacity: 1; background: rgba(28,28,26,.04); }
.sidebar .icon svg { width: 17px; height: 17px; }
/* Quiet: grey like the secondary text, not ink. */
.sidebar .icon { color: var(--text-3); opacity: .75; }
.sidebar .icon svg { stroke: currentColor; }
.sidebar .icon.toggle { left: 20px; }
/* The menu icon: three full lines, ink, 22 px; no button look. */
.sidebar .icon.toggle { color: #111; opacity: 1; }
.sidebar .icon.toggle svg { width: 22px; height: 22px; }
.sidebar .icon.toggle:hover, .sidebar .icon.toggle:focus-visible { background: none; }
/* "Nouvelle conversation": a real button, white on the panel grey, ink text. */
.new {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 9px 16px 9px 12px; border: 1px solid rgba(28,28,26,.12); border-radius: 10px;
  background: #fff; box-shadow: 0 1px 2px rgba(28,28,26,.05);
  font: 14px/18px "Luciole", serif; color: var(--ink); text-decoration: none; cursor: pointer;
  transition: background-color .2s ease, border-color .2s ease;
}
.new:hover, .new:focus-visible { background: #fafafa; border-color: rgba(28,28,26,.2); outline: 0; }
.new svg { width: 18px; height: 18px; flex: none; }
/* The product name, in the quotes' serif. */
.brand { font: 400 26px/32px "Spectral", serif; color: var(--ink); letter-spacing: .005em; margin: 0; }
.sidebar .brand { position: absolute; left: 28px; top: 66px; }
/* In the composer's place: its bottom edge, its one-line height, its corners. */
.sidebar .new, .history .new { height: 52px; padding: 0 20px; border-radius: 12px; }
.sidebar .new { position: absolute; left: 20px; bottom: var(--chat-bottom); white-space: nowrap; transition: bottom var(--move) var(--ease), background-color .2s ease, border-color .2s ease; }
.recent-title { position: absolute; left: 28px; top: 118px; font-size: 12px; line-height: 15px; color: var(--faint); }
.recent { position: absolute; left: 28px; width: 250px; top: 146px; list-style: none; }
.recent li { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.recent li { font-size: 14px; line-height: 17px; color: rgba(107,105,99,.9); margin-bottom: 17px; }


/* Quotes: 300 wide at (1044, 300). Secondary: they fade out through a
   5 px blur (Untitled) when the conversation starts. */
.quotes {
  position: fixed; left: calc(50% + var(--bh) / var(--ar) * .4 + 48px); top: calc(104px + 20vh);
  width: clamp(200px, calc(50% - var(--bh) / var(--ar) * .4 - 72px), 300px);
  display: flex; flex-direction: column; gap: 40px;
  will-change: transform;
  transition: opacity .6s ease, filter .6s ease, visibility 0s linear .6s;
}
.conv .quotes { opacity: 0; filter: blur(5px); visibility: hidden; pointer-events: none; }
.quote p { font: italic 300 21px/1.4 "Spectral", serif; }
.quote cite {
  display: block; margin-top: 10px;
  font: normal 400 12px "Spectral", serif; letter-spacing: .03em;
  color: var(--faint);
}
.quote.q1 p { color: rgba(28,28,26,.78); }
.quote.q1 cite { opacity: .93; }
.quote.q2 p { color: rgba(28,28,26,.42); }
.quote.q2 cite { opacity: .57; }

/* Conversation column: the whole height between the top band and the
   composer. The figure stays behind it, faint (uInk in the shader). */
.thread {
  position: fixed; left: 50%; transform: translateX(-50%);
  width: min(620px, calc(100vw - 520px));
  top: 72px; bottom: calc(48px + var(--chat-h) + 12px);
  overflow-y: auto; scrollbar-width: none;
  padding: 36px 4px 28px;
  display: flex; flex-direction: column; gap: 28px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 44px, #000 calc(100% - 20px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 44px, #000 calc(100% - 20px), transparent 100%);
  opacity: 0; visibility: hidden;
  transition: opacity .5s ease .25s;
}
.thread::-webkit-scrollbar { display: none; }
.conv .thread { opacity: 1; visibility: visible; }
.thread > :first-child { margin-top: auto; }

/* His message: right, a 5 percent ink bubble (Claude: radius 12, 12/16 padding). */
.msg.me {
  align-self: flex-end; max-width: 78%;
  padding: 10px 15px; border-radius: 12px;
  background: rgba(28,28,26,.05);
  font: 15px/21px "Luciole", serif; color: var(--ink);
  white-space: pre-wrap; overflow-wrap: anywhere;
  animation: rise .45s var(--ease) both;
}
@keyframes rise { from { opacity: 0; transform: translateY(10px); } }

/* Thinking: Claude's blinking dot (1200 ms, 0.3 to 1) and a shimmer band
   across the label (3000 ms). */
.msg.thinking { display: flex; align-items: center; gap: 10px; animation: rise .45s var(--ease) both; }
.msg.thinking .dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--text-3);
  animation: blink 1.2s linear infinite;
}
@keyframes blink { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }
.msg.thinking .label {
  font: 13px/18px "Luciole", serif;
  background: linear-gradient(90deg, var(--faint) 0%, var(--faint) 38%, var(--text) 50%, var(--faint) 62%, var(--faint) 100%);
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: shimmer 3s linear infinite;
}
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
/* Run 33: the line changes in place; the old one fades out, the new one fades in. */
.msg.thinking .label { transition: opacity 220ms ease; }
.msg.thinking .label.out { opacity: 0; }

/* His answer: no bubble, Spectral, words rise out of the mist one by one. */
.msg.bot { max-width: 560px; }
.msg.bot p.say { font: 300 20px/1.55 "Spectral", serif; color: var(--text); }
.msg.bot p.say + p.src { margin-top: 8px; }
.msg.bot p.src {
  font: 400 12px/1.4 "Spectral", serif; letter-spacing: .03em; color: var(--text-3);
  margin-bottom: 22px;
}
.msg.bot p.src:last-child { margin-bottom: 0; }
.msg.bot .w {
  display: inline-block;
  animation: mistIn .95s var(--ease) both;
  animation-delay: calc(var(--i) * 55ms);
}
@keyframes mistIn {
  from { opacity: 0; filter: blur(7px); transform: translateY(5px); }
  60% { filter: blur(0); }
  to { opacity: 1; filter: blur(0); transform: none; }
}
.msg.bot.instant .w { animation: none; }
/* Run 34: an answer in several paragraphs; the error line; the menu's open conversation. */
.msg.bot p.say + p.say { margin-top: 14px; }
.msg.err { font: 13px/18px "Luciole", serif; color: var(--text-3); }
.history-title[hidden] { display: none; }
.history-item[aria-current="true"] { background: rgba(28,28,26,.05); }

/* Composer: grows with the text up to 8 lines (ChatGPT), then scrolls.
   Anchored by its bottom, so it grows upward. */
.chat {
  position: fixed; left: 50%; transform: translateX(-50%); z-index: 30;
  bottom: calc(38vh - 200px);
  width: 520px; min-height: 52px; padding: 0 8px 0 22px;
  display: flex; align-items: flex-end; gap: 10px;
  background: rgba(255,255,255,.82); border: 1px solid rgba(28,28,26,.07);
  border-radius: 12px;
  box-shadow: 0 12px 36px rgba(28,28,26,.06);
  -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  transition: bottom var(--move) var(--ease), width var(--move) var(--ease);
}
.conv { --chat-bottom: 48px; }
.conv .chat { bottom: 48px; width: min(620px, calc(100vw - 520px)); }
.chat textarea {
  flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; resize: none;
  padding: 15px 0; max-height: 190px; overflow-y: auto; scrollbar-width: thin;
  font: 14px/20px "Luciole", serif; color: var(--ink); caret-color: var(--ink);
}
.chat button {
  flex: none; position: relative; width: 28px; height: 28px; margin-bottom: 11px;
  border: 0; border-radius: 18px;
  background: #111; display: grid; place-items: center; cursor: pointer;
  transition: opacity .2s ease;
}
.chat button svg { width: 18px; height: 18px; grid-area: 1 / 1; }
.chat .i-stop { display: none; }
/* Mic: 22 px, its centre --mic left of send's (send 28 wide, 10 px flex gap).
   Run 25: a button that records. #chat beats the .chat button rules (28 px round, ink
   background, the typing spring). */
#chat .mic { flex: none; width: 22px; height: 22px; margin: 0 calc(var(--mic, 41px) - 35px) 14px 0; padding: 0;
  border: 0; border-radius: 0; background: none; color: #111; display: block; cursor: pointer; transition: opacity .2s ease; animation: none; }
#chat .mic svg { width: 22px; height: 22px; display: block; }
#chat .mic[hidden] { display: none; }
/* Recording: the capsule fills with ink and the icon breathes, slowly. Reduced motion: the fill only. */
#chat .mic[aria-pressed="true"] .cap { fill: #111; }
#chat .mic[aria-pressed="true"] { animation: breathe 2.4s ease-in-out infinite; }
@keyframes breathe { 50% { opacity: .45; } }
/* The server is transcribing: faint, and a tap does nothing. */
#chat .mic.wait { opacity: .35; pointer-events: none; }
/* One short line under the box, three seconds, then gone. */
#chat .note { position: absolute; left: 22px; right: 22px; top: calc(100% + 8px); margin: 0; font: 12px/16px "Luciole", serif;
  color: var(--ink); opacity: 0; transition: opacity .3s ease; pointer-events: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#chat .note.on { opacity: .62; }
/* Run 29: the no-sound line is longer; it wraps instead of being cut. Without room
   under the box (the phone), the line goes above it. */
#chat .note.long { white-space: normal; }
#chat .note.above { top: auto; bottom: calc(100% + 8px); }
/* Empty: send at full opacity, disabled: it does nothing (addendum 1). */
.chat button:disabled { cursor: default; }
/* Typing: send springs in with an overshoot (Google AI Mode). */
[data-state="typing"] .chat button { animation: spring .32s cubic-bezier(.34, 1.56, .64, 1); }
@keyframes spring { from { transform: scale(.82); } }
/* Sent, thinking, answering: send becomes stop (ChatGPT, Claude). */
[data-state="sent"] .chat .i-send, [data-state="thinking"] .chat .i-send, [data-state="answering"] .chat .i-send { display: none; }
[data-state="sent"] .chat .i-stop, [data-state="thinking"] .chat .i-stop, [data-state="answering"] .chat .i-stop { display: block; }

/* Mist strength, for judging live: how much of the picture the white mist veils. Default 1. */
.mistctl {
  position: fixed; left: 28px; bottom: 24px; z-index: 40;
  display: flex; align-items: center; gap: 8px;
  padding: 6px 12px; border-radius: 999px;
  background: rgba(255,255,255,.7); border: 1px solid rgba(28,28,26,.08);
  font: 11px/14px "Luciole", serif; color: var(--text-3);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.mistctl input[type="range"] { width: 96px; accent-color: var(--text-3); }
.mistctl input[type="range"]:disabled, .mistctl.off output, .mistctl.off label { opacity: .4; }
/* The switch: a 26 x 16 pill, knob right when on. */
.mistctl input[role="switch"] {
  -webkit-appearance: none; appearance: none; flex: none; margin: 0;
  width: 26px; height: 16px; border-radius: 8px; position: relative; cursor: pointer;
  background: rgba(28,28,26,.18); transition: background-color .2s ease;
}
.mistctl input[role="switch"]::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(28,28,26,.2);
  transition: transform .2s var(--ease);
}
.mistctl input[role="switch"]:checked { background: var(--text-3); }
.mistctl input[role="switch"]:checked::after { transform: translateX(10px); }
.mistctl output { min-width: 22px; text-align: right; font-variant-numeric: tabular-nums; }

/* Run 22, PC: no sidebar, the panel as on the phone; the chat box at the
   products' width; the box in the centre at the start (addendum 3). */
:root { --cw: clamp(640px, 54vw, 768px); --fig: 1; }
.sidebar .new, .sidebar .brand, .recent-title, .recent { display: none; }
.sidebar { width: auto; bottom: auto; }
@media (min-width: 761px) {
  .chat { width: var(--cw); max-width: calc(100vw - 48px); }
  .conv .chat { width: var(--cw); }
  .thread { width: min(var(--cw), calc(100vw - 64px)); }
  /* The answer uses the whole column, as the products do. */
  .msg.bot { max-width: none; }
  body .history { width: 380px; padding-bottom: 48px; }
  /* ?fig scales him from the kepi top. */
  .box-bottom { --bh: calc((62vh + 68px) * var(--fig)); }
  /* Centre: the box's top at mid-height, growing down; the figure sized so
     his chin is about 30 px above it at the clips' lowest frames and the kepi top 40 px from the screen's top.
     Window y 0.02 to 1.0 of the clip: kepi at 0.0668 of the box, chin at
     0.695 at the lowest frames (run-22 shots); 0.71 leaves the margin. */
  /* Run 23: full height. The window is the clip's whole height, so --H is the
     clip's height on screen. Kepi top (clip y 0.078) at --kepi; clip y 0.97
     on the screen's bottom edge: H = (100vh - kepi) / 0.892. The box 16 px
     under the lowest chin (clip y 0.79): kepi + 0.712 H + 16, never under the screen. */
  body:not(.box-bottom) {
    --kepi: max(16px, 2vh);
    --H: calc((100vh - var(--kepi)) / 0.892 * var(--fig));
    /* Run 28: A puts the one-line box's middle at the screen's middle, whatever the
       clip; it grows downward. Run 24's place under his chin is gone. */
    --box-top: calc(50vh - 26px);
  }
  /* B docks at the bottom from the start. */
  body[data-box="b"]:not(.box-bottom) { --box-top: calc(100vh - 48px - var(--chat-h)); }
  body:not(.box-bottom) .chat { bottom: calc(100vh - var(--box-top) - var(--chat-h)); transition: width var(--move) var(--ease); }
  body.moving:not(.box-bottom) .chat { transition: bottom var(--move) var(--ease), width var(--move) var(--ease); }
  body:not(.box-bottom).conv .chat { bottom: 48px; }
  body:not(.box-bottom) .silhouette { top: calc(var(--kepi) - 0.078 * var(--H)); width: calc(var(--H) / var(--ar)); }
  body:not(.box-bottom) .edge.bottom { display: none; }
  body:not(.box-bottom) .edge.top { display: none; }
}

/* Phone: one column. */
@media (min-width: 761px) and (max-aspect-ratio: 7/5) {
  :root { --bh: 56vh; --chat-bottom: calc(48vh - 200px); }
  .chat { bottom: calc(48vh - 200px); }
}
@media (max-width: 760px) {
  .sidebar { width: auto; bottom: auto; }
  .sidebar .icon { top: max(16px, calc(env(safe-area-inset-top) - 8px)); }
  /* The top bar stays at the top of what is visible when Safari pans. */
  .sidebar { transform: translateY(var(--vv-top, 0px)); }
  .edge.bottom { bottom: var(--lift-chat, 0px); }
  .sidebar .icon.toggle { left: 12px; }
  :root, .conv { --chat-bottom: calc(28px + env(safe-area-inset-bottom)); }
  .sidebar .new, .sidebar .brand, .recent-title, .recent { display: none; }
  /* The figure fills the width from under the top bar down to
     8 px above the composer (one-line height, so typing does not move
     him); nothing overlaps him at rest.
     The shader fits the clip window to this box (applyWindow). No quotes on
     the phone, no white top band. */
  .silhouette {
    left: 0; right: 0; width: auto;
    /* The keyboard fits him above the composer: moved and scaled from his top centre. */
    transform: translateY(var(--fig-dy, 0px)) scale(var(--fig-s, 1)); transform-origin: 50% 0;
    transition: transform .25s ease-out;
    top: calc(64px + env(safe-area-inset-top));
    height: calc(var(--stage-h, 100dvh) - 64px - env(safe-area-inset-top) - 28px - env(safe-area-inset-bottom) - 52px - 8px);
  }
  .silhouette img { height: 100%; aspect-ratio: auto; object-position: 50% 0; }
  .quotes { display: none; }
  .edge.top { display: none; }
  .quotes {
    left: 50%; top: calc(124px + env(safe-area-inset-top)); bottom: auto;
    width: min(calc(100vw - 64px), 360px); margin-left: calc(min(calc(100vw - 64px), 360px) / -2);
    gap: 24px;
  }
  .quote p { font-size: 18px; }
  .quote cite { font-size: 11px; margin-top: 6px; }
  .chat, .conv .chat {
    bottom: calc(28px + env(safe-area-inset-bottom) + var(--lift-chat, 0px));
    transition: none; /* the keyboard moves it; no slow slide */
    width: calc(100vw - 32px); max-width: 520px;
  }
  /* 16 px stops iOS Safari from zooming on focus. */
  .chat textarea { font-size: 16px; line-height: 22px; padding: 14px 0; }
  .thread {
    left: 16px; right: 16px; width: auto; transform: none;
    /* Starts under the top bar; the figure is a faint layer behind it. */
    top: calc(64px + env(safe-area-inset-top) + var(--vv-top, 0px));
    bottom: calc(28px + env(safe-area-inset-bottom) + var(--chat-h) + 8px + var(--lift-chat, 0px));
    padding: 32px 2px 20px; gap: 22px;
  }
  .msg.me { font-size: 15px; max-width: 86%; }
  .msg.bot p.say { font-size: 18px; }
  /* On phones the slider lives in the top bar, beside the menu toggle. */
  .mistctl { top: max(22px, calc(env(safe-area-inset-top) - 2px)); bottom: auto; left: 56px; padding: 6px 10px; }
  .mistctl input[type="range"] { width: 72px; }
}
@media (max-width: 760px) and (max-height: 720px) {
  .quote.q2 { display: none; }
}
/* History panel: slides in from the left over the sidebar, closable by its
   button, the scrim, Escape or the toggle. Untitled panel gray F7F7F7. */
.scrim {
  position: fixed; inset: 0; z-index: 55; background: rgba(28,28,26,.04);
  opacity: 0; visibility: hidden; transition: opacity .35s ease, visibility 0s linear .35s;
}
.scrim.open { opacity: 1; visibility: visible; transition: opacity .35s ease; }
.history {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 60; width: 320px;
  display: flex; flex-direction: column; gap: 4px;
  padding: max(18px, env(safe-area-inset-top)) 14px 24px;
  background: #f7f7f7; border-right: 1px solid rgba(28,28,26,.06);
  box-shadow: 0 0 60px rgba(28,28,26,.06);
  overflow: hidden; padding-bottom: var(--chat-bottom);
  transform: translateX(-102%); visibility: hidden;
  transition: transform .45s var(--ease), visibility 0s linear .45s;
}
.history.open { transform: none; visibility: visible; transition: transform .45s var(--ease); }
.history-head { display: flex; align-items: center; padding: 6px 4px 0 10px; min-height: 36px; }
/* Run 23: the head is the menu icon's row (top 20, 36 high); "Charles" starts
   10 px right of the icon's lines (icon at 20, lines 27 to 49). */
.history { padding-top: 20px; }
.history-head { height: 36px; min-height: 0; padding: 0 0 0 45px; }
.history-title { font: 13px/18px "Luciole", serif; color: var(--text-3); margin: 16px 0 4px 10px; }
.history ul { list-style: none; flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.history-item {
  width: 100%; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 9px 10px; border: 0; border-radius: 8px; background: none; cursor: pointer; text-align: left;
  font: 14px/18px "Luciole", serif; color: var(--text);
}
.history-item:hover, .history-item:focus-visible { background: rgba(28,28,26,.05); outline: 0; }
/* 14 px panel padding + 2 = the phone composer's 16 px inset. */
.history .new { flex: none; display: flex; align-self: stretch; justify-content: center; margin: 12px 10px 0; }
@media (max-width: 760px) {
  .history { width: min(86vw, 340px); }
  /* Phone: the icon at left 12, top max(16px, safe area - 8px). */
  .history { padding-top: max(16px, calc(env(safe-area-inset-top) - 8px)); }
  .history-head { padding-left: 37px; }
  .scrim { background: rgba(28,28,26,.18); }
}
/* Run 24: the menu's motion (products and Emil Kowalski's guidance in run-24/notes.md).
   The panel slides in from the edge in 300 ms on the iOS sheet curve (Vaul,
   Claude): fast at first, a long gentle stop, no overshoot. It leaves faster,
   in 200 ms. The scrim fades with it. */
:root { --panel-in: 300ms; --panel-out: 200ms; --panel-ease: cubic-bezier(.32, .72, 0, 1); }
.history { transition: transform var(--panel-out) var(--panel-ease), visibility 0s linear var(--panel-out); }
.history.open { transition: transform var(--panel-in) var(--panel-ease); }
.scrim { transition: opacity var(--panel-out) ease, visibility 0s linear var(--panel-out); }
.scrim.open { transition: opacity var(--panel-in) ease; }
/* "Charles" does not ride in with the panel, so it never crosses the menu
   icon: the panel's own copy is hidden, and a still copy sits beside the icon,
   where run 23 put it (10 px right of the lines). Hidden while the panel is
   closed; it fades in place once the panel is nearly in, and out at once. */
.history .brand { visibility: hidden; }
.sidebar .panel-name {
  position: absolute; left: 59px; top: 22px; margin: 0; pointer-events: none; white-space: nowrap;
  font: 400 26px/32px "Spectral", serif; color: var(--ink); letter-spacing: .005em;
  opacity: 0; visibility: hidden; transition: opacity 120ms ease, visibility 0s linear 120ms;
}
.sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { opacity: 1; visibility: visible; transition: opacity 240ms ease-out 180ms; }
@media (max-width: 760px) {
  .sidebar .panel-name { left: 51px; top: calc(max(16px, calc(env(safe-area-inset-top) - 8px)) + 2px); }
}
/* Run 26: the figure and the mist fade in, still, at their final size, then
   the clip plays. Until body.fig-in nothing of the figure shows and its box
   cannot animate. 600 ms on a strong ease-out (Emil Kowalski): an entrance,
   seen once per visit. */
#mist, .silhouette img { opacity: 0; }
body:not(.fig-in) .silhouette { transition: none; }
body.fig-in #mist, body.fig-in .silhouette img { opacity: 1; transition: opacity 600ms cubic-bezier(.23, 1, .32, 1); }
@media (prefers-reduced-motion: reduce) {
  /* No slide: the panel and the name fade, 150 ms. */
  .history { transform: none; opacity: 0; transition: opacity 150ms ease, visibility 0s linear 150ms; }
  .history.open { opacity: 1; transition: opacity 150ms ease; }
  .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: opacity 150ms ease; }
  .silhouette, .chat, .quotes, .thread { transition: none; }
  .msg.me, .msg.thinking, .msg.bot .w, .chat button { animation: none !important; }
  .msg.thinking .label { animation: none; color: var(--faint); background: none; }
  .msg.thinking .dot { animation: none; opacity: .6; }
}
/* Run 31: menu craft options. ?logo, ?open, ?btn; body[data-logo|open|btn]. */
/* Logotype. "Charles" in Spectral: weight, tracking, and the six pairs
   kerned by hand (--k1 C-h, --k2 h-a, --k3 a-r, --k4 r-l, --k5 l-e, --k6 e-s). */
.sidebar .panel-name { font-kerning: normal; text-rendering: optimizeLegibility; font-feature-settings: "kern" 1, "liga" 1; }
.panel-name .word i { font-style: inherit; }
.panel-name .word i:nth-child(1) { margin-right: var(--k1, 0); }
.panel-name .word i:nth-child(2) { margin-right: var(--k2, 0); }
.panel-name .word i:nth-child(3) { margin-right: var(--k3, 0); }
.panel-name .word i:nth-child(4) { margin-right: var(--k4, 0); }
.panel-name .word i:nth-child(5) { margin-right: var(--k5, 0); }
.panel-name .word i:nth-child(6) { margin-right: var(--k6, 0); }
/* 1: Medium, a touch tight. The nearest to the weight of Claude's wordmark. */
body[data-logo="1"] .panel-name { font-weight: 500; letter-spacing: -.04em; --k1: -.015em; } /* run 37: -0.04 em (Arnaud), was -0.01 */
/* 2: Light, a little larger, opened up. Quiet. */
body[data-logo="2"] .panel-name { font-weight: 300; font-size: 28px; letter-spacing: .025em; }
/* 3: SemiBold, tight, the C pulled to the h, r and l kept apart. */
body[data-logo="3"] .panel-name { font-weight: 600; letter-spacing: -.02em; --k1: -.03em; --k4: .012em; }
/* 4: Regular, kerned pair by pair, no tracking. */
body[data-logo="4"] .panel-name { font-weight: 400; letter-spacing: 0; --k1: -.035em; --k2: -.005em; --k3: -.012em; --k4: .014em; --k5: -.01em; --k6: -.012em; }
/* 5: small capitals (Spectral SC), Medium, spaced. Engraved. */
body[data-logo="5"] .panel-name { font-family: "Spectral SC", "Spectral", serif; font-weight: 500; font-size: 23px; letter-spacing: .08em; }
/* 6: ExtraLight, larger, slightly tight. Fine and tall. */
body[data-logo="6"] .panel-name { font-weight: 200; font-size: 30px; letter-spacing: -.005em; --k1: -.02em; }
/* 7: Italic, Regular, the C tucked in. */
body[data-logo="7"] .panel-name { font-style: italic; font-weight: 400; letter-spacing: .005em; --k1: -.03em; --k6: .01em; }

/* Opening. Closing is always quicker than opening. */
/* 1: the same slide, slower, on a long gentle ease-out. */
body[data-open="1"] { --panel-in: 560ms; --panel-out: 320ms; --panel-ease: cubic-bezier(.22, 1, .36, 1); }
body[data-open="1"] .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: opacity 420ms ease-out 320ms; }
/* 2: a very slow glide, most of the time spent arriving. */
body[data-open="2"] { --panel-in: 820ms; --panel-out: 380ms; --panel-ease: cubic-bezier(.16, 1, .3, 1); }
body[data-open="2"] .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: opacity 520ms ease-out 420ms; }
/* 3: no movement, the panel fades in place. */
body[data-open="3"] .history { transform: none; opacity: 0; transition: opacity 260ms ease, visibility 0s linear 260ms; }
body[data-open="3"] .history.open { opacity: 1; transition: opacity 480ms cubic-bezier(.33, 1, .68, 1); }
body[data-open="3"] .scrim.open { transition: opacity 480ms ease; }
body[data-open="3"] .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: opacity 480ms ease-out 80ms; }
/* 4: a fade with a short drift, 20 px. */
body[data-open="4"] .history { transform: translateX(-20px); opacity: 0; transition: opacity 280ms ease, transform 280ms ease, visibility 0s linear 280ms; }
body[data-open="4"] .history.open { transform: none; opacity: 1; transition: opacity 560ms cubic-bezier(.22, 1, .36, 1), transform 560ms cubic-bezier(.22, 1, .36, 1); }
body[data-open="4"] .scrim.open { transition: opacity 560ms ease; }
body[data-open="4"] .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: opacity 460ms ease-out 140ms; }
/* 5: the panel does not move; it is uncovered from the left edge. */
body[data-open="5"] .history { transform: none; clip-path: inset(0 100% 0 0); transition: clip-path 300ms cubic-bezier(.37, 0, .63, 1), visibility 0s linear 300ms; }
body[data-open="5"] .history.open { clip-path: inset(0 0 0 0); transition: clip-path 680ms cubic-bezier(.37, 0, .63, 1); }
body[data-open="5"] .scrim.open { transition: opacity 680ms ease; }
body[data-open="5"] .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: opacity 420ms ease-out 260ms; }
/* 6: in two beats. The scrim first, then the panel fades, then its lines one by one. */
body[data-open="6"] .history { transform: none; opacity: 0; transition: opacity 240ms ease, visibility 0s linear 240ms; }
body[data-open="6"] .history.open { opacity: 1; transition: opacity 420ms ease-out 140ms; }
body[data-open="6"] .scrim.open { transition: opacity 360ms ease; }
body[data-open="6"] .history-title, body[data-open="6"] .history li, body[data-open="6"] .history .new { opacity: 0; transform: translateY(6px); transition: opacity 200ms ease, transform 200ms ease; }
body[data-open="6"] .history.open .history-title, body[data-open="6"] .history.open li, body[data-open="6"] .history.open .new { opacity: 1; transform: none; transition: opacity 420ms ease-out var(--d, 260ms), transform 420ms cubic-bezier(.22, 1, .36, 1) var(--d, 260ms); }
body[data-open="6"] .history li:nth-child(1) { --d: 300ms; } body[data-open="6"] .history li:nth-child(2) { --d: 340ms; }
body[data-open="6"] .history li:nth-child(3) { --d: 380ms; } body[data-open="6"] .history li:nth-child(4) { --d: 420ms; }
body[data-open="6"] .history li:nth-child(5) { --d: 460ms; } body[data-open="6"] .history li:nth-child(6) { --d: 500ms; }
body[data-open="6"] .history li:nth-child(7) { --d: 540ms; } body[data-open="6"] .history li:nth-child(8) { --d: 580ms; }
body[data-open="6"] .history .new { --d: 620ms; }
body[data-open="6"] .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: opacity 460ms ease-out 200ms; }
/* 7 (run 35): 6 with a hard cut. The scrim, the panel and the name are there at once; the lines still
   come in one by one, from 60 ms, 40 ms apart. Closing is a hard cut. */
body[data-open="7"] .history, body[data-open="7"] .history.open { transform: none; opacity: 1; transition: none; }
body[data-open="7"] .scrim, body[data-open="7"] .scrim.open { transition: none; }
body[data-open="7"] .sidebar .panel-name, body[data-open="7"] .sidebar .icon.toggle[aria-expanded="true"] ~ .panel-name { transition: none; }
body[data-open="7"] .history-title, body[data-open="7"] .history li, body[data-open="7"] .history .new { opacity: 0; transform: translateY(6px); transition: none; }
body[data-open="7"] .history.open .history-title, body[data-open="7"] .history.open li, body[data-open="7"] .history.open .new { opacity: 1; transform: none; transition: opacity 420ms ease-out var(--d, 60ms), transform 420ms cubic-bezier(.22, 1, .36, 1) var(--d, 60ms); }
body[data-open="7"] .history li:nth-child(1) { --d: 100ms; } body[data-open="7"] .history li:nth-child(2) { --d: 140ms; }
body[data-open="7"] .history li:nth-child(3) { --d: 180ms; } body[data-open="7"] .history li:nth-child(4) { --d: 220ms; }
body[data-open="7"] .history li:nth-child(5) { --d: 260ms; } body[data-open="7"] .history li:nth-child(6) { --d: 300ms; }
body[data-open="7"] .history li:nth-child(7) { --d: 340ms; } body[data-open="7"] .history li:nth-child(8) { --d: 380ms; }
body[data-open="7"] .history .new { --d: 420ms; }

/* Run 37: with the button at the top (4, 6), the cascade starts with it, then the heading, then the titles. */
body[data-open="6"][data-btn="4"] .history .new { --d: 260ms; } body[data-open="6"][data-btn="4"] .history-title { --d: 300ms; }
body[data-open="6"][data-btn="4"] .history li:nth-child(1) { --d: 340ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(2) { --d: 380ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(3) { --d: 420ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(4) { --d: 460ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(5) { --d: 500ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(6) { --d: 540ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(7) { --d: 580ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(8) { --d: 620ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(9) { --d: 660ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(10) { --d: 700ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(11) { --d: 740ms; } body[data-open="6"][data-btn="4"] .history li:nth-child(12) { --d: 780ms; }
body[data-open="6"][data-btn="6"] .history .new { --d: 260ms; } body[data-open="6"][data-btn="6"] .history-title { --d: 300ms; }
body[data-open="6"][data-btn="6"] .history li:nth-child(1) { --d: 340ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(2) { --d: 380ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(3) { --d: 420ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(4) { --d: 460ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(5) { --d: 500ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(6) { --d: 540ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(7) { --d: 580ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(8) { --d: 620ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(9) { --d: 660ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(10) { --d: 700ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(11) { --d: 740ms; } body[data-open="6"][data-btn="6"] .history li:nth-child(12) { --d: 780ms; }
body[data-open="7"][data-btn="4"] .history .new { --d: 60ms; } body[data-open="7"][data-btn="4"] .history-title { --d: 100ms; }
body[data-open="7"][data-btn="4"] .history li:nth-child(1) { --d: 140ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(2) { --d: 180ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(3) { --d: 220ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(4) { --d: 260ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(5) { --d: 300ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(6) { --d: 340ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(7) { --d: 380ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(8) { --d: 420ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(9) { --d: 460ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(10) { --d: 500ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(11) { --d: 540ms; } body[data-open="7"][data-btn="4"] .history li:nth-child(12) { --d: 580ms; }
body[data-open="7"][data-btn="6"] .history .new { --d: 60ms; } body[data-open="7"][data-btn="6"] .history-title { --d: 100ms; }
body[data-open="7"][data-btn="6"] .history li:nth-child(1) { --d: 140ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(2) { --d: 180ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(3) { --d: 220ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(4) { --d: 260ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(5) { --d: 300ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(6) { --d: 340ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(7) { --d: 380ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(8) { --d: 420ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(9) { --d: 460ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(10) { --d: 500ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(11) { --d: 540ms; } body[data-open="7"][data-btn="6"] .history li:nth-child(12) { --d: 580ms; }
/* Button. 0 is run 30's full-width box at the bottom. */
/* 1: a plain row at the bottom, like the conversation rows (ChatGPT, Claude, Gemini style, kept at the bottom). */
body[data-btn="1"] .history .new, body[data-btn="4"] .history .new {
  height: 40px; padding: 0 10px; margin: 10px 0 0; border: 0; border-radius: 8px; background: none; box-shadow: none;
  justify-content: flex-start; gap: 10px; font: 14px/18px "Luciole", serif; color: var(--ink);
}
body[data-btn="1"] .history .new:hover, body[data-btn="4"] .history .new:hover { background: rgba(28,28,26,.05); }
/* 2: a light pill, as wide as its words. */
body[data-btn="2"] .history .new { align-self: flex-start; height: 40px; padding: 0 18px 0 14px; margin-left: 10px; border-radius: 999px; gap: 9px; }
/* 3: an ink pill, as wide as its words, the send button's black. */
body[data-btn="3"] .history .new { align-self: flex-start; height: 40px; padding: 0 18px 0 14px; margin-left: 10px; border-radius: 999px; gap: 9px; background: #111; border-color: #111; color: #fff; box-shadow: none; }
body[data-btn="3"] .history .new svg { stroke: #fff; }
body[data-btn="3"] .history .new:hover { background: #2a2a2a; }
/* 4: the plain row at the top, above "Conversations", where the products put it. */
body[data-btn="4"] .history-head { order: 0; }
body[data-btn="4"] .history .new { order: 1; margin: 18px 0 0; }
body[data-btn="4"] .history-title { order: 2; }
body[data-btn="4"] .history ul { order: 3; }
/* 6 (run 36): 4 on the spine, the left end of the menu icon's lines. --spine is set by the script below. */
body[data-btn="6"] .history .new {
  order: 1; height: 40px; margin: 18px 0 0; padding: 0 10px 0 calc(var(--spine, 24px) - 14px - 1.69px);
  border: 0; border-radius: 8px; background: none; box-shadow: none;
  justify-content: flex-start; gap: 10px; font: 14px/18px "Luciole", serif; color: var(--ink);
}
body[data-btn="6"] .history .new:hover { background: rgba(28,28,26,.05); }
body[data-btn="6"] .history-head { order: 0; }
body[data-btn="6"] .history-title { order: 2; margin-left: calc(var(--spine, 24px) - 14px); }
body[data-btn="6"] .history ul { order: 3; }
body[data-btn="6"] .history-item { padding-left: calc(var(--spine, 24px) - 14px); }
/* 5: run 30's box, as wide as its words, 40 high. */
body[data-btn="5"] .history .new { align-self: flex-start; height: 40px; padding: 0 16px 0 12px; margin-left: 10px; border-radius: 10px; }

@media (prefers-reduced-motion: reduce) {
  body[data-open] .history-title, body[data-open] .history li, body[data-open] .history .new { transition: none; }
}
/* Run 38: buttons 4 and 6 on a 4 px grid. Centre to centre: menu row to button 48, button to heading 48,
   heading to the first title 28, titles 36. The flex gap (4) counts in each margin below. */
body[data-btn="4"] .history .new, body[data-btn="6"] .history .new { margin-top: 6px; gap: 8px; }
body[data-btn="4"] .history .new span, body[data-btn="6"] .history .new span { position: relative; top: -1.5px; }
body[data-btn="4"] .history-title, body[data-btn="6"] .history-title { margin-top: 15px; margin-bottom: -3px; }
/* Run 39: the waiting line alone. */
.msg.thinking .dot { display: none; }
/* Run 39: a row's "…" (on hover on PC, faint and always there on touch) and its menu. */
.history li { position: relative; }
.history-item { padding-right: 40px; }
.history .more {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px; padding: 0; border: 0; border-radius: 6px; background: none; cursor: pointer;
  display: grid; place-items: center; color: var(--text-3); opacity: 0; transition: opacity .15s ease, background-color .15s ease;
}
.history .more svg { width: 18px; height: 18px; }
.history li:hover .more, .history .more:focus-visible, .history li.menu-on .more { opacity: 1; }
.history .more:hover, .history li.menu-on .more { background: rgba(28,28,26,.06); color: var(--ink); }
@media (hover: none) { .history .more { opacity: .6; } }
.history .row-menu {
  display: none; position: absolute; right: 6px; top: calc(100% - 2px); z-index: 2; min-width: 180px; padding: 4px;
  background: #fff; border-radius: 10px; box-shadow: 0 0 0 1px rgba(28,28,26,.08), 0 8px 24px rgba(28,28,26,.10);
}
.history li.menu-on .row-menu { display: block; }
.history .row-menu button {
  width: 100%; height: 36px; display: flex; align-items: center; gap: 8px; padding: 0 10px;
  border: 0; border-radius: 6px; background: none; cursor: pointer; font: 14px/18px "Luciole", serif; color: var(--ink); text-align: left;
}
.history .row-menu button:hover { background: rgba(28,28,26,.05); }
.history .row-menu svg { width: 16px; height: 16px; flex: none; }
.history .row-menu .danger { color: #b42318; }
.history .row-menu .danger.armed { background: rgba(180,35,24,.08); }
.history ul { overflow-x: visible; }
/* Run 39: the phone starts with the box in the middle of the screen. */
@media (max-width: 760px) {
  body:not(.conv):not(.asking) .chat { bottom: calc(var(--stage-h, 100dvh) / 2 - var(--chat-h) / 2); }
}
