/*
 Theme Name:   bootCommerce Child
 Description:  bootScore WooCommerce Child Theme
 Author:       bootScore
 Author URI:   https://bootscore.me
 Template:     bootscore-main
 Version:      5.1.0.2
 Text Domain:  bootscore
*/

/*
All style editing is done via css/scss/_bscore_custom.scss
*/

/* Bootstrap */
.rounded {
	border-radius: 2.25rem !important;
}

.rounded-top {
	border-top-left-radius: 2.25rem !important;
    border-top-right-radius: 2.25rem !important;
}

.rounded-bottom {
	border-bottom-left-radius: 2.25rem !important;
    border-bottom-right-radius: 2.25rem !important;
}

.rounded-start {
    border-bottom-left-radius: 2.25rem !important;
    border-top-left-radius: 2.25rem !important;
}

.rounded-end {
    border-bottom-right-radius: 2.25rem !important;
    border-top-right-radius: 2.25rem !important;
}

.rounded-mini {
	border-radius: 1.75rem !important;
}

.modal-content {
    border-radius: 2.25rem !important;
}

.container-fluid-1920-xxl {
    width: 100%;
    padding-right: var(--bs-gutter-x, 0.75rem);
    padding-left: var(--bs-gutter-x, 0.75rem);
    margin-right: auto;
    margin-left: auto;
}

@media (min-width: 1921px) {
	.container-fluid-1920-xxl {
		max-width: 1320px;
	}
}


/* Легаси: цвет текста кнопок был зашит белым через !important. Снято 2026-08-19 —
   кнопки идут через контекстную палитру (раздел «КНОПКИ» в конце файла),
   где контрастный цвет вычисляется, а не назначается. Остался только .btn_dec. */
.btn_dec span {
    color: #fff !important;
}

.btn-secondary, .btn-secondary:hover, .btn-outline-secondary:hover, .btn-outline-secondary:active, .btn-outline-secondary:focus, .btn-outline-secondary.active, .btn-secondary:active, .btn-secondary:focus {
    color: #fff !important;
}

.card {
	border: none;
	box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 15%) !important;
	border-radius: 2.25rem !important;
}

.rotate {
    transform: rotateZ(315deg);
}

.accordion-item {
    background-color: transparent;
}



/* Цветовая схема */
.dark-theme .link-dark {
  color: var(--bs-light) !important;
}
@media (max-width: 768px) {
.dark-theme .woocommerce table.shop_table_responsive tr:nth-child(2n) td, .woocommerce-page table.shop_table_responsive tr:nth-child(2n) td {
	background-color: var(--bscore-shop-table-responsive, var(--bs-gray-dark));
}
}

.cookie_bg {
	background: #ffffffd6;
}


.bg_paints {
	display: block;
	position: relative;
}

.bg_deco {
	background-color: #ffffff3b;
  border: 5px dashed var(--bs-light);
}

.dark-theme .bg_deco {
	background-color: var(--macro-soft2);
	border: 5px dashed var(--macro-border);
}



.bg-trans-dark, .bg-opacity-dark {
	background-color: #0000000a;
}


.dark-theme .dark-img-inverse {
	filter: brightness(100);
}


/* Типографика — SF UI Display (MACRO) */

/* Легаси-классы .oswald / .roboto_m оставлены для обратной совместимости
   со старой разметкой и блоками, но указывают на брендовый шрифт. */
.oswald,
.roboto_m,
.sf-ui {
	font-family: 'SF UI Display', Roboto, system-ui, -apple-system, 'Segoe UI', Arial, sans-serif !important;
}

.fw-500 {
	font-weight: 500 !important;
}


/* Формы */

.form-control, .form-check-input[type="checkbox"] {
	border-radius: 0;
}

.form-control, .form-select, .form-check-input {
	background-color: #ffffff7a;
}

/* Граница контрола — ОТДЕЛЬНЫЙ токен, не волосяная линейка.
   В собранном bootstrap.min.css у .form-control / .form-select стоит
   литеральный #CACBCC (1.79 к белому), у .form-check-input —
   rgba(0,0,0,.25) (≈1.5 по эффективному цвету). Оба проваливают WCAG 1.4.11
   (границе КОНТРОЛА нужно ≥3:1), поэтому переводим их на --macro-line-strong:
   3.92 к белому, 3.53 к плите подвала.
   ⚠️ Декоративные линейки (.case-fact, .bottom_nav, --team-rule,
   .cases-head__rule) сюда НЕ переводятся и остаются на --macro-border /
   --ctx-border: 1.4.11 к разделителю не применяется, а «усиление» съело бы
   воздух и превратило вёрстку в сетку рамок. */
.form-control,
.form-select,
.form-check-input {
	border-color: var(--macro-line-strong);
}


.alert.alert-danger, .alert-danger.must-log-in, .alert-danger.no-comments, .alert.alert-warning, .alert-warning.must-log-in, .alert-warning.no-comments, .alert.alert-info, .alert-info.must-log-in, .must-log-in, .must-log-in.no-comments, .alert-info.no-comments, .no-comments.must-log-in, .no-comments, .alert.must-log-in, .alert.no-comments, .alert.alert-success, .alert-success.must-log-in, .alert-success.no-comments {
    padding-left: 3.25rem;
    border-radius: 2.25rem !important;
    margin-top: 0.5rem !important;
}

/* Parallax Effect */

.damn_magneto_xl, .damn_magneto {
	transition: 0.1s;
}

.focking_scaling {
	transform: scale(0.95);
	transition: 0.5s;
}

.focking_scaling:hover {
	transform: scale(1);
	transition: 0.5s;
}

.focking_scaling_bg_light {
	transform: scale(0.95);
	transition: 0.5s;
	background: transparent;
}

.focking_scaling_bg_light:hover {
	transform: scale(1);
	transition: 0.5s;
	background: radial-gradient(circle, rgba(var(--bs-light-rgb)) 0%, rgba(9,9,121,0) 60%);
}

/* Видео */


/* КНОПКА Play */

.video-block-trigger {
	cursor: pointer;
}

.video-block-trigger .play-button {
	height: 7rem;
  width: 7rem;
  display: block;
  position: absolute;
  top: calc(50% - 3.5rem);
  left: calc(50% - 3.5rem);
  border: 0.4rem solid var(--bs-white);
	box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 25%) !important;
  background: #00000021;
	transition: 0.5s;
	cursor: pointer;
}


.video-block-trigger .play-button .triangle-container {
	position: absolute;
	width: 3rem;
	height: 3rem;
	top: calc(50% - 1.5rem);
	left: calc(50% - 1.5rem);
}

.video-block-trigger .play-button .triangle,
.video-block-trigger .play-button .triangle:before,
.video-block-trigger .play-button .triangle:after {
	display: block;
	width:  2em;
	height: 2em;
	position: relative;
	background: var(--bs-white);
	transition: 0.5s;
	border-top-right-radius: 30%;
}

.video-block-trigger .play-button .triangle:before,
.video-block-trigger .play-button .triangle:after {
	content: '';
	position: absolute;
	margin: 0;
}

.video-block-trigger .play-button .triangle {
	transform: rotate(-90deg) skewX(-30deg) scale(1,.866);
}
.video-block-trigger .play-button .triangle:before {
	transform: rotate(-135deg) skewX(-45deg) scale(1.414,.707) translate(0,-50%);
}
.video-block-trigger .play-button .triangle:after {
	transform: rotate(135deg) skewY(-45deg) scale(.707,1.414) translate(50%);
}

.video-block-trigger:hover .play-button {
	border: 0.4rem solid var(--bs-white);
	background: var(--bs-white);
	transition: 0.5s;
	transform: scale(1.2);
}

.video-block-trigger:hover .play-button .triangle,
.video-block-trigger:hover .play-button .triangle:before,
.video-block-trigger:hover .play-button .triangle:after {
	background: var(--bs-primary);
	transition: 0.5s;
}


.vp-center #player {
	height: auto !important;
}

/* Кнопки — легаси-блок прежнего дизайна снят 2026-08-19.
   Было: border-radius: 0 !important (прямоугольные углы), фиксированный
   padding !important и белый текст !important. Всё это перебивало новую
   систему кнопок (пилюля + контекстный цвет), см. раздел «КНОПКИ» в конце
   файла — там один набор правил на весь сайт. */

#nav-main .btn {
	padding: 0.5rem 0.5rem !important
}

@media (min-width: 992px) {

#nav-main .btn {
	padding: 0.5rem 0 !important
}

}


/* Хедер */


.site-header {
	min-height: 100px;
}

.header_bg {
	position: relative;
	background: #ffffff38;
}


.header_bg:before {
	content: '';
	position: absolute;
	width: 100%;
	height: 100%;
	background: var(--bs-body-bg);
	opacity: 0.7;
	transition: 1s;
	z-index: -1;
}



.rotate {
	transform: rotateZ(315deg);
}

.dark-mode-switch .form-check-input[type="checkbox"] {
	border-radius: 2em;
}

#nav-main, .header_bg {
	transition: 0.5s;
}

.navbar-light .navbar-nav .offer_link a.nav-link {
	color: var(--bs-primary) !important;
}

/* Текст */
.text-justified {
	text-align: justify;
}

.text-shadow {
	text-shadow: 0px 0px 10px rgb(0 0 0);
}

.display-1, .display-2, .display-3, .display-4, .display-5, .display-6 {
	font-family: 'SF UI Display', Roboto, system-ui, -apple-system, 'Segoe UI', Arial, sans-serif !important;
	font-weight: 700;
}

.display-1 {
	font-size: calc(1.325rem + 3vw);
}

@media (min-width: 420px) {
	.display-1 {
		font-size: calc(1.625rem + 4.5vw);
	}
}

@media (min-width: 1200px) {
	.display-1 {
	    font-size: 5rem;
	}
}


.offer_link a {
	color: var(--bs-secondary) !important;
	opacity: 1 !important;
}

/* Разделители */

.hr-dashed {
	color: transparent;
	border-top: 2px dashed var(--bs-primary);
}












/* Заголовки */

.with_decor {
	padding-bottom: 1.5rem;
	position: relative;
}


/* Декоративная полоса под заголовком.
   Раньше на >=992px висел вынос left:-2.2rem — «свисающий» декор,
   подогнанный под метрики Oswald и левое выравнивание. С SF UI Display
   и центрированными заголовками он уезжал мимо текста (QA 2026-08-19),
   поэтому вынос убран: полоса привязана к самому тексту. */
.with_decor::after {
	content: "";
	left: 0;
	bottom: 0;
	position: absolute;
	width: 100px;
	max-width: 100%;
	height: 2px;
	/* ⚠️ Было var(--bs-primary) — то есть цвет ПРОЕКТА, а не страницы. Полоса
	   стоит под каждым H2 в тексте кейса, и на кейсе она обязана брать палитру
	   записи (канон «контекстная палитра», см. раздел ниже). Раньше нарушение
	   не бросалось в глаза, потому что прежний $primary #172747 читался почти
	   как основной текст; со сменой акцента на изумруд 01.09.2026 полоса на
	   кейсе стала зелёной поверх его собственной палитры — тогда и вскрылось.
	   Вне кейса поведение НЕ изменилось: там --ctx-accent == --bs-primary
	   (с 07.09.2026 в светлой оба #8b1d35, в тёмной оба #d33154). */
	background: var(--ctx-accent);
}

/* Центрируем, если центрирован сам заголовок — явным классом
   .with_decor_center или обычной утилитой .text-center */
.with_decor_center::after,
.with_decor.text-center::after,
.text-center .with_decor::after {
	left: 50%;
	transform: translateX(-50%);
}

/* Заголовок выровнен вправо — декор туда же */
.with_decor.text-end::after {
	left: auto;
	right: 0;
	transform: none;
}



/* Блок-вступление (hero) */

.social_links a {
	padding: 0.6rem 0 !important;
}

/* Стрелка «вниз, к содержанию» в hero кейса. Бокс держит САМА ссылка, а не
   svg внутри: раньше svg был абсолютным, ссылка схлопывалась в 0×0 и кольцо
   фокуса рисовалось в точку — первый же Tab на странице кейса уходил в никуда.
   Координаты перенесены на ссылку один-в-один, картинка не сдвинулась. */
.hero-scroll {
	display: block;
	position: absolute;
	left: 50%;
	bottom: 2rem;
	width: 60px;
	height: 72px;
	margin-left: -30px;
	border-radius: 4px;
}

.arrows {
	width: 60px;
	height: 72px;
	position: absolute;
	left: 50%;
	margin-left: -30px;
	bottom: 2rem;
}

.hero-scroll .arrows {
	position: static;
	left: auto;
	bottom: auto;
	margin-left: 0;
	display: block;
}

.arrows path {
	stroke:  var(--bs-light);
	fill: transparent;
	stroke-width: 1px;
	animation: arrow 2s infinite;
	-webkit-animation: arrow 2s infinite;
}

@keyframes arrow
{
0% {opacity:0}
40% {opacity:1}
80% {opacity:0}
100% {opacity:0}
}

@-webkit-keyframes arrow /*Safari and Chrome*/
{
0% {opacity:0}
40% {opacity:1}
80% {opacity:0}
100% {opacity:0}
}

.arrows path.a1 {
	animation-delay:-1s;
	-webkit-animation-delay:-1s; /* Safari 和 Chrome */
}

.arrows path.a2 {
	animation-delay:-0.5s;
	-webkit-animation-delay:-0.5s; /* Safari 和 Chrome */
}

.arrows path.a3 {
	animation-delay:0s;
	-webkit-animation-delay:0s; /* Safari 和 Chrome */
}

.hero_title .excerpt {
	max-width: 500px;
}


/* Инстайты на главной */

.resize_trigger p {
	line-height: 1.81;
}

.resize_attempt p {
	line-height: 1.5;
}

/* Портфолио на главной */

.portfolio_temporary {
	transition: 0.5s;
	z-index: 1;
}

.portfolio_temporary_back {
	transition: 0.5s;
	opacity: 0.25;
}

/* Тени сняты у hero: заголовок лежит на сплошной плашке (см. .hero_title ниже) */
.portfolio_temporary h3 {
	text-shadow: 0px 2px 15px #000000b5;
}

.portfolio_main .portfolio_overlay, .portfolio_main:hover .portfolio_temporary, .portfolio_main:hover .portfolio_temporary_back {
	opacity: 0;
}

.portfolio_main:hover .portfolio_overlay {
	opacity: 1;
}

.portfolio_overlay {
	position: absolute;
    padding: 1rem;
    opacity: 0;
    transition: opacity 500ms;
}

.overlay_background {
	content: '';
	z-index: 1;
	position: absolute;
	top:0;
	left:0;
	width: 100%;
	height: 100%;
	opacity: 0.7;
    backdrop-filter: grayscale(100%) blur(5px);
    -webkit-backdrop-filter: grayscale(100%) blur(5px);
}

.overlay-content {
	z-index: 2;
}



/* Портфолио сайтов */

.showcase_bp_image {
	transition: background-position 15s linear;
	margin: 0 auto;
}

.showcase_bp_image:hover {
  background-position: 0% 100%;
}

.showcase_bp_image_iphone {
	background-position: 0% 0%;
	background-size: cover;
	height: 346px;
    width: 195px;
    padding: 40px;
    position: absolute;
    top: 53px;
    left: 13px;
}

.iphone_bg {
	/* Картинка лежит в теме: раньше грузилась абсолютным URL с внешнего домена
	   и отвалилась бы вместе с ним. Внешних адресов в CSS не держим. */
	background: url('img/bg/iphone_bg.png') 0% 0% / cover;
	width: 221px;
	height: 450px;
	position: relative;
	margin: 0 auto;
}

.iphone_bg .fa-long-arrow-alt-up {
    position: absolute;
    top: 46%;
    left: -22px;
}

.iphone_bg .fa-long-arrow-alt-down {
    position: absolute;
    top: 46%;
    right: -22px;
}


.imac_bg {
	margin: 0 auto;
	position: relative;
}

.showcase_bp_image_imac {
	transition: background-position 20s linear;
	background-position: 0% 0%;
	background-size: cover;
	position: absolute;
    top: 4.4%;
    width: 74.5%;
    height: 74.5%;
    left: 12.7%;
}

.fake_showcase .fa-long-arrow-alt-up {
    position: absolute;
    top: 40%;
    left: 6.5%;
}

.fake_showcase .fa-long-arrow-alt-down {
    position: absolute;
    top: 40%;
    right: 6.5%;
}

.fake_showcase {
	position: relative;
}

@media (max-width: 425px) {
	.fake_showcase {
    transform: scale(1.45);
    margin: 50px 0;
}

.fake_showcase .fa-long-arrow-alt-down {
    right: 15.5%;
    color: #fff;
    text-shadow: 0px 0px 2px #747474;
    z-index: 2;
}


.fake_showcase .fa-long-arrow-alt-up {
    left: 15.5%;
    color: #fff;
    text-shadow: 0px 0px 2px #747474;
    z-index: 2;
}

}

.page-link, .page-link:hover {
	background-color: transparent;
	border: 0;
	font-weight: 600;
}

.dark-theme .page-link, .dark-theme .page-link:hover  {
	background-color: transparent;
}

.bottom_nav {
	max-width: 350px;
	position: relative;
}

.bottom_nav::before {
	content: '';
	position: absolute;
	width: 100%;
	height: 100%;
	border-left: 2px dashed var(--bs-primary);
	border-right: 2px dashed var(--bs-primary);
	opacity: 0.5;
}

/* Параллакс */

/*
 * Бокс обложки кейса всегда ~16:9: пара «width:177.77vh + height:100%» и пара
 * «min-width:100% + min-height:56.25vw» дают больший из двух 16:9-прямоугольников,
 * накрывающих вьюпорт.
 *
 * Раньше здесь стоял background-size: 110% — это ШИРИНА, высота считалась авто.
 * Картинка накрывала бокс только если её пропорция была не площе 16:9/1.1 (0.511).
 * Обложки площе (gk-praktika 1600x755 = 0.472, touchlink 1280x576 = 0.450) до низа
 * бокса не доставали, и background-position: 50% 40% клал 40% недостачи сверху —
 * та самая пустая полоса под цвет фона кейса (25 px на 1440x677). Вертикальный
 * mouse-параллакс при этом не двигал картинку, а возил эту полосу.
 *
 * cover гарантирует перекрытие при ЛЮБОЙ пропорции обложки, scale(1.1) возвращает
 * прежний 10% зум (кадрирование высоких обложек сохраняется 1-в-1) и даёт запас
 * по 5% бокса с каждой стороны — с ним полоса не вылезет и при сдвиге
 * background-position из js/parallax.js.
 */
/*
 * Бокс шире вьюпорта (на 375x667 это 1185 px против 375), и в разметке он
 * абсолютный (`.parallax.position-absolute` внутри флекс-обёртки #hero).
 * Без left/top его положение = «статическая позиция» абсолютного потомка
 * флекс-контейнера, а её движки трактуют по-разному: Chromium/Firefox
 * применяют justify-content родителя (получается центр), другие могут
 * поставить бокс в начало контент-бокса — тогда на узком экране видна левая
 * треть обложки вместо центра. Поэтому центруем явно: left:50% +
 * translateX(-50%) — это ровно та посадка, что Chromium даёт сейчас
 * (кадр на десктопе не меняется), но уже независимо от движка.
 * top:0 фиксирует вертикаль по той же причине (на низких широких вьюпортах
 * бокс выше обёртки: 56.25vw > высоты, и «стартовое» выравнивание сверху —
 * то самое, что видно сейчас).
 * translateX(-50%) считается от НЕмасштабированной ширины бокса, а scale(1.1)
 * идёт от центра (transform-origin 50% 50%), так что зум кадрирования
 * остаётся симметричным и запас в 5% бокса с каждой стороны сохраняется.
 */
.parallax {
  position: relative;
  width: 177.77777778vh;
  height: 100%;
  min-width: 100%;
  min-height: 56.25vw;
  left: 50%;
  top: 0;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: 50% 40%;
  transform: translateX(-50%) scale(1.1);
  transform-origin: 50% 50%;
}

/* FUCK YOU */

.accordion-item a {
	font-weight: 600;
}

.accordion-item a[class*="collapsed"] {
	font-weight: 400;
}



/* Контакты */

.choice_line {
    position: relative;
    display: flex;
    justify-content: center;
}

.choice_line span {
    padding: 3px;
    align-self: center;
    background: var(--bs-primary);
	color: #fff;
    position: relative;
}

.choice_line::before {
    content: '';
    position: absolute;
    height: 55%;
    border-top: 2px dashed var(--bs-primary);
    width: 100%;
    bottom: 0;
	opacity: 0.5;
}




@media (min-width: 992px) {

.choice_line {
    height: 230px;
}

.choice_line::before {
    height: 100%;
	border-top: none;
    border-left: 2px dashed var(--bs-primary);
    right: 50%;
	width: 0;
}
}



/* OWL SLIDER */

.owl-carousel {
    z-index: 0 !important;
}

.zaebatie_owl_slider_dots .owl-dots .owl-dot span {
    width: 10px;
    height: 10px;
    margin: 5px 7px;
		background: var(--bs-dark);
    opacity: 0.5;
    display: block;
    -webkit-backface-visibility: visible;
    transition: opacity .2s ease;
    border-radius: 30px;
		transition: 0.2s;
}

.dark-theme .zaebatie_owl_slider_dots .owl-dots .owl-dot span {
		background: var(--bs-light);
}

.zaebatie_owl_slider_dots .owl-dots .active span, .zaebatie_owl_slider_dots .owl-dots .owl-dot span:hover {
	opacity: 1;
}

.zaebatie_owl_slider_dots .owl-dots {
    text-align: center;
    -webkit-tap-highlight-color: transparent;
}

.zaebatie_owl_slider_dots .owl-dots .owl-dot {
    display: inline-block;
    zoom: 1;
}

.zaebataya_owl_slider_nav {
	position: relative;
}

.zaebataya_owl_slider_nav button.disabled, .zaebataya_owl_slider_nav button.disabled:hover {
	opacity: 0.4;
}

.zaebatie_owl_slider_nav_inside .owl-nav {
	width: 100% !important;
	z-index: 1;
	left: 0;
}

.zaebatie_owl_slider_nav_inside .owl-nav .arrow-left-3 path, .zaebatie_owl_slider_nav_inside .arrow-right-3 path, .zaebatie_owl_slider_nav_inside .owl-nav .arrow-top-3 path, .zaebatie_owl_slider_nav_inside .arrow-bottom-3 path {
	fill: var(--bs-dark) !important;
}

.dark-theme .zaebatie_owl_slider_nav_inside .owl-nav .arrow-left-3 path, .dark-theme .zaebatie_owl_slider_nav_inside .arrow-right-3 path, .dark-theme .zaebatie_owl_slider_nav_inside .owl-nav .arrow-top-3 path, .dark-theme .zaebatie_owl_slider_nav_inside .arrow-bottom-3 path {
	fill: var(--bs-white) !important;
}

.owl-carousel {
	overflow-x: hidden;
	padding-left: 2rem;
	padding-right: 2rem;
}

.owl-stage {
	width: max-content !important;
}

.owl-carousel .owl-stage-outer {
    z-index: 1;
}

.owl-nav {
	position: absolute;
	width: 100%;
	display: flex;
	justify-content: space-between;
    top: calc(50% - 1.5rem);
	height: 3rem;
	left: 0;
    font-size: 2rem;
	z-index: 0;
}

.arrow-left-3,
.arrow-right-3,
.arrow-top-3,
.arrow-bottom-3 {
    width: 2rem;
    height: 2rem;
    cursor: pointer;
}
.arrow-left-3 path,
.arrow-right-3 path,
.arrow-top-3 path,
.arrow-bottom-3 path {
  fill: var(--bs-dark);
	opacity: 0.65;
  transition: 0.2s;
}

.arrow-left-3 {
  transform: rotate(180deg);
}
.arrow-top-3 {
  transform: rotate(270deg);
}
.arrow-bottom-3 {
  transform: rotate(90deg);
}

.slick-disabled .arrow-left-3 path,
.slick-disabled .arrow-right-3 path,
.slick-disabled .arrow-top-3 path,
.slick-disabled .arrow-bottom-3 path {
	opacity: 0.25 !important;
	cursor: not-allowed;
}

.owl-nav .disabled, .owl-nav .disabled .arrow-left-3,
.owl-nav .disabled .arrow-right-3,
.owl-nav .disabled .arrow-top-3,
.owl-nav .disabled .arrow-bottom-3 .slick-disabled, .slick-disabled .arrow-left-3, .slick-disabled .arrow-right-3,
.slick-disabled .arrow-top-3,
.slick-disabled .arrow-bottom-3 {
	cursor: not-allowed;
}

.arrow-left-3:hover path,
.arrow-right-3:hover path,
.arrow-top-3:hover path,
.arrow-bottom-3:hover path {
   opacity: 1;
}

.dark-theme .arrow-left-3 path,
.dark-theme .arrow-right-3 path,
.dark-theme .arrow-top-3 path,
.dark-theme .arrow-bottom-3 path {
  fill: var(--bs-white);
}

/* Страница архивов */

.archive_link {
	position: absolute;
	top:0;
	left: 0;
	display: block;
	width: 100%;
	height: 100%;
	z-index: 2;
}

.archive_post {
	position: relative;
	z-index: 1;
}

.archive_post img {
	border-bottom-left-radius: 2.25rem !important;
	border-top-left-radius: 2.25rem !important;
}

/* ============================================================
   ПОЛОСЫ ПРОКРУТКИ — единый вид по всему сайту

   Установка владельца 02.09.2026: «прокрутку везде сделай rounded pill,
   а то она одна теперь с острыми углами». Радиус — не число в двух местах,
   а токен: бегунок и трек обязаны быть одной формы, иначе таблетка
   внутри прямоугольника читается хуже, чем два прямоугольника.

   ЦВЕТ БЕГУНКА — --macro-accent-text, А НЕ --ctx-accent, и это замер, а не вкус:
   бегунок — ГРАФИКА (WCAG 1.4.11, порог 3.0 к соседнему цвету). В тёмной
   теме заливочный --ctx-accent (#d33154) на треке (10 % ink поверх фона,
   фактически rgb(58,38,44)) даёт всего 2.90 — провал. Текстовая светлота
   акцента (#e78da1) даёт 5.84 к треку и 7.49 к фону страницы; в светлой теме
   это тот же #8b1d35, что и заливка (7.49 / 9.03) — то есть в светлой ничего
   не меняется, а тёмная перестаёт терять полосу на фоне.
   ⚠️ Числа перемерены 07.09.2026 на бордовой схеме; на изумруде тут стояло
   2.89 / 6.54 / 8.51 и 7.01 / 8.45. Вывод не изменился — заливочный акцент
   на треке проваливает 1.4.11 в тёмной теме ОБОИХ схем.
   На странице КЕЙСА бегунок уходит на --ctx-accent (= --case-rain): там он по
   построению противоположен фону записи по светлоте — канон контекстной
   палитры важнее фирменного акцента.

   ⚠️ FIREFOX РАДИУС НЕ ПОДДЕРЖИВАЕТ ВОВСЕ. У него есть ровно два свойства —
   scrollbar-width и scrollbar-color, форма бегунка там системная. Поэтому
   в Firefox полоса останется с его собственными углами; добираем тем, что
   доступно — thin + те же два цвета. Эмулировать скроллбар скриптом НЕЛЬЗЯ:
   это хуже прямых углов (решение владельца).

   ⚠️ Лента вкладок кейсов (.cases-tabs) ПРЯЧЕТ свою полосу намеренно и под
   эти правила НЕ попадает (свой scrollbar-width: none, специфичность выше):
   там вместо полосы работает затухание края, см. cases-grid.css.
   ============================================================ */

body {
	/* Толщина и радиус — одной парой токенов. Радиус 999px = гарантированно
	   половина толщины при любом --scroll-size, тот же приём, что у кнопок. */
	--scroll-size: 8px;
	--scroll-radius: 999px;
	--scroll-thumb: var(--macro-accent-text);
	--scroll-track: color-mix(in srgb, var(--ctx-ink) 10%, transparent);
}

/* На кейсе — палитра записи, как у всего остального интерфейса.
   Оба токена, а не один: --scroll-thumb-hover ниже по файлу выводится из
   --macro-accent-hover, то есть из ФИРМЕННОГО акцента проекта. Не переопределить
   его здесь — и на кейсе полоса под курсором прыгала бы из цвета записи в
   бордовый (замер 02.09.2026 на /cases/aukids/: покой #fdf0ff, hover был
   #004a46 изумрудный, теперь на его месте #76192d).
   Второй ступени у цвета записи нет и быть не может: --case-rain вычислен как
   противоположный фону по светлоте, любое смещение ломает этот расчёт. */
body.single-isotope {
	--scroll-thumb: var(--ctx-accent);
	--scroll-thumb-hover: var(--ctx-accent);
}

@supports not (color: color-mix(in srgb, red, blue)) {
	body {
		--scroll-track: var(--macro-border);
	}
}

