/* 00-tokens.css — слой tokens. ФАЙЛ СОБРАН АВТОМАТИЧЕСКИ, НЕ ПРАВИТЬ РУКАМИ.
   Источник палитры — Theme.kt приложения, который пишет scripts/theme-gen.py из seed #12B2F4.
   Пересобрать: python3 /root/tfsrc/build.py --tokens
   Правка цвета = правка генератора приложения, иначе сайт и приложение разъедутся.

   contains: роли Material 3 (--md-sys-color-*), формы, слои состояния, наши --tf-*.
   ⚠️ Единственный файл проекта, где допустимы шестнадцатеричные цвета. */

@layer tokens, base, type, components, layout, utilities;

@layer tokens {
:root {
  color-scheme: dark;

  /* === роли Material 3: один в один из Theme.kt ===================== */
  --md-sys-color-primary: #12B2F4;
  --md-sys-color-on-primary: #00344B;
  --md-sys-color-primary-container: #004C6B;
  --md-sys-color-on-primary-container: #C6E7FF;
  --md-sys-color-inverse-primary: #00658D;
  --md-sys-color-secondary: #A9CBE3;
  --md-sys-color-on-secondary: #0F3447;
  --md-sys-color-secondary-container: #0F3447;
  --md-sys-color-on-secondary-container: #C6E7FF;
  --md-sys-color-tertiary: #60E06B;
  --md-sys-color-on-tertiary: #00390D;
  --md-sys-color-tertiary-container: #005316;
  --md-sys-color-on-tertiary-container: #7DFD84;
  --md-sys-color-error: #FFB4AB;
  --md-sys-color-on-error: #690005;
  --md-sys-color-error-container: #93000A;
  --md-sys-color-on-error-container: #FFDAD6;
  --md-sys-color-surface: #10161B;
  --md-sys-color-on-surface: #CFD5DC;
  --md-sys-color-surface-variant: #3B4852;
  --md-sys-color-on-surface-variant: #ADBBC6;
  --md-sys-color-surface-tint: #12B2F4;
  --md-sys-color-inverse-surface: #DDE3EA;
  --md-sys-color-inverse-on-surface: #2B3136;
  --md-sys-color-outline: #85929D;
  --md-sys-color-outline-variant: #3B4852;
  --md-sys-color-scrim: #000000;
  --md-sys-color-surface-bright: #3D4449;
  --md-sys-color-surface-dim: #10161B;
  --md-sys-color-surface-container-lowest: #13191E;
  --md-sys-color-surface-container-low: #1F262A;
  --md-sys-color-surface-container: #232A2F;
  --md-sys-color-surface-container-high: #2E343A;
  --md-sys-color-surface-container-highest: #394045;

  /* === сверх схемы: есть в приложении, роли в M3 нет ================ */
  --tf-ground-top: #0D1318;      /* GroundTop: верх градиента земли */
  --tf-ground-bottom: #10161B;   /* GroundBottom == surface */
  --tf-heading: #DDE3EA;         /* HeadingText, тон 90 */
  --tf-brand-text: #F2F6F9;      /* BrandText из Theme.kt */
  --tf-brand-source: #68A706;    /* исходный фирменный зелёный, theme-gen.py */
  --tf-brand: #60E06B;
  --tf-on-brand: #00390D;
  --tf-brand-container: #005316;
  --tf-on-brand-container: #7DFD84;

  /* === только веб: в приложении таких понятий нет =================== */
  /* Знак ToolsFast — чистый белый: решение Руслана 19.09. Фирменные #F2F6F9
     и #F5F9FE на 4-5 % темнее белого и на тёмной земле читались серыми. */
  --tf-logo-text: #FFFFFF;
  --tf-link: var(--md-sys-color-primary);
  --tf-link-visited: var(--md-sys-color-secondary);
  --tf-focus-ring: var(--md-sys-color-secondary);
  --tf-selection-bg: var(--md-sys-color-primary-container);
  --tf-layout-margin: 16px;
  --tf-pane-max: 840px;
  --tf-measure: 68ch;

  /* === слои состояния: токены md-sys-state из material-web v0_192 =====
     ⚠️ Каталог m3.material.io пишет «Focus +10%, Press +10%», официальные
     токены дают 0.12. Берём токены: ими пользуются сами компоненты Google. */
  --md-sys-state-hover-state-layer-opacity: 0.08;
  --md-sys-state-focus-state-layer-opacity: 0.12;
  --md-sys-state-pressed-state-layer-opacity: 0.12;
  --md-sys-state-dragged-state-layer-opacity: 0.16;



  /* === движение: токены каталога M3, версия 2026-07-17 ===============
     Взято скриптом из styles/motion/easing-and-duration, руками не набиралось. */
  --md-sys-motion-easing-emphasized-accelerate: cubic-bezier(0.3, 0.0, 0.8, 0.15);
  --md-sys-motion-easing-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1.0);
  --md-sys-motion-easing-standard: cubic-bezier(0.2, 0.0, 0, 1.0);
  --md-sys-motion-easing-standard-accelerate: cubic-bezier(0.3, 0, 1, 1);
  --md-sys-motion-easing-standard-decelerate: cubic-bezier(0, 0, 0, 1);
  --md-sys-motion-easing-emphasized: cubic-bezier(0.2, 0.0, 0, 1.0);
  --md-sys-motion-easing-emphasized: linear(0.0000 0%, 0.0141 4%, 0.0616 8%, 0.1622 12%, 0.4000 17%, 0.6686 21%, 0.7728 25%, 0.8315 29%, 0.8706 33%, 0.8989 38%, 0.9204 42%, 0.9372 46%, 0.9506 50%, 0.9614 54%, 0.9701 58%, 0.9773 62%, 0.9830 67%, 0.9877 71%, 0.9914 75%, 0.9943 79%, 0.9965 83%, 0.9981 88%, 0.9992 92%, 0.9998 96%, 1.0000 100%);
  --md-sys-motion-duration-short1: 50ms;
  --md-sys-motion-duration-short2: 100ms;
  --md-sys-motion-duration-short3: 150ms;
  --md-sys-motion-duration-short4: 200ms;
  --md-sys-motion-duration-medium1: 250ms;
  --md-sys-motion-duration-medium2: 300ms;
  --md-sys-motion-duration-medium3: 350ms;
  --md-sys-motion-duration-medium4: 400ms;
  --md-sys-motion-duration-long1: 450ms;
  --md-sys-motion-duration-long2: 500ms;
  --md-sys-motion-duration-long3: 550ms;
  --md-sys-motion-duration-long4: 600ms;
  --md-sys-motion-duration-extra-long1: 700ms;
  --md-sys-motion-duration-extra-long2: 800ms;
  --md-sys-motion-duration-extra-long3: 900ms;
  --md-sys-motion-duration-extra-long4: 1000ms;

  /* === тени: формула из elevation/_elevation.scss material-web ====
     Два слоя, 30 % и 15 % от цвета тени; числа считаются, не копируются. */
  --md-sys-elevation-level0: none;
  --md-sys-elevation-level1: 0 1px 2px 0 rgb(0 0 0 / 0.30), 0 1px 3px 1px rgb(0 0 0 / 0.15);
  --md-sys-elevation-level2: 0 1px 2px 0 rgb(0 0 0 / 0.30), 0 2px 6px 2px rgb(0 0 0 / 0.15);
  --md-sys-elevation-level3: 0 1px 3px 0 rgb(0 0 0 / 0.30), 0 4px 8px 3px rgb(0 0 0 / 0.15);


  /* === формы: та же шкала, что MtvShapes в приложении =============== */
  --md-sys-shape-corner-none: 0;
  --md-sys-shape-corner-extra-small: 4px;
  --md-sys-shape-corner-small: 8px;
  --md-sys-shape-corner-medium: 12px;
  --md-sys-shape-corner-large: 16px;
  --md-sys-shape-corner-extra-large: 28px;
  --md-sys-shape-corner-full: 9999px;
}
}

