@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)) 24px max(24px, env(safe-area-inset-bottom));
}
.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); }
.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; }
.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: 8px; }
.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: 34px; top: 5px; 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: 8px; 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; }
  /* 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: -4px; 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: -4px; 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); }

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: 1240px; height: 100dvh; }
.call.visual { min-height: 0; }
.call.visual .controls { padding-bottom: 20px; }
.tiles {
  flex: 1; min-height: 0; position: relative; margin: 20px 0 8px;
  display: grid; gap: 8px; grid-template-columns: 1fr; grid-auto-rows: minmax(0, 1fr);
}
.tiles[data-n="3"], .tiles[data-n="4"], .tiles[data-n="5"], .tiles[data-n="6"], .tiles[data-n="7"], .tiles[data-n="8"] { grid-template-columns: 1fr 1fr; }
/* Two columns and an odd count: the last person takes the whole bottom row instead of leaving a hole. */
.tiles[data-n="3"] > .tile:last-child, .tiles[data-n="5"] > .tile:last-child, .tiles[data-n="7"] > .tile:last-child { grid-column: 1 / -1; }
@media (min-width: 900px) {
  .tiles[data-n="3"] > .tile:last-child, .tiles[data-n="5"] > .tile:last-child, .tiles[data-n="7"] > .tile:last-child { grid-column: auto; }
  .tiles[data-n="3"], .tiles[data-n="5"], .tiles[data-n="6"] { grid-template-columns: repeat(3, 1fr); }
  .tiles[data-n="7"], .tiles[data-n="8"] { grid-template-columns: repeat(4, 1fr); }
}
.tile {
  position: relative; min-height: 120px; 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; background: #000; }
.tile.ai-video video { object-fit: contain; }
.tile.mirror video { transform: scaleX(-1); }
.tile .initial { font-size: 40px; font-weight: 500; letter-spacing: -0.02em; color: var(--muted); }
.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 { font-size: 26px; }
/* 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:not(.pip) { 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)); }
@container (min-aspect-ratio: 1 / 1) { .tile video[data-portrait] { object-fit: contain; } }
/* 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; z-index: 0; margin: 0; }
.call.immersive .tile { outline-color: transparent; background: #000; }
.call.immersive .tile:not(.pip) { border-radius: 0; min-height: 0; }
.call.immersive .tile:not(.pip) .who { display: none; }
.call.immersive .tile .tag:not(:has(svg)) { display: none; }
.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 .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 .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.calm { cursor: none; }
.call.immersive::before, .call.immersive::after {
  content: ''; position: fixed; left: 0; right: 0; 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); }
.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. */
.call.showing header { display: flex; align-items: center; justify-content: center; gap: 4px 14px; flex-wrap: wrap; padding-top: 4px; }
.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; } }
}
/* Both sharing at once: your thumbnail joins the folded header line, small and first. */
.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; }

#toast {
  position: fixed; left: 50%; 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; }
.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; } }

.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 sit in a row as tall as the orb, centred on it, so every name lines up beneath. */
.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); }
/* Its mute: the muted-mic badge of a person, as a button — shown while it is muted, and on hover or focus while it
   talks (always on a touch screen). */
.face .ai-mute {
  appearance: none; border: 0; cursor: pointer; padding: 0; color: var(--ink); z-index: 1; /* over the speaking ring */
  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;
  opacity: 0; transition: opacity .2s, transform .2s var(--ease);
}
.face .ai-mute svg { width: 16px; height: 16px; stroke-width: 1.75; }
.face .ai-mute.off, .person.agent:hover .ai-mute, .ai-mute:focus-visible { opacity: 1; }
.face .ai-mute { background: var(--green-fill); color: #fff; }
.face .ai-mute.off { background: var(--red); }
.face .ai-mute:active { transform: scale(.92); }
@media (hover: none) { .face .ai-mute { opacity: 1; } }
.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; }
/* What runs it, while the alpha compares engines. */
.ai-control[data-ai="listening"] #ai { background: var(--green-fill); color: #fff; box-shadow: none; }
.ai-control[data-ai="quiet"] #ai { box-shadow: inset 0 0 0 2px var(--red); color: var(--red); }
.ai-control[data-ai="listening"] > span { color: var(--green); font-weight: 500; }
.ai-control[data-ai="quiet"] > span { color: var(--red); font-weight: 500; }
.call.immersive .ai-control[data-ai="listening"] #ai { background: var(--green-fill); color: #fff; }
.call.immersive .ai-control[data-ai="quiet"] #ai { box-shadow: inset 0 0 0 2px #ff7a6e; color: #fff; }
.call.immersive .ai-control[data-ai] > span { color: rgb(255 255 255 / .9); }
.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; }
}

.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 > .menu-label, .ai-menu > [role="radiogroup"] > .menu-label:first-child { margin-top: 4px; padding-top: 10px; border-top: 1px solid var(--line); }
.ai-menu .menu-label.sub { margin-top: 0; padding-top: 2px; border-top: 0; }
/* «экспериментально»: a quiet tag after the label, not a warning. */
.menu-label .beta { margin-left: 4px; padding: 1px 7px; border-radius: 999px; background: var(--soft); font-size: 12px; }
.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 rail at the right edge, 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; }
/* Folded into a round smile at rest, a little dim so it never pulls the eye from a face; a tap unfolds the rail around
   the same centre (a little above the middle, clear of the corner picture), and the same button, now a chevron at its top
   above a hairline, folds it back. Over a one-to-one picture it is frosted like the controls. */
