@font-face {
  font-family: Onest; font-weight: 100 900; font-display: swap;
  src: url(/assets/onest-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: Onest; font-weight: 100 900; font-display: swap;
  src: url(/assets/onest-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2190-2199, U+2212, U+2215;
}

:root {
  --paper: #fff;
  --ink: #111;
  --muted: #6b6b6b;
  --line: #e9e9e9;
  --soft: #f5f5f5;
  --red: #d33a2c;
  --green: #157a41; /* the assistant listening: text on paper 5.4:1 */
  --green-fill: #1e9e57;
  --placeholder: #8a8a8a;
  --shadow: rgb(0 0 0 / .12);
  /* The line drawings are black ink on white. Inverting by 0.929 lands white exactly on the dark paper
     (#121212) and the ink on #ededed, so no blending is needed. */
  --art-filter: none;
  --ease: cubic-bezier(.16, 1, .3, 1);
  color-scheme: light;
}
/* Dark: the same paper-and-ink, turned over. Telegram's own scheme wins inside the Mini App (data-theme). */
:root[data-theme="dark"] {
  --paper: #121212; --ink: #f2f2f2; --muted: #a0a0a0; --line: #2c2c2c; --soft: #1e1e1e; --red: #e0483a; --green: #4cc982; --green-fill: #23a65e;
  --placeholder: #8c8c8c; --shadow: rgb(0 0 0 / .5); --art-filter: invert(.929);
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #121212; --ink: #f2f2f2; --muted: #a0a0a0; --line: #2c2c2c; --soft: #1e1e1e; --red: #e0483a; --green: #4cc982; --green-fill: #23a65e;
    --placeholder: #8c8c8c; --shadow: rgb(0 0 0 / .5); --art-filter: invert(.929);
    color-scheme: dark;
  }
}
* { box-sizing: border-box; margin: 0; }
html, body { height: 100%; background: var(--paper); }
body {
  font: 400 17px/1.45 Onest, system-ui, sans-serif;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
  font-variant-numeric: tabular-nums;
}
::selection { background: var(--ink); color: var(--paper); }
/* A long press on a button must not select its label or open the iOS callout. */
button, .button { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; touch-action: manipulation; }
input { caret-color: var(--ink); }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

#app {
  min-height: 100dvh;
  display: flex; flex-direction: column;
  max-width: 440px; margin: 0 auto;
  padding: max(24px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right)) max(24px, env(safe-area-inset-bottom)) max(24px, env(safe-area-inset-left));
}
.stage { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 12px; }
.dock { display: grid; gap: 12px; padding-top: 24px; }

.art { width: min(78%, 300px); height: auto; margin-bottom: 36px; user-select: none; -webkit-user-drag: none; filter: var(--art-filter); }
h1 { font-size: 30px; line-height: 1.15; font-weight: 600; letter-spacing: -0.025em; text-wrap: balance; }
.lead { color: var(--muted); max-width: 30ch; text-wrap: pretty; }
.lead b { color: var(--ink); font-weight: 500; }

.button {
  appearance: none; border: 0; cursor: pointer;
  height: 56px; border-radius: 28px; width: 100%;
  font: 500 17px/1 Onest, system-ui, sans-serif;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--ink); color: var(--paper);
  transition: transform .2s var(--ease), opacity .2s;
  text-decoration: none;
}
.button svg { width: 20px; height: 20px; flex: none; }
.button:active { transform: scale(.98); }
.button[disabled] { opacity: .45; cursor: default; }
.button.quiet { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.link { appearance: none; background: none; border: 0; padding: 8px; font: inherit; color: var(--muted); text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--line); cursor: pointer; }

.field { width: 100%; text-align: left; display: grid; gap: 8px; }
.field span { font-size: 14px; color: var(--muted); }
.field input {
  height: 56px; border-radius: 16px; border: 1px solid var(--line); padding: 0 18px;
  font: 400 17px Onest, system-ui, sans-serif; color: var(--ink); background: var(--paper);
  transition: border-color .2s;
}
.field input:focus { outline: none; border-color: var(--ink); }
.field input::placeholder { color: var(--placeholder); }
/* The code from the letter (work email sign-in): six digits that read as one number. */
.field input.code { width: 100%; min-width: 0; height: 64px; font-size: 28px; font-weight: 500; letter-spacing: .32em; padding-left: calc(18px + .32em); text-align: center; font-variant-numeric: tabular-nums; }
.field input.code::placeholder { letter-spacing: .32em; }
/* Two quiet actions side by side, wrapping as a pair rather than leaving a separator behind. */
.fine.pair { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 4px; }
/* «или» between Google's button and the code by mail: a hairline either side. */
.or { display: flex; align-items: center; gap: 12px; color: var(--muted); font-size: 14px; }
.or::before, .or::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.link:disabled { cursor: default; text-decoration-color: transparent; }
.link:disabled:hover { color: var(--muted); }
.error { color: var(--red); font-size: 15px; min-height: 22px; }
.fine { color: var(--muted); font-size: 15px; line-height: 1.4; text-align: center; text-wrap: pretty; }
/* «Звонки этой компании записываются» on the join screen (server/policy.mjs): the recording's red dot, still. */
.rec-note { margin-top: 10px; max-width: 34ch; }
.rec-note span { display: inline-block; width: 8px; height: 8px; margin: 0 8px 1px 0; border-radius: 50%; background: var(--red); }
/* The company's name over a heading (server/companies.mjs): it belongs to the heading, so it sits close. */
.org { margin-bottom: -6px; }
.button svg + * { min-width: 0; }

/* In the call. It enters like every other screen; after that it is updated in place, so nothing re-enters. */
.call { flex: 1; display: flex; flex-direction: column; animation: enter .5s var(--ease) backwards; }
.call header { position: relative; text-align: center; padding-top: 11px; }
.call header h1 { font-size: 20px; font-weight: 500; letter-spacing: -0.01em; }
.call header p { color: var(--muted); font-size: 15px; margin-top: 2px; }
.notice.seal-problem { margin-top: 14px; margin-bottom: 0; }

/* Encryption: a quiet lock in the header's left corner, across from «Запись». Open while the call is plain, closed and
   in ink once it is encrypted; its popover offers «Зашифровать» or shows the four emoji to compare. */
.lock {
  appearance: none; border: 0; cursor: pointer; position: absolute; top: 0; left: 0; z-index: 3;
  width: 44px; height: 44px; border-radius: 22px; padding: 0; display: grid; place-items: center;
  background: none; color: var(--muted); transition: background .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.lock .icon { width: 20px; height: 20px; }
.lock.on { color: var(--ink); }
.lock:hover, .lock[aria-expanded="true"] { background: var(--soft); color: var(--ink); }
.lock:active { transform: scale(.94); }
.call header:has(.peek) .lock { left: 108px; }
.rec-pop.lock-pop { right: auto; left: 0; transform-origin: 22px 0; gap: 8px; }
.lock-pop > b { margin: 0; }
.lock-pop .notice-actions { margin-top: 4px; }
.seal-emoji { animation: settle .45s var(--ease) both; font-size: 28px; line-height: 1.2; letter-spacing: 0.12em; }

/* Recording: a quiet ring-and-dot in the header's corner; while a recording is on, a pill with a slowly
   breathing red dot for everyone in the call. Red here means «live», as on any recorder. */
.rec {
  appearance: none; border: 0; cursor: pointer; position: absolute; top: 0; right: 0; z-index: 3;
  min-width: 44px; height: 44px; border-radius: 22px; padding: 0 12px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  background: none; color: var(--muted); font: 500 14px/1 Onest, system-ui, sans-serif;
  transition: background .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.rec .icon { width: 22px; height: 22px; }
.rec:hover, .rec[aria-expanded="true"] { background: var(--soft); color: var(--ink); }
.rec:active { transform: scale(.94); }
.rec.live { color: var(--ink); background: var(--soft); height: 32px; top: 6px; padding: 0 12px 0 10px; }
.rec-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--red); animation: rec-breathe 2.4s ease-in-out infinite; }
@keyframes rec-breathe { 50% { opacity: .35; } }
.rec-pop {
  position: absolute; top: 62px; right: 0; z-index: 10; width: min(340px, calc(100vw - 48px));
  padding: 16px 18px; border-radius: 18px; text-align: left; display: grid; gap: 14px;
  background: var(--paper); box-shadow: 0 0 0 1px var(--line), 0 16px 40px -12px var(--shadow);
  transform-origin: calc(100% - 22px) 0; animation: pop .22s var(--ease) both;
}
@keyframes pop { from { opacity: 0; transform: translateY(-6px) scale(.97); } }
/* Sharing your screen: a live thumbnail of it in the header's left corner, across from «Запись».
   It grows out of its corner; hovered or focused, it offers to stop. */
.peek {
  appearance: none; border: 0; background: none; padding: 0; cursor: pointer; font: inherit;
  position: absolute; top: 4px; left: 0; z-index: 3; display: grid; justify-items: start; gap: 6px;
  color: var(--muted); font-size: 12px; line-height: 1; border-radius: 10px;
  transform-origin: 0 0; animation: peek .45s var(--ease) both;
}
@keyframes peek { from { opacity: 0; transform: scale(.9); filter: blur(4px); } }
.peek-frame {
  position: relative; display: block; width: 96px; aspect-ratio: 16 / 10; border-radius: 10px; overflow: hidden;
  background: #000; box-shadow: 0 0 0 1px var(--line), 0 8px 22px -10px var(--shadow);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease);
}
.peek-frame video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.peek-stop {
  position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; padding: 0 10px; text-align: center;
  background: color-mix(in srgb, var(--ink) 64%, transparent); color: var(--paper); font-weight: 500; line-height: 1.2;
  opacity: 0; transition: opacity .2s var(--ease);
}
.peek:hover .peek-frame, .peek:focus-visible .peek-frame { transform: scale(1.04); box-shadow: 0 0 0 1px var(--line), 0 12px 28px -10px var(--shadow); }
.peek:hover .peek-stop, .peek:focus-visible .peek-stop { opacity: 1; }
.peek:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.peek:active .peek-frame { transform: scale(.97); }
/* A window narrower than the call column and a margin for the picture beside it: a smaller picture and no caption. */
@media (max-width: 719px) { .peek-frame { width: 64px; border-radius: 8px; } .peek-label { display: none; } .peek-stop { font-size: 0; } .call header:has(.peek) .lock { left: 76px; } }
/* Your own screen remains a thumbnail, but it reserves a real header lane instead of floating into the timer and faces.
   The lanes are equal, so the timer stays in the middle (one lane on the left only squeezed it against the lock). */
.call.self-sharing:not(.showing) header { min-height: 82px; padding-left: 112px; padding-right: 112px; }
@media (max-width: 719px) { .call.self-sharing:not(.showing) header { min-height: 68px; padding-left: 76px; padding-right: 76px; } }
/* A window wider than the 440px call column has room beside it: your screen leaves the header for the window's top-left
   corner (120px, 200px from 1000px), and the header is the same as without sharing — lock, timer, «Запись». */