/* ⚠️⚠️ ПОЧЕМУ FIREFOX-СВОЙСТВА ЗАПЕРТЫ В @supports, А НЕ ОБЪЯВЛЕНЫ ПРОСТО ТАК.
   Замер 02.09.2026, Chromium 151, два одинаковых бокса рядом:
     • только ::-webkit-scrollbar*            → жёлоб 8px, бегунок — наша
                                                изумрудная ТАБЛЕТКА;
     • те же правила + scrollbar-width: thin  → жёлоб 10px, бегунок — СЕРЫЙ
                                                СИСТЕМНЫЙ ПРЯМОУГОЛЬНИК.
   С Chrome 121 действует правило: как только у элемента задано scrollbar-width
   или scrollbar-color, движок рисует СТАНДАРТНЫЙ скроллбар и ПОЛНОСТЬЮ
   игнорирует ::-webkit-scrollbar-*. То есть «на всякий случай написать оба
   набора» — это не запас прочности, а ровно тот способ выключить себе
   скругление во всех Chromium-браузерах, ради которого всё и делалось.

   Поэтому Firefox-ветка включается только там, где webkit-псевдоэлементов
   НЕТ вовсе. Проверка честная: CSS.supports('selector(::-webkit-scrollbar)')
   в Chromium возвращает true (замерено), в Firefox — false.

   ⚠️ В ЭТОЙ ВЕТКЕ РАДИУСА НЕТ И НЕ БУДЕТ. У Firefox из всего оформления полосы
   есть ровно два свойства — толщина и цвет; форму бегунка он не отдаёт вообще.
   Скруглить её там нечем, и эмулировать скроллбар скриптом запрещено
   (решение владельца 02.09.2026): накладной «скроллбар» ломает клавиатуру,
   тач-инерцию и системные настройки, а прямые углы — не ломают.

   scrollbar-color НАСЛЕДУЕТСЯ: одного объявления на body хватает и внутренним
   прокруткам, и вьюпорту (у html значение auto, и браузер поднимает его с
   body). scrollbar-width НЕ наследуется — его приходится раздавать всем.
   Специфичность `body *` = (0,0,1), любое правило блока её перебивает. */
@supports not selector(::-webkit-scrollbar) {
	body {
		scrollbar-color: var(--scroll-thumb) var(--scroll-track);
	}

	html,
	body,
	body * {
		scrollbar-width: thin;
	}
}

/* WebKit/Blink. Селекторы без субъекта — значит правила действуют на ВСЕ
   прокручиваемые элементы сразу, отдельных правил по блокам не нужно. */
::-webkit-scrollbar {
	width: var(--scroll-size);
	height: var(--scroll-size);
}

::-webkit-scrollbar-track {
	/* Было rgba(39, 40, 41, .1) — хардкод светлого --macro-ink, в тёмной теме
	   трек оставался «светло-серым по-тёмному». Теперь доля контекстного текста:
	   на кейсе поедет за палитрой записи вместе со всем остальным. */
	background: var(--scroll-track);
	border-radius: var(--scroll-radius);
}

::-webkit-scrollbar-thumb {
	background: var(--scroll-thumb);
	border-radius: var(--scroll-radius);
}

/* opacity у бегунка снята: она была 0.8 в покое и 1 на hover, то есть замеры
   контраста шли по неточному цвету. Отклик на hover теперь цветом — но ТОЛЬКО
   в светлой теме и только на мыши.
   ⚠️ В тёмной теме второй ступени у акцента НЕТ и завести её неоткуда: выше
   #e78da1 в семье акцента ничего не осталось, а уводить бегунок из семьи ради
   hover — менять смысл цвета. Ровно та же оговорка, что у заливки кнопок
   (см. блок «ТЁМНАЯ ТЕМА»). Поэтому --scroll-thumb-hover в тёмной равен
   самому бегунку, и правило просто ничего не делает. */
body {
	--scroll-thumb-hover: var(--macro-accent-hover, var(--scroll-thumb));
}

body.dark-theme {
	--scroll-thumb-hover: var(--scroll-thumb);
}

@media (hover: hover) and (pointer: fine) {
	::-webkit-scrollbar-thumb:hover {
		background: var(--scroll-thumb-hover);
	}
}

::-webkit-scrollbar-corner {
	background: transparent;
}

/* Выделение текста. Правила не было вовсе, и браузер рисовал СВОЙ синий —
   единственное синее пятно, которое переживало смену акцента. Через --ctx-*,
   значит на странице кейса выделение идёт цветом записи, а не проекта. */
::selection {
	background-color: var(--ctx-accent);
	color: var(--ctx-on-accent);
}


/* ============================================================
   MACRO — брендинг (лого, сетка кейсов)
   Цвета берём только из токенов Bootstrap (--bs-*).
   ============================================================ */

/* Логотип в шапке */

.navbar-brand.site-logo {
	line-height: 0;
}

.site-logo-img {
	display: block;
	height: 30px;
	width: auto;
	max-width: 100%;
	transition: opacity 0.3s;
}

@media (min-width: 576px) {
	.site-logo-img {
		height: 34px;
	}
}

@media (min-width: 768px) {
	.site-logo-img {
		height: 40px;
	}
}

@media (hover: hover) and (pointer: fine) {
	.navbar-brand.site-logo:hover .site-logo-img {
		opacity: 0.75;
	}
}

.navbar-brand.site-logo {
	touch-action: manipulation;
}


/* Сетка кейсов (bs-isotope masonry overlay) */

/* Панель фильтров скрывается шаблоном, если терминов нет.
   Дополнительно страхуемся: пустой контейнер не должен занимать место. */
#filters-masonry-overlay:empty,
#filters-product:empty {
	display: none;
}

/* Подложки. Если ACF-поля цвета пустые — работают эти фолбэки. */
.portfolio_temporary_back {
	background-color: var(--bs-primary);
}

.overlay_background {
	background-color: var(--bs-primary);
}

.portfolio_overlay .overlay-content {
	color: var(--bs-white);
}

.portfolio_overlay .blog-post-title {
	text-shadow: 0 2px 12px rgba(var(--bs-dark-rgb), 0.65);
}

.portfolio_overlay .readmore .btn {
	border-width: 2px;
}


/* ============================================================
   SVG из медиатеки
   У SVG нет метаданных ширины/высоты, поэтому WP отдаёт width="1" height="1"
   (или 0×0), и в гриде такие лого схлопываются. Задаём авто-размер.
   ============================================================ */

img[src$=".svg"],
img[src*=".svg?"],
.wp-block-image img[src$=".svg"],
.attachment-full[src$=".svg"],
figure img[src$=".svg"] {
	width: 100%;
	height: auto;
	max-width: 100%;
}

/* Лого в шапке — исключение: у него своя фиксированная высота. */
.site-logo-img[src$=".svg"] {
	width: auto;
	height: 30px;
}

@media (min-width: 576px) {
	.site-logo-img[src$=".svg"] {
		height: 34px;
	}
}

@media (min-width: 768px) {
	.site-logo-img[src$=".svg"] {
		height: 40px;
	}
}

/* Иконки/лого внутри карточек и слайдеров не должны растягиваться
   на всю ширину контейнера — им хватает ограничения по высоте.
   ВНИМАНИЕ: обложки кейсов (.case-card__img) сюда попасть не должны —
   это правило убивает object-fit: cover. Их перебивающий блок — ниже,
   в секции «Сетка кейсов». */
.card img[src$=".svg"],
.owl-carousel img[src$=".svg"] {
	width: auto;
	max-width: 100%;
	max-height: 100%;
	height: auto;
}


/* ============================================================
   Дизайн-токены (общие для обеих тем)
   Цвет заводим ОДИН раз токеном, в правилах ниже — только var(), без россыпи
   хардкод-hex. Полный разбор и все замеры — site/docs/macro-brand.md.

   ⚠️ Схема пересобрана 07.09.2026 вокруг БОГАТОГО БОРДОВОГО акцента #8b1d35
   (решение владельца). Предыдущая изумрудно-бирюзовая схема (#005752,
   01.09.2026) отменена целиком — тёмная тема тоже бордовая, см. блок
   «ТЁМНАЯ ТЕМА». ТЗ — site/docs/tz/tz-color-scheme-burgundy.md.

   Принцип схемы, из которого выведены ВСЕ значения ниже:
   1) подтон уходит в ПОВЕРХНОСТИ, нейтральность остаётся у ТЕКСТА.
      --macro-ink светлой темы остаётся нейтральным #272829 намеренно:
      двухцветность знака в шапке держится не светлотой (там 1.64), а
      ЦВЕТНОСТЬЮ — насыщенный акцент против нейтрального ink C* 0.8,
      ΔE2000 27.3 (замер 07.09.2026; у изумруда было 22.8). Затонируешь ink
      в бордо — ΔE упадёт, и вернёмся в яму прежней пары #172747/#272829
      с контрастом ровно 1.00;
   2) земля глубже и ГЛУШЕ акцента: рампа обеих тем — hue 339–348° при
      насыщенности ~40 % (тёмная) и 7–20 % (светлая), акцент — 347° при 65 %.
      Разводит их не тон (Δh ≈ 7°), а насыщенность и светлота.
      ⚠️ У бордового разрыв по насыщенности УЖЕ, чем был у изумруда
      (65 против 40 = 25 пунктов; было 100 против 41 = 59). На околочёрных
      ступенях это почти не читается, но именно это место схемы проверяется
      глазами на 375 в тёмной теме;
   3) фон СВЕТЛОЙ страницы остаётся белым. Под белым обложки кейсов не
      получают чужого подтона; цена тонирования замерена — контраст #FFFFFF
      к #F5F0F1 равен 1.128, то есть 12.8 % контраста у всего текста ради
      оттенка, который на листе почти не читается. Подтон отдан плите
      подвала и всей тёмной теме;
   4) ⚠️ красный тон НЕ НЕСЁТ СВЕТЛОТУ так, как бирюза (коэффициенты яркости
      R 0.2126 против G 0.7152). Изумруд набирал Y зелёным каналом почти
      даром, бордовый набирает его красным — вчетверо «дороже». Поэтому
      тёмная рампа ОПУЩЕНА на ступень относительно изумрудной (фон Y 0.0083
      против 0.0111, поверхность 0.0195 против 0.0240). Это сознательный
      отказ от прежнего правила «сохранить светлотную лестницу»: на прежней
      рампе бордовая заливка не проходила 3:1 к поверхности. Разбор — ТЗ §2.4.
   ============================================================ */

:root {
	/* Плита подвала (--ctx-plate). ⚠️ НЕ фон страницы: в светлой теме фон
	   страницы белый (--bs-body-bg), а --macro-soft лежит только под подвалом.
	   Фоном страницы этот токен работает лишь в ТЁМНОЙ теме. */
	--macro-soft: #f5f0f1;
	--macro-soft2: #fbf7f8;
	--macro-surface: #ffffff;
	/* Волосяные линейки и декоративные разделители. 1.29 к белому — сознательно
	   ниже 3:1: это декор, WCAG 1.4.11 к нему не применяется. Границы КОНТРОЛОВ
	   берут --macro-line-strong ниже, их путать нельзя. */
	--macro-border: #e9e0e3;
	/* Границы контролов: поля ввода, чекбоксы, пилюли табов, hover-рамка
	   тумблера. 3.90 к белому и 3.45 к плите — 1.4.11 проходит.
	   Потолок светлоты тут жёсткий: 3:1 к белому требует Y ≤ 0.2833,
	   у #937b81 Y = 0.2195. */
	--macro-line-strong: #937b81;
	/* Основной текст. НЕЙТРАЛЕН намеренно — см. п.1 в шапке блока. */
	--macro-ink: #272829;
	--macro-ink2: #605256;
	/* ⚠️ Было #7e7f82 = 4.00 к белому и 3.57 к плите подвала (замер на живой
	   странице 01.09.2026) — провал AA в обоих случаях. Нынешнее значение даёт
	   5.26 / 4.66, провал закрыт в самом токене, а не обходами в блоках.
	   (Паритет с изумрудным #676e6d держится намеренно: 5.21 / 4.69.) */
	--macro-muted: #78686c;
	/* ⚠️ Акцент проекта — БОГАТЫЙ БОРДОВЫЙ, решение владельца 07.09.2026
	   (до него изумрудно-бирюзовый #005752, до того тёмно-синий #172747).
	   Синий не исчез: он остался как --macro-brand-navy ниже, там он работает
	   затемнением под текстом на фото (scrim), и перекрашивать его нельзя —
	   он тонирует сами фотографии.
	   Три ступени одного цвета: hue 347°, saturation 65 %, меняется только
	   светлота (L 33 % → 51 % → 73 %). Светлая тема берёт нижнюю, тёмная —
	   среднюю и верхнюю (см. блок «ТЁМНАЯ ТЕМА»).
	   ⚠️ Акцент светлой темы лежит ВНУТРИ текстовой лестницы: Y = 0.0662,
	   между ink (0.0211) и ink2 (0.0919). Развести нельзя — свободного места
	   нет, отсюда требование подчёркивать ссылки (см. запрещённые пары в
	   site/docs/macro-brand.md). Замеры — там же. */
	--macro-accent: #8b1d35;
	--macro-accent-ink: #ffffff;
	/* В светлой теме заливочный и текстовый акцент совпадают: #8b1d35 даёт
	   9.03 к белой поверхности и 8.01 к плите подвала — читается как текст
	   без осветления (у изумруда было 8.45 / 7.61, стало лучше). */
	--macro-accent-text: #8b1d35;
	/* Состояния заливки и ссылки. Значения = shade 15 % и 20 % от акцента, те
	   же, что уже лежат в собранном bootstrap.min.css у .btn-primary:hover /
	   :active — заводим токеном, чтобы второй раз их никто не считал.
	   Hover ТЕМНЕЕ базы, поэтому контраст только растёт: 10.78 и 11.46.
	   ⚠️ Пары в ТЁМНОЙ теме нет и быть не может — см. блок «ТЁМНАЯ ТЕМА». */
	--macro-accent-hover: #76192d;
	--macro-accent-active: #6f172a;
	/* Акцент, который обязан читаться как ЦВЕТ, а не как тёмное пятно: мелкие
	   иконки, линейки 2–3 px. Одинаков в обеих темах намеренно.
	   4.84 к белому — AA берётся с запасом 7.6 %, поэтому текстом разрешён
	   только от 16 px и как графика; на плите подвала (4.29) текстом нельзя. */
	--macro-accent-bright: #d33154;
	/* Акцент ПОВЕРХ произвольного медиа (кольцо фокуса на обложке кейса).
	   Одинаков в обеих темах: он лежит на фотографии, а не на нашей рампе,
	   и от темы зависеть не должен. 7.42 к скриму обложки #0e172b и 7.88
	   к скриму тёмной темы #091020.
	   ⚠️ В светлой теме на нашей поверхности ЗАПРЕЩЁН: 2.41 к белому,
	   2.13 к плите подвала. */
	--macro-accent-onmedia: #e78da1;
	/* СТАТУСЫ. Выведены из семьи акцента НАМЕРЕННО: статус обязан отличаться
	   от акцента тоном, иначе «ошибка» и «активно» сливаются.

	   🔴 --macro-danger-text СИНИЙ, а не красный — решение владельца
	   07.09.2026. Бренд забрал красный: прежний #9b1917 отличался от бордового
	   акцента #8b1d35 на 14° по тону и в 1.09 раза по светлоте, то есть не
	   отличался вовсе. Сектор между бордовым (347°) и янтарным warning (36°)
	   слишком узок, чтобы вместить туда красную «ошибку» с зазором ≥30°
	   с обеих сторон — это геометрия, а не подбор. Красный у статуса забран.
	   #2154a1 (hue 216°, S 66 %, L 38 %) — замеры 07.09.2026:
	     • 7.38 к белому, 6.54 к плите подвала — AA/AAA;
	     • к акценту #8b1d35: Δh 131°, ΔE2000 36.6 — конфликт снят;
	     • к --bs-info #0dcaf0: контраст 3.77, ΔE2000 42.7 — не слипается;
	     • к --macro-brand-navy #172747: контраст 2.01, ΔE2000 17.8. Самая
	       узкая пара danger'а, но встретиться они не могут — navy это скрим
	       ПОД текстом на фото, а не смысловой цвет;
	     • ⚠️ к --macro-ink2 #605256 контраст 1.00 (ΔE2000 24.2): различает их
	       только цветность. Ровно как у акцента (1.22) — то есть статус,
	       как и ссылка, обязан нести ВТОРОЙ признак: иконку и слово.
	   ⚠️ Значение задано и в SCSS ($danger в _bscore_variables.scss), поэтому
	   вся семья Bootstrap (.btn-danger / .alert-danger / .table-danger /
	   иконки валидации форм в data-URI) уехала в синий пересборкой. Меняешь
	   здесь — меняй и там, иначе файлы разъедутся.

	   ⚠️ Зелёный «успех» на БОРДОВОМ сайте снова законен (Δh к акценту ≈ 130°),
	   прежний запрет был свойством изумруда. Но заводить $success — отдельная
	   задача, и всё равно вместе с иконкой (WCAG 1.4.1). */
	--macro-danger-text: #2154a1;
	--macro-warn-text: #8a5a12;

	/* Не меняется между темами. Скрим под текстом на фотографиях — перекрашивать
	   в изумруд нельзя, он тонирует сами кадры. Легальный «синий» №1 в проекте
	   (№2 — --case-scrim в cases-grid.css). */
	--macro-brand-navy: #172747;

	/* Вторая половина той же пары — «бумага», на которой брендовые знаки
	   НАРИСОВАНЫ. Тоже не меняется между темами, и по той же причине: это
	   свойство самих файлов, а не страницы. Продуктовые монограммы
	   (mg-mark-*.svg) залиты #172747 / #2B4987 намертво, светлого варианта
	   знака не существует и заказать его неоткуда. Значит подложка под таким
	   знаком обязана остаться СВЕТЛОЙ в обеих темах — иначе знак исчезает
	   (замер 01.09.2026: #172747 на тёмной поверхности #142F30 = 1.05, при
	   пороге 3.0 для графики; перемер 07.09.2026 на бордовой #3e1b27 — 1.02,
	   то есть стало ещё безнадёжнее, вывод тот же).
	   ⚠️ Литерал белого живёт здесь и только здесь. Компоненты берут не его,
	   а производный --brandmark-plate, который подмешивает в бумагу цвет
	   страницы кейса, — см. «ПЛАШКА ПОД ЗНАК» в разделе страницы кейса.
	   Легальный «белый» №1 в проекте: фоном страницы или поверхностью он НЕ
	   работает, для этого есть --macro-surface, который темой управляется. */
	--macro-brand-paper: #ffffff;

	--macro-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
	--macro-shadow-md: 0 3px 10px rgba(0, 0, 0, 0.12);
	--macro-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.2);

	/* «Вторичный» цвет Bootstrap уводим на нашу вторую ступень текста.
	   Причина — замер: собственный $secondary #6C757D даёт на плите подвала
	   4.22, то есть проваливает AA. В SCSS и в собранном CSS он оставлен
	   НЕЙТРАЛЬНЫМ намеренно (уводить его в семью акцента нельзя: получим два
	   зелёных, где один значит «действие», другой «второстепенно», и различать
	   их будет только светлота — а светлотный коридор тёмной темы уже забит).
	   Здесь мы просто перестаём его ПОКАЗЫВАТЬ: --macro-ink2 даёт 7.35 / 6.62.
	   Тёмная тема делала это с самого начала (см. блок «ТЁМНАЯ ТЕМА»), светлая
	   отставала.
	   ⚠️ В этой сборке .text-secondary и .bg-secondary идут через
	   rgba(var(--bs-secondary-rgb), …), а не литеральным hex, поэтому одной
	   пары переменных достаточно — отдельное правило .text-secondary не нужно.
	   style.css подключается ПОСЛЕ bootstrap.min.css (functions.php:12 и :448),
	   поэтому наш :root перебивает бутстраповский. */
	--bs-secondary: var(--macro-ink2);
	--bs-secondary-rgb: 96, 82, 86;
}


/* ============================================================
   Контролы левого верхнего угла: «Назад на главную» + переключатель темы.
   Шапки на сайте нет, поэтому они фиксированы поверх контента — но это
   деталь интерфейса, а не главный элемент первого экрана: тумблер сделан
   тихим (круг 44×44, прозрачный фон, приглушённая иконка солнце/луна из
   Font Awesome), поверхность и граница проявляются на hover/focus.
   Прошлая версия — трек-пилюля 68×44 с залитым состоянием — перетягивала
   внимание на себя, от неё отказались 2026-08-19.

   Разметка и id (#dark-mode) — от плагина bs-dark-mode-main, менять
   нельзя: на них завязано сохранение выбора темы в cookie. Здесь только
   внешний вид: input у бутстрапа appearance:none, стилизуется целиком.
   ============================================================ */

/* Вертикальная метрика верхней полосы — на :root, потому что ею меряется не
   только сама лента, но и верхний отступ страниц: контент, у которого нет hero
   (главная и любая обычная page), обязан начинаться НИЖЕ полосы.
   Держать эти числа в двух местах нельзя — разъедутся, как только поменяется
   паддинг или высота контролов.

   --top-plate-line  — толщина нижней границы. Отдельной переменной, а не числом
                       в двух местах: граница входит и в отрисовку полосы, и
                       в отступ контента под ней, и за три захода она успела
                       появиться, исчезнуть и вернуться (23.08.2026, владелец).
                       Уберут снова — правится одно место;
   --top-plate-h     — высота полосы БЕЗ границы: 44px тап-таргета контролов +
                       вертикальный паддинг с двух сторон: 52px до 768, 56px от 768;
   --top-plate-space — нижняя кромка полосы в координатах окна: высота + граница.
                       Полоса прижата к верху (top: 0), верхнего зазора у неё нет,
                       поэтому других слагаемых тут нет.
                       ⚠️ В space входит только то, что РЕАЛЬНО занимает место
                       сверху. Ореол контролов (см. ниже) не занимает: он лежит
                       вплотную к глифам внутри самой полосы. */
:root {
	/* ⚠️ 0 — граница полосы СНЯТА 01.09.2026 (владелец, «убрать линии сверху и
	   снизу»). Четвёртый заход по этому ребру: появлялась, исчезала, возвращалась,
	   снова снята. Переменную НЕ удаляю намеренно — она входит и в отрисовку
	   полосы, и в --top-plate-space (отступ контента под лентой); вернуть линию =
	   поставить сюда 1px, и оба места согласуются сами.
	   ⚠️ ФАКТ, важный для следующего захода: линия у полосы была ВСЕГДА ОДНА —
	   нижняя. border-top у .top-controls не было ни в одной ревизии (проверено
	   живьём: computed borderTopWidth = 0px на главной и на кейсе). «Линия
	   сверху», если её опишут снова, — это НЕ бордер, а либо верхняя кромка
	   самой заливки на фоне обложки, либо админ-бар WP. Ищи там. */
	--top-plate-line: 0px;
	--top-plate-pad-y: 0.25rem;
	--top-plate-h: calc(44px + 2 * var(--top-plate-pad-y));
	--top-plate-space: calc(var(--top-plate-h) + var(--top-plate-line));
}

@media (min-width: 768px) {
	:root {
		--top-plate-pad-y: 0.375rem;
	}
}

/* Лента «знак + Назад + распорка + тумблер» — ПОЛОСА во всю ширину окна,
   прижатая к верху, без скруглений.

   ⚠️ Установка владельца 22.08.2026. Она ОТМЕНЯЕТ, а не дополняет, прежнее
   решение того же дня — плавающую пилюлю (зазор --case-pad по краям, радиус
   999px, рамка по контуру, тень). Вместе с пилюлей отменено и её обоснование
   «на колонку контента встаёт левый край подложки, а знак закономерно
   отступает вправо на --top-plate-pad-l»: спор «край плашки против края
   логотипа» исчез сам, потому что у полосы нет собственного видимого левого
   края — она идёт от края до края окна.

   Поэтому по колонке контента снова выравнивается ЛЕВЫЙ КРАЙ ЗНАКА — ровно
   как у заголовка «Кейсы» и первой карточки: 16 / 16.9 / 34.5 / 64.8 px на
   320 / 375 / 768 / 1440. Делает это padding-left самой полосы; отрицательных
   margin, из-за которых пилюля когда-то липла к углу окна, тут нет и не надо.

   Пока ширина контента меньше потолка --case-max, край контента = --case-pad.
   Когда вьюпорт шире (--case-max + 2*pad ≈ 2192px), контент перестаёт расти и
   центрируется — тогда его край = (100% - --case-max) / 2, и знак едет вместе
   с контентом, а не липнет к краю экрана. max() выбирает нужную ветку сам.
   Проценты у fixed-элемента берутся от initial containing block, т.е. от
   вьюпорта без скроллбара — ровно то же, от чего центруется .cases-head.

   Правый паддинг — просто --case-pad, без max(): содержимое ленты прижато
   влево и правого края обычно не достаёт, паддинг тут работает страховкой от
   упирания тумблера в край окна на 320–375 (см. медиазапросы ниже).

   Внешний вид полосы (заливка, граница, ореол контролов) — ниже, в разделе
   «Два состояния ленты»: у неё их два, и геометрия от состояния не зависит. */
.top-controls {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 1030; /* выше контента, ниже cookie-карточки (1050) и modal (1055) */
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: var(--top-plate-pad-y) var(--case-pad);
	padding-left: max(var(--case-pad), calc((100% - var(--case-max)) / 2));
	/* Правый край зеркалит левый — с 23.08.2026, когда тумблер уехал в правый
	   угол. Раньше правым паддингом хватало голого --case-pad: содержимое
	   ленты было прижато влево и правого края не доставало. Теперь достаёт,
	   и на ультраширинах (> --case-max + 2*pad) тумблер обязан вставать по
	   правому краю КОЛОНКИ КОНТЕНТА, а не липнуть к краю экрана — иначе он
	   уезжает от сетки кейсов на сотни пикселей. Формула та же, что слева. */
	padding-right: max(var(--case-pad), calc((100% - var(--case-max)) / 2));
}

@media (min-width: 768px) {
	.top-controls {
		gap: 0.625rem;
	}
}

/* Админ-бар WordPress не должен накрывать контролы: полоса встаёт вплотную
   под него (46px на мобиле, 32px от 783px — величины самого WP). Зазора нет
   намеренно — две полосы подряд читаются как одна панель, а щель между ними
   показывала бы проезжающий контент. */
.admin-bar .top-controls {
	top: 46px;
}

@media (min-width: 783px) {
	.admin-bar .top-controls {
		top: 32px;
	}
}


