/*
Theme Name: Vira Skills
Theme URI: https://viraskills.online/
Author: Vira Skills
Description: Лёгкая тема школы Vira Skills. Тема A «Ember Dual», светлый режим, дизайн-система компании infobiz. Шрифты самохостятся в теме — внешних запросов страница не делает. Шапка и подвал темы дают обязательные сведения о продавце и ссылки на оферту на КАЖДОЙ странице, включая страницы Tutor LMS (курс, корзина, оформление заказа).
Version: 1.0.0
Requires at least: 6.5
Tested up to: 7.0
Requires PHP: 8.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: vira-skills
Tags: education, custom-colors, accessibility-ready
*/

/* ──────────────────────────────────────────────────────────────
   ШРИФТЫ — только свои файлы, никаких CDN.
   Мы ИП РФ и собираем почту: обращение к чужому CDN отдало бы IP
   посетителя третьей стороне. Лицензия OFL самохостинг разрешает
   (см. Company/companies/infobiz/legal/FONTS-AND-FOOTER.md).
   ────────────────────────────────────────────────────────────── */
@font-face{
  font-family:'Oswald';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('assets/fonts/oswald-cyrillic.woff2') format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}
@font-face{
  font-family:'Oswald';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('assets/fonts/oswald-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:'Inter';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('assets/fonts/inter-cyrillic.woff2') format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}
@font-face{
  font-family:'Inter';font-style:normal;font-weight:400 700;font-display:swap;
  src:url('assets/fonts/inter-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:'JetBrains Mono';font-style:normal;font-weight:400 500;font-display:swap;
  src:url('assets/fonts/jetbrains-mono-cyrillic.woff2') format('woff2');
  unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116;
}
@font-face{
  font-family:'JetBrains Mono';font-style:normal;font-weight:400 500;font-display:swap;
  src:url('assets/fonts/jetbrains-mono-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;
}

/* ── Токены дизайн-системы: тема A «Ember Dual», светлый режим ── */
:root{
  --vs-bg:#FFFFFF;
  --vs-bg-2:#F7F4EE;
  --vs-text:#1A1A1A;
  --vs-text-muted:#57606A;
  --vs-accent-ink:#C24500;   /* ember для ТЕКСТА на светлом — 5.07:1 */
  --vs-accent:#E8590C;       /* ember для заливок и крупного */
  --vs-on-accent:#FFFFFF;
  --vs-line:#D8D2C7;

  --vs-sp-1:8px; --vs-sp-2:16px; --vs-sp-3:24px; --vs-sp-4:32px;
  --vs-sp-6:48px; --vs-sp-8:64px; --vs-sp-12:96px;
  --vs-r:8px;
  --vs-maxw:1080px;

  /* Шкала кеглей §3.2 дизайн-системы — модульная 1.25, база 16.
     Промежуточных значений в ней нет: нужен «размер между» — значит нужна
     другая роль текста, а не другое число. 16px — пол, ниже не бывает нигде
     (ЦА 40–60+). Токены заведены, чтобы кегль можно было проверить
     grep-ом, а не глазом. */
  --vs-fs-xs:13px;    /* моно-метки, сноски, powered-by  */
  --vs-fs-sm:14px;    /* подписи                         */
  --vs-fs-base:16px;  /* 🔒 пол текста                   */
  --vs-fs-md:20px;    /* лид, вводный абзац              */
  --vs-fs-lg:25px;    /* h3                              */
  --vs-fs-xl:31px;    /* h2                              */
  --vs-fs-2xl:39px;   /* h1 страницы                     */
  --vs-fs-3xl:49px;   /* h1 слайда                       */
  --vs-fs-hero:clamp(39px,6vw,96px);  /* hero / обложка  */

  /* Кнопка — собственный кегль компонента, не ступень шкалы.
     §4.1 дизайн-системы, светлый режим: «текст #FFFFFF 19px bold (иначе AA
     не проходит)»: заливка --accent даёт 3.58:1, а этого достаточно только
     для крупного текста (≥18.66px bold). Ступени 16 и 20 тут не подходят:
     16 не проходит контраст, 20 — роль лида. Значение взято из системы. */
  --vs-fs-btn:19px;

  --vs-font-display:'Oswald',Impact,'Arial Narrow',system-ui,sans-serif;
  --vs-font-text:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif;
  --vs-font-mono:'JetBrains Mono',ui-monospace,'SFMono-Regular',Consolas,monospace;

  /* Tutor LMS красится нашим ember, чтобы путь «лендинг → курс → оплата»
     не менял язык посреди дороги (запрет 2 §2 дизайн-системы). */
  --tutor-color-primary:#E8590C;
  --tutor-color-primary-hover:#C24500;
  --tutor-color-primary-rgb:232,89,12;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
/* Картинка не распирает страницу. Без этого правила иллюстрация пустой
   корзины Tutor (её ширина 560px) выносила документ за экран на 100px
   при ширине 360 [замер 22.07]. Правило базовое: касается любой картинки
   на любой странице, а не одной корзины. */
img{max-width:100%;height:auto}
body{
  margin:0;
  background:var(--vs-bg);
  color:var(--vs-text);
  font-family:var(--vs-font-text);
  /* Ступень --fs-base: она же 🔒 пол кегля (§3.2, ЦА 40–60+).
     Было 18px — такого размера в шкале нет. Хотим тело крупнее пола —
     это новая ступень шкалы, то есть вопрос к дизайн-системе,
     а не число в теме. */
  font-size:var(--vs-fs-base);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}

h1,h2,h3,h4{font-family:var(--vs-font-display);font-weight:600;line-height:1.15;letter-spacing:-.01em}

/* Лестница заголовков — ступенями шкалы §3.2, одна на весь сайт.
   Было clamp(32,7vw,54) / clamp(27,5vw,39) / clamp(20,3.4vw,25): концы
   32 · 54 · 27 в шкале отсутствуют, а «резинка» между ступенями выдаёт
   на промежуточных ширинах значения, которых в шкале нет вообще.
   Лестница едет целиком: на узком 31/25/20, с брейкпоинта 640 — 39/31/25.
   Причина нижней ступени замером: «Политика конфиденциальности» на 39px
   не влезает в колонку 312px на 360 и выпирает за экран [замер 22.07]. */
.vs-main h1{font-size:var(--vs-fs-xl)}
.vs-main h2{font-size:var(--vs-fs-lg)}
.vs-main h3{font-size:var(--vs-fs-md)}
@media(min-width:640px){
  .vs-main h1{font-size:var(--vs-fs-2xl)}
  .vs-main h2{font-size:var(--vs-fs-xl)}
  .vs-main h3{font-size:var(--vs-fs-lg)}
}
/* Ширина текста — по контейнеру, без меры по числу знаков (решение владельца
   23.07, DESIGN-SYSTEM §3.2). `.vs-main p` собственной ширины не имеет. */
/* Кнопки красятся своими правилами — исключаем их, иначе селектор с элементом
   перебивает класс кнопки по специфичности и текст на заливке уходит в ember. */
.vs-main a:not(.vs-cta):not(.vs-ghost){color:var(--vs-accent-ink)}
/* Подвала здесь нет намеренно: его стили — в inc/site-footer.php, один блок
   на весь сайт (лендинги style.css не получают). */
.vs-main a:focus-visible,
.vs-site-header a:focus-visible{outline:3px solid var(--vs-text);outline-offset:3px}

.vs-wrap{max-width:var(--vs-maxw);margin:0 auto;padding:0 24px}
@media(min-width:900px){.vs-wrap{padding:0 40px}}

.vs-section{padding:var(--vs-sp-8) 0;border-top:1px solid var(--vs-line)}
.vs-section > .vs-wrap > h2{margin:0}
.vs-section > .vs-wrap > h2 + p{margin-top:var(--vs-sp-2);color:var(--vs-text-muted)}

/* Чип/метка — §4.5 дизайн-системы дословно: «JetBrains Mono, --fs-xs 13px,
   uppercase, letter-spacing .14em, padding 4px 12px», на светлом — рамка
   --accent-ink и текст --accent-ink. Это единственная роль, которой система
   разрешает кегль ниже пола: метка, а не текст. Поля 4px — тот самый случай,
   который §3.3 разрешает «внутри чипа/иконки». */
.vs-eyebrow{
  font-family:var(--vs-font-mono);font-size:var(--vs-fs-xs);font-weight:500;
  text-transform:uppercase;letter-spacing:.14em;
  color:var(--vs-accent-ink);
  display:inline-block;
  border:1px solid var(--vs-accent-ink);border-radius:999px;
  padding:4px 12px;
}

/* ── Шапка сайта ── */
.vs-site-header{padding:var(--vs-sp-3) 0 var(--vs-sp-3);border-bottom:1px solid var(--vs-line)}
.vs-site-header .vs-wrap{display:flex;flex-wrap:wrap;gap:var(--vs-sp-2) var(--vs-sp-4);align-items:center;justify-content:space-between}
/* Знак слева, название и слоган справа — колонкой рядом с ним. */
.vs-brand{display:flex;align-items:center;gap:var(--vs-sp-2);text-decoration:none}
.vs-brand-mark{display:block;width:52px;height:52px;border-radius:var(--vs-r);flex:0 0 auto}
/* Без gap: расстояние между названием и слоганом даёт межстрочный интервал.
   Стек названия — не чип и не иконка, поэтому поблажку §3.3 на 4px сюда
   тянуть нельзя, а своего числа заводить не из чего. */
.vs-brand-text{display:flex;flex-direction:column;min-width:0}
/* Wordmark — ступень --fs-lg (было 24px, такой ступени в шкале нет).
   Слоган — --fs-base: его читают, значит это текст, а текста ниже пола
   16px не бывает (§3.2). Было 15px — ниже пола и вне шкалы. */
.vs-wordmark{
  font-family:var(--vs-font-display);font-weight:600;font-size:var(--vs-fs-lg);
  text-transform:uppercase;letter-spacing:.04em;color:var(--vs-text);
}
.vs-wordmark .vs-mark{color:var(--vs-accent-ink)}   /* один ember-удар */
.vs-brand .vs-tagline{font-size:var(--vs-fs-base);color:var(--vs-text-muted)}
.vs-nav{display:flex;flex-wrap:wrap;gap:var(--vs-sp-1) var(--vs-sp-3);font-size:var(--vs-fs-base)}
/* Пункт меню — тач-цель, а не строка текста: §7 требует ≥44px, замер давал
   36px [22.07]. Высоту держит min-height, а не увеличенные поля, иначе
   подчёркивание активного пункта отъезжает от слова. */
.vs-nav a{color:var(--vs-text);text-decoration:none;border-bottom:1px solid transparent;
  display:inline-flex;align-items:center;min-height:44px}
.vs-nav a:hover{border-bottom-color:var(--vs-accent-ink)}
.vs-nav a[aria-current="page"]{color:var(--vs-accent-ink);border-bottom-color:var(--vs-accent-ink)}

/* ── Первый экран ── */
.vs-hero{border-top:none;padding-top:var(--vs-sp-6);padding-bottom:var(--vs-sp-8)}
/* Первый экран — единственное место с ролью «hero» (§3.2, ступень --fs-hero
   clamp(39px,6vw,96px)). Было clamp(32px,7vw,54px) — самодельная резинка
   между ступенями. Лид — ступень --fs-md «лид, вводный абзац» (было
   clamp(19,2.6vw,23): ни один конец в шкалу не попадает). */
.vs-hero h1{margin:var(--vs-sp-3) 0 0;font-size:var(--vs-fs-hero)}
/* Нижний отступ задан явно: браузерный `1em` при кегле 20px даёт 20px —
   число не по шагу сетки и не токеном. */
.vs-hero .vs-lead{font-size:var(--vs-fs-md);margin:var(--vs-sp-3) 0 0;color:var(--vs-text)}
.vs-hero .vs-lead b{color:var(--vs-accent-ink);font-weight:600}

/* ── Кнопки ── */
/* Кнопки — по §4.1/§4.2 дизайн-системы: кегль --fs-btn 19px (см. токен),
   «🔒 Тач-цель ≥ 44×44px в любом состоянии — min-height:48px;
   padding:14px 28px». Было 21px / 56px / 15px·34px — ни кегля, ни полей
   в системе нет. */
.vs-cta{
  display:block;width:100%;
  background:var(--vs-accent);color:var(--vs-on-accent);
  font-family:var(--vs-font-display);font-weight:600;font-size:var(--vs-fs-btn);
  letter-spacing:.01em;
  text-decoration:none;text-align:center;
  min-height:48px;padding:14px 28px;border-radius:var(--vs-r);
  border:0;cursor:pointer;
  transition:background .12s,transform .12s;
}
.vs-cta:hover{background:#C24500;transform:translateY(-2px);color:var(--vs-on-accent)}
.vs-cta:active{background:#A33900;transform:translateY(0)}
.vs-cta:focus-visible{outline:3px solid var(--vs-text);outline-offset:3px}
.vs-ghost{
  display:block;width:100%;
  border:2px solid var(--vs-accent-ink);color:var(--vs-accent-ink);background:transparent;
  font-family:var(--vs-font-display);font-weight:600;font-size:var(--vs-fs-btn);
  text-decoration:none;text-align:center;
  min-height:48px;padding:14px 28px;border-radius:var(--vs-r);
}
.vs-ghost:hover{background:rgba(232,89,12,.12)}
.vs-cta-block{margin-top:var(--vs-sp-4);display:flex;flex-wrap:wrap;gap:var(--vs-sp-2);align-items:center}
.vs-cta-note{margin-top:var(--vs-sp-2);font-size:var(--vs-fs-base);color:var(--vs-text-muted)}
/* Кнопка во всю ширину — состояние по умолчанию (проектируем с 360 вверх,
   §3.3), с первого системного брейкпоинта становится обычной.
   Было наоборот, через самодельный `max-width:520px`. */
@media(min-width:640px){.vs-cta,.vs-ghost{display:inline-block;width:auto}}

/* ── Карточки и списки ── */
.vs-grid{display:grid;gap:var(--vs-sp-2);margin-top:var(--vs-sp-4);grid-template-columns:1fr}
@media(min-width:900px){
  .vs-grid.vs-two{grid-template-columns:1fr 1fr}
  .vs-grid.vs-three{grid-template-columns:repeat(3,1fr)}
}
.vs-card{
  background:var(--vs-bg-2);border:1px solid var(--vs-line);border-radius:var(--vs-r);
  padding:var(--vs-sp-3);
}
.vs-card h3{margin:0 0 var(--vs-sp-1)}
.vs-card p{color:var(--vs-text);max-width:none}
/* Воздух между соседними абзацами в контенте (§3.5 «предложение = абзац»
   даёт много подряд идущих <p>): лид, вводки секций, финал, карточки. */
.vs-main p + p{margin-top:var(--vs-sp-2)}
.vs-card p + p{margin-top:var(--vs-sp-2)}

.vs-list{list-style:none;padding:0;margin:var(--vs-sp-3) 0 0;display:grid;gap:var(--vs-sp-2)}
.vs-list li{position:relative;padding-left:var(--vs-sp-4)}
/* top — выключка кружка по центру первой строки (16px × 1.6 = 25.6,
   середина 12.8, минус половина кружка): это выравнивание иконки,
   а не отступ ритма. */
.vs-list li::before{
  content:"";position:absolute;left:0;top:6px;
  width:14px;height:14px;border-radius:50%;
  background:var(--vs-accent);
}

/* ── Цена («честная цифра», §4.6 дизайн-системы) ── */
/* Цена набирается узким плакатным шрифтом, а не моноширинным: у моноширинного
   каждая цифра занимает одинаковую широкую ячейку, и «39 000 ₽» разъезжается
   дырами. Oswald узкий и вертикальный — цифры стоят плотно и читаются как
   единое число. font-variant-numeric:tabular-nums держит разряды ровными. */
/* Крупное число — ступень --fs-2xl (§4.6 дословно: «Крупное число —
   --fs-2xl»). Было clamp(34px,5.5vw,44px) — резинка мимо шкалы. */
.vs-price{
  font-family:var(--vs-font-display);font-weight:600;font-size:var(--vs-fs-2xl);
  letter-spacing:-.01em;font-variant-numeric:tabular-nums;line-height:1.05;
  color:var(--vs-accent-ink);display:block;margin:var(--vs-sp-1) 0;
}
.vs-price-note{font-size:var(--vs-fs-base);color:var(--vs-text-muted);display:block}
.vs-tariff{display:flex;flex-direction:column;height:100%}
.vs-tariff ul{list-style:none;padding:0;margin:var(--vs-sp-2) 0 0;display:grid;gap:var(--vs-sp-1);font-size:var(--vs-fs-base)}
.vs-tariff li{position:relative;padding-left:var(--vs-sp-3)}
.vs-tariff li::before{content:"✓";position:absolute;left:0;color:var(--vs-accent-ink);font-weight:700}
.vs-tariff li.vs-no{color:var(--vs-text-muted)}
.vs-tariff li.vs-no::before{content:"—";color:var(--vs-text-muted)}

/* ── Оплата частями (рассрочка) ──
   Компонент «честная цифра» (§4.6 дизайн-системы): крупный месячный платёж
   и ПОЛНАЯ цена стоят одним блоком, полная цена не мельче 16px и ни во что
   не свёрнута. Крупное число собрано из двух частей, чтобы на 360px
   переносилось «в месяц», а не сама сумма. */
.vs-inst{
  background:var(--vs-bg-2);border:1px solid var(--vs-line);
  border-left:4px solid var(--vs-accent);border-radius:var(--vs-r);
  padding:var(--vs-sp-3);margin:var(--vs-sp-6) 0 0;
}
.vs-inst > h2,.vs-inst > h3{margin:0}
/* Ступени вместо резинки: на узком --fs-xl, с брейкпоинта 640 — --fs-2xl,
   как у остальной лестницы. Было clamp(29px,6vw,39px). */
.vs-inst .vs-inst-anchor{
  margin:var(--vs-sp-2) 0 0;max-width:none;
  font-size:var(--vs-fs-xl);line-height:1.2;
}
@media(min-width:640px){.vs-inst .vs-inst-anchor{font-size:var(--vs-fs-2xl)}}
.vs-inst .vs-inst-per{font-family:var(--vs-font-text);font-size:var(--vs-fs-base);color:var(--vs-text);white-space:nowrap}
.vs-inst .vs-inst-of{margin:var(--vs-sp-1) 0 0;font-size:var(--vs-fs-base)}
.vs-inst .vs-inst-grid{margin-top:var(--vs-sp-3)}
.vs-inst .vs-inst-grid + h3{margin-top:var(--vs-sp-4)}
.vs-inst-card{background:var(--vs-bg)}
.vs-inst-card h3{font-size:var(--vs-fs-md)}
.vs-inst-price{margin:0;font-size:var(--vs-fs-base)}
.vs-inst-terms{list-style:none;padding:0;margin:var(--vs-sp-2) 0 0;display:grid;gap:var(--vs-sp-1);font-size:var(--vs-fs-base)}
.vs-inst-sum{font-family:var(--vs-font-mono);font-weight:500;font-size:var(--vs-fs-md);color:var(--vs-accent-ink)}
.vs-inst-total{margin:var(--vs-sp-2) 0 0;font-size:var(--vs-fs-base);color:var(--vs-text-muted)}
.vs-inst .vs-inst-how{margin-top:var(--vs-sp-2)}
.vs-inst .vs-inst-how li{font-size:var(--vs-fs-base)}
.vs-inst-short{margin-top:var(--vs-sp-4)}

/* ── Таблица ── */
.vs-tablewrap{overflow-x:auto;margin-top:var(--vs-sp-4)}
/* min-width 480 = 60 × шаг сетки: ниже этого таблица нечитаема и её
   прокручивает .vs-tablewrap. Прежние 520 путались с самодельным
   брейкпоинтом того же числа, который убран. */
.vs-table{border-collapse:collapse;width:100%;min-width:480px;font-size:var(--vs-fs-base)}
/* Поля ячейки — по шагу сетки 8px (§3.3), а не «12 на 14 на глаз». */
.vs-table th,.vs-table td{border:1px solid var(--vs-line);padding:var(--vs-sp-2);text-align:left;vertical-align:top}
.vs-table th{background:var(--vs-bg-2);font-family:var(--vs-font-display);font-weight:600}
.vs-table td.vs-num{font-family:var(--vs-font-mono);white-space:nowrap}

/* ── Уроки ── */
/* Одна колонка — состояние по умолчанию (§3.3: на мобайле 1 колонка,
   проектируем с 360 вверх). Номер встаёт слева с системного брейкпоинта 640;
   было наоборот, через самодельный `max-width:560px`. */
.vs-lesson{
  display:grid;grid-template-columns:1fr;gap:var(--vs-sp-2);
  align-items:start;padding:var(--vs-sp-3) 0;border-bottom:1px solid var(--vs-line);
}
@media(min-width:640px){
  .vs-lesson{grid-template-columns:auto 1fr;gap:var(--vs-sp-2) var(--vs-sp-3)}
}
.vs-lesson:first-of-type{border-top:1px solid var(--vs-line)}
.vs-lesson .vs-num{
  font-family:var(--vs-font-mono);font-weight:500;font-size:var(--vs-fs-base);
  color:var(--vs-on-accent);background:var(--vs-accent-ink);
  width:40px;height:40px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
}
.vs-lesson h3{margin:0 0 var(--vs-sp-1)}
.vs-lesson p{margin:0}

/* ── Автор, вопросы, финал ── */
.vs-author{background:var(--vs-bg-2);border:1px solid var(--vs-line);border-radius:var(--vs-r);padding:var(--vs-sp-4)}
.vs-author h2{margin:0 0 var(--vs-sp-2)}
.vs-author p + p{margin-top:var(--vs-sp-2)}
.vs-qa{margin-top:var(--vs-sp-4);display:grid;gap:var(--vs-sp-4)}
.vs-qa h3{margin:0}
.vs-qa p{margin-top:var(--vs-sp-1)}
.vs-final{background:var(--vs-bg-2)}

/* ── Обычная страница (заголовок + текст) ── */
.vs-page{padding:var(--vs-sp-6) 0 var(--vs-sp-8)}
.vs-page h1{margin:0 0 var(--vs-sp-3)}
.vs-page h2{margin:var(--vs-sp-6) 0 var(--vs-sp-2)}
.vs-page h3{margin:var(--vs-sp-4) 0 var(--vs-sp-1)}
.vs-page p,.vs-page ul,.vs-page ol{margin:0 0 var(--vs-sp-2)}
.vs-page ul,.vs-page ol{padding-left:24px}
.vs-page li{margin-bottom:8px}

/* ── СТРАНИЦА-ДОКУМЕНТ: одна сетка с шапкой и подвалом ──
   _(требование владельца 22.07: «в подвале информация выставлена по одной
   ширине — вот так же и текст должен идти. Везде»)_

   Правило одно и без исключений: у документа ВСЁ — заголовки, абзацы, списки,
   таблицы — идёт по той же колонке `.vs-wrap`, что шапка и подвал. Левый и
   правый край совпадают на всех трёх, поэтому страница читается как один
   выверенный лист, а не как набор блоков разной ширины.

   ⚠️ Не возвращать сюда `max-width` по типографской мере — ни на колонку,
   ни на абзацы. Ограничение длины строки снято по всему сайту решением
   владельца 23.07 (DESIGN-SYSTEM §3.2): длина строки = ширина контейнера
   и отступы, и на документе, и на лендинге. Прежде пробовали обрезку —
   край контента расходился с подвалом, это видно глазом.

   Класс ставится на `<main>` у КАЖДОЙ текстовой страницы: оферта, политика,
   реквизиты, «Оплата и возврат», «Контакты». Одна страница без него —
   и разнобой возвращается ровно там, где его заметят.

   Исключение одно и по смыслу: элементы управления, а не текст. Поле ввода
   формы (`.vs-form`) держит свою ширину — строку ввода на всю колонку
   никто не заполняет. */
.vs-doc p,.vs-doc ul,.vs-doc ol,.vs-doc li,
.vs-doc h1,.vs-doc h2,.vs-doc h3,.vs-doc h4,
.vs-doc blockquote,.vs-doc table{max-width:none}

/* Отдельной лестницы у документа больше нет: она одна на весь сайт
   и живёт выше, на `.vs-main` (39/31/25, на узком 31/25/20). Свою копию
   здесь держать нельзя — две лестницы разъедутся при первой же правке. */

.vs-note{background:var(--vs-bg-2);border:1px solid var(--vs-line);border-left:4px solid var(--vs-accent);
  border-radius:var(--vs-r);padding:var(--vs-sp-3);margin:var(--vs-sp-4) 0;max-width:none}
.vs-note p{max-width:none}
.vs-note p + p{margin-top:var(--vs-sp-2)}

/* ── Форма (страница «Контакты») ── */
.vs-form{max-width:32em;margin-top:var(--vs-sp-4);display:grid;gap:var(--vs-sp-3)}
.vs-field{display:grid;gap:var(--vs-sp-1)}
.vs-field label{font-weight:600;font-size:var(--vs-fs-base)}
/* §4.3: высота 48px, кегль 16px (ниже 16 iOS зумит страницу).
   Высоту держит min-height, поэтому поля берутся по шагу сетки. */
.vs-field input,.vs-field textarea{
  font-family:var(--vs-font-text);font-size:var(--vs-fs-base);
  min-height:48px;padding:var(--vs-sp-1) var(--vs-sp-2);
  border:1px solid var(--vs-line);border-radius:var(--vs-r);
  background:var(--vs-bg);color:var(--vs-text);width:100%;
}
.vs-field textarea{min-height:144px;resize:vertical}
.vs-field input:focus,.vs-field textarea:focus{outline:3px solid var(--vs-text);outline-offset:2px;border-color:var(--vs-accent-ink)}
/* Согласие на обработку ПДн — чекбокс с меткой; тач-цель ≥44px (§7). */
.vs-consent label{display:flex;gap:var(--vs-sp-1);align-items:flex-start;min-height:44px;cursor:pointer;font-size:var(--vs-fs-base)}
.vs-consent input[type=checkbox]{width:24px;height:24px;margin:2px 0 0;flex:0 0 auto;accent-color:var(--vs-accent)}
.vs-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.vs-msg{border-radius:var(--vs-r);padding:var(--vs-sp-3);margin-top:var(--vs-sp-3);max-width:32em}
.vs-msg-ok{background:#E8F5E9;border:1px solid #2E7D32;color:#1A1A1A}
.vs-msg-err{background:#FDECEA;border:1px solid #C0392B;color:#1A1A1A}

/* ── Форма подписки Newsletter на НАШЕЙ странице («Рассылка») ──
   Разметку рисует плагин, но страница наша, и человек на ней видит нашу
   вёрстку. По замеру 22.07 форма приходила мимо системы целиком: подписи
   14.4px (ниже 🔒 пола 16px), поле и кнопка 40px (§4.3 требует 48),
   чекбокс 13×13 (§7 требует тач-цель ≥44), кнопка серая #444 вместо ember.
   Правим селекторами у себя — разметку плагина не трогаем. */
/* Ритм формы тоже плагинский и не по шагу: поля разделял `0.7em` = 11.2px,
   подпись отбивалась 4px, у чекбокса стояло `margin:3px 6.67px 3px 4px`. */
/* `form div` в селекторе — не украшение: плагин держит отступ правилом
   `.tnp-subscription div.tnp-field` той же силы, а его файл подключается
   после нашего, поэтому при равном весе выигрывал он. */
.vs-main form div.tnp-field{margin-bottom:var(--vs-sp-2)}
.vs-main .tnp-field label{font-size:var(--vs-fs-base);font-weight:600;color:var(--vs-text);margin-bottom:var(--vs-sp-1)}
.vs-main .tnp-privacy-field label{margin-bottom:0;font-weight:400}
.vs-main .tnp-field input[type=email],
.vs-main .tnp-field input[type=text]{
  font-family:var(--vs-font-text);font-size:var(--vs-fs-base);
  min-height:48px;padding:var(--vs-sp-1) var(--vs-sp-2);
  border:1px solid var(--vs-line);border-radius:var(--vs-r);
  background:var(--vs-bg);color:var(--vs-text);width:100%;
}
.vs-main .tnp-field input:focus{outline:3px solid var(--vs-text);outline-offset:2px;border-color:var(--vs-accent-ink)}
/* Согласие: сам квадрат крупнее, а тач-цель набирает подпись — она
   обёрнута вокруг чекбокса, то есть нажимается целиком. */
.vs-main .tnp-privacy-field label{display:flex;align-items:center;gap:var(--vs-sp-1);min-height:44px}
/* `max-width` снимается тоже: плагин держит на чекбоксе `max-width:1em`
   («fixes some bad themes CSS»), и от одной ширины квадрат оставался 13px. */
.vs-main .tnp-privacy-field input[type=checkbox]{
  width:24px;height:24px;max-width:none;margin:0;flex:0 0 auto;accent-color:var(--vs-accent);
}
.vs-main .tnp-field input[type=submit]{
  background:var(--vs-accent);color:var(--vs-on-accent);
  font-family:var(--vs-font-display);font-weight:600;font-size:var(--vs-fs-btn);
  letter-spacing:.01em;text-align:center;
  min-height:48px;padding:14px 28px;border-radius:var(--vs-r);
  border:0;cursor:pointer;width:100%;
  transition:background .12s,transform .12s;
}
.vs-main .tnp-field input[type=submit]:hover{background:#C24500;transform:translateY(-2px)}
.vs-main .tnp-field input[type=submit]:active{background:#A33900;transform:translateY(0)}
.vs-main .tnp-field input[type=submit]:focus-visible{outline:3px solid var(--vs-text);outline-offset:3px}
@media(min-width:640px){.vs-main .tnp-field input[type=submit]{width:auto}}

/* ── Секция «Подписка на новости» — карточка-панель (Fluentform id 3) ──
   Тема A, светлый режим, токены DESIGN-SYSTEM.md. Карточка на тёплом bg-2 с
   лёгкой диагональной фактурой, скруглением, мягкой тенью и пунктирной рамкой
   внутри; наклонный ember-стикер «Бесплатно». Форма: поле e-mail + кнопка в
   ОДНУ строку (кнопка справа); на мобайле (<640) — вертикально. Согласие —
   строкой под формой (по действию), чекбокса нет. Разметку Fluentform (`.ff-*`)
   правим у себя; селекторы `.vs-newsletter .fluentform` (3 класса) перебивают
   тему плагина `ffs_default`. Акцент-текст на светлом — `--accent-ink` (§7). */
.vs-newsletter{padding:var(--vs-sp-8) 0}

.vs-nl-card{
  position:relative;background:var(--vs-bg-2);
  /* лёгкая диагональная фактура поверх тёплого фона — едва заметная */
  background-image:repeating-linear-gradient(135deg,rgba(26,26,26,.022) 0,rgba(26,26,26,.022) 1px,transparent 1px,transparent 7px);
  border:1px solid var(--vs-line);
  /* панель: 16px = 2×шаг сетки; крупнее радиуса контролов (8px) — по образцу владельца */
  border-radius:16px;box-shadow:0 10px 30px rgba(26,26,26,.07);
  /* плоский широкий баннер: вертикальные поля меньше горизонтальных, воздуха по высоте меньше */
  padding:var(--vs-sp-4) var(--vs-sp-6)}
/* Декоративная пунктирная рамка внутри у края (купонный вид). */
.vs-nl-card::before{content:"";position:absolute;inset:10px;
  border:2px dashed rgba(194,69,0,.30);border-radius:10px;pointer-events:none}
/* Наклонный ember-стикер «Бесплатно» — сидит на верхнем крае, чуть выступая
   вверх (сдвиг −30% высоты), чтобы не пересекаться с кнопкой. Заливка
   --accent-ink (белый на нём 5.07:1, §7). */
.vs-nl-sticker{position:absolute;top:0;right:var(--vs-sp-4);z-index:3;
  transform:translateY(-40%) rotate(-4deg);background:var(--vs-accent-ink);color:var(--vs-on-accent);
  font-family:var(--vs-font-display);font-weight:700;font-size:var(--vs-fs-base);
  text-transform:uppercase;letter-spacing:.06em;padding:5px 16px;border-radius:4px;
  box-shadow:0 4px 10px rgba(26,26,26,.18)}
/* Мобайл (<640): вынос стикера вверх на узком экране срезается краем
   (overflow-x:hidden предка переводит overflow-y в auto и клипает). Сажаем
   стикер ЦЕЛИКОМ внутрь верхнего края (без сдвига вверх) и даём карточке запас
   сверху, чтобы он не налезал на кикер. */
@media(max-width:639px){
  .vs-nl-card{padding-top:var(--vs-sp-8)}
  .vs-nl-sticker{top:var(--vs-sp-2);transform:rotate(-4deg)}
}
/* Десктоп: карточка плоская, но кнопка стоит близко к верху — даём немного
   верхнего поля, чтобы между стикером и кнопкой был чистый зазор. */
@media(min-width:900px){.vs-nl-card{padding-top:var(--vs-sp-6)}}

/* Лёгкий «пульс» стикера — привлекает глаз, не мигалка. Анимируем ТОЛЬКО
   transform (scale), без layout shift. Поворот −4° и позиционирование
   сохранены в keyframes (десктоп несёт translateY(-40%), мобайл — нет), иначе
   они сбросились бы. Амплитуда 5% — на пике не задевает кнопку (зазор ~22px).
   🔒 Гейт §7: анимация только при prefers-reduced-motion: no-preference. */
@keyframes vs-nl-pulse-d{
  0%,100%{transform:translateY(-40%) rotate(-4deg) scale(1);box-shadow:0 4px 10px rgba(26,26,26,.18)}
  50%{transform:translateY(-40%) rotate(-4deg) scale(1.05);box-shadow:0 6px 16px rgba(26,26,26,.24)}
}
@keyframes vs-nl-pulse-m{
  0%,100%{transform:rotate(-4deg) scale(1);box-shadow:0 4px 10px rgba(26,26,26,.18)}
  50%{transform:rotate(-4deg) scale(1.05);box-shadow:0 6px 16px rgba(26,26,26,.24)}
}
@media (prefers-reduced-motion: no-preference) and (min-width:640px){
  .vs-nl-sticker{animation:vs-nl-pulse-d 1.8s ease-in-out infinite}
}
@media (prefers-reduced-motion: no-preference) and (max-width:639px){
  .vs-nl-sticker{animation:vs-nl-pulse-m 1.8s ease-in-out infinite}
}

.vs-nl-main{position:relative;z-index:1;display:grid;gap:var(--vs-sp-3);grid-template-columns:1fr}
/* Правая (форм-)колонка шире левой — поле доминирует, как в образце. */
@media(min-width:900px){.vs-nl-main{grid-template-columns:minmax(0,4fr) minmax(0,8fr);gap:var(--vs-sp-6);align-items:center}}

/* Левая колонка */
.vs-nl-kicker{display:inline-block;font-family:var(--vs-font-mono);font-size:var(--vs-fs-sm);
  color:var(--vs-text-muted);letter-spacing:.04em;margin-bottom:var(--vs-sp-2)}
.vs-nl-card h2{margin:0}
.vs-nl-lead{display:flex;gap:var(--vs-sp-1);align-items:flex-start;margin:var(--vs-sp-2) 0 0;
  color:var(--vs-text-muted);font-size:var(--vs-fs-base);line-height:1.6;max-width:none}
.vs-nl-env{flex:0 0 auto;margin-top:3px;color:var(--vs-accent-ink)}

/* Правая колонка: форма (поле+кнопка в строку), выгоды, согласие */
/* §4.3: видимый label не нужен — контекст даёт заголовок/лид; a11y держит
   aria-label на инпуте (label прячем, не удаляя из DOM). */
.vs-newsletter .fluentform .ff-el-input--label{position:absolute!important;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* Поле e-mail + кнопка — одна строка, кнопка справа. Fluentform оборачивает
   поля в <fieldset> — flex-контейнер именно он, а не <form>. hidden-поля
   display:none сами; sr-legend убираем из потока, чтобы не давал лишний gap. */
.vs-newsletter .frm-fluent-form fieldset{display:flex;flex-wrap:wrap;align-items:stretch;
  gap:var(--vs-sp-2);border:0;margin:0;padding:0;min-width:0}
.vs-newsletter .frm-fluent-form legend.ff_screen_reader_title{position:absolute}
.vs-newsletter .frm-fluent-form .ff-el-group{margin:0;flex:1 1 320px;min-width:0;order:1}
.vs-newsletter .frm-fluent-form .ff_submit_btn_wrapper{margin:0;flex:0 0 auto;order:2;display:flex}
/* Поле 44px (тач-цель — минимум §7), кегль 16px (ниже 16 iOS зумит). Поле растёт
   на всю ширину строки минус кнопка — доминирует, как в образце. */
.vs-newsletter .fluentform .ff-el-input--content{height:100%}
.vs-newsletter .fluentform .ff-el-form-control{
  font-family:var(--vs-font-text);font-size:var(--vs-fs-base);
  min-height:44px;height:100%;padding:var(--vs-sp-1) var(--vs-sp-2);
  border:1px solid var(--vs-line);border-radius:var(--vs-r);
  background:var(--vs-bg);color:var(--vs-text);width:100%;box-sizing:border-box}
.vs-newsletter .fluentform .ff-el-form-control:focus{
  outline:3px solid var(--vs-text);outline-offset:2px;border-color:var(--vs-accent-ink)}
.vs-newsletter .fluentform .ff-el-is-error .ff-el-form-control{border-color:#C0392B}
.vs-newsletter .fluentform .error,
.vs-newsletter .fluentform .text-danger{color:#C0392B;font-size:var(--vs-fs-sm);margin-top:var(--vs-sp-1)}
/* §4.2 кнопка ghost (ВТОРИЧНОЕ действие): не конкурирует с solid-ember primary
   лид-кнопкой (на экране один primary). Обводка 2px --accent-ink, фон прозрачный,
   текст --accent-ink (на светлой карточке 4.6:1 — AA), радиус 8px, hover — фон
   accent 12% альфы. Высота 44px (тач-цель §7), border-box чтобы высота с обводкой
   совпала с полем. */
.vs-newsletter .fluentform .ff-btn-submit{
  display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;
  background:transparent;color:var(--vs-accent-ink);
  font-family:var(--vs-font-display);font-weight:600;font-size:var(--vs-fs-btn);letter-spacing:.01em;
  min-height:44px;padding:0 var(--vs-sp-4);border:2px solid var(--vs-accent-ink);border-radius:var(--vs-r);
  cursor:pointer;white-space:nowrap;transition:background .12s}
.vs-newsletter .fluentform .ff-btn-submit:hover{background:rgba(232,89,12,.12)}
.vs-newsletter .fluentform .ff-btn-submit:focus-visible{outline:3px solid var(--vs-text);outline-offset:3px}
/* Мобайл (<640): поле на всю ширину, кнопка под ним на всю ширину. */
@media(max-width:639px){
  .vs-newsletter .frm-fluent-form fieldset{flex-direction:column;align-items:stretch}
  .vs-newsletter .frm-fluent-form .ff-el-group,
  .vs-newsletter .frm-fluent-form .ff_submit_btn_wrapper{flex:1 1 auto;width:100%}
  .vs-newsletter .fluentform .ff-btn-submit{width:100%}
}
/* Выгоды — мелкие вспомогательные подписи (14px, служебный регистр §3.2).
   ⚠️ Отклонение от пола 16px §3.2 — по прямой правке владельца (это подписи,
   не тело); отметить дизайнеру. Без само-деклараций честности (§6). */
.vs-nl-benefits{list-style:none;margin:var(--vs-sp-2) 0 0;padding:0;
  display:flex;flex-wrap:wrap;gap:var(--vs-sp-1) var(--vs-sp-3);font-size:var(--vs-fs-sm);color:var(--vs-text)}
.vs-nl-benefits li{position:relative;padding-left:var(--vs-sp-3)}
.vs-nl-benefits li::before{content:"\2713";position:absolute;left:0;color:var(--vs-accent-ink);font-weight:700}
/* Согласие по действию — мелкая приглушённая строка (служебный регистр §3.2, 14px). */
.vs-nl-consent{margin:var(--vs-sp-2) 0 0;font-size:var(--vs-fs-sm);color:var(--vs-text-muted);
  line-height:1.6;max-width:none}
.vs-nl-consent a{color:var(--vs-accent-ink);text-decoration:underline}
/* Сообщение после сабмита — §4.3 success/error: рамка + текст, не только цвет. */
.vs-newsletter .ff-message-success{
  background:#E8F5E9;border:1px solid #2E7D32;color:var(--vs-text);
  border-radius:var(--vs-r);padding:var(--vs-sp-3);font-size:var(--vs-fs-base)}

/* ── Пустое место под данные, которых у нас ещё нет ── */
.vs-todo{
  /* 15px было ниже пола шкалы (§3.2). Плашку читает человек — значит текст,
     значит не мельче 16px. Поля 2×8 — по шагу сетки не проходят, но §3.3
     разрешает 4 внутри чипа: это чип. */
  font-family:var(--vs-font-mono);font-size:var(--vs-fs-base);
  background:#FDECEA;border:1px dashed #C0392B;border-radius:4px;
  padding:4px 8px;color:#8A2A1E;
  /* переносится: на 360px строка «— текст готовится» иначе распирает страницу */
  display:inline;white-space:normal;overflow-wrap:anywhere;
}

/* ── Подвал ──
   Стилей подвала здесь НЕТ. Они лежат рядом с его разметкой — один блок
   в `inc/site-footer.php`, потому что лендинги плагина `blank-html-landing`
   этот файл не получают: подвал на них остался бы без сетки и кеглей.
   Правишь подвал — правишь только `inc/site-footer.php`. */

/* ── Стыковка с Tutor LMS ──
   Плагин рисует страницу курса своей вёрсткой, её мы не переписываем.
   Трогаем только заголовок курса: он должен быть роднёй заголовкам сайта,
   иначе путь «лендинг → курс» читается как переход на чужой сайт. */
.tutor-course-details-title{
  font-family:var(--vs-font-display);font-weight:600;letter-spacing:-.01em;
}

/* ── Скрытая ссылка «к содержимому» ── */
.vs-skip{position:absolute;left:-9999px}
.vs-skip:focus{left:var(--vs-sp-2);top:var(--vs-sp-2);z-index:999;background:var(--vs-bg);color:var(--vs-text);
  padding:var(--vs-sp-2) var(--vs-sp-3);border:2px solid var(--vs-text);border-radius:var(--vs-r)}
.screen-reader-text{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(1px,1px,1px,1px)}

/* Кнопка внутри карточки тарифа: прижата к низу, во всю ширину —
   у трёх карточек разной высоты кнопки должны стоять на одной линии. */
.vs-tariff{display:flex;flex-direction:column}
.vs-tariff ul{flex:1 1 auto}
.vs-cta-tariff{
  display:block;width:100%;text-align:center;
  margin-top:var(--vs-sp-3);padding:14px 28px;
}