/* 10-base.css — слой base: сброс, земля, фокус, пользовательские предпочтения.
   contains: reset, body с градиентом земли, ссылки, кольцо фокуса, reduced-motion, prefers-contrast.
   dependencies: 00-tokens.css (все цвета только оттуда).
   ⚠️ Ни одного hex и ни одного размера шрифта в этом файле быть не должно. */

@layer base {

  *, *::before, *::after { box-sizing: border-box; }

  html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

  /* Глубину даёт земля, а не тени — как в приложении: градиент на один экран,
     дальше ровно. 100svh, чтобы градиент не прыгал от адресной строки в Safari. */
  body {
    margin: 0;
    min-height: 100svh;
    color: var(--md-sys-color-on-surface);
    background-color: var(--tf-ground-bottom);
    background-image: linear-gradient(180deg, var(--tf-ground-top) 0, var(--tf-ground-bottom) 100%);
    background-repeat: no-repeat;
    background-size: 100% 100svh;
  }

  img, svg { max-width: 100%; }
  img { height: auto; }

  /* Ссылка отличается от текста не только цветом — иначе WCAG 1.4.1. */
  a {
    color: var(--tf-link); text-decoration: underline; text-underline-offset: 0.18em;
    transition: color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                text-decoration-thickness var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
  }
  a:hover { text-decoration-thickness: 2px; }
  a:visited { color: var(--tf-link-visited); }

  ::selection {
    background: var(--tf-selection-bg);
    color: var(--md-sys-color-on-primary-container);
  }

  /* Кольцо фокуса — числа из md-comp-focus-ring: width 3, outward-offset 2,
     color secondary, active-width 8, duration long4. Реализация material-web
     на этой длительности проигрывает рост 25 % и сжатие 75 % с кривой
     emphasized — повторяем, не изобретая своего. */
  :where(a, button, summary, input, textarea, select, [tabindex]):focus-visible {
    outline: 3px solid var(--tf-focus-ring);
    outline-offset: 2px;
    animation: tf-focus-ring var(--md-sys-motion-duration-long4) var(--md-sys-motion-easing-emphasized);
  }
  @keyframes tf-focus-ring {
    0%   { outline-width: 3px; }
    25%  { outline-width: 8px; }
    100% { outline-width: 3px; }
  }

  /* Движение выключается целиком: и переходы, и морфинг формы, и выезд панели. */
  @media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after, *::details-content {
      animation-duration: 1ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 1ms !important;
      transition-delay: 0ms !important;
    }
  }

  /* Повышенный контраст: подписи и контуры подтягиваются к основным ролям. */
  @media (prefers-contrast: more) {
    :root {
      --md-sys-color-on-surface-variant: var(--md-sys-color-on-surface);
      --md-sys-color-outline-variant: var(--md-sys-color-outline);
    }
  }
}

/* 20-type.css — слой type: шрифт и типовой масштаб Material 3.
   contains: @font-face Roboto (самохостинг, latin+cyrillic), 15 ролей типового масштаба,
             умолчания тегов, роль кода.
   dependencies: 00-tokens.css (цвета), /assets/fonts/*.woff2.
   ⚠️ ЕДИНСТВЕННОЕ место в проекте, где встречаются размеры шрифта.
   Значения — канон M3 (v0_192, tokens/_md-sys-typescale.scss), в rem.
   Трекинг в CSS-токенах MWC отсутствует и задаётся здесь руками, в em. */