/* ============================================================
   Два состояния ленты: у верха страницы — прозрачная, в прокрутке — с цветом
   ============================================================

   ⚠️ Установка владельца 23.08.2026, четвёртый заход по этому элементу.
   Она ОТМЕНЯЕТ предыдущее решение целиком, вместе с его доводами:
     • «полоса всегда залита, читаемость держит подложка» — отменено:
       у верха страницы заливки НЕТ вообще, потому что она срезала верх
       обложки кейса, а обложка — это hero, главный кадр страницы;
     • «переход к контенту должен быть незаметным, без кромки» — отменено:
       нужна ЧЁТКАЯ граница внизу;
     • «фон ленты чуть в блюре» (backdrop-filter + маска схода на нет +
       компенсирующий --top-scrim-tone) — отменено: размытия нет, вся эта
       машинерия удалена. Не возвращать её «до кучи» к новому состоянию:
       блюр под чёткой границей — это ровно тот вид, от которого ушли.

   Состояний ровно два, и переключает их ОДИН класс .topbar-at-top на <html>:

   1) У ВЕРХА ДОКУМЕНТА (.topbar-at-top) — background-color: transparent и
      прозрачная граница. Полоса не закрывает собой ничего: на кейсе сквозь
      неё видно обложку целиком, на главной — фон страницы.
   2) ВО ВСЕХ ОСТАЛЬНЫХ ПОЛОЖЕНИЯХ (класса нет) — плотный --ctx-surface плюс
      граница --ctx-border снизу. Плотный, а не полупрозрачный: под лентой
      едет произвольный контент (скриншоты кейсов, карточки), и любая
      прозрачность возвращает старую проблему «контраст считается от палитры,
      а под текстом чужая картинка».

   ⚠️ Направление класса выбрано так, что БЕЗ JS остаётся состояние 2.
   Правило по умолчанию — залитое; прозрачность НАВЕШИВАЕТСЯ классом. Сломался
   скрипт, не поддержан IntersectionObserver, отключён JS — лента просто всегда
   с цветом, то есть всегда читаема. Обратный вариант (по умолчанию прозрачно,
   класс добавляет цвет) при том же коде оставил бы контролы навсегда висеть
   на обложке.

   ⚠️ ПЕРЕСМОТР 01.09.2026 (владелец), и он отменяет ДВА пункта предыдущего
   решения, оставляя остальное:
     • «нужна ЧЁТКАЯ граница внизу» — ОТМЕНЕНО, границы больше нет
       (--top-plate-line: 0, см. :root);
     • «плотный, а не полупрозрачный» — ОТМЕНЕНО: полоса в прокрутке стала
       матовым стеклом, полупрозрачная заливка + backdrop-filter.
   Не отменено и остаётся в силе: два состояния, направление класса
   .topbar-at-top (без JS — залито), прозрачность у верха документа.

   ⚠️ УТОЧНЕНИЕ 07.09.2026 (владелец): «Когда экран находится в самом верху,
   фона у хедера быть не должно, ДАЖЕ ГРАДИЕНТА. При пролистывании вниз он
   появляется». Про сам слой стекла это ничего не меняет — он и так гаснет в
   ноль (.topbar-at-top .top-controls::before, ниже; замер: computed opacity 0
   на всех трёх страницах в обеих темах, снимок верхней полосы главной и
   «Студии» побайтово равен снимку с принудительно выключенным стеклом).
   Правкой это стало для ЕДИНСТВЕННОГО слоя, который в верхней позиции ещё
   что-то рисовал, — подтона обложки .hero-topveil: он отключён, разбор и
   замеры у самого правила. Формулировка требования теперь буквальная: у верха
   документа под лентой не рисует НИЧЕГО — ни заливка, ни блюр, ни градиент,
   ни на ленте, ни на обложке под ней.

   ⚠️ Это фактически ВОЗВРАТ блюра, снятого 23.08.2026. Тогда его убрали не
   потому, что он плох сам по себе, а потому что «блюр под чёткой границей —
   ровно тот вид, от которого ушли». Границы теперь нет, и возражение снято
   вместе с ней. Возвращён именно блюр, БЕЗ прежней машинерии: маски схода
   на нет и компенсирующего --top-scrim-tone нет и заводить не надо.

   ЧИТАЕМОСТЬ. Возражение «под лентой едет произвольный контент, и любая
   прозрачность возвращает проблему “контраст считается от палитры, а под
   текстом чужая картинка”» — верное, и снимается оно не отменой стекла,
   а тремя вещами сразу:
     1) плотность заливки 72 % — под стеклом остаётся 28 % чужого;
     2) blur + saturate размывают чужой контент в РОВНОЕ пятно: локальных
        перепадов под глифом не остаётся, и худший случай считается по
        средней светлоте, а не по краю скриншота;
     3) ореол глифов (--top-halo, см. ниже) — ПЛОТНЫЙ --ctx-surface, он
        сквозь стекло не просвечивает и держит контур каждой буквы.
   Замер худших случаев (белый скриншот под тёмной темой и наоборот) —
   в отчёте frontender 01.09.2026.

   ⚠️ ФОЛБЭК ОБЯЗАТЕЛЕН. Без backdrop-filter полупрозрачная заливка — это
   просто дырка: текст ляжет прямо на контент. @supports ниже поднимает
   плотность до 94 %, то есть без блюра полоса почти плотная. Проверяется
   принудительно, а не «на глаз»: сама подмена --top-glass-alpha.

   ⚠️ Блюр НЕ применяется у верха документа: там полоса обязана быть
   полностью прозрачной, иначе размоет hero-обложку кейса — то, ради чего
   прозрачное состояние и заводили. Гасится явно в .topbar-at-top.

   ⚠️ Радиус блюра держать маленьким. backdrop-filter на фиксированном
   элементе пересчитывается на каждый кадр прокрутки; 14px — компромисс,
   при котором эффект читается, а прокрутка не дёргается. Не наращивать.

   Переход 0.25s только по цвету: геометрия у обоих состояний одна и та же,
   ничего не двигается. При prefers-reduced-motion переход снимается. */
.top-controls {
	/* Плотность стекла. Токеном, а не числом в трёх местах: её меняет фолбэк
	   @supports, и она же — единственная ручка «эффект против читаемости».
	   Поднимать сюда: 72 -> 85 % заметно спокойнее на пёстрых обложках. */
	--top-glass-alpha: 72%;
	--top-glass-blur: 14px;
	/* Высота зоны растворения. Она лежит НИЖЕ полосы, а не внутри неё, — см.
	   разбор у ::before. Меняешь — растворение просто станет длиннее/короче,
	   на читаемость самой полосы это не влияет. */
	--top-glass-fade-h: 26px;

	border-bottom: var(--top-plate-line) solid var(--ctx-border);
	transition: border-bottom-color 0.25s ease;
}

/* --- Слой стекла (::before) ---
   ⚠️ Заливка и блюр живут в ОТДЕЛЬНОМ СЛОЕ, а не на самой .top-controls, и это
   не стилистическая прихоть — иначе не сделать растворяющийся низ.

   ЗАДАЧА (владелец 01.09.2026): низ полосы должен растворяться в контенте,
   а не обрываться кромкой.
   ⚠️ ЛОВУШКА, в которую нельзя падать: повесить mask-image прямо на
   .top-controls. Маска применяется ко ВСЕМУ элементу вместе с содержимым —
   растворяться начнут низ знака, вкладок и кнопок, причём заметнее всего
   у знака (самый крупный кегль в полосе). Поэтому маска — только здесь,
   на слое, а контент полосы остаётся полностью непрозрачным поверх него.

   ГЕОМЕТРИЯ. Слой СВЕШИВАЕТСЯ ниже полосы на --top-glass-fade-h. Так сделано
   специально: если бы растворение шло внутри высоты полосы, оно съедало бы
   фон под нижней третью контролов (44px тап-таргета из 52–56px высоты) —
   то есть ровно под текстом. Свес выносит весь градиент в пустое место
   НИЖЕ полосы: под контролами стекло на полной плотности, растворение
   начинается там, где элементов уже нет.

   БЛЮР ЗАТУХАЕТ ВМЕСТЕ С ФОНОМ, одним слоем. Маска применяется к результату
   отрисовки элемента ЦЕЛИКОМ, включая уже отфильтрованный backdrop, поэтому
   к низу сходят на нет и заливка, и размытие. Отдельных слоёв с разным
   радиусом не нужно — проверено замером (см. отчёт frontender 01.09.2026):
   иначе получилась бы та же чёткая граница, только по краю размытия.

   ГРАДИЕНТ В ВОСЕМЬ СТОПОВ, а не в два. Линейный переход alpha 1 -> 0 даёт
   видимую полосу примерно на середине (полоса Маха): глаз ловит излом
   производной. Стопы ниже приближают плавную кривую с затяжным хвостом.
   Не упрощать до `#000, transparent` — вернётся ступенька.

   z-index: -1 — слой уходит под содержимое полосы, но остаётся внутри её
   стекающего контекста (.top-controls позиционирована и имеет z-index),
   поэтому под страницу он не проваливается.
   ⚠️ position: absolute тут обязателен ещё и потому, что .top-controls —
   флекс-контейнер: у статического псевдоэлемента он бы отнял место как
   у флекс-элемента и раздвинул ленту. */
.top-controls::before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: calc(-1 * var(--top-glass-fade-h));
	z-index: -1;
	pointer-events: none;

	/* Заливка КОНТЕКСТНАЯ: color-mix от --ctx-surface, а не rgba-хардкод.
	   На кейсе surface выводится из палитры записи, поэтому стекло идёт
	   цветом кейса; в тёмной теме — тёмным. Хардкод-hex тут запрещён так же,
	   как везде по проекту. */
	background-color: color-mix(in srgb, var(--ctx-surface) var(--top-glass-alpha), transparent);
	/* saturate вместе с blur — иначе размытый контент под стеклом выцветает
	   в серую кашу и стекло читается грязным, а не матовым. */
	-webkit-backdrop-filter: blur(var(--top-glass-blur)) saturate(1.6);
	backdrop-filter: blur(var(--top-glass-blur)) saturate(1.6);

	-webkit-mask-image: linear-gradient(to bottom,
		rgb(0 0 0 / 1)    calc(100% - var(--top-glass-fade-h)),
		rgb(0 0 0 / 0.95) calc(100% - var(--top-glass-fade-h) * 0.86),
		rgb(0 0 0 / 0.82) calc(100% - var(--top-glass-fade-h) * 0.72),
		rgb(0 0 0 / 0.62) calc(100% - var(--top-glass-fade-h) * 0.56),
		rgb(0 0 0 / 0.40) calc(100% - var(--top-glass-fade-h) * 0.40),
		rgb(0 0 0 / 0.20) calc(100% - var(--top-glass-fade-h) * 0.24),
		rgb(0 0 0 / 0.07) calc(100% - var(--top-glass-fade-h) * 0.12),
		rgb(0 0 0 / 0)    100%);
	mask-image: linear-gradient(to bottom,
		rgb(0 0 0 / 1)    calc(100% - var(--top-glass-fade-h)),
		rgb(0 0 0 / 0.95) calc(100% - var(--top-glass-fade-h) * 0.86),
		rgb(0 0 0 / 0.82) calc(100% - var(--top-glass-fade-h) * 0.72),
		rgb(0 0 0 / 0.62) calc(100% - var(--top-glass-fade-h) * 0.56),
		rgb(0 0 0 / 0.40) calc(100% - var(--top-glass-fade-h) * 0.40),
		rgb(0 0 0 / 0.20) calc(100% - var(--top-glass-fade-h) * 0.24),
		rgb(0 0 0 / 0.07) calc(100% - var(--top-glass-fade-h) * 0.12),
		rgb(0 0 0 / 0)    100%);

	transition: opacity 0.25s ease, background-color 0.25s ease;
}

/* Фолбэк 1: движок без backdrop-filter (или Safari без -webkit-, или блюр
   отключён политикой) получает почти плотную полосу вместо дырки. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
	.top-controls {
		--top-glass-alpha: 94%;
	}
}

/* Фолбэк 2: движок без mask-image. Свес слоя обнуляется, иначе непрозрачный
   хвост в 26px просто опустил бы ту же чёткую кромку на 26px ниже —
   хуже, чем было. Текст при этом остаётся на плотном фоне, читаемость
   не страдает: теряется только эффект растворения. */
