/* ============================================================================
   MENDEE RESPONSIVE — общий слой адаптивности для всех сайтов
   v1.0 · 13.08.2026 · обычный CSS, без сборки и препроцессоров

   Ставится в: StartNewLife (Astro 6), svoi.uk (Nuxt 4), Skybow (Astro 5),
   Mendee Digital (Astro 5), Perevod London (Astro 6), Buryat Global (Astro 7),
   HelloType1 (Nuxt 2). Подключается одной строкой, ничего не требует от сборки.

   ПОЧЕМУ @layer: слой mendee проигрывает любому НЕслоёному CSS проекта.
   Файл можно подключить в существующий сайт и он ничего не сломает —
   локальные стили продолжат побеждать. Затем правила переносятся по одному.

   Подключение — ПЕРВЫМ, до остальных стилей:
     Astro/Nuxt:  <link rel="stylesheet" href="/mendee-responsive.css">
     Nuxt 2:      nuxt.config.js → css: ['~/static/mendee-responsive.css']

   Обязательное дополнение в <head> каждой страницы:
     <meta name="viewport" content="width=device-width, initial-scale=1">
   Без width=device-width браузер берёт ICB ~980px и масштабирует страницу —
   все пороги ниже теряют смысл. user-scalable=no и maximum-scale=1 запрещены:
   они ломают WCAG 1.4.4 (текст должен масштабироваться до 200%).
   ============================================================================ */

@layer mendee.tokens, mendee.base, mendee.util;

@layer mendee.tokens {
  :root {
    /* ---- Пороги раскладки ------------------------------------------------
       Три, а не сорок. Взяты от КОНТЕНТА, как советует web.dev, и сверены
       с реальными ширинами аудитории (GA4 SNL, 15.05-13.08.2026, за вычетом
       бот-подписей): до 640 — 55% людей, 900-1200 — ноутбуки, выше — мониторы.
       Планшетов 1,5% — отдельного порога под них НЕТ намеренно.
       В медиазапросах переменные не работают, значения продублированы ниже
       числами. Эти токены — для JS и для документации.                     */
    --bp-md: 640px;   /* одна колонка → две; действия в ряд вместо стопки   */
    --bp-lg: 900px;   /* боковая колонка / TOC рядом с текстом             */
    --bp-xl: 1200px;  /* предел ширины контента                            */

    /* ---- Цели нажатия ----------------------------------------------------
       24 — норма WCAG 2.2 AA (SC 2.5.8). 44 — AAA (SC 2.5.5) и дефолт Apple.
       48 — рекомендация Google, не норма. Проектируем на 44, гейт держим
       на 24. Измеряется КЛИКАБЕЛЬНАЯ область, padding засчитывается.       */
    --tap-min: 24px;  /* минимум соответствия AA                            */
    --tap: 44px;      /* цель проектирования                                */
    --tap-gap: 8px;   /* просвет между соседними целями                     */

    /* ---- Поля и ширины ---------------------------------------------------
       Боковое поле растёт вместе с экраном, но не схлопывается на 320.     */
    --pad-x: clamp(12px, 4vw, 24px);
    --content-max: 72ch;  /* длина строки 70-80 знаков — рекомендация web.dev */
    --wrap-max: 1200px;

    /* ---- Типографика -----------------------------------------------------
       rem, не px: иначе пользовательский размер шрифта игнорируется.
       Единицы вьюпорта как ОСНОВНОЙ способ задать размер текста запрещены —
       это техника отказа F94 по WCAG 1.4.4. Здесь vw только как добавка
       внутри clamp(), с постоянной rem-базой — так требование соблюдается. */
    --fs-base: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
    --fs-small: clamp(0.875rem, 0.85rem + 0.1vw, 0.9375rem);
    --fs-input: 16px; /* НЕ МЕНЬШЕ: iOS Safari зумит страницу при фокусе,
                         масштаб = 16 / font-size (WebKit, WKWebViewIOS.mm) */
    --lh: 1.55;
  }
}

