/* Mates: the "Свет" design. Sasha's presence is light from the top edge: golden by day, lamp-warm by night.
   When she speaks the light is up; when the learner speaks it dims and a teal light rises from the bottom.
   Every colour is a token. :root is the dark theme; :root[data-theme="light"] under it is the light one, «Утро»: warm
   paper, cream cards, plum ink. The script in each page's <head> sets data-theme before the first paint. The admin
   shares these tokens, and web/foundations.html shows them all. */
:root {
  color-scheme: dark;
  /* surfaces and ink */
  --bg: #15121c;
  --card: #1f1a29;
  --raised: #2a2435;
  --line: #3d3550;
  --fg: #f4f1ec;
  --muted: #b4aebf;
  --dim: #8e879b;
  --faint: #6e6880;
  --clock-total: var(--faint);  /* the call's «/ 10:00», under the light */
  --comment: #c9c3d3;  /* the letter's notes */
  /* accents: the text colour, and where it differs the one for a fill, a ground or a line */
  --lilac: #c4b5fd;
  --lilac-hover: #d4c8ff;
  --lilac-bg: #2e2842;  /* light's selection and admin buttons; dark uses neither and keeps the browser's selection */
  --on-accent: #1a1520;  /* text on a lilac fill */
  --teal: #72cdb6;
  --teal-bg: #1e2a2d;
  --teal-fill: var(--teal);  /* the minutes bar */
  --sun: #f5c451;
  --sun-fill: var(--sun);  /* the sun as a bar, a dot, an icon */
  --sun-bg: rgba(245, 196, 81, 0.15);
  --moon: #f4d2c0;
  --end: #f09a9a;
  --end-text: #f4b0b0;
  --end-bg: rgba(240, 154, 154, 0.12);
  --end-press: rgba(240, 154, 154, 0.24);
  --end-line: rgba(240, 154, 154, 0.3);
  --down-bg: #2f2228;  /* a score that went down */
  --accent: var(--moon);
  /* the mates: a tint for text and dots, a glow for their card; the switcher's thumb */
  --sasha: #f28ac6;
  --sasha-glow: rgba(242, 138, 198, 0.24);
  --roger: #7ea0ff;
  --roger-glow: rgba(111, 140, 255, 0.26);
  --lilac-glow: rgba(196, 181, 253, 0.22);  /* a third mate's */
  --thumb: linear-gradient(110deg, #6f8cff 0%, #a58bff 45%, #f28ac6 100%);
  --thumb-shadow: 0 6px 20px rgba(242, 138, 198, 0.28), 0 6px 20px rgba(111, 140, 255, 0.22);
  --on-thumb: #15121c;
  --stack-back: #1a1623;
  --stack-edge: var(--raised);
  /* slips and scores: the report's tones, the admin's grades */
  --rough: #f28b9b;
  --noticeable: #f5ad6e;
  --minor: #7fd49c;
  --meter-off: rgba(244, 241, 236, 0.14);
  --hi-bg: rgba(114, 205, 182, 0.14);
  --mid-bg: rgba(245, 196, 81, 0.14);
  --lo-bg: rgba(240, 154, 154, 0.14);
  /* the light, and the call button's living ring */
  --light-sun: radial-gradient(ellipse 90% 60% at 50% -12%, rgba(245, 196, 81, 0.42) 0%, rgba(245, 196, 81, 0) 70%);
  --light-moon: radial-gradient(ellipse 90% 60% at 62% -12%, rgba(244, 204, 184, 0.4) 0%, rgba(244, 204, 184, 0) 70%);
  --light-you: radial-gradient(ellipse 90% 50% at 50% 112%, rgba(114, 205, 182, 0.3) 0%, rgba(114, 205, 182, 0) 70%);
  --ring-night: conic-gradient(from 0deg, rgba(244, 210, 192, 0.9), rgba(212, 156, 172, 0.55), rgba(248, 230, 210, 0.95), rgba(205, 180, 228, 0.7), rgba(244, 210, 192, 0.9));
  --ring-day: conic-gradient(from 0deg, #f5c451, #72cdb6, #fff1c2, #f5c451);
  --ring-inner: #1b1724;
  --ring-glow: rgba(120, 110, 200, 0.22);
  /* controls and the admin's surfaces */
  --card-edge: var(--raised);  /* the hairline round a letter, the switcher, the voice button */
  --pill-edge: var(--line);  /* the outlined pills: «Текст», «Подсмотреть», «Отменить», «Закрыть» */
  --fact-bg: transparent;  /* the admin's pills of a learner's settings */
  --track: var(--raised);  /* the call's progress */
  --control: var(--line);  /* an empty radio's edge */
  --switch-off: var(--raised);
  --knob: var(--muted);
  --knob-on: var(--on-accent);
  --knob-shadow: none;
  --field: var(--bg);
  --well: var(--raised);  /* the feedback's textarea */
  --pop-bg: var(--raised);  /* the plan popover */
  --btn-bg: var(--raised);  /* the admin's secondary buttons */
  --btn-hover: #342d43;
  --row-hover: rgba(196, 181, 253, 0.045);
  --en-bg: rgba(245, 196, 81, 0.13);
  --inbox-glow: rgba(245, 196, 81, 0.075);
  --new-fade: rgba(30, 42, 45, 0.25);  /* a new learner's row, fading out of --teal-bg */
  --scrim: rgba(10, 8, 14, 0.6);
  --sky-edge: rgba(255, 255, 255, 0.07);  /* the hairline round «Небо»'s window */
  /* «Язык»: a language's letter on the track, a step under its name, so its lilac mark stands off it */
  --letter: var(--dim);
  --mark-on: #6445c7;  /* the mark on the chosen thumb: the lilac halfway between the thumb and the letter, the light's violet */
  --pulp: #857aac;  /* the orange's pulp: the mark's colour as a fill */
  /* shadows: none on the dark page, where a card is lighter than the ground */
  --shadow-card: none;
  --shadow-lift: 0 14px 30px rgba(0, 0, 0, 0.35);
  --shadow-pop: 0 22px 48px rgba(0, 0, 0, 0.5);
  --shadow-sheet: none;
}
/* «Утро / тёплая бумага»: light on paper cannot add, only tint, so the light is a warm wash (the sun's with a white core) */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f7f1e8;  /* warm paper */
  --card: #fffcf7;  /* a cream sheet */
  --raised: #f1e9dd;  /* pressed into a card: tracks, pills */
  --line: #e2d7c7;
  --fg: #2b2127;  /* plum ink, never black */
  --muted: #4f444c;
  --dim: #6b5f67;
  --faint: #6f6268;
  --clock-total: var(--dim);  /* on paper the light's peak is darker than the page */
  --comment: #4b4048;
  --lilac: #6445c7;  /* violet ink */
  --lilac-hover: #5536b3;
  --lilac-bg: #ebe4fc;
  --on-accent: #fffcf7;
  --teal: #1b715f;  /* sea green */
  --teal-bg: #e0f0e9;
  --teal-fill: #168a6e;
  --sun: #8f5c08;  /* honey: the sun as text */
  --sun-fill: #a56f04;  /* gold: the sun as a bar, a dot, an icon, 3:1 on every ground */
  --sun-bg: #f8ecd0;
  --moon: #ad5638;  /* terracotta: the evening lamp */
  --end: #b53a31;
  --end-text: var(--end);
  --end-bg: #fbe8e4;  /* opaque, so the hang-up stays crisp over the teal light */
  --end-press: #f6d7d0;
  --end-line: #efc3ba;
  --down-bg: var(--end-bg);
  --sasha: #b53a80;
  --sasha-glow: rgba(242, 138, 198, 0.22);
  --roger: #3b5fd0;
  --roger-glow: rgba(111, 140, 255, 0.2);
  --lilac-glow: rgba(150, 125, 235, 0.16);
  --thumb: linear-gradient(110deg, #9db2ff 0%, #bca6ff 45%, #f5a3d2 100%);
  --thumb-shadow: 0 4px 14px rgba(242, 138, 198, 0.26), 0 4px 14px rgba(111, 140, 255, 0.18);
  --on-thumb: var(--fg);
  --stack-back: #fbf6ef;
  --stack-edge: var(--line);  /* the card behind needs an edge on paper */
  --rough: #c0314f;
  --noticeable: #a8520c;
  --minor: #2a7743;
  --meter-off: rgba(43, 33, 39, 0.13);
  --hi-bg: var(--teal-bg);
  --mid-bg: var(--sun-bg);
  --lo-bg: var(--end-bg);
  --light-sun: radial-gradient(ellipse 90% 60% at 50% -12%, rgba(255, 250, 236, 0.9) 0%, rgba(255, 184, 64, 0.5) 22%, rgba(255, 184, 64, 0.16) 40%, rgba(255, 184, 64, 0) 64%);
  --light-moon: radial-gradient(ellipse 90% 60% at 62% -12%, rgba(255, 158, 112, 0.44) 0%, rgba(255, 158, 112, 0) 70%);  /* the mock's broad lamp */
  --light-you: radial-gradient(ellipse 90% 50% at 50% 112%, rgba(240, 255, 250, 0.9) 0%, rgba(40, 190, 158, 0.55) 30%, rgba(90, 205, 176, 0.3) 46%, rgba(220, 244, 236, 0.7) 60%, rgba(228, 246, 240, 0) 78%);  /* a mint-white rim, not sage */
  --ring-night: conic-gradient(from 0deg, #ee8f5f, #e2679a, #f6b36b, #9577ea, #ee8f5f);
  --ring-day: conic-gradient(from 0deg, #eba61c, #2f9f84, #f9cf5a, #eba61c);
  --ring-inner: linear-gradient(180deg, #fffdf9 0%, #fff3e6 100%);
  --ring-glow: rgba(226, 120, 70, 0.2);
  --card-edge: transparent;  /* on paper the shadow is the edge */
  --pill-edge: color-mix(in srgb, var(--fg) 18%, transparent);  /* ink, so it shows on the paper and on the mint alike */
  --fact-bg: var(--card);
  --track: #e6dccd;  /* the call runs on the paper, where --raised is too close to see */
  --control: #93867c;  /* a pencil circle, 3:1 */
  --switch-off: var(--line);
  --knob: var(--card);
  --knob-shadow: 0 1px 3px rgba(43, 33, 39, 0.22);
  --field: var(--card);
  --well: var(--bg);
  --pop-bg: var(--card);
  --btn-bg: var(--lilac-bg);
  --btn-hover: #e3d9fb;
  --row-hover: rgba(100, 69, 199, 0.035);
  --en-bg: var(--sun-bg);
  --inbox-glow: var(--sun-bg);
  --new-fade: color-mix(in srgb, var(--teal-bg) 30%, transparent);
  --scrim: rgba(43, 33, 39, 0.13);  /* plum ink: the sheet's own shadow does the lifting */
  --sky-edge: rgba(92, 60, 30, 0.1);  /* a warm pencil line on paper */
  --letter: var(--muted);  /* on paper --dim is as dark as the violet (1.07:1) */
  --mark-on: #b09cf8;  /* 2.8:1 on the violet thumb, 2.3:1 on the cream letter (the dark's pale lilac is 1.8:1 on cream) */
  --pulp: #b2a1df;
  --shadow-card: 0 1px 2px rgba(92, 60, 30, 0.05), 0 4px 16px rgba(92, 60, 30, 0.07);
  --shadow-lift: 0 10px 24px rgba(92, 60, 30, 0.1), 0 2px 5px rgba(92, 60, 30, 0.05);
  --shadow-pop: 0 18px 40px rgba(92, 60, 30, 0.16), 0 2px 8px rgba(92, 60, 30, 0.08);
  --shadow-sheet: 0 -12px 40px rgba(92, 60, 30, 0.14);
}
/* What a token cannot say: it depends on the element's own tint or the time of day, or has no dark twin (::selection) */
:root[data-theme="light"] .feature-tab[aria-selected="true"] { background: color-mix(in srgb, var(--tint) 9%, var(--card)); }
:root[data-theme="light"] .letter-icon { background: color-mix(in srgb, var(--accent) 12%, var(--card)); }
:root[data-theme="light"] ::selection { background: var(--lilac-bg); }
body[data-time="day"] { --accent: var(--sun-fill); }

/* The fonts, from this server (web/fonts/, tests/test_fonts.py): Google Fonts' own files, each subset a variable font
   whose weight axis covers every weight the pages use, loaded only when a page has a letter of its range. */
@font-face { font-family: Manrope; src: url("/web/fonts/manrope-v20-cyrillic.woff2") format("woff2"); font-style: normal; font-weight: 200 800; font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: Manrope; src: url("/web/fonts/manrope-v20-latin-ext.woff2") format("woff2"); font-style: normal; font-weight: 200 800; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Manrope; src: url("/web/fonts/manrope-v20-latin.woff2") format("woff2"); font-style: normal; font-weight: 200 800; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: Unbounded; src: url("/web/fonts/unbounded-v12-cyrillic.woff2") format("woff2"); font-style: normal; font-weight: 200 900; font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; }
@font-face { font-family: Unbounded; src: url("/web/fonts/unbounded-v12-latin-ext.woff2") format("woff2"); font-style: normal; font-weight: 200 900; font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: Unbounded; src: url("/web/fonts/unbounded-v12-latin.woff2") format("woff2"); font-style: normal; font-weight: 200 900; font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

* { box-sizing: border-box; }
/* the keyboard's focus: the app's lilac ring on everything (the browser's own ring is lost on the dark page) */
:focus-visible { outline: 2px solid var(--lilac); outline-offset: 2px; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.45 Manrope, "Segoe UI", system-ui, sans-serif;
  position: relative;
  isolation: isolate;
  overflow-x: hidden;
}
h1, .name, .name-small, .wordmark, .clock, .knocking, .companion-name { font-family: Unbounded, Manrope, sans-serif; font-weight: 500; }

/* The light */
.light { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.light > div { position: absolute; inset: 0; opacity: 0; transition: opacity 900ms ease; transform-origin: 50% 0; }
.light-sun { background: var(--light-sun); }
.light-moon { background: var(--light-moon); }
.light-you { background: var(--light-you); }
@keyframes glow { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } }
@keyframes knock { 0%, 100% { opacity: 0.3; transform: scale(1); } 50% { opacity: 1; transform: scale(1.1); } }
/* idle: a resting glow on the home screen */
body[data-time="day"][data-mode="idle"] .light-sun,
body[data-time="night"][data-mode="idle"] .light-moon { opacity: 0.6; animation: glow 6s ease-in-out infinite; }
/* connecting: the light knocks */
body[data-time="day"][data-mode="connecting"] .light-sun,
body[data-time="night"][data-mode="connecting"] .light-moon { animation: knock 1.8s ease-in-out infinite; }
/* speaking: Sasha's light is up */
body[data-time="day"][data-mode="speaking"] .light-sun,
body[data-time="night"][data-mode="speaking"] .light-moon { opacity: 1; animation: glow 4.5s ease-in-out infinite; }
/* listening: her light dims and yours rises */
body[data-time="day"][data-mode="listening"] .light-sun,
body[data-time="night"][data-mode="listening"] .light-moon { opacity: 0.3; }
body[data-mode="listening"] .light-you { opacity: 0.9; }

/* Screens */
main { max-width: 480px; min-height: 100%; margin: 0 auto; padding: max(28px, env(safe-area-inset-top)) 24px 28px; }
.screen { display: none; min-height: calc(100vh - 56px); min-height: calc(100dvh - 56px); flex-direction: column; gap: 18px; }
body[data-screen="home"] .screen-home,
body[data-screen="connecting"] .screen-connecting,
body[data-screen="call"] .screen-call { display: flex; }

.bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.report-title { display: flex; align-items: center; gap: 14px; min-width: 0; }  /* the back arrow, then whose letter it is */
.bar-stack { display: flex; flex-direction: column; gap: 12px; }
.wordmark { font-size: 15px; letter-spacing: 0.14em; color: var(--muted); }
.caption { font-size: 14px; color: var(--muted); }
.muted { color: var(--faint); }
.chip { display: inline-flex; align-items: center; gap: 8px; padding: 10px 14px; border-radius: 999px; font-size: 14px; font-weight: 600; }
.chip-plan { padding: 6px 12px; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; color: var(--lilac); border: 1px solid var(--line); }
.chip-done { background: var(--teal-bg); color: var(--teal); }
.chip-today { border: 1px solid var(--lilac); color: var(--lilac); }
.chips { display: flex; flex-wrap: wrap; gap: 10px; }

.hero { flex-grow: 1; display: flex; flex-direction: column; justify-content: center; gap: 16px; }
.hero.centered { align-items: center; text-align: center; gap: 12px; }
.name-block { display: flex; flex-direction: column; gap: 6px; }
.name { margin: 0; font-size: 30px; line-height: 1.1; }
/* the mate's face left of their name; a tap opens the whole photo */
.name-row { display: flex; align-items: center; gap: 14px; min-width: 0; }
.mate-avatar { flex: none; display: block; width: 52px; height: 52px; margin: 0; padding: 0; border: 0; border-radius: 50%;
  overflow: hidden; background: var(--raised); box-shadow: 0 0 0 3px var(--card), var(--shadow-card); cursor: zoom-in; }
.mate-avatar[hidden] { display: none; }
.mate-avatar img { display: block; width: 100%; height: 100%; object-fit: cover; }
.mate-avatar:focus-visible { outline: 2px solid var(--lilac); outline-offset: 3px; }
.name-small { font-size: 16px; }
.note { margin: 0; font-size: 22px; line-height: 1.35; font-weight: 500; letter-spacing: -0.01em; text-wrap: pretty; }
/* Before the link is opened: what this is, in three short paragraphs under the note */
.about { display: flex; flex-direction: column; gap: 10px; }
.about p { margin: 0; font-size: 14px; line-height: 1.42; color: var(--muted); text-wrap: pretty; }
/* Without a key the home is a landing: from the top, the headline larger, everything on one phone screen */
/* Like the home under a link: the whole height, MATES at the top and the sign-up at the bottom; the free space goes in
   equal parts above the headline, to the companions, to the features and to the sign-up line, never into one hole */
body[data-locked="true"] .hero { flex-grow: 1; justify-content: flex-start; gap: 10px; }
body[data-locked="true"] .about { display: contents; }
body[data-locked="true"] .note,
body[data-locked="true"] .hero .companions,
body[data-locked="true"] .hero .features,
body[data-locked="true"] .about > p:last-child { margin-top: auto; }
body[data-locked="true"] main { padding-bottom: 12px; }
body[data-locked="true"] .screen-home { gap: 14px; }
body[data-locked="true"] .note { font-size: 23px; line-height: 1.2; font-weight: 600; letter-spacing: -0.015em; text-wrap: balance; }
/* /login: the headline and the email form alone, with no pitch to fill the screen, sit in the middle of it, not at its foot */
body[data-login-only="true"] .hero { flex-grow: 0; margin-top: auto; }
body[data-login-only="true"] .screen-home > .apply { margin-bottom: auto; }  /* the free space splits above and below the pair */
/* The same landing on a desktop or a tablet: the phone's tight rhythm would look cramped there, so the column breathes -
   a little on a laptop (760 px and taller), fully on a tall screen (900 px and taller) */
@media (min-width: 600px) and (min-height: 760px) {
  body[data-locked="true"] main { max-width: 520px; padding-top: 28px; padding-bottom: 24px; }
  body[data-locked="true"] .screen-home { gap: 20px; }
  body[data-locked="true"] .hero { gap: 26px; }
  body[data-locked="true"] .about > p:first-child { margin-top: -14px; }  /* the paragraph stays with its headline */
  body[data-locked="true"] .note { font-size: 30px; line-height: 1.15; letter-spacing: -0.02em; }
  body[data-locked="true"] .about > p { font-size: 16px; line-height: 1.5; }
  body[data-locked="true"] .switcher { height: 50px; padding: 4px; }
  body[data-locked="true"] .voice-play { width: 50px; height: 50px; }
  body[data-locked="true"] .switcher-thumb { top: 4px; bottom: 4px; left: 4px; width: calc((100% - 8px) / var(--count)); }
  body[data-locked="true"] .switcher button { font-size: 16px; }
  body[data-locked="true"] .stack-card { gap: 8px; padding: 16px 16px 16px 20px; }
  body[data-locked="true"] .stack .stack-about { font-size: 15px; line-height: 1.45; }
  body[data-locked="true"] .features { gap: 10px; }
  body[data-locked="true"] .feature-tabs { gap: 8px; }
  body[data-locked="true"] .feature-tab { height: 50px; }
  body[data-locked="true"] .feature-card { gap: 6px; min-height: 96px; padding: 14px 18px 16px; }
  body[data-locked="true"] .feature-card b { font-size: 16px; }
  body[data-locked="true"] .about .feature-card p { font-size: 14.5px; line-height: 1.5; }
  body[data-locked="true"] .apply input { height: 52px; padding: 0 16px; font-size: 16px; }
  body[data-locked="true"] .apply .ring-button { width: 140px; height: 52px; }
  body[data-locked="true"] .apply .ring-inner { font-size: 15.5px; }
}
@media (min-width: 600px) and (min-height: 900px) {
  body[data-locked="true"] main { max-width: 540px; padding-top: 40px; padding-bottom: 40px; }
  body[data-locked="true"] .screen-home { min-height: calc(100vh - 80px); min-height: calc(100dvh - 80px); }  /* the taller padding above */
  body[data-locked="true"] .screen-home { gap: 24px; }
  body[data-locked="true"] .hero { gap: 40px; }
  body[data-locked="true"] .about > p:first-child { margin-top: -24px; }
  body[data-locked="true"] .wordmark { font-size: 16px; }
  body[data-locked="true"] .note { font-size: 32px; }
  body[data-locked="true"] .about > p { font-size: 16.5px; line-height: 1.55; }
  body[data-locked="true"] .companions { gap: 10px; }
  body[data-locked="true"] .switcher { height: 52px; }
  body[data-locked="true"] .voice-play { width: 52px; height: 52px; }
  body[data-locked="true"] .stack { padding-bottom: 11px; }
  body[data-locked="true"] .stack-back { left: 16px; right: 16px; top: 11px; }
  body[data-locked="true"] .stack-card { gap: 8px; padding: 16px 16px 16px 20px; }
  body[data-locked="true"] .stack .stack-about { font-size: 15.5px; }
  body[data-locked="true"] .stack .stack-now { font-size: 14px; }
  body[data-locked="true"] .feature-tab { height: 52px; border-radius: 16px; }
  body[data-locked="true"] .feature-tab svg { transform: scale(1.15); }
  body[data-locked="true"] .feature-card { gap: 6px; min-height: 100px; padding: 16px 20px 18px; border-radius: 18px; }
  body[data-locked="true"] .about .feature-card p { font-size: 15px; }
  body[data-locked="true"] .apply input { height: 54px; padding: 0 18px; }
  body[data-locked="true"] .apply .ring-button { width: 146px; height: 54px; }
}
.about .dim { font-size: 14px; color: var(--dim); }
/* Whom there is to call: a switcher with a blue-pink thumb and their voice beside it, over a stack of cards - the chosen
   one in front, the next one peeking out behind, so it shows there are more voices; a tap on the card goes to the next.
   The card's text has the card's full width and the height of the longest one (app.js), so switching does not move the page */
.companions { --tint: var(--sasha); --glow: var(--sasha-glow); --next-glow: var(--roger-glow);
  display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.picker { display: flex; gap: 8px; }
.picker .switcher { flex: 1; min-width: 0; }
.switcher { --count: 2; --index: 0; position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
  height: 44px; padding: 3px; border: 1px solid var(--card-edge); border-radius: 999px; background: var(--card); box-shadow: var(--shadow-card); }
.switcher-thumb { position: absolute; top: 3px; bottom: 3px; left: 3px; width: calc((100% - 6px) / var(--count)); border-radius: 999px;
  background-image: var(--thumb); background-size: 200% 100%;
  transform: translateX(calc(var(--index) * 100%)); transition: transform 380ms cubic-bezier(0.3, 1.3, 0.5, 1);
  box-shadow: var(--thumb-shadow); animation: sheen 5s ease-in-out infinite alternate; }
@keyframes sheen { from { background-position: 0% 50%; } to { background-position: 100% 50%; } }
.switcher button { position: relative; z-index: 1; -webkit-tap-highlight-color: transparent; outline: none; border: 0; border-radius: 999px; background: transparent; color: var(--muted);
  font-family: Unbounded, Manrope, sans-serif; font-size: 15px; font-weight: 500; cursor: pointer; transition: color 250ms ease; }
.switcher button[aria-selected="true"] { color: var(--on-thumb); }
.switcher button:focus-visible { box-shadow: inset 0 0 0 2px var(--lilac); }
.stack { position: relative; padding-bottom: 9px; }
.stack-back { position: absolute; left: 14px; right: 14px; top: 10px; bottom: 0; border: 1px solid var(--stack-edge); border-radius: 22px;
  background: radial-gradient(ellipse 75% 100% at 100% 0%, var(--next-glow) 0%, transparent 70%), var(--stack-back); }
/* the landing's card: the mate's face beside the lines about them, ringed in their tint */
.stack-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.stack-face { flex: none; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; overflow: hidden; background: var(--raised);
  box-shadow: 0 0 0 2px var(--tint); cursor: zoom-in; }
.stack-face[hidden] { display: none; }
.stack-face img { display: block; width: 100%; height: 100%; object-fit: cover; }
.stack-head .stack-about { flex: 1 1 auto; min-width: 0; }
.stack-card { position: relative; z-index: 1; box-sizing: border-box; display: flex; flex-direction: column; gap: 6px;
  padding: 12px 12px 12px 18px; border-radius: 22px; cursor: pointer; box-shadow: var(--shadow-lift);
  background: radial-gradient(ellipse 75% 100% at 100% 0%, var(--glow) 0%, transparent 70%), var(--card); }
.stack .stack-about { margin: 0; font-size: 13.5px; font-weight: 500; line-height: 1.36; color: var(--fg); text-wrap: pretty; }
.voice-play { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px;
  border: 1px solid var(--card-edge); border-radius: 50%; background: var(--card); box-shadow: var(--shadow-card); color: var(--tint); cursor: pointer;
  -webkit-tap-highlight-color: transparent; transition: color 250ms ease; }
.voice-play:focus-visible { outline: 2px solid var(--lilac); outline-offset: 2px; }
.voice-play .icon-pause, .voice-play[aria-pressed="true"] .icon-play { display: none; }
.voice-play[aria-pressed="true"] .icon-pause { display: block; }
.stack .stack-now { display: block; min-width: 0; margin: 0; font-size: 13px; font-weight: 600; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stack-now::before { content: ""; display: inline-block; width: 7px; height: 7px; margin: 0 8px 1px 0; vertical-align: middle; border-radius: 50%; background: var(--tint); animation: pulse 1.6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .stack-now::before, .switcher-thumb { animation: none; } .switcher-thumb { transition: none; } }
/* What Mates can do: a row of four icons, the chosen one's card under it; the card keeps the height of three lines so
   switching does not move the page */
.features { display: flex; flex-direction: column; gap: 8px; }
.feature-tabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.feature-tab { display: flex; align-items: center; justify-content: center; height: 46px; border: 0; border-radius: 14px;
  background: var(--card); box-shadow: var(--shadow-card); color: var(--dim); cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 200ms ease, color 200ms ease, box-shadow 200ms ease; }
.feature-tab[aria-selected="true"] { background: var(--raised); color: var(--tint); box-shadow: inset 0 0 0 1.5px var(--tint); }
.feature-tab:focus { outline: none; }
.feature-tab:focus-visible { outline: 2px solid var(--lilac); outline-offset: 2px; }

/* The feature icons come alive in the chosen tab (and play once under a pointer): the book turns a page, the bubble
   chatters, the rays of the blown mind flash out, the plane flies off and comes back */
.ico * { transform-box: fill-box; }
.ico-book .page { transform-origin: left center; }
.feature-tab[aria-selected="true"] .ico-book .page { animation: page-turn 2.2s ease-in-out infinite; }
@keyframes page-turn {
  0%, 20% { transform: scaleX(1); }
  55% { transform: scaleX(-1); }
  56%, 100% { transform: scaleX(-1); opacity: 0; }
}
.ico-bla .bubble { transform-origin: 30% 100%; }
.feature-tab[aria-selected="true"] .ico-bla .bubble { animation: bubble-wobble 1.6s ease-in-out infinite; }
.feature-tab[aria-selected="true"] .ico-bla .bla1 { animation: bla-hop 0.8s ease-in-out infinite; }
.feature-tab[aria-selected="true"] .ico-bla .bla2 { animation: bla-hop 0.8s ease-in-out 0.4s infinite; }
@keyframes bubble-wobble { 0%, 100% { transform: rotate(-3deg); } 50% { transform: rotate(3deg); } }
@keyframes bla-hop { 0%, 100% { transform: translateY(0); } 40% { transform: translateY(-1.6px); } }
.ico-blown .ray { transform-origin: center; }
.feature-tab[aria-selected="true"] .ico-blown .ray { animation: ray-burst 1.4s ease-out infinite; }
.feature-tab[aria-selected="true"] .ico-blown .r2, .feature-tab[aria-selected="true"] .ico-blown .r3 { animation-delay: 0.08s; }
.feature-tab[aria-selected="true"] .ico-blown .r4, .feature-tab[aria-selected="true"] .ico-blown .r5 { animation-delay: 0.16s; }
.feature-tab[aria-selected="true"] .ico-blown .thought { animation: thought-wiggle 0.35s ease-in-out infinite alternate; }
@keyframes ray-burst {
  0% { opacity: 0; transform: scale(0.3) translateY(3px); }
  30% { opacity: 1; transform: scale(1.25) translateY(-1px); }
  70%, 100% { opacity: 0.25; transform: scale(1) translateY(0); }
}
@keyframes thought-wiggle { from { transform: translateX(-0.6px); } to { transform: translateX(0.6px); } }
.feature-tab[aria-selected="true"] .ico-plane .plane { animation: plane-fly 2.4s ease-in-out infinite; }
@keyframes plane-fly {
  0%, 15% { transform: translate(0, 0) scale(1); opacity: 1; }
  45% { transform: translate(9px, -9px) scale(0.6); opacity: 0; }
  46% { transform: translate(-9px, 9px) scale(0.6); opacity: 0; }
  75%, 100% { transform: translate(0, 0) scale(1); opacity: 1; }
}
@media (hover: hover) {
  .feature-tab:hover .ico-book .page { animation: page-turn 1.4s ease-in-out 1; }
  .feature-tab:hover .ico-bla .bla1 { animation: bla-hop 0.8s ease-in-out 2; }
  .feature-tab:hover .ico-bla .bla2 { animation: bla-hop 0.8s ease-in-out 0.4s 2; }
  .feature-tab:hover .ico-blown .ray { animation: ray-burst 1.2s ease-out 1; }
  .feature-tab:hover .ico-plane .plane { animation: plane-fly 1.8s ease-in-out 1; }
}
@media (prefers-reduced-motion: reduce) {
  .ico *, .feature-tab .ico * { animation: none !important; }
}
.feature-card { display: flex; flex-direction: column; gap: 4px; min-height: 84px; box-sizing: border-box; padding: 11px 14px 12px;
  border-radius: 16px; background: var(--card); box-shadow: var(--shadow-card); }
.feature-card b { font-size: 15px; font-weight: 600; }
.feature-title { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.feature-kind { flex: none; padding: 3px 9px; border-radius: 999px; background: var(--raised); color: var(--muted);
  font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.about .feature-card p { font-size: 13.5px; line-height: 1.4; }
/* The sign-up for the alpha under the pitch: inputs in the app's look, the call button's ring at an ordinary height; once
   it is in, the form gives way to one muted line */
.apply { display: flex; flex-direction: column; gap: 10px; }
.apply .label { padding: 0 4px; }
.apply form { display: flex; gap: 8px; }
.apply input {
  flex: 1 1 auto; min-width: 0; height: 48px; padding: 0 12px; border: 1px solid var(--raised); border-radius: 16px;
  background: var(--card); box-shadow: var(--shadow-card); color: var(--fg); font: inherit; font-size: 16px;
}
.apply input::placeholder { color: var(--dim); }
.apply input:focus { outline: 2px solid var(--lilac); outline-offset: 1px; }
.apply input:disabled { opacity: 0.6; }
.apply .ring-button { flex: none; width: 116px; height: 48px; box-shadow: 0 12px 30px var(--ring-glow); }
.apply .ring-inner { font-size: 14.5px; }
.apply .status { padding: 0 4px; text-align: left; }
.apply-hint { margin: 0; font-size: 14px; line-height: 1.42; color: var(--muted); text-wrap: pretty; }  /* flush with the pitch's paragraphs */
.apply-done { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.apply-done p { margin: 0; font-size: 15px; line-height: 1.4; color: var(--muted); text-wrap: pretty; }
.apply-done .text-link { align-self: flex-start; margin-left: -12px; }  /* its own padding: the words align with the line above */
.week { display: flex; flex-direction: column; gap: 10px; }
.week .caption { font-size: 13px; color: var(--dim); }
/* The week, one row Пн..Вс: only whether the learner practised matters. A day with calls is a green circle with a check,
   or the number of calls when there were more; the latest call's day is a pill that also says how long and with whom, its
   check or number on a solid green badge so "2" never runs into "20 мин". A day without a call is an empty ring, today
   before its call a lilac one, the days ahead a dotted one. The size follows the width: 24 px circles at 356, 27 at 390,
   30 at most. Each day is a button (app.js renderWeek), ready to open that day's letters later */
.days {
  --d: 26px;  /* a WebView without clamp(): the pill shortens its words with an ellipsis if it must */
  --wk-ring: color-mix(in srgb, var(--faint) 72%, transparent);
  --wk-dots: color-mix(in srgb, var(--faint) 80%, transparent);
  container-type: inline-size;
  display: flex; align-items: center; justify-content: space-between; gap: 4px;
}
/* without container units, by the page's width: the row is the page less main's 24 px sides, up to its 480 px */
@supports (width: clamp(1px, 1vw, 2px)) { .days { --d: clamp(24px, calc((100vw - 198px) / 7), 30px); } }
@supports (width: 1cqw) { .days { --d: clamp(24px, calc((100cqw - 150px) / 7), 30px); } }
.day {
  position: relative; isolation: isolate; flex: none; display: inline-flex; align-items: center;
  height: var(--d); min-width: var(--d); margin: 0; padding: 0;
  border: 1.5px solid transparent; border-radius: 999px; background: none;
  color: var(--faint); font-family: inherit; font-size: 11px; font-weight: 600; line-height: 1;
  cursor: default; -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: transform 140ms ease;
}
.day::after { content: ""; position: absolute; inset: -10px -2px; }  /* a 44 px tall finger target */
.day:first-child::after { left: 0; }
.day:last-child::after { right: 0; }
.day-mark { position: relative; flex: none; display: grid; place-items: center; width: calc(var(--d) - 3px); height: 100%; }
.day-mark svg { display: block; width: 13px; height: 13px; }
.day-mark path { stroke-width: 3; }  /* the check drawn a little bolder than in the chips, as small as it is here */

.day.is-empty { border-color: var(--wk-ring); color: var(--dim); }  /* a day gone by without a call */
.day.is-future { border-style: dotted; border-color: var(--wk-dots); }  /* a day ahead: quieter */
.day.is-today { border-color: var(--lilac); color: var(--lilac); }  /* today before its call, as «Сегодня» was */

.day.is-done { color: var(--teal); font-size: 13px; font-weight: 700; cursor: pointer; }
.day.is-done::before { content: ""; position: absolute; z-index: -1; inset: -1.5px; border-radius: inherit; background: var(--teal-bg); }

/* The latest call's day: the badge, then how long and with whom */
.day.is-latest { flex: 0 1 auto; min-width: var(--d); }
.day.is-latest .day-mark { color: var(--teal-bg); font-size: 12px; }
.day.is-latest .day-mark svg { width: 11px; height: 11px; }
.day.is-latest .day-mark::before, .day.is-leaving .day-mark::before { content: ""; position: absolute; z-index: -1; left: 50%; top: 50%;
  width: calc(var(--d) - 7px); height: calc(var(--d) - 7px); margin: calc((var(--d) - 7px) / -2) 0 0 calc((var(--d) - 7px) / -2);
  border-radius: 50%; background: var(--teal); }
.day-tail { display: grid; grid-template-columns: 1fr; min-width: 0; }
.day-text { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 13px; font-weight: 600; }
.day-text > span { padding: 0 10px 0 3px; }  /* inside the clip, so a folded pill is its circle exactly */

/* A tap, for now: the day gives under the finger and darkens a shade; later it opens that day's letters */
.day.is-done::before { transition: background-color 140ms ease; }
.day.is-done:active { transform: scale(0.92); }
.day.is-done:active::before { background: color-mix(in srgb, var(--teal) 18%, var(--teal-bg)); }
.day.is-latest:active { transform: scale(0.96); }
.day:focus { outline: none; }
.day:focus-visible { outline: 2px solid var(--lilac); outline-offset: 0; }  /* hugging the day: the gap to the next is 4 px at 356 */

/* A call has landed, 0.9 s. Today's lilac ring fills green and its check pops onto the badge (0-0.55 s); then the old
   pill folds its words back into its circle while today opens into the new pill, on the same curve, so the row keeps
   its length and the pill seems to travel from the old day to today (0.38-0.9 s). A day gone by (a call seen only after
   its day) fills from its quiet ring instead. app.js adds the classes, and none of them under reduced motion */
.day-was { position: absolute; left: 0; top: 0; display: grid; place-items: center; width: calc(var(--d) - 3px); height: 100%;
  color: var(--was-ink); font-size: 11px; font-weight: 600; animation: day-hush 160ms ease-in 60ms both; }
.day.is-landing { --was-ring: var(--lilac); --was-ink: var(--lilac); animation: day-ring-out 240ms ease-out 80ms both; }
.day.is-landing.was-empty { --was-ring: var(--wk-ring); --was-ink: var(--dim); }
.day.is-landing::before { animation: day-fill 380ms cubic-bezier(0.3, 1.4, 0.5, 1) 80ms both; }
.day.is-landing .day-mark { animation: day-pop 340ms cubic-bezier(0.3, 1.6, 0.5, 1) 220ms both; }
.day.is-landing .day-tail { animation: day-open 420ms cubic-bezier(0.45, 0, 0.2, 1) 380ms both; }
.day.is-landing .day-text { text-overflow: clip; animation: day-say 300ms ease-out 580ms both; }
.day.is-leaving .day-mark { animation: day-ink 300ms ease-out 380ms both; }
.day.is-leaving .day-mark::before { animation: day-unbadge 300ms ease-in 380ms both; }
.day.is-leaving .day-tail { animation: day-fold 420ms cubic-bezier(0.45, 0, 0.2, 1) 380ms both; }
.day.is-leaving .day-text { text-overflow: clip; animation: day-hush 150ms ease-in 380ms both; }
/* Another call on the same day: the pill stays, its badge bumps as it counts up and the words brighten into the new sum */
.day.is-more .day-mark { animation: day-bump 460ms cubic-bezier(0.3, 1.5, 0.5, 1) 60ms; }
.day.is-more .day-text { animation: day-brighten 420ms ease-out 120ms backwards; }

@keyframes day-hush { to { opacity: 0; } }
@keyframes day-ring-out { from { border-color: var(--was-ring); } to { border-color: transparent; } }
@keyframes day-fill { from { transform: scale(0); } }
@keyframes day-pop { from { opacity: 0; transform: scale(0.4); } }
@keyframes day-open { from { grid-template-columns: 0fr; } }
@keyframes day-say { from { opacity: 0; transform: translateX(-4px); } }
@keyframes day-fold { from { grid-template-columns: 1fr; } to { grid-template-columns: 0fr; } }
@keyframes day-ink { from { color: var(--teal-bg); } }
@keyframes day-unbadge { to { opacity: 0; transform: scale(0.5); } }
@keyframes day-bump { 35% { transform: scale(1.2); } }
@keyframes day-brighten { from { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .day, .day.is-done::before { transition: none; } }
.status { margin: 0; min-height: 1.4em; text-align: center; font-size: 14px; color: var(--muted); }
.status.error { color: var(--end); }
.status-detail { display: block; margin-top: 2px; font-size: 12px; color: var(--muted); overflow-wrap: anywhere; } /* the technical message under a call's line */

/* The primary button: dark glass (cream on paper) with a living ring in the light's colours */
.ring-button {
  position: relative; display: block; width: 100%; height: 60px; padding: 0; border: 0; border-radius: 999px;
  overflow: hidden; isolation: isolate; background: transparent; cursor: pointer; font: inherit; color: var(--fg);
  box-shadow: 0 16px 40px var(--ring-glow);
}
.ring-button:disabled { opacity: 0.5; cursor: default; }
.ring { position: absolute; left: 50%; top: 50%; width: 600px; height: 600px; margin: -300px 0 0 -300px; animation: spin 7s linear infinite;
  background: var(--ring-night); }
body[data-time="day"] .ring { background: var(--ring-day); }
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.ring-inner { position: absolute; inset: 2px; border-radius: 999px; background: var(--ring-inner); display: flex; align-items: center; justify-content: center; gap: 10px; font-size: 18px; font-weight: 700; }

.ghost-button, .end-button {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; height: 56px; border-radius: 999px;
  font: inherit; font-size: 16px; font-weight: 600; color: var(--fg); cursor: pointer;
}
.ghost-button { background: transparent; border: 1px solid var(--pill-edge); }
/* A hang-up, not a slab: a compact pill in the warm red of the screen, the handset facing down */
.end-button { width: auto; height: 52px; margin: 0 auto; padding: 0 26px 0 20px; background: var(--end-bg); border: 1px solid var(--end-line); color: var(--end-text); }
.end-button:active { background: var(--end-press); }
.end-button:disabled, .ghost-button:disabled { opacity: 0.5; cursor: default; }

/* Connecting */
.knocking { font-size: 24px; line-height: 1.2; }
.dots span { animation: pulse 1.4s ease-in-out infinite; }
.dots span:nth-child(2) { animation-delay: 0.25s; }
.dots span:nth-child(3) { animation-delay: 0.5s; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* Call */
.clock { position: relative; font-size: 14px; letter-spacing: 0.04em; color: var(--muted); }
.clock .muted { color: var(--clock-total); transition: color 400ms ease; }
/* A call that grew: "+5 мин" pops up left of the clock for a few seconds, in the learner's teal (it was their yes), and
   the new total is lit as long. It floats, so the clock never moves. */
.extended {
  position: absolute; top: 50%; right: calc(100% + 8px); padding: 3px 9px; border-radius: 999px; white-space: nowrap; pointer-events: none;
  font: 700 12px/1.3 Manrope, "Segoe UI", system-ui, sans-serif; letter-spacing: 0; color: var(--teal); background: var(--teal-bg);
  opacity: 0; transform: translateY(-50%) scale(0.8); transition: opacity 400ms ease, transform 400ms ease;
}
.extended.is-on { opacity: 1; transform: translateY(-50%) scale(1); transition-duration: 250ms; transition-timing-function: cubic-bezier(0.3, 1.4, 0.6, 1); }
.clock .muted.is-grown { color: var(--teal); }
@media (prefers-reduced-motion: reduce) { .extended, .extended.is-on { transform: translateY(-50%); } }
.progress { height: 3px; border-radius: 999px; background: var(--track); overflow: hidden; }
.progress-fill { width: 0; height: 100%; border-radius: 999px; background: var(--accent); transition: width 1s linear, background 900ms ease; }
.feed { list-style: none; margin: 0; padding: 0; flex-grow: 1; display: flex; flex-direction: column; justify-content: center; gap: 22px; overflow: hidden; }
.feed li { max-width: 92%; font-size: 17px; line-height: 1.4; color: var(--muted); text-wrap: pretty; }
.feed li.you { align-self: flex-end; text-align: right; }
.feed li.sasha { color: var(--faint); }
.feed li.sasha.current { font-size: 24px; line-height: 1.3; font-weight: 600; letter-spacing: -0.01em; color: var(--fg); }
.feed li.you.live { color: var(--fg); }
.feed mark { background: transparent; color: inherit; border-bottom: 3px solid var(--lilac); padding-bottom: 1px; }
/* one line taller than the room: its end stays in view and its beginning fades out under the progress bar (a mask
   reads only alpha, so its #000 is not a colour) */
.feed.overflowing { justify-content: flex-end; -webkit-mask-image: linear-gradient(to bottom, transparent, #000 56px); mask-image: linear-gradient(to bottom, transparent, #000 56px); }
.mode-line { display: flex; align-items: center; justify-content: center; gap: 8px; font-size: 14px; font-weight: 600; color: var(--muted); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); animation: pulse 1.6s ease-in-out infinite; transition: background 900ms ease; }
body[data-mode="listening"] .dot { background: var(--teal); }

/* PRO mode: no transcript during the call, only the voice */
[hidden] { display: none !important; }
/* for a screen reader only: out of sight, and out of any flex row it sits in */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
.icon-button { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin: -11px; border: 0; border-radius: 50%; background: transparent; color: var(--muted); cursor: pointer; }
.icon-button:hover { color: var(--fg); }
.stats .chip { padding: 8px 12px; }
.chip-score { background: var(--card); box-shadow: var(--shadow-card); color: var(--lilac); }
.chip-level { background: var(--card); box-shadow: var(--shadow-card); color: var(--sun); gap: 6px; }
.chip-level strong { color: var(--fg); font-weight: 700; }
.chip-next { color: var(--dim); font-weight: 500; }
body[data-screen="settings"] .screen-settings { display: flex; }
.settings-group { display: flex; flex-direction: column; gap: 8px; }
.settings-group .label { padding: 0 4px 4px; }
.row { display: flex; align-items: center; justify-content: space-between; gap: 14px; width: 100%; min-height: 64px; padding: 12px 18px; border: 0; border-radius: 18px; background: var(--card); box-shadow: var(--shadow-card); color: var(--fg); font: inherit; text-align: left; cursor: pointer; }
.row.static { cursor: default; }
.row:disabled { opacity: 0.6; cursor: default; }  /* the choice is on its way to the profile */
.rows { display: flex; flex-direction: column; gap: 8px; }  /* a radiogroup of rows: one per companion */
/* a mate with a photo: the whole scene small on the left, their name and city beside it, the radio on the right, the hint
   across the row under them */
.row.has-photo { display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; grid-template-areas: "photo text radio" "hint hint hint";
  align-items: center; column-gap: 14px; row-gap: 10px; padding: 12px 18px 14px 12px; }
.row.has-photo .row-photo { grid-area: photo; position: relative; display: block; width: 96px; max-width: 100%; aspect-ratio: 3 / 2;
  border-radius: 10px; overflow: hidden; background: var(--raised); cursor: zoom-in; }
.row-photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.row-photo-expand { position: absolute; right: 5px; bottom: 5px; padding: 4px; box-sizing: content-box; border-radius: 50%;
  background: rgba(21, 18, 28, 0.62); color: #f4f1ec; }  /* on the photo in both themes: it opens the whole scene */

/* The whole scene of a mate's photo, over the page; a tap anywhere closes it */
.photo-viewer { width: min(960px, calc(100vw - 24px)); max-width: none; max-height: none; padding: 0; border: 0; background: transparent;
  color: #f4f1ec; overflow: visible; }
.photo-viewer::backdrop { background: rgba(10, 8, 14, 0.9); }
.photo-viewer-figure { margin: 0; display: grid; gap: 12px; }
.photo-viewer-figure img { display: block; width: 100%; height: auto; max-height: calc(100dvh - 120px); object-fit: contain; border-radius: 14px; }
.photo-viewer-figure figcaption { font-size: 15px; font-weight: 600; text-align: center; }
.photo-viewer-close { position: fixed; top: max(16px, env(safe-area-inset-top)); right: 16px; display: grid; place-items: center;
  width: 44px; height: 44px; border: 0; border-radius: 50%; background: rgba(244, 241, 236, 0.14); color: #f4f1ec; cursor: pointer; }
.row.has-photo .row-text { grid-area: text; gap: 2px; }
.row.has-photo .radio { grid-area: radio; }
.row.has-photo > .row-hint { grid-area: hint; padding-left: 6px; }
.row-city { font-size: 13px; color: var(--dim); }
.row-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.row-title { font-size: 16px; font-weight: 600; }
.row-hint { font-size: 13px; color: var(--dim); line-height: 1.35; }
.switch { flex: none; width: 46px; height: 28px; border-radius: 999px; background: var(--switch-off); position: relative; transition: background 250ms ease; }
.switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: var(--knob); box-shadow: var(--knob-shadow); transition: transform 250ms ease, background 250ms ease; }
.row[aria-checked="true"] .switch { background: var(--lilac); }
.row[aria-checked="true"] .switch::after { transform: translateX(18px); background: var(--knob-on); }
.radio { flex: none; width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--control); }
.row[role="radio"][aria-checked="true"] .radio { border-color: var(--lilac); box-shadow: inset 0 0 0 5px var(--lilac); }
/* A segmented choice: a pill group on the raised surface, the chosen segment lit like a card */
.segments { display: inline-flex; flex: none; padding: 2px; border-radius: 999px; background: var(--raised); }
.segments button { min-width: 44px; height: 40px; padding: 0 14px; border: 0; border-radius: 999px; background: transparent; color: var(--muted); font: inherit; font-size: 15px; font-weight: 600; cursor: pointer; transition: background 250ms ease, color 250ms ease; }
.segments button[aria-checked="true"] { background: var(--lilac); color: var(--on-accent); }  /* a bubble, not a shade of the card */
.segments button[disabled] { opacity: 0.5; cursor: default; }
.segments-unit { flex: none; display: flex; align-items: center; gap: 8px; }
/* a row whose hint needs the width: the choice goes under the text, its segments sharing the row */
.row.stack { flex-direction: column; align-items: stretch; gap: 12px; }
.row.stack .segments { display: flex; }
.row.stack .segments button { flex: 1; }
.row.stack .segments-unit { align-self: stretch; }
.row.stack .segments-unit .segments { flex: 1; }
/* «Умная» beside three numbers: the word as wide as it needs, the numbers sharing the rest equally, so all fit at 356 px */
.row.stack .segments-unit .segments button[data-minutes="smart"] { flex: none; padding: 0 18px; }
.unit { font-size: 13px; color: var(--dim); }
/* «Язык»: the title, the chosen language's saying under it (the saying, then its Russian), and the saying's thing standing
   at the right on its last line, as if put down on it. Then the segments, each a letter over its name. */
.row-text.lang-head { display: grid; grid-template-columns: minmax(0, 1fr) 40px;
  grid-template-areas: "title thing" "sayings thing" "rules rules"; column-gap: 12px; row-gap: 6px; align-items: last baseline; }
.lang-head .row-title { grid-area: title; align-self: start; }
/* Every offered saying lies in one cell, only the chosen one shown: the cell is as tall as the tallest, so a choice never
   moves the card. Each sits at the cell's foot, so the last lines share one baseline with the thing. */
.sayings { grid-area: sayings; display: grid; }
.saying { grid-area: 1 / 1; display: flex; flex-direction: column; justify-content: flex-end; gap: 1px; margin: 0;
  opacity: 0; visibility: hidden; transition: opacity 160ms ease, visibility 0s linear 160ms; }
.saying.is-on { opacity: 1; visibility: visible; transition: opacity 220ms ease 190ms, visibility 0s linear 190ms; }
.say { font-size: 15px; font-weight: 600; line-height: 1.3; color: var(--fg); }
.sense { font-size: 13px; line-height: 1.35; color: var(--dim); }
/* the things, all in one cell; the box has 10 px of air on top, for the cherry and the grains */
.things { grid-area: thing; display: grid; justify-items: center; position: relative; top: 1px; }  /* the ink, not the box, on the baseline */
/* «Как читать по-испански» under the saying: a quiet link to the cheat sheet of the language chosen (app.js markLanguage). Its
   row is always in the grid (no :has, which older engines lack): every language offered has a set, so it is never hidden. */
.lang-head .rules-link { grid-area: rules; }
.thing { grid-area: 1 / 1; visibility: hidden; }
.thing.is-on { visibility: visible; }
/* an engine without last-baseline alignment (iOS before 16.2) would put the thing up beside «Язык»: at the saying's foot, raised
   by how far the Russian's line runs under its baseline */
@supports not (align-items: last baseline) { .things { align-self: end; margin-bottom: 4.5px; } }
/* the segments: a letter over the name, the name as every other segment's (15/600) */
.segments.lang button { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-width: 0; height: 60px; padding: 0 4px; }
.segments.lang .lang-name { line-height: 20px; white-space: nowrap; }  /* scoped: the admin's «Языки» has a .lang-name cell of its own */
.segments.lang button > .lang-name:only-child { margin-top: 26px; }  /* a language without a letter: its name on the others' line */
/* a choice plays on the tap (app.js chooseSegment): the bar stays at full strength while the choice is on its way */
.segments.lang button[disabled] { opacity: 1; }
/* line drawings with the app's pen: 2 px, round caps and joins, currentColor */
.glyph, .thing { flex: none; display: block; overflow: visible; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.glyph { color: var(--letter); transition: color 250ms ease; }
.glyph .mark { color: var(--lilac); transition: color 250ms ease; }
.segments.lang button[aria-checked="true"] .glyph { color: inherit; }
.segments.lang button[aria-checked="true"] .glyph .mark { color: var(--mark-on); }
.thing { color: var(--muted); }
.thing .mark { color: var(--lilac); }
.thing .solid { fill: currentColor; stroke: none; }
.thing .pulp { fill: var(--pulp); stroke: none; }
/* A choice, one beat (app.js markLanguage). The thumb's fill takes 250 ms; at 190 ms, as it lands, the chosen letter's mark
   says hello and the new thing, turned in from edge-on, does its gesture; the old thing has turned edge-on. Once, never on
   load; all still by 0.8 s (LANGUAGE_BEAT_MS). The rule of the set: the lilac part is the part that comes alive (the bar,
   the tilde, the cedilla; the cherry, the pulp, the grains). */
.glyph .mark, .thing .cherry, .thing .half, .thing .shaker, .thing .grains { transform-box: fill-box; }
.glyph[data-lang="en"] .mark { transform-origin: 100% 50%; }
.glyph[data-lang="es"] .mark { transform-origin: 50% 50%; }
.glyph[data-lang="fr"] .mark { transform-origin: 20% 0; }
/* th: the bar springs out of the h, shoots past the t into the open on the left and settles back (an overshoot to the right
   would hide under the h's shoulder); ñ: the tilde waves; ç: the cedilla swings */
@keyframes lang-bar { 0% { transform: scaleX(0); } 55% { transform: scaleX(1.18); } 78% { transform: scaleX(0.96); } 100% { transform: none; } }
@keyframes lang-wave { 0%, 100% { transform: none; } 30% { transform: translateY(-1.5px) rotate(-14deg); } 65% { transform: translateY(0.5px) rotate(8deg); } }
@keyframes lang-swing { 0%, 100% { transform: none; } 30% { transform: rotate(32deg); } 65% { transform: rotate(-12deg); } }
.segments.lang .play[data-lang="en"] .mark { animation: lang-bar 520ms cubic-bezier(0.3, 0.6, 0.4, 1) 190ms both; }
.segments.lang .play[data-lang="es"] .mark { animation: lang-wave 560ms cubic-bezier(0.45, 0, 0.35, 1) 190ms both; }
.segments.lang .play[data-lang="fr"] .mark { animation: lang-swing 580ms cubic-bezier(0.3, 0.6, 0.4, 1) 190ms both; }
/* the coin turn: the old thing goes edge-on, the new one comes round from edge-on */
@keyframes lang-coin-out { to { transform: perspective(120px) rotateY(90deg); } }
@keyframes lang-coin-in { from { transform: perspective(120px) rotateY(-90deg); } to { transform: none; } }
.thing.leaving { visibility: visible; animation: lang-coin-out 170ms cubic-bezier(0.5, 0, 1, 1) both; }
.thing.play { animation: lang-coin-in 200ms cubic-bezier(0, 0, 0.3, 1) 190ms both; }
.thing .cherry { transform-origin: 49% 100%; }
.thing .half, .thing .shaker, .thing .grains { transform-origin: 50% 100%; }
/* piece of cake: the cherry drops on, squashes as it lands, the slice gives 0.7 px under it, one small bounce; mi media
   naranja: the half rocks on its round side; grain de sel: the shaker shakes, the grains fly out and settle */
@keyframes lang-cherry { 0% { transform: translateY(-13px); opacity: 0; animation-timing-function: cubic-bezier(0.5, 0, 1, 1); }
  18% { opacity: 1; } 46% { transform: scale(1.16, 0.82); opacity: 1; animation-timing-function: ease-out; }
  64% { transform: translateY(-2.2px) scale(0.95, 1.06); animation-timing-function: ease-in; }
  80% { transform: scale(1.04, 0.96); } 100% { transform: none; opacity: 1; } }
@keyframes lang-dip { 0%, 44% { transform: none; } 52% { transform: translateY(0.7px); } 66%, 100% { transform: none; } }
@keyframes lang-wobble { 0%, 100% { transform: none; } 30% { transform: rotate(-9deg); } 62% { transform: rotate(5deg); } 84% { transform: rotate(-1.5deg); } }
@keyframes lang-shake { 0%, 100% { transform: none; } 22% { transform: rotate(-13deg); } 50% { transform: rotate(10deg); } 76% { transform: rotate(-4deg); } }
@keyframes lang-grains { 0% { transform: translateY(9px) scale(0.5); opacity: 0; } 40% { opacity: 1; } 70% { transform: translateY(-1.5px); } 100% { transform: none; opacity: 1; } }
.thing.play .cherry { animation: lang-cherry 520ms 260ms both; }
.thing.play .slice { animation: lang-dip 520ms ease 260ms both; }
.thing.play .half { animation: lang-wobble 520ms ease 240ms both; }
.thing.play .shaker { animation: lang-shake 520ms ease 220ms both; }
.thing.play .grains { animation: lang-grains 460ms ease-out 300ms both; }
@media (prefers-reduced-motion: reduce) {
  .segments.lang .play .mark, .thing.play, .thing.play *, .thing.leaving { animation: none !important; }
  .thing.leaving { visibility: hidden; }
  .saying, .saying.is-on, .glyph, .glyph .mark, .segments.lang button { transition: none !important; }
}
/* «Небо», the theme at the bottom of the settings (sky.js): the theme as the time of day over the companion's river. One
   body travels a dotted arc: the moon low over the water is «Тёмная», the sun high is «Светлая», and between them «Как в
   системе», at dawn when the phone is light and at dusk when it is dark. Drag the body, tap the sky or a name under it;
   the three names are the radiogroup. The picture is the same in both themes: its colours are its own, drawn by sky.js
   (the ground below is the night's, until the first drawing) */
@property --p { syntax: "<number>"; inherits: false; initial-value: 0; }
.theme-row { padding-bottom: 4px; }
.sky { --p: 0; position: relative; height: 112px; border-radius: 14px; overflow: hidden; background: #1c1836;
  cursor: pointer; touch-action: pan-y; user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent;
  view-transition-name: sky; }
.sky::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--sky-edge); pointer-events: none; }
.sky svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.sky.is-dragging { cursor: grabbing; }
/* The far bank: Petersburg for Саша, Moscow for Роджер. The one leaving sinks under the horizon as the other rises */
.sky-city { transition: opacity 360ms ease 120ms, transform 520ms cubic-bezier(0.22, 0.8, 0.3, 1) 120ms; }
.sky-city:not(.is-on) { opacity: 0; transform: translateY(10px); transition-duration: 260ms, 380ms; transition-delay: 0ms; }
/* The sky settles when the screen opens: two slow breaths of the stars and the glints, then it stays still */
.star { animation: twinkle 3.2s ease-in-out 2; }
@keyframes twinkle { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
.glint { transform-box: fill-box; transform-origin: center; animation: glint 2.8s ease-in-out 2; }
@keyframes glint { 0%, 100% { transform: scaleX(1); } 50% { transform: scaleX(0.74); } }
.sky-stops { display: grid; grid-template-columns: 1fr 1.34fr 1fr; margin-top: -4px; }
.sky-stop { display: flex; justify-content: center; align-items: flex-start; min-height: 44px; padding: 6px 2px 4px;
  border: 0; border-radius: 12px; background: transparent; color: var(--dim); font: inherit; font-size: 14px; font-weight: 600;
  line-height: 1.25; text-align: center; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: color 250ms ease; }
.sky-stop[aria-checked="true"] { color: var(--fg); font-weight: 700; }
.sky-stops.is-dragging .sky-stop { color: var(--dim); font-weight: 600; }
.sky-stops.is-dragging .sky-stop.is-near { color: var(--fg); font-weight: 700; }
/* One focus ring, round the name: the sky is a picture of the choice, not a second focus */
.sky-stop:focus { outline: none; }
.sky-label { display: inline-flex; flex-direction: column; align-items: center; gap: 1px; padding: 1px 7px; border-radius: 9px; }
.sky-stop:focus-visible .sky-label { outline: 2px solid var(--lilac); outline-offset: 2px; }
.sky-now { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 500; color: var(--faint); white-space: nowrap; }
.sky-now svg { flex: none; }
/* Narrower than the 356 px the page is drawn for (a 320 px phone): the names a size smaller, so the three still stand
   under the sky and the sun keeps its rays */
@media (max-width: 349px) {
  .sky-stop { font-size: 13px; }
  .sky-label { padding: 1px 3px; }
  .sky-now { font-size: 11px; }
}
@media (prefers-reduced-motion: reduce) { .star, .glint { animation: none; } .sky-stop, .sky-city { transition: none; } }
/* The wash: the new theme spreads over the old from where the body now stands. Night comes straight in from the moon
   with a soft rim; morning blooms from the sun, all feather and no hard core. Nothing tints the page on the way. The sky
   stays live above it (its own view-transition group). The mask grows in sky.js, from nothing to past the far corner
   (a mask reads only alpha, so its #000 is not a colour) */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-new(root) {
  -webkit-mask: radial-gradient(closest-side, #000 50%, transparent) 0 0 / 0 0 no-repeat;
  mask: radial-gradient(closest-side, #000 50%, transparent) 0 0 / 0 0 no-repeat;
}
html[data-wash="dusk"]::view-transition-new(root) {
  -webkit-mask-image: radial-gradient(closest-side, #000 58%, rgba(0, 0, 0, 0.55) 80%, transparent);
  mask-image: radial-gradient(closest-side, #000 58%, rgba(0, 0, 0, 0.55) 80%, transparent);
}
html[data-wash="dawn"]::view-transition-new(root) {
  -webkit-mask-image: radial-gradient(closest-side, #000 54%, rgba(0, 0, 0, 0.6) 74%, rgba(0, 0, 0, 0.2) 90%, transparent);
  mask-image: radial-gradient(closest-side, #000 54%, rgba(0, 0, 0, 0.6) 74%, rgba(0, 0, 0, 0.2) 90%, transparent);
}
::view-transition-group(sky), ::view-transition-new(sky) { animation: none; }
::view-transition-old(sky) { display: none; }
.screen-connecting .bar .caption { text-align: right; }  /* the length line wraps to two lines next to the wordmark */
body[data-text="off"] .feed { display: none; }
/* the call screen never scrolls: the light is the interface, and a scrolled page hides the end button */
body[data-screen="call"] { overflow: hidden; overscroll-behavior: none; }
body[data-screen="call"] main { height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; }
body[data-screen="call"] .screen-call { height: 100%; min-height: 0; }
.screen-call .mode-row { margin-top: auto; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 16px; }
.screen-call .mode-line { flex-basis: 100%; }  /* the state on its own line, the pills side by side under it */  /* with the feed gone, the state and the button still sit at the bottom */
.peek { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 12px; border: 1px solid var(--pill-edge); border-radius: 999px; background: transparent; color: var(--muted); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; }
.peek[aria-pressed="true"] { border-color: var(--lilac); color: var(--lilac); }
/* «Не слышно?»: in the sun's colour, nudging until it is tapped or her voice comes */
.screen-call .hear-line { flex-basis: 100%; display: flex; justify-content: center; }
.peek.hear { border-color: var(--sun-fill); color: var(--sun); background: var(--sun-bg); animation: hear-nudge 1.6s ease-in-out infinite; }
@keyframes hear-nudge { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
@media (prefers-reduced-motion: reduce) { .peek.hear { animation: none; } }
/* «Текст» in the call: lit with the captions icon while the text shows, crossed out and quiet when it is off */
.text-switch .icon-off, .text-switch[aria-pressed="false"] .icon-on { display: none; }
.text-switch[aria-pressed="false"] .icon-off { display: block; }
.agenda { gap: 10px; }
.agenda-task, .agenda-phrase { margin: 0; font-size: 16px; line-height: 1.4; text-wrap: pretty; }
.agenda-phrase { color: var(--teal); }
.agenda-task:empty, .agenda-phrase:empty { display: none; }
.agenda .chips:empty { display: none; }
.agenda-practice, .agenda-lines { display: flex; flex-direction: column; gap: 6px; }
.letter { display: flex; align-items: center; gap: 14px; width: 100%; padding: 14px 16px 14px 14px; border: 1px solid var(--card-edge); border-radius: 20px; background: var(--card); box-shadow: var(--shadow-card); color: var(--fg); font: inherit; text-align: left; cursor: pointer; }
.letter:hover { border-color: var(--line); }
.letter:disabled { opacity: 0.6; cursor: default; }  /* its report is on its way */
.letters { display: flex; flex-direction: column; gap: 10px; }
.letter-icon { flex: none; display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 14px; background: var(--raised); color: var(--accent); }
.letter-text { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.letter-line { font-size: 15px; line-height: 1.35; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.go { flex: none; color: var(--dim); }  /* the chevron at the end of a letter or a row that opens something, never squeezed */
/* The letter still being written: not a button yet, the pen writes and three dots type, as in a messenger; under the line,
   a quiet note of what is coming. Late, the pen rests and the dots go */
.letter-writing { cursor: default; }
.letter-writing:hover { border-color: var(--card-edge); }
.letter-writing .letter-line { white-space: normal; }  /* a long name wraps the line rather than cutting it */
.letter-note { font-size: 13px; line-height: 1.35; color: var(--muted); text-wrap: pretty; }  /* no lone word on its last line */
.letter-writing .pen { transform-origin: 20% 80%; animation: pen-write 1.4s ease-in-out infinite; }
@keyframes pen-write { 0%, 100% { transform: translate(0, 0) rotate(0deg); } 25% { transform: translate(1.5px, -1px) rotate(-6deg); } 50% { transform: translate(3px, 0) rotate(0deg); } 75% { transform: translate(1.5px, 1px) rotate(4deg); } }
.letter-writing.late .pen { animation: none; }
.letter-writing.late .typing { display: none; }
.typing { display: inline-flex; gap: 3px; margin-left: 5px; vertical-align: middle; }
.typing i { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); opacity: 0.25; animation: typing 1.2s ease-in-out infinite; }
.typing i:nth-child(2) { animation-delay: 0.2s; }
.typing i:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing { 0%, 60%, 100% { opacity: 0.25; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-2px); } }
@media (prefers-reduced-motion: reduce) { .letter-writing .pen, .typing i { animation: none; } .typing i { opacity: 0.6; } }
.status:empty { display: none; }

/* Report */
body[data-screen="report"] .screen-report { display: flex; }
.report-intro { margin: 0; font-size: 20px; font-weight: 600; line-height: 1.35; text-wrap: pretty; }
.tile { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px; border-radius: 22px; background: var(--card); box-shadow: var(--shadow-card); }
.score-tile { flex-direction: row; align-items: center; gap: 18px; }
.score { display: flex; align-items: baseline; gap: 6px; font-family: Unbounded, Manrope, sans-serif; }
.score > span:first-child { font-size: 56px; font-weight: 500; line-height: 1; color: var(--lilac); }
.score-of { font-size: 16px; color: var(--dim); }
/* the number with its parts under it, «активность 100 · качество 68»: the line takes the number's width and wraps there */
.score-main { display: flex; flex-direction: column; gap: 6px; }
.score-parts { width: 0; min-width: 100%; font-size: 12px; font-weight: 600; line-height: 1.3; color: var(--dim); }
.score.short > span:first-child { font-size: 19px; line-height: 1.2; }  /* «короткий звонок» in place of a number */
.score.short .score-of { display: none; }
/* «?» after the parts: a 20 px circle in the 2 px line, a 40 px target around it; its popover drops under the tile, over
   the tiles below, its tail at the «?» (--tail-x, app.js setScoreHelpOpen). The admin's «?» has its own (admin.css) */
.score-tile { position: relative; }
.help-button { position: relative; display: inline-flex; margin-left: 6px; padding: 0; border: 0; border-radius: 50%; background: transparent;
  color: var(--dim); vertical-align: -6px; cursor: pointer; }
.help-button::before { content: ""; position: absolute; inset: -10px; }
.help-button:hover, .help-button[aria-expanded="true"] { color: var(--lilac); }
#report-parts:empty + .help-button { margin-left: 0; }
.score-tile .help-pop { position: absolute; z-index: 30; top: calc(100% + 10px); left: 0; right: 0; display: flex; flex-direction: column; gap: 10px;
  padding: 14px 18px 18px; border: 1px solid var(--line); border-radius: 20px; background: var(--pop-bg); box-shadow: var(--shadow-pop);
  font-family: Manrope, sans-serif; font-size: 14px; line-height: 1.45; color: var(--comment); }
.score-tile .help-pop[hidden] { display: none; }
main[data-help-open] { -webkit-tap-highlight-color: transparent; }  /* main listens for the tap outside it: no flash of all of it */
.score-tile .help-pop:focus { outline: none; }  /* the box the focus is moved to, to be read; nothing in it to press but the cross */
.score-tile .help-pop::before { content: ""; position: absolute; top: -7px; left: calc(var(--tail-x, 40px) - 6px); width: 12px; height: 12px;
  border-top: 1px solid var(--line); border-left: 1px solid var(--line); border-top-left-radius: 3px; background: var(--pop-bg); transform: rotate(45deg); }
.help-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.score-tile .help-title { margin: 0; font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--fg); }
.help-head .icon-button { flex: none; margin: -12px -12px -12px 0; }
.help-why { margin: 0; font-weight: 700; color: var(--fg); text-wrap: pretty; }
.help-why[hidden] { display: none; }
.help-how { display: flex; flex-direction: column; gap: 8px; }
.help-how p { margin: 0; text-wrap: pretty; }
.help-figures { display: flex; flex-direction: column; gap: 6px; padding-top: 12px; border-top: 1px solid var(--line); }
.help-figures[hidden] { display: none; }
.help-figures .label { font-size: 11px; color: var(--muted); }  /* --dim is too faint on --pop-bg */
.help-figures ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.help-figures li { text-wrap: pretty; }
.help-figures strong { font-weight: 700; color: var(--fg); }
.score-meta { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.cheer { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; font-size: 14px; line-height: 1.3; color: var(--fg); }
.cheer li strong { color: var(--lilac); font-weight: 700; }
.label { font-size: 12px; font-weight: 700; letter-spacing: 0.1em; color: var(--dim); }
.score-line { display: flex; align-items: center; gap: 8px; }
.delta { font-size: 13px; font-weight: 700; color: var(--teal); background: var(--teal-bg); border-radius: 999px; padding: 3px 9px; }
.delta.down { color: var(--end); background: var(--down-bg); }
.block-title { display: flex; align-items: center; gap: 10px; font-size: 17px; font-weight: 700; }
.tone-sun { color: var(--sun-fill); }  /* the report's block icons, drawn in currentColor */
.tone-lilac { color: var(--lilac); }
.tone-teal { color: var(--teal); }
.quote { margin: 0; font-size: 16px; line-height: 1.4; text-wrap: pretty; }
.quote.you { color: var(--dim); }
.quote mark { background: transparent; color: var(--fg); border-bottom: 3px solid var(--lilac); padding-bottom: 1px; font-weight: 700; }
.comment { margin: 0; font-size: 15px; line-height: 1.45; color: var(--comment); text-wrap: pretty; }
.comment:empty { display: none; }
/* The other slips: the tile's title is the button, so the whole header is the tap target and the tile looks like its neighbours until opened */
.tile-slips { gap: 0; padding: 0; }
.slips-toggle { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 44px; padding: 18px 20px; border: 0; border-radius: 22px; background: transparent; color: var(--fg); font: inherit; font-size: 17px; font-weight: 700; text-align: left; cursor: pointer; }
.slips-toggle:hover .chevron { color: var(--fg); }
.slips-title { flex-grow: 1; }
.slips-count { color: var(--dim); font-weight: 600; }
.slips-count:not(:empty)::before { content: "· "; }
.chevron { flex: none; color: var(--dim); transition: transform 250ms ease; }
.slips-toggle[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.slips { list-style: none; margin: 0; padding: 0 20px 18px; display: flex; flex-direction: column; }
.slips li { display: flex; flex-direction: column; gap: 4px; padding: 12px 0; border-top: 1px solid var(--raised); }
.slips li:last-child { padding-bottom: 0; }
.slip-said, .slip-better { font-size: 15px; }  /* a step below the one correction above: the quote stays dim, the better line lit */
.slip-why { font-size: 14px; color: var(--muted); }
/* in the "all" view a small signal meter opens the note: three bars of rising height filled by how much the slip matters -
   rough three in pink-red, noticeable two in orange, a minor thing that is not an error one in green - and the word after it */
.slip-severity { --tone: var(--rough); display: inline-flex; align-items: baseline; gap: 6px; margin-right: 8px; color: var(--tone); }
.slip-severity.noticeable { --tone: var(--noticeable); }
.slip-severity.minor { --tone: var(--minor); }
.meter { display: inline-flex; align-items: flex-end; gap: 2px; height: 11px; }
.meter .bar { width: 3px; height: 5px; border-radius: 1.5px; background: var(--meter-off); }
.meter .bar:nth-child(2) { height: 8px; }
.meter .bar:nth-child(3) { height: 11px; }
.meter .bar.on { background: var(--tone); }
.slip-severity-word { font-size: 12px; font-weight: 700; line-height: 1; }
.slips-hidden { font-size: 14px; color: var(--dim); }  /* the slips the view hides: a count and where the switch is */
@media (prefers-reduced-motion: reduce) { .chevron { transition: none; } }
.chip-word { background: var(--teal-bg); color: var(--teal); font-size: 15px; padding: 8px 12px; }
/* a word with its Russian: the chip is a button, the swap icon before the word, a tap shows the translation and a second one the word */
.chip-swap { gap: 6px; border: 0; font-family: inherit; line-height: inherit; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.chip-swap svg { flex: none; opacity: 0.75; }
.chip-swap[aria-pressed="true"] { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--teal) 45%, transparent); }
.chip-swap:focus { outline: none; }
.chip-swap:focus-visible { outline: 2px solid var(--lilac); outline-offset: 2px; }
.chip-pron { background: var(--raised); color: var(--fg); font-size: 15px; padding: 8px 12px; }
/* A phrase's speaker (listenButton in app.js): quiet until tapped, a 40 px target. While the sound loads its waves breathe;
   while it plays they pulse outwards in teal, drawn bolder, which says it without the motion too. */
.listen { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px; background: transparent; color: var(--dim); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.listen svg { display: block; }
.listen:focus { outline: none; }
.listen:focus-visible { outline: 2px solid var(--lilac); outline-offset: -3px; }
@media (hover: hover) { .listen:hover { color: var(--muted); } }
.listen[data-state="loading"] .wave { animation: listen-wait 1.1s ease-in-out infinite; }
.listen[data-state="playing"] .wave { animation: listen-wave 0.9s ease-in-out infinite; }
.listen[data-state="playing"] .wave-far { animation-delay: 0.18s; }
.listen[data-state="playing"] .wave { stroke-width: 2.75; }
@keyframes listen-wait { 50% { opacity: 0.15; } }
@keyframes listen-wave { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
/* a line with its speaker after it: the glyph by the line's first row, the target reaching into the card's padding */
.listen-line { display: flex; align-items: flex-start; gap: 2px; }
.listen-line > :first-child { flex: 1; min-width: 0; }
.listen-line > .listen { margin: -9px -11px -9px 0; }
.agenda-lines .listen-line + .listen-line { margin-top: 6px; }  /* the practice lines as far apart as the letter's: speakers 34 px apart */
/* a chip with a speaker: the word (or the button that flips it) from the chip's left edge, as tall as a chip without one; the
   speaker is its right end, drawn 30 px wide so two short chips still share a row on a phone, its target 40 px wide and
   tall all the same, reaching across the gap after the chip */
.chip-listen { gap: 0; padding: 0; }
.chip-listen > :first-child { align-self: stretch; display: inline-flex; align-items: center; gap: 6px; padding: 8px 0 8px 12px; }
.chip-listen .chip-swap { margin: 0; border-radius: 999px 0 0 999px; background: none; color: inherit; font-size: inherit; font-weight: inherit; }
.chip-listen .chip-swap[aria-pressed="true"] { box-shadow: none; }
.chip-listen.is-flipped { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--teal) 45%, transparent); }
.chip-listen .listen { position: relative; align-self: stretch; width: 30px; height: auto; padding: 0; color: inherit; }
.chip-listen .listen::after { content: ""; position: absolute; inset: -3px -10px -3px 0; }
.chip-listen .listen[data-state="idle"] svg { opacity: 0.7; }
:root[data-theme="light"] .chip-listen .listen[data-state="idle"] svg { opacity: 0.85; }  /* 3.8:1 on --teal-bg: a control's glyph needs 3:1 */
.listen[data-state="playing"] { color: var(--teal); }
.listen-note { margin: 0; font-size: 13px; line-height: 1.4; color: var(--dim); }
@media (prefers-reduced-motion: reduce) { .listen .wave { animation: none; } .listen[data-state="loading"] .wave { opacity: 0.35; } }
.task-block, .hook-block { display: flex; flex-direction: column; gap: 6px; padding: 0 4px; }
.task, .hook { margin: 0; font-size: 16px; line-height: 1.45; text-wrap: pretty; }
.task-block:has(.task:empty), .hook-block:has(.hook:empty) { display: none; }
.hook { color: var(--muted); font-style: italic; }
.sign { margin: 0; font-family: Unbounded, Manrope, sans-serif; font-size: 13px; color: var(--dim); }
.sign::before { content: "— "; }
.screen-report .ring-button { margin-top: auto; }
/* «Как это читается»: how one or two of a beginner's letter's phrases are read, each phrase with the rule's letters marked
   (the recast's mark), the rule under it, its explanation, and the mate's note set off by a lilac line */
.reading-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.reading-item { display: flex; flex-direction: column; gap: 6px; }
.reading-item + .reading-item { padding-top: 14px; border-top: 1px solid var(--raised); }
.reading-rule { margin: 2px 0 0; font-size: 15px; font-weight: 700; line-height: 1.35; text-wrap: pretty; }
.reading-item .comment { font-size: 14px; }  /* quieter than the letter's own notes: a hint, not a lesson */
.reading-item .reading-note, .rule-note { padding-left: 12px; border-left: 2px solid var(--lilac); font-size: 13px; line-height: 1.45; color: var(--muted); }
/* a link to the cheat sheet, in the letter and under «Язык»'s saying: lilac ink, a 40 px target that takes no room of its own */
.rules-link { justify-self: start; align-self: flex-start; min-height: 40px; margin: -10px 0 -10px -8px; padding: 0 8px; border: 0;
  background: transparent; color: var(--lilac); font: inherit; font-size: 14px; font-weight: 600; text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 3px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.rules-link:hover { color: var(--lilac-hover); }
.rules-link:focus { outline: none; }
.rules-link:focus-visible { outline: 2px solid var(--lilac); outline-offset: -4px; border-radius: 8px; }
.lang-head .rules-link { margin-top: -6px; font-size: 13px; }

/* «Как читать по-испански»: every rule, a sheet up from the bottom edge over the screen it was opened from, scrolling on
   its own; its head stays. The examples: the word with the rule's letters marked, how it sounds, and its speaker. */
.rules-sheet { width: 100%; max-width: 480px; height: auto; max-height: calc(100dvh - max(24px, env(safe-area-inset-top)));
  margin: auto auto 0; padding: 0; border: 0; border-radius: 24px 24px 0 0; background: var(--card); color: var(--fg);
  box-shadow: var(--shadow-sheet); overflow: hidden; }
.rules-sheet[open] { display: flex; flex-direction: column; animation: rules-up 300ms ease; }
.rules-sheet::backdrop { background: var(--scrim); }
@keyframes rules-up { from { transform: translateY(100%); } }
.rules-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 20px 20px 0; }
.rules-title { margin: 0; font-family: Unbounded, Manrope, sans-serif; font-size: 17px; font-weight: 500; line-height: 1.3; }
.rules-head .icon-button { margin: -11px -11px -11px 0; }
.rules-title .nowrap, .rules-link { white-space: nowrap; }
.rules-body { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 10px 20px max(24px, env(safe-area-inset-bottom));
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14px); mask-image: linear-gradient(to bottom, transparent, #000 14px); }
.rules-status { margin: 8px 0; font-size: 15px; color: var(--muted); }
.rules-status:empty { display: none; }
.rules-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.rule { display: flex; flex-direction: column; gap: 6px; padding: 16px 0; border-top: 1px solid var(--raised); }
.rule:first-child { padding-top: 4px; border-top: 0; }
.rule-title { margin: 0; font-size: 16px; font-weight: 700; line-height: 1.35; text-wrap: pretty; }
.rule-explain { margin: 0; font-size: 15px; line-height: 1.45; color: var(--comment); text-wrap: pretty; }
.rule-examples { list-style: none; margin: 2px 0 0; padding: 0; display: flex; flex-direction: column; }
.rule-example { display: flex; align-items: center; flex-wrap: wrap; column-gap: 10px; min-height: 40px; }
.rule-word { font-size: 16px; font-weight: 600; }
.rule-word mark { background: transparent; color: var(--fg); border-bottom: 2px solid var(--lilac); padding-bottom: 1px; font-weight: 800; }
.rule-sounds { font-size: 15px; color: var(--dim); }
.rule-example .listen { margin: 0 -11px 0 auto; }
.rule-note { margin: 4px 0 0; font-size: 14px; text-wrap: pretty; }
@media (prefers-reduced-motion: reduce) { .rules-sheet[open] { animation: none; } }

/* a quiet line under the letter: one tap to tell us what went wrong */
.text-link { align-self: center; min-height: 44px; padding: 0 12px; border: 0; background: transparent; color: var(--dim); font: inherit; font-size: 14px; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.text-link:hover { color: var(--muted); }

/* Feedback: a sheet that slides up from the bottom edge, over whatever screen is open */
.sheet { position: fixed; inset: 0; z-index: 10; display: flex; align-items: flex-end; justify-content: center; }
.sheet-backdrop { position: absolute; inset: 0; background: var(--scrim); opacity: 0; transition: opacity 300ms ease; }
.sheet-panel {
  position: relative; width: 100%; max-width: 480px; margin: 0; padding: 20px 16px max(20px, env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 12px; border-radius: 24px 24px 0 0; background: var(--card); box-shadow: var(--shadow-sheet);
  transform: translateY(100%); transition: transform 300ms ease;
}
.sheet.open .sheet-backdrop { opacity: 1; }
.sheet.open .sheet-panel { transform: none; }
.sheet-panel .label { padding: 0 4px; }
.sheet textarea {
  width: 100%; min-height: 120px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 16px; resize: vertical;
  background: var(--well); color: var(--fg); font: inherit; font-size: 16px; line-height: 1.4;
}
.sheet textarea:focus { outline: 2px solid var(--lilac); outline-offset: 1px; }
.sheet textarea::placeholder { color: var(--dim); }  /* as every other field's, not the browser's grey */
.sheet-status { margin: 0; min-height: 1.4em; padding: 0 4px; font-size: 14px; color: var(--teal); }
.sheet-status:empty { display: none; }
.sheet-send { height: 44px; border: 0; border-radius: 999px; background: var(--lilac); color: var(--on-accent); font: inherit; font-size: 16px; font-weight: 700; cursor: pointer; }
.sheet-send:disabled { opacity: 0.5; cursor: default; }
.sheet .ghost-button { height: 44px; }
@media (prefers-reduced-motion: reduce) { .sheet-panel, .sheet-backdrop { transition: none; } }

/* «Итоги и план»: the week's summary from a language's mates, a screen of its own (app.js showWeekly), as the approved mock
   drew it: their faces and the week's stamp, Форма first and largest with its 21 days, the road to the next level's mark
   and its dates, the plan with a face for each day, and what to go over, with speakers. A rise is teal and every drop
   honey, never the hang-up's red. Nothing on it moves but what the app's own parts move (a speaker, a chevron). */
body[data-screen="weekly"] .screen-weekly { display: flex; }
.screen-weekly .weekly-body { display: contents; }
.screen-weekly .delta.down { color: var(--sun); background: var(--sun-bg); }
.screen-weekly .delta.flat { color: var(--muted); background: var(--raised); }
.screen-weekly .faces { display: inline-flex; flex: none; }
.screen-weekly .faces img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; box-shadow: 0 0 0 2.5px var(--bg); }
.screen-weekly .faces img + img { margin-left: -10px; }
/* the head: whose page, the language and the week, and the week's number on a postage stamp */
.screen-weekly .week-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: -6px; }
.screen-weekly .week-row > div { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.screen-weekly .week-row .caption { font-size: 13px; color: var(--dim); }
.screen-weekly .stamp { flex: none; position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; width: 56px; height: 62px;
  background: linear-gradient(var(--card), var(--card)) center / calc(100% - 8px) calc(100% - 8px) no-repeat,
              radial-gradient(circle at center, transparent 2.1px, var(--card) 2.7px) -4px -4px / 8px 8px;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.22)); transform: rotate(4deg); }
.screen-weekly .stamp::before { content: ""; position: absolute; inset: 7px; border: 1.5px dashed var(--line); border-radius: 3px; }
.screen-weekly .stamp b { font: 500 22px/1 Unbounded, Manrope, sans-serif; color: var(--lilac); }
.screen-weekly .stamp span { margin-top: 5px; font-size: 8px; font-weight: 700; letter-spacing: 0.12em; color: var(--dim); }
/* the verdict: Форма, the 21 days it is made of, then the level and the learner's own words */
.screen-weekly .form-tile { gap: 14px; }
/* a score of three digits leaves the line beside it too little room: the line goes under it then (wide), and any line too
   long to sit beside the score wraps under it too */
.screen-weekly .form-top { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; }
.screen-weekly .form-top.wide { flex-direction: column; align-items: flex-start; gap: 10px; }
.screen-weekly .form-top.wide .form-meta { flex: none; padding-top: 0; }
.screen-weekly .form-score { display: flex; flex-direction: column; gap: 6px; flex: none; }
.screen-weekly .form-score .label, .screen-weekly .cell .label, .screen-weekly .sub-label .label { font-size: 11px; }
.screen-weekly .form-tile .score > span:first-child { font-size: 54px; }
.screen-weekly .form-meta { display: flex; flex: 1 1 120px; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; padding-top: 16px; }
.screen-weekly .form-line { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.35; text-wrap: pretty; }
.screen-weekly .strip { display: flex; align-items: flex-end; gap: 3px; height: 32px; }
.screen-weekly .strip i { flex: 1 1 0; min-width: 0; border-radius: 3px; background: var(--lilac); }
.screen-weekly .strip i.gap { flex: none; width: 5px; background: none; }
.screen-weekly .strip i.none { height: 4px; background: var(--meter-off); }
.screen-weekly .strip i.before { height: 4px; background: transparent; box-shadow: inset 0 0 0 1px var(--meter-off); }
.screen-weekly .strip-legend { display: flex; justify-content: space-between; margin-top: -8px; font-size: 12px; color: var(--dim); }
.screen-weekly .note-small { margin: 0; font-size: 13.5px; line-height: 1.42; color: var(--comment); text-wrap: pretty; }
.screen-weekly .cells2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); padding-top: 14px; border-top: 1px solid var(--raised); }
.screen-weekly .cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.screen-weekly .cell + .cell { padding-left: 16px; border-left: 1px solid var(--raised); }
.screen-weekly .cell-row { display: flex; align-items: center; gap: 8px; }
.screen-weekly .cell-value { font-family: Unbounded, Manrope, sans-serif; font-size: 24px; font-weight: 500; line-height: 1.15; }
.screen-weekly .cell-sub { font-size: 13px; color: var(--muted); }
.screen-weekly .v-level { color: var(--sun); }
.screen-weekly .v-words { color: var(--teal); }
/* the road to the next level's mark */
.screen-weekly .title-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.screen-weekly .title-row .block-title { min-width: 0; }
.screen-weekly .pct { font-family: Unbounded, Manrope, sans-serif; font-size: 17px; font-weight: 500; color: var(--lilac); white-space: nowrap; }
.screen-weekly .track { position: relative; height: 10px; border-radius: 999px; background: var(--raised); overflow: hidden; }
.screen-weekly .track b { position: absolute; inset: 0 auto 0 0; min-width: 10px; border-radius: 999px; background: var(--lilac); }
.screen-weekly .track-ends { display: flex; justify-content: space-between; gap: 8px; margin-top: -6px; font-size: 12px; color: var(--dim); }
.screen-weekly .big-line { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.3; }
.screen-weekly .big-line span { color: var(--dim); font-weight: 600; }
.screen-weekly .funnel { display: flex; flex-direction: column; gap: 9px; }
.screen-weekly .fun-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; font-size: 14px; color: var(--muted); }
.screen-weekly .fun-top b { font-size: 15px; color: var(--fg); white-space: nowrap; }
.screen-weekly .fun-top b small { margin-left: 6px; font-size: 12.5px; font-weight: 700; color: var(--teal); }
.screen-weekly .fun-bar { height: 4px; margin-top: 5px; border-radius: 999px; background: var(--raised); overflow: hidden; }
.screen-weekly .fun-bar i { display: block; height: 100%; border-radius: 999px; background: color-mix(in srgb, var(--teal-fill) 45%, transparent); }
.screen-weekly .fun-row.own .fun-top { color: var(--fg); font-weight: 700; }
.screen-weekly .fun-row.own .fun-bar i { background: var(--teal-fill); }
.screen-weekly .divider { height: 1px; margin: 2px 0; background: var(--raised); }
.screen-weekly .legend { display: flex; flex-direction: column; gap: 12px; }
.screen-weekly .leg { display: grid; grid-template-columns: 14px minmax(0, 1fr); column-gap: 12px; row-gap: 2px; align-items: start; }
.screen-weekly .leg-mark { width: 12px; height: 12px; margin-top: 4px; border-radius: 50%; }
.screen-weekly .leg-mark.daily { background: var(--lilac); }
.screen-weekly .leg-mark.pace { box-shadow: inset 0 0 0 2.5px var(--lilac); }
.screen-weekly .leg-label { font-size: 14px; line-height: 1.35; color: var(--muted); }
.screen-weekly .leg-date { grid-column: 2; font-size: 17px; font-weight: 700; line-height: 1.3; }
.screen-weekly .leg-was { grid-column: 2; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; margin-top: 3px; font-size: 13px; color: var(--dim); }
.screen-weekly .leg-was s { text-decoration-thickness: 1px; }
.screen-weekly .leg-was .delta { padding: 2px 8px; font-size: 12.5px; }
/* a disclosure inside a tile, the letter's slips-toggle in small: «Твои слова · 38», «Ещё 4 поправки» */
.screen-weekly .more-toggle { display: flex; align-items: center; gap: 8px; align-self: flex-start; min-height: 44px; margin: -4px 0 -6px; padding: 0; border: 0;
  background: transparent; color: var(--lilac); font: inherit; font-size: 15px; font-weight: 700; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.screen-weekly .more-toggle .count { color: var(--dim); font-weight: 600; }
.screen-weekly .more-toggle .chevron { color: var(--lilac); }
.screen-weekly .more-toggle[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.screen-weekly .own-words { display: flex; flex-wrap: wrap; gap: 6px; }
.screen-weekly .own-words span { padding: 5px 10px; border-radius: 999px; background: var(--raised); font-size: 14px; font-weight: 600; }
.screen-weekly .own-words[hidden], .screen-weekly .fix[hidden], .screen-weekly .fix-group[hidden], .screen-weekly .fix-rest[hidden] { display: none; }
/* a title of two lines keeps its icon by the first */
.screen-weekly .block-title { align-items: flex-start; }
.screen-weekly .block-title > svg { flex: none; margin-top: 1px; }
/* the plan: a mate's face over each day it has a call */
.screen-weekly .plan-days { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); justify-items: center; margin-top: 2px; }
.screen-weekly .pd { display: flex; flex-direction: column; align-items: center; gap: 7px; }
.screen-weekly .pd-face { width: 30px; height: 30px; border-radius: 50%; object-fit: cover; outline: 1.5px dashed var(--lilac); outline-offset: 2.5px; }
.screen-weekly .pd-face.none { outline-color: var(--line); background: transparent; }
.screen-weekly .pd-wd { font-size: 12px; font-weight: 700; color: var(--lilac); }
.screen-weekly .pd.off .pd-wd { color: var(--faint); }
.screen-weekly .pd-who { margin: -2px 0 0; font-size: 14px; line-height: 1.4; color: var(--comment); text-wrap: pretty; }
.screen-weekly .pd-who b { font-family: Unbounded, Manrope, sans-serif; font-size: 14px; font-weight: 500; color: var(--lilac); }
.screen-weekly .items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.screen-weekly .item { display: grid; grid-template-columns: 22px minmax(0, 1fr); column-gap: 12px; padding: 14px 0; border-top: 1px solid var(--raised); }
.screen-weekly .item:last-child { padding-bottom: 0; }
.screen-weekly .item > svg { margin-top: 1px; }
.screen-weekly .item-body { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.screen-weekly .item-title { font-size: 15.5px; font-weight: 700; line-height: 1.3; }
.screen-weekly .item-text { margin: 0; font-size: 14.5px; line-height: 1.42; color: var(--comment); text-wrap: pretty; }
/* a model's line may quote a long run the language's short words glue: it breaks inside a word before it leaves the column */
.screen-weekly .report-intro, .screen-weekly .item-text, .screen-weekly .fix-note, .screen-weekly .hook { overflow-wrap: anywhere; }
.screen-weekly .item .listen-line .quote { font-size: 15.5px; }
/* the app's phrase chip: grey while the learner has yet to say it, green once they have */
.screen-weekly .chips.tight { gap: 8px; }
.screen-weekly .chip-word.todo { background: var(--raised); color: var(--fg); }
.screen-weekly .chip-word.todo .chip-swap svg { opacity: 0.6; }
.screen-weekly .group-label { display: flex; align-items: center; gap: 5px; margin: 2px 0 -4px; font-size: 11px; font-weight: 700; letter-spacing: 0.1em; color: var(--dim); }
.screen-weekly .group-label.said { color: var(--teal); }
.screen-weekly .group-label svg { width: 13px; height: 13px; }
/* to go over: «Скажи так», the letters' phrases */
.screen-weekly .sub-label { display: flex; justify-content: space-between; gap: 8px; margin-top: 2px; }
.screen-weekly .sub-label .label + .label { text-align: right; }
.screen-weekly .sub-label.next-part { margin-top: 10px; }
.screen-weekly .fixes { display: flex; flex-direction: column; }
.screen-weekly .fix { display: flex; flex-direction: column; gap: 2px; padding: 11px 0; border-top: 1px solid var(--raised); }
.screen-weekly .fix:first-child { padding-top: 0; border-top: 0; }
.screen-weekly .fix-was { margin: 0; font-size: 13.5px; line-height: 1.35; color: var(--dim); }
.screen-weekly .fix-was s { text-decoration-thickness: 1px; }
.screen-weekly .fix .quote { font-size: 16px; }
.screen-weekly .fix-note { margin: 0; font-size: 13px; line-height: 1.35; color: var(--dim); text-wrap: pretty; }
.screen-weekly .fix-group { margin: 0; padding: 12px 0 2px; border-top: 1px solid var(--raised); font-size: 13.5px; font-weight: 600; color: var(--comment); text-wrap: pretty; }
.screen-weekly .fix-group + .fix { border-top: 0; }
.screen-weekly .fix-rest { margin: 0; padding-top: 12px; border-top: 1px solid var(--raised); font-size: 13px; line-height: 1.35; color: var(--dim); }
/* the week's numbers: the letter's slips tile, closed until asked */
.screen-weekly .nums-tile .slips-toggle { padding-bottom: 14px; }
.screen-weekly .nums-summary { margin: -6px 20px 18px 50px; font-size: 14px; color: var(--dim); }
.screen-weekly .nums { display: flex; flex-direction: column; padding: 0 20px 18px; }
.screen-weekly .nums[hidden], .screen-weekly .nums-summary[hidden] { display: none; }
.screen-weekly .num { display: flex; flex-direction: column; gap: 6px; padding: 12px 0; border-top: 1px solid var(--raised); }
.screen-weekly .num:last-child { padding-bottom: 0; }
.screen-weekly .num-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.screen-weekly .num-label { font-size: 14px; color: var(--muted); }
.screen-weekly .num-val { font-size: 15px; font-weight: 700; white-space: nowrap; }
.screen-weekly .num-sub { margin: 0; font-size: 13.5px; line-height: 1.4; color: var(--dim); text-wrap: pretty; }
.screen-weekly .num-sub:empty { display: none; }
.screen-weekly .split { display: flex; height: 8px; border-radius: 999px; overflow: hidden; background: var(--raised); }
.screen-weekly .split b { background: var(--teal-fill); }
.screen-weekly .split b + b { background: color-mix(in srgb, var(--teal-fill) 35%, transparent); }
.screen-weekly .split-legend { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; color: var(--dim); }
.screen-weekly .split-legend span:last-child { text-align: right; }
.screen-weekly .sev-row { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 13px; }
.screen-weekly .sev-row .slip-severity { margin-right: 0; }
.screen-weekly .sev-row .slip-severity-word { font-size: 12.5px; }
.screen-weekly .nums .day { cursor: default; }
.screen-weekly .nums .day.is-before { border-color: transparent; color: var(--faint); opacity: 0.7; }
/* the end: the P.S. in the writer's voice, both mates' faces and names, the call, when the next one comes */
.screen-weekly .weekly-foot { display: flex; flex-direction: column; gap: 10px; padding: 0 4px; }
.screen-weekly .weekly-foot .hook { font-size: 15.5px; }
.screen-weekly .sign-row { display: flex; align-items: center; gap: 10px; }
.screen-weekly .sign-row .faces img { width: 26px; height: 26px; box-shadow: 0 0 0 2px var(--bg); }
.screen-weekly .sign-row .faces img + img { margin-left: -8px; }
.screen-weekly .ring-button { flex: none; }
.screen-weekly .next-line { margin: -6px 0 0; text-align: center; font-size: 13px; color: var(--dim); }
/* a phone of 356 px: the mock's narrow frame */
@media (max-width: 374px) {
  .screen-weekly .form-top { gap: 12px; }
  .screen-weekly .form-tile .score > span:first-child { font-size: 50px; }
  .screen-weekly .form-line { font-size: 14px; }
  .screen-weekly .pd-face { width: 27px; height: 27px; outline-offset: 2px; }
}
/* The weekly summary on the home screen, among the letters: the writer's face in the icon's place, the language and the week,
   and Форма at the end */
.letter-face { flex: none; width: 44px; height: 44px; border-radius: 50%; object-fit: cover; background: var(--raised); }
.letter-form { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.letter-form b { font: 500 20px/1 Unbounded, Manrope, sans-serif; color: var(--lilac); }
.letter-form span { font-size: 11px; font-weight: 700; letter-spacing: 0.06em; color: var(--dim); }
.letter-weekly .letter-line { white-space: normal; }
.weekly-link { margin-top: -12px; }

/* The page a link from an email opens (web/login.html, signin.py): one card with a title, a line and one button or one link */
body[data-screen="gate"] .screen-gate { display: flex; min-height: calc(100vh - 56px); min-height: calc(100dvh - 56px); }
.gate-card { display: flex; flex-direction: column; gap: 14px; margin-top: 8vh; padding: 22px 20px 20px; border-radius: 22px; background: var(--card); box-shadow: var(--shadow-card); }
.gate-title { margin: 0; font-size: 22px; font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; text-wrap: balance; }
.gate-text { margin: 0; font-size: 15px; line-height: 1.45; color: var(--muted); text-wrap: pretty; }
.gate-card form { display: flex; margin-top: 6px; }
.gate-card .ring-button { width: 100%; }
.gate-card a.ring-button { margin-top: 6px; text-decoration: none; }  /* the one thing to do next, as a link: «Прислать новую» */
.gate-card .text-link { align-self: flex-start; margin: 2px 0 0 -12px; }

/* The bell between the wordmark and the gear, its badge the unread count (app.js showUnread) */
.bar-actions { display: flex; align-items: center; gap: 22px; }  /* each icon-button is 44 px around 22 px of icon: the targets must not overlap */
.bell { position: relative; }
.bell[hidden] { display: none; }
.badge { position: absolute; top: 6px; right: 4px; box-sizing: border-box; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px; border: 2px solid var(--bg);
  background: var(--lilac); color: var(--on-accent); font-size: 10px; font-weight: 700; line-height: 13px; text-align: center; letter-spacing: 0; }
.badge[hidden] { display: none; }
/* The bell's list: the letters' cards, the mate's face, the title with a dot while unread, the line, when */
body[data-screen="notifications"] .screen-notifications { display: flex; }
.notification .letter-text { gap: 2px; }
.notification-title { font-size: 15px; font-weight: 600; line-height: 1.3; }
.notification.unread .notification-title::before { content: ""; display: inline-block; width: 7px; height: 7px; margin: 0 7px 2px 0; border-radius: 50%; background: var(--lilac); }
.notification-body { font-size: 13px; line-height: 1.35; color: var(--muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.notification-body:empty { display: none; }
.notification-when { font-size: 12px; color: var(--dim); }
.notifications-status { text-align: left; padding: 0 4px; text-wrap: pretty; }
/* «ПОЧТА» in the settings: the row's hint by the address's state; the sheet's one field */
.row[data-state="confirmed"] .row-hint { color: var(--teal); }
.row[data-state="pending"] .row-hint { color: var(--sun); }
.sheet-hint { margin: 0; padding: 0 4px; font-size: 14px; line-height: 1.4; color: var(--muted); text-wrap: pretty; }
.sheet-input { width: 100%; height: 48px; padding: 0 14px; border: 1px solid var(--line); border-radius: 16px; background: var(--well); color: var(--fg); font: inherit; font-size: 16px; }
.sheet-input:focus { outline: 2px solid var(--lilac); outline-offset: 1px; }
.sheet-input::placeholder { color: var(--dim); }
.sheet-input:disabled { opacity: 0.6; }
.sheet-status.error { color: var(--end); }