@supports not ((mask-image: linear-gradient(#000, transparent)) or (-webkit-mask-image: linear-gradient(#000, transparent))) {
	.top-controls {
		--top-glass-fade-h: 0px;
	}
}

.topbar-at-top .top-controls {
	border-bottom-color: transparent;
	/* Ореол в прозрачном состоянии красится фоном СТРАНИЦЫ, а не поверхностью
	   ленты: он лежит прямо на странице, и совпасть обязан с ней. В светлой
	   теме это один и тот же цвет, а в тёмной странице #251017 против
	   поверхности #3e1b27 — с surface вокруг знака оставалось видимое светлое
	   пятно на главной (мерили: 14.77 -> 12.60 на ровном фоне; после перекраски
	   рампы в бордо 07.09.2026 соотношение ступеней то же, 1.19 против 1.21
	   у изумруда и 1.23 у прежней синей). */
	--top-halo: var(--ctx-page);
}

/* У верха документа стекла НЕТ ВООБЩЕ: слой гасится целиком, иначе блюр
   размывал бы hero-обложку кейса — ровно то, ради чего прозрачное состояние
   и заводили. Гасим opacity, а не background: под opacity уходит и
   backdrop-filter, под background-color — нет. */
.topbar-at-top .top-controls::before {
	opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
	.top-controls,
	.top-controls::before {
		transition: none;
	}
}

/* Сторожевик состояния. Пустой бокс высотой в ленту, приклеенный к самому
   верху документа: пока он в кадре — мы «у верха», ушёл выше — «в прокрутке».
   Смысл именно в элементе: за ним следит IntersectionObserver (header.php),
   и обработчик прокрутки с чтением координат не нужен вовсе — браузер сам
   присылает событие на пересечении и только в момент пересечения.

   position: absolute, а не блок в потоке: в потоке он сдвигал бы первый
   элемент страницы и ломал бы селекторы вида :first-child. Абсолютный бокс
   без позиционированного предка встаёт в initial containing block, то есть
   в координаты документа, и прокручивается вместе с ним — ровно то, что надо.

   Высота = --top-plate-space: цвет набирается ровно тогда, когда под ленту
   уехала первая её высота контента. Меньше (10–20px) — лента моргает от
   любого касания тачпада, больше — на кейсе успевает уехать половина hero,
   а лента всё ещё висит прозрачной поверх мелких деталей обложки.
   ⚠️ Админ-бар WP сдвигает контент вниз на 32/46px, а сторожевик — нет
   (он в координатах документа). Для залогиненного админа порог оказывается
   на эти пиксели раньше. Осознанно не правим: разница незаметна и стоила бы
   дубля метрик админ-бара в третьем месте. */
#topbar-sentinel {
	position: absolute;
	top: 0;
	left: 0;
	width: 1px;
	height: var(--top-plate-space);
	pointer-events: none;
}

/* --- Ореол контролов (--top-halo) ---
   Задача, которую он решает: пока лента прозрачна, знак, «Назад» и тумблер
   лежат ПРЯМО НА ОБЛОЖКЕ КЕЙСА. Их цвет (--ctx-ink) вычислен от палитры
   страницы, а не от того, что оказалось под ними физически, и на обложке
   всегда есть локальные пятна не того тона — блик окна, светлая крыша,
   белая шапка интерфейса. Ореол даёт каждому глифу СВОЮ подложку по контуру:
   стопку теней нулевого смещения цветом фона, на котором глиф лежит.

   ⚠️ ИСПРАВЛЕНО 23.08.2026. Прежнее обоснование этого раздела стояло на
   неверной посылке — будто ореол «САМ СЕБЯ прячет там, где не нужен: цвет
   ореола = цвет фона под ним». Под ним на кейсе НЕ фон страницы, а обложка,
   и вуаль .parallax-hero-bg с её opacity 0.2 светлую обложку почти не гасила.
   Ореол получался цветом страницы поверх чужого тона — то есть отчётливым
   грязным пятном вокруг глифов, ровно той плашкой, которой он не должен был
   становиться. Замер приёмки: фон под знаком 168–177 из 255 в тёмной теме на
   светлых обложках при цвете ореола 25–44. Иначе говоря, ореол тогда работал
   не «контуром на своём фоне», а компенсацией недостающего затемнения, и
   тянул нагрузку, на которую не рассчитан.

   Лечение — не здесь: фон под контролами подтягивается к цвету страницы
   слоем .hero-topveil (см. следующий раздел), и посылка «под ореолом цвет
   страницы» становится верной по факту, а не по допущению. Ореолу осталась
   его настоящая работа — локальные пятна, которые подтон не берёт (у
   promstroy в тёмной теме подтона нет вовсе, а светлые фасады домов под
   знаком дают 154 при медиане 85).

   Почему ореол вообще честная замена подложке под ленту:
     • контраст текста определяется тем, что лежит вплотную к штриху. Ореол
       кроет именно эту зону;
     • обложку он не закрывает: занятая площадь — контур букв плюс 2–3px,
       а не 57px на всю ширину окна.

   ⚠️ Цвет берётся ПО СОСТОЯНИЮ, и это не придирка: у прозрачной ленты под
   глифами фон СТРАНИЦЫ (--ctx-page), у залитой — поверхность ленты
   (--ctx-surface). В светлой теме это один цвет, в тёмной — разные ступени
   рампы (#251017 против #3e1b27), и ошибка видна глазом: с surface у верха
   главной вокруг знака стояло светлое пятно (замер на ровном фоне падал
   с 14.77 до 12.60). Правило для прозрачного состояния — выше, у
   .topbar-at-top. ⚠️ И то же самое --ctx-page берёт .hero-topveil: цвет
   ореола и цвет подтона обязаны совпадать, иначе подтон подгонит фон не под
   тот тон. Одна переменная на оба — не совпадение, а условие.
   ⚠️ 07.09.2026 подтон ОТКЛЮЧЁН (владелец, «даже градиента» — см. правило
   .hero-topveil ниже), так что весь фон под глифами у верха кейса держит
   теперь один ореол. Связку не разрываю: вернут подтон — она снова в игре.

   ПОЧЕМУ ОРЕОЛ НЕ ГАСИТСЯ В ЗАЛИТОМ СОСТОЯНИИ и стоит всегда: гасить нечего,
   в залитом состоянии он совпадает с поверхностью и невидим. Зато включение
   по классу потребовало бы анимировать text-shadow у КАЖДОГО потомка
   (свойство наследуемое, но переход у наследника свой), и на время перехода
   0.25s ореол пропадал бы раньше, чем появляется заливка, — ровно в тот
   момент, когда он ещё нужен.

   РАЗМЕР СТОПКИ ПЕРЕСЧИТАН 23.08.2026 вместе с подтоном. Было семь теней
   с радиусами 1/1/2/2/3/4/6 — набор под фон 197–213, который ореолу
   приходилось перебивать в одиночку. Теперь фон под контролами нигде не
   светлее 154 в худшей ЛОКАЛЬНОЙ точке (promstroy, тёмная тема, подтона нет)
   и 127 в остальных кейсах, поэтому два самых широких радиуса убраны:
   осталось 1/1/2/2/3. Что это даёт и чем подтверждено:
     • ширина видимого фартука упала с ~6px до ~3px — именно внешние 4 и 6px
       и читались плашкой вокруг знака, плотность у самого штриха держат
       мелкие радиусы, а их пять из пяти;
     • снято глазами на четырёх кейсах в обеих темах (~/tmp/veil-fix/shots,
       halo-now / halo-trim / halo-none): с новым фоном вариант halo-none
       читается уже сам по себе, то есть запас у стопки есть и после урезания.
   ⚠️ Дальше не резать без пересчёта: 1/1/2/3 на прежнем фоне давали худшую
   точку 2.50 против 5.76 у семёрки — то есть мелкие радиусы поодиночке до
   зоны, где глаз считает контраст, не достают. Работает связка «подтон фона
   плюс короткий ореол», а не каждый по отдельности.

   text-shadow объявлен ОДИН раз на .top-controls: свойство наследуемое,
   поэтому его получают и подпись «Назад», и иконки Font Awesome, и
   псевдоэлементы тумблера — новый текстовый элемент в ленте получит ореол
   сам, без правки этого файла.

   ⚠️ ОСТАЁТСЯ В СИЛЕ с прошлого захода и подтоном НЕ лечится: самая слабая
   точка ленты — иконки стрелки/домика у «Назад», и виноват не ореол, а сам
   токен --ctx-muted. На СПЛОШНОЙ ленте, где никакой обложки под ним нет, он
   даёт 4.87 — то есть 4.5 не добирает и при полностью непрозрачном фоне.
   Иконки декоративные, рядом с ними та же мысль подписью на --ctx-ink,
   поэтому это принято (для нетекстовых элементов порог 3.0). Хочешь их по
   WCAG — это правка ТОКЕНА, и отдельный разговор.

   Стопка теней, а не одна: альфа складывается, и у самого штриха ореол
   выходит практически непрозрачным, а к 3px сходит на нет. Одна тень такой
   же ширины даёт мутное пятно вместо контура.

   ⚠️ Знак с 01.09.2026 — ТЕКСТ, а не маска, и ореол он получает наследованием
   вместе с «Назад»: отдельного правила ему больше не нужно. Прежний знак был
   маскированным элементом, и ему приходилось задавать filter: drop-shadow
   (маска срезает собственный box-ореол элемента). То правило снято — если
   когда-нибудь в ленту вернётся элемент-КАРТИНКА, ореол ему надо будет
   выдать именно фильтром, а не text-shadow.

   ⚠️ Цвет ореола — только токены (--ctx-page / --ctx-surface). Хардкод тут
   запрещён так же, как везде: на кейсе обе величины выводятся из палитры
   записи, и ореол обязан ехать за ней. */
.top-controls {
	--top-halo: var(--ctx-surface);
	--top-halo-shadow:
		0 0 1px var(--top-halo),
		0 0 1px var(--top-halo),
		0 0 2px var(--top-halo),
		0 0 2px var(--top-halo),
		0 0 3px var(--top-halo);

	text-shadow: var(--top-halo-shadow);
}

/* ⚠️ Тумблер — <input>, а он ОБРЫВАЕТ наследование text-shadow (проверено:
   у .form-check ореол есть, у самого input уже none — так его гасит UA-стиль
   формы). Поэтому иконкам солнца/луны тень задаётся явно. Список теней вынесен
   в --top-halo-shadow, чтобы не разошёлся с лентой: сами переменные через
   input проходят нормально, обрывается только само свойство. */
.theme-switch-fixed .form-switch .form-check-input::after,
.theme-switch-fixed .form-switch .form-check-input::before {
	text-shadow: var(--top-halo-shadow);
}

/* Знаку собственного правила ореола НЕ НУЖНО: он текстовый и берёт
   text-shadow наследованием от .top-controls, ровно как «Назад».
   Прежняя пара drop-shadow'ов снята вместе с маской (01.09.2026). */


/* --- Подтон верхней кромки обложки (.hero-topveil) ---
   Разметка: сосед .parallax внутри hero (bs-isotope-main/cpt-single.php).
   Сила — --hero-veil, её считает header.php по самой обложке (см. там же).

   ЗАЧЕМ. У верха документа лента прозрачна, и знак, «Назад» и тумблер лежат
   прямо на обложке кейса. Их цвет (--ctx-ink) и цвет их ореола (--ctx-page)
   выведены из палитры ЗАПИСИ, а обложка — произвольная картинка, которая
   сплошь и рядом противоположна палитре по светлоте: светлый скриншот
   интерфейса в тёмной теме, тёмная фотография в светлой. Тогда ореол,
   рассчитанный на цвет страницы, ложится на чужой тон и читается грязным
   пятном вокруг глифов (замер 23.08.2026: фон под знаком 197–206 из 255 при
   цвете ореола 25–44 — macrosales, mera, ai-platform, dataai в тёмной теме;
   зеркально то же в светлой на тёмной обложке — apartgroup, фон 57 при
   ореоле 244). Лечим ФОН, а не ореол: подтягиваем кромку обложки к
   --ctx-page, на который ореол и рассчитан.

   ЭТО НЕ ОТМЕНЁННАЯ ПЛАШКА. Владелец 22–23.08.2026 трижды отказался от
   ПОДЛОЖКИ ПОД ЛЕНТУ — пилюли, залитой ленты, ленты в блюре с маской. Общее
   у всех трёх: непрозрачная поверхность высотой в ленту, с видимой кромкой,
   которая СРЕЗАЛА верх обложки («обложка — это hero, главный кадр страницы»).
   Отличия здесь, по пунктам:
     • ничего не срезается — слой полупрозрачный, обложка видна насквозь на
       всём его протяжении;
     • кромки нет вовсе, слой сходит на нет градиентом;
     • он лежит НЕ НА ЛЕНТЕ, а на самой обложке, и уезжает вместе с ней при
       прокрутке, тогда как лента остаётся;
     • у большинства кейсов его нет совсем (см. «сила» ниже).
   Приём не новый для проекта: тем же живут карточки кейсов на главной
   (.case-card__scrim), и той же природы сама вуаль .parallax-hero-bg —
   обложка и так тонируется цветом кейса, тут она тонируется сильнее ровно в
   полосе, где лежат контролы.

   ПОЧЕМУ НЕ УСИЛИТЬ ВУАЛЬ .parallax-hero-bg. Она ровная по всей обложке и
   одна на все кейсы. Замер: чтобы у худшей обложки (светлый скриншот, 206)
   увести фон под знаком к 106, ровной вуали нужно ~0.65 вместо 0.2 — и та же
   вуаль погасит тёмное фото promstroy с 95 до 67, хотя у него и без неё всё
   в порядке. Подтон же и локален по высоте, и считается под конкретную
   обложку.

   СИЛА — ПЕРЕМЕННАЯ, И ЧАЩЕ ВСЕГО ОНА НОЛЬ. --hero-veil приходит из header.php
   как решение уравнения «остаточное расхождение обложки с цветом страницы не
   больше допуска» (вывод и числа — там). Обложка ближе допуска — множитель 0,
   слой не рисуется, картинка не тронута; так выходит у тёмных фото в тёмной
   теме и у светлых скриншотов в светлой, то есть у кейса в его «родной» теме.
   Фолбэк там же: неизвестна яркость обложки — 0, «не знаю» значит «не трогаю».

   ГЕОМЕТРИЯ. Плато на высоту ленты (--top-plate-space, 53/57px) — там глифы,
   там нужна полная сила. Дальше сход на нет к удвоенной высоте (106/114px),
   это ~12% высоты hero на 1440x900. Короче нельзя: градиент короче полутора
   своих плато начинает читаться кромкой, то есть возвращает ту самую видимую
   границу, от которой ушли. Длиннее незачем: ниже ленты подтон ничего не
   решает. Профиль стопов заваленный (1 / 0.9 / 0.32 / 0 от силы), а не
   линейный — у линейного на середине видна ступенька тона.

   ⚠️ Цвет — только --ctx-page через color-mix. Хардкод-hex тут запрещён так же,
   как везде: на кейсе --ctx-page выводится из палитры записи, и подтон обязан
   ехать за ней. Без поддержки color-mix (@supports ниже) слоя просто нет:
   сплошной --ctx-page дал бы ровно ту непрозрачную плашку, которую отменили. */
.hero-topveil {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 0;
	height: calc(var(--top-plate-space) * 2);
	pointer-events: none;
}

@supports (color: color-mix(in srgb, red, blue)) {
	.hero-topveil {
		background-image: linear-gradient(
			to bottom,
			color-mix(in srgb, var(--ctx-page) calc(var(--hero-veil, 0) * 100%), transparent) 0,
			color-mix(in srgb, var(--ctx-page) calc(var(--hero-veil, 0) * 90%), transparent) var(--top-plate-space),
			color-mix(in srgb, var(--ctx-page) calc(var(--hero-veil, 0) * 32%), transparent) calc(var(--top-plate-space) * 1.5),
			transparent 100%
		);
	}
}

/* 🔴 ПОДТОН ОТКЛЮЧЁН 07.09.2026. Установка владельца: «Когда экран находится
   в самом верху, фона у хедера быть не должно, даже градиента. При
   пролистывании вниз он появляется».

   ПОЧЕМУ ПРАВКА ЗДЕСЬ, А НЕ В СТЕКЛЕ ЛЕНТЫ. Слой стекла
   .top-controls::before у верха документа уже гасится в ноль — computed
   opacity 0 в .topbar-at-top, проверено на /, /studio/ и /cases/…/ в обеих
   темах. Больше того: снимок верхней полосы главной и «Студии» ПОБАЙТОВО
   совпадает со снимком той же полосы, снятым с принудительно выключенным
   стеклом (одинаковые md5 в светлой и тёмной). То есть лента в верхней
   позиции не рисовала ничего уже до этой правки, и «фон, который видно
   наверху» — это был подтон обложки: на /cases/dev-platform/ в светлой теме
   он поднимал полосу под контролами со светлоты 82 до 155 из 255 (медиана
   73 -> 152). В тёмной теме у той же обложки множитель и так 0, разницы нет.

   ПОЧЕМУ display: none, А НЕ ГАШЕНИЕ ПО .topbar-at-top. Подтон лежит на самой
   обложке и уезжает вместе с ней, а класс снимается на --top-plate-space
   (56px) прокрутки. Гашение по классу дало бы подтону ВСПЛЫТЬ на отрезке
   57–112px — пятно, которого нет в покое, появлялось бы в движении, уже под
   стеклом. Хуже, чем оба состояния по отдельности.

   ⚠️ ЦЕНА ИЗВЕСТНА И ПРИНЯТА: у верха кейса знак, «Назад» и тумблер лежат
   прямо на обложке, и контур им держит только ореол (--top-halo). Разбор
   «ЗАЧЕМ» выше по механике остаётся верным — отменено само решение
   тонировать кромку, а не его обоснование. Не удаляю ни разбор, ни расчёт
   силы (--hero-veil в header.php, bootscore_case_veil_alpha в functions.php),
   ни разметку слоя: вернуть подтон = снять это одно правило. */
.hero-topveil {
	display: none;
}

/* Тумблер — крайний ПРАВЫЙ элемент ленты (владелец, 23.08.2026: «выбор темы
   увести вправо в угол»). margin-left: auto, а не justify-content: space-between
   на самой ленте: состав ленты переменный (на главной «Назад» нет), и
   space-between развёл бы знак и «Назад» по разным краям, стоило кнопке
   появиться. Распорка на самом тумблере не зависит от числа соседей.
   Фиксацию по-прежнему несёт .top-controls. */
.theme-switch-fixed {
	display: flex;
	align-items: center;
	margin-left: auto;
}


/* --- Знак «Prod.by_Лазарев» ---
   Единственное место, где бренд присутствует визуально: в остальном на страницах
   названий, логотипов и контактов нет, бренд живёт в SEO-слое. Это осознанное
   исключение. Знак некликабельный — это метка, а не навигация.

   ⚠️ ЗАМЕНИЛ знак MACRO Global (01.09.2026, владелец). Прежний рисовался маской
   по img/logo/macro-logo.svg; нынешний — ТЕКСТ, разметка в header.php.
   Устройство: одна строка без пробелов, «Prod.by_Лазарев», подчёркивание —
   часть знака; акцентом выделена только приставка «Prod.by», «_Лазарев» идёт
   цветом основного текста. На < 768 приставка сокращается до «by» (сам
   «Prod.» спрятан утилитами d-none/d-md-inline в разметке).
   ⚠️ Текстовое написание бренда другое — «Prod. by Лазарев», с пробелами.
   В знаке пробелов нет. Не приводить к одному написанию.

   ⚠️ Гарнитура знака — Oswald (семейство задано ниже в .top-logo). Это
   ЕДИНСТВЕННОЕ исключение из проектной SF UI Display; остальная типографика
   сайта на SF UI Display и НЕ менялась. Исходный знак владельца (ws.lazarewww.ru)
   набран Oswald 32/500 — сюда перенесена и структура знака, и гарнитура,
   кегль под неё пересчитан (см. --top-logo-size).
   ⚠️ Здесь стояла запись «гарнитура — SF UI Display, НЕ Oswald… переезд на
   него — правка одной строки». Она описывала состояние ДО перевода знака
   на Oswald и протухла в тот же день, когда перевод сделали — снята 01.09.2026.

   ⚠️ Начертание у знака ОДНО на обе половины (500). Различие половин —
   только цвет; разбор, почему не вес и не второй цвет, — у .top-logo__prefix.

   Порядок в паре: знак стоит ПЕРВЫМ, левее «Назад». Причина не вкусовая:
   содержимое .top-controls прижато к краю колонки контента, поэтому только
   первый элемент стоит на одном месте и на главной (где «Назад» нет), и на кейсе
   (где он есть). Поставь знак между контролами — и он прыгал бы вправо
   на ширину «Назад» при каждом переходе на кейс.
   ⚠️ Левый край знака совпадает с колонкой контента (заголовок «Кейсы»,
   первая карточка) — выравнивание несёт padding-left самой полосы
   (см. .top-controls).

   Ореол глифов знак получает наследованием от .top-controls (text-shadow) —
   собственного правила у него нет, в отличие от прежнего знака-маски.

   Отдельного правила для печати не заводим: знак лежит внутри
   .top-controls.no-print и обязан исчезать/печататься вместе с остальной парой. */
.top-logo {
	/* ⚠️ Знак — ЕДИНСТВЕННОЕ место на сайте, где типографика не SF UI Display.
	   Решение владельца 01.09.2026: на SF UI Display знак читался как набранная
	   строка, а не как логотип — шрифт широкий и нейтральный. Oswald узкий и
	   характерный, силуэт получается знаковый. Остальная типографика сайта
	   остаётся SF UI Display — это отдельное решение, и оно НЕ менялось.
	   Новых зависимостей нет: Oswald уже лежит в теме (fonts/oswald/), все
	   шесть начертаний 200–700 объявлены в css/lib/bootstrap.min.css.
	   ⚠️ Легаси-класс .oswald для этого НЕ годится — он с !important
	   перенаправлен на SF UI Display (см. верх файла), поэтому семейство
	   задаётся здесь напрямую.
	   Фолбэк — узкие гротески по убыванию распространённости: если Oswald не
	   отдался, знак останется узким и не распорет ленту. Последним стоит
	   sans-serif, а не SF UI Display: подстановка широкого шрифта под кегль,
	   рассчитанный на узкий, — худший из вариантов. */
	font-family: 'Oswald', 'PT Sans Narrow', 'Roboto Condensed', 'Arial Narrow', system-ui, sans-serif;

	/* Кегль знака. Он заметно крупнее подписи «Назад» (0.875rem) намеренно:
	   знак обязан читаться знаком, а не третьим пунктом ленты. Потолок задаёт
	   не вкус, а ширина ленты на 320–375: знак тут самый длинный элемент.
	   ⚠️ Числа ПЕРЕСЧИТАНЫ под Oswald и не равны прежним. Замер 01.09.2026
	   на кегле 100px: cap-height Oswald 81 против 71 у SF UI Display (×1.14),
	   ширина строки «by_Лазарев» 458 против 546 (×0.84). То есть один и тот же
	   font-size даёт у Oswald заметно более КРУПНЫЙ знак — оптический размер
	   несёт высота прописных, а не em. Поэтому кегль уменьшен примерно в 1.14
	   раза: 1.5rem → 1.375rem и 1.25rem → 1.125rem. Взято на волос выше строгой
	   cap-паритетной величины (21.0px и 17.5px) — узкая гарнитура при равной
	   высоте несёт меньше визуальной массы, и точный паритет читается мелковато.

	   ⚠️ УВЕЛИЧЕН 01.09.2026 (владелец: «лого побольше»). Одним числом на все
	   ширины это сделать нельзя, и вот почему — замер запаса ленты (свободные
	   пиксели внутри .top-controls после знака, «Назад» и тумблера):

	     страница кейса, 320px: было 34.6 → при 22px 15.0 → при 24px 5.7
	     страница кейса, 360px: было 66.2 → при 30px  8.4 → при 32px 2.1
	     страница кейса, 375px: было 79.8 → при 32px 15.7
	     страница кейса, 768px: было 367  → при 40px 245
	     главная,        320px: было 155  → запас вчетверо больше

	   То есть потолок держит УЗКИЙ экран страницы кейса (там в ленте на один
	   элемент больше — «Назад»), а на десктопе запас избыточен. Поэтому кегль
	   отзывчивый: две полосы clamp() вместо двух фиксированных чисел.

	   Мобильная полоса: 22px на 320 (это и есть потолок с запасом 15px) и до
	   26px к 767. Знак растёт медленнее, чем сама лента, поэтому с ростом
	   экрана запас только увеличивается — тесно может быть ТОЛЬКО в нижней
	   точке, и она проверена.
	   ⚠️ Высоту ленты знак не трогает ни в одной точке: line-height 1, бокс
	   равен кеглю, а высоту задаёт тумблер (44px). Замерено: barH держится
	   53px (мобильная) / 57px (десктоп) вплоть до кегля 40px. */
	--top-logo-size: clamp(1.375rem, 1rem + 1.75vw, 1.625rem);

	flex: none;
	font-size: var(--top-logo-size);
	/* Oswald Medium — реальное начертание, не синтетика.
	   ⚠️ Вес у знака ОДИН на обе половины, и это решение владельца 01.09.2026,
	   а не «ещё не дошли руки». Приём «различать половины весом» (700 у
	   приставки против 300 здесь) был внедрён и в тот же день ОТМЕНЁН
	   владельцем: «лого пусть будет в едином начертании, просто двухцветный».
	   Не переоткрывать — ни здесь, ни у .top-logo__prefix. */
	font-weight: 500;
	line-height: 1;
	/* ⚠️ Трекинг сменил ЗНАК. Прежний минус (-0.02em) стоял тут ровно потому,
	   что SF UI Display шире Oswald и знак расползался. С Oswald причина
	   исчезла, а появилась обратная: у узкого гротеска соседние вертикали
	   («Лазарев» — сплошные штамбы) слипаются, и знак превращается в частокол.
	   Небольшой плюс возвращает буквам воздух. */
	letter-spacing: 0.015em;
	white-space: nowrap;           /* знак не переносится НИКОГДА */
	color: var(--ctx-ink);

	/* --- ЗНАК — ССЫЛКА НА ГЛАВНУЮ (07.09.2026, владелец) ---
	   Был <span>, стал <a> (header.php). Отсюда три декларации ниже: снять
	   подчёркивание, которое ссылке даёт браузер/бутстрап, дать курсор и
	   убрать 300-мс задержку тапа. Цвет знака ссылка перебить НЕ должна —
	   защита ниже, в правиле с !important. */
	text-decoration: none;
	cursor: pointer;
	touch-action: manipulation;

	/* --- ОПТИЧЕСКОЕ ВЫРАВНИВАНИЕ ЗНАКА С КОНТРОЛАМИ ЛЕНТЫ ---
	   Задача владельца 07.09.2026: «кнопки визуально выше логотипа».

	   ⚠️ Дело НЕ в раскладке: боксы выровнены идеально. Замер 07.09.2026,
	   главная, 1440px — центр бокса у знака, у пункта меню и у тумблера
	   совпадает до пикселя (cy = 28.00 у всех трёх, .top-controls стоит на
	   align-items: center). Расходятся не боксы, а ГЛИФЫ, и виновата
	   метрика Oswald: у знака своя гарнитура, у остальной ленты — SF UI Display.

	   Механика (замер тем же прогоном, кегль 32px):
	     Oswald:        ascent 38, descent 9, cap-высота 26 -> строчная коробка
	                    47px центрируется по боксу, и оптический центр прописных
	                    оказывается НИЖЕ центра бокса на 1.5px;
	     SF UI Display: ascent 13, descent 3, cap 12 при кегле 14 -> тот же расчёт
	                    даёт ВЫШЕ центра бокса на 1.0px.
	   Итог: знак сидел на 2.5px ниже пунктов меню (29.00 против 27.00–27.50)
	   и на 2.5px ниже подписи «Назад» (27.50) на странице кейса. Это и видно
	   глазом как «кнопки выше логотипа».

	   Отсюда формула сдвига, а не магическое число:
	     em-часть  = (ascent - descent)/2 - cap/2 у Oswald
	               = (1.1875 - 0.28125)/2 - 0.8125/2 = 0.0469em   (масштабируется
	                 вместе с кеглем знака, а он у нас отзывчивый — clamp());
	     px-часть  = 0.5px — встречный подъём, который SF UI Display даёт подписям
	                 контролов. Их кегль фиксирован (14px), поэтому слагаемое
	                 фиксированное; 0.5 — среднее между двумя пунктами, они и сами
	                 расходятся на полпикселя (-1.0 у «Кейсы», -0.5 у «Студия»:
	                 у строк разные самые высокие глифы).
	   ⚠️ Число 0.5 ПОДОБРАНО ЗАМЕРОМ, а не выведено, и это честная граница метода:
	   canvas-метрики шрифта (по ним считается em-часть) и метрики РАСКЛАДКИ строки
	   расходятся на доли пикселя, поэтому чистая формула давала промах ~0.7px.
	   На 1440 сдвиг выходит 2.0px, на 768 — 1.83px, на 375 — 1.56px.

	   ПРОВЕРКА (замер 07.09.2026, оптический центр прописных; «мид» — середина
	   между двумя пунктами меню):
	              было      стало     мид пунктов   промах после
	     1440     29.00     27.00        27.25         -0.25
	      768     29.34     27.52        27.25         +0.27
	      375     26.72     25.16        25.25         -0.09
	   Было расхождение до 2.5px (его и видел владелец), стало ≤0.3px — за
	   границей различимого.
	   ⚠️ Страница кейса проверена отдельно: там вместо пунктов подпись «Назад»
	   (оптический центр 27.50 на 1440), знак встаёт на 27.00 — те же полпикселя.

	   ⚠️ Именно transform, а не margin/padding/position: transform НЕ участвует
	   в раскладке — высота ленты, её паддинги и левый край знака (он выровнен
	   по колонке контента) остаются нетронутыми. Замер: barH 56px до и после.
	   ⚠️ Это не анимация, а статическая компенсация метрики, поэтому под
	   prefers-reduced-motion она НЕ снимается. */
	--top-logo-optical-shift: calc(0.0469em + 0.5px);

	transform: translateY(calc(-1 * var(--top-logo-optical-shift)));

	/* та же длительность, что у «Назад» и тумблера — при смене темы
	   вся пара перекрашивается одним движением */
	transition: color 0.3s ease;
}

/* Цвет знака не отдаём ссылочным правилам.
   ⚠️ !important вынужденный: общее .dark-theme a:not(.btn):not(…) имеет
   специфичность (0,5,1) из-за цепочки :not() и покрасило бы знак акцентным
   цветом ссылок. Тот же приём, что у .top-back и пунктов меню.
   ⚠️ hover/focus перечислены НАМЕРЕННО и означают «ничего не происходит»:
   собственного ховера у знака нет по решению владельца 07.09.2026 —
   подчёркивание в ленте есть только у пунктов меню. Кольца фокуса это
   не касается: :focus-visible раздаёт общая система (раздел «ФОКУС
   С КЛАВИАТУРЫ»), и оно у знака остаётся. */
.top-logo,
.top-logo:hover,
.top-logo:focus,
body.dark-theme .top-logo,
body.dark-theme .top-logo:hover,
body.dark-theme .top-logo:focus,
.single-isotope .top-logo {
	color: var(--ctx-ink) !important;
	text-decoration: none;
}

/* Приставка обязана оставаться акцентной и внутри ссылки: правило выше
   красит САМ <a>, а половина знака имеет собственный цвет. Специфичность
   (0,2,0) против (0,1,0) — перебивает без !important, кроме тёмной темы,
   где в игру входит .dark-theme a:not(…) (0,5,1). Оно целится в <a>, а не
   в span внутри него, поэтому здесь тоже хватает обычного правила. */
.top-logo .top-logo__prefix,
.top-logo:hover .top-logo__prefix,
.top-logo:focus .top-logo__prefix {
	color: var(--ctx-accent);
}

/* Цвет приставки — ЧИСТЫЙ --ctx-accent.
   ⚠️ Здесь стоял color-mix(--ctx-accent 50%, --ctx-muted) — костыль под
   ПРЕЖНИЙ синий акцент: у #172747 и --ctx-ink (#272829) контраст был ровно
   1.00, то есть по светлоте они совпадали полностью и двухцветность знака
   в основной теме сайта пропадала. С акцентом #005752 причина исчезла,
   и костыль снят (01.09.2026); с бордовым #8b1d35 (07.09.2026) она тем более
   не вернулась. Замер той же пары «приставка ↔ _Лазарев» в СВЕТЛОЙ теме
   проекта:

                                контраст   ΔE2000   к фону
     БЫЛО  синий, чисто          1.00      14.6     14.81
     БЫЛО  синий, mix 50/50      1.91      16.2      7.74
     БЫЛО  изумруд, чисто        1.75      22.8      8.45
     СТАЛО бордо, чисто          1.64      27.3      9.03   ← это правило

   ⚠️ Контраст половин ПРОСЕЛ (1.75 → 1.64) — это единственная просевшая
   цифра всей бордовой схемы, и она самая узкая: правило проекта «≥1.5 ИЛИ
   ΔE2000 ≥20» она берёт по первому критерию с запасом 9 %. Зато по второму
   критерию стало лучше: различает две части знака не светлота, а ЦВЕТНОСТЬ,
   и ΔE2000 вырос 22.8 → 27.3 (замер 07.09.2026), потому что #8b1d35 насыщен,
   а «_Лазарев» идёт нейтральным #272829 (C* 0.8). Приставка к фону тоже
   стала читаемее: 9.03 против 8.45 у изумруда и 5.96 у прежней смеси.

   Тёмная тема, та же пара: чисто #d33154 — к ink 4.04, к фону 3.72
   (у изумруда было 3.89 / 3.76 — паритет, между половинами даже лучше).
   ⚠️ 3.72 к фону — ниже 4.5, и это осознанно: знак — логотип, а WCAG 1.4.3
   к контрасту логотипа требований не предъявляет; кегль тут 22–32px, и
   прежний ЧИСТЫЙ синий акцент на этом же месте давал ещё меньше — 3.39.

   ⚠️ Перемер 07.09.2026 после перекраски тёмной рампы в бордо: по СВЕТЛОТЕ
   почти не изменилось, 3.76 → 3.72. Тон фона по-прежнему близок к тону
   приставки (Δh ≈ 7°), разводят их насыщенность (65 % у приставки против
   40 % у фона) и светлота (Y 0.167 против 0.008, разница в 20 раз).
   ⚠️ Разрыв по насыщенности у бордового УЖЕ, чем был у изумруда (25 пунктов
   против 59) — это место схемы проверяется глазами на 375 в тёмной теме.
   Числа держатся, поэтому правило оставлено как есть; страховочный ход, если
   когда-нибудь окажется, что приставка читается кашей, — увести
   .top-logo__prefix на отдельный --ctx-accent-text, который в тёмной теме
   равен --macro-accent-text (#e78da1): даёт 7.49 к фону вместо 3.72 и 2.01
   к «_Лазарев». Заводить его превентивно не надо — это лишняя сущность.

   ⚠️ Хардкод-hex тут запрещён так же, как везде.

   ============================================================
   ⚠️⚠️ ПОЧЕМУ ЗДЕСЬ --ctx-accent, ХОТЯ НА КЕЙСАХ ЗНАК ОДНОЦВЕТНЫЙ
   (решение владельца 01.09.2026 — НЕ «чинить» обратно)

   Знак едет за КОНТЕКСТНОЙ палитрой: на главной — акцент проекта, на
   странице кейса — var(--case-rain), то есть цвет самой записи. Это канон
   сайта («на странице кейса ВСЕ элементы берут палитру этого кейса»), и
   владелец распространил его на знак сознательно, уже зная цену.

   Цена замерена (qa-tester, 01.09.2026, воспроизведено дважды). Контраст
   пары «Prod.by» ↔ «_Лазарев» на странице кейса:
     светлая тема   1.01–1.85 на 18 кейсах (macrosales 1.01, niks-rs 1.04,
                    apartgroup 1.06)
     тёмная тема    1.08–1.19 на ВСЕХ 18
   Четыре кейса, восстановленных 01.09.2026 (aukids, alesikalex, spectr,
   shagnsk), ложатся в тот же диапазон — перемер frontender 01.09.2026:
   светлая 1.03–1.59, тёмная 1.08–1.15. Диапазон устойчив, потому что
   вытекает из построения (ниже), а не из подбора палитр.
   То есть на кейсе знак читается ОДНОЦВЕТНЫМ. Это ИЗВЕСТНОЕ И ПРИНЯТОЕ
   состояние, а не дефект и не недосмотр.

   ⚠️ Внутри палитры кейса это НЕ ЧИНИТСЯ — не «плохо подобрали», а нечем:
     • --case-ink считает bootscore_case_ink() (header.php:145) по яркости и
       возвращает ВСЕГДА один из двух нейтралов — #141a24 или #ffffff
       (C* 2 и 0). Третьего значения у функции нет;
     • --case-rain — противоположная по светлоте половина авторской пары,
       то есть в светлой теме всегда тёмный, в тёмной всегда светлый. Он
       садится на ТУ ЖЕ сторону светлотной шкалы, что и ink, — отсюда 1.0x;
     • насыщенности у него может не быть вовсе: у macrosales пара
       #f1f2f3 / #0f1a30, первый — чистый серый, разводить по ΔE нечем.
   Второго цвета в палитре кейса физически НЕТ.

   ⚠️ Поэтому не повторяй уже пройденный круг. 01.09.2026 приставку выводили
   отсюда на постоянный --macro-accent-text (тогда #005752 / #00ccc0, сейчас
   #8b1d35 / #e78da1) — двухцветность возвращалась на любой палитре, но знак
   переставал слушаться кейса, и владелец ОТКАТИЛ правку: канон важнее.
   Сам токен --macro-accent-text оставлен — он узаконен ТЗ
   (site/docs/tz/tz-color-scheme-burgundy.md, §12) и работает в трёх блоках;
   просто здесь он не применяется.

   ⚠️ ⛔ ТУПИК ЗАКРЫТ — ОБА ПУТИ ПРОЙДЕНЫ И ОТКЛОНЕНЫ ВЛАДЕЛЬЦЕМ 01.09.2026.
   Это финальное состояние, а не промежуточное:
     • вернуть двухцветность ЦВЕТОМ (постоянный --macro-accent-text вместо
       контекстного акцента) — внедрялось, откачено: знак переставал
       слушаться палитры кейса, канон важнее;
     • различать половины НАЧЕРТАНИЕМ (приставка 700, «_Лазарев» 300) —
       внедрялось, откачено в тот же день: «лого пусть будет в едином
       начертании, просто двухцветный». Отклонён и вариант 600/200.
   Итог: знак набран ОДНИМ весом (500), различие несёт только цвет, и на
   кейсах он поэтому читается одноцветным. Владельцу цена названа, он её
   принял. Третьего захода не нужно — если кажется, что нашёл новый приём,
   сначала перечитай этот блок целиком.

   ⚠️ ВТОРАЯ половина знака («_Лазарев», .top-logo выше) на --ctx-ink:
   она обязана читаться на фоне СТРАНИЦЫ, а его задаёт кейс. Обе части
   контекстные — исключений в знаке больше нет.
   ============================================================ */
.top-logo__prefix {
	color: var(--ctx-accent);
	/* ⚠️ font-weight тут НЕТ намеренно — приставка наследует 500 от .top-logo.
	   Знак набран ЕДИНЫМ начертанием, различие половин несёт ТОЛЬКО цвет.
	   Не добавляй сюда вес «чтобы приставка читалась» — это ровно тот приём,
	   который был внедрён и отменён владельцем 01.09.2026. */
	transition: color 0.3s ease;
}

@media (min-width: 768px) {
	.top-logo {
		--top-logo-size: clamp(1.75rem, 1.05rem + 1.5vw, 2rem);
	}
}

@media (prefers-reduced-motion: reduce) {
	.top-logo,
	.top-logo__prefix {
		transition: none;
	}
}


/* --- Кнопка «Назад на главную» ---
   Одного рода с тумблером и ссылками навигации: та же высота 44px (она же
   тап-таргет), тот же радиус. Иконки — Font Awesome, уже подключён родительской
   темой; новых зависимостей не тянем.

   ⚠️ Собственной плашки у неё БОЛЬШЕ НЕТ (снята 22.08.2026). Раньше «Назад»
   единственная в ленте несла поверхность + рамку + тень — и именно поэтому
   единственная не страдала от нечитаемости на обложке кейса. Залитый чип
   внутри ленты читался как вторая поверхность поверх первой: две вложенные
   рамки в 1px друг от друга.
   ⚠️ Довод «контраст теперь даёт общая подложка ленты» ОТМЕНЁН 23.08.2026
   вместе с самой подложкой: у верха страницы лента прозрачна. Читаемость
   кнопки на обложке держит ореол (--top-halo, см. раздел «Ореол контролов»),
   он же наследуется сюда как text-shadow. Поэтому в покое кнопка «тихая»
   (только текст и иконки), а поверхность с рамкой проявляется на hover/focus.
   Прозрачная рамка, а не её отсутствие: иначе на hover кнопка подрастала бы
   на 2px и лента дёргалась.

   ⚠️ С 23.08.2026 (ТЗ tz-home-tabs.md) «Назад» — единственный навигационный
   элемент ленты: ссылки «Портфолио» / «Команда» удалены, разделы переехали
   в ленту вкладок на главной. Прежний довод «это дубль ссылки Портфолио,
   поэтому её и прячем на узких экранах» вместе с ними отменён — кнопка
   показывается на ВСЕХ ширинах, а ведёт на главную с вкладкой категории
   кейса (см. header.php). */

.top-back {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	height: 44px;
	padding: 0 0.9375rem;
	border: 1px solid transparent;
	border-radius: 999px;
	background-color: transparent;
	box-shadow: none;
	color: var(--ctx-ink);
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
	touch-action: manipulation;
	transition: background-color 0.3s ease, border-color 0.3s ease,
		box-shadow 0.3s ease, color 0.3s ease;
}

.top-back__icons {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
	color: var(--ctx-muted);
	transition: color 0.3s ease, transform 0.3s ease;
}

.top-back__arrow {
	font-size: 0.75rem;
	transition: transform 0.3s ease;
}

.top-back__home {
	font-size: 1rem;
}

.top-back__label {
	letter-spacing: 0.01em;
}

@media (hover: hover) and (pointer: fine) {
	.top-back:hover {
		/* Поверхность и рамка появляются только тут — в покое кнопка тихая,
		   контраст держит ореол глифов. Рамка акцентная: это
		   единственный навигационный жест в ленте, и он вправе отзываться
		   заметнее декоративного знака. */
		border-color: var(--ctx-accent);
		background-color: var(--ctx-surface);
		box-shadow: var(--macro-shadow-sm);
		color: var(--ctx-ink);
	}

	.top-back:hover .top-back__icons {
		color: var(--ctx-accent);
	}

	/* Стрелка отъезжает влево — направление «назад» читается без текста */
	.top-back:hover .top-back__arrow {
		transform: translateX(-2px);
	}
}


/* Общее .dark-theme a:not(.btn):not(…) имеет специфичность (0,5,1) из-за цепочки
   :not() — без !important подпись кнопки красилась в голубой цвет ссылок. */
/* .dark-theme a:not(.btn):not(…) — специфичность (0,5,1), обычным правилом
   не перебить. Цвет тот же контекстный, просто протаскиваем его через !important. */
body.dark-theme .top-back,
body.dark-theme .top-back:hover,
body.dark-theme .top-back:focus,
.single-isotope .top-back {
	color: var(--ctx-ink) !important;
}

/* Совсем узкие экраны: лента упирается в правый край.
   Состав ленты: знак + «Назад» + распорка + тумблер.
   ⚠️ Отдельного кегля знака здесь БОЛЬШЕ НЕТ (снят 01.09.2026 вместе с
   переводом знака на Oswald). Он тут стоял ровно потому, что широкий
   SF UI Display на 320 съедал ~15 px запаса ленты — при переводе на узкую
   гарнитуру причина исчезла: знак базовым кеглем 18 px стал УЖЕ, чем был
   прежний специально ужатый до 17 px (84.7 px против 93.6 px). Оставшаяся
   разница между базовым кеглем и прежним шагом — 1 px (18 против 17),
   ради неё держать частный случай незачем.
   Замер 01.09.2026 на кейсе (самый плотный случай), Oswald:
   320 — содержимое 253.4 px при 288 доступных, запас 34.6;
   375 — 261.4 при 341.3, запас 79.8. Переполнения нет нигде.
   Порог 359.98 оставлен ради поджатия зазора: на 320 он единственный
   отделяет ленту от краёв. */
@media (max-width: 359.98px) {
	.top-controls {
		gap: 0.25rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.top-back,
	.top-back__icons,
	.top-back__arrow {
		transition: none;
	}

	.top-back:hover .top-back__arrow {
		transform: none;
	}
}

/* --- Меню разделов в ленте (.top-nav) ---
   ТЗ: site/docs/tz/tz-studio-page.md §2.3. Пункты приходят из админки
   (область 'top-nav', см. functions.php), разметка — в header.php.

   ⚠️ ЗАПИСЬ ИЗМЕНЕНА 07.09.2026. Раньше здесь стояло «шкура пункта — ровно та
   же, что у .top-back: радиус 999px, прозрачная рамка, поверхность и рамка
   появляются только на hover; правишь одну — правь обе». Первая половина
   отменена владельцем: у пунктов меню отклик теперь ПОДЧЁРКИВАНИЕ, а не пилюля
   (разбор — у правила :hover ниже). Общими у пункта и «Назад» остались тап-таргет
   44px, кегль 14/500 и контекстный цвет; пилюля осталась ТОЛЬКО у «Назад».
   ⚠️ Правило «правь обе» больше не действует и специально: в одной ленте эти
   два элемента не встречаются НИКОГДА — «Назад» показывается только на странице
   кейса, а меню там намеренно не выводится (условие в header.php). Разными
   языками они не спорят, потому что не бывают в кадре одновременно.
   ⚠️ Прозрачной рамки у пункта тоже больше нет: она держала пункт от подрастания
   на 2px при появлении рамки на hover — рамки нет, страховать нечего.

   ⚠️ Меню НЕ выводится на странице кейса (условие в header.php). Причина —
   замер запаса ленты, записанный у .top-logo: на кейсе 320px остаётся 5.7px,
   360px — 2.1px. Здесь, на главной и «Студии», «Назад» в ленте нет, и его
   место занимают пункты.

   Ореол глифов наследуется от .top-controls (text-shadow) — своего правила
   пунктам не нужно, они текстовые, как и «Назад».

   Отдельного правила для печати нет: меню лежит внутри
   .top-controls.no-print и исчезает вместе с остальной лентой. */

.top-nav {
	/* --- ВОЗДУХ МЕЖДУ ЗНАКОМ И МЕНЮ (владелец, 07.09.2026: «отступ меню от
	   логотипа чуть шире») ---
	   Собственный отступ меню, ДОБАВОЧНЫЙ к общему gap ленты. Отдельной ручкой,
	   а не увеличением `gap` у .top-controls: тот раздаёт зазор ВСЕМ соседям
	   сразу, а раздвинуть надо ровно одну пару «знак ↔ меню» — правая группа
	   (тумблер) стоит на margin-left: auto и от gap не зависит, пока в ленте
	   есть свободное место.
	   ⚠️ Отступ АДАПТИВНЫЙ и ниже 576px равен НУЛЮ. Замер свободного места
	   в ленте на главной 07.09.2026 (от правого края меню до тумблера):
	     320 — 27.7px   360 — 61.9px   375 — 74.4px
	     576 — 195px    768 — 297px    1440 — 884px
	   То есть воздух есть только от 576px, а на 320 весь запас ленты — 27.7px,
	   и тратить его на декоративный зазор нельзя: следом лента переносится
	   и тумблер уезжает за край. Ровно поэтому на узких прибавки нет.
	   Величины: зазор ленты 8px (<768) / 10px (>=768) — прибавка удваивает его
	   до 16px и 20px соответственно. Единицы относительные (rem), не px.
	   ⚠️ Страницы кейса это не касается вовсе: меню там не выводится, а «Назад»
	   своего отступа не получал и не получает. */
	--top-nav-air: 0rem;

	/* flex: none — меню не должно ни растягиваться распоркой, ни ужиматься:
	   тумблер отжимается вправо своим margin-left: auto. */
	flex: none;
	min-width: 0;
	margin-left: var(--top-nav-air);
}

@media (min-width: 576px) {
	.top-nav {
		--top-nav-air: 0.5rem;
	}
}

@media (min-width: 768px) {
	.top-nav {
		--top-nav-air: 0.625rem;
	}
}

.top-nav__list {
	display: flex;
	align-items: center;
	/* Зазор минимальный: пункты и так разведены собственным горизонтальным
	   паддингом, а лента на 320 считается по пикселям. */
	gap: 0.125rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.top-nav__list li {
	margin: 0;
}

.top-nav__list a {
	/* Отступ линейки от краёв пункта. Одна ручка на ДВА состояния — hover
	   и активный пункт: линейка обязана быть шириной ТЕКСТА, а паддинг
	   пункта меняется по брейкпоинтам. Раньше эти же числа дублировались
	   в двух медиазапросах отдельными правилами для ::after; теперь они
	   едут за паддингом сами. */
	--top-nav-rule-inset: 0.625rem;

	position: relative;
	display: inline-flex;
	align-items: center;
	height: 44px;
	/* Узкая полоса — сначала режем ПАДДИНГ, а не кегль: 14px уже нижняя
	   граница читаемости в ленте (тот же кегль у «Назад»). */
	padding: 0 0.625rem;
	color: var(--ctx-ink);
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1;
	letter-spacing: 0.01em;
	text-decoration: none;
	white-space: nowrap;
	touch-action: manipulation;
	/* Переход остался ОДИН — по цвету: он нужен для смены темы, где вся лента
	   перекрашивается одним движением. Прежние background-color/border-color/
	   box-shadow ушли вместе с пилюлей hover (см. ниже): анимировать больше
	   нечего, а подчёркивание обязано появляться сразу целиком. */
	transition: color 0.3s ease;
}

/* ⚠️ Самые узкие экраны: паддинг режем, КЕГЛЬ НЕ ТРОГАЕМ.
   Правило из ТЗ (tz-studio-page.md §2.4): 14px — нижняя граница читаемости
   в ленте, поэтому при нехватке места жертвуем воздухом вокруг слова.

   Замер 01.09.2026 на «Студии» (лента: знак + «Кейсы» + «Студия» + тумблер,
   свободные пиксели внутри .top-controls после всех элементов и зазоров):

     ширина  паддинг 0.625rem   паддинг 0.25rem + gap 0
       320      −12.8  (не влезает)      +13.2
       360       +7.8                    +33.8
       375      +35.9  (не нужен)          —

   То есть без этого шага лента на 320 переполнялась и тумблер уезжал
   за правый край. Порог 399.98 взят с запасом относительно 360: на 375
   штатный паддинг уже проходит, но менять шкуру пункта на 15 пикселях
   ширины — лишнее мельтешение. */
@media (max-width: 399.98px) {
	.top-nav__list {
		gap: 0;
	}

	.top-nav__list a {
		--top-nav-rule-inset: 0.25rem;

		padding: 0 0.25rem;
	}
}

@media (min-width: 576px) {
	.top-nav__list a {
		--top-nav-rule-inset: 0.9375rem;

		padding: 0 0.9375rem;
	}
}

/* Общее правило темы `.dark-theme a:not(.btn):not(…)` имеет специфичность
   (0,5,1) из-за цепочки :not() — без !important пункты красились бы
   в акцентный цвет ссылок. Цвет тот же контекстный, просто протаскиваем его.
   Тот же приём, что у .top-back. */
body.dark-theme .top-nav__list a,
body.dark-theme .top-nav__list a:hover,
body.dark-theme .top-nav__list a:focus,
.single-isotope .top-nav__list a {
	color: var(--ctx-ink) !important;
}

/* --- HOVER — ПРОСТОЕ ПОДЧЁРКИВАНИЕ, СРАЗУ В КОНЕЧНОМ ВИДЕ ---
   Установка владельца 07.09.2026: «при наведении на Кейсы/Студия просто ховер
   с подчёркиванием, как он есть на финальном виде».

   ⚠️ ЧТО ОТМЕНЕНО. До этой правки на hover проявлялась ПИЛЮЛЯ: поверхность
   --ctx-surface, акцентная рамка 1px и тень --macro-shadow-sm, всё с переходом
   0.3s (замер 07.09.2026, светлая тема: background #ffffff, border 1px #8b1d35,
   box-shadow 0 1px 3px rgba(0,0,0,.06)). Подчёркивания на hover не было вовсе —
   линейка принадлежала только активному пункту. Не возвращать.

   ⚠️ ЛИНИЯ ПОЯВЛЯЕТСЯ ЦЕЛИКОМ, без роста от центра и без проявления по
   прозрачности: это прямое требование «в конечном виде». Поэтому у ::after
   нет ни transition, ни transform — псевдоэлемент просто создаётся.

   ЦВЕТ — currentColor, то есть --ctx-ink пункта, а НЕ акцент. Причина: акцентная
   линейка в этой ленте уже занята и означает «этот раздел открыт» (см. блок
   активного пункта ниже). Раздавать тот же знак курсору — размывать значение,
   а на главной было бы видно ДВЕ акцентные линейки разом (активные «Кейсы» +
   наведённая «Студия»). Ink к тому же контрастнее: замер 07.09.2026 на фоне
   страницы — светлая 14.81, тёмная 13.63; акцент дал бы 9.03 и 3.72.
   ⚠️ Ореол глифов (--top-halo) на линию НЕ действует — он text-shadow, а линия
   не текст. В нулевой позиции прокрутки лента прозрачна, и линия лежит прямо
   на странице; именно поэтому взят самый контрастный из доступных цветов.

   ГЕОМЕТРИЯ — ровно та же, что у активного пункта (ширина текста, 2px, bottom
   7px, радиус 1px). Раскладку не трогает: ::after абсолютный, высоту ленты
   и ширину пункта не меняет.

   ⚠️ На АКТИВНОМ пункте hover ничего не перекрашивает: правило активного идёт
   НИЖЕ по файлу и при равной специфичности (0,2,2) выигрывает — линия остаётся
   акцентной. Переставлять блоки местами нельзя, на этом порядке всё и держится.

   Клавиатурный фокус на подчёркивание не завязан: кольцо раздаёт общая система
   фокуса (:focus-visible в разделе «ФОКУС С КЛАВИАТУРЫ»), она к hover
   отношения не имеет. */
@media (hover: hover) and (pointer: fine) {
	.top-nav__list a:hover::after {
		content: "";
		position: absolute;
		left: var(--top-nav-rule-inset);
		right: var(--top-nav-rule-inset);
		bottom: 7px;
		height: 2px;
		border-radius: 1px;
		background-color: currentColor;
		pointer-events: none;
	}
}

/* --- Активный пункт ---
   ⚠️ ЛИНЕЙКА, А НЕ ЗАЛИВКА, и это не вкусовщина: цветная пилюля в ленте
   противоречит регистру сайта (тот же довод, что в tz-color-scheme-emerald.md
   §10, вариант Г — залитый чип отклонён).

   ⚠️ Текст активного пункта остаётся --ctx-ink и цветом НЕ красится —
   запрещённая пара №4 (§7 того же ТЗ): контраст акцент↔ink 1.64, то есть
   акцентный текст в ленте был бы неотличим от обычного.

   Линейка 2px — ГРАФИЧЕСКИЙ объект, к нему применяется 1.4.11 с порогом 3.0:
   --ctx-accent в светлой теме #8b1d35 даёт 9.03 к белому, в тёмной #d33154 —
   3.72 к фону. Проходит в обеих.

   Ширина линейки = ширина ТЕКСТА: left/right берутся из --top-nav-rule-inset,
   а он объявлен рядом с паддингом пункта и меняется вместе с ним на каждом
   брейкпоинте — второго объявления линейка не требует. bottom подобран так,
   чтобы линейка встала под текстом, а не по нижней кромке 44-пиксельного бокса.

   ⚠️ С 07.09.2026 та же геометрия у линии hover (выше). Отличаются они ЦВЕТОМ:
   активный — акцент, hover — currentColor/ink. Плюс активный набран весом 600.
   Совпадение hover и активного на одном пункте разрешает порядок правил: этот
   блок идёт ниже, специфичность равная (0,2,2), значит на активном пункте
   при наведении остаётся акцентная линия. */
.top-nav__list .current-menu-item > a,
.top-nav__list .current_page_item > a,
.top-nav__list a[aria-current="page"] {
	font-weight: 600;
}

.top-nav__list .current-menu-item > a::after,
.top-nav__list .current_page_item > a::after,
.top-nav__list a[aria-current="page"]::after {
	content: "";
	position: absolute;
	left: var(--top-nav-rule-inset);
	right: var(--top-nav-rule-inset);
	bottom: 7px;
	height: 2px;
	border-radius: 1px;
	background-color: var(--ctx-accent);
	pointer-events: none;
}

/* Кольцо фокуса — штатное кольцо темы (--focus-ring-color, раздел «ФОКУС
   С КЛАВИАТУРЫ»). Своего пунктам не заводим. */

@media (prefers-reduced-motion: reduce) {
	.top-nav__list a {
		transition: none;
	}
}


/* Сбрасываем раскладку бутстраповского .form-switch: она рассчитана на
   маленький чекбокс с отрицательным margin внутри padding-left. */
.theme-switch-fixed .dark-mode-switch {
	margin-right: 0;
}

.theme-switch-fixed .form-check {
	display: flex;
	align-items: center;
	margin-bottom: 0;
	min-height: 0;
	padding-left: 0;
}

.theme-switch-fixed .form-check-label {
	margin: 0;
}

/* Сам контрол: круглая зона 44×44 (тап-таргет целиком, WCAG 2.5.5),
   визуально — ТОЛЬКО символ: фон и граница прозрачные, тени нет.
   ⚠️ Хвост «поверхность и граница проявляются на hover/focus» снят 07.09.2026:
   плашки больше нет ни в одном состоянии, разбор — ниже, у правил hover/focus.
   Никакого трека-пилюли и залитого «включённого» состояния: состояние читается
   символом (солнце = светлая тема сейчас, луна = тёмная).

   !important местами вынужденный: и dark-theme.css, и switch.css плагина целятся
   в тумблер селекторами вида
   .dark-theme .form-switch .form-check-input:not(.dark-theme .form-switch .form-check-input:checked)
   — :not() наследует специфичность аргумента, получается (0,7,0), обычным
   правилом не перебить. */
.theme-switch-fixed .form-check-input {
	position: relative;
	float: none;
	margin: 0;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1px solid transparent !important;
	border-radius: 50%;
	background-color: transparent !important;
	background-image: none !important;
	box-shadow: none;
	cursor: pointer;
	touch-action: manipulation;
	transition: background-color 0.25s ease, border-color 0.25s ease,
		box-shadow 0.25s ease;
}

/* Иконки солнца/луны рисует сам плагин псевдоэлементами
   (::after — солнце \f185, ::before — луна \f186). Оба кладём в центр и
   переключаем прозрачностью: в кадре всегда ровно один символ. */
.theme-switch-fixed .form-switch .form-check-input::after,
.theme-switch-fixed .form-switch .form-check-input::before {
	/* !important — у плагина в @-moz-document висит top:-1px !important,
	   а слева/справа свои координаты под трек */
	top: 50% !important;
	left: 50% !important;
	right: auto !important;
	transform: translate(-50%, -50%);
	font-size: 1.0625rem;
	line-height: 1;
	/* Цвет иконок — всегда контекстный ink (на кейсе он вычислен по яркости
	   цвета кейса). !important обязателен: и dark-theme.css, и switch.css плагина
	   целятся в псевдоэлементы цепочками :not() со специфичностью (0,7,0). */
	color: var(--ctx-ink) !important;
	transition: opacity 0.25s ease, transform 0.25s ease, color 0.25s ease;
}

/* Светлая тема — солнце */
.theme-switch-fixed .form-switch .form-check-input::after {
	opacity: 1;
}

.theme-switch-fixed .form-switch .form-check-input::before {
	opacity: 0;
}

/* Тёмная — луна. Правило продублировано на body.dark-theme: скрипт плагина
   проставляет checked только на DOM-ready, а класс dark-theme приходит уже
   с сервера (body_class) — иначе на первых кадрах символ был бы «не от той темы». */
.theme-switch-fixed .form-check-input:checked::after,
body.dark-theme .theme-switch-fixed .form-switch .form-check-input::after {
	opacity: 0;
	transform: translate(-50%, -50%) rotate(-45deg);
}

.theme-switch-fixed .form-check-input:checked::before,
body.dark-theme .theme-switch-fixed .form-switch .form-check-input::before {
	opacity: 1;
	color: var(--ctx-ink) !important;
}

/* --- ТУМБЛЕР — ИКОНКА, А НЕ КНОПКА (владелец, 07.09.2026) ---
   «Убери фокус с солнца/луны, не должно выделяться как кнопка».

   ⚠️ ЧТО ОТМЕНЕНО. До этой правки контрол на hover и на ЛЮБОМ фокусе (включая
   мышиный клик) проявлял ПЛАШКУ: заливка --ctx-surface, круглая рамка 1px
   --macro-line-strong, на hover ещё и тень --macro-shadow-sm. Замер 07.09.2026,
   светлая тема: hover -> background #ffffff, border #937b81, box-shadow
   0 1px 3px rgba(0,0,0,.06); тёмная -> #3e1b27 / #ae939a. Ровно это и читалось
   кнопкой. Не возвращать.

   ⚠️ ЧТО ОСТАЛОСЬ ОТКЛИКОМ НА МЫШЬ: перекраска САМОГО СИМВОЛА в акцент. Это
   отклик иконочного языка, а не кнопочного — ни плашки, ни рамки, ни тени.

   ⚠️ ФОКУС РАЗВЕДЁН НА ДВА. Прежнее правило целилось в голый :focus, поэтому
   после клика мышью плашка ЗАЛИПАЛА до следующего клика мимо. Теперь:
     • :focus:not(:focus-visible) — мышь/тап: ничего, контрол остаётся иконкой
       (эта ветка ещё и глушит бутстраповский .form-check-input:focus, который
       вешает своё box-shadow-кольцо);
     • :focus-visible — клавиатура: кольцо остаётся, но ДЕЛИКАТНОЕ. Общая
       система фокуса даёт 3px с отступом 3px; здесь оба числа поджаты
       переменными до 2px — контрол круглый, 44×44 и стоит впритык к краю
       окна, толстое кольцо на нём читается той же кнопкой, от которой уходим.
       Цвет кольца контекстный (--focus-ring-color), хардкода нет.
   ⚠️ outline: none без замены тут НЕ применяется нигде — доступность фокуса
   сохранена, снят только мышиный след. */
@media (hover: hover) and (pointer: fine) {
	.theme-switch-fixed .form-check-input:hover::after,
	.theme-switch-fixed .form-check-input:hover::before {
		color: var(--ctx-accent) !important;
	}

	/* ⚠️ Отдельная пара селекторов на ЛУНУ, и она обязательна. Правило
	   «символ активной темы красится ink» выше по файлу имеет вид
	   `body.dark-theme .theme-switch-fixed .form-switch .form-check-input::before`
	   — специфичность (0,4,1) и !important, то есть строку hover (0,3,1)
	   оно перебивает. Замер до правки: в тёмной теме на hover солнце
	   становилось акцентным, а видимая ЛУНА оставалась #f2e8eb, то есть
	   отклика не было вовсе. Здесь специфичность выровнена. */
	body.dark-theme .theme-switch-fixed .form-switch .form-check-input:hover::before,
	.theme-switch-fixed .form-check-input:checked:hover::before {
		color: var(--ctx-accent) !important;
	}
}

/* !important — плагинные switch.css / dark-theme.css целятся в контрол
   цепочками :not() со специфичностью (0,7,0); без него бутстраповская заливка
   и рамка чекбокса возвращаются на фокусе. */
.theme-switch-fixed .form-check-input:focus,
.theme-switch-fixed .form-check-input:focus:not(:focus-visible),
.theme-switch-fixed .form-check-input:active {
	background-color: transparent !important;
	border-color: transparent !important;
	box-shadow: none !important;
}

.theme-switch-fixed .form-check-input:focus-visible {
	--focus-ring-width: 2px;
	--focus-ring-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.theme-switch-fixed .form-check-input,
	.theme-switch-fixed .form-switch .form-check-input::after,
	.theme-switch-fixed .form-switch .form-check-input::before {
		transition: none;
	}

	.theme-switch-fixed .form-check-input:checked::after,
	body.dark-theme .theme-switch-fixed .form-switch .form-check-input::after {
		transform: translate(-50%, -50%);
	}
}


/* Верхний отступ первого экрана: шапки нет, но контент не должен
   ни упираться в край, ни оставлять дыру на месте бывшего навбара.
   Внутренние страницы (page.php / single.php) уже дают py-5 mt-4,
   у кейса — полноэкранный hero, им это правило не нужно. */
/* Верхний отступ первого экрана.
   Шапки-навбара у сайта нет, но сверху лежит фиксированная ЛЕНТА (с 22.08.2026 —
   полоса во всю ширину, прижатая к верху), поэтому контент обязан начинаться
   ниже неё. Второе слагаемое max() — та же страховка, что у .cases-section:
   кромка полосы (--top-plate-space) + 1.5rem воздуха = 77/81px, это всегда
   меньше clamp'а, так что при обычных метриках выигрывает первый аргумент.
   Отступ по умолчанию держит сам
   #page_entry_content; когда .cases-section станет первым элементом контента
   (backender уберёт гутенберговскую обёртку с заголовком), отступ отдаём
   секции — у неё свой clamp(4.5rem, 8vw, 8rem), иначе сложится вдвое.
   Без поддержки :has() остаётся текущее поведение — просто чуть больше воздуха.

   overflow-x: clip — страховка под full-bleed: если шорткод окажется внутри
   бутстраповского .container, секция вырывается на 100vw, и лишние пиксели
   под вертикальным скроллбаром надо обрезать, а не скроллить. */
.home #page_entry_content {
	padding-top: max(clamp(5.75rem, 8vw, 8rem),
		calc(var(--top-plate-space) + 1.5rem)) !important;
	overflow-x: clip;
}

.home #page_entry_content:has(> .entry-content > .cases-section:first-child) {
	padding-top: 0 !important;
}

/* То же самое для обычных страниц (page.php печатает
   .site-content.container.py-5.mt-5) — сейчас это /team/, завтра любая новая.
   Контент обязан начинаться НИЖЕ верхней полосы.

   ⚠️ Арифметика пересчитана 22.08.2026 вместе с заменой пилюли полосой.
   При пилюле её нижняя кромка = --case-pad + высота, на 1440 это 122.8px,
   и второе слагаемое max() РЕАЛЬНО перебивало 6rem — заголовок страницы уходил
   под ленту. Полоса прижата к верху, её кромка = 53/57px на любой ширине
   (52/56 высоты контролов + 1px границы, вернувшейся 23.08.2026), плюс воздух
   1.5rem = 77/81px. Это меньше 6rem всегда, поэтому теперь всегда
   выигрывает первый аргумент, а второй остался СТРАХОВКОЙ: подрастёт высота
   контролов — отступ подрастёт сам, без правки числа здесь.

   Страница кейса исключена намеренно: там во весь экран hero-обложка, лента
   лежит поверх неё по замыслу, отодвигать нечего.

   Почему margin-top: 0 и весь отступ в padding: так правило не зависит от того,
   какие бутстраповские утилиты стоят в шаблоне (.mt-5 + .py-5 дают 48+48=96px).
   6rem в max() — те же 96px, поэтому вид не меняется вообще.
   !important — перебиваем утилиты, у них !important уже стоит. */
body:not(.home):not(.single-isotope) .site-content {
	margin-top: 0 !important;
	padding-top: max(6rem, calc(var(--top-plate-space) + 1.5rem)) !important;
}


/* ============================================================
   ТЁМНАЯ ТЕМА
   БОРДОВАЯ, не серая, не тёмно-синяя и больше не изумрудная. Переключение —
   классом .dark-theme от плагина bs-dark-mode-main (механику не трогаем,
   берём только цвета).

   ⚠️ Рампа перекрашена целиком 07.09.2026 (изумруд #0d1e1f / #112829 /
   #142f30 / #1d4546 → бордо). До изумруда была синяя #0f1a30 / #16253f /
   #1b2c4b / #2c4066.

   🔴 ГЛАВНОЕ ОТЛИЧИЕ ЭТОЙ ПЕРЕКРАСКИ ОТ ПРЕДЫДУЩЕЙ. При переходе в изумруд
   действовало правило «сохранить светлотную лестницу»: Y каждой ступени
   совпадала с предшественником в пределах ~2 %, менялся только тон, и все
   прежние замеры оставались в силе. С бордовым это правило ФИЗИЧЕСКИ
   НЕСОВМЕСТИМО и от него отказались осознанно (ТЗ §2.4).
   Причина — коэффициенты яркости WCAG: R 0.2126 против G 0.7152. Изумруд
   набирал Y зелёным каналом почти даром, бордовый набирает красным, вчетверо
   «дороже». Чтобы попасть в СТАРОЕ окно заливки [0.1719 … 0.1833], бордовый
   обязан был бы стать ярко-вишнёвым #d43558 и сесть на самый пол окна
   (отрыв от поверхности 3.007 при пороге 3.0 — запаса нет).
   Поэтому рампа ОПУЩЕНА на ступень: фон Y 0.0111 → 0.0083, поверхность
   0.0240 → 0.0195. Все контрасты пересчитаны заново, и ни один не стал
   хуже — текстовые стали лучше (ink 14.62 → 15.03 к фону).

   Насыщенность рампы — ~40 % (у изумруда была ~41 %, у синей ~50 %).
   У синей рампы отрыв от акцента давал сам тон (Δh ≈ 40°); у бордовой, как
   и у изумрудной, тона почти совпадают (Δh ≈ 7°), и разводить их обязана
   насыщенность: 40 % против 65 % у акцента.
   ⚠️ Разрыв по насыщенности УЖЕ, чем был у изумруда: 25 пунктов против 59
   (там было 41 % против 100 %). В абсолютных величинах на околочёрных
   ступенях это почти не читается, но это ЕДИНСТВЕННОЕ место схемы, которое
   обязано проверяться глазами на 375 px в тёмной теме.

   Принцип как в их STYLE.md: цвета заведены ОДИН раз токенами, ниже
   правила только перекладывают токены на переменные Bootstrap.
   Отдельными правилами добираем места, где в собранном bootstrap.min.css
   стоит литеральный hex, а не var() (BS 5.1 не имеет --bs-border-color,
   --bs-link-color и т.п.).
   ============================================================ */

body.dark-theme {
	/* --- токены темы ---
	   hue 339–340° при насыщенности ~40 % у поверхностей, 342–345° при 14–28 %
	   у текста: подтон уходит в землю, текст остаётся почти нейтральным. */
	--macro-soft: #251017;   /* фон страницы (--ctx-page), Y 0.00826 (замер) */
	--macro-soft2: #341620;  /* вторая поверхность, поля ввода, трек скроллбара */
	--macro-surface: #3e1b27; /* поверхности, карточки, подвал, залитая лента */
	/* Волосяные линейки: 1.61 к фону — декор, 1.4.11 не применяется.
	   Границы КОНТРОЛОВ — --macro-line-strong ниже. */
	--macro-border: #60293c;
	/* Границы контролов. Светлота здесь выше, чем можно было бы ожидать, и это
	   вынужденно: 3:1 к поверхности требует Y ≥ 0.1586, но любое Y в
	   0.159…0.183 попадает в окно заливки акцента (#d33154, Y 0.1669) — линия
	   слилась бы с ней. Поэтому линия уходит на светлоту muted: Y 0.3220,
	   отрыв от акцента 1.72, к фону 6.39. ⚠️ Темнее не делать. */
	--macro-line-strong: #ae939a;
	--macro-ink: #f2e8eb;
	--macro-ink2: #d3bbc1;
	--macro-muted: #ae939a;
	/* ⚠️ Тёмная пара к акценту #8b1d35 — тот же цвет, только светлее:
	   hue 347°, saturation 65 %, светлота 33 % → 51 % → 73 %.
	   Значения подобраны замером, а не на глаз (07.09.2026).

	   --macro-accent #d33154 — ЗАЛИВКА. Окно её светлоты — СТЕНА, а не
	     рекомендация: белый текст на заливке требует Y ≤ 0.1833 (4.5), а отрыв
	     заливки от поверхности требует Y ≥ 3·(Y_surface + 0.05) − 0.05.
	     На поверхности #3e1b27 (Y = 0.019545) это Y ≥ 0.158635, то есть окно
	     [0.158635 … 0.183333], ШИРИНОЙ 0.0247. У #d33154 Y = 0.16686 — стоит
	     на 33 % глубины окна, а не впритык к потолку, как стоял изумруд.
	     ⚠️ Окно стало ШИРЕ в 2.15 раза (было 0.0115) — но не потому, что
	     бордовый удачнее, а потому, что рампа опущена на ступень (см. шапку
	     блока). Это и есть выигрыш, ради которого от неё отказались:
	     самая больная цифра изумрудной схемы — белый на заливке активной
	     вкладки 4.57 с запасом 1.6 % — стала 4.84 с запасом 7.6 %.
	     Следствия, которые нельзя обойти:
	       • второй ступени заливки (hover/active) в тёмной теме ВСЁ РАВНО НЕ
	         СУЩЕСТВУЕТ: 0.0247 по Y на такой светлоте — меньше одной различимой
	         ступени. Hover/active выражаются рамкой (--macro-line-strong),
	         цветом текста (--macro-accent-text) и кольцом фокуса. Заливка
	         постоянна — пары --macro-accent-hover / --macro-accent-active
	         тут нет намеренно;
	       • поверхность нельзя осветлять выше Y = 0.022285, иначе заливка
	         теряет 3:1. #3e1b27 = 0.019545, запас 14 %. Отрыв заливки от
	         поверхности сейчас 3.12 при пороге 3.0 — ВТОРАЯ по узости цифра
	         схемы после знака в шапке;
	       • заливку нельзя осветлять выше Y = 0.1833: на 4.5 к белому сидит
	         подпись активной вкладки ленты (.cases-tab.is-active) — см. её
	         типографику и разбор в cases-grid.css.

	   --macro-accent-text #e78da1 — ТЕКСТОВАЯ светлота (ссылки тёмной темы,
	     .text-primary/.link-primary, кольцо фокуса вне кейса): к фону 7.49,
	     к поверхности 6.27 (у изумруда было 8.51 / 7.03 — просело, но обе
	     цифры остаются AAA). */
	--macro-accent: #d33154;
	--macro-accent-ink: #ffffff;
	--macro-accent-text: #e78da1;
	/* Одинаковы в обеих темах — объявлены на :root, здесь не переопределяются:
	   --macro-accent-bright (#d33154) и --macro-accent-onmedia (#e78da1). */
	--macro-danger-text: #5a95ed;
	--macro-warn-text: #e8b168;

	--macro-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35);
	--macro-shadow-md: 0 3px 10px rgba(0, 0, 0, 0.45);
	--macro-shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);

	/* --- перекладка на Bootstrap ---
	   Плагин красит страницу так: body bg = var(--bs-gray-dark),
	   body color = var(--bs-light), вторичные поверхности = var(--bs-dark).
	   Поэтому именно эти три переменные несут soft / ink / surface. */
	--bs-gray-dark: var(--macro-soft);
	--bs-light: var(--macro-ink);
	--bs-light-rgb: 242, 232, 235;
	--bs-dark: var(--macro-surface);
	--bs-dark-rgb: 62, 27, 39;

	--bs-body-bg: var(--macro-soft);
	--bs-body-bg-rgb: 37, 16, 23;
	--bs-body-color: var(--macro-ink);
	--bs-body-color-rgb: 242, 232, 235;

	--bs-primary: var(--macro-accent);
	/* ⚠️ Здесь до 01.09.2026 жил живой баг: --bs-primary уже был перекрашен,
	   а его rgb-двойник оставался синим (62, 107, 196). Всё, что в BS 5.1 идёт
	   через rgba(var(--bs-primary-rgb), α), в тёмной теме рисовалось синим —
	   в частности тень карточки кейса на hover (cases-grid.css). Держать эти
	   два значения синхронно обязательно: var() в rgb-двойник не подставишь,
	   он раскладывается по каналам. */
	--bs-primary-rgb: 211, 49, 84;
	--bs-secondary: var(--macro-ink2);
	--bs-secondary-rgb: 211, 187, 193;
	--bs-danger: var(--macro-danger-text);
	--bs-danger-rgb: 90, 149, 237;
	--bs-warning: var(--macro-warn-text);
	--bs-warning-rgb: 232, 177, 104;

	/* Серая шкала переворачивается в бордовую рампу: 100 — самый светлый
	   (текст), 900 — фон страницы. Плагин берёт gray-600 для рамок полей,
	   gray-700 для рамок тостов/таблиц — попадают в border/surface. */
	--bs-gray-100: var(--macro-ink);
	--bs-gray-200: var(--macro-ink2);
	--bs-gray-300: var(--macro-muted);
	--bs-gray-400: #8e767c;
	--bs-gray-500: #6b575c;
	--bs-gray-600: var(--macro-border);
	--bs-gray-700: var(--macro-surface);
	--bs-gray-800: var(--macro-soft2);
	--bs-gray-900: var(--macro-soft);
	--bs-gray: var(--macro-border);
}

