/*
 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;
}


.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;
	background: var(--bs-primary);
}

/* Центрируем, если центрирован сам заголовок — явным классом
   .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;
}

/* Скроллинг */

::-webkit-scrollbar{
width: 8px;
height: 8px;
border-radius:12px
}
::-webkit-scrollbar-thumb{
background: var(--bs-primary);
opacity: 0.8;
border-radius: 0px;
}
::-webkit-scrollbar-thumb:hover{
opacity: 1;
}
::-webkit-scrollbar-track{
background: rgba(39, 40, 41, 0.1);
border-radius: 0px;
box-shadow: inset 0px 0px 0px 0px #F0F0F0;
}


/* ============================================================
   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;
}


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

:root {
	--macro-soft: #f1f2f3;
	--macro-soft2: #fafbfb;
	--macro-surface: #ffffff;
	--macro-border: #e3e4e6;
	--macro-ink: #272829;
	--macro-ink2: #5a616b;
	--macro-muted: #7e7f82;
	--macro-accent: #172747;
	--macro-accent-ink: #ffffff;
	--macro-accent-text: #172747;
	--macro-danger-text: #9b1917;
	--macro-warn-text: #8a5a12;
	--macro-chip-bg: #fff3e2;
	--macro-col-divider: #c4c6ca;

	/* Не меняются между темами */
	--macro-brand-navy: #172747;

	/* Верхняя полоса (.top-controls) — БЕЛАЯ и ОДИНАКОВАЯ на всех страницах
	   (установка владельца, T20, 23.08.2026). Оба токена объявлены ЗДЕСЬ и
	   намеренно НЕ переопределяются ни в .dark-theme, ни в контекстном слое
	   --ctx-*: полоса не должна реагировать ни на тему, ни на палитру кейса.
	   Фон — белый, содержимое (знак, бегущая строка, логотип-разделитель) —
	   фиксированный тёмно-синий бренда, читаемый на белом. */
	--topbar-bg: #ffffff;
	--topbar-ink: var(--macro-brand-navy);

	--macro-nav-active: #2b4987;
	--macro-presence-green: #1d9e75;
	--macro-badge-blue: #5b86d6;
	--macro-alert-orange: #e8821e;

	--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);
}


/* ============================================================
   Контролы левого верхнего угла: «Назад на главную» + переключатель темы.
   Шапки на сайте нет, поэтому они фиксированы поверх контента — но это
   деталь интерфейса, а не главный элемент первого экрана: тумблер сделан
   тихим (круг 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 тап-таргета контролов +
                       вертикальный паддинг с двух сторон (T45, +~10% к высоте):
                       ~57px до 768, ~62px от 768;
   --top-plate-space — нижняя кромка полосы в координатах окна: высота + граница.
                       Полоса прижата к верху (top: 0), верхнего зазора у неё нет,
                       поэтому других слагаемых тут нет.
                       ⚠️ В space входит только то, что РЕАЛЬНО занимает место
                       сверху. Ореол контролов (см. ниже) не занимает: он лежит
                       вплотную к глифам внутри самой полосы. */
:root {
	--top-plate-line: 1px;
	/* T45: высота полосы поднята на ~10% приростом вертикального паддинга.
	   Было 0.25rem (4px) → h=52px; стало 0.41rem (~6.56px) → h≈57.1px (+9.8%).
	   Знак/текст не трогаем — растёт только «воздух» полосы. --top-plate-space
	   и padding-top контента пересчитываются от --top-plate-h автоматически. */
	--top-plate-pad-y: 0.41rem;
	--top-plate-h: calc(44px + 2 * var(--top-plate-pad-y));
	--top-plate-space: calc(var(--top-plate-h) + var(--top-plate-line));

	/* Воздух под полосой = меж-кейсовый зазор ленты кейсов (T16, владелец):
	   расстояние от нижней кромки полосы до первого элемента контента должно
	   равняться расстоянию между карточками кейсов. Значение зеркалит
	   --case-gap из cases-grid.css (.cases-section) — clamp(0.75rem,1.4vw,1.75rem):
	   12px мобайл … ~20px на 1440 … 28px потолок. Дублируется числом, а не
	   var(--case-gap): та объявлена локально на .cases-section и на :root не
	   видна; при правке зазора в ленте синхронизировать здесь. */
	--top-content-air: clamp(0.75rem, 1.4vw, 1.75rem);
}