@layer mendee.base {
  /* Границы блока считаются вместе с padding — иначе любой отступ на 320px
     выталкивает элемент за экран. Это причина №1 в нашем аудите.           */
  *, *::before, *::after { box-sizing: border-box; }

  html {
    -webkit-text-size-adjust: 100%; /* iOS не «улучшает» размер сам        */
    text-size-adjust: 100%;
  }

  body {
    font-size: var(--fs-base);
    line-height: var(--lh);
    /* Ломать только те слова, которые физически не влезают в строку.
       break-word, а не anywhere: не влияет на расчёт min-content, поэтому
       раскладку не двигает. Нужно потому, что длинные адреса госорганов
       встречаются не только в ссылках, но и простым текстом внутри <strong>
       (пример: гайд по письмам AHRO — адрес шириной 486px при экране 320). */
    overflow-wrap: break-word;
    /* overflow-x: clip НЕ ставим. Клип прячет переполнение и от читателя,
       и от любого замера: контент обрезан, а полосы прокрутки нет, и
       человек не знает, что часть текста существует. Переполнение надо
       чинить, а не заклеивать.                                            */
  }

  /* Медиа никогда не шире контейнера. */
  img, svg, video, canvas, iframe, embed, object {
    max-width: 100%;
    height: auto;
  }

  /* Длинные неразрывные строки — почты, ссылки, коды, номера дел.
     Причина №1 обрезанного контента: адрес вида
     ahrocentralcommunicationshub@contactus.homeoffice.gov.uk занимает
     486px в окне 320. Перенос где угодно — единственное, что помогает,
     потому что в таких строках нет ни пробелов, ни дефисов.               */
  a[href^="mailto:"], a[href^="tel:"], code, kbd, samp, pre {
    overflow-wrap: anywhere;
    word-break: normal;
  }

  /* Поля ввода: 16px — порог автозума iOS. Ширина 100%, иначе поле
     фиксированной ширины выталкивает форму за экран.                      */
  input, select, textarea, button {
    font: inherit;
    font-size: max(var(--fs-input), 1rem);
    max-width: 100%;
  }

  /* Заголовки не должны переполнять на узком экране из-за длинных слов
     (казахский, киргизский, таджикский дают самые длинные токены).        */
  h1, h2, h3, h4 { overflow-wrap: break-word; }

  /* На сенсорном вводе цели растут. any-pointer, а не pointer: у ноутбука
     с тачскрином первичный ввод — мышь, но пальцем по нему тоже тыкают.   */
  @media (any-pointer: coarse) {
    a[href], button, [role="button"], summary, label[for],
    input[type="checkbox"], input[type="radio"] {
      min-height: var(--tap);
    }
    button, [role="button"], input[type="checkbox"], input[type="radio"] {
      min-width: var(--tap);
    }
  }

  /* Ссылка внутри абзаца — исключение Inline в SC 2.5.8: её размер задан
     строкой текста, растягивать нельзя. Явно снимаем требование, чтобы
     правило выше не ломало вёрстку текста.                                */
  @media (any-pointer: coarse) {
    p a[href], li a[href] { min-height: 0; }
  }

  /* Ховер-эффекты только там, где есть указатель. На тач-экране :hover
     залипает после нажатия и выглядит как «кнопка не отжалась».           */
  @media (hover: none) {
    a:hover, button:hover, [role="button"]:hover { transform: none; }
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

@layer mendee.util {
  /* Обёртка страницы: поле по краям + предел ширины. */
  .m-wrap {
    width: 100%;
    max-width: var(--wrap-max);
    margin-inline: auto;
    padding-inline: var(--pad-x);
  }

  /* Колонка текста читаемой длины. */
  .m-prose { max-width: var(--content-max); }

  /* Таблица, которая не помещается: прокручивается САМА, а не тянет
     страницу. WCAG 1.4.10 разрешает двумерную прокрутку таблице данных,
     но только ей — заголовки и навигация вокруг обязаны переноситься.
     Разметка: <div class="m-tablewrap"><table>…</table></div>            */
  .m-tablewrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
  }
  .m-tablewrap > table { min-width: max-content; }

  /* Сетка, которая сама решает, сколько колонок влезло. Без медиазапросов
     и без риска переполнения: колонка не станет уже своего минимума.      */
  .m-grid {
    display: grid;
    gap: var(--tap-gap);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  }

  /* Ряд действий: на узком экране кнопки переносятся, а не сжимаются
     и не обрезаются. Фиксированная высота + nowrap — вторая по частоте
     причина обрезанного текста в нашем аудите, особенно на локалях,
     где строка длиннее русской на 10-20%.                                 */
  .m-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tap-gap);
  }
  .m-actions > * {
    min-height: var(--tap);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    white-space: normal;   /* не nowrap: пусть переносится               */
    text-align: center;
  }

  /* Увеличить зону нажатия, не двигая вёрстку: отрицательный margin
     компенсирует padding. Для мелких ссылок в плотных списках.           */
  .m-tap {
    display: inline-flex;
    align-items: center;
    min-height: var(--tap);
    padding: 8px 10px;
    margin: -8px -10px;
  }

  /* Принудительный перенос для длинных строк вне списка выше. */
  .m-break { overflow-wrap: anywhere; }
}