/* Ссылки: в BS 5.1 у `a` литеральный hex, а не var(). После смены акцента
   07.09.2026 там лежит #8b1d35 (= light-accent) — собранный bootstrap.min.css
   ПЕРЕСОБРАН из SCSS компилятором темы (bootscore-main/inc/scssphp/), а не
   правлен вручную; методика в site/docs/macro-brand.md. */
/* :not(.case-card__link) — заголовки карточек кейсов остаются белыми
   поверх обложки. Цепочка :not() накручивает специфичность до (0,5,1),
   отдельным правилом .dark-theme .case-card__link её не перебить. */
.dark-theme a:not(.btn):not(.page-link):not(.nav-link):not(.dropdown-item):not(.case-card__link) {
	color: var(--macro-accent-text);
}

.dark-theme .text-primary,
.dark-theme .link-primary {
	color: var(--macro-accent-text) !important;
}

.dark-theme .text-secondary {
	color: var(--macro-ink2) !important;
}

.dark-theme .text-muted {
	color: var(--macro-muted) !important;
}

/* Рамки: BS 5.1 держит литеральный #D9DADB */
.dark-theme .border,
.dark-theme .border-top,
.dark-theme .border-end,
.dark-theme .border-bottom,
.dark-theme .border-start {
	border-color: var(--macro-border) !important;
}