@media (min-width: 768px) {
	:root {
		/* T45: было 0.375rem (6px) → h=56px; стало 0.55rem (8.8px) → h=61.6px (+10%). */
		--top-plate-pad-y: 0.55rem;
	}
}

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

   ⚠️ Установка владельца 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 {
	/* Высота знака. Объявлена ЗДЕСЬ, на общем предке, а НЕ на .top-logo —
	   custom properties наследуются вниз, поэтому её видят и .top-logo (знак),
	   и .top-marquee (fade-маска считает из неё ширину знака). Будь она объявлена
	   на сиблинге .top-logo — до marquee бы не дошла: var(--top-logo-h) стал бы
	   невалиден и вся mask-image схлопнулась в none (буквы наезжали на знак слева
	   и лезли под тумблер справа). Брейкпоинты 40/29 — в медиазапросах ниже. */
	--top-logo-h: 35px;

	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;
		--top-logo-h: 40px;   /* знак и marquee-маска берут её по наследованию */
	}
}

/* Админ-бар 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 — лента просто всегда
   с цветом, то есть всегда читаема. Обратный вариант (по умолчанию прозрачно,
   класс добавляет цвет) при том же коде оставил бы контролы навсегда висеть
   на обложке.

   Граница — --ctx-border, а не тень: тень это тот же размытый край, от которого
   на этом сайте отказались. Токен контекстный, на кейсе он выводится из палитры
   записи, поэтому линия всегда своя для страницы и хардкода тут нет.

   ⚠️ ПЕРЕСМОТРЕНО 23.08.2026 (T20, установка владельца): полоса теперь
   БЕЛАЯ и ОДИНАКОВАЯ на всех страницах и в обеих темах — не прозрачная у
   верха, не контекстная. Двух состояний больше нет: заливка фиксированная
   --topbar-bg (white), не зависит ни от .topbar-at-top, ни от --ctx-*.
   Прежний контекстный вариант (--ctx-surface / прозрачность по классу /
   ореол под палитру кейса) отменён целиком. Класс .topbar-at-top на <html>
   продолжает навешиваться скриптом, но на вид полосы больше не влияет.

   Нижняя граница — тонкая нейтральная линия для отделения белой полосы от
   контента/обложки кейса (фиксированный --macro-border, не контекстный).
   Переход по цвету снят: менять полосе теперь нечего. */
.top-controls {
	background-color: var(--topbar-bg);
	border-bottom: var(--top-plate-line) solid var(--macro-border);
	box-shadow: var(--macro-shadow-sm);
}

/* T96: на СТРАНИЦАХ КЕЙСОВ полоса перестаёт быть белой и берёт фон кейса.
   header.php печатает на .single-isotope пару --case-color (фон кейса для
   текущей темы) и --case-ink (контрастный к нему текст), обе уже переключаются
   светлая/тёмная. Переопределяем ими локальные токены полосы: фон = фон кейса,
   всё содержимое (знак MACRO, marquee, разделитель «M Global», тумблер темы)
   красится через --topbar-ink и потому становится контрастным на этом фоне.
   Селектор скоплен на .single-isotope — на главной и обычных страницах полоса
   остаётся белой (--topbar-bg:#fff с :root). Нижнюю границу делаем контекстной
   полупрозрачным --case-ink, чтобы на цветном фоне не торчала чужая линия. */
.single-isotope .top-controls {
	--topbar-bg: var(--case-color);
	--topbar-ink: var(--case-ink);
	border-bottom-color: color-mix(in srgb, var(--case-ink) 18%, transparent);
}

/* Прежний прозрачный режим у верха страницы отменён (T20): полоса всегда
   белая. Правило .topbar-at-top .top-controls намеренно оставлено пустым по
   эффекту — фон/границу оно больше не трогает, класс сохранён только для
   скрипта-сторожевика. Ореол в белой полосе не нужен (см. ниже, снят). */