@media (min-width: 720px) {
  .call.self-sharing:not(.showing):not(.visual) header { min-height: 0; padding-left: 0; padding-right: 0; }
  .call.self-sharing:not(.showing):not(.visual) header .lock { left: 0; }
  .call.self-sharing:not(.showing):not(.visual) .peek { position: fixed; top: calc(20px + env(safe-area-inset-top)); left: 24px; gap: 8px; font-size: 13px; }
  .call.self-sharing:not(.showing):not(.visual) .peek-frame { width: 120px; }
}
@media (min-width: 1000px) { .call.self-sharing:not(.showing):not(.visual) .peek-frame { width: 200px; border-radius: 12px; } }
.rec-pop p { font-size: 15px; color: var(--muted); text-wrap: pretty; }
.rec-pop b { display: block; color: var(--ink); font-weight: 600; font-size: 17px; margin-bottom: 4px; }
.rec-pop .chip { display: inline-flex; align-items: center; padding: 0 14px; text-decoration: none; }
.rec-pop .chip[disabled] { opacity: .45; }
/* Keeping your voice out is always the quiet chip, also when it is the only one left. */
.rec-pop .chip.quiet { background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.people {
  flex: 1; display: flex; flex-wrap: wrap; align-content: center; justify-content: center;
  gap: 32px 28px; padding: 32px 0;
}
.person { width: 104px; display: grid; justify-items: center; align-content: start; gap: 12px; }
.face {
  position: relative; width: 96px; height: 96px; border-radius: 50%;
  display: grid; place-items: center; background: var(--soft);
  font-size: 34px; font-weight: 500; letter-spacing: -0.02em;
}
.people.many .person { width: 84px; }
.people.many .face { width: 76px; height: 76px; font-size: 28px; }
/* The ring breathes with the speaker's voice. */
.face::after {
  content: ''; position: absolute; inset: -7px; border-radius: 50%;
  border: 1.5px solid var(--ink); opacity: 0;
  transform: scale(calc(.94 + var(--level, 0) * .16));
  transition: opacity .25s, transform .12s linear;
}
.person.speaking .face::after { opacity: 1; }
.face .muted {
  position: absolute; right: -2px; bottom: -2px; width: 30px; height: 30px; border-radius: 50%;
  background: var(--paper); box-shadow: 0 1px 4px var(--shadow); display: grid; place-items: center;
}
.face .muted svg { width: 16px; height: 16px; }
/* Weak link: signal bars with one lit, a badge on the face opposite the muted mic. */
.face .weak {
  position: absolute; right: -2px; top: -2px; width: 30px; height: 30px; border-radius: 50%;
  background: var(--paper); box-shadow: 0 1px 4px var(--shadow); display: grid; place-items: center;
}
.face .weak svg { width: 16px; height: 16px; stroke-width: 2.25; }
.call header p .weak { display: inline-flex; vertical-align: -3px; margin-left: 6px; color: var(--ink); }
.call header p .weak svg { width: 17px; height: 17px; stroke-width: 2.25; }
.tile .tag .weak { display: inline-flex; }
.tile .tag .who { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tile .tag .weak svg { stroke-width: 2.25; }
.face video { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.person .name { font-size: 15px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.waiting { text-align: center; color: var(--muted); padding-bottom: 8px; }

.controls { position: relative; display: flex; justify-content: center; align-items: flex-start; gap: clamp(12px, 5vw, 28px); padding: 12px 0 36px; }
.control { display: grid; justify-items: center; align-content: start; gap: 10px; font-size: 13px; white-space: nowrap; color: var(--muted); }
.control > button, .mic-wrap > button, .screen-wrap > button {
  appearance: none; border: 0; cursor: pointer; width: 64px; height: 64px; border-radius: 50%;
  display: grid; place-items: center; background: var(--paper); color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line);
  transition: transform .2s var(--ease), background .2s, color .2s;
}
.control > button:active, .mic-wrap > button:active, .screen-wrap > button:active { transform: scale(.94); }
.control > button[aria-pressed="true"], .mic-wrap > button[aria-pressed="true"], .screen-wrap > button[aria-pressed="true"] { background: var(--ink); color: var(--paper); box-shadow: none; }
.control > button.leave { background: var(--red); color: #fff; box-shadow: none; }
.control > button[disabled], .mic-wrap > button[disabled], .screen-wrap > button[disabled] { opacity: .45; }
.control > button svg, .mic-wrap > button svg, .screen-wrap > button svg { width: 26px; height: 26px; }
/* Every control gets an equal share of the row (at most 92px; the row borrows 16px of each side margin), so three
   to six of them always fit: on a narrow phone the buttons shrink towards 48px and the labels towards 12px instead of running off screen. */
@supports (width: 1cqi) {
  .controls { gap: 0; margin-inline: -16px; container-type: inline-size; --n: 3; }
  .controls:has(> .control:nth-child(4)) { --n: 4; }
  .controls:has(> .control:nth-child(5)) { --n: 5; }
  .controls:has(> .control:nth-child(6)) { --n: 6; }
  .controls:has(> .control:nth-child(7)) { --n: 7; }
  /* Six on a 320px phone: «Микрофон» is wider than a sixth of the row, so it takes its width and the short ones («Чат»,
     «Ещё») give it up, at 11px — whole instead of «Микро…». Wider rows look as before. */
  .controls:has(> .control:nth-child(6)) .control { font-size: clamp(11px, var(--slot) / 5.8, 13px); }
  .controls:has(> .control:nth-child(6)):not(:has(> .control:nth-child(7))) .control { flex: 1 1 0; width: auto; min-width: max-content; max-width: 92px; }
  /* Seven in a narrow window: the labels step down to 11px and never run into the next one. */
  .controls:has(> .control:nth-child(7)) .control { font-size: clamp(11px, var(--slot) / 5.6, 13px); }
  .control > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .control { --slot: min(92px, 100cqi / var(--n)); width: var(--slot); flex: none; font-size: clamp(12px, var(--slot) / 6.2, 13px); }
  .control > button, .mic-wrap > button, .screen-wrap > button { width: clamp(48px, var(--slot) - 12px, 64px); height: clamp(48px, var(--slot) - 12px, 64px); }
}

/* Microphone and camera: the main toggle plus a small chevron that opens the device list,
   shown only when there is more than one device. The list sits centred above the whole row of controls,
   so it never runs off the edge of a phone screen. */
.mic-wrap { position: relative; }
.screen-wrap { position: relative; }
.control .mic-more {
  position: absolute; right: -4px; bottom: -2px; width: 26px; height: 26px;
  background: var(--paper); color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line), 0 1px 3px var(--shadow);
}
.control .mic-more svg { width: 14px; height: 14px; transition: transform .25s var(--ease); }
.control .mic-more[aria-expanded="true"] svg { transform: rotate(180deg); }
.control .screen-more {
  position: absolute; right: -4px; bottom: -2px; width: 26px; height: 26px;
  background: var(--paper); color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line), 0 1px 3px var(--shadow);
}
.control .screen-more svg { width: 14px; height: 14px; transition: transform .25s var(--ease); }
.control .screen-more[aria-expanded="true"] svg { transform: rotate(180deg); }
.screen-menu {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 8px); z-index: 12; width: min(360px, calc(100vw - 24px));
  margin: 0 auto; padding: 8px; border-radius: 18px; background: var(--paper);
  box-shadow: 0 0 0 1px var(--line), 0 12px 32px -8px var(--shadow); display: grid; gap: 4px;
  max-height: min(320px, calc(100dvh - 112px)); overflow-y: auto; overscroll-behavior: contain; animation: menu .22s var(--ease) both;
}
.screen-menu > .menu-label { padding-top: 6px; }
.screen-menu > .menu-label + .screen-options { margin-bottom: 4px; }
.screen-options { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 8px; }
.screen-choice {
  appearance: none; border: 0; cursor: pointer; height: 40px; padding: 0 14px; border-radius: 20px;
  font: 500 15px/1 Onest, system-ui, sans-serif; color: var(--ink); background: var(--paper); box-shadow: inset 0 0 0 1px var(--line);
  transition: transform .2s var(--ease), background .2s, color .2s;
}
.screen-choice[aria-checked="true"] { background: var(--ink); color: var(--paper); box-shadow: none; }
.screen-choice:active { transform: scale(.96); }
.screen-choice:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.screen-note { padding: 6px 14px 4px; color: var(--muted); font-size: 13px; line-height: 1.35; text-wrap: pretty; }
.mic-menu {
  position: absolute; left: 0; right: 0; margin: 0 auto; bottom: calc(100% + 4px); z-index: 10;
  width: min(340px, 100%); padding: 6px; border-radius: 18px;
  background: var(--paper); box-shadow: 0 0 0 1px var(--line), 0 12px 32px -8px var(--shadow);
  display: grid; gap: 2px; transform-origin: 50% 100%; overflow-y: auto; overscroll-behavior: contain;
  animation: menu .22s var(--ease) both;
}
@keyframes menu { from { opacity: 0; transform: translateY(6px) scale(.97); } }
.mic-option {
  appearance: none; border: 0; background: none; cursor: pointer; text-align: left;
  min-height: 48px; padding: 10px 14px; border-radius: 12px;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font: 400 16px/1.3 Onest, system-ui, sans-serif; color: var(--ink);
}
.mic-option span { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.mic-option:hover, .mic-option:focus-visible { background: var(--soft); outline: none; }
.mic-option[aria-selected="true"] { font-weight: 500; }
.mic-option svg { width: 18px; height: 18px; flex: none; }
/* Microphones and outputs in one menu: two quiet labels, a hairline between. */
.mic-menu > [role="listbox"] { display: grid; gap: 2px; }
.mic-menu > [role="listbox"] + [role="listbox"] { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--line); }
.menu-label { padding: 6px 14px 2px; font-size: 13px; color: var(--muted); }
/* «Громкость собеседников»: a hairline above and below, like the lists around it; a 4px track filled with ink up to the
   thumb, an ink thumb with a paper ring. The input itself is 44px tall, so a thumb is easy to catch. */
.mic-menu > .menu-volume { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--line); }
.mic-menu > .menu-volume + [role="listbox"] { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--line); }
.volume { display: flex; align-items: center; gap: 12px; padding: 0 14px 4px; color: var(--muted); }
.volume svg { width: 18px; height: 18px; flex: none; }
.volume input {
  appearance: none; -webkit-appearance: none; flex: 1; min-width: 0; height: 44px; margin: 0; background: none; cursor: pointer;
  --track: linear-gradient(var(--ink), var(--ink)) 0 / var(--at, 0%) 100% no-repeat, var(--line);
}
.volume input::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: var(--track); }
.volume input::-moz-range-track { height: 4px; border-radius: 2px; background: var(--track); }
.volume input::-webkit-slider-thumb {
  -webkit-appearance: none; width: 22px; height: 22px; margin-top: -9px; border-radius: 50%; border: 0;
  background: var(--ink); box-shadow: 0 0 0 3px var(--paper), 0 2px 6px -1px var(--shadow); transition: transform .15s var(--ease);
}
.volume input::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; border: 0; background: var(--ink); box-shadow: 0 0 0 3px var(--paper), 0 2px 6px -1px var(--shadow); }
.volume input:active::-webkit-slider-thumb { transform: scale(1.1); }
.volume input:focus-visible { outline: none; }
.volume input:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--ink); }
.volume input:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 3px var(--paper), 0 0 0 5px var(--ink); }
/* «Улучшить внешность» in the camera's menu: a row with a 40×24 switch (hairline track, ink when on), and while it is on
   the volume slider's look with «Слабо» and «Сильно» at its ends. A hairline above it when cameras are listed. */
.mic-menu > [role="listbox"] + .menu-touch { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--line); }
.cam-menu { grid-template-columns: minmax(0, 1fr); }
.touch-switch { width: 100%; justify-content: flex-start; }
.touch-switch > span:not(.switch) { flex: 1; }
.mic-option .switch { display: block; overflow: visible; }
.switch { position: relative; flex: none; width: 40px; height: 24px; border-radius: 12px; background: var(--line); transition: background .2s var(--ease); }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--paper); box-shadow: 0 1px 3px var(--shadow); transition: transform .2s var(--ease); }
.touch-switch[aria-checked="true"] .switch { background: var(--ink); }
.touch-switch[aria-checked="true"] .switch::after { transform: translateX(16px); }
.touch-level { font-size: 13px; }
.touch-level span { flex: none; }