/* Поверхности */
.dark-theme .card {
	background-color: var(--macro-surface) !important;
	border-color: var(--macro-border) !important;
	box-shadow: var(--macro-shadow-md) !important;
}

.dark-theme .accordion-item,
.dark-theme .accordion-button,
.dark-theme .list-group-item,
.dark-theme .offcanvas,
.dark-theme .modal-content,
.dark-theme .dropdown-menu,
.dark-theme .toast {
	background-color: var(--macro-surface);
	border-color: var(--macro-border);
}

.dark-theme .bg-light,
.dark-theme .bg-white {
	background-color: var(--macro-surface) !important;
}

.dark-theme .bg-trans-dark,
.dark-theme .bg-opacity-dark {
	background-color: var(--macro-soft2);
}

/* Кнопки в тёмной теме отдельными правилами больше не красятся: они, как и
   всё остальное, идут через контекстную палитру — см. раздел «КНОПКИ» ниже.
   Прежний блок (в т.ч. хардкод #5580d4 на hover) снят 2026-08-19. */

/* Прочие литеральные вхождения primary в собранном CSS */
.dark-theme .form-check-input:checked,
.dark-theme .progress-bar,
.dark-theme .nav-pills .nav-link.active,
.dark-theme .nav-pills .show > .nav-link,
.dark-theme .dropdown-item.active,
.dark-theme .dropdown-item:active {
	background-color: var(--macro-accent);
	border-color: var(--macro-accent);
}

/* Формы */
.dark-theme .form-control,
.dark-theme .form-select,
.dark-theme .form-check-input:not(:checked) {
	background-color: var(--macro-soft2);
	/* Не --macro-border (1.35 к поверхности — провал 1.4.11), а линия контрола:
	   5.20 к поверхности, 6.30 к фону. */
	border-color: var(--macro-line-strong);
	color: var(--macro-ink);
}

.dark-theme .form-control:focus,
.dark-theme .form-select:focus {
	background-color: var(--macro-soft2);
	border-color: var(--macro-accent);
	box-shadow: 0 0 0 0.25rem rgba(231, 141, 161, 0.30);
}

.dark-theme .form-control::placeholder {
	color: var(--macro-muted);
}

/* Светлые заливки статусов в тёмной теме — текст на них должен быть тёмным */
.dark-theme .bg-danger,
.dark-theme .bg-warning {
	color: var(--macro-soft) !important;
}

/* Скроллбар: отдельной тёмной ветки БОЛЬШЕ НЕТ — полосы прокрутки целиком
   переведены на токены --scroll-* (см. блок «ПОЛОСЫ ПРОКРУТКИ» выше), а те
   объявлены на body и потому уже знают про тему.
   ⚠️ Правила, стоявшие здесь, снесены не «для порядка», а по замеру:
     • бегунок был --macro-accent (#d33154) — 2.90 к треку, провал 1.4.11
       для графики (порог 3.0). Теперь --macro-accent-text (#e78da1), 5.84;
     • трек был --macro-soft2 (#341620) — сплошная ступень рампы, из-за неё
       на плитках и в модалах полоса рисовалась темнее собственной подложки.
       Теперь доля контекстного текста, как в светлой. */

/* Cookie-баннер: был свой хардкод под старую тёмную тему */
.dark-theme .cookie_bg {
	background: rgba(37, 16, 23, 0.92);
}


/* ============================================================
   Страница кейса (шаблон плагина bs-isotope-main/templates/cpt-single.php).
   Шаблон грузится жёстким путём через фильтр single_template, переопределить
   его из темы нельзя — поэтому правим внешний вид только стилями.
   ============================================================ */

/* Подложка заголовка hero — СПЛОШНАЯ плашка, а не мягкое пятно.
   Было: радиальный градиент с зашитым rgba(15,26,48,…) (тёмно-синий общей
   темы). Он не имел отношения к палитре кейса и на светлой/пёстрой обложке
   читался как грязь.

   Стало: плотный прямоугольник цвета САМОГО кейса. Цвет и контрастный к нему
   цвет текста приезжают переменными --case-color / --case-ink, их считает
   header.php по ACF-полям isotope_background_light|dark (яркость по WCAG,
   порог 0.18) — то есть результат предсказуем при любом выборе автора, хоть
   почти белом, хоть почти чёрном. Фолбэк на случай, если поля пустые: тёмная
   поверхность общей темы. */
.hero_title {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	/* Ширина — та же мера, что у текста на странице кейса (--case-col, 736px).
	   Отдельного числа для hero не заводим: мер ровно три. */
	max-width: var(--case-col);
	margin-inline: auto;
	padding: 1.75rem 1.5rem;
	border-radius: var(--case-radius);
	background-color: var(--case-color);
	color: var(--case-ink);
	box-shadow: var(--macro-shadow-lg);
}

/* Canvas «цифрового дождя» (js/custom.js) — фоновый слой плашки: лежит под
   текстом, кликов не ловит, скринридеру не виден. Без JS/при ошибке canvas
   элемент просто не создаётся, плашка остаётся как есть. */
.hero_title .case-hero-rain {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: block;
	width: 100%;
	height: 100%;
	border-radius: inherit;
	pointer-events: none;
}

.hero_title > *:not(.case-hero-rain) {
	position: relative;
	z-index: 1;
}

/* Заголовок и подзаголовок наследуют --case-ink: на плашке цвет всегда
   контрастный, а .text-light/.text-* с родителя тут только мешали.
   Тени текста сняты: по сплошному фону они не нужны и мылят шрифт. */
.hero_title h1,
.hero_title .excerpt p {
	color: inherit;
	text-shadow: none;
}