@media (prefers-reduced-motion: reduce) {
	.top-controls {
		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). В светлой теме это один цвет, в тёмной — разные ступени
   рампы (#0f1a30 против #1b2c4b), и ошибка видна глазом: с surface у верха
   главной вокруг знака стояло светлое пятно (замер на ровном фоне падал
   с 14.77 до 12.60). Правило для прозрачного состояния — выше, у
   .topbar-at-top. ⚠️ И то же самое --ctx-page берёт .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 сходит на нет. Одна тень такой
   же ширины даёт мутное пятно вместо контура.

   Знак — маска, а не текст, поэтому ему нужен filter: drop-shadow (он берёт
   альфу отрисованного элемента, то есть силуэт после маски). Цепочка
   drop-shadow работает так же, как стопка text-shadow: каждый следующий
   накладывается на результат предыдущего. Радиусы мельче — у подписи
   «Global Technologies» в знаке штрих около 1px, широкий ореол её замылил бы.

   ⚠️ Цвет ореола — только токены (--ctx-page / --ctx-surface). Хардкод тут
   запрещён так же, как везде: на кейсе обе величины выводятся из палитры
   записи, и ореол обязан ехать за ней. */
/* ⚠️ T20 (23.08.2026): полоса стала белой и одинаковой, тёмный контент лежит
   прямо на белом и в ореоле больше не нуждается — свечение вокруг тёмных
   глифов на белом только грязнило бы вид. Ореол СНЯТ: --top-halo-shadow пуст,
   text-shadow: none. Переменная сохранена (её ещё читают иконки тумблера и
   marquee-элементы) — просто раскрывается в пустоту. Весь разбор выше — про
   прежний прозрачный режим поверх обложек; к белой полосе он неприменим. */
.top-controls {
	--top-halo: transparent;
	--top-halo-shadow: none;

	/* Фиксированный тёмный цвет содержимого полосы (знак/строка/разделитель),
	   одинаковый на всех страницах и в обеих темах. Наследуется вниз потомкам.
	   НЕ --ctx-ink: полоса не контекстная. */
	color: var(--topbar-ink);
	text-shadow: none;
}

/* ⚠️ Тумблер — <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);
}

/* ⚠️ Знаку drop-shadow нельзя ставить НА МАСКИРОВАННЫЙ элемент: фильтр в конвейере
   применяется ДО маски, и маска срезает собственную тень элемента вместе с фоном —
   ореола просто нет (мерили: альфа 0.00). Поэтому маска уехала на .top-logo::before
   (см. «Знак MACRO Global»), а фильтр остался на родителе: к моменту его применения
   псевдоэлемент уже отрисован маской, и тень строится по силуэту знака.
   Радиусы мельче, чем у текста: у подписи «Global Technologies» штрих около 1px,
   широкий ореол её замылил бы. */
.top-logo {
	filter:
		drop-shadow(0 0 1px var(--top-halo))
		drop-shadow(0 0 2px var(--top-halo));
}


/* --- Подтон верхней кромки обложки (.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%
		);
	}
}

/* Переключатель тёмной темы (T9, 2026-08-23): переехал из верхней полосы
   .top-controls в ПОДВАЛ (footer.php, .site-footer__controls). Не фиксирован —
   лежит обычным потоком, скроллится со страницей. Класс .theme-switch-fixed
   исторический (имя сохранено, чтобы не переписывать общие стили тумблера и
   иконок ниже); фиксации он больше не несёт. Здесь только выкладка внутри
   футерной группы; сам круг/иконки/hover — общие правила ниже. */
.theme-switch-fixed {
	display: flex;
	align-items: center;
}


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

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

   Рисуем маской, а не <img>: исходник одноцветный (тёмно-синий) и на тёмной
   теме или тёмной палитре кейса сливался бы с фоном. Маска перекрашивает знак
   одним токеном --ctx-ink — тем же, которым написана подпись «Назад» и
   нарисована иконка тумблера. Значит он читается и в обеих темах, и на любой
   авторской палитре кейса (там --ctx-ink вычислен по яркости, см. header.php),
   а своего цвета в правиле нет вообще.

   Отдельного правила для печати не заводим: знак лежит внутри
   .top-controls.no-print и обязан исчезать/печататься вместе с остальной парой. */
/* Ссылка-обёртка знака (T13, 2026-08-23): знак стал кликабельным, ведёт на
   главную. Обёртка — новый flex-элемент .top-controls вместо самого span, поэтому
   flex:none и позиционирование в потоке несёт теперь она; сам знак внутри неё
   размеряется своими width/height. Декор ссылки гасим: у знака свой вид (маска),
   подчёркивание/цвет ссылки ему не нужны и на маску не влияют, но убираем ради
   чистоты и одинакового поведения в обеих темах. */
.top-logo-link {
	flex: none;
	display: inline-flex;
	line-height: 0;
	text-decoration: none;
	color: inherit;
	touch-action: manipulation;
}

.top-logo {
	/* Высота знака --top-logo-h объявлена на предке .top-controls (35/40/29 по
	   брейкпоинтам) — знак берёт её по наследованию, а не заводит свою: тот же
	   токен должна видеть и marquee-маска (сиблинг). Ширина считается из пропорций
	   исходника 281×88. Знак ниже тумблера (44px) намеренно — не спорит с контролами. */

	flex: none;
	position: relative;
	/* Над фоновым слоем marquee (z-index:0): буквы бегущей строки, доезжая до
	   знака, уходят ему за спину — часть эффекта «втекания». Fade-маска marquee
	   довершает растворение. См. раздел «Бегущая строка (.top-marquee)». */
	z-index: 1;
	width: calc(var(--top-logo-h) * 281 / 88);
	height: var(--top-logo-h);
}

/* ⚠️ Сама маска — на псевдоэлементе, а не на .top-logo, и это не косметика:
   на маскированном элементе не работает его собственный filter: drop-shadow
   (фильтр применяется до маски, и маска срезает тень). Ореол знака держится
   именно на этом разделении — подробности в «Ореоле контролов» выше.
   Красится псевдоэлемент тем же --ctx-ink, что и раньше. */
.top-logo::before {
	content: "";
	position: absolute;
	inset: 0;
	/* T20: фиксированный тёмный цвет знака на белой полосе, не контекстный */
	background-color: var(--topbar-ink);
	-webkit-mask-image: url("img/logo/macro-logo.svg");
	mask-image: url("img/logo/macro-logo.svg");
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	/* та же длительность, что у «Назад» и тумблера — при смене темы
	   вся пара перекрашивается одним движением */
	transition: background-color 0.3s ease;
}

/* Брейкпоинт-высоты знака (--top-logo-h: 40px ≥768px, 29px <360px) вынесены на
   предок .top-controls — знак наследует их вместе с marquee-маской. */

/* Без поддержки masking знак выродился бы в залитый прямоугольник — тогда
   лучше не показывать его вовсе: он декоративный, его отсутствие ничего
   не ломает, а прямоугольник поверх обложки кейса ломает. */
@supports not ((-webkit-mask-image: url("#m")) or (mask-image: url("#m"))) {
	.top-logo {
		display: none;
	}
}

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


/* ============================================================
   Бегущая строка (.top-marquee)
   ============================================================
   Маркетинговый marquee — ФОНОВЫЙ слой внутри фиксированной полосы .top-controls,
   лежит абсолютом на всю её площадь ПОД контролами (z-index:0; знак/«Назад»/тумблер
   подняты на z-index:1). В раскладке flex-полосы не участвует, высоту не меняет,
   события не перехватывает (pointer-events:none), из дерева доступности исключён
   (aria-hidden в разметке). Контент — из ACF options-поля marquee_text; пусто →
   в header.php не рендерится вовсе.

   Цвет строго --ctx-ink (тот же токен, что красит знак/«Назад»/иконку тумблера) —
   строка сама читается в светлой/тёмной теме и на любой авторской палитре кейса.
   Своего фона/плашки НЕТ (вторая поверхность внутри ленты запрещена, как и у
   «Назад»); читаемость на прозрачной ленте держит ореол --top-halo-shadow,
   наследуемый от .top-controls как text-shadow. */
.top-marquee {
	position: absolute;
	inset: 0;               /* на всю площадь фиксированной полосы */
	z-index: 0;             /* под контролами (z-index:1) */
	display: flex;
	align-items: center;    /* вертикальное центрирование, без вклада в высоту полосы */
	overflow: hidden;
	pointer-events: none;   /* сквозной клик: marquee ничего не перехватывает */

	/* Эффект «втекания в знак»: fade-маска.
	   Слева — «мёртвая зона» шириной [padding-left полосы + ширина знака + воздух]:
	   там маска прозрачна, буквы растворяются, доезжая до знака (знак сверху по
	   z-index довершает иллюзию). Формулы padding-left и ширины знака — те же, что
	   на .top-controls и .top-logo, поэтому зона совпадает с фактическим положением
	   знака на любой ширине и на ультраширинах (когда колонка центрируется).
	   Справа — короткое затухание, чтобы буквы не обрубались резко о тумблер.
	   #000/transparent здесь — альфа маски (непрозрачно/прозрачно), не цвет: хардкодом
	   палитры не является. */
	/* Фолбэк 35px в var(--top-logo-h) — страховка: если переменная почему-то не
	   дотянется по наследованию, calc() остаётся валиден и маска не схлопнется
	   в none (базовый кейс дефекта QA). Штатно значение приходит с .top-controls. */
	--marquee-fade-left: calc(
		max(var(--case-pad), (100% - var(--case-max)) / 2)   /* = padding-left полосы */
		+ (var(--top-logo-h, 35px) * 281 / 88)               /* ширина знака */
		+ 1rem                                               /* воздух: гаснем ДО контура знака */
	);
	--marquee-fade-right: 2.5rem;

	-webkit-mask-image: linear-gradient(
		to right,
		transparent 0,
		transparent var(--marquee-fade-left),
		#000 calc(var(--marquee-fade-left) + 1.5rem),       /* мягкий вход после знака */
		#000 calc(100% - var(--marquee-fade-right)),
		transparent 100%
	);
	mask-image: linear-gradient(
		to right,
		transparent 0,
		transparent var(--marquee-fade-left),
		#000 calc(var(--marquee-fade-left) + 1.5rem),
		#000 calc(100% - var(--marquee-fade-right)),
		transparent 100%
	);
}

/* Дорожка: две идентичные копии подряд, ширина по контенту. Анимация сдвигает её
   ровно на одну копию (translateX -50%) → бесшовный цикл. Движение — только
   transform (композитится на GPU, без reflow). Скорость задаётся --marquee-duration
   (длительность полного цикла), а не px/s: на широких экранах цикл длиннее, чтобы
   линейная скорость оставалась комфортной (~40-60 px/s). */
.top-marquee__track {
	display: flex;
	flex: none;
	width: max-content;
	will-change: transform;
	animation: top-marquee-scroll var(--marquee-duration, 35s) linear infinite;
}

.top-marquee__item {
	flex: none;
	white-space: nowrap;
	padding-right: 3rem;    /* зазор перед следующей копией + место под разделитель */
	/* Шрифт — SF UI Display, наследуется от темы, как у остальных контролов. */
	font-weight: 400;
	font-size: var(--marquee-fs, 0.8125rem);
	line-height: 1;
	color: var(--topbar-ink);  /* T20: фиксированный тёмный на белой полосе, одинаково везде */
	letter-spacing: 0.01em;
	/* Тот же ореол, что у контролов — читаемость на прозрачной ленте поверх обложки.
	   text-shadow наследуемый и доходит сюда от .top-controls, но проставляем явно:
	   элемент глубоко вложен, а стоимость дубля нулевая. */
	text-shadow: var(--top-halo-shadow);
}

/* Разделитель между копиями — псевдоэлемент (в ACF не выносим): мини-знак
   «M Global» через CSS-маску, перекрашенную в --topbar-ink (тот же фиксированный
   тёмный токен, что у текста строки и знака, T20) — читается на белой полосе
   одинаково на всех страницах и в обеих темах, как знак в углу.
   margin-left симметричен зазору item (3rem) → маркер по центру шва.
   Маска — та же схема, что у .top-logo::before; путь относителен от style.css. */
.top-marquee__item::after {
	content: "";
	display: inline-block;
	vertical-align: middle;
	margin-left: 3rem;      /* тот же зазор, что был у точки (padding-left) */
	height: 1.3em;
	width: calc(1.3em * 0.7798);   /* w/h силуэта 340×436 */
	background-color: var(--topbar-ink);
	-webkit-mask-image: url("img/logo/macro-global-mark.png");
	mask-image: url("img/logo/macro-global-mark.png");
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

/* Фолбэк для браузеров без masking: вместо пустоты возвращаем буллет
   --topbar-ink с пониженной альфой, снимаем размеры и заливку. */
@supports not ((-webkit-mask-image: url("#m")) or (mask-image: url("#m"))) {
	.top-marquee__item::after {
		content: "•";
		display: inline;
		width: auto;
		height: auto;
		margin-left: 0;
		padding-left: 3rem;
		background-color: transparent;
		color: color-mix(in srgb, var(--topbar-ink) 45%, transparent);
	}
}

@keyframes top-marquee-scroll {
	from { transform: translateX(0); }
	to   { transform: translateX(-50%); }  /* сдвиг ровно на одну копию → бесшовный цикл */
}

/* Адаптив: скорость/кегль через переменные. Полоса и знак уже адаптивны
   (--top-logo-h 29/35/40px, паддинги через --case-pad), мёртвая зона маски
   пересчитывается автоматически. Marquee высоту полосы не увеличивает. */
@media (min-width: 768px) {
	.top-marquee {
		--marquee-fs: 0.875rem;
		--marquee-duration: 45s;
	}
}

@media (min-width: 1440px) {
	.top-marquee {
		--marquee-fs: 0.9375rem;
		--marquee-duration: 55s;   /* длинная полоса — цикл длиннее, чтобы читалось */
	}
}

/* prefers-reduced-motion: бегущая строка — ключевой брендовый/декоративный
   элемент и по решению владельца ЕДЕТ ВСЕГДА, в том числе при reduce. Поэтому
   здесь анимацию .top-marquee__track НЕ снимаем (никаких animation:none /
   transform:none). Прочие reduced-motion правила темы (переходы, reveal,
   параллакс) остаются в силе в своих @media-блоках. Маска-fade и втекание
   в знак от motion не зависят и продолжают работать. */


/* --- Кнопка «Назад на главную» (.top-back) удалена 23.08.2026 (T19) ---
   Возврат наверх со страницы кейса теперь даёт кликабельный знак
   .top-logo-link (T13). Все правила .top-back / .top-back__* сняты вместе
   с разметкой в header.php. */

/* Совсем узкие экраны: лента упирается в правый край.
   ⚠️ Состав полосы (после T19, 23.08.2026): знак-ссылка + бегущая строка;
   тумблер темы переехал в подвал. Порог 359.98 оставлен ради знака: на 320
   полноразмерный знак съедает лишние px запаса и полоса выглядит забитой,
   поэтому здесь он уменьшается до 29px. */
@media (max-width: 359.98px) {
	.top-controls {
		gap: 0.25rem;
		--top-logo-h: 29px;   /* знак и marquee-маска берут её по наследованию */
	}

	/* Совсем узкие экраны: кегль строки на минимум (не ниже 0.75rem — читаемость),
	   цикл короче. Мёртвая зона слева считается из --top-logo-h:29px автоматически,
	   под текст остаётся достаточная доля полосы. */
	.top-marquee {
		--marquee-fs: 0.75rem;
		--marquee-duration: 30s;
	}

}

/* Сбрасываем раскладку бутстраповского .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.
   Никакого трека-пилюли и залитого «включённого» состояния: состояние читается
   символом (солнце = светлая тема сейчас, луна = тёмная).

   !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;
}

@media (hover: hover) and (pointer: fine) {
	.theme-switch-fixed .form-check-input:hover {
		background-color: var(--ctx-surface) !important;
		border-color: var(--ctx-border) !important;
		box-shadow: var(--macro-shadow-sm);
	}

	.theme-switch-fixed .form-check-input:hover::after,
	.theme-switch-fixed .form-check-input:hover::before {
		color: var(--ctx-accent) !important;
	}
}

.theme-switch-fixed .form-check-input:focus {
	background-color: var(--ctx-surface) !important;
	border-color: var(--ctx-border) !important;
	box-shadow: none;
}

.theme-switch-fixed .form-check-input:focus-visible {
	/* кольцо — из общей системы фокуса; тут только отступ: круг 44×44 и так
	   стоит впритык к краю экрана */
	outline-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 {
	/* Fallback: активен, только если первым в контенте окажется НЕ .cases-section
	   (гутенберг-обёртка) — иначе правило ниже даёт padding-top: 0 и весь отступ
	   держит сама .cases-section. Воздух под полосой сведён к меж-кейсовому
	   зазору (--top-content-air), высоту полосы компенсирует --top-plate-space.
	   Было max(clamp(5.75rem,8vw,8rem), …) — избыточный воздух ~71px на 1440. */
	padding-top: calc(var(--top-plate-space) + var(--top-content-air)) !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;
	/* Воздух под полосой = меж-кейсовый зазор (--top-content-air), а высоту
	   полосы держит --top-plate-space. Было max(6rem, …) = 96px; ужато до
	   кромки полосы + зазор ленты, чтобы верхний отступ читался как ритм сетки
	   кейсов, а не как дыра. */
	padding-top: calc(var(--top-plate-space) + var(--top-content-air)) !important;
}


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

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

body.dark-theme {
	/* --- токены темы --- */
	--macro-soft: #0f1a30;
	--macro-soft2: #16253f;
	--macro-surface: #1b2c4b;
	--macro-border: #2c4066;
	--macro-ink: #e9edf4;
	--macro-ink2: #b7c1d2;
	--macro-muted: #8b96a9;
	--macro-accent: #3e6bc4;
	--macro-accent-ink: #ffffff;
	--macro-accent-text: #9db8ff;
	--macro-danger-text: #ff9e96;
	--macro-warn-text: #e8b168;
	--macro-chip-bg: #3a2e1b;
	--macro-col-divider: #3e5580;

	/* Верхняя полоса (.top-controls) в тёмной теме — ТЁМНАЯ, но НЕ контекстная:
	   одинаковая на всех страницах в пределах темы (T34, установка владельца).
	   В светлой теме токены остаются на :root (белый фон / navy-контент, T20),
	   здесь переопределяются на тёмную поверхность и светлый контент через
	   семантические токены темы — без хардкод-hex. Поверхность --macro-surface
	   (#1b2c4b) читается как отдельная полоса на фоне страницы --macro-soft
	   (#0f1a30); контент — --macro-ink (#e9edf4). Нижняя граница и тень полосы
	   уже берут --macro-border (#2c4066) и --macro-shadow-sm, которые в этой же
	   теме переопределены ниже под тёмный режим — отдельных правил не нужно. */
	--topbar-bg: var(--macro-surface);
	--topbar-ink: var(--macro-ink);

	--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: 233, 237, 244;
	--bs-dark: var(--macro-surface);
	--bs-dark-rgb: 27, 44, 75;

	--bs-body-bg: var(--macro-soft);
	--bs-body-bg-rgb: 15, 26, 48;
	--bs-body-color: var(--macro-ink);
	--bs-body-color-rgb: 233, 237, 244;

	--bs-primary: var(--macro-accent);
	--bs-primary-rgb: 62, 107, 196;
	--bs-secondary: var(--macro-ink2);
	--bs-secondary-rgb: 183, 193, 210;
	--bs-danger: var(--macro-danger-text);
	--bs-danger-rgb: 255, 158, 150;
	--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: #6c7993;
	--bs-gray-500: #4c5d7c;
	--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` литеральный #172747 (= light-accent) */
/* :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);
	border-color: var(--macro-border);
	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(62, 107, 196, 0.3);
}

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

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

/* Скроллбар */
.dark-theme ::-webkit-scrollbar-thumb {
	background: var(--macro-accent);
}

body.dark-theme::-webkit-scrollbar-track {
	background: var(--macro-soft2);
}

/* Cookie-баннер: был свой хардкод под старую тёмную тему */
.dark-theme .cookie_bg {
	background: rgba(15, 26, 48, 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;
	font-size: 0.9375rem;
	font-weight: 600;
	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);
}


/* --- Типы блоков (§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;
}

/* 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);
	/* Полоса сокращена по высоте ~в 3 раза (T72a, 2026-08-24): режем только
	   вертикальный padding, было clamp(2.5rem, 5vw, 4rem). Горизонтальные
	   отступы (--case-pad) и содержимое не трогаем. margin-top не меняем —
	   это отдельная правка отступа кейсов. */
	padding-block: clamp(0.85rem, 1.7vw, 1.35rem);
	border-top: 1px solid var(--ctx-border);
	background-color: var(--ctx-plate);
}

/* T72b (2026-08-24): зазор кейсов от футера сокращён ~в 3 раза. margin-top
   футера — общий и для страниц кейсов, где своего нижнего отступа нет, поэтому
   глобально его НЕ режем (кейсам этот воздух нужен). Урезаем только на главной,
   где к нему ещё прибавляется padding-bottom секции .cases-section: там суммарный
   зазор был ~136px, теперь ~48px (≈/3). Страницы кейсов сохраняют 96px. */
.home .site-footer {
	margin-top: clamp(1rem, 2.3vw, 2rem);
}

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

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

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

/* Правая группа подвала — переключатель темы + «Наверх». Держатся вместе, чтобы
   space-between развёл копирайт (слева) и эту пару (справа), а не растащил три
   элемента по краям и центру. Тумблер (44×44 круг) чуть уводим влево к «Наверх»
   отрицательным зазором нет нужды — обычный gap. На узком экране, когда бар
   переносит группу под копирайт, она встаёт справа своей строки. */
.site-footer__controls {
	display: flex;
	align-items: center;
	gap: 0.75rem;
}

/* Копирайт: год + правовая формула с правообладателем (ТОО, T38). Разделители —
   точки-кружки, чтобы куски читались как одна строка, а на узком экране
   аккуратно переносились. */
.footer-copy {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 0.75rem;
	/* T71 (2026-08-24): типографика футера приведена к тэглайн-бару карточки
	   продукта (.case-card__plate--tagline в cases-grid.css) — по прямому указанию
	   заказчика «такой же шрифт, размер и цвет». Было: 0.8125rem / lh 1.5 /
	   ls 0.02em / color --macro-muted. Семейство (SF UI Display) уже совпадало.
	   ::first-letter-капитализацию тэглайна НЕ переносим — она про первую букву
	   подписи. Цвет — navy/светлый по теме, как у тэглайна: на светлой
	   --macro-brand-navy, в тёмной --macro-ink (тёмная ветка ниже). */
	font-size: clamp(0.75rem, 1vw, 0.9375rem);
	font-weight: 400;
	line-height: 1.35;
	letter-spacing: normal;
	color: var(--macro-brand-navy);
}

/* T71: тёмная тема — как у тэглайна на тёмной плашке (color: --macro-ink) */
body.dark-theme .footer-copy {
	color: var(--macro-ink);
}

/* Длинная строка правообладателя: при крайней тесноте (≈320px) ломается по
   словам, а не распирает подвал горизонтальным скроллом. */
.footer-copy__owner {
	min-width: 0;
	overflow-wrap: anywhere;
}

.footer-copy__year {
	font-weight: 600;
	letter-spacing: 0.06em;
	/* T71: год берёт тот же тон, что и остальной копирайт (навстречу «такому же
	   цвету, как в тэглайне»); в тёмной теме — светлый (ветка ниже). Вес 600
	   оставлен как мягкий акцент на числе — на family/size это не влияет. */
	color: var(--macro-brand-navy);
}

body.dark-theme .footer-copy__year {
	color: var(--macro-ink);
}

.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;
	justify-content: center;
	width: 44px;
	min-height: 44px;
	padding: 0;
	border: 1px solid var(--macro-border);
	border-radius: 999px;
	background-color: var(--macro-surface);
	color: var(--macro-ink);
	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.875rem;
	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);           /* крупные площади: подвал */
	/* Фон САМОЙ страницы — не то же, что поверхность: в тёмной теме страница
	   на ступень темнее плиток (#0f1a30 против #1b2c4b). Нужен там, где
	   элемент лежит не на плитке, а прямо на странице, — сейчас это ореол
	   контролов у прозрачной ленты (см. «Ореол контролов»). */
	--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»: в тёмной теме заливочный
	   акцент (#3e6bc4) на тёмном фоне даёт 2.7:1, а кольцу нужно ≥3:1 к соседнему
	   цвету (WCAG 2.2, 1.4.11). Берём тот же акцент в «текстовой» светлоте
	   (--macro-accent-text), которым тема и так пишет акцентные ссылки. */
	--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);
}

/* T71: текст копирайта НЕ уходит в контекстную палитру — он должен всюду
   совпадать с тэглайн-баром карточки (navy на светлой теме, светлый в тёмной),
   как просил заказчик. Поэтому здесь цвет НЕ переопределяем на --ctx-*: тон
   держат базовое правило .footer-copy и его тёмная ветка выше. Подложку/линию
   футера контекст красит по-прежнему (см. .site-footer выше). */

.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;
	}
}