@layer type {

  /* Roboto: канон M3 и тот же шрифт, что рисует приложение на Android.
     Статические начертания 400 и 500, два подмножества. CJK, арабский и
     деванагари Roboto не покрывает — их языки возьмут системный шрифт
     через :lang(), когда дойдёт до перевода. */
  @font-face {
    font-family: Roboto; font-style: normal; font-weight: 400; font-display: swap;
    src: url(/assets/fonts/roboto-400-latin.woff2) format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
  }
  @font-face {
    font-family: Roboto; font-style: normal; font-weight: 400; font-display: swap;
    src: url(/assets/fonts/roboto-400-cyrillic.woff2) format("woff2");
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
  }
  @font-face {
    font-family: Roboto; font-style: normal; font-weight: 500; font-display: swap;
    src: url(/assets/fonts/roboto-500-latin.woff2) format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
  }
  @font-face {
    font-family: Roboto; font-style: normal; font-weight: 500; font-display: swap;
    src: url(/assets/fonts/roboto-500-cyrillic.woff2) format("woff2");
    unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
  }

  :root {
    --md-ref-typeface-plain: Roboto, "Segoe UI Variable Text", "Segoe UI", -apple-system,
                             BlinkMacSystemFont, "Noto Sans", Arial, sans-serif;
    --md-ref-typeface-brand: var(--md-ref-typeface-plain);
    --tf-typeface-mono: "Roboto Mono", ui-monospace, SFMono-Regular, Consolas, monospace;

    --md-sys-typescale-display-small-size: 2.25rem;
    --md-sys-typescale-display-small-line-height: 2.75rem;
    --md-sys-typescale-headline-medium-size: 1.75rem;
    --md-sys-typescale-headline-medium-line-height: 2.25rem;
    --md-sys-typescale-headline-small-size: 1.5rem;
    --md-sys-typescale-headline-small-line-height: 2rem;
    --md-sys-typescale-title-large-size: 1.375rem;
    --md-sys-typescale-title-large-line-height: 1.75rem;
    --md-sys-typescale-title-small-size: 0.875rem;
    --md-sys-typescale-title-small-line-height: 1.25rem;
    --md-sys-typescale-title-medium-size: 1rem;
    --md-sys-typescale-title-medium-line-height: 1.5rem;
    --md-sys-typescale-title-medium-tracking: 0.009em;
    --md-sys-typescale-body-large-size: 1rem;
    --md-sys-typescale-body-large-line-height: 1.5rem;
    --md-sys-typescale-body-large-tracking: 0.031em;
    --md-sys-typescale-body-medium-size: 0.875rem;
    --md-sys-typescale-body-medium-line-height: 1.25rem;
    --md-sys-typescale-body-medium-tracking: 0.018em;
    --md-sys-typescale-body-small-size: 0.75rem;
    --md-sys-typescale-body-small-line-height: 1rem;
    --md-sys-typescale-body-small-tracking: 0.033em;
    --md-sys-typescale-label-large-size: 0.875rem;
    --md-sys-typescale-label-large-line-height: 1.25rem;
    --md-sys-typescale-label-large-tracking: 0.007em;
  }

  body {
    font-family: var(--md-ref-typeface-plain);
    font-size: var(--md-sys-typescale-body-large-size);
    line-height: var(--md-sys-typescale-body-large-line-height);
    letter-spacing: var(--md-sys-typescale-body-large-tracking);
    font-weight: 400;
  }

  /* Заголовки держатся на тоне 90, когда основной текст приглушён до 85 —
     то же правило, что в приложении (HeadingText). */
  h1, h2, h3 { color: var(--tf-heading); font-weight: 400; margin: 0; }

  h1 {
    font-size: var(--md-sys-typescale-headline-small-size);
    line-height: var(--md-sys-typescale-headline-small-line-height);
  }
  h2 {
    font-size: var(--md-sys-typescale-title-large-size);
    line-height: var(--md-sys-typescale-title-large-line-height);
  }
  h3 {
    font-size: var(--md-sys-typescale-title-medium-size);
    line-height: var(--md-sys-typescale-title-medium-line-height);
    letter-spacing: var(--md-sys-typescale-title-medium-tracking);
    font-weight: 500;
  }

  p, li { margin: 0; }
}

/* 30-layout.css — слой layout: контейнеры, поля, брейкпоинты.
   contains: .l-page, .l-prose, .l-stack, .l-grid, поля 16/24 dp, классы окна M3.
   dependencies: 00-tokens.css.
   ⚠️ ЕДИНСТВЕННОЕ место, где допустимы медиазапросы по ширине.
   Границы — классы окна Material 3: 600 / 840 / 1200 / 1600. Ширина полосы
   растёт вместе с классом: одна колонка 840 на мониторе 1580 оставляла
   по 370 px пустоты с каждой стороны. */