.hero_title h1 {
	/* Потолок снижен с 5rem: плашка сузилась до --case-col, и длинное название
	   («Корпоративный портал застройщика …») уезжало в пять строк на 736px. */
	font-size: clamp(2rem, 4.6vw, 3.75rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
	margin-bottom: 0;
	text-wrap: balance;
	overflow-wrap: break-word;
	hyphens: auto;
}

.hero_title .excerpt {
	max-width: 42ch;
}

.hero_title .excerpt p {
	margin-bottom: 0;
	font-weight: 500;
	opacity: 0.85;
}

/* На мобилке плашка не должна упираться в края экрана — тот же отступ,
   что у контейнера кейсов. */
@media (max-width: 767.98px) {
	.hero_title {
		margin-left: var(--case-pad);
		margin-right: var(--case-pad);
	}
}

@media (min-width: 768px) {
	.hero_title {
		padding: 2.5rem 2.75rem;
	}

	.hero_title .excerpt p {
		font-size: 1.125rem;
	}
}

/* «Смотреть далее»: previous_post_link/next_post_link при отсутствии
   соседних кейсов не выводят ничего, оставался заголовок и пустая
   пагинация. Прячем блок целиком, когда в нём нет ни одной ссылки. */
.bottom_nav:not(:has(.page-item a)) {
	display: none;
}

/* :empty не сработает — внутри li остаются переводы строк из шаблона */
.bottom_nav .page-item:not(:has(a)) {
	display: none;
}

/* ============================================================
   ГЕОМЕТРИЯ ОСНОВНОГО КОНТЕЙНЕРА
   Правила самой сетки кейсов переехали в блок
   plugins/easy-acf-blocks-main/acf-blocks/cases-grid/cases-grid.css
   (главная рендерится блоком acf/cases-grid, копия в теме удалена
   2026-08-19 — источник правды один).

   Здесь остались только переменные: их используют не только карточки,
   но и фиксированные контролы (.top-controls), cookie-карточка и плашка
   hero на странице кейса — всё это живёт вне блока.
   ============================================================ */

/* Геометрия основного контейнера. Объявлена на :root, а не на .cases-section:
   те же величины нужны переключателю темы (он в header.php, вне секции), чтобы
   его левый край совпадал с левым краем заголовка и первой карточки.
   ЕДИНСТВЕННОЕ место, где эти числа заданы, — не дублировать. */
:root {
	--case-pad: clamp(1rem, 4.5vw, 6rem);
	--case-max: 2000px;
	--case-radius: 1.25rem;

	/* Три меры ширины страницы кейса (ТЗ tz-case-page.md §2). Объявлены на
	   :root, а не на .case-page: ими же меряется плашка заголовка в hero,
	   а она лежит выше .case-page. Числа заданы ЗДЕСЬ и больше нигде. */
	--case-col: min(100%, 46rem);    /* 736px — текст, ~68 знаков в строке */
	--case-wide: min(100%, 72rem);   /* 1152px — сплит, галереи, факты, отзыв */
	--case-full: min(100%, 100rem);  /* 1600px — широкое медиа */
}

@media (min-width: 768px) {
	:root {
		--case-radius: 1.5rem;
	}
}


/* ============================================================
   СОСЕДНИЕ КЕЙСЫ — навигация внизу single-страницы (бывш. «Смотреть далее»)

   Разметка: themes/bootcommerce-child-main/bs-isotope-main/cpt-single.php
   (копия шаблона плагина, её подставляет фильтр single_template в
   functions.php). Стороны опознаём по классам .case-nav__item--prev/--next,
   а не по rel: класс приходит из нашей разметки и не зависит от того, что
   WP считает «предыдущим» по дате.

   Было: пара крупных плиток-карточек (радиус --case-radius, поверхность,
   тень, подписи через ::before) — низ страницы перевешивал.
   Стало: компактная строка-«футер раздела»: тонкая линейка сверху и две
   текстовые ссылки со стрелками. Ни фона, ни рамок, ни теней — вес держат
   только типографика и контекстный цвет (--ctx-*), поэтому блок одинаково
   живёт и на главной палитре, и на палитре кейса, в обеих темах.
   Видимой подписи над парой больше нет (см. .case-nav__caption ниже): её
   типографическую роль взяли на себя .case-nav__label внутри ссылок.

   Тап-таргет — min-height 44px на самой ссылке (визуальная высота меньше,
   область нажатия — нет).
   ============================================================ */

.bottom_nav {
	max-width: none;
	width: 100%;
	margin-top: clamp(2rem, 4vw, 3rem);
	/* Чуть больше воздуха под линейкой, чем было при видимой подписи: теперь
	   первым идёт .case-nav__label, и без этого запаса он «прилипал» к линии.
	   Даже с прибавкой блок ниже прежнего — подпись занимала ~13px. */
	padding-top: clamp(0.875rem, 1.6vw, 1.25rem);
	border-top: 1px solid var(--ctx-border);
}

/* пунктирные боковины из старого оформления */
.bottom_nav::before {
	content: none;
}

/* Видимой подписи раздела больше нет. h2 «Смотреть далее» остался в разметке
   с .visually-hidden — только для скринридеров и структуры документа (так же
   оформлены navigation-блоки ядра WP). Причина: капсом-подпись стояла ТРЕТЬЕЙ
   микро-строкой над двумя точно такими же («ПРЕДЫДУЩИЙ КЕЙС» / «СЛЕДУЮЩИЙ
   КЕЙС»), дублировала их смысл и на глаз читалась как наложение строк.
   Типографический слой «мелкая подпись сразу под линейкой» никуда не делся —
   его держат .case-nav__label, поэтому композиция без h2 не разваливается.
   Своих правил у .case-nav__caption нет намеренно: любое font-size/margin
   поверх .visually-hidden — мусор. */

/* Пара ссылок. flex:1 1 0 вместо grid: когда сосед один, оставшаяся ссылка
   занимает всю ширину и остаётся у своего края — ни дыры, ни съезда в центр
   (у «следующего» край правый, поэтому его li выравнивает содержимое вправо). */
.bottom_nav .case-nav__list {
	display: flex !important;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between !important;
	gap: 0 clamp(1rem, 3vw, 2.5rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.bottom_nav .case-nav__item {
	display: flex;
	flex: 1 1 0;
	min-width: 0;
	font-size: 1rem !important;
	text-transform: none !important;
}

.bottom_nav .case-nav__item--next {
	justify-content: flex-end;
}

.bottom_nav .case-nav__link {
	display: inline-flex;
	align-items: center;
	gap: 0.625rem;
	max-width: 100%;
	min-height: 44px;
	padding: 0.25rem 0;
	border: 0;
	border-radius: 0.5rem;
	background-color: transparent;
	box-shadow: none;
	color: var(--ctx-ink);
	text-decoration: none;
	touch-action: manipulation;
	transition: color 0.25s ease;
}

/* Стрелка — единственный «графический» элемент, отсюда и направление */
.bottom_nav .case-nav__arrow {
	flex: 0 0 auto;
	font-size: 1.125rem;
	line-height: 1;
	color: var(--ctx-muted);
	transition: color 0.25s ease, transform 0.25s ease;
}

.bottom_nav .case-nav__text {
	display: flex;
	flex-direction: column;
	gap: 0.0625rem;
	min-width: 0;
}

.bottom_nav .case-nav__label {
	font-size: 0.6875rem;
	font-weight: 500;
	line-height: 1.2;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--ctx-muted);
	transition: color 0.25s ease;
}

/* Одна строка: длинные названия кейсов режем многоточием, иначе высота
   блока скачет от кейса к кейсу и «компактно» кончается. */
.bottom_nav .case-nav__name {
	display: block;
	max-width: 100%;
	overflow: hidden;
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1.3;
	white-space: nowrap;
	text-overflow: ellipsis;
}

@media (min-width: 992px) {
	.bottom_nav .case-nav__name {
		font-size: 1.0625rem;
	}
}

/* «Следующий» зеркалим: стрелка справа, текст прижат к правому краю —
   пара читается как «туда/сюда» */
.bottom_nav .case-nav__item--next .case-nav__link {
	flex-direction: row-reverse;
	text-align: right;
}

.bottom_nav .case-nav__item--next .case-nav__text {
	align-items: flex-end;
}

/* Чужие стрелки-кавычки у ссылок пагинации («…») — дублируют наши */
.bottom_nav .case-nav__link::before,
.bottom_nav .case-nav__link::after {
	content: none;
}

@media (hover: hover) and (pointer: fine) {
	.bottom_nav .case-nav__link:hover .case-nav__arrow,
	.bottom_nav .case-nav__link:hover .case-nav__label {
		color: var(--ctx-accent);
	}

	.bottom_nav .case-nav__link:hover .case-nav__name {
		text-decoration: underline;
		text-underline-offset: 0.25em;
		text-decoration-thickness: 1px;
	}

	.bottom_nav .case-nav__item--prev .case-nav__link:hover .case-nav__arrow {
		transform: translateX(-3px);
	}

	.bottom_nav .case-nav__item--next .case-nav__link:hover .case-nav__arrow {
		transform: translateX(3px);
	}
}

/* Кольцо — из общей системы фокуса (раздел «ФОКУС С КЛАВИАТУРЫ»). Раньше тут
   стоял точечный !important против заглушки родителя — заглушка снята
   централизованно, точечный перебив убран. Своё — только отступ: ссылка
   занимает половину строки, кольцу нужен воздух. */
.bottom_nav .case-nav__link:focus-visible {
	outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
	.bottom_nav .case-nav__link,
	.bottom_nav .case-nav__arrow,
	.bottom_nav .case-nav__label {
		transition: none;
	}

	.bottom_nav .case-nav__link:hover .case-nav__arrow {
		transform: none;
	}
}

/* До 768 — в столбик: две ссылки в строку упираются в многоточие уже на
   первом слове.

   Обе строки строятся одинаково: [стрелка][текст]. Раньше «следующий»
   зеркалился и на мобилке (row-reverse + space-between, стрелка у правого
   края) — из-за этого его текст начинался от края экрана, а текст
   «предыдущего» был сдвинут на ширину стрелки: левый край пары рвался.
   Заметно это стало после снятия видимой подписи, поэтому зеркалим только
   на десктопе, где ссылки стоят в РАЗНЫХ половинах строки и зеркало
   осмысленно. На мобилке они друг под другом — направление держит сам
   глиф (← / →), а не позиция, и стрелки выстраиваются в одну колонку.

   Колонка стрелок фиксированной ширины: ← и → в Roboto Mono одной ширины
   не гарантированы, а разница в пару пикселей — тот же рваный край. */
@media (max-width: 767.98px) {
	.bottom_nav .case-nav__list {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
	}

	.bottom_nav .case-nav__item {
		flex: 0 0 auto;
		width: 100%;
	}

	.bottom_nav .case-nav__item + .case-nav__item {
		border-top: 1px solid var(--ctx-border);
	}

	.bottom_nav .case-nav__link {
		width: 100%;
	}

	/* отменяем десктопное зеркало */
	.bottom_nav .case-nav__item--next .case-nav__link {
		flex-direction: row;
		justify-content: flex-start;
		text-align: left;
	}

	.bottom_nav .case-nav__item--next .case-nav__text {
		align-items: flex-start;
	}

	.bottom_nav .case-nav__arrow {
		width: 1.125rem;
		text-align: center;
	}
}

/* Цвет тянется из контекстной палитры. !important — против общего
   .dark-theme a:not(.btn):not(.page-link)… (0,5,1), обычным правилом
   его не перебить: заголовок соседнего кейса красился в голубой. */
.dark-theme .bottom_nav .page-item a,
.dark-theme .bottom_nav .page-item a:hover,
.dark-theme .bottom_nav .page-item a:focus,
.single-isotope .bottom_nav .page-item a {
	color: var(--ctx-ink) !important;
}


/* ============================================================
   COOKIE-СОГЛАСИЕ — компактная карточка вместо полосы
   Разметка: override шаблона плагина (themes/…/bs-cookie-consent-main/
   cookie-consent.php). Согласие оставляем как есть по смыслу, меняем подачу:
   полноширинная полоса .bg-light py-3 накрывала низ первого экрана и первую
   карточку кейса. Теперь — карточка в левом нижнем углу, по той же вертикали
   --case-pad, что и остальной контент.

   display НЕ трогаем: скрытие/показ делает JS плагина (display:block на
   .cookies-accept, fadeOut по кнопке). Поэтому раскладка внутри — на flex-wrap
   у потомков, а не на display самого блока.
   ============================================================ */

.cookie-card {
	position: fixed;
	left: var(--case-pad);
	left: max(var(--case-pad), calc((100% - var(--case-max)) / 2));
	bottom: clamp(1rem, 2.5vw, 1.5rem);
	width: min(26rem, calc(100% - 2 * var(--case-pad)));
	padding: 1rem 1.125rem;
	border: 1px solid var(--ctx-border);
	border-radius: var(--case-radius);
	background-color: var(--ctx-surface);
	box-shadow: var(--macro-shadow-lg);
	color: var(--ctx-ink);
}

.cookie-card__text {
	margin: 0 0 0.75rem;
	font-size: 0.875rem;
	line-height: 1.45;
	color: var(--ctx-muted);
}

.cookie-card .privacylink {
	color: var(--ctx-accent);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.cookie-card__accept {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 0 1.25rem;
	border: 1px solid var(--ctx-accent);
	border-radius: 999px;
	background-color: var(--ctx-accent);
	color: var(--ctx-on-accent);
	font-family: inherit;
	/* Тот же случай, что подпись активной вкладки: белый на заливке акцента
	   даёт в тёмной теме 4.57 при пороге 4.5. 15 px / 600 крупным текстом по
	   WCAG 1.4.3 НЕ считается (нужно ≥18.66 px при 700), поэтому кегль и вес
	   подняты — 17 px / 700 переводит подпись в режим, где порог 3.0.
	   Цвет при этом не двигается: окно светлоты заливки в тёмной теме забито
	   целиком, разбор — блок «ТЁМНАЯ ТЕМА». */
	font-size: 1.0625rem;
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
	touch-action: manipulation;
	transition: box-shadow 0.3s ease, filter 0.3s ease;
}

@media (hover: hover) and (pointer: fine) {
	.cookie-card__accept:hover {
		box-shadow: var(--macro-shadow-md);
		filter: brightness(1.08);
	}
}


@media (prefers-reduced-motion: reduce) {
	.cookie-card__accept {
		transition: none;
	}
}


/* ============================================================
   СТРАНИЦА КЕЙСА — система блоков
   ТЗ: site/docs/tz/tz-case-page.md. Разметка — шаблон темы
   bs-isotope-main/cpt-single.php (#main_content.case-page,
   .entry-content.case-body), подменяется фильтром single_template.

   Идея в трёх фразах:
   1) ширины НЕ задаются в контенте — есть ровно три меры;
   2) отступы НЕ задаются в контенте — есть один вертикальный шаг;
   3) цвет кейса раскрывается в набор токенов, всё остальное одинаково.
   ============================================================ */

.case-page {
	/* Три меры ширины (§2) объявлены на :root — см. блок «ГЕОМЕТРИЯ
	   ОСНОВНОГО КОНТЕЙНЕРА» выше. Четвёртой меры не существует. */

	/* --- Один вертикальный ритм (§3) --- */
	--case-rhythm: clamp(2.75rem, 6vw, 5rem);
	--case-rhythm-lg: clamp(4.5rem, 9vw, 8rem);
	--case-gap: clamp(1rem, 2.2vw, 2rem);

	/* Потолок высоты кадра в рядах case-split / case-gallery (§6). Нужен
	   портретным скриншотам: мобильная версия снимается в каждом кейсе, а по
	   ширине колонки такой кадр вырастает на пол-экрана. На case-media /
	   case-media--full НЕ распространяется — там кадр обязан занимать свою
	   меру целиком, см. комментарий у правил медиа ниже. */
	--case-media-max-h: min(70vh, 40rem);

	/* --- Токены цвета кейса (§4) ---
	   Выводятся из контекстной палитры (--ctx-*), а не считаются параллельно:
	   на странице кейса --ctx-accent = противоположный по светлоте цвет кейса,
	   и он же меняется при переключении темы. Своего источника цвета здесь нет. */
	--case-accent-text: var(--ctx-accent);
	--case-line: var(--ctx-border);
	--case-tint: color-mix(in srgb, var(--ctx-accent) 8%, var(--ctx-surface));
	--case-border: var(--ctx-border);
	--case-bar: var(--ctx-accent);

	padding-inline: var(--case-pad);
	padding-block: var(--case-rhythm) var(--case-rhythm-lg);
	overflow-x: clip; /* страховка от широких медиа/эмбедов */
}

/* Тёмная тема отрабатывает сама: header.php отдаёт свою пару
   --case-color / --case-rain для body.dark-theme, а --ctx-* собраны из неё.
   Отдельной тёмной ветки здесь не нужно. */

/* Плоский фолбэк там, где нет color-mix */
@supports not (color: color-mix(in srgb, red, blue)) {
	.case-page {
		--case-tint: var(--ctx-surface);
	}
}


/* --- Слой нормализации (§7, шаг 1) ---
   Чинит старую разметку (Aukids: 3+5 · 5+4 · 8 · 4+6 …) без единой правки
   контента: ширины и вертикальные утилиты из контента перестают действовать,
   ряд получает меру по своему содержимому. :has() в проекте уже используется. */

.case-body {
	counter-reset: case-sec;
}

/* display: grid !important — ряды из старого контента несут утилиту .d-flex
   (Bootstrap задаёт её через !important). Без !important ряд оставался флексом,
   grid-template-columns не действовали, а колонки с width:auto растягивались
   по содержимому и вылезали за пределы страницы (в Aukids до -246px).

   ⚠️ ПРИОРИТЕТ ТИПА НАД АВТООПРЕДЕЛЕНИЕМ (правило системы, не трогать)
   Мера и раскладка ряда НЕ задаются здесь напрямую — они читаются из пары
   независимых токенов:
       --case-measure / --case-cols / --case-align       ← тип ряда (§5)
       --case-measure-auto / --case-cols-auto / …-auto   ← слой нормализации (§7)
   var() берёт первый ОПРЕДЕЛЁННЫЙ токен, и это разные свойства — значит
   специфичность селекторов больше не решает, кто победил. Раньше решала:
   `.row:has(> [class*="col"]:only-child)` (0,4,0) перебивал `.row.case-media--full`
   (0,3,0), и полноширинный кадр рендерился в 736px вместо 1600.
   Следствия, на которые можно опираться:
   • типизированный ряд ВСЕГДА выигрывает у нормализации — независимо от порядка
     правил и от того, сколько :has() навесит нормализация дальше;
   • десятый тип не ломает систему: объявил --case-measure — работает; не объявил —
     тихо падает в автоопределение по содержимому, как безымянный ряд из контента. */
.case-body > .row {
	display: grid !important;
	grid-template-columns: var(--case-cols, var(--case-cols-auto, 1fr));
	align-items: var(--case-align, var(--case-align-auto, stretch));
	gap: var(--case-gap);
	max-width: var(--case-measure, var(--case-measure-auto, var(--case-wide)));
	margin-inline: auto;
}

/* Токены раскладки наследуются, а внутри колонок встречаются вложенные .row
   (Aukids). Сбрасываем на колонке, чтобы вложенный ряд не унаследовал меру
   родителя. `initial` для custom property = «значение не задано» → var()
   уходит в свой фолбэк. */
.case-body [class*="col"] {
	--case-measure: initial;
	--case-measure-auto: initial;
	--case-cols: initial;
	--case-cols-auto: initial;
	--case-align: initial;
	--case-align-auto: initial;
}

.case-body > .row > [class*="col"] {
	width: auto !important;
	max-width: none;
	min-width: 0; /* иначе длинная строка распирает грид-трек */
	flex: none;
	/* горизонтальные гаттеры Bootstrap заменены нашим gap */
	padding-left: 0;
	padding-right: 0;
	padding-top: 0 !important;
	padding-bottom: 0 !important;
	margin-top: 0;
	margin-bottom: 0;
}

/* Колонки из контента с .d-flex сжимали блочное содержимое до ширины его текста
   (на 768 «Для тех, кому интересен сайт» вставал на 215px вместо 35) — внутри
   нормализованной сетки колонка и так занимает трек целиком, флекс ей не нужен. */
.case-body .row > [class*="col"].d-flex {
	display: block !important;
}

/* …но намерение автора «по центру» при этом терять нельзя: колонка, которая
   просила центрирование флексом, получает его текстовым выравниванием.
   Разница принципиальная: text-align центрирует содержимое, НЕ сжимая блоки,
   поэтому левая линия абзацев остаётся единой, а кнопка/подпись стоят по центру.
   Без этого правила CTA «На сайт!» уезжала влево. */
.case-body .row > [class*="col"].justify-content-center,
.case-body .row > [class*="col"].text-center {
	text-align: center;
}

/* Внутренние обёртки из контента (div.p-2, div.ps-3, div.px-*) добавляли
   свои горизонтальные отступы, и на мобилке текст вставал на 8px правее
   заголовков и картинок. Гасим горизонтальные паддинги у любых служебных
   обёрток внутри колонок — вертикальные не трогаем, ритм держит .case-body. */
.case-body .row [class*="col"] div[class*="p-"],
.case-body .row [class*="col"] div[class*="px-"],
.case-body .row [class*="col"] div[class*="ps-"],
.case-body .row [class*="col"] div[class*="pe-"] {
	padding-left: 0 !important;
	padding-right: 0 !important;
}

/* Встроенные ACF-секции нормализуем той же логикой: их внутренние ряды
   тоже становятся гридом по общей мере, иначе на 768 они давали свои
   левые края (215px, 155px) вместо единой линии.

   ⚠️ ЛЕЧЕНИЕ, А НЕ ЗАКОН. Нормализация чинит ЧУЖИЕ блоки — те, что верстались
   под другие страницы и о мерах кейса не знают. Блок, сделанный ПОД эту
   страницу, лечить не нужно и вредно: правило ниже ломает любую сетку сложнее
   одной колонки (display: grid !important + обнуление гаттеров Bootstrap).
   Такой блок помечает себя классом `case-native` на своей секции и выходит
   из нормализации целиком — дальше он отвечает за меру и раскладку сам,
   пользуясь общими токенами (--case-col / --case-wide / --case-gap / --ctx-*).
   Первым это использует блок case-facts-grid (плитки фактов, 2–4 колонки).
   Общую меру и снятие вертикальных паддингов (`.case-body > section` ниже)
   метка НЕ отменяет — единая ось страницы обязательна для всех. */
.case-body > section:not(.case-native) .row {
	display: grid !important;
	grid-template-columns: 1fr;
	gap: var(--case-gap);
	margin-inline: 0;
}

.case-body > section:not(.case-native) .row > [class*="col"] {
	width: auto !important;
	max-width: none;
	min-width: 0;
	flex: none;
	padding-left: 0 !important;
	padding-right: 0 !important;
}

@media (min-width: 992px) {
	.case-body > section:not(.case-native) .row:has(> [class*="col"]:nth-child(2)) {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		align-items: center;
	}
}

/* Автоопределение пишет ТОЛЬКО в *-auto-токены (см. базовое правило ряда):
   это догадка по содержимому для рядов без класса, и она обязана уступать
   явному типу, какой бы специфичности ни набрал селектор с :has().

   Одиночная колонка = текст → узкая мера. Если внутри неё только медиа —
   мера широкая, иначе скриншот сжимался до ширины абзаца. */
.case-body > .row:has(> [class*="col"]:only-child) {
	--case-measure-auto: var(--case-col);
}

.case-body > .row:has(> [class*="col"]:only-child:has(> figure:only-child)),
.case-body > .row:has(> [class*="col"]:only-child:has(> .wp-block-image:only-child)),
.case-body > .row:has(> [class*="col"]:only-child:has(> .wp-block-embed:only-child)) {
	--case-measure-auto: var(--case-wide);
}

@media (min-width: 992px) {
	.case-body > .row:has(> [class*="col"]:nth-child(2)) {
		--case-cols-auto: repeat(2, minmax(0, 1fr));
		--case-align-auto: center;
	}

	.case-body > .row:has(> [class*="col"]:nth-child(3)) {
		--case-cols-auto: repeat(3, minmax(0, 1fr));
		--case-align-auto: start;
	}

	.case-body > .row:has(> [class*="col"]:nth-child(4)) {
		--case-cols-auto: repeat(4, minmax(0, 1fr));
		--case-align-auto: start;
	}
}


/* --- Вертикальный ритм (§3) --- */

.case-body > * + * {
	margin-top: var(--case-rhythm);
}

.case-body > .case-head {
	margin-top: var(--case-rhythm-lg);
}

.case-body > *:first-child {
	margin-top: 0;
}

/* Заголовок и его первый абзац живут ближе друг к другу */
.case-body h2 + *,
.case-body h3 + * {
	margin-top: var(--case-gap);
}

.case-body figure,
.case-body p:last-child,
.case-body ul:last-child,
.case-body ol:last-child {
	margin-bottom: 0;
}


/* --- Типографика (§5.2) ---
   Глобальный --bs-body-line-height: 1.2 для лонгрида не годится. */

.case-body p,
.case-body li {
	font-size: clamp(1rem, 1.1vw, 1.125rem);
	line-height: 1.65;
	color: var(--ctx-ink);
}

.case-body p {
	margin-bottom: var(--case-gap);
}

.case-body h2 {
	font-size: clamp(1.75rem, 3.4vw, 3rem);
	font-weight: 700;
	line-height: 1.08;
	letter-spacing: -0.02em;
	color: var(--ctx-ink);
	margin-bottom: 0;
}

.case-body h3 {
	font-size: clamp(1.25rem, 2vw, 1.75rem);
	font-weight: 600;
	line-height: 1.2;
	color: var(--ctx-ink);
	margin-bottom: 0;
}

.case-body h4 {
	font-size: 1.125rem;
	font-weight: 600;
	color: var(--ctx-ink);
	margin-bottom: 0;
}

/* Автонумерация разделов (§6): kicker над каждым h2, ноль работы в контенте */
.case-body h2 {
	counter-increment: case-sec;
}

.case-body h2::before {
	content: counter(case-sec, decimal-leading-zero);
	display: block;
	margin-bottom: 0.5rem;
	font-size: 0.8125rem;
	font-weight: 500;
	line-height: 1;
	letter-spacing: 0.12em;
	color: var(--case-accent-text);
}

.case-body .case-head--nocount h2::before,
.case-body h2.case-head--nocount::before {
	content: none;
}

.case-body ul,
.case-body ol {
	padding-left: 1.25em;
	margin-bottom: var(--case-gap);
}

.case-body li + li {
	margin-top: 0.35rem;
}

.case-body ul li::marker {
	color: var(--case-accent-text);
}

.case-body a:not(.btn) {
	color: var(--ctx-ink);
	text-decoration: underline;
	text-decoration-color: var(--case-line);
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
	transition: color 0.25s ease, text-decoration-color 0.25s ease;
}

@media (hover: hover) and (pointer: fine) {
	.case-body a:not(.btn):hover {
		color: var(--case-accent-text);
		text-decoration-color: var(--case-accent-text);
	}
}

body.dark-theme .case-body a:not(.btn),
.single-isotope .case-body a:not(.btn) {
	color: var(--ctx-ink) !important; /* .dark-theme a:not()… — (0,5,1) */
}


/* --- Медиа (§6) --- */

.case-body figure {
	margin: 0;
}

.case-body figure img,
.case-body .wp-block-image img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--case-radius);
	border: 1px solid var(--case-border);
	box-shadow: var(--macro-shadow-sm);
}

/* Портретные кадры (мобильные скриншоты, ~780×1600).
   width: 100% растягивал их по ширине колонки: в сплите на 1440 такой кадр
   получался 560×1210 и съедал экран целиком, а на планшете ряд стекается —
   и кадр становился ещё шире. Правило общее (типизированные ряды), а не
   «по месту»: мобильная версия теперь есть в каждом кейсе.

   Механика: снимаем принудительную ширину и даём браузеру ДВА предела —
   max-width по колонке и max-height по высоте. Для заменяемых элементов он
   ужимает кадр по более жёсткому из них, сохраняя пропорции (CSS 2.1 §10.4).
   Портрет садится по высоте и центрируется, альбомный кадр не меняется:
   при ширине колонки его высота заведомо ниже потолка (у нынешних кейсов
   максимум 584px при потолке 640).

   Ширину подхватывает и figure (width: fit-content) — иначе подпись
   висела бы по всей колонке, оторвавшись от узкого кадра.

   Область действия — case-split и case-gallery, и это НЕ случайность:
   портретные кадры живут только там (в контенте сейчас 0.32 / 0.46 / 0.96).
   Ряды case-media / case-media--full сюда НЕ входят — это «широкое медиа»
   и «полноширинный кадр» (§5 ТЗ, всегда альбомные, 1.35–6.27), их смысл
   в том, чтобы занять свою меру целиком. Потолок высоты там резал кадр по
   70vh и делал --case-full неотличимым от --case-wide (на 1440 обе меры
   давали один и тот же кадр 1008×630), а рама переставала совпадать с левым
   краем меры — то есть ломалось требование ТЗ «ровно три левых края».
   Кадру в case-media достаётся базовое правило .case-body figure img
   (width: 100%, без max-height). Портрет в такой ряд не кладём — для него
   есть case-split / case-gallery. */
.case-body > .row.case-split figure,
.case-body > .row.case-gallery figure,
.case-body > .row.case-split .wp-block-image,
.case-body > .row.case-gallery .wp-block-image {
	width: fit-content;
	max-width: 100%;
	margin-inline: auto;
}

.case-body > .row.case-split figure img,
.case-body > .row.case-gallery figure img,
.case-body > .row.case-split .wp-block-image img,
.case-body > .row.case-gallery .wp-block-image img {
	width: auto;
	max-width: 100%;
	max-height: var(--case-media-max-h);
	margin-inline: auto;
}

/* Подпись не должна раздувать figure: её строка шире узкого портрета, и
   figure переставал обнимать кадр (подпись торчала левее). width: 0 убирает
   вклад подписи в ширину, min-width: 100% возвращает ей ширину кадра. */
.case-body > .row.case-split figcaption,
.case-body > .row.case-media figcaption,
.case-body > .row.case-gallery figcaption {
	width: 0;
	min-width: 100%;
}

.case-body figcaption,
.case-body .wp-block-image figcaption {
	margin-top: 0.625rem;
	font-size: 0.875rem;
	line-height: 1.45;
	color: var(--ctx-muted);
	text-align: left;
}

.case-body iframe,
.case-body video {
	display: block;
	width: 100%;
	border-radius: var(--case-radius);
	border: 1px solid var(--case-border);
}


/* --- 6b. ПЛАШКА ПОД ЗНАК (.case-brandmark) ---
   Компонент под ОДИН класс изображений — брендовые знаки/монограммы, залитые
   фирменным цветом внутри файла. Ставится классом на <figure>; больше на этой
   figure никаких утилит быть не должно (см. «Как применять» ниже).

   ⚠️ ЗАЧЕМ ОТДЕЛЬНЫЙ КОМПОНЕНТ, А НЕ bg-white + p-4
   Ровно эти две утилиты и стояли на плашках знаков в кейсе macro-global, и обе
   дали дефект:

   1) `bg-white` в тёмной теме БЕЛЫМ НЕ ЯВЛЯЕТСЯ. `.dark-theme .bg-white`
      уводит подложку на --macro-surface (#3e1b27), а знак свой #172747 не
      меняет — заливка лежит внутри SVG и теме не подчиняется. Замер: 1.02
      (на изумрудной поверхности #142F30 был 1.05 — вывод не изменился).
      ⚠️ То правило ПРАВИЛЬНОЕ и трогать его нельзя: белая плашка в тёмной теме
      действительно должна темнеть. Исключение нужно не «белым» вообще, а
      носителю знака — поэтому оно и оформлено отдельным классом, а не
      отменой общего правила.

   2) размера не было вовсе. Утилита фона размер не задаёт, а у файлов внутри
      стоит width="73" height="73"; правило галереи (`figure { width:
      fit-content }` + `img { width: auto }`) честно обняло эти 73px, и плашка
      схлопывалась в 123px внутри колонки 363px. Подпись при этом получала
      те же 75px (figcaption: `width: 0; min-width: 100%`) и ломалась посреди
      слова — «Бейдж MacroBroke / r».

   КАК УСТРОЕНО
   • Плашкой работает САМ <img>: фон, паддинг и радиус висят на нём, а знак
     вписывается внутрь через object-fit: contain. Отсюда сразу два свойства,
     ради которых это и сделано: высота плашки задаётся нами и одинакова у всех
     знаков ряда, а внутренние width/height файла на неё не влияют вообще —
     хоть 73×73, хоть 682×874.
   • Подпись остаётся СНАРУЖИ плашки, на фоне страницы. Это не косметика:
     figcaption красится в --ctx-muted, а он в тёмной теме светлый — на светлой
     плашке подпись стала бы нечитаемой. Плашка держит только знак.
   • Ширина — вся колонка, но не шире --brandmark-max-w: на стопке (до 576px и
     в узких рядах) знак иначе оказывается один посреди 700px пустой бумаги.

   ЦВЕТ — ТОКЕНАМИ, И ЭТО НЕ «ХАРДКОД #fff»
   --brandmark-plate = бумага (--macro-brand-paper) + 8 % цвета страницы кейса
   (--ctx-page). Светлота остаётся бумажной в обеих темах, но подтон приезжает
   из палитры записи, поэтому плашка не спорит с ней:
     • светлая тема — почти чистая бумага, она СВЕТЛЕЕ фона страницы кейса и
       за счёт этого отделяется от него;
     • тёмная тема — мягкий тёплый офф-вайт вместо слепящего белого пятна.
   Рамка --brandmark-line выведена из --macro-brand-navy, а НЕ из --ctx-border:
   ctx-граница в тёмной теме светлая и на светлой плашке пропадает. Линия
   декоративная (WCAG 1.4.11 к ней не применяется), её ориентир — домашняя
   норма --macro-border (1.29 к белому); здесь 1.33–1.38.

   КАК ПРИМЕНЯТЬ (разметка в контенте)
       <figure class="wp-block-image size-full case-brandmark">
   Классы bg-white / rounded / p-* с этой figure снимаются: фон, радиус и
   паддинг компонент задаёт сам, а `rounded` в теме = 2.25rem и на плашке
   выглядит подушкой.

   ⚠️ ЭТО НЕ ЗАМЕНА ОБЫЧНОЙ КАРТИНКЕ. Скриншот, фотография, кадр интерфейса
   идут как были — им плашка вредна: object-fit: contain впишет кадр в чужую
   высоту и оставит поля. Класс только для знаков на прозрачном фоне. */

.case-body > .row > [class*="col"] figure.case-brandmark {
	/* Высота плашки. Одна на все знаки ряда — отсюда «одинаковая высота»
	   независимо от того, что написано в самих файлах. */
	--brandmark-h: clamp(8rem, 15vw, 11rem);
	--brandmark-pad: clamp(1.25rem, 2.6vw, 2rem);
	--brandmark-max-w: 22rem;
	--brandmark-plate: color-mix(in srgb, var(--ctx-page) 8%, var(--macro-brand-paper));
	--brandmark-line: color-mix(in srgb, var(--macro-brand-navy) 18%, transparent);

	/* Перебивает `width: fit-content` галереи — та мера считалась по 73px
	   внутри файла. Специфичность (0,4,1) против (0,3,1), не порядок. */
	width: 100%;
	max-width: var(--brandmark-max-w);
	margin-inline: auto;
}

.case-body > .row > [class*="col"] figure.case-brandmark img {
	width: 100%;
	height: var(--brandmark-h);
	max-width: none;
	/* галерейный потолок --case-media-max-h снимаем: высота здесь наша */
	max-height: none;
	padding: var(--brandmark-pad);
	object-fit: contain;
	object-position: center;
	background-color: var(--brandmark-plate);
	border: 1px solid var(--brandmark-line);
	border-radius: var(--case-radius);
	box-shadow: none;
	/* Цвет alt-текста, если знак не загрузился: он окажется на СВЕТЛОЙ плашке,
	   и наследованный --ctx-ink в тёмной теме был бы белым по белому. */
	color: var(--macro-brand-navy);
}

/* Знаки мелкие — на планшете и широком телефоне они обязаны стоять в ряд, а не
   стопкой в 700px шириной. auto-fit, а не repeat(3): ряд может нести два знака
   или четыре, и раскладка посчитается сама. Пишем в --case-cols (токен ТИПА),
   поэтому автоопределение §7 сюда не вмешивается. */
@media (min-width: 576px) {
	.case-body > .row:has(> [class*="col"] figure.case-brandmark) {
		--case-cols: repeat(auto-fit, minmax(8.5rem, 1fr));
		--case-align: start;
	}
}

@supports not (color: color-mix(in srgb, red, blue)) {
	.case-body > .row > [class*="col"] figure.case-brandmark {
		--brandmark-plate: var(--macro-brand-paper);
		--brandmark-line: var(--macro-line-strong);
	}
}


/* --- Типы блоков (§5). Тип задаётся классом ряда в редакторе ---
   Мера объявляется через --case-measure, раскладка — через --case-cols /
   --case-align (см. «ПРИОРИТЕТ ТИПА» в базовом правиле ряда). Прямой
   max-width / grid-template-columns здесь НЕ писать: он снова вступит в
   гонку специфичности со слоем нормализации, и слой выиграет.
   Новый тип = одна строка --case-measure; раскладку можно не объявлять —
   тогда колонки посчитает нормализация (как у case-gallery / case-facts). */

/* 1. Заголовок раздела */
.case-body > .row.case-head {
	--case-measure: var(--case-col);
}

.case-body > .row.case-head > [class*="col"] {
	padding-bottom: var(--case-gap) !important;
	border-bottom: 1px solid var(--case-line);
}

/* 2. Текст */
.case-body > .row.case-text {
	--case-measure: var(--case-col);
}

/* 3. Текст + изображение */
.case-body > .row.case-split {
	--case-measure: var(--case-wide);
}

@media (min-width: 992px) {
	.case-body > .row.case-split {
		--case-cols: repeat(2, minmax(0, 1fr));
		--case-align: center;
	}

	/* единственный разрешённый модификатор порядка */
	.case-body > .row.case-split--reverse > [class*="col"]:first-child {
		order: 2;
	}
}

/* 4. Широкое медиа / 4b полноширинный кадр */
.case-body > .row.case-media {
	--case-measure: var(--case-wide);
}

.case-body > .row.case-media--full {
	--case-measure: var(--case-full);
}

/* 5. Галерея */
.case-body > .row.case-gallery {
	--case-measure: var(--case-wide);
}

@media (min-width: 576px) and (max-width: 991.98px) {
	.case-body > .row.case-gallery:has(> [class*="col"]:nth-child(2)):not(:has(> [class*="col"]:nth-child(3))) {
		--case-cols: repeat(2, minmax(0, 1fr));
	}
}

/* 5b. Акцент/CTA: кнопка (+ подпись под ней) по центру узкой меры.
   Заводится классом ряда case-cta — новым кейсам не нужно повторять
   бутстраповскую акробатику с d-flex/justify-content, достаточно класса. */
.case-body > .row.case-cta {
	--case-measure: var(--case-col);
	text-align: center;
}

.case-body > .row.case-cta .btn,
.case-body > .row.case-cta .wp-block-button__link {
	min-width: min(100%, 18rem);
}

.case-body > .row.case-cta p {
	color: var(--ctx-muted);
	margin-bottom: 0;
}

/* --- ДВЕ ПАРЫ «КНОПКА + ПОДПИСЬ» В ОДИН РЯД НА ДЕСКТОПЕ ---
   Владелец 07.09.2026: «в таком случае делай кнопки на пк в один ряд».

   ⚠️ РАЗМЕТКА В КОНТЕНТЕ НЕ ТРОГАЛАСЬ — это принципиально: внутри одной
   колонки лежит плоская последовательность <a>, <p>, <a>, <p> (блоки
   wp:html + wp:paragraph), и обёртки «пара» там нет. Пары держит РАСКЛАДКА:
   grid-auto-flow: column при двух строках раскладывает детей СТОЛБЦАМИ —
   1-й ребёнок в (строка 1, колонка 1), 2-й в (строка 2, колонка 1), 3-й в
   (строка 1, колонка 2), 4-й в (строка 2, колонка 2). То есть подпись
   физически не может уехать к чужой кнопке: она следующий по порядку
   элемент, а порядок задаёт сам контент.
   ⚠️ Отсюда же ограничение: приём верен, пока чередование строгое
   «кнопка, подпись, кнопка, подпись». Кнопка без подписи (или две подписи
   подряд) сдвинет всю раскладку на шаг. На 07.09.2026 чередование
   соблюдено во всех шести кейсах с этим рядом (проверено по post_content:
   moh, naydi-sebya, istoki — по две пары; inhaus-ge, evera-dev, alesikalex,
   spectr, shagnsk, vizion — по одной).

   ⚠️ :has(.btn ~ .btn) — включаем сетку ТОЛЬКО там, где кнопок две и больше.
   Кейсы с одной кнопкой не получают её вовсе и остаются побайтово прежними
   (замер: кнопка 288px по центру колонки 736px — одинаково до и после).
   Без этого условия одиночная кнопка попала бы в единственную 1fr-колонку,
   и её пришлось бы отдельно защищать от растяжения.

   grid-auto-columns: minmax(0, 1fr) — колонки делят меру поровну и не дают
   длинной подписи растащить ряд по max-content. Проверка вместимости:
   мера --case-col = min(100%, 46rem); при 736px на колонку приходится
   (736 - 40) / 2 = 348px против 288px минимальной ширины кнопки — влезает
   с запасом. На 768px мера 698.9 -> 329px на колонку, тоже влезает; ниже
   768 сетка не включается вовсе и пары идут друг под другом, как раньше.

   justify-items: center — иначе элементы растянулись бы на всю колонку
   (кнопка стала бы вдвое шире). align-items: start — подписи разной длины
   не тянут кнопки по высоте.
   row-gap: 0 намеренно: в столбце «кнопка + подпись» зазора нет и сейчас
   (замер: <a> кончается на 10780.9, <p> начинается там же), и разводить
   их только в парном варианте значит развести два вида одного ряда. */
@media (min-width: 768px) {
	.case-body > .row.case-cta > [class*="col"]:has(.btn ~ .btn) {
		display: grid;
		grid-template-rows: auto auto;
		grid-auto-flow: column;
		grid-auto-columns: minmax(0, 1fr);
		justify-items: center;
		align-items: start;
		column-gap: clamp(1.5rem, 3vw, 2.5rem);
		row-gap: 0;
	}
}

/* 6. Цитата */
.case-body > .row.case-quote {
	--case-measure: var(--case-col);
}

.case-body blockquote,
.case-body > .row.case-quote > [class*="col"] {
	position: relative;
	margin: 0;
	padding: clamp(1.25rem, 2.5vw, 2rem) clamp(1.25rem, 2.5vw, 2rem) clamp(1.25rem, 2.5vw, 2rem)
		clamp(1.5rem, 3vw, 2.5rem);
	border: 1px solid var(--case-border);
	border-radius: var(--case-radius);
	background-color: var(--case-tint);
}

/* стойка 4px слева */
.case-body blockquote::before,
.case-body > .row.case-quote > [class*="col"]::before {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	width: 4px;
	border-radius: var(--case-radius) 0 0 var(--case-radius);
	background-color: var(--case-bar);
}

/* вложенный blockquote внутри ряда-цитаты не должен получать плашку дважды */
.case-body > .row.case-quote blockquote {
	padding: 0;
	border: 0;
	background: none;
}

.case-body > .row.case-quote blockquote::before {
	content: none;
}

.case-body blockquote p {
	font-size: clamp(1.25rem, 2.4vw, 1.875rem);
	font-weight: 500;
	line-height: 1.35;
	color: var(--ctx-ink);
}

.case-body blockquote cite,
.case-body blockquote p:last-child:not(:only-child) {
	font-size: 0.9375rem;
	font-style: normal;
	color: var(--ctx-muted);
}

/* 7. Факты / цифры */
.case-body > .row.case-facts {
	--case-measure: var(--case-wide);
}

.case-body > .row.case-facts > [class*="col"] {
	position: relative;
	padding: clamp(1.25rem, 2.5vw, 1.75rem) !important;
	border: 1px solid var(--case-border);
	border-radius: var(--case-radius);
	background-color: var(--case-tint);
	overflow: hidden;
}

.case-body > .row.case-facts > [class*="col"]::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 4px;
	background-color: var(--case-bar);
}

.case-body > .row.case-facts h3,
.case-body > .row.case-facts h2 {
	font-size: clamp(2.25rem, 5vw, 3.75rem);
	font-weight: 700;
	line-height: 1;
	letter-spacing: -0.03em;
	color: var(--case-accent-text);
}

/* цифра факта — не раздел, сквозная нумерация её не касается */
.case-body > .row.case-facts h2::before {
	content: none;
}

.case-body > .row.case-facts p {
	font-size: 0.9375rem;
	line-height: 1.4;
	color: var(--ctx-muted);
	margin-bottom: 0;
}

@media (min-width: 576px) and (max-width: 991.98px) {
	.case-body > .row.case-facts {
		--case-cols: repeat(2, minmax(0, 1fr));
	}
}

/* 8. Отзыв заказчика */
.case-body > .row.case-review {
	--case-measure: var(--case-wide);
	padding: clamp(1.25rem, 2.5vw, 2rem);
	border: 1px solid var(--case-border);
	border-radius: var(--case-radius);
	background-color: var(--case-tint);
}

/* Фото — колонкой по своему размеру, текст — остатком. Через --case-cols:
   иначе нормализация (два ребёнка → repeat(2, 1fr) + align-items: center)
   перебивала эту раскладку по специфичности, и фото занимало половину ряда. */
@media (min-width: 992px) {
	.case-body > .row.case-review {
		--case-cols: auto minmax(0, 1fr);
		--case-align: start;
	}
}

.case-body > .row.case-review img {
	width: 96px;
	height: 96px;
	object-fit: cover;
	border-radius: 50%;
	border: 1px solid var(--case-border);
	box-shadow: none;
}

.case-body > .row.case-review blockquote {
	padding: 0;
	border: 0;
	background: none;
}

.case-body > .row.case-review blockquote::before {
	content: none;
}

.case-body > .row.case-review blockquote p {
	font-size: clamp(1.0625rem, 1.6vw, 1.25rem);
	font-weight: 400;
	line-height: 1.55;
}


/* --- Мелочи, которые ломали ритм в старой разметке --- */

/* Бутстраповские вертикальные утилиты из контента гасим на уровне ряда тоже */
.case-body > .row[class*="pt-"],
.case-body > .row[class*="pb-"],
.case-body > .row[class*="py-"],
.case-body > .row[class*="mt-"],
.case-body > .row[class*="mb-"],
.case-body > .row[class*="my-"] {
	padding-top: 0 !important;
	padding-bottom: 0 !important;
}

/* Разделители из старого контента (hr.my-5) несли собственные отступы поверх
   ритма — гасим и приводим к линии --case-line. */
.case-body > hr {
	max-width: var(--case-wide);
	margin: var(--case-rhythm) auto 0 !important;
	border: 0;
	border-top: 1px solid var(--case-line);
	opacity: 1 !important;
}

/* Встроенные в контент ACF-блоки (section с собственным .container) живут по
   своим правилам вёрстки — приводим их хотя бы к общей мере и общему ритму,
   чтобы левый край не гулял третьим-четвёртым значением. */
.case-body > section {
	max-width: var(--case-wide);
	margin-inline: auto;
	padding-top: 0 !important;
	padding-bottom: 0 !important;
}

.case-body > section .container,
.case-body > section .container-fluid {
	max-width: 100%;
	padding-inline: 0;
}

/* Пустые ряды-распорки из старого контента не должны давать двойной шаг */
.case-body > .row:not(:has(*)) {
	display: none;
}

/* Шапка кейса (категория) — по той же оси, что контент */
.single-isotope .entry-header {
	padding-inline: var(--case-pad);
}


/* ============================================================
   ПОДВАЛ
   Перерисован 2026-08-19. Задача — внятно закончить страницу: смена фона
   плюс линия дают границу, воздух сверху/снизу не даёт прижаться к краю окна,
   композиция стоит на тех же --case-pad / --case-max, что и весь контент.
   Разметка — footer.php (.site-footer). Плавающая .top-button убрана,
   «Наверх» переехало в подвал.
   ============================================================ */

.site-footer {
	margin-top: clamp(3rem, 7vw, 6rem);
	padding-inline: var(--case-pad);
	padding-block: clamp(2.5rem, 5vw, 4rem);
	border-top: 1px solid var(--ctx-border);
	background-color: var(--ctx-plate);
}

.site-footer__inner {
	max-width: var(--case-max);
	margin-inline: auto;
}

.site-footer__widgets {
	margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}


/* --- Строка-сущность: кто автор сайта ---
   Добавлена 09.09.2026 (tz-aeo-geo.md, W6/A9). Разметка — footer.php,
   весь текст приходит из настроек «О проекте».

   Регистр тот же, что у остального подвала: ни рамок, ни плашек, ни теней —
   волосяная линейка снизу и типографика. Линейка ПОД строкой, а не над:
   сверху границу подвала уже держит его собственный border-top, вторая линия
   в 20px от неё читалась бы как ошибка.

   Цвет — только контекстные токены. На странице кейса подвал уходит в палитру
   кейса целиком (см. «Подвал в цвете страницы» ниже), и строка-сущность
   обязана ехать вместе с ним, а не оставаться фирменной. */