svg.icon { fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.notice {
  margin: 0 auto 20px; width: 100%; padding: 16px 18px; border-radius: 18px;
  background: var(--soft); display: grid; gap: 12px; text-align: left;
  animation: rise .3s var(--ease) both;
}
@keyframes rise { from { opacity: 0; transform: translateY(6px); } }
.notice p { font-size: 15px; color: var(--muted); }
.notice b { display: block; color: var(--ink); font-weight: 600; font-size: 17px; margin-bottom: 2px; }
.notice-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  appearance: none; border: 0; cursor: pointer; height: 40px; padding: 0 16px; border-radius: 20px;
  font: 500 15px/1 Onest, system-ui, sans-serif; background: var(--ink); color: var(--paper);
  transition: transform .2s var(--ease);
}
.chip + .chip { background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.chip:active { transform: scale(.97); }

/* ——— Video and screen sharing (experimental) ——— */
/* With pictures on screen the column widens; the controls stay one centred row. */
body.wide #app { max-width: 1600px; height: 100dvh; }
.call.visual { min-height: 0; }
.call.visual .controls { padding-bottom: 20px; }
/* The stage fills what the header and controls leave. Each tile is placed on it by web/app.js (fitTiles) with the
   rectangles web/layout.js computes from every picture's shape (DESIGN.md «Video layout»). */
.tiles { --gap: 8px; flex: 1; min-height: 96px; position: relative; margin: 16px 0 8px; }
.tiles > .tile:not(.pip) { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }
.tile {
  position: relative; isolation: isolate; border-radius: 20px; overflow: hidden; background: var(--soft);
  display: grid; place-items: center; outline: 2px solid transparent; outline-offset: 3px; transition: outline-color .25s;
}
.tile.speaking { outline-color: var(--ink); }
.tile video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 35%; opacity: 0; transition: opacity .35s var(--ease); }
.tile video[data-live] { opacity: 1; }
/* Shown whole (a phone held upright in a wide tile, a wide picture in a tall one): over a blurred copy of itself. */
.tile[data-fit="contain"] > video:not(.blur) { object-fit: contain; object-position: 50% 50%; }
.tile > video.blur { z-index: -1; filter: blur(28px) saturate(1.1) brightness(.75); transform: scale(1.2); }
.tile.mirror > video.blur { transform: scale(-1.2, 1.2); }
.tile.mirror video { transform: scaleX(-1); }
.tile .initial {
  width: clamp(56px, 30cqmin, 128px); aspect-ratio: 1; border-radius: 50%; display: grid; place-items: center;
  background: var(--paper); font-size: clamp(22px, 12cqmin, 48px); font-weight: 500; letter-spacing: -0.02em; color: var(--muted);
}
.tile .initial.agent-mark { background: none; }
/* «Крупно» on a picture of the two: on hover with a mouse, always on touch. */
.tile .grow { position: absolute; top: 8px; right: 8px; z-index: 1; width: 36px; height: 36px; opacity: 0; transition: opacity .2s var(--ease), transform .2s var(--ease); }
.tile .grow svg { width: 17px; height: 17px; }
.tile:hover .grow, .tile .grow:focus-visible { opacity: 1; }
@media (hover: none) { .tile .grow { opacity: .9; } }
/* Among three and more on touch a double tap pins; the button would sit on every face. Only «Все вместе» on the pinned one stays. */
@media (hover: none) { .tile:not([data-pinned]) > .grow[data-pin] { display: none; } }
.tile:has(.flip) .grow { right: 56px; }
.tile .tag {
  position: absolute; left: 10px; bottom: 10px; max-width: calc(100% - 20px);
  display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 14px;
  background: color-mix(in srgb, var(--paper) 86%, transparent); color: var(--ink); font-size: 14px; line-height: 18px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile .tag svg { width: 14px; height: 14px; flex: none; }
/* One-to-one: the other person fills the frame, you sit in the corner. */
.tile.pip {
  position: absolute; right: 12px; bottom: 12px; z-index: 2; width: clamp(96px, 26%, 220px); aspect-ratio: 3 / 4; min-height: 0;
  box-shadow: 0 6px 20px -6px var(--shadow), 0 0 0 1px var(--line);
}
@media (min-width: 900px) { .tile.pip { aspect-ratio: 4 / 3; } }
.tile.pip .initial { width: 56px; font-size: 22px; }
/* It can be dragged to any corner (web/app.js); on release it settles there from where the finger let go. */
.tile.pip { touch-action: none; cursor: grab; }
.tile.pip.dragging { cursor: grabbing; transition: none; box-shadow: 0 16px 36px -10px var(--shadow), 0 0 0 1px var(--line); }
.tile.pip.settling { transition: translate .42s var(--ease); }
.tile.pip[data-corner$="l"] { right: auto; left: 12px; }
.tile.pip[data-corner^="t"] { bottom: auto; top: 12px; }
/* A phone held upright on a wide tile: the whole picture on black, as FaceTime shows it, not a crop of the face. */
.tile { container-type: size; }
/* With your picture in the bottom-left corner their name moves to the right. */
.tiles:has(> .pip[data-corner="bl"]) > .tile:not(.pip) .tag { left: auto; right: 10px; }
.call.immersive .tiles:has(> .pip[data-corner="bl"]) > .tile:not(.pip) .tag { left: auto; right: max(16px, env(safe-area-inset-right)); }
/* The other person's name stops short of your corner picture. */
.tiles[data-n="1"] > .tile:not(.pip) .tag { max-width: calc(100% - 44px - clamp(96px, 26%, 220px)); }
.tile.pip .tag { left: 6px; bottom: 6px; font-size: 12px; padding: 3px 8px; }
.round {
  appearance: none; border: 0; cursor: pointer; width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; color: var(--ink);
  background: color-mix(in srgb, var(--paper) 86%, transparent); transition: transform .2s var(--ease);
}
.round:active { transform: scale(.92); }
.round svg { width: 20px; height: 20px; }
.tile .flip { position: absolute; top: 8px; right: 8px; z-index: 1; }
.tile.pip .flip { width: 34px; height: 34px; top: 6px; right: 6px; }

/* One-to-one with their camera on, as in FaceTime: they fill the whole screen, edge to edge. Over the picture the
   header and controls turn white on a soft dark scrim, the buttons frosted; a tap hides them (.calm), another brings
   them back. Your corner picture and their badge ride just above whatever is at the bottom (--dock). */
.call.immersive { touch-action: manipulation; }
.call.immersive .tiles { position: fixed; inset: 0 var(--chat-w, 0px) 0 0; z-index: 0; margin: 0; }
.call.immersive .tile { outline-color: transparent; background: #000; }
.call.immersive .tile:not(.pip) { border-radius: 0; min-height: 0; }
/* A face without a camera among pictures edge to edge (or in your corner): a dark card, the initial on a frosted circle. */
.call.immersive .tile[data-video="off"] { background: #1c1c1c; }
.call.immersive .tile[data-video="off"] .initial { background: rgb(255 255 255 / .14); color: #fff; }
.call.immersive .tiles[data-n="1"] .tile:not(.pip) .who { display: none; }
.call.immersive .tiles[data-n="1"] .tile .tag:not(:has(svg)) { display: none; }
/* Both edge to edge: a hairline of black between them. */
.call.immersive .tiles:not([data-n="1"]) { --gap: 2px; background: #000; }
/* Faces, names and seams never go under the notch, the status bar or the home bar: several pictures edge to edge keep
   inside the safe area, the black around them reaching the screen's edges. Only one picture alone may run under them. */
.call.immersive .tiles:not([data-n="1"]) {
  inset: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  box-shadow: 0 0 0 100vmax #000;
}
.call.immersive .tile.pip { right: max(16px, env(safe-area-inset-right)); bottom: var(--dock, 140px); box-shadow: 0 10px 28px -8px rgb(0 0 0 / .5); transition: bottom .45s var(--ease); }
.call.immersive .tiles:is([data-n="1"], [data-duo]) .tile:not(.pip) .tag { left: max(16px, env(safe-area-inset-left)); bottom: var(--dock, 140px); transition: bottom .45s var(--ease); }
.call.calm .tile.pip, .call.calm .tiles:is([data-n="1"], [data-duo]) .tile:not(.pip) .tag { bottom: max(16px, env(safe-area-inset-bottom)); }
.call.immersive .tile.pip[data-corner$="l"] { right: auto; left: max(16px, env(safe-area-inset-left)); }
.call.immersive .tile.pip[data-corner^="t"] { bottom: auto; top: var(--top, 120px); transition: top .45s var(--ease); }
.call.calm .tile.pip[data-corner^="t"] { bottom: auto; top: max(16px, env(safe-area-inset-top)); }
.call.immersive .tile.pip.settling { transition: translate .42s var(--ease), top .45s var(--ease), bottom .45s var(--ease); }
.call.immersive .flip { transition: opacity .3s var(--ease), transform .2s var(--ease); }
.call.calm .flip { opacity: 0; pointer-events: none; }
.call.immersive:not(.calm) .tile[data-top]:not(.pip) > :is(.grow, .flip) { top: calc(var(--top, 120px) - env(safe-area-inset-top)); }
.call.calm { cursor: none; }
.call.immersive::before, .call.immersive::after {
  content: ''; position: fixed; left: 0; right: var(--chat-w, 0px); z-index: 1; pointer-events: none; transition: opacity .35s var(--ease);
}
.call.immersive::before { top: 0; height: calc(env(safe-area-inset-top) + 170px); background: linear-gradient(rgb(0 0 0 / .5), transparent); }
.call.immersive::after { bottom: 0; height: calc(env(safe-area-inset-bottom) + 220px); background: linear-gradient(transparent, rgb(0 0 0 / .55)); }
.call.calm::before, .call.calm::after { opacity: 0; }
.call.immersive > :not(.tiles) {
  position: relative; z-index: 2;
  transition: opacity .3s var(--ease), transform .45s var(--ease), visibility 0s;
}
.call.calm > :not(.tiles) {
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .3s var(--ease), transform .45s var(--ease), visibility 0s .45s;
}
.call.calm > header { transform: translateY(-10px); }
/* Shown again over the picture, the header and the row of controls take a press only on what they hold: their empty space
   lets it through to the picture, so your corner picture, which sat under them while they were hidden, is dragged at once. */
.call.immersive:not(.calm) > :is(header, .controls) { pointer-events: none; }
.call.immersive:not(.calm) > .controls > *, .call.immersive:not(.calm) > header :is(button, a, .lock-pop, .rec-pop) { pointer-events: auto; }
.call.calm > .controls { transform: translateY(16px); }
/* With the picture behind, everything below the header gathers at the bottom, in the thumb zone. */
.call.immersive > header { margin-bottom: auto; color: #fff; text-shadow: 0 1px 10px rgb(0 0 0 / .3); }
.call.immersive header > p, .call.immersive .lock { color: rgb(255 255 255 / .82); }
.call.immersive header > p .weak { color: #fff; }
.call.immersive .lock:hover, .call.immersive .lock[aria-expanded="true"],
.call.immersive .rec:hover, .call.immersive .rec[aria-expanded="true"], .call.immersive .rec.live { background: rgb(255 255 255 / .18); color: #fff; }
.call.immersive .rec { color: rgb(255 255 255 / .82); }
.call.immersive .controls { padding-top: 16px; }
.call.immersive .control { color: rgb(255 255 255 / .9); text-shadow: 0 1px 8px rgb(0 0 0 / .3); }
.call.immersive .control > button, .call.immersive .mic-wrap > button, .call.immersive .screen-wrap > button {
  background: rgb(255 255 255 / .2); color: #fff; box-shadow: none;
  -webkit-backdrop-filter: blur(20px) saturate(1.6); backdrop-filter: blur(20px) saturate(1.6);
}
.call.immersive .control > button[aria-pressed="true"], .call.immersive .mic-wrap > button[aria-pressed="true"], .call.immersive .screen-wrap > button[aria-pressed="true"] { background: #fff; color: #111; }
.call.immersive .control > button.leave { background: var(--red); color: #fff; }
.call.immersive .control .mic-more, .call.immersive .control .screen-more { background: rgb(40 40 40 / .8); color: #fff; box-shadow: none; }
.call.immersive .rec-pop, .call.immersive .mic-menu { color: var(--ink); text-shadow: none; }

/* A shared screen: the whole frame, letterboxed, never cropped. «1:1» shows it pixel for pixel. */
.screen {
  flex: 0 0 auto; align-self: center; width: 100%; max-width: 100%; min-height: 0; position: relative; margin: 20px 0 8px; border-radius: 20px; overflow: hidden;
  background: #000; display: flex; flex-direction: column; isolation: isolate;
}
.screen .view { flex: 1; min-height: 0; position: relative; overflow: hidden; }
.screen video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
.screen.actual .view { overflow: auto; overscroll-behavior: contain; }
.screen.actual video { position: static; width: auto; height: auto; max-width: none; }
.screen-bar { position: absolute; left: 10px; right: 10px; bottom: 10px; display: flex; align-items: center; gap: 8px; pointer-events: none; }
.screen-bar > * { pointer-events: auto; }
.screen-bar .tag { margin-right: auto; padding: 5px 10px; border-radius: 14px; font-size: 14px; background: color-mix(in srgb, var(--paper) 86%, transparent); max-width: 60%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.screen-bar .round { width: auto; min-width: 40px; padding: 0 12px; border-radius: 20px; font: 500 14px/1 Onest, system-ui, sans-serif; }
.screen:fullscreen { margin: 0; border-radius: 0; }
/* Watching a shared screen: the header folds into one line and the strip slims down, so the screen gets the height.
   The line is centred on the corners' 44px, as the timer is, and keeps clear of the lock and «Запись»; where it would
   not fit beside them (a phone), the header stays the call's own two lines. */
@media (min-width: 520px) {
  .call.showing header { display: flex; align-items: center; justify-content: center; gap: 4px 14px; padding: 0 52px; min-height: 44px; }
  .call.showing header:has(.rec.live) { padding-right: 108px; }
  .call.showing header h1 { font-size: 17px; }
  .call.showing header p { margin-top: 0; font-size: 14px; }
}
.call.showing .screen { margin: 10px 0 12px; }
/* Under a shared screen people are chips, not circles: the name on soft fill (a muted-mic or weak-link icon before
   it), in one row (more scroll sideways under a fade). Circles stay the controls' shape, so the two rows no longer
   look alike. Whoever speaks gets an ink outline around their chip. */
.strip {
  display: flex; justify-content: safe center; gap: 6px; padding: 8px 24px 4px; margin: 0 -24px;
  overflow-x: auto; scrollbar-width: none; mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.strip::-webkit-scrollbar { display: none; }
.strip .person {
  flex: none; width: auto; display: flex; align-items: center; gap: 5px; height: 34px; padding: 0 14px;
  border-radius: 17px; background: var(--soft); transition: box-shadow .25s;
}
.strip .person.speaking { box-shadow: inset 0 0 0 1.5px var(--ink); }
.strip .muted, .strip .weak { display: inline-flex; color: var(--muted); }
.strip .weak { color: var(--ink); }
.strip .muted svg, .strip .weak svg { width: 15px; height: 15px; }
.strip .weak svg { stroke-width: 2.25; }
.strip .name { font-size: 14px; max-width: 10em; }
.call.showing .controls { padding: 10px 0 16px; }
/* On a computer the people and the controls share one bar under the screen: the chips on the left, the controls centred. */
@media (min-width: 900px) {
  .bar { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; column-gap: 24px; padding: 8px 0 16px; }
  .bar .strip { justify-content: flex-start; padding: 0; margin: 0; }
  .call.showing .bar .controls { padding: 0; }
  @supports (width: 1cqi) { .call.showing .bar .controls { width: calc(var(--n) * 92px); margin-inline: 0; } }
}
/* «Прогулка» (Игры): Street View takes the stage the way a shared screen does, the same 20px corners, people as chips. */
.game { flex: 1 1 auto; min-height: 0; width: 100%; position: relative; margin: 10px 0 12px; border-radius: 20px; overflow: hidden; background: var(--soft); isolation: isolate; }
.game iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
/* Both sharing at once: your thumbnail joins the folded header line, small and first (on a phone it keeps its corner). */
@media (min-width: 520px) {
  .call.showing .peek { position: static; order: -1; grid-auto-flow: column; align-items: center; }
  .call.showing .peek-frame { width: 52px; border-radius: 7px; }
  .call.showing .peek-label { display: none; }
  .call.showing header:has(.peek) .lock { left: 0; }
}

#toast {
  position: fixed; left: calc(50% - var(--chat-w, 0px) / 2); bottom: max(28px, env(safe-area-inset-bottom));
  transform: translate(-50%, 12px); opacity: 0; pointer-events: none;
  background: var(--ink); color: var(--paper); padding: 12px 18px; border-radius: 22px; font-size: 15px;
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }

.enter { animation: enter .6s var(--ease) both; }
@keyframes enter { from { opacity: 0; transform: translateY(8px); filter: blur(4px); } }
/* The key arrived: the four emoji come into focus in place of «Шифруем…». */
@keyframes settle { from { opacity: 0; filter: blur(6px); transform: scale(.96); } }
@media (prefers-reduced-motion: reduce) {
  *, *::after { animation: none !important; transition: none !important; }
}

/* Связной on the home screen: the phone drawing, numbered steps with the browser's own buttons drawn inline, and a
   pointer at that button just outside the page (Safari's bottom bar, the top-right corner elsewhere). */
.art-send { width: min(88%, 330px); }
.art-home { width: 112px; margin-bottom: 20px; }
.install { gap: 10px; }
.install h1 { max-width: 13em; font-size: 26px; }
@media (max-height: 640px) { .art-home { width: 76px; margin-bottom: 8px; } .install:has(.steps) .lead { display: none; } body[data-state="install"] #app { padding-bottom: 96px; } }
.steps { list-style: none; padding: 0; margin-top: 14px; display: grid; gap: 12px; text-align: left; counter-reset: step; max-width: 330px; width: 100%; }
.steps li { counter-increment: step; display: grid; grid-template-columns: 28px 1fr; gap: 12px; align-items: baseline; font-size: 16px; line-height: 1.4; text-wrap: pretty; }
.steps li::before { content: counter(step); width: 28px; height: 28px; border-radius: 50%; background: var(--soft); display: grid; place-items: center; font-size: 14px; font-weight: 600; transform: translateY(-1px); }
.icon.inline { width: 1.15em; height: 1.15em; vertical-align: -0.2em; margin: 0 .1em; stroke-width: 2; }
body[data-state="install"] #app { padding-top: max(64px, calc(env(safe-area-inset-top) + 48px)); padding-bottom: max(76px, calc(env(safe-area-inset-bottom) + 60px)); }
.pointer {
  position: fixed; z-index: 5; padding: 8px 14px; border-radius: 18px;
  background: var(--ink); color: var(--paper); font-size: 15px; font-weight: 500; line-height: 20px;
  box-shadow: 0 6px 18px var(--shadow); pointer-events: none;
  animation: point 1.4s var(--ease) infinite alternate;
}
.pointer::after { content: ''; position: absolute; width: 12px; height: 12px; background: inherit; border-radius: 2px; transform: rotate(45deg); }
.pointer-bottom, .pointer-corner { bottom: calc(env(safe-area-inset-bottom) + 14px); --dir: 6px; }
.pointer-bottom { left: 50%; translate: -50% 0; }
.pointer-bottom::after { left: calc(50% - 6px); bottom: -5px; }
.pointer-corner { right: 12px; }
.pointer-corner::after { right: 18px; bottom: -5px; }
.pointer-top { top: calc(env(safe-area-inset-top) + 14px); right: 12px; --dir: -6px; }
.pointer-top::after { right: 18px; top: -5px; }
@keyframes point { from { transform: translateY(0); } to { transform: translateY(var(--dir)); } }

/* Post-call rating: one tap, skippable. */
/* «Плохо слышно?»: one more quiet word on the status line, after a dot. */
.call header p .sep { margin: 0 7px; }
.hear {
  appearance: none; border: 0; background: none; padding: 6px 2px; margin: -6px 0; cursor: pointer;
  font: inherit; color: var(--muted); transition: color .2s;
}
.hear:hover, .hear:focus-visible { color: var(--ink); }
.hear:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }
.hear.done, .hear.done:hover { color: var(--muted); }
.hear.done { cursor: default; display: inline-flex; align-items: center; gap: 4px; vertical-align: -3px; animation: settle .45s var(--ease) both; }
.hear.done svg { width: 16px; height: 16px; }
.hear-ask { display: inline-flex; align-items: baseline; gap: 6px; animation: settle .35s var(--ease) both; }
.hear-ask .hear { margin: -6px 0; }
/* Pulse from a band (web/pulse.js): your own number on the status line, the heart in muted ink, the beats tabular. */
.pulse { display: inline-flex; align-items: center; gap: 4px; vertical-align: -2px; color: var(--ink); font-variant-numeric: tabular-nums; }
.pulse svg { width: 15px; height: 15px; color: var(--muted); }
.hear-ask > span { color: var(--line); }
.immersive .hear { color: rgb(255 255 255 / .8); }

/* After the call: one line of numbers, who talked how much as a thin split bar, and how it got through. */
.recap { width: min(100%, 300px); display: grid; gap: 10px; margin-top: 12px; }
.recap-head { color: var(--muted); }
.recap-head b { color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }
.share { display: flex; gap: 3px; height: 6px; }
.share i { border-radius: 3px; background: var(--ink); animation: grow .6s var(--ease) both; transform-origin: left; }
.share i:nth-child(2) { opacity: .5; } .share i:nth-child(3) { opacity: .28; } .share i:nth-child(4) { opacity: .14; }
.recap-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 16px; font-size: 15px; color: var(--muted); }
.recap-legend b { color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }
.recap-note { font-size: 15px; color: var(--muted); text-wrap: pretty; }
@keyframes grow { from { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) { .share i { animation: none; } }
.recap.settled .share i { animation: none; }

.rec-sent { margin-top: 0; }
/* «Как было слышно?» and three quiet chips on one row. */
.rate { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 28px; }
.rate p { width: 100%; margin: 0 0 2px; color: var(--muted); font-size: 15px; }
.rate .chip { background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); padding: 0 14px; }
.rate-done { margin-top: 28px; }
/* «Что улучшить в Связном?»: one soft line under the rating that grows with the words, a round send button inside it. */
.feedback { position: relative; width: min(100%, 340px); margin: 14px auto 0; }
.feedback textarea {
  display: block; width: 100%; min-height: 44px; max-height: 132px; field-sizing: content; resize: none;
  padding: 11px 50px 11px 16px; border: 0; border-radius: 22px; background: var(--soft); color: var(--ink);
  font: inherit; font-size: 15px; line-height: 1.45; outline: none; transition: box-shadow .2s;
}
.feedback textarea::placeholder { color: var(--placeholder); }
.feedback textarea:focus-visible { box-shadow: inset 0 0 0 1.5px var(--ink); }
.feedback-send {
  position: absolute; right: 4px; bottom: 4px; width: 36px; height: 36px; border: 0; border-radius: 50%; padding: 0;
  display: grid; place-items: center; background: var(--ink); color: var(--paper); cursor: pointer; transition: opacity .2s, transform .15s var(--ease);
}
.feedback-send svg { width: 17px; height: 17px; }
.feedback-send:disabled { opacity: .25; cursor: default; }
.feedback-send:not(:disabled):active { transform: scale(.9); }

/* ——— Memory: the last time you talked (server/memory.mjs) ——— */
.memo { width: 100%; max-width: 360px; margin-top: 12px; padding: 14px 16px; border-radius: 18px; background: var(--soft); text-align: left; display: grid; gap: 6px; }
.memo.enter { animation: rise .3s var(--ease) both; }
.memo-head { font-size: 13px; color: var(--muted); }
.memo-text { font-size: 15px; line-height: 1.4; color: var(--ink); text-wrap: pretty; }
.memo-list { list-style: none; margin: 2px 0 0; padding: 0; display: grid; gap: 4px; font-size: 15px; line-height: 1.4; color: var(--muted); }
.memo-list b { color: var(--ink); font-weight: 500; }
.memo-due { white-space: nowrap; }
.notice.memo-note .memo-head { margin: 0 0 4px; font-size: 13px; }
.notice.memo-note .memo-text { color: var(--ink); }
.notice.memo-note .memo-list { margin-top: 6px; }
.notice.memo-note .memo-list b { display: inline; font-size: inherit; margin: 0; font-weight: 500; }
/* After the call, a guest in a plain browser: one quiet line and the bot link. */
.tie { display: grid; justify-items: center; gap: 12px; margin-top: 28px; }
.tie p { max-width: 30ch; color: var(--muted); font-size: 15px; line-height: 1.4; text-wrap: pretty; }
.tie .chip { display: inline-flex; align-items: center; text-decoration: none; background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }

/* Связной, the AI participant. Its face is the brand's drawing — two tin cans on a string — in ink on the soft fill;
   the string trembles while it speaks, and the face gets the same breathing ring as a person. While it listens to
   someone, an ink dot sits on its face. Its words and the others' translated words read under the faces. */
.person.agent .face > svg { width: 46px; height: 46px; stroke-width: 1.5; }
.agent-mark svg, .tile .agent-mark svg { width: 56px; height: 56px; stroke-width: 1.5; }
.icon .string { transform-origin: 50% 50%; }
.person.agent.speaking .icon .string, .tile.speaking .agent-mark .string { animation: twang .32s ease-in-out infinite alternate; }
@keyframes twang { from { transform: translateY(-1.2px) scaleY(.7); } to { transform: translateY(1.4px) scaleY(1.25); } }
.person.agent.listening .face::before {
  content: ''; position: absolute; right: 6px; top: 6px; width: 12px; height: 12px; border-radius: 50%;
  background: var(--ink); box-shadow: 0 0 0 3px var(--soft); animation: rec-breathe 2.4s ease-in-out infinite;
}
/* The orb (web/orb.js): Связной's own face, a pearl that drifts in colour and swells with its voice. It is the face
   itself, so no soft disc behind it and no speaking ring around it; a CSS pearl stands in where WebGL cannot draw.
   Next to it the others' faces are centred on it, each name right under its own face (the rule after the masks). */
.people:has(> .orb) { --orb: 160px; align-items: start; }
.call:has(> .captions, > .coach) .people:has(> .orb) { --orb: 120px; }
.people:has(> .orb) > .person { grid-template-rows: var(--orb) auto; align-items: center; }
.person.agent.orb { width: calc(var(--orb) + 20px); }
.person.agent.orb .face { width: var(--orb); height: var(--orb); background: none; }
.person.agent.orb .face::after, .person.agent.orb .face::before { display: none; }
canvas.orb { display: block; width: 100%; height: 100%; border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, #fff 0 8%, #eeeef6 30%, #dcdfe9 70%, #cfd3df); }
canvas.orb.lit { background: none; border-radius: 0; }
.agent-mark canvas.orb { width: min(46%, 220px); height: auto; aspect-ratio: 1; }
/* Its mute is the orb itself: a hover brings a faint microphone up from its middle, a click mutes or unmutes it. */
.orb-mute {
  appearance: none; border: 0; padding: 0; cursor: pointer; position: absolute; inset: 0; border-radius: 50%;
  background: none; color: rgb(17 17 17 / .55); display: grid; place-items: center;
}
.orb-mute svg { width: 34px; height: 34px; stroke-width: 1.5; opacity: 0; transform: scale(.9);
  transition: opacity .25s var(--ease), transform .25s var(--ease); }
.orb-mute:hover svg, .orb-mute:focus-visible svg { opacity: 1; transform: none; }
.orb-mute:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.orb-mute:active svg { transform: scale(.92); }
.person .role { margin-top: -8px; font-size: 13px; color: var(--muted); max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.person .role.live, .person .role.quiet { display: inline-flex; align-items: center; gap: 6px; font-weight: 500; }
.person .role.live { color: var(--green); }
.person .role.quiet { color: var(--red); }
.person .role.live::before, .person .role.quiet::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.person .role.live::before { animation: rec-breathe 2.4s ease-in-out infinite; }
.person.agent { width: 140px; }

.captions { display: grid; justify-items: center; gap: 8px; width: min(380px, 100%); margin: -8px auto 8px; text-align: center; }
.captions p { margin: 0; text-wrap: pretty; animation: settle .35s var(--ease) both; }
.captions .said {
  padding: 10px 16px; border-radius: 18px; background: var(--soft); color: var(--ink);
  font-size: 16px; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.captions .sub { font-size: 16px; line-height: 1.4; color: var(--ink); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.captions .sub span { color: var(--muted); margin-right: 6px; }
/* With pictures the lines sit between the stage and the controls. */
.call.visual .captions { margin: 8px auto 0; }
/* Words and a hint sit just above the controls (`.over`). On a screen with room they lie over the stage, so the faces or
   pictures keep their place and size whether a hint, a question or subtitles come and go. On a phone they take their
   own room instead and never push the controls off it: the faces close up into one smaller row, still centred,
   pictures give up height, the lines are cut shorter while a hint is showing, and the hint's room keeps one height
   from questions to hints, so the faces move once, when hints are turned on. */
#app:has(> .call) { height: 100dvh; }
.call { min-height: 0; }
.over, .over-in { display: contents; }
.over-in > * { flex: none; }
@media (min-height: 761px), (min-width: 700px) and (min-height: 600px) {
  .call:not(.immersive, .showing) > .over { display: block; position: relative; height: 0; }
  .call:not(.immersive, .showing) .over-in { display: grid; position: absolute; left: 0; right: 0; bottom: 0; }
}
@media (max-height: 760px) and (max-width: 699px), (max-height: 599px) {
  .call:not(.immersive, .showing):has(.coach) .over-in { display: grid; align-content: end; min-height: 168px; }
  .call:has(> .over) .people { flex-wrap: nowrap; align-items: center; gap: 20px; padding: 12px 0; min-height: 0; }
  .call:has(> .over) .person, .call:has(> .over) .person.agent { width: 84px; }
  .call:has(> .over) .face { width: 76px; height: 76px; font-size: 28px; }
  .call:has(> .over) .person.agent .face > svg { width: 38px; height: 38px; }
  .call:has(> .over) .person .role { max-width: 124px; }
  .call:has(> .over) .tile { min-height: 0; }
  .call:has(.coach) .captions .said, .call:has(.coach) .captions .sub { -webkit-line-clamp: 2; }
}
/* A notice about the microphone or the key takes its room from the faces too, and if they still do not fit they scroll:
   the controls never leave a short phone's screen. */
.call .people { min-height: 0; overflow-y: auto; align-content: safe center; }
@media (max-height: 760px) and (max-width: 699px), (max-height: 599px) {
  .call:has(> .notice) .people { gap: 16px 20px; padding: 12px 0; }
  .call:has(> .notice) .person { width: 84px; }
  .call:has(> .notice) .face { width: 76px; height: 76px; font-size: 28px; }
}
@media (max-height: 700px) and (max-width: 699px), (max-height: 599px) {
  .call:has(> .notice) .people { padding: 8px 0; }
  .call:has(> .notice) .person { gap: 6px; }
  .call:has(> .notice) .face { width: 56px; height: 56px; font-size: 22px; }
  .call:has(> .notice) .face::after { inset: -5px; }
  .call:has(> .notice) .person .name { font-size: 13px; }
  .call:has(> .notice) .face .muted { width: 24px; height: 24px; }
  .call:has(> .notice) .face .muted svg { width: 13px; height: 13px; }
  .call:has(> .over) .people { padding: 4px 0; }
  .call:has(> .over) .person { gap: 6px; }
  .call:has(> .over) .face { width: 56px; height: 56px; font-size: 22px; }
  .call:has(> .over) .face::after { inset: -5px; }
  .call:has(> .over) .person.agent .face > svg { width: 30px; height: 30px; }
  .call:has(> .over) .person .name { font-size: 13px; }
  .call:has(> .over) .person .role { display: none; }
  .call:has(> .over) .face .muted { width: 24px; height: 24px; }
  .call:has(> .over) .face .muted svg { width: 13px; height: 13px; }
  .captions .said, .captions .sub { -webkit-line-clamp: 2; }
}
/* A phone held sideways: the faces close up into one row, so their names stay whole and clear of the controls. */
@media (max-height: 480px) {
  .call:not(.visual) .people { flex-wrap: nowrap; align-items: center; gap: 16px; padding: 8px 0; }
  .call:not(.visual) .person { width: 84px; gap: 8px; }
  .call:not(.visual) .face { width: 64px; height: 64px; font-size: 24px; }
}

.ai-menu .ai-ask { min-height: 64px; }
.ai-menu .ai-ask b { display: block; font-weight: 500; }
.ai-menu .ai-ask small { display: block; margin-top: 2px; font-size: 13px; line-height: 1.35; color: var(--muted); }
.ai-menu .ai-ask > span { -webkit-line-clamp: unset; display: block; }
.ai-menu .ai-ask svg { width: 26px; height: 26px; }
.ai-menu .ai-ask > span { white-space: normal; }
.ai-langs { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 8px 8px; }
.ai-langs .lang {
  appearance: none; border: 0; cursor: pointer; height: 40px; padding: 0 14px; border-radius: 20px;
  font: 500 15px/1 Onest, system-ui, sans-serif; color: var(--ink); background: var(--paper); box-shadow: inset 0 0 0 1px var(--line);
  transition: background .2s, color .2s, transform .2s var(--ease);
}
.ai-langs .lang:active { transform: scale(.96); }
.ai-langs .lang[aria-checked="true"] { background: var(--ink); color: var(--paper); box-shadow: none; }
.ai-langs .lang:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* Over a full-screen picture (a video face or someone's camera) the words stay: subtitles on 86% paper, also when the
   controls fade away. */
.call.immersive .over-in > .captions { margin: 0 auto 4px; padding: 0 16px; }
.call.immersive .over-in > .captions p { padding: 8px 14px; border-radius: 16px; background: color-mix(in srgb, var(--paper) 86%, transparent); color: var(--ink); text-shadow: none; }
.call.calm .over-in > .captions { opacity: 1; visibility: visible; }

/* «Подсказки»: the brief, asked in the Связной menu itself, and the hint only you see, above the controls. */
.ai-brief { gap: 10px; padding: 14px; white-space: normal; color: var(--ink); text-align: left; }
.ai-brief-label b { display: block; font-weight: 500; font-size: 16px; }
.ai-brief-label small { display: block; margin-top: 2px; font-size: 13px; color: var(--muted); }
.ai-brief textarea {
  width: 100%; resize: none; padding: 12px 14px; border: 0; border-radius: 14px;
  font: 400 16px/1.4 Onest, system-ui, sans-serif; color: var(--ink); background: var(--soft);
}
.ai-brief textarea::placeholder { color: var(--placeholder); }
.ai-brief textarea:focus { outline: none; box-shadow: inset 0 0 0 1.5px var(--ink); }
.coach {
  display: flex; align-items: flex-start; gap: 4px; width: min(380px, 100%); margin: 0 auto 12px;
  padding: 12px 6px 12px 16px; border-radius: 18px; background: var(--soft); text-align: left;
  animation: rise .3s var(--ease) both;
}
.coach-body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.coach-body p { margin: 0; }
.coach-to { font-size: 13px; line-height: 1.35; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.coach-hint { font-size: 17px; line-height: 1.35; font-weight: 500; color: var(--ink); text-wrap: pretty; animation: settle .35s var(--ease) both; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.coach-off {
  appearance: none; border: 0; background: none; cursor: pointer; flex: none;
  width: 32px; height: 32px; margin-top: -4px; border-radius: 16px; display: grid; place-items: center; color: var(--muted);
}
.coach-off:hover, .coach-off:focus-visible { color: var(--ink); background: var(--paper); outline: none; }
.coach-off svg { width: 16px; height: 16px; }
.coach-answers { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.coach-answers .chip { height: 36px; padding: 0 14px; font-size: 14px; background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.coach-answers .chip:hover { box-shadow: inset 0 0 0 1px var(--ink); }
.coach-answers .chip.quiet { box-shadow: none; color: var(--muted); padding: 0 8px; }
.call.visual .coach { margin: 8px auto 0; }
/* Over a full-screen picture the hint stays too, like the subtitles. */
.call.immersive .over-in > .coach { margin: 0 auto 4px; background: color-mix(in srgb, var(--paper) 86%, transparent); color: var(--ink); text-shadow: none; }
.call.calm .over-in > .coach { opacity: 1; visibility: visible; }

/* ——— Реакции: a bubble over the call, a knock on a face, funny voices in the microphone's menu ——— */
/* Emoji are Noto's vector pictures (fun.js emojiSrc), sharp at any size and the same on every phone. */
.emoji, .fx-emoji, .fx-p img { display: block; user-select: none; pointer-events: none; }
/* A round smile floating over the call like a chat head, stuck to a side: flat paper on a hairline, no shadow, a little dim
   so it never pulls the eye from a face. It takes no room from the faces; it is dragged anywhere and springs back to the
   nearer side (app.js placeBubble keeps it between the header and the controls and off your corner picture). */
.bubble {
  position: fixed; z-index: 4; top: 46%; right: calc(max(8px, env(safe-area-inset-right)) + var(--chat-w, 0px)); width: 52px; height: 52px;
  opacity: .72; transition: opacity .3s var(--ease), transform .3s var(--spring);
}
.bubble.l { right: auto; left: max(8px, env(safe-area-inset-left)); }
.bubble.open, .bubble:hover, .bubble:focus-within, .bubble.dragging { opacity: 1; }
.bubble.dragging { z-index: 13; }
.bubble.dragging .rail-fold { cursor: grabbing; }
.bubble.dragging :is(.rail-fold, .rail-shape) { scale: 1.08; }
.bubble.settling { transition: translate .5s cubic-bezier(.34, 1.36, .64, 1), opacity .3s var(--ease); }
/* A menu or popover of the call takes the space: the bubble steps aside until it closes. */
.call:has(.mic-menu, .rec-pop, .lock-pop) .bubble { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .2s var(--ease), visibility 0s .2s; }
/* One shape: the bubble itself is a 52px capsule that grows from its own place (Viber's chat head). Closed it is the round
   smile; open it stretches up (down when the room above is short, app.js placeBubble) to hold the emoji, the switch to the
   sounds right by the bubble, and the bubble's end, now a ×. A spring that never overshoots the edge it stops at. */
.bubble { --spring: linear(0, 0.079, 0.237, 0.404, 0.552, 0.672, 0.765, 0.834, 0.884, 0.92, 0.945, 0.962, 0.975, 0.983, 0.988, 0.992, 1); }
.rail-shape {
  position: absolute; left: 0; bottom: 0; width: 52px; height: 52px; border-radius: 26px; overflow: hidden;
  background: var(--paper); box-shadow: 0 0 0 1px var(--line); transform-origin: 26px calc(100% - 26px); transition: height .3s var(--spring), scale .25s var(--ease);
}
.bubble.down .rail-shape { bottom: auto; top: 0; transform-origin: 26px 26px; }
.bubble.open .rail-shape { height: var(--h, 52px); transition-duration: .38s, .25s; }
/* Short of room both ways, the open bubble moves along as little as it must (app.js placeBubble, --move). */
.bubble.open { transform: translateY(var(--move, 0px)); transition-duration: .3s, .38s; }
.rail-fold {
  position: relative; appearance: none; border: 0; background: none; cursor: pointer; width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center; color: var(--ink); touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
  transition: transform .25s var(--ease), scale .25s var(--ease);
}
.rail-fold .icon { grid-area: 1 / 1; transition: opacity .25s var(--ease), rotate .4s var(--ease), scale .4s var(--ease); }
.rail-fold .rail-close { opacity: 0; rotate: -90deg; scale: .6; color: var(--muted); }
.bubble.open .rail-fold .rail-smile { opacity: 0; rotate: 90deg; scale: .6; }
.bubble.open .rail-fold .rail-close { opacity: 1; rotate: 0deg; scale: 1; }
/* Over pictures it is frosted, still without a shadow. */
.call.visual .rail-shape { background: color-mix(in srgb, var(--paper) 88%, transparent); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); }
/* What the capsule holds sits beyond the bubble's end, inside the shape, so the growing shape uncovers it. */
.rail-body {
  position: absolute; left: 4px; bottom: 52px; width: 44px; padding-top: 4px; display: flex; flex-direction: column; align-items: center;
  visibility: hidden; transition: visibility 0s .3s;
}
.bubble.down .rail-body { bottom: auto; top: 52px; padding: 0 0 4px; flex-direction: column-reverse; }
.bubble.open .rail-body { visibility: visible; transition: visibility 0s; }
/* The emoji come in one by one from the bubble outwards, rising out of it (falling, when it opens down). */
.rail-item, .rail-swap { opacity: 0; translate: 0 8px; scale: .7; }
.bubble.down .rail-item, .bubble.down .rail-swap { translate: 0 -8px; }
.bubble.open .rail-item, .bubble.open .rail-swap {
  opacity: 1; translate: 0 0; scale: 1;
  transition: transform .25s var(--ease), background .2s, opacity .2s var(--ease) var(--wait), translate .34s var(--ease) var(--wait), scale .34s var(--ease) var(--wait);
}
.rail-swap { --wait: 50ms; }
.rail-item { --wait: calc(80ms + min(var(--n) - 1 - var(--i), 8) * 24ms); }
.bubble.down .rail-item { --wait: calc(80ms + min(var(--i), 8) * 24ms); }
.rail-list { display: grid; justify-items: center; gap: 2px; max-height: var(--list, min(42vh, 380px)); overflow-y: auto; scrollbar-width: none; overscroll-behavior: contain; }
.rail-list::-webkit-scrollbar { display: none; }
.rail-item, .rail-swap {
  appearance: none; border: 0; background: none; cursor: pointer; width: 44px; height: 44px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: var(--ink); transition: transform .25s var(--ease), background .2s, opacity .12s, translate .12s, scale .12s;
}
.rail-item .emoji { width: 28px; height: 28px; }
.rail-item svg, .rail-swap svg, .rail-fold svg { width: 20px; height: 20px; }
.rail-fold svg { width: 22px; height: 22px; }
.rail-item:hover, .rail-swap:hover { background: var(--soft); }
.rail-item:active, .rail-swap:active, .rail-fold:active { transform: scale(.88); transition-duration: .08s; }
.rail-item:focus-visible, .rail-swap:focus-visible, .rail-fold:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.rail-item:focus-visible, .rail-swap:focus-visible { outline-offset: -2px; }
.rail-hush[aria-pressed="true"] { color: var(--red); }
.rail-swap { position: relative; margin-top: 5px; }
.rail-swap::before { content: ''; position: absolute; top: -3px; left: 10px; right: 10px; height: 1px; background: var(--line); }
.bubble.down .rail-swap { margin: 0 0 5px; }
.bubble.down .rail-swap::before { top: auto; bottom: -3px; }
.call.immersive > .bubble { position: fixed; z-index: 3; }
.call.immersive .rail-shape { background: rgb(20 20 20 / .42); box-shadow: inset 0 0 0 1px rgb(255 255 255 / .12); }
.call.immersive .rail-item, .call.immersive .rail-swap, .call.immersive .rail-fold, .call.immersive .rail-fold .rail-close { color: #fff; }
.call.immersive .rail-item:hover, .call.immersive .rail-swap:hover { background: rgb(255 255 255 / .14); }
.call.immersive .rail-swap::before { background: rgb(255 255 255 / .16); }
/* Reduced motion: no morph, the capsule is simply there or not. */
@media (prefers-reduced-motion: reduce) {
  .bubble, .bubble.open, .bubble.settling, .rail-shape, .bubble.open .rail-shape, .rail-body, .rail-fold .icon, .rail-item, .rail-swap, .bubble.open .rail-item, .bubble.open .rail-swap { transition-duration: .01s !important; transition-delay: 0s !important; }
  .rail-item, .rail-swap { translate: none; scale: none; }
}
/* «Настройки звука»: the microphone and the output as two dropdowns, a label beside each; the noise and the voice as rows of
   quiet chips; a hairline between the groups. Short enough on a computer to need no scrolling. */
.mic-menu.audio-menu { width: min(372px, 100%); }
.audio-menu > * + * { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line); }
.menu-picks { display: grid; gap: 4px; padding: 4px 0; }
.menu-picks > [role="listbox"] { display: grid; gap: 2px; }
.menu-picks > [role="listbox"] + [role="listbox"] { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--line); }
.menu-pick { display: grid; grid-template-columns: 104px minmax(0, 1fr); align-items: center; gap: 4px; padding-right: 4px; }
.menu-pick .menu-label { padding: 0 0 0 14px; }
.pick { position: relative; display: block; min-width: 0; }
.pick select {
  appearance: none; -webkit-appearance: none; width: 100%; height: 40px; margin: 0; padding: 0 34px 0 12px; border: 0; border-radius: 12px;
  font: 400 15px/1 Onest, system-ui, sans-serif; color: var(--ink); background: var(--soft); cursor: pointer;
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden; transition: background .2s;
}
.pick select:hover { background: color-mix(in srgb, var(--ink) 8%, var(--soft)); }
.pick select:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.pick .icon { position: absolute; right: 10px; top: 50%; width: 16px; height: 16px; translate: 0 -50%; color: var(--muted); pointer-events: none; }
.mic-menu .menu-chips { padding: 2px 8px 6px; display: flex; flex-wrap: wrap; gap: 6px; }
.mic-menu .menu-chips .lang { height: 36px; padding: 0 12px; font-size: 14px; }
.mic-menu .menu-chips .lang[disabled] { opacity: .4; cursor: default; }
/* Someone's face can be knocked on. */
.people .person.knock .face { cursor: pointer; }

/* What everyone sees: a layer over the whole call that never takes a tap. */
#fx { position: fixed; inset: 0; z-index: 60; pointer-events: none; overflow: hidden; contain: strict; }
.fx-bloom {
  position: absolute; inset: 0; opacity: 0;
  background: radial-gradient(120% 75% at 50% 44%, color-mix(in srgb, var(--c) 34%, transparent), color-mix(in srgb, var(--c) 10%, transparent) 52%, transparent 78%);
}
.fx-hero { position: absolute; left: 50%; top: 44%; display: grid; justify-items: center; gap: 14px; will-change: transform, opacity; }
.fx-emoji { width: calc(clamp(104px, 32vw, 176px) * 1.28); height: auto; aspect-ratio: 1; filter: drop-shadow(0 14px 26px rgb(0 0 0 / .16)); }
.fx-name {
  padding: 7px 14px; border-radius: 17px; font-size: 15px; font-weight: 500; white-space: nowrap; color: var(--ink);
  background: color-mix(in srgb, var(--paper) 90%, transparent); box-shadow: 0 0 0 1px var(--line), 0 10px 24px -12px var(--shadow);
}
.fx-p { position: absolute; top: 100%; will-change: transform, opacity; }
.fx-p img { width: 100%; height: auto; }
.fx-bit { margin: -7px 0 0 -4px; border-radius: 2px; }
.fx-pill {
  position: absolute; left: 50%; top: calc(max(24px, env(safe-area-inset-top)) + 64px); max-width: calc(100vw - 48px);
  padding: 9px 16px; border-radius: 20px; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--ink); background: var(--paper); box-shadow: 0 0 0 1px var(--line), 0 12px 30px -12px var(--shadow);
}

/* ——— The landing (the start page of everyone's Связной for a stranger): the call's paper and ink at page scale ——— */
[data-state="landing"] #app {
  max-width: 1120px; padding: max(20px, env(safe-area-inset-top)) max(24px, env(safe-area-inset-right)) max(24px, env(safe-area-inset-bottom)) max(24px, env(safe-area-inset-left));
}
.land-top { display: flex; align-items: center; min-height: 44px; }
.land-mark { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; letter-spacing: -0.01em; }
.land-mark .icon { width: 26px; height: 26px; }
.land-hero { display: flex; flex-direction: column; align-items: center; text-align: center; padding-top: clamp(8px, 3vh, 40px); }
/* The drawing over rings of ink dots that spread from it (web/landing.js); a hole behind the cans keeps the line clean. */
.land-art { position: relative; width: 100%; max-width: 760px; height: clamp(220px, min(34vw, 34vh), 400px); display: grid; place-items: center; margin-bottom: clamp(8px, 2vw, 24px); }
.land-art img { position: relative; width: clamp(196px, 44%, 440px); height: auto; filter: var(--art-filter); mix-blend-mode: multiply; user-select: none; -webkit-user-drag: none; }
.land-signal {
  position: absolute; inset: 0; color: var(--ink); opacity: 0; transition: opacity 1.6s var(--ease);
  -webkit-mask: radial-gradient(ellipse 50% 50% at 50% 50%, transparent 36%, #000 58%, #000 70%, transparent 100%);
  mask: radial-gradient(ellipse 50% 50% at 50% 50%, transparent 36%, #000 58%, #000 70%, transparent 100%);
}
.land-signal[data-live] { opacity: 1; }
.land-hero h1 { font-size: clamp(34px, 6vw, 68px); line-height: 1.04; letter-spacing: -0.035em; max-width: 16ch; }
.land-hero .lead { font-size: clamp(17px, 1.6vw, 20px); max-width: 36ch; margin-top: clamp(14px, 1.6vw, 20px); }
.land-actions { display: grid; gap: 12px; width: 100%; max-width: 360px; margin-top: clamp(28px, 3.4vw, 40px); }
.land-actions .button { padding: 0 24px; white-space: nowrap; }
.land-hero .fine { margin-top: 16px; max-width: 44ch; }
.land-points { list-style: none; padding: 0; display: grid; gap: 28px; margin: clamp(56px, 8vw, 104px) 0 0; }
.land-points li { border-top: 1px solid var(--line); padding-top: 18px; }
.land-points h2 { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.3; }
.land-points p { color: var(--muted); font-size: 15px; line-height: 1.5; margin-top: 6px; max-width: 40ch; text-wrap: pretty; }
.land-foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 24px; margin-top: clamp(48px, 7vw, 88px); padding-top: 18px; border-top: 1px solid var(--line); color: var(--muted); font-size: 14px; }
.land-foot a { color: var(--muted); text-decoration: underline; text-decoration-color: currentColor; text-underline-offset: 4px; transition: color .2s; }
.land-foot a:hover, .land-foot a:focus-visible { color: var(--ink); }
@media (hover: hover) { .land-actions .button:hover { opacity: .88; } .land-actions .button.quiet:hover { opacity: 1; box-shadow: inset 0 0 0 1px var(--ink); } }
@media (min-width: 720px) {
  .land-actions { display: flex; justify-content: center; max-width: none; }
  .land-actions .button { width: auto; min-width: 248px; }
  .land-points { grid-template-columns: repeat(2, 1fr); gap: 40px 56px; }
}
@media (min-width: 1024px) { .land-points { grid-template-columns: repeat(4, 1fr); gap: 40px; } }
@media (prefers-color-scheme: dark) { .land-art img { mix-blend-mode: screen; } }
/* ——— Встречи (web/meetings.js): the list, the form, a meeting before its time ——— */
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.stage.top { justify-content: flex-start; padding-top: 8vh; }
.link .icon.inline { margin-right: .35em; }
.links { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 16px; margin: 0; }
.link.danger { color: var(--red); text-decoration-color: color-mix(in srgb, var(--red) 35%, transparent); }
.link:hover { color: var(--ink); }
.link.danger:hover { color: var(--red); text-decoration-color: currentColor; }
.meet-group { align-self: stretch; text-align: left; font-size: 15px; font-weight: 600; color: var(--muted); margin-top: 24px; }
.meet-list h1 + .meet-group { margin-top: 20px; }
.meet-rows { list-style: none; padding: 0; align-self: stretch; text-align: left; border-top: 1px solid var(--line); }
.meet-rows li { border-bottom: 1px solid var(--line); }
.meet-row {
  display: grid; grid-template-columns: 1fr 20px; column-gap: 12px; align-items: center; min-height: 64px; padding: 12px 2px;
  color: var(--ink); text-decoration: none; border-radius: 12px; transition: background-color .2s;
}
.meet-row:hover { background: var(--soft); }
.meet-row:active { background: var(--soft); }
.meet-row-title { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.meet-row-when { grid-row: 2; font-size: 15px; color: var(--muted); }
.meet-row-go { grid-row: 1 / 3; grid-column: 2; width: 20px; height: 20px; color: var(--placeholder); }
.meet-rows.past .meet-row-title { color: var(--muted); font-weight: 400; }
/* Google Календарь on /m (web/meetings.js): rows in the list's own hairlines; a button row reads as a link row. */
button.meet-row { appearance: none; width: 100%; background: none; border: 0; font: inherit; text-align: left; cursor: pointer; }
button.meet-row:disabled { cursor: progress; opacity: .6; }
button.meet-row:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.meet-row-when { text-wrap: pretty; }
.meet-cal-on { display: grid; min-height: 64px; padding: 12px 2px; align-content: center; }
.meet-cal-on .meet-row-when { grid-row: auto; overflow-wrap: anywhere; }
.meet-switch { grid-template-columns: 1fr 40px; }
.meet-switch .meet-row-title { white-space: normal; line-height: 1.3; }

/* ——— Звонки (web/calls.js): past calls, a call's card, its transcript and note ——— */
.calls-rows .meet-row-title, .call-actions .meet-row-title { color: var(--ink); }
.call-card, .call-read { align-items: stretch; text-align: left; max-width: 34rem; width: 100%; margin: 0 auto; }
.call-card h1, .call-read h1 { text-wrap: balance; }
.call-when { max-width: none; margin-top: -4px; }
.call-card .meet-group { margin-top: 28px; margin-bottom: -2px; }
.call-tldr { line-height: 1.5; text-wrap: pretty; }
.call-list { margin: 0; padding-left: 1.1em; display: grid; gap: 8px; line-height: 1.45; }
.call-list li::marker { color: var(--placeholder); }
.call-list li.done { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--placeholder); }
.call-due { color: var(--muted); white-space: nowrap; }
.call-actions { margin-top: 28px; }
.call-action { min-height: 56px; }
.call-action .meet-row-title { grid-row: 1 / 3; }
.call-action .meet-row-go { color: var(--muted); }
.call-card .fine, .call-read .fine { text-align: left; }
.call-none, .call-state { margin-top: 20px; }
.call-text { display: grid; gap: 12px; margin-top: 16px; line-height: 1.55; overflow-wrap: anywhere; }
.call-text p { margin: 0; }
.call-text b { font-weight: 600; }
.call-read-h { font-size: 19px; font-weight: 600; margin: 16px 0 0; letter-spacing: -0.01em; }
.meet-switch .switch { grid-row: 1 / 3; grid-column: 2; }
.meet-switch[aria-checked="true"] .switch { background: var(--ink); }
.meet-switch[aria-checked="true"] .switch::after { transform: translateX(16px); }
.meet-cal-note { align-self: stretch; text-align: left; margin-top: 12px; }
.meet-cal-note + .meet-cal-note { margin-top: 0; }
.meet-cal-note .link { padding: 8px 0; }
.meet-cal-error { color: var(--red); }
.meet-form { justify-content: flex-start; align-items: stretch; gap: 18px; padding-top: 4vh; }
.meet-form h1 { margin-bottom: 4px; }
.meet-form fieldset { border: 0; padding: 0; min-width: 0; transition: opacity .2s; }
.meet-form fieldset:disabled { opacity: .38; }
.meet-when { display: grid; grid-template-columns: 1.3fr 1fr; gap: 12px; }
.meet-form .field input[type="date"], .meet-form .field input[type="time"] { width: 100%; min-width: 0; -webkit-appearance: none; appearance: none; text-align: left; }
.meet-form .field input::-webkit-date-and-time-value { text-align: left; }
.field textarea {
  border-radius: 16px; border: 1px solid var(--line); padding: 14px 18px; resize: vertical; min-height: 92px;
  font: 400 17px/1.4 Onest, system-ui, sans-serif; color: var(--ink); background: var(--paper); transition: border-color .2s;
}
.field textarea:focus { outline: none; border-color: var(--ink); }
.field textarea::placeholder { color: var(--placeholder); }
.field legend { padding: 0; margin-bottom: 8px; }
.meet-untimed { display: flex; align-items: center; gap: 12px; text-align: left; font-size: 16px; cursor: pointer; margin-top: -4px; }
.meet-untimed input { width: 22px; height: 22px; margin: 0; flex: none; accent-color: var(--ink); }
.meet-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.meet-chips label { position: relative; }
.meet-chips input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.meet-chips span {
  display: inline-flex; align-items: center; height: 40px; padding: 0 16px; border-radius: 20px; font-size: 15px; font-weight: 500;
  box-shadow: inset 0 0 0 1px var(--line); transition: background-color .2s, color .2s, box-shadow .2s;
}
.meet-chips input:checked + span { background: var(--ink); color: var(--paper); box-shadow: none; }
.meet-chips input:focus-visible + span { outline: 2px solid var(--ink); outline-offset: 3px; }
.meet-tz { text-align: left; margin-top: -4px; }
.meet-about { width: 100%; max-width: 360px; margin-top: 8px; padding: 14px 16px; border-radius: 18px; background: var(--soft); text-align: left; font-size: 15px; line-height: 1.45; white-space: pre-line; overflow-wrap: anywhere; }
.meet-own { display: flex; justify-content: center; align-items: center; gap: 4px; }
.meet-own span { color: var(--line); }
/* A meeting before its time (Eugene, 2026-11-04): a calendar's event card. The day tile and the title side by side, the
   facts as the list's hairline rows with a muted icon each, one «Зайти» in the dock, pale until the room opens. */
.meet-page { align-items: stretch; text-align: left; max-width: 34rem; width: 100%; margin: 0 auto; gap: 0; }
.meet-page .org { text-align: left; margin-bottom: 12px; }
.meet-head { display: grid; grid-template-columns: 56px 1fr; gap: 16px; align-items: start; }
.meet-day { display: grid; justify-items: center; align-content: center; width: 56px; height: 60px; border-radius: 16px; box-shadow: inset 0 0 0 1px var(--line); line-height: 1; }
.meet-day span { font-size: 12px; font-weight: 600; color: var(--red); text-transform: lowercase; letter-spacing: .02em; }
.meet-day b { font-size: 26px; font-weight: 600; margin-top: 4px; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.meet-head-text { min-width: 0; }
.meet-page h1 { font-size: 26px; line-height: 1.15; margin: 0; text-wrap: balance; overflow-wrap: anywhere; }
.meet-time { margin: 6px 0 0; font-size: 17px; color: var(--ink); font-variant-numeric: tabular-nums; }
.meet-left { margin: 2px 0 0; font-size: 15px; color: var(--muted); }
.meet-left .nowrap { white-space: nowrap; }
.meet-theirs { margin: 14px 0 0; display: flex; align-items: center; gap: 6px; }
.meet-page .meet-about { max-width: none; margin-top: 20px; }
.meet-facts { margin-top: 24px; }
.meet-fact { display: grid; grid-template-columns: 24px 1fr auto; column-gap: 14px; align-items: start; min-height: 64px; }
.meet-fact-icon { width: 22px; height: 22px; margin-top: 13px; color: var(--muted); }
.meet-fact-main { display: grid; gap: 2px; min-width: 0; padding: 12px 0; color: var(--ink); text-align: left; }
button.meet-fact-main { appearance: none; background: none; border: 0; font: inherit; cursor: pointer; border-radius: 12px; }
button.meet-fact-main:focus-visible, .meet-fact-end:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.meet-fact .meet-row-when { grid-row: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.meet-fact .meet-switch { grid-template-columns: 1fr 40px; column-gap: 12px; grid-column: 2 / 4; align-items: center; }
.meet-fact .meet-switch .meet-row-title, .meet-fact .meet-switch .meet-row-when { grid-column: 1; }
.meet-fact-end { appearance: none; border: 0; background: none; cursor: pointer; width: 44px; height: 44px; margin: 10px -10px 0 0; border-radius: 22px; display: grid; place-items: center; color: var(--muted); transition: background-color .2s, color .2s; }
.meet-fact-end .icon { width: 20px; height: 20px; }
.meet-fact-end:hover { background: var(--soft); color: var(--ink); }
.meet-cal { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.meet-cal .chip, .meet-cal .chip + .chip { display: inline-flex; align-items: center; height: 36px; padding: 0 14px; font-size: 14px; text-decoration: none; background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }
.meet-cal .chip:hover { background: var(--soft); }
.meet-page .chat-link { align-self: flex-start; margin-top: 20px; }
.button:disabled.quiet { color: var(--muted); cursor: default; }
/* ——— «Звонок для близких»: the guest's whole call is their face, their name and «Завершить» ——— */
.call.simple { text-align: center; }
.simple-who { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 24px 0; }
.simple-face {
  position: relative; width: min(52vw, 196px); aspect-ratio: 1; border-radius: 50%; margin-bottom: 18px;
  display: grid; place-items: center; background: var(--soft);
  font-size: 76px; font-weight: 500; letter-spacing: -0.02em;
}
.simple-face::after {
  content: ''; position: absolute; inset: -9px; border-radius: inherit; border: 2px solid var(--ink); opacity: 0;
  transform: scale(calc(.96 + var(--level, 0) * .1)); transition: opacity .25s, transform .12s linear;
}
.simple-face.speaking::after { opacity: 1; }
/* Their camera on: the picture as large as the screen allows, still the only thing to look at. */
.simple-face.video { width: 100%; aspect-ratio: 3 / 4; max-height: min(56dvh, calc(100dvh - 420px)); border-radius: 28px; background: #000; overflow: hidden; }
.simple-face.video::after { display: none; }
.simple-face video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.simple h1 { font-size: 40px; line-height: 1.1; }
.simple-status { font-size: 22px; color: var(--muted); }
.simple-hint { font-size: 22px; line-height: 1.35; max-width: 16em; margin: 0 auto 28px; text-wrap: balance; animation: rise .3s var(--ease) both; }
.simple-hint b { font-weight: 600; }
.simple-fix { display: grid; gap: 16px; margin-bottom: 28px; }
.simple-fix .simple-hint { margin-bottom: 0; }
.simple-fix ol { list-style: none; padding: 0; counter-reset: step; display: grid; gap: 12px; text-align: left; font-size: 20px; line-height: 1.35; }
.simple-fix li { counter-increment: step; display: grid; grid-template-columns: 36px 1fr; gap: 12px; align-items: start; }
.simple-fix li::before { content: counter(step); width: 36px; height: 36px; border-radius: 50%; background: var(--soft); display: grid; place-items: center; font-weight: 600; font-size: 18px; }
.simple-fix .button { height: 64px; border-radius: 32px; font-size: 20px; }
.button.end { flex: none; height: 76px; border-radius: 38px; background: var(--red); color: #fff; font-size: 24px; font-weight: 600; margin-bottom: 12px; }
.button.end svg { width: 30px; height: 30px; }
/* Their own camera: one big quiet button, and while it is on, they see themselves small in the top left corner. */
.button.simple-cam { flex: none; height: 64px; border-radius: 32px; font-size: 20px; margin-bottom: 12px; }
.button.simple-cam svg { width: 26px; height: 26px; }
.simple-me { position: absolute; z-index: 2; top: max(16px, env(safe-area-inset-top)); left: 16px; width: 96px; aspect-ratio: 3 / 4; border-radius: 16px; overflow: hidden; background: #000; box-shadow: 0 6px 20px rgb(0 0 0 / .18); }
.simple-me video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }
.simple-rec { position: absolute; top: max(16px, env(safe-area-inset-top)); right: 20px; display: inline-flex; align-items: center; gap: 8px; font-size: 15px; color: var(--muted); }
/* The browser would not play sound without a touch: then the whole screen is that one touch. */
.hear-all {
  appearance: none; border: 0; cursor: pointer; position: fixed; inset: 0; z-index: 30;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 24px; padding: 32px;
  background: var(--paper); color: var(--ink); font: 600 34px/1.2 Onest, system-ui, sans-serif; text-wrap: balance;
  animation: enter .4s var(--ease) both;
}
.hear-all svg { width: 56px; height: 56px; }
.hear-all span { max-width: 11em; }
/* Alone in the call: the link goes out from here. «Поделиться» in ink, «Скопировать ссылку» outlined beside it (under it
   when the two do not fit on one line), and the address the link is on in one muted line. Reactions wait until someone
   is there to see them, so nothing sits over these. */
.share-call { display: grid; gap: 8px; margin: 0 0 12px; animation: settle .45s var(--ease) both; }
.share-row { display: flex; flex-wrap: wrap; gap: 8px; }
.share-row .button { flex: 1 0 auto; width: auto; height: 52px; border-radius: 26px; padding: 0 22px; font-size: 16px; white-space: nowrap; }
.share-row .button svg { width: 18px; height: 18px; }
.share-at { color: var(--muted); font-size: 13px; line-height: 1.3; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* «Ещё» in the call, compact (2026-11-01): four quick tiles on soft fill — Игры, Маска, Голос, the link — the one that is
   on (a game, a mask, a voice) in ink; under a hairline one-line rows, an icon on the left and what is on at the end. */
.more-root { padding: 10px; gap: 0; }
.more-tiles { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 8px; }
.more-tile {
  appearance: none; border: 0; cursor: pointer; min-height: 72px; padding: 12px 4px 10px; border-radius: 16px;
  background: var(--soft); color: var(--ink); display: grid; justify-items: center; align-content: center; gap: 6px;
  font: 500 13px/1.2 Onest, system-ui, sans-serif; transition: background .2s var(--ease), color .2s var(--ease), transform .15s var(--ease);
}
.more-tile svg { width: 22px; height: 22px; }
.more-tile > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.more-tile:hover { background: color-mix(in oklab, var(--soft), var(--ink) 6%); }
.more-tile:active { transform: scale(.96); }
.more-tile:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.more-tile[aria-pressed="true"] { background: var(--ink); color: var(--paper); }
.more-rows { display: grid; gap: 2px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); }
.more-row { min-width: 0; justify-content: flex-start; gap: 14px; padding: 10px 12px; }
.more-row > svg { width: 20px; height: 20px; color: var(--muted); }
.more-row > span:not(.switch) { flex: 0 1 auto; min-width: 0; display: block; white-space: normal; text-wrap: balance; }
.more-row > small { flex: 1 1 0; min-width: 0; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; color: var(--muted); }
.more-row > .more-go { width: 16px; height: 16px; margin-left: -8px; }
.more-row > .switch { margin-left: auto; }
.more-row[role="switch"][aria-checked="true"] .switch { background: var(--ink); }
.more-row[role="switch"][aria-checked="true"] .switch::after { transform: translateX(16px); }
/* Masks (experiment): «Маска» in «Ещё» opens seven little 3D heads and «Без маски», four to a row; the one you wear has an
   ink ring. In the call a masked face drops its soft circle and grows to the orb's size; the mask's own mouth shows who
   talks, so the breathing ring stays off. */
.mask-menu { padding: 14px 10px 12px; }
.mask-head { display: grid; gap: 2px; padding: 0 6px 10px; text-align: center; }
.mask-head b { font-weight: 600; font-size: 17px; color: var(--ink); }
.mask-head small { font-size: 13px; line-height: 1.35; color: var(--muted); text-wrap: balance; }
.mask-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px 2px; }
.mask-pick {
  appearance: none; border: 0; background: none; cursor: pointer; padding: 0; display: grid; justify-items: center; gap: 4px;
  font: 400 12px/1.2 Onest, system-ui, sans-serif; color: var(--muted);
}
.mask-pick img, .mask-pick .mask-none {
  width: 60px; height: 60px; border-radius: 50%; background: var(--soft); display: grid; place-items: center;
  transition: box-shadow .2s var(--ease), transform .2s var(--ease);
}
.mask-pick .mask-none { font-size: 22px; font-weight: 500; color: var(--ink); }
.mask-sub { grid-column: 1 / -1; margin: 6px 0 -2px; text-align: center; font-size: 13px; color: var(--muted); }
.mask-pick > span:last-child { max-width: 100%; text-align: center; text-wrap: balance; }
.mask-pick:hover img, .mask-pick:focus-visible img { transform: scale(1.06); }
.mask-pick:focus-visible { outline: none; }
.mask-pick:focus-visible > :first-child { box-shadow: 0 0 0 2px var(--ink); }
.mask-pick[aria-pressed="true"] { color: var(--ink); }
.mask-pick[aria-pressed="true"] > :first-child { box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink); }
/* «Голос» in «Ещё»: the masks' popover with the voices' emoji on soft circles, the radio's ink ring on the one you speak
   in, and the probe under a hairline; while it listens, its row fills with soft from the left over the three seconds (each re-render picks the fill up where it was). */
.mask-pick[aria-checked="true"] { color: var(--ink); }
.mask-pick[aria-checked="true"] > :first-child { box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink); }
.mask-pick[disabled] { opacity: .4; cursor: default; }
.mask-pick .voice-face {
  width: 60px; height: 60px; border-radius: 50%; background: var(--soft); display: grid; place-items: center;
  transition: box-shadow .2s var(--ease);
}
.voice-face .emoji { width: 34px; height: 34px; transition: transform .2s var(--ease); }
.mask-pick:not([disabled]):hover .voice-face .emoji, .mask-pick:focus-visible .voice-face .emoji { transform: scale(1.1) rotate(-6deg); }
.voice-menu .mask-grid { padding-bottom: 12px; margin-bottom: 6px; border-bottom: 1px solid var(--line); }
.voice-probe { position: relative; isolation: isolate; overflow: hidden; width: 100%; }
.voice-probe[data-state="rec"]::after {
  content: ''; position: absolute; inset: 0; z-index: -1; background: var(--soft); transform-origin: left;
  animation: probe-fill 3s linear both; animation-delay: var(--at, 0s);
}
@keyframes probe-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) { .voice-probe[data-state="rec"]::after { animation: none; } }
.people:has(> .masked) { --orb: 160px; align-items: start; }
.people:has(> .masked) > .person { grid-template-rows: var(--orb) auto; align-items: center; }
/* A plain face next to an orb or a mask keeps its name right under it (2026-10-31: in a row as tall as the mask, «Аня»
   hung 30 px below her circle); the whole person is centred on the row, so the face is centred on the big ones. */
.people:has(> .masked, > .orb) > .person:not(.masked, .orb) { grid-template-rows: none; align-self: center; }
.person.masked { width: calc(var(--orb) + 20px); }
.person.masked .face { width: var(--orb); height: var(--orb); background: none; }
.person.masked .face::after { display: none; }
canvas.mask { width: 100%; height: 100%; display: block; }
.tile .initial.masked { background: none; width: clamp(96px, 62cqmin, 300px); }
/* «Вы — … · Изменить»: the name for calls, edited in place. */
.me-edit { display: grid; gap: 8px; }
/* The first call's two tips: a quiet line over the controls, one thought at a time. */
.tip { text-align: center; color: var(--muted); font-size: 15px; line-height: 1.4; max-width: 30ch; margin: 0 auto 4px; text-wrap: balance; animation: settle .45s var(--ease) both; }

/* ——— The call's chat (web/chat.js) ———
   The live's sheet (public/live.css) for a call, as tall as what it holds: on a phone it stands on the bottom edge (on the
   keyboard when it is up: --vvh, --vvt from visualViewport) and grows with the messages up to 68% of the screen (all but
   the header's strip with the keyboard up), then scrolls; from 900px it is a card in the bottom right corner growing up
   to the top, and the call makes room for it. web/chat.js eases each change of its height. Runs of messages under
   a name; a reply quotes on soft fill; reactions are soft-fill chips (yours ringed in ink); a tap opens a message's
   actions under it. Closed, a quiet paper card above the controls shows what came in, without a sound. */
.ch .visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
#toast { z-index: 50; }
.control > button { position: relative; }
.ch-badge {
  position: absolute; top: -2px; right: -2px; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px;
  background: var(--ink); color: var(--paper); font: 600 12px/22px Onest, system-ui, sans-serif; font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--paper); animation: settle .3s var(--ease) both;
}
.control > button[aria-pressed="true"] .ch-badge { background: var(--paper); color: var(--ink); box-shadow: 0 0 0 2px var(--ink); }
.ch-sheet {
  position: fixed; z-index: 40; left: 0; right: 0; top: calc(var(--vvt, 0px) + var(--vvh, 100dvh)); translate: 0 -100%;
  max-height: min(calc(var(--vvh, 100dvh) - env(safe-area-inset-top) - 96px), 68svh);
  display: flex; flex-direction: column; overflow: hidden; background: var(--paper); border-radius: 24px 24px 0 0;
  box-shadow: 0 0 0 1px var(--line), 0 -16px 40px -20px var(--shadow);
  padding: 0 env(safe-area-inset-right) 0 env(safe-area-inset-left);
  animation: ch-up .32s var(--ease) both;
}
@keyframes ch-up { from { opacity: 0; transform: translateY(24px); } }
.ch-sheet[hidden] { display: none; }
@media (min-width: 900px) {
  .ch-sheet { left: auto; right: 16px; top: auto; bottom: 16px; translate: none; max-height: calc(100dvh - 32px); width: 380px; padding: 0; border-radius: 22px; box-shadow: 0 0 0 1px var(--line), 0 20px 48px -16px var(--shadow); animation-name: menu; transform-origin: 100% 100%; }
  /* Whatever stands fixed over the call (the picture edge to edge, its scrims, the bubble, a toast) keeps clear of it too. */
  body.chat-open:not(.chat-page) { --chat-w: 412px; padding-right: var(--chat-w); }
}
.ch-head { display: flex; align-items: center; gap: 10px; padding: 12px 12px 6px 20px; min-height: 64px; }
.ch-head b { font-size: 17px; font-weight: 600; }
.ch-sub { flex: 1; min-width: 0; color: var(--muted); font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-head .round { background: var(--soft); flex: none; }
.ch-msgs { flex: 0 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; padding: 0 8px 8px; }
.ch-msgs > :first-child { margin-top: auto; }
.ch-msgs::-webkit-scrollbar { width: 6px; }
.ch-msgs::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }
.ch-msgs > .ch-empty { margin: 10px auto 14px; padding: 0 24px; max-width: 30ch; text-align: center; color: var(--muted); font-size: 15px; line-height: 1.4; text-wrap: balance; }
.ch-msg { position: relative; padding: 2px 40px 2px 12px; border-radius: 14px; transition: background .2s; }
.ch-msg.first { margin-top: 14px; }
.ch-msg.for-me, .ch-msg.acting { background: var(--soft); }
.ch-msg.for-me { padding-block: 6px; }
.ch-msg.lit { animation: lit 1.4s var(--ease); }
@keyframes lit { from { background: color-mix(in srgb, var(--ink) 12%, transparent); } }
.ch-from { display: flex; align-items: baseline; gap: 8px; min-width: 0; font-size: 13px; color: var(--muted); margin-bottom: 2px; }
.ch-from b { font-size: 14px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-from time { flex: none; font-variant-numeric: tabular-nums; }
.ch-msg p { margin: 0; font-size: 16px; line-height: 1.4; white-space: pre-wrap; overflow-wrap: anywhere; }
.ch-msg a:not(.ch-pic, .ch-doc) { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; color: inherit; text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; }
.ch-msg a:not(.ch-pic, .ch-doc):hover { text-decoration-color: currentColor; }
.ch-msg.folded p { display: -webkit-box; -webkit-line-clamp: 10; -webkit-box-orient: vertical; overflow: hidden; }
.ch-at { font-weight: 600; }
.ch-at.me { padding: 0 3px; margin: 0 -1px; border-radius: 6px; background: var(--ink); color: var(--paper); }
.ch-more { border: 0; background: none; padding: 4px 0; cursor: pointer; font: 500 14px Onest, system-ui, sans-serif; color: var(--muted); }
.ch-more:hover, .ch-more:focus-visible { color: var(--ink); }
.ch-quote {
  appearance: none; border: 0; cursor: pointer; display: grid; max-width: 100%; margin: 2px 0 4px; padding: 6px 12px; border-radius: 12px;
  background: var(--soft); text-align: left; font: inherit; color: var(--ink);
}
.ch-msg.for-me .ch-quote, .ch-msg.acting .ch-quote { background: var(--paper); }
.ch-quote b { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-quote span { font-size: 14px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-pics { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; }
.ch-pic { display: block; max-width: 100%; border-radius: 14px; overflow: hidden; background: var(--soft); box-shadow: inset 0 0 0 1px var(--line); }
.ch-pic img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ch-doc {
  display: flex; align-items: center; gap: 10px; width: fit-content; max-width: 100%; margin: 6px 0 2px; padding: 8px 14px 8px 10px;
  border-radius: 14px; box-shadow: inset 0 0 0 1px var(--line); color: var(--ink); text-decoration: none; background: var(--paper);
}
.ch-doc:hover { background: var(--soft); }
.ch-doc > svg { width: 22px; height: 22px; flex: none; color: var(--muted); }
.ch-doc span { display: grid; min-width: 0; }
.ch-doc b { font-size: 15px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-doc small { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.ch-reacts { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; }
.ch-react {
  appearance: none; border: 0; cursor: pointer; display: flex; align-items: center; gap: 4px; height: 28px; padding: 0 10px 0 6px; border-radius: 14px;
  background: var(--soft); color: var(--ink); font: 500 13px/1 Onest, system-ui, sans-serif; font-variant-numeric: tabular-nums;
}
.ch-msg.for-me .ch-react, .ch-msg.acting .ch-react { background: var(--paper); }
.ch-react.on { background: var(--paper); box-shadow: inset 0 0 0 1.5px var(--ink); }
.ch-react[disabled] { cursor: default; }
.ch-react .emoji { width: 18px; height: 18px; }
.ch-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin: 8px 0 4px; animation: rise .25s var(--ease) both; }
.ch-pick { display: flex; gap: 2px; }
.ch-pick button { appearance: none; border: 0; cursor: pointer; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: none; transition: transform .2s var(--ease), background .2s; }
.ch-pick button:hover, .ch-pick button:focus-visible { background: var(--paper); transform: scale(1.12); }
.ch-pick .emoji { width: 26px; height: 26px; }
.ch-act {
  appearance: none; border: 0; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 14px 0 10px; border-radius: 17px;
  background: var(--paper); color: var(--ink); font: 500 14px/1 Onest, system-ui, sans-serif; box-shadow: inset 0 0 0 1px var(--line);
}
.ch-act svg { width: 16px; height: 16px; }
.ch-act.danger { color: var(--red); }
.ch-reply {
  position: absolute; right: 4px; top: 2px; width: 32px; height: 32px; border: 0; border-radius: 50%; padding: 0; cursor: pointer;
  display: grid; place-items: center; background: none; color: var(--muted); opacity: 0; transition: opacity .15s, color .15s;
}
.ch-msg.first > .ch-reply { top: 0; }
.ch-reply svg { width: 16px; height: 16px; }
.ch-msg:hover > .ch-reply, .ch-reply:focus-visible { opacity: 1; }
.ch-reply:hover { color: var(--ink); }
@media (pointer: coarse) { .ch-reply { display: none; } }
.ch-new-at { position: relative; height: 0; }
.ch-new {
  position: absolute; left: 0; right: 0; bottom: 8px; width: fit-content; margin-inline: auto; z-index: 1;
  display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 14px 0 10px; border: 0; border-radius: 16px; cursor: pointer;
  background: var(--paper); color: var(--ink); font: 500 14px Onest, system-ui, sans-serif; white-space: nowrap;
  box-shadow: 0 0 0 1px var(--line), 0 6px 16px -6px var(--shadow); animation: settle .3s var(--ease) both;
}
.ch-new[hidden] { display: none; }
.ch-new svg { width: 16px; height: 16px; }
.ch-foot { position: relative; padding-bottom: env(safe-area-inset-bottom); }
.ch-compose { display: flex; align-items: flex-end; gap: 4px; margin: 6px 12px 12px; padding: 5px; border-radius: 22px; background: var(--soft); }
.ch-compose:focus-within { box-shadow: inset 0 0 0 1px var(--ink); }
.ch-compose textarea {
  flex: 1; min-width: 0; height: 36px; max-height: max(66px, min(132px, calc(var(--vvh, 100dvh) * .22))); padding: 7px 4px; border: 0; background: none; resize: none; outline: none;
  font: 400 16px/22px Onest, system-ui, sans-serif; color: var(--ink); caret-color: var(--ink); scrollbar-width: none;
}
.ch-compose textarea::placeholder { color: var(--placeholder); }
.ch-attach { flex: none; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; cursor: pointer; color: var(--muted); transition: color .15s, background .15s; }
.ch-attach:hover, .ch-attach:focus-within { color: var(--ink); background: var(--paper); }
.ch-attach svg { width: 20px; height: 20px; }
.ch-send {
  flex: none; width: 36px; height: 36px; border: 0; border-radius: 50%; padding: 0; cursor: pointer;
  display: grid; place-items: center; background: var(--ink); color: var(--paper); transition: opacity .15s;
}
.ch-send svg { width: 18px; height: 18px; }
.ch-send:disabled { opacity: .25; cursor: default; }
.ch-x { appearance: none; border: 0; cursor: pointer; flex: none; width: 32px; height: 32px; border-radius: 50%; padding: 0; display: grid; place-items: center; background: none; color: var(--muted); }
.ch-x:hover, .ch-x:focus-visible { color: var(--ink); }
.ch-x svg { width: 16px; height: 16px; }
.ch-replying { display: flex; align-items: center; gap: 10px; margin: 4px 12px 0; padding: 4px 4px 4px 14px; animation: rise .2s var(--ease) both; }
.ch-replying > span svg { width: 18px; height: 18px; color: var(--muted); display: block; }
.ch-replying div { flex: 1; min-width: 0; display: grid; }
.ch-replying b { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-replying div span { font-size: 14px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-pending { display: flex; gap: 6px; margin: 6px 12px 0; overflow-x: auto; scrollbar-width: none; }
.ch-file { flex: none; display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 2px 0 6px; border-radius: 14px; background: var(--soft); font-size: 14px; animation: rise .2s var(--ease) both; }
.ch-file img { width: 32px; height: 32px; border-radius: 9px; object-fit: cover; }
.ch-file > svg:first-child { width: 20px; height: 20px; color: var(--muted); margin-left: 4px; }
.ch-file > span { max-width: 11em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-file .spin { width: 16px; height: 16px; color: var(--muted); }
.ch-mention {
  display: grid; margin: 0 12px 6px; padding: 6px; border-radius: 18px; background: var(--paper);
  box-shadow: 0 0 0 1px var(--line), 0 12px 32px -12px var(--shadow); animation: menu .18s var(--ease) both; transform-origin: 50% 100%;
}
.ch-mention button { appearance: none; border: 0; cursor: pointer; display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 0 10px; border-radius: 12px; background: none; font: 400 16px Onest, system-ui, sans-serif; color: var(--ink); text-align: left; }
.ch-mention button[aria-selected="true"], .ch-mention button:hover { background: var(--soft); }
.ch-ini { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; background: var(--soft); font-size: 13px; font-weight: 500; }
.ch-mention button[aria-selected="true"] .ch-ini, .ch-mention button:hover .ch-ini { background: var(--paper); }
.ch-closed { margin: 0; padding: 12px 24px 20px; text-align: center; color: var(--muted); font-size: 15px; line-height: 1.4; }
.ch-closed a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; }
.ch-drop {
  position: absolute; inset: 8px; z-index: 2; display: none; place-items: center; border-radius: 18px; pointer-events: none;
  background: color-mix(in srgb, var(--paper) 92%, transparent); box-shadow: inset 0 0 0 1.5px var(--ink); font-size: 17px; font-weight: 500;
}
.ch.dropping .ch-drop { display: grid; }
/* Closed: what came in, once, above the controls. A tap opens the chat. */
.ch-peek {
  appearance: none; border: 0; cursor: pointer; position: fixed; z-index: 35; left: 50%; bottom: calc(150px + env(safe-area-inset-bottom));
  translate: -50% 0; width: min(360px, calc(100vw - 32px)); display: grid; gap: 2px; padding: 10px 16px 11px; border-radius: 18px; text-align: left;
  background: var(--paper); color: var(--ink); font: inherit; box-shadow: 0 0 0 1px var(--line), 0 12px 32px -12px var(--shadow);
  animation: settle .35s var(--ease) both;
}
.ch-peek[hidden] { display: none; }
.ch-peek b { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ch-peek b span { font-weight: 400; color: var(--muted); }
.ch-peek.me b span { color: var(--ink); font-weight: 500; }
.ch-peek > span { font-size: 15px; color: var(--muted); line-height: 1.35; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
body.chat-open .ch-peek { display: none; }
@media (prefers-reduced-motion: reduce) { .ch-sheet, .ch-peek, .ch-acts, .ch-new, .ch-badge, .ch-mention, .ch-file, .ch-replying { animation: none; } .ch-msg.lit { animation: none; } }
/* After the call, /c/<room>/chat: the same list as a page of its own. */
body.chat-page #app { max-width: 640px; height: 100dvh; padding-bottom: 0; }
.ch-archive { flex: 1; min-height: 0; display: flex; }
.ch-archive .ch-sheet { position: static; flex: 1; width: auto; height: auto; max-height: none; translate: none; overflow: visible; padding: 0; border-radius: 0; box-shadow: none; animation: enter .5s var(--ease) both; }
.ch-archive .ch-msgs { flex: 1; }
.ch-archive .ch-msgs > .ch-empty { margin: auto; }
.ch-archive .ch-head { flex-wrap: wrap; row-gap: 2px; padding: 0 8px 8px 12px; }
.ch-archive .ch-head b { font-size: 26px; letter-spacing: -0.025em; width: 100%; }
a.chat-link { display: inline-flex; align-items: center; text-decoration: none; margin-top: 12px; background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); }

/* «Крокодил» (web/crocodile.js): one quiet card between the header and the stage — the word for whoever shows it, who
   shows and how to guess for the rest, the word and who guessed between turns, the scores at the end. The turn's clock is
   a 3px ink line along its foot that runs out. Over pictures it is frosted like the reactions' rail and stays when the
   call's chrome hides, since the game goes on. */
.croc {
  position: relative; flex: none; width: min(420px, 100%); margin: 10px auto 0; padding: 14px 18px 17px; overflow: hidden;
  border-radius: 18px; background: var(--soft); display: grid; gap: 3px; text-align: left; animation: rise .3s var(--ease) both;
}
.croc p { margin: 0; }
.croc-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 13px; line-height: 1.35; color: var(--muted); }
.croc-top > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.croc-time { flex: none; font-size: 15px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.croc-word { margin: 2px 0 8px; font-size: 30px; font-weight: 600; line-height: 1.15; letter-spacing: -0.025em; color: var(--ink); text-wrap: balance; overflow-wrap: anywhere; }
.croc-head { font-size: 17px; font-weight: 600; line-height: 1.3; color: var(--ink); text-wrap: balance; }
.croc-note, .croc-none { font-size: 15px; line-height: 1.35; color: var(--muted); text-wrap: pretty; }
.croc-ask { font-size: 13px; color: var(--muted); }
.croc-score { margin-top: 4px; font-size: 14px; color: var(--muted); }
.croc-score b, .croc-final b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.croc-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 6px; }
.croc-acts .chip[disabled] { opacity: .5; cursor: default; }
.croc-acts .croc-name { background: var(--paper); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); max-width: 12em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.croc-acts .croc-name:hover, .croc-acts .croc-name:focus-visible { box-shadow: inset 0 0 0 1.5px var(--ink); outline: none; }
.croc-acts .chip.quiet { background: none; box-shadow: none; color: var(--muted); padding: 0 10px; }
.croc-acts .chip.quiet:hover { color: var(--ink); }
.croc-line { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--line); }
.croc-line > i { display: block; height: 100%; background: var(--ink); transform-origin: left; transition: transform 1s linear; }
.croc-final { list-style: none; margin: 6px 0 2px; padding: 0; }
.croc-final li { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; font-size: 15px; color: var(--ink); border-bottom: 1px solid var(--line); }
.croc-final li.top { font-weight: 600; }
.croc-final li:last-child { border-bottom: 0; }
.croc-final li span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.croc-go { display: flex; gap: 8px; padding: 10px 8px 4px; }
.croc-go .chip { flex: 1; height: 44px; border-radius: 22px; }
.call.visual .croc { background: color-mix(in srgb, var(--paper) 90%, transparent); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); box-shadow: 0 6px 24px -10px rgb(0 0 0 / .25); }
.call.calm > .croc { opacity: 1; visibility: visible; pointer-events: auto; }
@media (max-width: 420px) { .croc { padding: 12px 16px 15px; } .croc-word { font-size: 26px; } }