.rail {
  position: fixed; z-index: 4; right: max(8px, env(safe-area-inset-right)); top: 46%; translate: 0 -50%;
  display: grid; justify-items: center; width: 52px; padding: 4px 0; border-radius: 26px;
  background: color-mix(in srgb, var(--paper) 88%, transparent); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  box-shadow: 0 0 0 1px var(--line), 0 8px 22px -12px var(--shadow);
  opacity: .72; transition: opacity .3s var(--ease);
}
.rail.open, .rail:hover, .rail:focus-within { opacity: 1; }
/* A menu or popover of the call takes the space: the rail steps aside until it closes. */
.call:has(.mic-menu, .rec-pop, .lock-pop) .rail { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .2s var(--ease), visibility 0s .2s; }
.rail-fold .icon { grid-area: 1 / 1; transition: opacity .25s var(--ease), rotate .4s var(--ease), scale .4s var(--ease); }
.rail-fold .rail-chevron { opacity: 0; rotate: 180deg; scale: .6; }
.rail.open .rail-fold .rail-smile { opacity: 0; rotate: -90deg; scale: .6; }
.rail.open .rail-fold .rail-chevron { opacity: 1; rotate: 0deg; scale: 1; color: var(--muted); }
.rail-body { display: grid; grid-template-rows: 0fr; opacity: 0; transition: grid-template-rows .42s var(--ease), opacity .22s var(--ease); }
.rail.open .rail-body { grid-template-rows: 1fr; opacity: 1; transition: grid-template-rows .42s var(--ease), opacity .3s var(--ease) .08s; }
.rail-in { min-height: 0; overflow: hidden; display: grid; justify-items: center; position: relative; }
.rail-in::before { content: ''; display: block; justify-self: stretch; height: 1px; margin: 3px 12px 4px; background: var(--line); }
.rail-list .rail-item { transition: transform .25s var(--ease), background .2s, opacity .3s var(--ease), translate .4s var(--ease); }
.rail:not(.open) .rail-list .rail-item { opacity: 0; translate: 0 -8px; }
.rail-list { display: grid; justify-items: center; gap: 2px; max-height: min(38vh, 360px); overflow-y: auto; scrollbar-width: none; overscroll-behavior: contain; }
.rail-list::-webkit-scrollbar { display: none; }
.rail-item, .rail-swap, .rail-fold {
  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;
}
.rail-item .emoji { width: 28px; height: 28px; }
.rail-item svg, .rail-swap svg, .rail-fold svg { width: 20px; height: 20px; }
.rail-item:hover, .rail-swap:hover, .rail-fold:hover { background: var(--soft); }
.rail-item:active, .rail-swap:active, .rail-fold:active { transform: scale(.82); transition-duration: .08s; }
.rail-item:focus-visible, .rail-swap:focus-visible, .rail-fold:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.rail-hush[aria-pressed="true"] { color: var(--red); }
.rail-swap { position: relative; margin-top: 4px; }
.rail-swap::before { content: ''; position: absolute; top: -3px; left: 12px; right: 12px; height: 1px; background: var(--line); }
.call.immersive > .rail { position: fixed; z-index: 3; }
/* Over a one-to-one picture it takes the side your corner picture is not on. */
.rail.left { right: auto; left: max(8px, env(safe-area-inset-left)); }
.call.immersive .rail { background: rgb(20 20 20 / .42); box-shadow: inset 0 0 0 1px rgb(255 255 255 / .12), 0 12px 30px -12px rgb(0 0 0 / .5); }
.call.immersive .rail-item, .call.immersive .rail-swap, .call.immersive .rail-fold, .call.immersive .rail.open .rail-fold .rail-chevron { color: #fff; }
.call.immersive .rail-item:hover, .call.immersive .rail-swap:hover, .call.immersive .rail-fold:hover { background: rgb(255 255 255 / .14); }
.call.immersive .rail-swap::before, .call.immersive .rail-in::before { background: rgb(255 255 255 / .16); }
@media (prefers-reduced-motion: reduce) { .rail-body, .rail.open .rail-body, .rail-fold .icon, .rail-list .rail-item { transition-duration: .01s; transition-delay: 0s; } }
/* On a phone the faces keep clear of it: the column gives up the rail's lane, the orb a little of its size. */
@media (max-width: 520px) {
  .call:not(.visual) .people { padding-inline-end: 40px; }
  .call:not(.visual) .people:has(> .orb) { --orb: 148px; }
  .call:not(.visual):has(> .over) .people:has(> .orb) { --orb: 120px; }
}
.mic-menu .fun-voices { padding: 4px 8px 8px; display: flex; flex-wrap: wrap; gap: 6px; }
.mic-menu .fun-voices .lang { height: 36px; padding: 0 12px; font-size: 14px; }
.mic-menu .fun-voices .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);
}