.site-footer__identity {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.75rem 1.5rem;
	margin-bottom: clamp(1.25rem, 2.5vw, 1.75rem);
	padding-bottom: clamp(1.25rem, 2.5vw, 1.75rem);
	border-bottom: 1px solid var(--ctx-border);
}

.site-footer .footer-identity {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.5rem 0.75rem;
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.5;
}

/* Имя — --ctx-ink, а не приглушённый: это единственное место в подвале,
   где написано, чей это сайт. Замер по паре «текст ↔ плита подвала»
   (tz-color-scheme-burgundy.md §5): светлая 13.09, тёмная 12.59. */
.site-footer .footer-identity__name {
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--ctx-ink);
	text-decoration: none;
	touch-action: manipulation;
}

/* Ссылка на визитку подчёркивается — §7.4 схемы: смысл ссылки не может
   держаться на одном цвете. Подчёркивание приглушённое, на hover доводится
   до currentColor (тот же приём, что у .studio-link в интро-блоке). */
.site-footer a.footer-identity__name {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.25em;
	text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
	transition: text-decoration-color 0.3s ease;
}

@supports not (color: color-mix(in srgb, red, blue)) {
	.site-footer a.footer-identity__name {
		text-decoration-color: currentColor;
	}
}

@media (hover: hover) and (pointer: fine) {
	.site-footer a.footer-identity__name:hover {
		text-decoration-color: currentColor;
		text-decoration-thickness: 2px;
	}
}

/* Общее правило темы `.dark-theme a:not(.btn):not(…)` — специфичность (0,5,1),
   обычным правилом его не перебить. Тот же приём, что у .footer-top ниже. */
body.dark-theme .site-footer a.footer-identity__name,
body.dark-theme .site-footer a.footer-identity__name:hover,
body.dark-theme .site-footer a.footer-identity__name:focus {
	color: var(--ctx-ink) !important;
}

.site-footer .footer-identity__role {
	color: var(--ctx-ink);
}

.site-footer .footer-identity__sep {
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background-color: var(--ctx-border);
}

/* Профили. Список без маркеров: маркер здесь — само подчёркивание. */
.site-footer .footer-profiles {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.25rem 1.25rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-footer .footer-profiles__item {
	margin: 0;
}

/* Акцент ТЕКСТОМ ≠ акцент заливкой: вне кейса в тёмной теме заливочный
   --macro-accent слишком тёмен для мелкого текста. Порядок фолбэков — тот же,
   что у .studio-link, .case-fact__kicker и .about-*: сначала палитра кейса,
   потом фирменный «текстовый» акцент, в конце заливочный.
   Замер (tz-color-scheme-burgundy.md §5): #8B1D35 на плите #F5F0F1 — 8.01;
   #E78DA1 на поверхности #3E1B27 — 6.27. Оба выше 4.5. */
.site-footer .footer-profile {
	display: inline-block;
	min-height: 24px;
	font-size: 0.9375rem;
	font-weight: 500;
	line-height: 1.5;
	white-space: nowrap;
	color: var(--case-accent-text, var(--macro-accent-text, var(--ctx-accent)));
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.25em;
	text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
	touch-action: manipulation;
	transition: text-decoration-color 0.3s ease;
}

body.dark-theme .site-footer .footer-profile,
body.dark-theme .site-footer .footer-profile:hover,
body.dark-theme .site-footer .footer-profile:focus {
	color: var(--case-accent-text, var(--macro-accent-text, var(--ctx-accent))) !important;
}

@supports not (color: color-mix(in srgb, red, blue)) {
	.site-footer .footer-profile {
		text-decoration-color: currentColor;
	}
}

@media (hover: hover) and (pointer: fine) {
	.site-footer .footer-profile:hover {
		text-decoration-color: currentColor;
		text-decoration-thickness: 2px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.site-footer a.footer-identity__name,
	.site-footer .footer-profile {
		transition: none;
	}
}

/* До 576px строка-сущность встаёт в две строки по левому краю: на 375px
   имя+роль и три профиля в один ряд не помещаются, а space-between
   растащил бы их по краям и разорвал бы связку «кто это». */
@media (max-width: 575.98px) {
	.site-footer__identity {
		flex-direction: column;
		align-items: flex-start;
	}
}

.site-footer__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem 1.5rem;
}

/* Звёздочка у профиля Meta (footer.php ставит её только рядом со сноской).
   Отдельным span'ом, а не символом в подписи: подпись приходит из настроек и
   питает ещё и блок «Автор — визитка» с лентой контактов интро-блока, где
   сноски нет — там хвостовые «*» с подписи срезает lazarewww_profile_label(). Подчёркивание ссылки маркер не тянет —
   иначе на конце строки висел бы обрубок линии. */
.site-footer .footer-profile__mark {
	display: inline-block;
	margin-left: 0.05em;
	text-decoration: none;
}

/* Сноска к звёздочке — ЕДИНСТВЕННАЯ на сайте (решение владельца 09.09.2026:
   оговорка о статусе Meta живёт только в подвале, интро-блок «Студии» свою
   печатать перестал). Кегль и ритм: 0.6875rem / 1.55, приглушённый цвет,
   строка не длиннее 60ch. Сброс small обязателен — Bootstrap уводит его
   на 0.875em от родителя и текст ушёл бы ниже 11px, где кириллические
   строчные перестают различаться. */
.site-footer .footer-note {
	max-width: 60ch;
	margin: clamp(1.25rem, 2.5vw, 1.75rem) 0 0;
	color: var(--ctx-muted);
	font-size: 0.6875rem;
	line-height: 1.55;
}

.site-footer .footer-note small {
	font-size: inherit;
}

/* На странице кейса --ctx-muted собирается как «case-ink 65% над плитой», и на
   самой светлой авторской паре (naydi-sebya, светлая тема) это ровно граница:
   4.497 при пороге 4.5. Копирайту (13px) хватает, сноске 11px — нет, поэтому
   на кейсе она чуть плотнее. 70% проверено по всем 14 парам цветов сразу:
   минимум 5.18 (та же naydi-sebya, светлая), максимум 7.4.
   Браузер без color-mix объявление отбросит и вернётся к --ctx-muted выше —
   а там в этом же случае подставлен чистый --case-ink, то есть ещё контрастнее. */
body.single-isotope .site-footer .footer-note {
	color: color-mix(in srgb, var(--case-ink) 70%, transparent);
}


/* Копирайт: названия компании нет, поэтому строка собрана из года и правовой
   формулы. Разделители — точки-кружки, чтобы три коротких куска читались
   как одна строка, а на узком экране аккуратно переносились. */
.footer-copy {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 0.75rem;
	font-size: 0.8125rem;
	line-height: 1.5;
	letter-spacing: 0.02em;
	color: var(--macro-muted);
}

.footer-copy__year {
	font-weight: 600;
	letter-spacing: 0.06em;
	color: var(--macro-ink2);
}

.footer-copy__sep {
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background-color: var(--macro-border);
}

/* «Наверх» — пилюля в языке контролов ленты (.top-back, .cases-tab):
   сама лента с 22.08.2026 стала прямой полосой, но её ВНУТРЕННИЕ контролы
   скругления сохранили, и эта кнопка равняется на них. */
.footer-top {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	min-height: 44px;
	padding: 0 1.125rem;
	border: 1px solid var(--macro-border);
	border-radius: 999px;
	background-color: var(--macro-surface);
	color: var(--macro-ink);
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
	touch-action: manipulation;
	transition: border-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
}

.footer-top i {
	font-size: 0.75rem;
	color: var(--macro-muted);
	transition: transform 0.3s ease, color 0.3s ease;
}

@media (hover: hover) and (pointer: fine) {
	.footer-top:hover {
		border-color: var(--macro-accent);
		box-shadow: var(--macro-shadow-sm);
		color: var(--macro-ink);
	}

	.footer-top:hover i {
		transform: translateY(-2px);
		color: var(--macro-accent);
	}
}


body.dark-theme .footer-top,
body.dark-theme .footer-top:hover,
body.dark-theme .footer-top:focus {
	/* .dark-theme a:not(.btn):not(…) — (0,5,1), обычным правилом не перебить */
	color: var(--macro-ink) !important;
}

@media (hover: hover) and (pointer: fine) {
	body.dark-theme .footer-top:hover i {
		color: var(--macro-accent-text);
	}
}

@media (prefers-reduced-motion: reduce) {
	.footer-top,
	.footer-top i {
		transition: none;
	}

	.footer-top:hover i {
		transform: none;
	}
}

/* На мобилке — две строки, но осмысленные: копирайт и кнопка по левому краю */
@media (max-width: 575.98px) {
	.site-footer__bar {
		flex-direction: column;
		align-items: flex-start;
	}
}


/* --- Плавающая «наверх» ---
   Один набор правил на все страницы: селекторы НЕ привязаны ни к классу body,
   ни к .cases-section — иначе на странице кейса осталась бы квадратная кнопка
   родительской темы. Форма/размер/тень общие с контролами левого верхнего угла.

   Цвет — единственное, что зависит от страницы, и он приходит одной парой
   переменных. Дефолт (главная и любые страницы без палитры кейса) — основной
   цвет проекта. На кейсе пара переопределяется теми же токенами, что уже
   считает header.php: --case-rain (противоположный по светлоте цвет кейса)
   и --case-color. Второй ветки стилей нет. */

/* ============================================================
   КОНТЕКСТНАЯ ПАЛИТРА ИНТЕРФЕЙСА — общий принцип проекта

   Правило: на странице кейса ВСЕ элементы интерфейса берут палитру этого
   кейса, на остальных страницах — фирменную палитру проекта. Компоненты
   при этом пишутся ОДИН раз и не знают, на какой они странице: они всегда
   используют --ctx-*. Ветвления «если главная — один CSS, если кейс — другой»
   нет и заводить нельзя.

   Источник для страницы кейса один: header.php считает из ACF-полей записи
   пару --case-color / --case-rain (цвет фона текущей темы и противоположный
   ему по светлоте) и контрастный --case-ink (яркость по WCAG). Всё остальное
   — производные. Автор кейса может выбрать любой цвет: читаемость держит
   вычисляемый ink, а не подбор руками.
   ============================================================ */

/* ВАЖНО про селектор: дефолты объявлены на body, а НЕ на :root.
   Класс темы (.dark-theme) висит на body, поэтому var(--macro-*) внутри :root
   подставился бы значением светлой темы и застрял бы им навсегда — именно так
   в тёмной теме на главной подвал получался белым. На body подстановка идёт
   по токенам того же элемента, то есть с учётом текущей темы. */
body {
	--ctx-accent: var(--macro-accent);        /* заливка акцента, активные состояния */
	--ctx-on-accent: var(--macro-accent-ink); /* текст/иконка НА акценте */
	--ctx-surface: var(--macro-surface);      /* поверхность контролов и плиток */
	--ctx-plate: var(--macro-soft);           /* крупные площади: подвал */
	/* Фон САМОЙ страницы — не то же, что поверхность: в тёмной теме страница
	   на ступень темнее плиток (#251017 против #3e1b27). Нужен там, где
	   элемент лежит не на плитке, а прямо на странице, — сейчас это ореол
	   контролов у прозрачной ленты (см. «Ореол контролов»). */
	--ctx-page: var(--bs-body-bg);
	--ctx-ink: var(--macro-ink);              /* основной текст на поверхности */
	--ctx-muted: var(--macro-muted);          /* второстепенный текст */
	--ctx-border: var(--macro-border);        /* границы и линейки */
	--focus-ring-color: var(--ctx-accent);    /* кольцо фокуса с клавиатуры */

	/* Дефолты палитры «кейса» для страниц, где кейса нет (главная и прочие):
	   тоже по паре на тему, а не одно значение на обе. */
	--case-color: var(--macro-soft);
	--case-ink: var(--macro-ink);
	--case-rain: var(--macro-accent);
}

/* В тёмной теме фон страницы — это как раз --macro-soft, поэтому крупная
   площадь подвала берёт следующую ступень рампы, иначе он сливался бы с фоном. */
body.dark-theme {
	--ctx-plate: var(--macro-surface);
	/* Кольцо фокуса — исключение из «беру --ctx-accent»: в тёмной теме заливочный
	   акцент светлее фона недостаточно, а кольцу нужно ≥3:1 к соседнему цвету
	   (WCAG 2.2, 1.4.11). Берём тот же акцент в «текстовой» светлоте
	   (--macro-accent-text), которым тема и так пишет акцентные ссылки.
	   ⚠️ Перемер 07.09.2026 после перекраски рампы в бордо: заливочный #d33154
	   к фону #251017 даёт 3.72 — то есть формально порог уже проходит (у
	   прежнего синего #3e6bc4 было 2.72, отсюда и правило; у изумрудного
	   #00847d на изумрудном фоне было 3.76 — паритет). Исключение оставлено
	   сознательно: у --macro-accent-text (#e78da1) 7.49, кольцо обязано быть
	   громким, а не «на грани». Убирать это правило по факту 3.72 не надо. */
	--focus-ring-color: var(--macro-accent-text);
}

/* Страница кейса: та же система, но питается парой цветов записи.
   Значения --case-* отдаёт header.php на селекторе .single-isotope.
   Селектор с body обязателен: правило темы выше — body.dark-theme (0,1,1),
   и голый .single-isotope (0,1,0) ему проигрывал, из-за чего подвал кейса
   в тёмной теме получал общую поверхность вместо цвета кейса. */
body.single-isotope {
	--ctx-accent: var(--case-rain);
	/* НЕ --case-color: цвет текста на заливке считается от самой заливки
	   (header.php, по яркости WCAG). При произвольной авторской паре
	   «фон страницы» может совпасть с акцентом, и подпись пропадёт. */
	--ctx-on-accent: var(--case-on-accent);
	--ctx-surface: color-mix(in srgb, var(--case-rain) 6%, var(--case-color));
	--ctx-plate: color-mix(in srgb, var(--case-rain) 6%, var(--case-color));
	/* Фон страницы кейса задаёт сам кейс (cpt-single.php красит body в
	   isotope_background_light/dark) — это ровно --case-color, от него же
	   header.php считает --case-ink. */
	--ctx-page: var(--case-color);
	--ctx-ink: var(--case-ink);
	--ctx-muted: color-mix(in srgb, var(--case-ink) 65%, transparent);
	--ctx-border: color-mix(in srgb, var(--case-rain) 28%, transparent);
	/* На кейсе контраст кольца держит сама пара цветов: --case-rain всегда
	   противоположен фону страницы по светлоте. Правило темы выше (0,1,1)
	   перебивается порядком — это правило ниже по файлу. */
	--focus-ring-color: var(--ctx-accent);
}

@supports not (color: color-mix(in srgb, red, blue)) {
	body.single-isotope {
		--ctx-surface: var(--case-color);
		--ctx-plate: var(--case-color);
		--ctx-page: var(--case-color);
		--ctx-muted: var(--case-ink);
		--ctx-border: var(--macro-border);
	}
}

/* ============================================================
   ФОКУС С КЛАВИАТУРЫ — общая система проекта

   Родительская тема глушит обводку глобально и жёстко:
   bootscore-main/style.css → `:focus { outline: none !important }` плюс все
   лонгхенды (outline-color/style/width) тоже с !important. Из-за этого кольцо
   фокуса пропадало у ВСЕХ наших компонентов, которые задавали outline обычным
   правилом, и навигация с клавиатуры шла вслепую.

   Родителя править нельзя (обновляемая тема), дописывать !important в каждый
   компонент — путь в никуда: правило пришлось бы дублировать в каждом новом
   блоке и легко забыть. Поэтому заглушка снимается ОДИН раз, здесь, и
   разводится по двум состояниям:

     • :focus:not(:focus-visible) — мышь/тап. Обводки нет: ровно то, ради чего
       заглушку в родителе и вводили (после клика кольцо выглядит как поломка).
     • :focus-visible — клавиатура. Кольцо есть всегда и везде.

   Цвет кольца — контекстный, токен --focus-ring-color (объявлен рядом с
   --ctx-* в разделе «КОНТЕКСТНАЯ ПАЛИТРА»). По умолчанию это --ctx-accent:
   на странице кейса — акцент палитры кейса, на главной — фирменный. Одно
   исключение прописано там же: в тёмной теме вне кейса заливочный акцент
   слишком тёмен для кольца, и берётся его «текстовая» светлота.

   Почему это работает: дочерняя style.css грузится ПОСЛЕ родительской
   (порядок в <head>: parent-style → bootscore-style), специфичность
   :focus-visible (0,1,0) равна родительскому :focus (0,1,0), значит при
   одинаковом !important побеждает то, что ниже по каскаду, — наше.

   Как компоненту уточнить кольцо:
     • свой отступ — обычным правилом `.x:focus-visible { outline-offset: … }`
       (специфичность выше нашей, !important не нужен);
     • свой цвет/толщину — переменными --focus-ring-color / --focus-ring-width
       на самом элементе или на любом его предке;
     • совсем отменить внешнее кольцо (например, чтобы нарисовать его ВНУТРЬ
       под overflow: hidden) — только `outline: none !important`, потому что
       перебивать приходится !important. Такой случай в проекте один:
       .case-card__link (cases-grid.css), там кольцо рисует псевдоэлемент.
   ============================================================ */

/* Указатель: как было. Правило дублирует родительское намеренно — чтобы
   поведение не зависело от того, останется ли заглушка в обновлённой теме. */
:focus:not(:focus-visible) {
	outline: none;
}

:focus-visible {
	outline: var(--focus-ring-width, 3px) solid var(--focus-ring-color, var(--ctx-accent)) !important;
	outline-offset: var(--focus-ring-offset, 3px);
}

/* Safari < 15.4 и прочие без поддержки :focus-visible: там наше правило выше
   не сматчится вообще, и фокус останется невидимым. Отдаём кольцо на обычный
   :focus — лучше лишняя обводка после клика, чем слепая клавиатура. */
@supports not selector(:focus-visible) {
	a:focus,
	button:focus,
	input:focus,
	select:focus,
	textarea:focus,
	summary:focus,
	[tabindex]:focus {
		outline: var(--focus-ring-width, 3px) solid var(--focus-ring-color, var(--ctx-accent)) !important;
		outline-offset: var(--focus-ring-offset, 3px);
	}
}

.top-button {
	position: fixed;
	right: var(--case-pad);
	right: max(var(--case-pad), calc((100% - var(--case-max)) / 2));
	bottom: clamp(1rem, 2.5vw, 1.5rem);
	z-index: 1020; /* ниже cookie-карточки (1050) и модалок */
	opacity: 0;
	transform: translateY(8px);
	pointer-events: none;
	/* visibility, а не только opacity: невидимая кнопка не должна ловить
	   табуляцию. С одной прозрачностью фокус уезжал на пустое место —
	   пользователь жал Tab и кольцо пропадало из кадра. Задержка 0.3s
	   держит элемент видимым, пока идёт затухание. */
	visibility: hidden;
	transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s linear 0.3s;
}

/* .visible вешает theme.js родителя после 500px скролла */
.top-button.visible {
	opacity: 1;
	transform: none;
	pointer-events: auto;
	visibility: visible;
	transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s;
}

/* Подвал в кадре — плавающая кнопка уступает место пилюле «Наверх» в подвале
   (класс ставит js/custom.js), чтобы они не дублировали друг друга. */
/* !important: класс .visible на этом же элементе вешает theme.js родителя, а в
   Bootstrap `.visible` — утилита `visibility: visible !important`. Без перебива
   пристыкованная (невидимая) кнопка оставалась бы в обходе по Tab. */
.top-button.is-docked {
	opacity: 0;
	transform: translateY(8px);
	pointer-events: none;
	visibility: hidden !important;
	transition: opacity 0.3s ease, transform 0.3s ease, visibility 0s linear 0.3s;
}

.top-button .top-up {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border: 1px solid transparent;
	border-radius: 999px;
	background-color: var(--ctx-accent);
	color: var(--ctx-on-accent);
	font-size: 1rem;
	line-height: 1;
	text-decoration: none;
	box-shadow: var(--macro-shadow-md);
	touch-action: manipulation;
	transition: box-shadow 0.3s ease, transform 0.3s ease, filter 0.3s ease;
}

@media (hover: hover) and (pointer: fine) {
	.top-button .top-up:hover {
		box-shadow: var(--macro-shadow-lg);
		transform: translateY(-2px);
		filter: brightness(1.06);
	}
}


/* .dark-theme a:not(.btn):not(…) — (0,5,1), обычным правилом не перебить */
body.dark-theme .top-button .top-up,
body.dark-theme .top-button .top-up:hover,
body.dark-theme .top-button .top-up:focus {
	color: var(--ctx-on-accent) !important;
}

/* Пилюля в подвале — тот же язык, тот же контекстный цвет у иконки */
.footer-top i {
	color: var(--ctx-accent);
}

@media (prefers-reduced-motion: reduce) {
	.top-button,
	.top-button .top-up {
		transition: none;
	}

	.top-button .top-up:hover {
		transform: none;
	}
}


/* --- Подвал в цвете страницы ---
   На странице кейса подвал обязан быть в цвете этого кейса, иначе он обрывает
   страницу чужим тоном. Точка входа та же, что у кнопки «наверх» и плашки hero:
   --case-color (фон текущей темы) и --case-ink (контрастный к нему текст,
   считается по яркости WCAG в header.php). Дефолт — нейтральная рампа проекта.

   Чтобы подвал не слился с фоном страницы в одно пятно, подложка сдвинута на 6%
   в сторону противоположного цвета кейса (--case-rain) и добавлена линия из него
   же. Оба приёма работают при любой авторской паре цветов. */

/* Подвал — в контекстной палитре: на кейсе цвет кейса, иначе рампа проекта.
   Чтобы он не слился с фоном страницы в одно пятно, подложкой служит
   --ctx-surface (на кейсе это цвет кейса, сдвинутый на 6% к акцентному)
   плюс линия сверху. Приём работает при любой авторской паре цветов. */
.site-footer {
	border-top-color: var(--ctx-border);
	background-color: var(--ctx-plate);
}

.footer-copy {
	color: var(--ctx-muted);
}

.footer-copy__year {
	color: var(--ctx-ink);
}

.footer-copy__sep {
	background-color: var(--ctx-border);
}

.footer-top {
	border-color: var(--ctx-border);
	background-color: transparent;
	color: var(--ctx-ink);
}

body.dark-theme .footer-top,
body.dark-theme .footer-top:hover,
body.dark-theme .footer-top:focus,
.single-isotope .footer-top {
	color: var(--ctx-ink) !important;
}

@media (hover: hover) and (pointer: fine) {
	.footer-top:hover {
		border-color: var(--ctx-accent);
	}
}


/* --- Тег категории на странице кейса ---
   Разметка — шаблон темы (bs-isotope-main/cpt-single.php): плагинную
   isotope_category_badge() не зовём, у неё .badge.bg-primary.rounded-0 и
   ссылка на неоформленный архив. Здесь чип того же языка, что табы категорий
   на главной, и цвет — контекстный. Ведёт на главную с выбранным табом. */

/* Размещение — слева, по общей левой линии контента (решение владельца
   2026-08-19; варианты размещения показаны отдельно, см. отчёт). */
.case-terms {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	max-width: var(--case-max);
	margin-inline: auto;
	margin-top: clamp(1.25rem, 3vw, 2rem);
}

.case-term {
	display: inline-flex;
	align-items: center;
	min-height: 36px;
	padding: 0.5rem 1.125rem;
	border: 1px solid var(--ctx-border);
	border-radius: 999px;
	background-color: transparent;
	color: var(--ctx-ink);
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1.2;
	letter-spacing: 0.02em;
	text-decoration: none;
	touch-action: manipulation;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

/* .dark-theme a:not(.btn):not(…) — (0,5,1).
   :not(:hover):not(:focus) обязателен: у этих селекторов специфичность (0,2,1),
   и без исключения они перебивали цвет наведения — на залитом чипе подпись
   оставалась цвета покоя и пропадала. */
body.dark-theme .case-term:not(:hover):not(:focus),
.single-isotope .case-term:not(:hover):not(:focus) {
	color: var(--ctx-ink) !important;
}

@media (hover: hover) and (pointer: fine) {
	.case-term:hover {
		border-color: var(--ctx-accent);
		background-color: var(--ctx-accent);
		color: var(--ctx-on-accent) !important;
	}
}

.case-term:focus-visible {
	/* кольцо — из общей системы фокуса; тег мелкий, отступ поджат */
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.case-term {
		transition: none;
	}
}

.single-isotope .entry-header {
	margin-top: 0 !important;
}


/* ============================================================
   КНОПКИ — один набор правил на весь сайт

   Эталон — главная (табы категорий и контролы): пилюля, тонкая граница,
   спокойные переходы 0.3s ease, подъём на hover, лёгкое проседание на нажатии.
   Цвет — контекстный (--ctx-*): на странице кейса кнопки автоматически берут
   палитру этого кейса, на остальных — фирменную палитру проекта. Второй ветки
   стилей и хардкод-цветов нет.

   Правила намеренно повешены на бутстраповские классы (.btn-primary,
   .btn-outline-primary, .wp-block-button__link): контент кейсов собирается в
   Гутенберге, и кнопка в новом кейсе должна выглядеть правильно сразу, без
   ручной доводки.
   ============================================================ */

.btn,
.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	min-height: 44px; /* тап-таргет */
	padding: 0.625rem 1.5rem;
	border-radius: 999px;
	border-width: 1px;
	font-weight: 500;
	line-height: 1.2;
	text-decoration: none;
	touch-action: manipulation;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease,
		box-shadow 0.3s ease, transform 0.3s ease;
}

.btn-primary,
.btn-primary:disabled,
.btn-primary.disabled,
.wp-block-button__link {
	background-color: var(--ctx-accent);
	border-color: var(--ctx-accent);
	color: var(--ctx-on-accent);
}

.btn-outline-primary {
	background-color: transparent;
	border-color: var(--ctx-accent);
	color: var(--ctx-ink);
}

/* .dark-theme a:not(.btn)… кнопок не касается, но .single-isotope-правила
   для ссылок — да, поэтому цвет кнопок фиксируем явно */
.single-isotope .btn-outline-primary,
body.dark-theme .btn-outline-primary {
	color: var(--ctx-ink);
}

/* СОСТОЯНИЯ. Три принципа:
   1) в каждом состоянии фон = --ctx-accent, текст = --ctx-on-accent, то есть
      вычисленная контрастная пара цвета страницы. Никаких brightness/затемнений
      фона: при произвольном авторском цвете они ломают контраст непредсказуемо,
      а «нажатие» и так читается по геометрии;
   2) отличие состояний несёт не цвет, а тень и смещение;
   3) !important обязателен — у Bootstrap состояния описаны цепочками
      .btn-primary:not(:disabled):not(.disabled):active (0,4,0) и
      .btn-check:checked + .btn-primary, они перебивают обычное правило.
      Именно из-за них на нажатии выезжала общая синяя заливка поверх текста. */

@media (hover: hover) and (pointer: fine) {
	.btn-primary:hover,
	.btn-outline-primary:hover,
	.wp-block-button__link:hover {
		background-color: var(--ctx-accent) !important;
		border-color: var(--ctx-accent) !important;
		color: var(--ctx-on-accent) !important;
		box-shadow: var(--macro-shadow-md);
		transform: translateY(-2px);
	}
}

/* Нажатие — лёгкое проседание, тем же языком, что отклик карточки кейса.
   Цвет при этом НЕ меняется, поэтому подпись не может пропасть. */
.btn:active,
.btn:focus,
.btn.active,
.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:not(:disabled):not(.disabled).active,
.btn-outline-primary:not(:disabled):not(.disabled):active,
.btn-outline-primary:not(:disabled):not(.disabled).active,
.wp-block-button__link:active {
	background-color: var(--ctx-accent) !important;
	border-color: var(--ctx-accent) !important;
	color: var(--ctx-on-accent) !important;
}

.btn:active,
.wp-block-button__link:active {
	transform: translateY(0) scale(0.99);
	box-shadow: none;
}

/* В покое контурная кнопка остаётся контурной: заливка только в состояниях */
.btn-outline-primary:not(:hover):not(:active):not(:focus):not(.active) {
	background-color: transparent !important;
	color: var(--ctx-ink) !important;
}

.btn-primary:disabled,
.btn-primary.disabled,
.btn-outline-primary:disabled,
.btn-outline-primary.disabled {
	background-color: var(--ctx-accent);
	border-color: var(--ctx-accent);
	color: var(--ctx-on-accent);
	opacity: 0.55;
}

.btn:focus-visible,
.wp-block-button__link:focus-visible {
	/* кольцо — из общей системы фокуса; здесь гасим бутстраповскую тень,
	   иначе она размывает кольцо */
	box-shadow: none;
}

/* Bootstrap-овские тени фокуса на кнопках гасим — фокус показывает outline */
.btn:focus,
.btn.focus {
	box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
	.btn,
	.wp-block-button__link {
		transition: none;
	}

	.btn:hover,
	.btn:active,
	.wp-block-button__link:hover,
	.wp-block-button__link:active {
		transform: none;
	}
}