@layer layout {

  .l-page {
    width: 100%;
    max-width: var(--tf-pane-max);
    margin-inline: auto;
    padding-inline: var(--tf-layout-margin);
    padding-block: 32px 56px;
  }

  /* Мера строки: 840 px на кириллице дают около 90 знаков — много для чтения.
     ⚠️ Проза НЕ центрируется внутри полосы: так на странице появлялись две
     левые оси — заголовки секций от края полосы, текст от центра. Ось одна,
     а колонку целиком центрирует .l-page--text. */
  .l-prose { max-width: var(--tf-measure); }

  /* Страницы сплошного текста: узкая колонка по центру экрана, без пустоты
     справа от текста и «прижатости» влево. */
  .l-page--text { max-width: min(var(--tf-pane-max), 78ch); }

  .l-stack { display: flex; flex-direction: column; gap: 16px; }
  .l-stack--tight { gap: 8px; }
  /* Ритм: между секциями заметно больше, чем внутри секции. */
  .l-stack--sections { gap: 40px; }

  .l-grid { display: grid; gap: 16px; }

  /* medium: поле экрана 24 dp вместо 16, полоса 840 */
  @media (min-width: 600px) {
    :root { --tf-layout-margin: 24px; }
    .l-page { padding-block: 40px 72px; }
    .l-grid--2 { grid-template-columns: 1fr 1fr; }
  }

  /* expanded */
  @media (min-width: 840px) {
    :root { --tf-pane-max: 1040px; }
    .l-stack--sections { gap: 48px; }
  }

  /* large: три колонки карточек — каталог допускает до двух панелей, а сетка
     карточек внутри одной панели ограничена только читаемостью */
  @media (min-width: 1200px) {
    :root { --tf-pane-max: 1280px; }
    .l-grid--2 { grid-template-columns: repeat(3, 1fr); }
  }

  /* extra-large */
  @media (min-width: 1600px) {
    :root { --tf-pane-max: 1440px; }
  }

  /* G. Типографика отвечает на ширину: на телефоне остаётся как было */
  @media (min-width: 840px) {
    .m3-hero__title {
      font-size: var(--md-sys-typescale-display-small-size);
      line-height: var(--md-sys-typescale-display-small-line-height);
    }
    h1 {
      font-size: var(--md-sys-typescale-headline-medium-size);
      line-height: var(--md-sys-typescale-headline-medium-line-height);
    }
    h2 {
      font-size: var(--md-sys-typescale-headline-small-size);
      line-height: var(--md-sys-typescale-headline-small-line-height);
    }
  }

  /* Навигация: до 600 dp — кнопка меню и drawer, дальше — ссылки в строку. */
  @media (max-width: 599px) {
    .l-nav-inline { display: none; }
  }
  @media (min-width: 600px) {
    .l-nav-trigger { display: none; }
  }

  /* === ДВЕ КОЛОНКИ: ТЕКСТ И КАРТИНКА ============================= */
  /* Первый экран и блок про платформы. До 1200 dp картинка идёт под
     текстом: в двух колонках на планшете обе половины становятся узкими. */
  /* ⚠️ minmax(0, 1fr) обязателен даже для одной колонки: без него колонка
     берёт ширину по самому широкому содержимому, и лежачий снимок телевизора
     (1252 x 830 при потолке высоты) распирал страницу на 47 px вбок на 360. */
  .l-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; align-items: center; }

  /* === СЛАЙДЕР ЭКРАНОВ =========================================== */
  /* Один экран за раз: и на телефоне, и в колонке рядом с текстом.
     Полоса прокрутки скрыта, сама прокрутка остаётся — свайп, колесо,
     стрелки клавиатуры. */
  .m3-slider__track {
    display: flex; gap: 16px;
    overflow-x: auto; scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .m3-slider__track::-webkit-scrollbar { display: none; }
  .m3-slider__track > * { flex: 0 0 100%; scroll-snap-align: center; }

  /* Вопросы в две колонки: на широком экране одна колонка оставляла
     половину полосы пустой. align-items: start — чтобы раскрытый ответ
     не растягивал соседний вопрос. */
  @media (min-width: 840px) {
    .m3-faq {
      display: grid; grid-template-columns: repeat(2, 1fr);
      gap: 8px 16px; align-items: start;
    }
  }

  @media (min-width: 1200px) {
    .l-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 40px; }
  }
}

/* 40-components.css — слой components: компоненты каталога Material 3.
   contains: примеси .m3-state и .m3-tap, top app bar, text button, подвал, skip link.
   dependencies: 00-tokens.css, 30-layout.css.
   Имена классов зеркалят каталог M3, чтобы класс можно было найти в спецификации.
   ⚠️ Мёртвых селекторов быть не должно: check.py --css сверяет каждый класс с HTML.
   Компоненты страниц (карточки, поля, меню, drawer) добавляются на этапе 2. */

@layer components {

  /* === СЛОЙ СОСТОЯНИЯ ============================================
     Ripple в вебе не воспроизвести без JS. Официальная подмена — тонирование
     currentColor поверх. Проценты — из каталога: hover 8, focus 10, pressed 10. */
  .m3-state { position: relative; isolation: isolate; }
  .m3-state::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background: var(--tf-state-layer-color, currentColor); opacity: 0; pointer-events: none;
    transition: opacity var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
  }
  /* Без hover:hover подсветка залипает на телефоне после тапа. */
  @media (hover: hover) {
    .m3-state:hover::after { opacity: var(--md-sys-state-hover-state-layer-opacity); }
  }
  .m3-state:focus-visible::after { opacity: var(--md-sys-state-focus-state-layer-opacity); }
  .m3-state:active::after { opacity: var(--md-sys-state-pressed-state-layer-opacity); }

  /* === ЗОНА НАЖАТИЯ 48 dp ========================================
     Визуальный размер остаётся прежним, цель растёт. */
  .m3-tap { position: relative; }
  .m3-tap::before {
    content: ""; position: absolute; inset-inline: 0; top: 50%;
    height: 48px; transform: translateY(-50%);
  }

  /* === TOP APP BAR, small ======================================== */
  /* ⚠️ Без backdrop-filter намеренно: он делает шапку containing block для
     position:fixed, и панель меню начинала позиционироваться относительно неё —
     drawer выезжал обрезанным. В M3 глубину и так даёт тон, а не размытие. */
  .m3-top-app-bar {
    position: sticky; top: 0; z-index: 10;
    background: var(--tf-ground-top);
  }
  .m3-top-app-bar__row {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    min-height: 64px;
    max-width: var(--tf-pane-max); margin-inline: auto;
    padding-inline: var(--tf-layout-margin);
  }
  /* Знак, а не кнопка: слоя состояния на нём нет — под курсором появлялась
     серая плашка во всю ширину текста. Цвет — BrandText из Theme.kt,
     фирменный белый; тон 90 делал знак серым. */
  .m3-top-app-bar__title {
    display: inline-flex; align-items: center; min-height: 48px;
    color: var(--tf-logo-text);
    font-weight: 700; letter-spacing: -0.01em;
    font-size: var(--md-sys-typescale-title-large-size);
    line-height: var(--md-sys-typescale-title-large-line-height);
    font-weight: 500; text-decoration: none; white-space: nowrap;
  }
  .m3-top-app-bar__title:hover { text-decoration: none; }
  /* Зелёный знака — тот же яркий brand, что у значков, номеров шагов и метки
     на сайте (#60E06B). Исходный #68A706 на тёмной земле выглядел тусклым. */
  .m3-top-app-bar__brand { color: var(--tf-brand); }

  /* === TEXT BUTTON =============================================== */
  /* Официально: container-height 40, min-width 64, gap 8, значок 18.
     48 dp — это зона нажатия, а не высота кнопки: material-web добавляет её
     отдельным элементом. У нас то же самое делает ::before. */
  .m3-button {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    min-height: 40px; min-width: 64px; padding-inline: 12px;
    border: 0; border-radius: var(--md-sys-shape-corner-full);
    font-family: inherit;
    font-size: var(--md-sys-typescale-label-large-size);
    line-height: var(--md-sys-typescale-label-large-line-height);
    letter-spacing: var(--md-sys-typescale-label-large-tracking);
    font-weight: 500; text-decoration: none; cursor: pointer; background: transparent;
    transition: background-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                border-radius var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-emphasized);
  }
  /* Каталог: «When pressed, buttons can morph to become more square.» */
  .m3-button:active { border-radius: var(--md-sys-shape-corner-medium); }
  .m3-button:hover { text-decoration: none; }

  /* === ПОДВАЛ ==================================================== */
  .m3-footer { border-block-start: 1px solid var(--md-sys-color-outline-variant); }
  .m3-footer__row {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px;
    max-width: var(--tf-pane-max); margin-inline: auto;
    padding-inline: var(--tf-layout-margin); padding-block: 16px 32px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-medium-size);
    line-height: var(--md-sys-typescale-body-medium-line-height);
    letter-spacing: var(--md-sys-typescale-body-medium-tracking);
  }
  /* Высота настоящая, а не фантомная зона из ::before: на 360 px ссылки
     переносятся в две строки с шагом 24 px, и зоны 48 px перекрывались —
     тап у границы попадал в соседнюю ссылку. */
  .m3-footer__link {
    display: inline-flex; align-items: center; min-height: 48px;
    color: var(--md-sys-color-on-surface-variant);
    text-decoration: none;
    transition: color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                text-decoration-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }
  .m3-footer__link:hover {
    color: var(--md-sys-color-on-surface);
    text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 0.2em;
  }
  .m3-footer__link:active { color: var(--tf-link); }
  .m3-footer__copy { margin-inline-start: auto; }

  /* === SKIP LINK ================================================= */
  .m3-skip-link {
    position: absolute; inset-inline-start: -9999px; top: 8px; z-index: 20;
    display: inline-flex; align-items: center; min-height: 48px; padding-inline: 16px;
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
    text-decoration: none;
  }
  .m3-skip-link:focus-visible { inset-inline-start: 8px; }

  /* === CARD, filled ==============================================
     Заливка вместо рамки: outline-variant даёт 1,94:1 к земле, а глубину
     в M3 несёт тон поверхности, а не контур. */
  .m3-card {
    border-radius: var(--md-sys-shape-corner-medium);
    padding: 16px;
  }
  .m3-card--filled { background: var(--md-sys-color-surface-container-low); }

  /* === СПИСОК В ПРОЗЕ ============================================ */
  .m3-list { display: flex; flex-direction: column; gap: 8px; margin: 0; padding-inline-start: 22px; }

  /* === КНОПКИ ==================================================== */
  /* Зона нажатия 48 dp поверх контейнера 40 — как touch target в material-web */
  .m3-button::before {
    content: ""; position: absolute; inset-inline: 0; top: 50%;
    height: 48px; transform: translateY(-50%);
  }
  /* Токены md-comp-filled-button: container-elevation level0,
     hover-container-elevation **level1**, pressed и focus снова level0.
     Тени не было — поэтому наведение на яркой зелёной кнопке не читалось:
     тёмный слой 8 % на тоне 80 глазом почти не виден. */
  .m3-button--filled {
    background: var(--tf-brand);
    color: var(--tf-on-brand);
    padding-inline: 24px;
    box-shadow: var(--md-sys-elevation-level0);
    transition: background-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                box-shadow var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                border-radius var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-emphasized);
  }
  /* ⚠️ Осознанное отступление. По токенам слой наведения у заливной кнопки —
     8 % «on»-цвета. На контейнере тона 80 (наш зелёный) это тёмная плёнка,
     дающая разницу 1,12:1: глазом не читается. Тень level1 на тёмной земле
     тоже почти не видна — тени в тёмной теме M3 вообще слабый сигнал.
     Поднимаем слой до 16 % (значение dragged из того же набора токенов):
     разница становится 1,25:1 и наведение видно. Критерий — видимость,
     а не буквальные 8 %. */
  @media (hover: hover) {
    .m3-button--filled:hover {
      box-shadow: var(--md-sys-elevation-level1);
      --tf-state-layer-opacity-hover: var(--md-sys-state-dragged-state-layer-opacity);
    }
    .m3-button--filled.m3-state:hover::after {
      opacity: var(--tf-state-layer-opacity-hover);
    }
  }
  .m3-button--filled:active,
  .m3-button--filled:focus-visible { box-shadow: var(--md-sys-elevation-level0); }
  .m3-button--filled:disabled { opacity: .6; cursor: default; }

  /* === TEXT FIELD, outlined ======================================
     Кегль поля ровно 1rem: меньше — и iOS Safari зумит страницу при фокусе. */
  .m3-text-field { display: flex; flex-direction: column; gap: 6px; }
  .m3-text-field__label {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-small-size);
    line-height: var(--md-sys-typescale-body-small-line-height);
    letter-spacing: var(--md-sys-typescale-body-small-tracking);
  }
  .m3-text-field__input {
    width: 100%;
    min-height: 56px;
    padding: 14px 16px;
    border: 1px solid var(--md-sys-color-outline);
    border-radius: var(--md-sys-shape-corner-extra-small);
    background: transparent;
    color: var(--md-sys-color-on-surface);
    font-family: inherit;
    font-size: var(--md-sys-typescale-body-large-size);
    line-height: var(--md-sys-typescale-body-large-line-height);
  }
  .m3-text-field__input:focus { border-color: var(--md-sys-color-primary); border-width: 2px; }

  /* === СТРОКА СОСТОЯНИЯ ФОРМЫ ====================================
     Цвет снекбара M3: инверсная поверхность. */
  .m3-status {
    min-height: 24px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-medium-size);
    line-height: var(--md-sys-typescale-body-medium-line-height);
  }
  .m3-status--ok {
    display: inline-block;
    padding: 12px 16px;
    border-radius: var(--md-sys-shape-corner-extra-small);
    background: var(--md-sys-color-inverse-surface);
    color: var(--md-sys-color-inverse-on-surface);
  }
  .m3-status--err { color: var(--md-sys-color-error); }

  /* === HERO ====================================================== */
  /* Бокс по содержимому: флекс растягивал его на всю колонку, и SVG
     центрировался внутри себя — логотип стоял не на одной оси с заголовком. */
  .m3-hero__logo { display: block; height: 48px; width: auto; align-self: start; }
  .m3-hero__title {
    font-size: var(--md-sys-typescale-headline-medium-size);
    line-height: var(--md-sys-typescale-headline-medium-line-height);
  }
  .m3-hero__lead {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-large-size);
    line-height: var(--md-sys-typescale-body-large-line-height);
  }
  /* Плашка «скоро»: не кнопка — нажимать нечего, и выглядеть кнопкой она не должна. */
  /* ⚠️ Это НЕ кнопка: нажимать пока некуда, приложение ещё не в Play.
     Пока она была залитой пилюлей, её принимали за главный CTA и ждали
     отклика на наведение. Тональная пара + прямоугольная форма: фирменный
     зелёный остаётся, ложный аффорданс уходит. */
  .m3-badge {
    display: inline-flex; align-items: center; gap: 8px;
    min-height: 40px; padding-inline: 16px;
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--tf-brand-container); color: var(--tf-on-brand-container);
    font-size: var(--md-sys-typescale-label-large-size);
    line-height: var(--md-sys-typescale-label-large-line-height);
    letter-spacing: var(--md-sys-typescale-label-large-tracking);
    font-weight: 500;
  }

  /* === КАРТОЧКА ВОЗМОЖНОСТИ ====================================== */
  .m3-feature__text {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-medium-size);
    line-height: var(--md-sys-typescale-body-medium-line-height);
    letter-spacing: var(--md-sys-typescale-body-medium-tracking);
  }

  /* === ШАГИ ====================================================== */
  .m3-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 16px; }
  .m3-steps__item { display: flex; gap: 12px; align-items: flex-start; min-height: 48px; }
  .m3-steps__num {
    flex: none; width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--md-sys-shape-corner-full);
    /* Пара brand/on-brand из Theme.kt — та, которой приложение красит FAB. */
    background: var(--tf-brand);
    color: var(--tf-on-brand);
    font-size: var(--md-sys-typescale-label-large-size);
    font-weight: 500;
  }

  /* === CHIP (платформы) ========================================== */
  .m3-chips { display: flex; flex-wrap: wrap; gap: 8px; }
  /* Официально: container-height 32, shape small, outline 1, значок 18.
     У нас чипы платформ некликабельны, поэтому зона нажатия им не нужна. */
  .m3-chip {
    display: inline-flex; align-items: center; gap: 8px;
    min-height: 32px; padding-inline: 16px;
    border: 1px solid var(--md-sys-color-outline);
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface);
    font-size: var(--md-sys-typescale-label-large-size);
    line-height: var(--md-sys-typescale-label-large-line-height);
  }

  /* === РОЛИК И СНИМКИ ЭКРАНОВ ==================================== */
  /* Пропорции держит сам файл (width/height в разметке): места под ролик
     и снимки резервируются до загрузки, поэтому страница не прыгает. */
  .m3-video {
    display: block; width: 100%; height: auto;
    border-radius: var(--md-sys-shape-corner-large);
    background: var(--md-sys-color-surface-container-low);
  }
  /* Слайд одинаковой высоты при любой картинке: телефон стоячий, телевизор
     лежачий, и без общего потолка панель со стрелками прыгала бы при
     перелистывании. Высота слайда — по самой высокой картинке. */
  .m3-shot {
    display: flex; flex-direction: column; justify-content: flex-end; gap: 8px;
    margin: 0;
  }
  .m3-shot img {
    display: block; margin-inline: auto;
    width: auto; max-width: 100%;
    height: auto; max-height: 420px;
  }
  .m3-shot figcaption { text-align: center; text-wrap: balance; }

  /* === СЛАЙДЕР ЭКРАНОВ =========================================== */
  /* Лента со «прилипанием» работает без скрипта: свайпом, колесом
     и клавишами. Стрелки и точки добавляет enhance.js — они спрятаны
     атрибутом hidden, пока скрипт не отработал. */
  /* min-width: 0 обязателен: в колонке грида элемент с прокруткой иначе
     распирает колонку по ширине содержимого, и появляется горизонтальная
     прокрутка всей страницы. */
  .m3-slider { min-width: 0; }
  /* Место под картинку резервируется заранее: иначе при подгрузке слайда
     страница дёргается, а стрелки уезжают вниз. */
  .m3-slider__track > * { min-height: 460px; }
  .m3-slider__bar {
    display: flex; align-items: center; justify-content: center; gap: 12px;
    margin-block-start: 12px;
  }
  .m3-slider__btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 48px; height: 48px; padding: 0;
    border: 0; border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface);
    cursor: pointer;
  }
  .m3-slider__dots { display: flex; align-items: center; gap: 8px; }
  /* ⚠️ Зона нажатия настоящая, а не нарисованная: сама кнопка 32 x 32,
     видимая точка — псевдоэлемент внутри. Точка 8 x 8 кнопкой не годится:
     Lighthouse справедливо ловил её на target-size, а невидимая зона
     поверх маленького элемента в ряду приводит к перекрытиям. */
  .m3-slider__dot {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0;
    border: 0; border-radius: var(--md-sys-shape-corner-full);
    background: none;
    cursor: pointer;
  }
  .m3-slider__dot::before {
    content: ""; display: block; width: 8px; height: 8px;
    border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-outline);
    transition: width var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard),
                background-color var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-standard);
  }
  .m3-slider__dot--on::before { width: 24px; background: var(--md-sys-color-primary); }

  /* === FAQ на <details> ========================================== */
  .m3-faq { display: flex; flex-direction: column; gap: 8px; }
  .m3-faq__item {
    background: var(--md-sys-color-surface-container-low);
    border-radius: var(--md-sys-shape-corner-medium);
    /* Слой состояния рисовался прямоугольником поверх скруглённой карточки —
       углы торчали наружу. Обрезаем по форме карточки. */
    overflow: clip;
  }
  .m3-faq__q {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 56px; padding: 12px 16px;
    border-radius: var(--md-sys-shape-corner-medium); cursor: pointer; list-style: none;
    color: var(--md-sys-color-on-surface);
    font-size: var(--md-sys-typescale-title-medium-size);
    line-height: var(--md-sys-typescale-title-medium-line-height);
    font-weight: 500;
  }
  .m3-faq__q::-webkit-details-marker { display: none; }
  .m3-faq__chevron {
    flex: none; width: 24px; height: 24px;
    color: var(--md-sys-color-on-surface-variant);
    transition: rotate 120ms linear;
  }
  .m3-faq__item[open] .m3-faq__chevron { rotate: 180deg; }
  .m3-faq__a {
    padding: 8px 16px 20px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-medium-size);
    line-height: var(--md-sys-typescale-body-medium-line-height);
    letter-spacing: var(--md-sys-typescale-body-medium-tracking);
  }

  /* Значения выстраиваются в одну колонку: раньше длинные (хеш коммита)
     переносились под подпись, а короткие оставались справа — список рвался. */
  .m3-dl { display: grid; gap: 8px; margin: 0; }
  .m3-dl div { display: grid; grid-template-columns: minmax(140px, 200px) 1fr; gap: 4px 16px; align-items: baseline; }
  .m3-dl dt { color: var(--md-sys-color-on-surface-variant); margin: 0; }
  /* Хеш коммита — 40 знаков без пробелов: без переноса он распирает страницу. */
  .m3-dl dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
  .m3-dl code { font-family: var(--tf-typeface-mono); overflow-wrap: anywhere; }

  /* === MODAL NAVIGATION DRAWER ===================================
     На <details>: открывается и закрывается без JS. enhance.js добавляет
     только Esc и клик по затемнению — без него меню полностью работает. */
  .m3-nav-drawer { position: relative; }
  .m3-nav-drawer__trigger {
    display: inline-flex; align-items: center; justify-content: center;
    width: 48px; height: 48px; border-radius: var(--md-sys-shape-corner-full);
    cursor: pointer; list-style: none;
    color: var(--md-sys-color-on-surface-variant);
  }
  .m3-nav-drawer__trigger::-webkit-details-marker { display: none; }
  .m3-nav-drawer__scrim {
    position: fixed; inset: 0; z-index: 20;
    background: var(--md-sys-color-scrim); opacity: 0.32;
  }
  .m3-nav-drawer__panel {
    position: fixed; inset-block: 0; inset-inline-start: 0; z-index: 21;
    width: min(360px, 80vw); overflow-y: auto; overscroll-behavior: contain;  /* container-width 360 */
    display: flex; flex-direction: column; gap: 4px;
    padding: 16px 12px;
    background: var(--md-sys-color-surface-container-low);
    border-start-end-radius: var(--md-sys-shape-corner-large);
    border-end-end-radius: var(--md-sys-shape-corner-large);
  }
  .m3-nav-drawer__item {
    display: flex; align-items: center; min-height: 56px; padding-inline: 24px;
    border-radius: var(--md-sys-shape-corner-full);
    color: var(--md-sys-color-on-surface-variant); text-decoration: none;
    font-size: var(--md-sys-typescale-label-large-size);
    line-height: var(--md-sys-typescale-label-large-line-height);
    letter-spacing: var(--md-sys-typescale-label-large-tracking);
    font-weight: 500;
  }
  .m3-nav-drawer__item:hover { text-decoration: none; }

  /* === ДВИЖЕНИЕ: отклик у каждого интерактивного элемента ==========
     Длительности и кривые — токены каталога M3. Всё гасится целиком
     через prefers-reduced-motion в слое base. */

  .m3-top-app-bar__title,
  .m3-nav-drawer__trigger {
    transition: color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                border-radius var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-emphasized);
  }
  .m3-nav-drawer__trigger:active { border-radius: var(--md-sys-shape-corner-medium); }

  .m3-nav-drawer__item {
    transition: background-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                border-radius var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-emphasized);
  }
  .m3-nav-drawer__item:hover { color: var(--md-sys-color-on-surface); }
  .m3-nav-drawer__item:active { border-radius: var(--md-sys-shape-corner-medium); }

  /* Панель выезжает, затемнение проявляется. transition-behavior: allow-discrete
     нужен, потому что <details> переключает display, а не только прозрачность. */
  .m3-nav-drawer__panel {
    transition: translate var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized-decelerate),
                display var(--md-sys-motion-duration-medium2) allow-discrete;
  }
  .m3-nav-drawer__scrim {
    transition: opacity var(--md-sys-motion-duration-medium1) var(--md-sys-motion-easing-standard),
                display var(--md-sys-motion-duration-medium1) allow-discrete;
  }
  @starting-style {
    .m3-nav-drawer[open] .m3-nav-drawer__panel { translate: -100% 0; }
    .m3-nav-drawer[open] .m3-nav-drawer__scrim { opacity: 0; }
  }

  .m3-faq__item {
    transition: background-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }
  .m3-faq__item[open] { background: var(--md-sys-color-surface-container); }
  .m3-faq__q {
    transition: border-radius var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-emphasized);
  }
  .m3-faq__q:active { border-radius: var(--md-sys-shape-corner-medium); }
  .m3-faq__chevron {
    transition: rotate var(--md-sys-motion-duration-medium1) var(--md-sys-motion-easing-emphasized),
                color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }
  /* Раскрытие ответа: ::details-content поддерживают не все браузеры —
     там, где нет, содержимое просто появляется, как и раньше. */
  .m3-faq__item::details-content {
    block-size: 0; overflow: clip;
    transition: block-size var(--md-sys-motion-duration-medium2) var(--md-sys-motion-easing-emphasized),
                content-visibility var(--md-sys-motion-duration-medium2) allow-discrete;
  }
  .m3-faq__item[open]::details-content { block-size: auto; }

  .m3-text-field__input {
    transition: border-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                background-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }
  .m3-text-field__input:hover { background: var(--md-sys-color-surface-container-high); }
  .m3-text-field__label {
    transition: color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }

  .m3-chip {
    transition: background-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard),
                border-color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }

  .m3-skip-link {
    transition: inset-inline-start var(--md-sys-motion-duration-short4) var(--md-sys-motion-easing-emphasized-decelerate);
  }

  .m3-status {
    transition: color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }

  /* === ЗНАЧКИ ====================================================
     Material Symbols Rounded — тот же набор и те же глифы, что в приложении.
     Размер 24 dp по спецификации, цвет наследуется. */
  .m3-icon { width: 24px; height: 24px; flex: none; }
  /* Официально значок внутри кнопки и чипа — 18 dp, а не 24 */
  .m3-button .m3-icon, .m3-chip .m3-icon, .m3-badge .m3-icon { width: 18px; height: 18px; }
  .m3-icon--lead { color: var(--tf-brand); }
  .m3-icon--chip { width: 20px; height: 20px; }

  /* === ВОЛНА ПРИ НАЖАТИИ =========================================
     Ставится enhance.js; без него остаётся слой состояния, как прежде.
     Мягкий край — радиальный градиент из _ripple.scss material-web,
     затухание 375 ms linear оттуда же. */
  .m3-state { overflow: hidden; }
  .m3-ripple {
    position: absolute; border-radius: 50%; pointer-events: none;
    transform-origin: center center; will-change: transform, opacity;
    background: radial-gradient(closest-side,
      var(--tf-state-layer-color, currentColor) max(calc(100% - 70px), 65%),
      transparent 100%);
    opacity: var(--md-sys-state-pressed-state-layer-opacity);
    transition: opacity 375ms linear;
  }
  .m3-ripple--out { opacity: 0; }
  @media (prefers-reduced-motion: reduce) {
    .m3-ripple { display: none; }
  }

  /* === PRIMARY TABS (внешний вид) =================================
     Числа из md-comp-primary-navigation-tab: контейнер 48, индикатор 3 px
     цветом primary, вырез 2 dp по бокам, полное скругление.
     ⚠️ Слоя состояния у вкладок нет намеренно (решение Руслана 19.09):
     тонировка во всю высоту 48 читалась как чужая серая плашка под курсором.
     Отклик остаётся цветом подписи, кольцо фокуса — общее из 10-base.css.
     ⚠️ Семантика навигационная: <nav> + <a> + aria-current="page".
     Ролей role="tab"/"tabpanel" нет намеренно — они обещают переключение
     панели внутри страницы, а у нас переход по адресу с перезагрузкой. */
  .m3-tabs { display: flex; align-items: stretch; gap: 0; }
  .m3-tab {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 48px; padding-inline: 16px;
    color: var(--md-sys-color-on-surface-variant);
    text-decoration: none; white-space: nowrap;
    font-size: var(--md-sys-typescale-title-small-size);
    line-height: var(--md-sys-typescale-title-small-line-height);
    font-weight: 500;
    transition: color var(--md-sys-motion-duration-short3) var(--md-sys-motion-easing-standard);
  }
  .m3-tab:hover { text-decoration: none; color: var(--md-sys-color-on-surface); }
  .m3-tab--active { color: var(--md-sys-color-primary); }
  .m3-tab--active::before {
    content: ""; position: absolute; inset-inline: 2px; bottom: 0;
    height: 3px; border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-primary);
  }

  /* Активный пункт в выдвижном меню — штатный индикатор списка */
  .m3-nav-drawer__item--active {
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
  }
}

/* 50-utilities.css — слой utilities: роли типового масштаба как классы и мелкие помощники.
   contains: .md-<роль> для точечного назначения роли, .u-muted, .u-visually-hidden.
   dependencies: 20-type.css (переменные масштаба), 00-tokens.css (цвета).
   Слой объявлен последним, поэтому утилита побеждает компонент без !important. */

@layer utilities {

  .md-body-medium {
    font-size: var(--md-sys-typescale-body-medium-size);
    line-height: var(--md-sys-typescale-body-medium-line-height);
    letter-spacing: var(--md-sys-typescale-body-medium-tracking);
  }

  .md-body-small {
    font-size: var(--md-sys-typescale-body-small-size);
    line-height: var(--md-sys-typescale-body-small-line-height);
    letter-spacing: var(--md-sys-typescale-body-small-tracking);
  }

  /* Вторичный текст: тон 75, как onSurfaceVariant в приложении — самая частая роль. */
  /* Пиксель счётчика для браузеров без JavaScript: он не должен ни
     занимать место, ни попадать в озвучку. */
  .u-offscreen { position: absolute; inset-inline-start: -9999px; }
  .u-muted { color: var(--md-sys-color-on-surface-variant); }
}
