/* ============================================================
   extras.css — отложенная подгрузка, грузится async после first paint.
   Содержимое: модалки, overlay, калькулятор, мега-меню, TV-channels модалка.
   Всё это скрыто до взаимодействия пользователя, поэтому не нужно для FCP.
   Подключается из sections/header_meta.php через rel=preload + onload-swap.
   ============================================================ */

/* ----- Mega-menu dropdown ----- */
.has-menu { position: relative; }
.has-menu .menu-trigger {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: none; padding: 10px 18px; border-radius: 999px;
  font-family: inherit; font-size: 16px; font-weight: 500; color: var(--fg);
  position: relative; cursor: pointer;
  text-decoration: none;
  transition: background var(--duration) var(--easing), color var(--duration) var(--easing);
}
/* Invisible bridge between trigger and mega-menu — keeps hover continuous across the 8px gap */
.has-menu .menu-trigger::after {
  content: ''; position: absolute;
  left: 0; right: 0; top: 100%; height: 12px;
}
/* Hover + keyboard focus = open. .open class kept for backward compat / JS overrides. */
.has-menu:hover .menu-trigger,
.has-menu:focus-within .menu-trigger,
.has-menu.open .menu-trigger { background: var(--color-gray-100); color: var(--color-brand); }
.has-menu .menu-trigger .chev { transition: transform var(--duration) var(--easing); }
.has-menu:hover .menu-trigger .chev,
.has-menu:focus-within .menu-trigger .chev,
.has-menu.open .menu-trigger .chev { transform: rotate(180deg); }

.mega-menu {
  position: absolute; top: calc(100% + 8px); left: 0;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow-lg);
  padding: 24px; min-width: 580px; max-width: calc(100vw - 32px);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  /* On hide: opacity fades 150ms, then visibility flips. On show: visibility flips instantly so focus() works. */
  transition: opacity 150ms var(--easing), transform 150ms var(--easing), visibility 0s 150ms;
  z-index: 60;
}
.has-menu:hover .mega-menu,
.has-menu:focus-within .mega-menu,
.has-menu.open .mega-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
  transition: opacity 150ms var(--easing), transform 150ms var(--easing), visibility 0s 0s;
}
@media (prefers-reduced-motion: reduce) {
  .has-menu .menu-trigger .chev { transition: none; }
  .mega-menu { transition: none; }
}

.mega-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 32px; }
.mega-section { padding: 0 0 8px; }
.mega-section-title { font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-gray-500); margin: 0 0 12px; padding: 0 12px; }
.mega-link {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px; border-radius: 8px;
  color: var(--fg); text-decoration: none;
  transition: background var(--duration) var(--easing), color var(--duration) var(--easing);
}
.mega-link:hover { background: var(--color-brand-pale); color: var(--color-brand); }
.mega-link .ico {
  flex-shrink: 0; width: 40px; height: 40px; border-radius: 8px;
  background: var(--color-gray-100); color: var(--color-brand);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--duration) var(--easing);
}
.mega-link:hover .ico { background: var(--bg); }
.mega-link .ico i { width: 20px; height: 20px; }
.mega-link .ttl { display: block; font-size: 15px; font-weight: 600; line-height: 1.3; }
.mega-link .sub { display: block; font-size: 13px; color: var(--color-gray-500); margin-top: 4px; line-height: 1.4; }
.mega-link:hover .sub { color: var(--color-brand-dark); }
.mega-footer { display: flex; justify-content: space-between; gap: 16px; align-items: center; margin-top: 16px; padding-top: 20px; border-top: 1px solid var(--color-gray-200); }
.mega-footer a { font-size: 14px; font-weight: 600; color: var(--color-brand); display: inline-flex; align-items: center; gap: 8px; transition: color var(--duration) var(--easing); }
.mega-footer a:hover { color: var(--color-brand-dark); }

/* ----- Calculator -----
   .calc-wrap: на десктопе 2 колонки grid, на mobile — простой block-поток.
   Раньше mobile-override жил в style.css → extras.css его перебивал
   (extras грузится позже, без media). В Safari при overshoot контента
   правая колонка превращалась в узкую вертикальную полосу справа.
   Block + margin между детьми — самый предсказуемый layout для всех
   браузеров. */
.calc-wrap { display: grid; grid-template-columns: 1.2fr 1fr; gap: 48px; align-items: start; }
@media (max-width: 768px) {
  .calc-wrap { display: block; }
  .calc-wrap > * + * { margin-top: 16px; }
}
.calc-main { display: flex; flex-direction: column; gap: 32px; }
.eyebrow { font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-brand); margin: 0; }
.calc-eyebrow { display: inline-flex; align-items: center; gap: 6px; }
.calc-eyebrow > svg, .calc-eyebrow > i { width: 14px; height: 14px; opacity: 0.85; }
.section-h2 { font-size: 32px; font-weight: 700; margin: 4px 0 0; letter-spacing: 0; }
.calc-main .section-h2 { font-size: 44px; line-height: 1.1; letter-spacing: -0.01em; max-width: 14ch; text-wrap: balance; }
.calc-lead { font-size: 16px; line-height: 1.55; color: var(--color-gray-500); margin: 12px 0 0; max-width: 480px; }
.calc-field { display: flex; flex-direction: column; gap: 14px; }
.calc-field-label { display: flex; justify-content: space-between; font-size: 15px; font-weight: 500; }
.calc-speed-val { font-weight: 700; color: var(--brand-on-dark); display: inline-block; }
.tabular { font-variant-numeric: tabular-nums; }

/* Slider */
.calc-slider-wrap { position: relative; height: 36px; padding: 0; }
.calc-slider-track { position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); height: 8px; border-radius: 999px; background: var(--border); overflow: visible; pointer-events: none; }
.calc-slider-fill { position: absolute; left: 0; top: 0; bottom: 0; width: var(--val, 0%); border-radius: 999px; background: linear-gradient(90deg, var(--color-brand) 0%, var(--color-brand-light) 100%); transition: width 280ms var(--easing); z-index: 1; }
.calc-slider-tick { position: absolute; top: 50%; left: var(--p); width: 2px; height: 10px; border-radius: 1px; background: rgba(0,0,0,0.18); transform: translate(-50%, -50%); pointer-events: none; }
.calc-slider { -webkit-appearance: none; appearance: none; position: relative; width: 100%; height: 36px; background: transparent; outline: none; cursor: pointer; padding: 0; margin: 0; z-index: 2; }
.calc-slider::-webkit-slider-runnable-track { background: transparent; height: 36px; border: none; }
.calc-slider::-moz-range-track { background: transparent; height: 36px; border: none; }
.calc-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 28px; height: 28px; border-radius: 50%; background: #fff; cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.04), 0 4px 12px rgba(224, 64, 0,0.35), inset 0 0 0 6px var(--color-brand); border: none; transition: transform 160ms var(--easing), box-shadow 160ms var(--easing); margin-top: 4px; }
.calc-slider::-moz-range-thumb { width: 28px; height: 28px; border-radius: 50%; background: #fff; cursor: pointer; box-shadow: 0 2px 0 rgba(0,0,0,0.04), 0 4px 12px rgba(224, 64, 0,0.35), inset 0 0 0 6px var(--color-brand); border: none; transition: transform 160ms var(--easing), box-shadow 160ms var(--easing); }
@media (hover: hover) {
  .calc-slider:hover::-webkit-slider-thumb { transform: scale(1.06); box-shadow: 0 2px 0 rgba(0,0,0,0.04), 0 6px 16px rgba(224, 64, 0,0.45), inset 0 0 0 6px var(--color-brand); }
  .calc-slider:hover::-moz-range-thumb { transform: scale(1.06); box-shadow: 0 2px 0 rgba(0,0,0,0.04), 0 6px 16px rgba(224, 64, 0,0.45), inset 0 0 0 6px var(--color-brand); }
}
.calc-slider:active::-webkit-slider-thumb { transform: scale(1.14); box-shadow: 0 0 0 6px rgba(224, 64, 0,0.18), 0 6px 18px rgba(224, 64, 0,0.5), inset 0 0 0 6px var(--color-brand); }
.calc-slider:active::-moz-range-thumb { transform: scale(1.14); box-shadow: 0 0 0 6px rgba(224, 64, 0,0.18), 0 6px 18px rgba(224, 64, 0,0.5), inset 0 0 0 6px var(--color-brand); }
.calc-slider.snapped::-webkit-slider-thumb { transform: scale(1.18); box-shadow: 0 0 0 9px rgba(224, 64, 0,0.16), 0 4px 14px rgba(224, 64, 0,0.5), inset 0 0 0 6px var(--color-brand); }
.calc-slider.snapped::-moz-range-thumb { transform: scale(1.18); box-shadow: 0 0 0 9px rgba(224, 64, 0,0.16), 0 4px 14px rgba(224, 64, 0,0.5), inset 0 0 0 6px var(--color-brand); }
/* Run-14 C6: outer ring α 0.22 = 1.37:1 (fail). Усилили до 0.7 (~3.5:1, pass). */
.calc-slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px rgba(224, 64, 0,0.7), 0 4px 12px rgba(224, 64, 0,0.35), inset 0 0 0 6px var(--color-brand); }
.calc-slider:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px rgba(224, 64, 0,0.7), 0 4px 12px rgba(224, 64, 0,0.35), inset 0 0 0 6px var(--color-brand); }
.calc-slider-wrap.dragging .calc-slider-fill {
  background: linear-gradient(90deg, var(--color-brand-dark) 0%, var(--color-brand) 50%, var(--color-brand-light) 100%);
  background-size: 220% 100%;
  animation: calc-slider-shimmer 1.6s linear infinite;
}
@keyframes calc-slider-shimmer { from { background-position: 0% 0; } to { background-position: -200% 0; } }

/* Tier marks (clickable shortcuts) */
.calc-marks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; margin-top: 6px; }
.calc-mark { appearance: none; background: transparent; border: 0; padding: 10px 14px; min-height: 44px; cursor: pointer; font-family: inherit; color: var(--color-gray-500); display: inline-flex; flex-direction: column; align-items: center; justify-content: center; justify-self: center; gap: 1px; border-radius: 8px; transition: color var(--duration) var(--easing), background-color var(--duration) var(--easing); }
.calc-mark:nth-child(1) { justify-self: start; padding-left: 0; }
.calc-mark:nth-child(3) { justify-self: end; padding-right: 0; }
.calc-mark-num { font-size: 14px; font-weight: 600; }
@media (hover: hover) {
  .calc-mark:hover { color: var(--fg); background: rgba(0,0,0,0.04); }
  .calc-mark.is-active:hover { background: var(--color-brand-pale); }
}
.calc-mark.is-active { color: var(--brand-on-dark); }
.calc-mark.is-active .calc-mark-num { font-weight: 700; }
.calc-mark:focus-visible { outline: 2px solid var(--color-brand); outline-offset: 4px; background: rgba(0,0,0,0.04); }

/* Speed explainer (what this tier means in real terms) */
.calc-explainer { display: inline-flex; align-items: center; gap: 8px; font-size: 15px; line-height: 1.4; color: var(--color-gray-500); margin: 4px 0 0; transition: opacity 180ms var(--easing); }
.calc-explainer::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--color-brand); flex-shrink: 0; }
.calc-explainer.flash { animation: calc-explainer-flash 280ms var(--easing) 120ms both; }
@keyframes calc-explainer-flash { 0% { opacity: 0.4; transform: translateY(2px); } 100% { opacity: 1; transform: translateY(0); } }

/* Options & toggles */
.calc-options-label { font-size: 14px; font-weight: 600; margin: 0 0 12px; }
.calc-toggles { display: grid; grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); gap: 12px; }
.calc-toggle {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  border: 1.5px solid var(--border);
  border-radius: 12px;
  background: var(--bg-elevated);
  cursor: pointer;
  font-family: var(--font-sans);
  color: var(--fg);
  text-align: left;
  transition: border-color 200ms var(--easing), background-color 200ms var(--easing), box-shadow 200ms var(--easing), transform 200ms var(--easing);
}
@media (hover: hover) {
  .calc-toggle:hover { border-color: var(--color-gray-300); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
}
.calc-toggle-icon { width: 40px; height: 40px; border-radius: 10px; background: var(--color-brand-pale); color: var(--color-brand); display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; transition: background-color 200ms var(--easing), color 200ms var(--easing); }
.calc-toggle-icon > * { width: 20px; height: 20px; }
.calc-toggle-body { display: flex; flex-direction: column; min-width: 0; }
.calc-toggle-title { font-size: 15px; font-weight: 600; line-height: 1.3; }
.calc-toggle-meta { font-size: 13px; color: var(--color-gray-500); margin-top: 2px; }
.calc-toggle-price { font-size: 14px; font-weight: 600; color: var(--fg); white-space: nowrap; }
.calc-toggle-per { font-size: 12px; font-weight: 500; color: var(--color-gray-500); margin-left: 2px; }
.calc-toggle-check { position: absolute; top: 10px; right: 10px; width: 20px; height: 20px; border-radius: 50%; background: var(--bg); border: 1.5px solid var(--border); color: var(--color-white); display: inline-flex; align-items: center; justify-content: center; transition: background-color 160ms var(--easing), border-color 160ms var(--easing); overflow: hidden; }
.calc-toggle-check > * { width: 12px; height: 12px; opacity: 0; transform: scale(0.6); transition: opacity 140ms var(--easing), transform 140ms var(--easing); }

.calc-toggle.on { border-color: var(--color-brand); background: var(--color-brand-pale); box-shadow: 0 6px 18px -8px rgba(224, 64, 0,0.4); }
.calc-toggle.on .calc-toggle-icon { background: var(--color-brand); color: #fff; }
.calc-toggle.on .calc-toggle-price { color: var(--color-brand); }
.calc-toggle.on .calc-toggle-per { color: var(--color-brand); opacity: 0.8; }
.calc-toggle.on .calc-toggle-check { background: var(--color-brand); border-color: var(--color-brand); }
.calc-toggle.on .calc-toggle-check > * { animation: calc-check-pop 280ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }
@keyframes calc-check-pop {
  0%   { opacity: 0; transform: scale(0.4); }
  55%  { opacity: 1; transform: scale(1.18); }
  100% { opacity: 1; transform: scale(1); }
}
.calc-toggle:focus-visible { outline: 3px solid var(--color-brand); outline-offset: 2px; box-shadow: none; }

/* Side card */
.calc-side {
  border-radius: 20px;
  padding: 0;
  color: #fff;
  overflow: hidden;
  isolation: isolate;
  background:
    radial-gradient(120% 80% at 100% 0%, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0) 55%),
    radial-gradient(80% 60% at 0% 100%, rgba(0,0,0,0.18) 0%, rgba(0,0,0,0) 60%),
    linear-gradient(160deg, var(--color-brand-light) 0%, var(--color-brand) 55%, var(--color-brand-dark) 100%);
  box-shadow: 0 24px 60px -24px rgba(224, 64, 0,0.45), 0 2px 6px rgba(0,0,0,0.04);
}
.calc-side-deco { position: absolute; inset: 0; pointer-events: none; opacity: 0.55; mix-blend-mode: overlay; background-image: radial-gradient(rgba(255,255,255,0.6) 1px, transparent 1px); background-size: 22px 22px; background-position: 0 0; mask-image: radial-gradient(120% 60% at 110% -10%, #000 0%, transparent 60%); -webkit-mask-image: radial-gradient(120% 60% at 110% -10%, #000 0%, transparent 60%); }
.calc-side-inner { position: relative; padding: 32px; display: flex; flex-direction: column; gap: 14px; }
.calc-side-label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.12em; opacity: 0.85; margin: 0; }
.calc-total { display: flex; align-items: baseline; gap: 8px; line-height: 1; }
.calc-total-num { font-size: 64px; font-weight: 700; line-height: 1; letter-spacing: -0.01em; transform-origin: left center; }
.calc-total-num.flash { animation: calc-price-pulse 320ms var(--easing) 60ms both; }
@keyframes calc-price-pulse {
  0%   { transform: translateY(0)    scale(1);    text-shadow: 0 0 0 rgba(255,255,255,0); }
  35%  { transform: translateY(-4px) scale(1.04); text-shadow: 0 6px 18px rgba(255,255,255,0.35); }
  100% { transform: translateY(0)    scale(1);    text-shadow: 0 0 0 rgba(255,255,255,0); }
}
.calc-total-num.claimed { animation: calc-claim-pop 320ms var(--easing); }
@keyframes calc-claim-pop {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.13); text-shadow: 0 8px 24px rgba(255,255,255,0.45); }
  100% { transform: scale(1); text-shadow: 0 0 0 rgba(255,255,255,0); }
}
.calc-speed-val.flash { animation: calc-speed-flash 240ms var(--easing) both; }
@keyframes calc-speed-flash {
  0%   { transform: translateY(2px); opacity: 0.5; }
  100% { transform: translateY(0);   opacity: 1; }
}
.calc-total-unit { font-size: 18px; font-weight: 600; opacity: 0.9; }
.calc-total-per { font-size: 14px; font-weight: 500; opacity: 0.8; margin-left: 2px; }

.calc-breakdown { list-style: none; margin: 4px 0 0; padding: 14px 0 0; display: flex; flex-direction: column; gap: 10px; border-top: 1px solid rgba(255,255,255,0.28); }
.calc-breakdown-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; font-size: 14px; }
.calc-breakdown-row .label { display: inline-flex; align-items: center; gap: 8px; opacity: 0.95; }
.calc-breakdown-row .label::before { content: ''; width: 4px; height: 4px; border-radius: 50%; background: rgba(255,255,255,0.7); flex-shrink: 0; }
.calc-breakdown-row .price { font-weight: 600; opacity: 1; }

.calc-cta {
  margin-top: 6px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 52px; padding: 0 24px;
  background: #fff; color: var(--color-brand);
  border-radius: 999px;
  font-family: var(--font-sans); font-size: 16px; font-weight: 700;
  text-decoration: none;
  box-shadow: 0 8px 22px -10px rgba(0,0,0,0.35);
  transition: transform 180ms var(--easing), box-shadow 180ms var(--easing), color 180ms var(--easing);
}
.calc-cta i { width: 18px; height: 18px; transition: transform 180ms var(--easing); }
@media (hover: hover) {
  .calc-cta:hover { transform: translateY(-1px); box-shadow: 0 12px 26px -10px rgba(0,0,0,0.4); color: var(--color-brand-dark); }
  .calc-cta:hover i { transform: translateX(3px); }
}
.calc-cta:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,0.6), 0 8px 22px -10px rgba(0,0,0,0.35); }

.calc-perks { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.calc-perks li {
  display: inline-flex; align-items: center; gap: 8px; font-size: 13px;
  opacity: 0; transform: translateY(8px);
  transition: opacity 360ms var(--easing), transform 360ms var(--easing);
}
.calc-perks.in li { opacity: 0.92; transform: translateY(0); }
.calc-perks.in li:nth-child(1) { transition-delay: 0ms; }
.calc-perks.in li:nth-child(2) { transition-delay: 80ms; }
.calc-perks.in li:nth-child(3) { transition-delay: 160ms; }
.calc-perks i { width: 14px; height: 14px; flex-shrink: 0; opacity: 0.85; }

/* Mobile compact: уменьшаем вертикальные ритмы, калькулятор плотнее
   без ущерба touch-target'ам (44pt сохранены — slider/marks/toggle).
   Поставлен ПОСЛЕ всех базовых .calc-* правил: при одинаковой specificity
   позднее объявление выигрывает. */
@media (max-width: 768px) {
  .calc-main { gap: 20px; }
  .calc-main .section-h2 { font-size: 32px; line-height: 1.15; }
  .calc-lead { margin-top: 8px; font-size: 15px; }
  .calc-field { gap: 10px; }
  .calc-options-label { margin-bottom: 8px; }
  .calc-side-inner { padding: 20px; gap: 10px; }
  .calc-sticky-mobile { padding: 12px 16px; margin-bottom: 12px; }
}

/* Mobile sticky live-total bar (only visible ≤768px) */
.calc-sticky-mobile { display: none; }

/* Reduced motion: disable all calc animations and transitions */
@media (prefers-reduced-motion: reduce) {
  .calc-total-num.flash,
  .calc-total-num.claimed,
  .calc-speed-val.flash,
  .calc-explainer.flash,
  .calc-toggle.on .calc-toggle-check > *,
  .connect-form-anchor-pulse,
  .calc-slider-wrap.dragging .calc-slider-fill { animation: none !important; }
  .calc-toggle, .calc-mark, .calc-cta, .calc-toggle-icon, .calc-toggle-check, .calc-toggle-check > *,
  .calc-cta i, .calc-slider-fill, .calc-speed-val, .calc-perks li,
  .connect-tariff-summary, .calc-sticky-mobile-cta {
    transition-duration: 0ms !important;
  }
  .calc-toggle:hover, .calc-cta:hover, .calc-cta:hover i { transform: none !important; }
  .calc-perks li { opacity: 0.92 !important; transform: none !important; }
  .connect-tariff-summary { transform: none !important; opacity: 1 !important; }
  .calc-slider::-webkit-slider-thumb,
  .calc-slider::-moz-range-thumb { transition: none !important; }
}

/* ----- Overlay ----- */
.search-overlay {
  position: fixed; inset: 0;
  z-index: 300;
  display: flex; align-items: flex-start; justify-content: center;
  padding: max(64px, 8vh) 16px 16px;
}
.search-overlay[hidden] { display: none; }
.search-overlay-backdrop {
  position: absolute; inset: 0;
  /* Stronger pure-black scrim — readable on both light and dark page bg */
  background: rgba(0, 0, 0, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  animation: search-fade-in 180ms var(--easing);
}
@keyframes search-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes search-slide-in {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.search-panel {
  position: relative; z-index: 1;
  width: 100%; max-width: 640px;
  background: var(--bg-elevated); border-radius: 16px;
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  max-height: min(640px, calc(100vh - 96px));
  overflow: hidden;
  animation: search-slide-in 200ms var(--easing);
}

/* Focus переехал с input на саму .search-form через :focus-within — раньше
   глобальное input:focus-visible { outline 2px brand + offset 2 } давало толстую
   оранжевую рамку прямо вокруг текстового поля, читалось как ошибка валидации.
   Теперь подсветка едва заметная — нижний бордер меняет цвет, без обводки. */
.search-form {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--color-gray-200);
  flex-shrink: 0;
  transition: border-bottom-color var(--duration) var(--easing);
}
.search-form:focus-within { border-bottom-color: var(--color-brand); }
.search-form-icon { color: var(--color-gray-500); display: inline-flex; flex-shrink: 0; }
.search-form-icon svg { width: 20px; height: 20px; }
.search-input {
  flex: 1; min-width: 0;
  font-family: inherit; font-size: 16px; font-weight: 500;
  color: var(--fg); background: transparent;
  border: none; outline: none; padding: 8px 4px;
  appearance: none; -webkit-appearance: none;
}
/* Гасим глобальный input:focus-visible (строка ~26) — индикатор теперь у формы. */
.search-input:focus,
.search-input:focus-visible { outline: none; box-shadow: none; }
.search-input::-webkit-search-cancel-button { display: none; }
.search-input::placeholder { color: var(--color-gray-500); font-weight: 400; }
/* Маленький × внутри поля — очищает запрос, не закрывает overlay.
   Иконка остаётся 16px, кнопка 36×36, расширенный hit-area до 44×44 через ::before. */
.search-clear {
  position: relative;
  width: 36px; height: 36px; border-radius: 999px;
  background: transparent; color: var(--color-gray-500);
  border: none; cursor: pointer; padding: 0; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--duration) var(--easing), color var(--duration) var(--easing);
}
.search-clear::before {
  content: ""; position: absolute; inset: -4px; /* 36 + 8 = 44 — touch target */
}
.search-clear:hover { background: var(--color-gray-100); color: var(--fg); }

/* Большая × справа — закрывает overlay; круглая, как close-btn мобильного меню */
.search-close {
  flex-shrink: 0;
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-gray-100); color: var(--fg);
  border: none; border-radius: 999px;
  cursor: pointer; padding: 0;
  transition: background var(--duration) var(--easing), color var(--duration) var(--easing);
}
.search-close:hover { background: var(--color-gray-200); color: var(--color-brand); }
.search-close svg { display: block; }

.search-results-wrap {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 8px 0;
}

/* Empty state — quick links */
.search-empty { padding: 16px 20px 8px; }
.search-empty-label {
  margin: 0 0 12px;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-gray-500);
}
.search-quick { display: flex; flex-wrap: wrap; gap: 8px; }
.search-quick a,
.search-quick-item {
  display: inline-flex; align-items: center;
  padding: 10px 16px; min-height: 44px; border-radius: 999px;
  background: var(--color-gray-100); color: var(--fg);
  font-size: 14px; font-weight: 500; text-decoration: none;
  font-family: inherit; border: none; cursor: pointer;
  transition: background var(--duration) var(--easing), color var(--duration) var(--easing);
}
.search-quick a:hover,
.search-quick-item:hover { background: var(--color-brand-pale); color: var(--color-brand); }

/* Недавние запросы — секция над «Популярное» в empty state */
.search-recent { margin-bottom: 16px; }
.search-empty-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 0 0 12px;
}
.search-empty-head .search-empty-label { margin: 0; }
.search-recent-clear {
  font-family: inherit; font-size: 12px; font-weight: 600;
  color: var(--color-gray-500); background: transparent; border: none;
  cursor: pointer; padding: 4px 8px; border-radius: 6px;
  transition: color var(--duration) var(--easing), background var(--duration) var(--easing);
}
.search-recent-clear:hover { color: var(--color-brand); background: var(--color-brand-pale); }

/* Results list */
.search-results { list-style: none; margin: 0; padding: 4px 8px; }
.search-result {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 10px 12px;
  align-items: center;
  padding: 10px 12px;
  border-radius: 10px;
  color: var(--fg); text-decoration: none;
  cursor: pointer;
  transition: background var(--duration) var(--easing);
}
.search-result:hover, .search-result.active { background: var(--color-brand-pale); }
.search-result-kind {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  background: var(--color-gray-100); color: var(--color-brand);
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  flex-shrink: 0;
}
/* Lead-результаты — конверсионные, в скоринге дают +1.5 буст. Визуально
   выделяем заполненной brand-иконкой → пользователь сразу видит «короткий
   путь к заявке» среди прочих результатов (Von Restorff). */
.search-result[data-kind="lead"] .search-result-kind {
  background: var(--color-brand); color: #fff;
}
.search-result-kind svg { width: 18px; height: 18px; }
.search-result-body { min-width: 0; }
.search-result-title {
  font-size: 15px; font-weight: 600;
  color: var(--fg); line-height: 1.3;
  margin: 0;
  overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical;
}
/* Подсветка совпадения. Без horizontal padding — иначе раздвигает соседние
   буквы и текст «плавает». Разделение по бокам делает фоновая прозрачность. */
.search-result mark {
  background: rgba(224, 64, 0, 0.18);
  color: inherit;
  padding: 0;
  border-radius: 2px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.search-result-sub {
  margin: 2px 0 0; font-size: 13px;
  color: var(--color-gray-500); line-height: 1.35;
  overflow: hidden;
  display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical;
}
/* Правый столбец строки результата: badge сверху, kind-метка снизу.
   Раньше .search-result-meta-wrap не имел CSS вообще — badge «Популярный»
   и текст «ТАРИФ» вставали в одну строку без gap и визуально наезжали
   друг на друга (особенно на узких экранах). Теперь column + gap. */
.search-result-meta-wrap {
  display: inline-flex; flex-direction: column;
  align-items: flex-end; gap: 4px;
  flex-shrink: 0;
}
.search-result-meta {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 600;
  color: var(--color-gray-500); flex-shrink: 0;
  text-transform: uppercase; letter-spacing: 0.04em;
}
/* На active row используем brand-darker (#A83000) — даёт ≥6:1 контраста на brand-pale,
   тогда как brand (#E04000) на pale = 3.82:1 (фейл AA для 11px small text). */
.search-result.active .search-result-meta { color: var(--color-brand-darker); }
.search-result-badge {
  font-size: 10px; padding: 2px 6px;
  background: var(--color-brand); color: #fff;
  border-radius: 4px; font-weight: 700;
  letter-spacing: 0; text-transform: none;
  white-space: nowrap;
}
/* Очень узкие экраны (≤360) — kind-метка дублирует иконку слева, прячем
   её, остаётся только badge. На обычных мобилках 375-480 — оба видны. */
@media (max-width: 360px) {
  .search-result-meta-wrap .search-result-meta { display: none; }
}


/* Zero-result state */
.search-zero { padding: 20px; }
.search-zero-head { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 16px; }
.search-zero-ico {
  width: 40px; height: 40px; border-radius: 10px;
  background: var(--color-brand-pale); color: var(--color-brand);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.search-zero-title { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.3; color: var(--fg); }
.search-zero-title span { color: var(--color-brand); }
.search-zero-sub { margin: 4px 0 0; font-size: 13px; color: var(--color-gray-500); line-height: 1.4; }
.search-zero-form { display: grid; grid-template-columns: 1fr auto; gap: 8px; }
.search-zero-phone {
  font-family: inherit; font-size: 15px;
  padding: 10px 14px; min-height: 44px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg); color: var(--fg);
}
.search-zero-phone:focus { outline: none; border-color: var(--color-brand); box-shadow: 0 0 0 3px rgba(224, 64, 0,0.12); }
.search-zero-phone[aria-invalid="true"] { border-color: var(--color-error); box-shadow: 0 0 0 3px rgba(217,48,37,0.12); }

/* Универсальная подсветка невалидного телефона + helper-text под полем.
   Маска main.js ставит aria-invalid="true" в момент, когда юзер дошёл до 11 цифр
   и это не мобильный РФ (вторая цифра ≠ 9, двойная 7, иностранный, и т.п.).
   .phone-helper вставляется JS-ом сразу после input. */
input[type="tel"][aria-invalid="true"] {
  border-color: var(--color-error);
  box-shadow: 0 0 0 3px rgba(217,48,37,0.12);
}
.phone-helper {
  display: block;
  margin-top: 6px;
  color: var(--color-error);
  font-size: 13px;
  line-height: 1.35;
}
.phone-helper[hidden] { display: none; }
/* Внутри оранжевой формы (`.connect-new-fields`) обычный красный сливается
   с фоном (#D93025 на #E04000 — контраст ~1.5:1, fail WCAG).
   Делаем chip с белой подложкой и красным текстом — контрастно в любом контексте. */
.connect-new-fields .phone-helper {
  display: inline-block;
  padding: 4px 10px;
  background: #fff;
  border-radius: 6px;
  color: var(--color-error);
  font-weight: 500;
}
.search-zero-submit { padding: 0 18px; min-height: 44px; }
.search-zero-submit:disabled { opacity: 0.6; cursor: progress; }
.search-zero-success {
  margin: 12px 0 0; padding: 12px 14px;
  background: rgba(46,168,79,0.08); color: #1e7a36;
  border-radius: 10px; font-size: 14px; font-weight: 500;
}

/* Footer hints */
.search-footer {
  display: flex; gap: 16px; flex-wrap: wrap;
  padding: 10px 16px;
  border-top: 1px solid var(--color-gray-200);
  background: var(--color-gray-100);
  font-size: 12px; color: var(--color-gray-500);
  flex-shrink: 0;
}
.search-hint { display: inline-flex; align-items: center; gap: 4px; }
.search-hint svg { width: 12px; height: 12px; }

@media (prefers-reduced-motion: reduce) {
  .search-overlay-backdrop, .search-panel { animation: none; }
}

@media (max-width: 640px) {
  /* На мобильном поиск открывается попапом сверху, не на весь экран.
     Раньше .search-panel занимал 100vh + border-radius 0 — выглядел как
     самостоятельный экран, не как модалка над сайтом. Теперь видна часть
     контента под backdrop'ом и поведение типично для модального окна. */
  .search-overlay { padding: max(48px, 6dvh) 12px 12px; align-items: flex-start; }
  .search-panel {
    max-width: none; width: 100%;
    height: auto;
    /* Ограничиваем высоту с учётом dvh (живой viewport — учитывает клавиатуру iOS)
       и оставляем место сверху/снизу под backdrop. */
    max-height: min(560px, calc(100dvh - max(48px, 6dvh) - 24px));
    border-radius: 16px;
  }
  .search-form { padding: 14px 14px; }
  .search-footer { display: none; }
  .search-zero-form { grid-template-columns: 1fr; }
}

/* На мобильном чат-кнопка не нужна (есть мессенджеры в меню) — оставляем
   только лупу + телефон + CTA + бургер. Лупа стоит первой по порядку HTML. */
@media (max-width: 1100px) {
  .main-nav .right .quick-action.quick-chat { display: none; }
}

/* ============================================================================
   /help — Полезное и инструкции
   ============================================================================ */
.help-section { padding: 48px 0 64px; }
.help-head { max-width: 760px; margin-bottom: 40px; }
.help-head h1 {
  margin: 0 0 12px; font-size: 40px; line-height: 1.1; letter-spacing: -0.01em;
  color: var(--fg);
}
.help-head .eyebrow {
  display: inline-block; font-size: 12px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-brand); margin: 0 0 12px;
}
.help-subtitle { margin: 0; font-size: 17px; color: var(--color-gray-500); line-height: 1.5; }

.help-grid {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 48px;
  align-items: start;
}
/* Grid items по умолчанию имеют min-width:auto = их min-content. На mobile
   это раздувало .help-toc и .help-articles на ~8px шире .help-grid → горизонтальный
   скролл всей страницы. min-width:0 разрешает item ужиматься под column. */
.help-grid > * { min-width: 0; }

/* Sticky TOC */
.help-toc { position: sticky; top: 96px; }
.help-toc-label {
  margin: 0 0 12px;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-gray-500);
}
.help-toc nav ul { list-style: none; padding: 0; margin: 0; }
.help-toc nav li { margin: 0; }
.help-toc nav a {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 12px; border-radius: 8px;
  font-size: 14px; font-weight: 500; color: var(--fg);
  text-decoration: none;
  transition: background var(--duration) var(--easing), color var(--duration) var(--easing);
}
.help-toc nav a:hover { background: var(--color-brand-pale); color: var(--color-brand); }
.help-toc nav a.active { background: var(--color-brand-pale); color: var(--color-brand); }
.help-toc-count {
  font-size: 11px; font-weight: 600;
  padding: 2px 6px; border-radius: 4px;
  background: var(--color-gray-100); color: var(--color-gray-500);
  min-width: 20px; text-align: center;
}
.help-toc nav a:hover .help-toc-count,
.help-toc nav a.active .help-toc-count {
  background: var(--bg-elevated); color: var(--color-brand);
}
.help-toc-cta {
  margin-top: 20px; padding-top: 20px;
  border-top: 1px solid var(--color-gray-200);
}
.help-toc-cta-label { margin: 0 0 8px; font-size: 13px; color: var(--color-gray-500); }
.help-toc-cta .btn { width: 100%; gap: 8px; min-height: 40px; padding: 0 14px; font-size: 14px; }

/* Articles */
.help-articles { display: flex; flex-direction: column; gap: 56px; }
.help-block { scroll-margin-top: 96px; }
.help-block-title {
  margin: 0 0 6px; font-size: 28px; line-height: 1.15;
  color: var(--fg);
}
.help-block-sub {
  margin: 0 0 24px; font-size: 15px; color: var(--color-gray-500); line-height: 1.5;
}
.help-articles-list { display: flex; flex-direction: column; gap: 20px; }

.help-article {
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: 16px;
  padding: 28px 32px;
  scroll-margin-top: 96px;
  transition: border-color 200ms var(--easing), box-shadow 200ms var(--easing);
}
.help-article:target {
  border-color: var(--color-brand);
  box-shadow: 0 0 0 4px rgba(224, 64, 0, 0.08);
}
.help-article-title {
  margin: 0 0 4px; font-size: 20px; line-height: 1.3;
  color: var(--fg);
  display: flex; align-items: center; gap: 8px;
}
.help-article-anchor {
  font-size: 16px; color: var(--color-gray-300);
  text-decoration: none; opacity: 0;
  transition: opacity 200ms var(--easing), color 200ms var(--easing);
}
.help-article:hover .help-article-anchor,
.help-article:target .help-article-anchor { opacity: 1; }
.help-article-anchor:hover { color: var(--color-brand); }
.help-article-intent {
  margin: 0 0 16px; font-size: 13px;
  color: var(--color-gray-500); font-weight: 500;
}
.help-article-body { display: flex; flex-direction: column; gap: 10px; }
.help-article-body p {
  margin: 0; font-size: 15px; line-height: 1.55; color: var(--fg);
}
.help-article-cta {
  margin-top: 20px;
  display: flex; flex-wrap: wrap; gap: 10px;
}
.help-article-cta .btn {
  min-height: 40px; padding: 0 18px; font-size: 14px;
}
.help-article-cta .btn-ghost {
  background: var(--color-gray-100); color: var(--fg);
  border: 1px solid var(--color-gray-200);
}
.help-article-cta .btn-ghost:hover {
  background: var(--bg-elevated); border-color: var(--color-brand); color: var(--color-brand);
}

/* Tablet & mobile */
@media (max-width: 960px) {
  .help-grid { grid-template-columns: 1fr; gap: 32px; }
  .help-toc { position: static; }
  .help-toc nav ul {
    display: flex; flex-wrap: wrap; gap: 8px;
  }
  .help-toc nav a {
    padding: 8px 14px; border-radius: 999px;
    background: var(--color-gray-100);
  }
  .help-toc-cta { display: none; }
}
@media (max-width: 640px) {
  .help-section { padding: 32px 0 48px; }
  .help-head h1 { font-size: 30px; }
  .help-head { margin-bottom: 28px; }
  .help-block-title { font-size: 22px; }
  .help-article { padding: 22px 20px; }
  .help-article-title { font-size: 17px; }
  .help-articles { gap: 40px; }
  .help-article-cta .btn { width: 100%; justify-content: center; }
}
/* TOC-чипы шире viewport (~167–219px каждый), на узких mobile (≤380px)
   два в ряд уже не помещаются — рвутся за правый край. Раскладываем
   по одному на строку, формат list-row вместо chip-row. */
@media (max-width: 380px) {
  .help-toc nav ul { flex-direction: column; gap: 6px; }
  .help-toc nav li { width: 100%; }
  .help-toc nav a { width: 100%; }
}

/* ============================================================================
   Dark-mode brand-pale surfaces — warm-pale (oklch 0.30 .04 45) bg + brand
   orange text reads at ~1.1:1 (both warm + close in luminance). Switch the
   entire family to neutral cool gray (oklch 0.36 0 0) bg + brand-light
   (#FF5A1F) text. Pop comes from hue + chroma shift, not just lightness.
   AA-pass for both icons and labels on the cool gray surface.
   ============================================================================ */
/* GROUP A — static accent pills/cards: keep gray bg + brand-light text.
   These are phone/callback/form surfaces where brand-orange text is small
   and not the primary readable content (the surface itself signals brand). */
/* Утилитарка в dark — без border-bottom (серый --border читался как
   светлая полоса) и с едва заметно более светлым фоном (0.02 разницы
   в L), чтобы utility row отличалась от main-nav, но не выглядела
   отдельной плашкой. В light оставляем. */
:root[data-theme="dark"] .utility { border-bottom: 0; background: oklch(0.275 0.005 260); }

:root[data-theme="dark"] .city-menu a:hover,
:root[data-theme="dark"] .city-menu a.active,
:root[data-theme="dark"] .mega-link:hover,
:root[data-theme="dark"] .utility .phone,
:root[data-theme="dark"] .utility .lang-pill:hover,
:root[data-theme="dark"] .utility .theme-toggle.is-active,
:root[data-theme="dark"] .mobile-menu .mm-city-menu a:hover,
:root[data-theme="dark"] .mobile-menu .mm-city-menu a.active,
:root[data-theme="dark"] .mobile-menu .mm-phone,
:root[data-theme="dark"] .mobile-menu .mm-phone:active,
:root[data-theme="dark"] .mobile-menu .mm-row.mm-theme-toggle.is-active,
:root[data-theme="dark"] .help-toc nav a:hover,
:root[data-theme="dark"] .help-toc nav a.active,
:root[data-theme="dark"] .search-quick a:hover,
:root[data-theme="dark"] .search-quick-item:hover,
:root[data-theme="dark"] .search-result:hover,
:root[data-theme="dark"] .search-result.active,
:root[data-theme="dark"] .contact-card.cb,
:root[data-theme="dark"] .connect-form,
:root[data-theme="dark"] .check-tip {
  background: oklch(0.36 0 0);
  color: var(--color-brand-light);
}
/* В dark у элементов с тёмной активной подложкой (toggle «Тёмная тема»
 * в моб. меню и desktop-хедере, номер телефона .utility .phone) текст и
 * иконки делаем белыми — Pro Max #1: один primary brand-color на экран
 * (это «Подключить»), остальное нейтральное.
 * Подложка oklch(0.36 0 0) сохраняется как «active»-индикатор. */
:root[data-theme="dark"] .mobile-menu .mm-row.mm-theme-toggle.is-active,
:root[data-theme="dark"] .mobile-menu .mm-row.mm-theme-toggle.is-active .mm-ico,
:root[data-theme="dark"] .utility .phone,
:root[data-theme="dark"] .utility .phone svg {
  color: var(--fg);
}
/* Лого в dark — единым белым, как в футере (.f-logo). Плашка-«ламинат»
 * под brand-цвета — тяжёлая в шапке; футер же давно даёт ровный белый и
 * читается лучше. filter работает и на <svg use> (logo-combo), и на <img>
 * (EN-локаль logo-letai-tattelecom-en.svg). */
:root[data-theme="dark"] .main-nav .brand-row .logo-combo,
:root[data-theme="dark"] .mobile-menu .mm-header .mm-brand img,
:root[data-theme="dark"] .mobile-menu .mm-header .mm-brand svg {
  filter: brightness(0) invert(1);
}
/* DaData-подсказка active/hover — оставляем тёмный фон-индикатор, но
 * текст белым (--fg), а не оранжевым: длинные адреса оранжевым плохо
 * читаются и сливаются с brand-CTA. */
:root[data-theme="dark"] .dadata-item:hover,
:root[data-theme="dark"] .dadata-item.is-active {
  background: oklch(0.36 0 0);
  color: var(--fg);
}

/* GROUP B — eyebrows + active nav items: variant B (white text + orange
   icon). brand-light text on neutral gray gives only 3.5:1 — fails AA.
   Switch the readable label to white (#fff at oklch 0.97 → ~9:1 over gray)
   while keeping the icon brand-orange so the chip still feels branded. */
:root[data-theme="dark"] .check-v2-eyebrow,
:root[data-theme="dark"] .calc-eyebrow,
:root[data-theme="dark"] .eyebrow,
:root[data-theme="dark"] .tariff-hero-eyebrow,
:root[data-theme="dark"] .news-tag--inline,
:root[data-theme="dark"] .gift-eyebrow,
:root[data-theme="dark"] .main-nav .links a.active,
:root[data-theme="dark"] .main-nav .links .has-menu .menu-trigger.active,
:root[data-theme="dark"] .main-nav .links .menu-trigger--accent:hover,
:root[data-theme="dark"] .main-nav .links .menu-trigger--accent.active,
:root[data-theme="dark"] .utility .lang-pill.is-active,
:root[data-theme="dark"] .mobile-menu .mm-lang__pill.is-active,
:root[data-theme="dark"] .mobile-menu a.active,
:root[data-theme="dark"] .mobile-menu .mm-row.active {
  background: oklch(0.36 0 0);
  color: var(--fg);
}
/* В тёмной теме "Проверить адрес" в одном цветовом ряду с остальными пунктами
   шапки: текст белый, акцент остаётся только на иконке-пине. */
:root[data-theme="dark"] .main-nav .links .menu-trigger--accent { color: var(--fg); }
:root[data-theme="dark"] .main-nav .links .menu-trigger--accent svg { color: var(--color-brand); }
/* Eyebrows must remain short inline chips, not full-width bars. Some are
   on <p> elements which default to block — explicitly force inline-flex
   and tight padding so the gray bg hugs the text + icon only. */
:root[data-theme="dark"] .check-v2-eyebrow,
:root[data-theme="dark"] .calc-eyebrow,
:root[data-theme="dark"] .eyebrow,
:root[data-theme="dark"] .tariff-hero-eyebrow,
:root[data-theme="dark"] .news-tag--inline,
:root[data-theme="dark"] .gift-eyebrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: 999px;
  width: auto;
  max-width: max-content;
  align-self: flex-start;
  line-height: 1;
}
/* Icons inside eyebrows + active nav stay brand-orange for brand presence. */
:root[data-theme="dark"] .check-v2-eyebrow svg,
:root[data-theme="dark"] .calc-eyebrow svg,
:root[data-theme="dark"] .eyebrow svg,
:root[data-theme="dark"] .tariff-hero-eyebrow svg,
:root[data-theme="dark"] .news-tag--inline svg,
:root[data-theme="dark"] .gift-eyebrow svg,
:root[data-theme="dark"] .main-nav .links a.active svg,
:root[data-theme="dark"] .main-nav .links .menu-trigger.active svg,
:root[data-theme="dark"] .mobile-menu a.active svg,
:root[data-theme="dark"] .mobile-menu .mm-row.active .mm-ico,
:root[data-theme="dark"] .mobile-menu .mm-row.active svg {
  color: var(--color-brand-light);
}
/* Active main-nav pill — neutral gray chip + white text in dark theme.
   White on neutral gray gives ~9:1, well above AA. Earlier variant used
   brand-light text, but per request the highlighted nav item must stay
   white in dark to match the visual prominence of the surrounding labels. */
:root[data-theme="dark"] .main-nav .links a.active,
:root[data-theme="dark"] .main-nav .links .has-menu .menu-trigger.active {
  background: oklch(0.36 0 0);
  color: var(--fg);
  border-radius: 999px;
  padding: 8px 16px;
  font-weight: 700;
}
/* Chevron inside active menu-trigger stays in text color (white in dark),
   not brand-orange — matches the surrounding label. */
:root[data-theme="dark"] .main-nav .links .menu-trigger.active .chev {
  color: var(--fg);
}
/* Mobile-menu active row keeps the row layout — bg gray chip + orange text.
   Negative margin lets the bg pill extend into the menu's 24px gutter while
   content (icon + text) stays left-aligned with inactive rows. */
:root[data-theme="dark"] .mobile-menu .mm-row.active {
  background: oklch(0.36 0 0);
  color: var(--color-brand-light);
  border-radius: 12px;
  margin-left: -12px;
  margin-right: -12px;
  padding-left: 12px;
  padding-right: 12px;
  font-weight: 700;
}
:root[data-theme="dark"] .mobile-menu a.active {
  background: transparent;
}

/* Gift-card secondary badge (.gift-pill-paid, e.g. "100 ₽ выезд").
   In light theme bg=gray-700 (#4A4A4A dark gray) + white text reads fine.
   In dark theme gray-700 flips to oklch(0.86) — almost the same as white →
   1.5:1 contrast, label invisible. Pin an explicit dark surface here. */
:root[data-theme="dark"] .gift-pill-paid {
  background: oklch(0.30 0.005 260);
  color: var(--fg);
  box-shadow: 0 2px 6px -2px rgba(0, 0, 0, 0.4);
}
/* Gift-panel eyebrow: inline orange text + icon, no chip. The .eyebrow rule
   above adds a gray chip background that we don't want on the brown gift panel. */
:root[data-theme="dark"] .gift-panel .gift-eyebrow {
  background: transparent;
  color: var(--color-brand-light);
  padding: 0;
}
/* Color-only lifts: hover/active text on plain page bg (no chip). brand-orange
   #E04000 → brand-light #FF5A1F over page bg for AA contrast.
   NOTE: .mobile-menu a.active and .mm-row.active are handled by the variant-B
   block above (white text + orange icon) — don't re-color them here. */
:root[data-theme="dark"] .mobile-menu .mm-row:active,
:root[data-theme="dark"] .mobile-menu .mm-toggle:hover,
:root[data-theme="dark"] .utility .seg-tab.active,
:root[data-theme="dark"] .hero-bar .hero-seg a:not(.active):hover,
:root[data-theme="dark"] .mobile-menu .mm-segment a:not(.active):hover {
  color: var(--color-brand-light);
}
/* Icons inside :hover/:active mm-row stay orange. */
:root[data-theme="dark"] .mobile-menu .mm-row:hover .mm-ico,
:root[data-theme="dark"] .mobile-menu .mm-row:active .mm-ico {
  color: var(--color-brand-light);
}
/* .contact-card.cb also has border-color: brand-pale → desaturate to match */
:root[data-theme="dark"] .contact-card.cb,
:root[data-theme="dark"] .connect-form {
  border-color: oklch(0.42 0.005 260);
}

/* Icon squares — switch warm brand-pale bg to neutral cool gray in dark.
   Original design: bg --color-brand-pale + icon --color-brand. In dark
   mode both are warm + close in luminance → merge visually. Neutral gray
   bg gives chromatic separation: warm orange icon pops on cool gray.
   Active-state variants (e.g. .calc-toggle.on) keep their brand-filled style. */
:root[data-theme="dark"] .check-v2-side-header .ico,
:root[data-theme="dark"] .check-v2-tariff-card-ico,
:root[data-theme="dark"] .mega-link .ico,
:root[data-theme="dark"] .contact-card .ico,
:root[data-theme="dark"] .gift-card-ico,
:root[data-theme="dark"] .calc-toggle:not(.on) .calc-toggle-icon,
:root[data-theme="dark"] .about-feature .ico,
:root[data-theme="dark"] .tariff-services-icon,
:root[data-theme="dark"] .howto-card-icon,
:root[data-theme="dark"] .b-cat-ico,
:root[data-theme="dark"] .b-included-item .ico,
:root[data-theme="dark"] .search-zero-ico,
:root[data-theme="dark"] .search-result-kind,
:root[data-theme="dark"] .hero-v3l-feature .ic,
:root[data-theme="dark"] .why-feat-ico,
:root[data-theme="dark"] .why-item .ico,
:root[data-theme="dark"] .why-grid .ico,
:root[data-theme="dark"] .b-industries-grid li .b-ind-ico,
:root[data-theme="dark"] .b-extras .b-extra-ico,
:root[data-theme="dark"] .b-why .b-why-ico,
:root[data-theme="dark"] .b-contacts-strip .item .ico {
  background: oklch(0.36 0 0);
  color: var(--color-brand-light);
}

/* Business-page tinted section ("Что входит") — soft warm wash. In dark
   mode flip to neutral elevated surface so the page reads as a unified
   slate gray rather than a warm tint band. */
:root[data-theme="dark"] section.b-included {
  background: var(--bg-soft);
}

/* Gift-card top border highlight — inset 0 1px 0 rgba(255,255,255,0.6) was
   designed for light theme glass-effect. In dark theme it renders as a
   bright white line across the top of every card — visually loud and
   chromatic break. Strip the white inset; keep the outer drop shadow. */
:root[data-theme="dark"] .gift-card {
  box-shadow: 0 4px 14px -8px rgba(0, 0, 0, 0.25);
  border-color: rgba(255, 90, 31, 0.12);
}
:root[data-theme="dark"] .gift-card:hover {
  box-shadow: 0 18px 30px -16px rgba(255, 90, 31, 0.28);
  border-color: rgba(255, 90, 31, 0.30);
}

/* ============================================================================
   Dark-mode outlined buttons — brand orange (#E04000) on dark bg has poor
   contrast (~2.6:1, fails AA). Switch to brand-light (#FF5A1F). Background
   stays transparent so the page shows through — warm border + warm text on
   cool slate-gray pop, no muddy "warm bg + warm text" merge.
   ============================================================================ */
:root[data-theme="dark"] .btn-secondary,
:root[data-theme="dark"] .help-article-cta .btn-ghost:hover {
  background: transparent;
  border-color: var(--brand-on-dark);
  color: var(--brand-on-dark);
}
:root[data-theme="dark"] .btn-secondary:hover {
  background: rgba(255, 90, 31, 0.10);
  border-color: var(--color-brand-light);
  color: var(--color-brand-light);
}
/* Catch-all for any other outlined-orange button: if both border and text
   are var(--color-brand), upgrade to brand-light in dark for AA contrast. */
/* Same for the popular-tariff override that uses white outline — keep it
   white because that lives on the always-orange .tariff.popular bg. */

/* ============================================================================
   Dark-mode brand-orange sections — bright #E04000 against slate-gray rest
   of the page is jarring. Mute to a deeper warm tone (--color-brand-darker
   = #A83000, oklch 0.46) so the section still reads as branded but doesn't
   shout. White text contrast ~6:1 — passes AA.
   ============================================================================ */
:root[data-theme="dark"] section.connect-orange,
:root[data-theme="dark"] .hero {
  background: var(--color-brand-darker);
}
/* The .hero rule above replaces the bright orange gradient. If you want it
   to feel less flat, restore the gradient with darker stops only in dark. */
:root[data-theme="dark"] .hero {
  background: linear-gradient(180deg, var(--color-brand-darker) 0%, oklch(0.36 0.10 40) 100%);
}

/* ============================================================================
   Dark-mode brand-orange surfaces — solid bright-orange fills (#E04000) on
   cards, primary buttons, sticky CTAs and the calc summary panel feel too
   shouty next to the muted slate page background. Drop them to brand-darker
   (#A83000, oklch 0.46) so they stay clearly branded but recede a notch.
   White text on darker tone still holds ~5:1 contrast → AA pass.
   Hover restores brand-light edge highlight (#FF5A1F) for clear feedback.
   ============================================================================ */
:root[data-theme="dark"] .tariff.popular,
:root[data-theme="dark"] .btn-primary,
:root[data-theme="dark"] .btn-v3l-primary,
:root[data-theme="dark"] .check-v2-btn-primary,
:root[data-theme="dark"] .sticky-cta,
:root[data-theme="dark"] .calc-sticky-mobile-cta,
:root[data-theme="dark"] .check-v2-btn-secondary {
  background: var(--color-brand-darker);
  border-color: var(--color-brand-darker);
  color: #fff;
}
:root[data-theme="dark"] .btn-primary:hover,
:root[data-theme="dark"] .btn-v3l-primary:hover,
:root[data-theme="dark"] .check-v2-btn-primary:hover,
:root[data-theme="dark"] .sticky-cta:hover,
:root[data-theme="dark"] .calc-sticky-mobile-cta:hover {
  background: var(--color-brand);
  border-color: var(--color-brand);
}
/* Calc summary panel (.calc-side) had a 3-stop bright-orange gradient.
   Replace with a single muted brand-darker tone + subtle internal glow so
   it still feels lifted, just quieter. */
:root[data-theme="dark"] .calc-side {
  background:
    radial-gradient(120% 80% at 100% 0%, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0) 55%),
    radial-gradient(80% 60% at 0% 100%, rgba(0,0,0,0.20) 0%, rgba(0,0,0,0) 60%),
    var(--color-brand-darker);
  box-shadow: 0 16px 40px -20px rgba(0,0,0,0.6), 0 1px 2px rgba(0,0,0,0.3);
}
/* The .tariff.popular .cta (white pill button) — its label "Подключить"
   was brand-orange #E04000. On the darker-brand bg now, brand text reads OK,
   but bump to brand-darker for a little more weight (white pill is high
   contrast either way). Keep white bg.
   Why bg/border are restated: the group rule above (`:root[data-theme="dark"]
   .btn-primary`) has equal specificity to `.tariff.popular .btn-primary` and
   wins by source order, so it paints the CTA brand-darker → same tone as the
   card bg → invisible. Restate to win on source order. */
:root[data-theme="dark"] .tariff.popular .cta,
:root[data-theme="dark"] .tariff.popular .btn-primary {
  background: #fff;
  border-color: #fff;
  color: var(--color-brand-darker);
}
:root[data-theme="dark"] .tariff.popular .cta:hover,
:root[data-theme="dark"] .tariff.popular .btn-primary:hover {
  background: #fff;
  border-color: #fff;
  color: var(--color-brand-darker);
  box-shadow: 0 6px 20px rgba(0,0,0,0.32);
  transform: translateY(-1px);
}

/* ============================================================================
   Dark-mode segment switches — variant E (underline indicator).
   Tab/segment is selected via:
   • neutral gray container fill — same family as other dark surfaces
   • WHITE text (8:1 over gray → WCAG AAA pass) — high readability
   • brand-orange icon — keeps brand presence as accent
   • orange bottom border as a tab-indicator (color-not-only rule satisfied)
   Inactive tabs stay muted; active tab pops via the orange line.
   Passes ui-ux-pro-max: color-contrast / color-not-only / state-clarity.
   ============================================================================ */
:root[data-theme="dark"] .hero-bar .hero-seg a.active,
:root[data-theme="dark"] .mobile-menu .mm-segment a.active,
:root[data-theme="dark"] .utility .lang-pill.is-active,
:root[data-theme="dark"] .mobile-menu .mm-lang__pill.is-active {
  background: transparent;
  color: var(--fg);
  /* Subtle neutral 1px ring (same as .menu-trigger--accent outlined button).
     Following the page bg, the white text reads cleanly while the soft gray
     border marks the active state. Brand stays in the icon. */
  box-shadow: inset 0 0 0 1px var(--border);
}

/* Icons inside active tabs stay brand-orange for brand presence. */
:root[data-theme="dark"] .hero-bar .hero-seg a.active svg,
:root[data-theme="dark"] .tariff-tabs button.active svg,
:root[data-theme="dark"] .mobile-menu .mm-segment a.active svg {
  color: var(--color-brand-light);
}

/* Run-13b M5: drawer segment "Для дома / Для бизнеса" в dark — solid bg вместо
   слабого 1px inset ring. Outside of это override остальные tabs (hero-seg,
   tariff-tabs, lang-pill) keep the neutral ring pattern. */
:root[data-theme="dark"] .mobile-menu .mm-segment a.active {
  background: var(--border-strong);
  color: var(--fg);
  box-shadow: 0 1px 2px rgba(0,0,0,0.3);
}
/* Hover на неактивном — нейтральный lighter bg, не бренд (предотвращает
   путаницу "что выбрано") */
:root[data-theme="dark"] .mobile-menu .mm-segment a:not(.active):hover {
  background: var(--border);
  color: var(--fg);
}

/* Smaller chips/labels that still used brand-pale (warm) bg — give them the
   same neutral gray treatment as the active pills. */
:root[data-theme="dark"] .why-feat-meta,
:root[data-theme="dark"] .howto-eta {
  background: oklch(0.36 0 0);
  color: var(--brand-on-dark);
}
/* Theme-toggle desktop (utility pill) — explicit bg override so it doesn't
   fall back to brand-pale token. Текст и иконка белые (var(--fg)), как
   в моб. меню — один primary brand-color на экран. */
:root[data-theme="dark"] .utility .theme-toggle.is-active,
:root[data-theme="dark"] .utility .theme-toggle.is-active:hover {
  background: oklch(0.36 0 0);
  color: var(--fg);
}

/* ============================================================================
   Theme toggle — single moon icon, 2-state (off/on).
   Active state = dark theme is on. Lights up brand-pale + brand color.
   Two placements share the same data-theme-toggle attribute:
   • .theme-toggle  — desktop utility row pill (icon only)
   • .mm-theme-toggle — mobile menu row (icon + "Тёмная тема" label)
   ============================================================================ */
/* Scoped under .utility to outweigh .utility button (0,1,1 specificity).
   Pill shape: icon + visible "Тёмная тема" label. Visible only on >1100px
   (utility row is hidden below that — see media block ~line 1476). */
.utility .theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  border-radius: 999px;
  background: transparent; border: 0; cursor: pointer;
  color: var(--fg-muted);
  flex-shrink: 0;
  font: inherit; font-size: 13px; font-weight: 500; line-height: 1;
  transition: background var(--duration) var(--easing), color var(--duration) var(--easing);
}
.utility .theme-toggle:hover { background: var(--color-gray-100); color: var(--color-brand); }
.utility .theme-toggle.is-active { background: var(--color-brand-pale); color: var(--color-brand); }
.utility .theme-toggle.is-active:hover { background: var(--color-brand-pale); color: var(--color-brand-dark); }
.utility .theme-toggle:focus-visible { outline: 2px solid var(--color-brand); outline-offset: 2px; }
.utility .theme-toggle .ti { width: 18px; height: 18px; flex-shrink: 0; }
.theme-toggle-label { white-space: nowrap; }

/* Mobile-menu variant — full-width row, 24px icon + label */
.mm-theme-toggle {
  width: 100%; appearance: none;
  background: none; border: 0; padding: 12px 0;
  min-height: 52px;
  display: flex; align-items: center; gap: 12px;
  font: inherit; font-size: 17px; font-weight: 600;
  color: var(--fg);
  text-align: left; cursor: pointer;
  touch-action: manipulation;
  border-radius: 12px;
  transition: color var(--duration) var(--easing), background var(--duration) var(--easing);
}
.mm-theme-toggle .mm-ico {
  flex-shrink: 0; width: 24px; height: 24px;
  color: var(--color-gray-500);
  transition: color var(--duration) var(--easing);
}
.mm-theme-toggle:hover { color: var(--color-brand); }
.mm-theme-toggle:hover .mm-ico { color: var(--color-brand); }
/* Active state = dark theme on. Pill background + brand color spans the whole row. */
.mm-theme-toggle.is-active {
  background: var(--color-brand-pale);
  color: var(--color-brand);
  padding: 12px 14px;
}
.mm-theme-toggle.is-active .mm-ico { color: var(--color-brand); }

/* ============================================================================
   Dark-theme prompt — subtle hint shown above hero when system prefers dark
   and the user hasn't picked a theme yet. Mobile only (≤1100px).
   Neutral muted styling — small text, no brand color, no scrim, no close.
   Hidden by default; JS removes [hidden] when conditions are met.
   ============================================================================ */
.dark-prompt {
  background: transparent;
  padding: 6px 0 0;
}
.dark-prompt[hidden] { display: none !important; }
.dark-prompt-inner {
  display: flex; align-items: center;
  justify-content: flex-end;
}
.dark-prompt-cta {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 8px;
  background: transparent; border: 0;
  font: inherit; font-size: 12px; font-weight: 500;
  color: var(--fg-muted);
  cursor: pointer;
  border-radius: 6px;
  touch-action: manipulation;
  transition: color var(--duration) var(--easing);
}
.dark-prompt-cta:hover,
.dark-prompt-cta:focus-visible {
  color: var(--fg);
  outline: none;
}
.dark-prompt-cta .ti { flex-shrink: 0; opacity: 0.85; transition: opacity var(--duration) var(--easing), fill var(--duration) var(--easing); }
/* Active state — dark theme is on. Slightly more emphasized text + filled
   moon icon, but stays neutral (no brand color, no background). */
.dark-prompt-cta.is-active {
  color: var(--fg);
  font-weight: 600;
}
.dark-prompt-cta.is-active .ti {
  opacity: 1;
  fill: currentColor;
}
/* Banner is phone-only — at ≥769px the main-nav has its own theme button
   (.quick-action.quick-theme on tablet, .theme-toggle on desktop), so the
   banner would duplicate the control. Also hide on mobile now that
   .mobile-top-bar surfaces the same control with a permanent pill. */
@media (min-width: 769px) {
  .dark-prompt { display: none !important; }
}
@media (max-width: 1100px) {
  .dark-prompt { display: none !important; }
}

/* ============================================================================
   /za-gorodom — хаб GPON-посёлков и одиночные карточки посёлков
   ============================================================================ */
.section { padding: 56px 0; }
@media (max-width: 720px) {
  .section { padding: 36px 0; }
}
.section--hero-light { padding: 56px 0 32px; }
.section--hero-light h1 { font-size: 40px; line-height: 1.15; margin: 8px 0 16px; max-width: 880px; }
@media (max-width: 720px) {
  .section--hero-light { padding: 32px 0 20px; }
  .section--hero-light h1 { font-size: 28px; }
}

.breadcrumbs { font-size: 13px; color: var(--color-gray-500, #6b7280); margin: 0 0 12px; display: flex; flex-wrap: wrap; gap: 6px; }
.breadcrumbs a { color: inherit; text-decoration: none; }
.breadcrumbs a:hover { text-decoration: underline; }
.breadcrumbs .sep { opacity: 0.55; }
.breadcrumbs [aria-current="page"] { color: var(--fg, #111); font-weight: 500; }

.lede.small { font-size: 15px; max-width: 860px; }

.village-search { display: block; position: relative; margin: 0 0 16px; max-width: 560px; }
.village-search input {
  width: 100%; padding: 12px 16px 12px 44px; font-size: 16px; min-height: 48px;
  border: 1px solid var(--border, #d1d5db);
  border-radius: 10px;
  background: var(--bg-elevated, #fff);
  color: var(--fg, #111);
  box-sizing: border-box;
}
.village-search input::placeholder { color: var(--color-gray-500); }
.village-search input:focus { outline: 2px solid var(--color-brand, #fa4906); outline-offset: 2px; border-color: var(--color-brand, #fa4906); }
.village-search::before {
  content: "";
  position: absolute;
  left: 16px; top: 50%;
  width: 18px; height: 18px;
  transform: translateY(-50%);
  background: currentColor;
  color: var(--color-gray-500);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><path d='m21 21-4.3-4.3'/></svg>") no-repeat center / contain;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><path d='m21 21-4.3-4.3'/></svg>") no-repeat center / contain;
  pointer-events: none;
}

/* Neighbor-rayon list — rayon page ----------------------------------------- */
.neighbor-rayon-list {
  list-style: none; padding: 0; margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px;
}
.neighbor-rayon-list__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-4, 16px);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
  transition: border-color var(--duration, 200ms) var(--easing);
}
.neighbor-rayon-list__item:hover { border-color: var(--color-brand); }
.neighbor-rayon-list__link {
  font-size: var(--text-body, 16px);
  font-weight: 600;
  color: var(--link);
  text-decoration: none;
}
.neighbor-rayon-list__link:hover { color: var(--link-hover); text-decoration: underline; }
.neighbor-rayon-list__count {
  font-size: var(--text-body-sm, 14px);
  color: var(--fg-muted);
}

/* Top-settlements list — rayon page ---------------------------------------- */
.top-settlement-list {
  list-style: none; padding: 0; margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 8px;
}
.top-settlement-list__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3, 12px);
  padding: var(--space-3, 12px) var(--space-4, 16px);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
}
.top-settlement-list__link {
  font-size: var(--text-body, 16px);
  font-weight: 600;
  color: var(--link);
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.top-settlement-list__link:hover { color: var(--link-hover); text-decoration: underline; }
.top-settlement-list__pop {
  font-size: var(--text-body-sm, 14px);
  color: var(--fg-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Factbox — stat bar on rayon page ---------------------------------------- */
.rayon-factbox {
  display: flex;
  flex-wrap: wrap;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 8px);
  padding: var(--space-3, 12px) 0;
  margin: var(--space-6, 24px) 0 0;
}
.rayon-factbox__cell {
  flex: 1 1 0;
  min-width: 110px;
  padding: var(--space-3, 12px) var(--space-5, 20px);
  border-right: 1px solid var(--border);
}
.rayon-factbox__cell:last-child { border-right: 0; }
.rayon-factbox__num {
  display: block;
  font-size: 26px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--color-brand, #e04000);
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.01em;
}
.rayon-factbox__label {
  display: block;
  font-size: var(--text-body-sm, 14px);
  color: var(--fg-muted);
  margin-top: 2px;
}
@media (max-width: 480px) {
  .rayon-factbox { flex-wrap: wrap; }
  .rayon-factbox__cell {
    flex: 1 1 calc(50% - 1px);
    min-width: 0;
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }
  .rayon-factbox__cell:last-child { border-bottom: 0; }
  .rayon-factbox__cell:nth-child(odd) { border-right: 1px solid var(--border); }
}

.village-list {
  list-style: none; padding: 0; margin: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px 16px;
}
/* Collapse village list — hide tail past 60 items on desktop, 24 on mobile.
   Selectors target only direct .village-list__item children so structural
   helpers (search inputs, empty-state) aren't affected. JS removes the class
   when the user clicks "Показать все" or types in the search field. */
.village-list.is-collapsed > .village-list__item:nth-child(n+61) { display: none; }
@media (max-width: 768px) {
  .village-list.is-collapsed > .village-list__item:nth-child(n+25) { display: none; }
}
/* Collapse rayon grid only on mobile — desktop already fits 43 cards in 3 cols. */
@media (max-width: 768px) {
  .rayon-grid.is-collapsed-mobile > .rayon-card:nth-child(n+9) { display: none; }
}
.show-all-btn {
  display: block;
  margin: 20px auto 0;
  padding: 10px 28px;
  font: inherit;
  font-weight: 500;
  color: var(--fg);
  background: transparent;
  border: 1px solid var(--border, rgba(0,0,0,0.16));
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--duration) var(--easing), border-color var(--duration) var(--easing), color var(--duration) var(--easing);
}
.show-all-btn:hover {
  background: var(--bg-soft, rgba(0,0,0,0.04));
  border-color: var(--color-brand, #fa4906);
  color: var(--color-brand, #fa4906);
}
.show-all-btn[hidden] { display: none !important; }
.show-all-btn--mobile-only { display: none; }
@media (max-width: 768px) { .show-all-btn--mobile-only { display: block; } }
.village-list__item { padding: 6px 0; display: flex; align-items: center; gap: 8px; }
.village-list__item a { color: var(--fg, #111); text-decoration: none; }
.village-list__item a:hover { color: var(--brand, #fa4906); text-decoration: underline; }
.village-list__item.is-building a { color: var(--color-gray-500, #6b7280); }
.village-list__loading { color: var(--fg-muted); font-style: italic; }

.badge--soon {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px;
  padding: 2px 6px; border-radius: 4px; font-weight: 600;
  background: rgba(250, 73, 6, 0.1); color: var(--brand, #fa4906);
}

.village-list__nope { margin: 24px 0 0; color: var(--color-gray-500, #6b7280); font-size: 14px; }
.village-list__more { margin: 16px 0 0; }
.village-list__more a { color: var(--color-brand, #fa4906); font-weight: 500; text-decoration: none; }
.village-list__more a:hover { text-decoration: underline; }

/* Soft section background */
.section--soft { background: var(--bg-soft, rgba(0, 0, 0, 0.02)); }

/* Eyebrow above H1 on settlement page */
.eyebrow { display: inline-block; margin: 0 0 12px; font-size: 14px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-gray-500, #6b7280); }

/* Hero layout for settlement page — copy + facts side-by-side on desktop.
   margin-top: 32px — отступ от .village-toggle (segment control) на /flat,
   без него pill-переключатель слипается с eyebrow и читается как один блок. */
.village-hero { display: grid; grid-template-columns: 1fr; gap: 32px; margin-top: 32px; }
@media (min-width: 900px) {
  .village-hero { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); align-items: start; }
}

/* Переключатель «Частный дом / Квартира» на странице нас. пункта */
.village-toggle {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  margin: 24px 0 0;
  background: var(--bg-elevated, #fff);
  border: 1px solid var(--border, rgba(0,0,0,0.08));
  border-radius: 12px;
}
.village-toggle__btn {
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-gray-600, #4b5563);
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}
.village-toggle__btn:hover { background: rgba(0, 0, 0, 0.04); }
.village-toggle__btn.is-active {
  background: var(--color-brand, #fa4906);
  color: #fff;
}
.village-toggle__btn.is-active:hover { background: var(--color-brand, #fa4906); }
/* Dark: неактивная кнопка — серый #4b5563 сливался с тёмной панелью;
   подменяем на --color-gray-500 (oklch 0.74 в dark) — приглушённый светлый.
   :not(.is-active) — критично, иначе перебивает color:#fff активной кнопки
   на оранжевом фоне (тогда «Квартира» становится серой на оранжевом). */
:root[data-theme="dark"] .village-toggle__btn:not(.is-active) { color: var(--color-gray-500); }
:root[data-theme="dark"] .village-toggle__btn:not(.is-active):hover { background: rgba(255, 255, 255, 0.06); }
.village-hero__copy h1 { margin: 0 0 16px; }
.village-hero__type { margin: 0 0 16px; font-size: 15px; color: var(--color-gray-500, #6b7280); }
.village-hero__copy .lede { max-width: 640px; }
.village-hero__cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; }
.btn-ghost { background: transparent; color: var(--fg, #111); border: 1px solid var(--border, rgba(0,0,0,0.12)); padding: 10px 18px; border-radius: 8px; font-weight: 500; text-decoration: none; }
.btn-ghost:hover { background: rgba(0, 0, 0, 0.04); }

.village-hero__facts {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
  padding: 24px; border-radius: 14px;
  background: var(--bg-elevated, #fff); border: 1px solid var(--border, rgba(0,0,0,0.08));
}
.village-hero__facts .fact { padding: 8px 4px; }
.village-hero__facts .fact__num { font-size: 26px; font-weight: 700; line-height: 1.1; color: var(--color-brand, #fa4906); }
.village-hero__facts .fact__lbl { margin-top: 4px; font-size: 13px; color: var(--color-gray-500, #6b7280); }

/* Hero photo on ADSL village pages — replaces facts aside in the 2-col grid. */
.village-hero__art {
  display: block;
  border-radius: 16px;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  background: var(--bg-elevated, #fff);
  box-shadow: 0 1px 2px rgba(0,0,0,0.04), 0 8px 24px rgba(0,0,0,0.06);
}
.village-hero__art img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Horizontal facts row below the ADSL hero — replaces the boxed 2x2 plate. */
@media (max-width: 720px) {
}

/* 3-card "benefits with photos" row on ADSL village page — under the hero. */
.village-benefits {
  list-style: none; padding: 0; margin: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px;
}
@media (max-width: 900px) {
  .village-benefits { grid-template-columns: 1fr; gap: 20px; }
}
.village-benefit {
  background: var(--bg-elevated, #fff);
  border: 1px solid var(--border, rgba(0,0,0,0.08));
  border-radius: 16px;
  overflow: hidden;
  display: flex; flex-direction: column;
}
.village-benefit picture { display: block; aspect-ratio: 16 / 10; overflow: hidden; }
.village-benefit picture img { width: 100%; height: 100%; object-fit: cover; display: block; }
.village-benefit__body { padding: 20px 22px 24px; }
.village-benefit h3 { font-size: 18px; font-weight: 700; line-height: 1.3; margin: 0 0 8px; letter-spacing: -0.005em; }
.village-benefit p { font-size: 14px; color: var(--color-gray-500, #6b7280); line-height: 1.55; margin: 0; }

/* Rayon grid on /za-gorodom hub */
.rayon-grid {
  list-style: none; padding: 0; margin: 24px 0 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px;
}
.rayon-card { display: block; }
.rayon-card__link {
  display: block; padding: 14px 16px; border-radius: 10px;
  background: var(--bg-elevated, #fff); border: 1px solid var(--border, rgba(0,0,0,0.08));
  text-decoration: none; color: var(--fg, #111);
  transition: border-color 150ms ease, transform 150ms ease;
}
.rayon-card__link:hover { border-color: var(--color-brand, #fa4906); transform: translateY(-1px); }
.rayon-card__name { display: block; font-weight: 600; font-size: 15px; }
.rayon-card__meta { display: block; margin-top: 4px; font-size: 13px; color: var(--color-gray-500, #6b7280); }
.rayon-card__soon { color: var(--color-brand, #fa4906); }

/* ============================================================================
   City ↔ rayon cross-link card (perelinkovka)
   ----------------------------------------------------------------------------
   Тонкий блок между секциями. Не должен «кричать», но должен быть кликабельным
   на всю площадь и узнаваемым (иконка + eyebrow + заголовок).
   ============================================================================ */
.crl { padding: 16px 0; }
.crl-card {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px;
  background: var(--color-gray-50, #f7f7f8);
  border: 1px solid var(--color-gray-200, #e5e7eb);
  border-radius: 12px;
  text-decoration: none; color: inherit;
  transition: border-color .15s, transform .15s, background .15s;
}
.crl-card:hover {
  border-color: var(--color-brand, #fa4906);
  background: #fff;
  transform: translateY(-1px);
}
.crl-ico {
  flex: 0 0 auto;
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-brand, #fa4906); color: #fff;
  border-radius: 8px;
}
.crl-ico svg { width: 18px; height: 18px; }
.crl-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.crl-eyebrow { font-size: 13px; color: var(--color-gray-500, #6b7280); }
.crl-title { font-size: 15px; font-weight: 600; color: var(--color-text, #111); }
@media (max-width: 640px) {
  .crl-card { padding: 12px 14px; gap: 12px; }
  .crl-eyebrow { font-size: 12px; }
  .crl-title { font-size: 14px; }
}

/* ============================================================================
   Office card on city pages (NAP block — name/address/phone)
   ============================================================================ */
.office-card {
  max-width: 720px;
  margin: 24px 0 0;
  padding: 24px 28px;
  background: var(--color-gray-50, #f7f7f8);
  border: 1px solid var(--color-gray-200, #e5e7eb);
  border-radius: 14px;
}
.office-card__row {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 16px;
  padding: 12px 0;
}
/* Разделители между строками: border-top на втором и далее. Прежнее
   `:last-of-type { border-bottom:0 }` не работало — :last-of-type выбирает
   по тегу, а все дочерние элементы карточки — <div>, последним div идёт
   .office-card__actions, поэтому border-bottom у строки «Часы работы»
   оставался и давал двойную линию перед кнопками. */
.office-card__row + .office-card__row {
  border-top: 1px solid var(--color-gray-200, #e5e7eb);
}
.office-card__label { color: var(--color-gray-500, #6b7280); font-size: 14px; }
.office-card__value { color: var(--color-text, #111); font-size: 15px; font-weight: 500; }
.office-card__value--link { color: var(--color-brand, #fa4906); text-decoration: none; }
.office-card__value--link:hover { text-decoration: underline; }
.office-card__actions {
  display: flex; gap: 12px; flex-wrap: wrap;
  margin-top: 16px; padding-top: 16px;
  border-top: 1px solid var(--color-gray-200, #e5e7eb);
}
.office-card__actions .btn { display: inline-flex; align-items: center; gap: 8px; }
@media (max-width: 640px) {
  .office-card { padding: 18px 20px; }
  .office-card__row { grid-template-columns: 1fr; gap: 4px; padding: 10px 0; }
  .office-card__label { font-size: 14px; }
  .office-card__actions { flex-direction: column; }
  .office-card__actions .btn { justify-content: center; }
}

/* Dark-mode office card — light gray-50 surface (#f7f7f8) is near-white,
   reads as a giant bright block on dark theme. Swap to elevated dark
   surface, dim the dividers, lift text colors. */
:root[data-theme="dark"] .office-card {
  background: var(--bg-elevated);
  border-color: rgba(255, 255, 255, 0.08);
}
:root[data-theme="dark"] .office-card__row + .office-card__row,
:root[data-theme="dark"] .office-card__actions {
  border-top-color: rgba(255, 255, 255, 0.08);
}
:root[data-theme="dark"] .office-card__label {
  color: var(--fg-on-dark-muted);
}
:root[data-theme="dark"] .office-card__value {
  color: var(--fg);
}
:root[data-theme="dark"] .office-card__value--link {
  color: var(--color-brand-light);
}

/* ============================================================================
   Dark-mode "no small orange text" — brand-orange on dark gives ~3.5:1
   which fails AA for regular text (needs 4.5:1) but passes AA for "large"
   text (≥18px regular OR ≥14px bold) where 3:1 is enough.
   Rule: any brand-orange label/meta below 16px is bumped to 14-15px + bold
   in dark theme so it lands in the "large text" tier and reads clearly.
   Bonus: color lifted to brand-light where it was the muted brand-dark.
   ============================================================================ */
:root[data-theme="dark"] .gift-card-meta {
  font-size: 14px;
  font-weight: 700;
  color: var(--brand-on-dark);
  border-top-color: rgba(255, 90, 31, 0.20);
}
:root[data-theme="dark"] .badge.badge--soon,
:root[data-theme="dark"] .badge--soon {
  font-size: 14px;
  font-weight: 700;
  color: var(--color-brand-light);
  background: oklch(0.36 0 0);
}
/* "Казань" city picker active label — 14-15px medium; bump weight so 3.48:1
   on neutral gray lands in WCAG large-text tier. */
:root[data-theme="dark"] .city-btn,
:root[data-theme="dark"] .city-menu a.active,
:root[data-theme="dark"] .mobile-menu .mm-city-menu a.active {
  font-weight: 700;
}
/* Theme-toggle pill label (13px) — bump to 14px + bold so brand-light passes
   large-text tier on the gray pill. */
:root[data-theme="dark"] .theme-toggle-label {
  font-size: 14px;
  font-weight: 700;
}
/* Eyebrows (.calc-eyebrow etc) already at 12px 600 — bump to 14px bold so
   orange icon + label visually anchor and label itself isn't tiny. */
:root[data-theme="dark"] .check-v2-eyebrow,
:root[data-theme="dark"] .calc-eyebrow,
:root[data-theme="dark"] .eyebrow,
:root[data-theme="dark"] .tariff-hero-eyebrow,
:root[data-theme="dark"] .news-tag--inline,
:root[data-theme="dark"] .gift-eyebrow {
  font-size: 13px;
  font-weight: 700;
}
/* Catch-all bump for orange chip/label/badge text — anything that was below
   the large-text bar (14px regular) gets bumped to 14px+ bold. */
:root[data-theme="dark"] .utility .phone,
:root[data-theme="dark"] .why-feat-meta,
:root[data-theme="dark"] .howto-eta,
:root[data-theme="dark"] .gift-panel,
:root[data-theme="dark"] .rayon-card__soon,
:root[data-theme="dark"] .tariff .badge,
:root[data-theme="dark"] .tariff-card .badge {
  font-size: 14px;
  font-weight: 700;
}
/* Active nav/lang labels that already had 14-16px medium → bold for large-text
   AA tier. */
:root[data-theme="dark"] .main-nav .links .menu-trigger--accent,
:root[data-theme="dark"] .main-nav .links .menu-trigger--accent.active,
:root[data-theme="dark"] .utility .lang-pill,
:root[data-theme="dark"] .utility .lang-pill.is-active,
:root[data-theme="dark"] .mobile-menu .mm-lang__pill,
:root[data-theme="dark"] .btn-secondary,
:root[data-theme="dark"] .tariff.popular .cta {
  font-weight: 700;
}
/* Tiny link "политике конфиденциальности" — 13px 400 link, bump weight. */
:root[data-theme="dark"] .legal-note a,
:root[data-theme="dark"] .form-note a,
:root[data-theme="dark"] p a,
:root[data-theme="dark"] small a {
  font-weight: 700;
  font-size: 14px;
}
/* Stragglers: small orange labels missed by earlier selectors. */
:root[data-theme="dark"] .lang-pill,
:root[data-theme="dark"] .lang-pills .is-active,
:root[data-theme="dark"] .mm-lang__pill.is-active,
:root[data-theme="dark"] .mm-theme-toggle .mm-row-label,
:root[data-theme="dark"] .mm-theme-toggle span:not(.mm-ico),
:root[data-theme="dark"] .mm-phone .mm-phone-num,
:root[data-theme="dark"] .mm-phone-num,
:root[data-theme="dark"] .tariff.popular .btn-white,
:root[data-theme="dark"] .btn-white.btn-lg,
:root[data-theme="dark"] .gift-panel-eyebrow {
  font-weight: 700;
}
/* Drawer lang-switcher активный — единый паттерн с light: brand-pale-фон + brand-цвет.
   Перебивает ранний dark-override line ~4488 (transparent + neutral 1px ring),
   который был общим для нескольких актив-состояний. Для drawer-lang в пилюль-
   контейнере 1px ring почти не виден на тёмном фоне — поэтому brand-pale
   читается ясно. */
:root[data-theme="dark"] .mobile-menu .mm-lang__pill.is-active {
  background: var(--color-brand-pale);
  color: var(--color-brand);
  box-shadow: none;
}
/* .rayon-card__soon — 2.96:1 fails large-text 3:1. Lift color + size. */
:root[data-theme="dark"] .rayon-card__soon {
  font-size: 16px;
  font-weight: 700;
  color: var(--color-brand-light);
}
/* Gift-eyebrow inside .gift-panel — 13px 700 sits at 4.43:1 (just under
   AA-normal 4.5). Bump to 14px so the large-text 3:1 tier applies. */
:root[data-theme="dark"] .gift-panel .gift-eyebrow {
  font-size: 14px;
}
/* Consent label link "политике конфиденциальности" — small inline link
   inside connect-form. Bump to 14px bold for large-text tier. */
:root[data-theme="dark"] .connect-form .consent a,
:root[data-theme="dark"] label.consent a {
  font-size: 14px;
  font-weight: 700;
  color: var(--color-brand-light);
}
/* …но в оранжевой форме (.connect-new-fields) фон сам бренд-оранжевый —
   brand-light на нём даёт ~2.6:1 (нечитаемо). Текст согласия там белый,
   ссылка должна быть тоже белой (≈5.8:1). Специфичность (0,4,1) бьёт
   широкое label.consent a выше. */
:root[data-theme="dark"] .connect-new-fields .consent a {
  color: #fff;
}
/* Force phone numbers in mobile menu off the warm bg, onto gray (already
   done for .mm-phone but the inner .mm-phone-num still has its own bg
   somewhere). The text itself is orange; on neutral gray contrast climbs
   from 2.54 to 3.48 (large-text passes). */
:root[data-theme="dark"] .mm-phone-num {
  background: transparent;
  color: var(--color-brand-light);
}

/* ============================================================================
   Dark-mode hero-v3l readability — the hero photo bleeds past the original
   38% gradient overlay, so the features ("500 Мбит/с", "230 каналов",
   "1-3 дня") sit on raw photo pixels with low text contrast.
   Fix: stretch the dark overlay to 100% with a long fade so the photo is
   muted under all text + lift label color from gray-500 to fg-muted (much
   brighter on dark). Adds an explicit dark-photo veil only in dark theme —
   light theme overlay untouched.
   ============================================================================ */
:root[data-theme="dark"] .hero-v3l-bg::after {
  background:
    linear-gradient(95deg,
      var(--surface-warm) 0%,
      var(--surface-warm) 38%,
      rgba(38, 30, 25, 0.62) 60%,
      rgba(38, 30, 25, 0.18) 100%);
}
/* Mobile dark: возвращаем вертикальный градиент. Без этого
   правила выше (95deg horizontal) перекрывает мобильный
   @media и фото семьи скрыто почти полностью. */
@media (max-width: 600px) {
  :root[data-theme="dark"] .hero-v3l-bg::after {
    background: linear-gradient(180deg,
      var(--surface-warm) 0%,
      var(--surface-warm) 42%,
      rgba(38, 30, 25, 0.55) 72%,
      rgba(38, 30, 25, 0.20) 100%
    );
  }
}
:root[data-theme="dark"] .hero-v3l-feature .lbl {
  color: var(--fg);
  opacity: 0.85;
}
/* Отменяем светлые halo из мобильного light-фикса в dark theme —
   тёплый кремовый ореол на dark фоне выглядит чужеродно. */
:root[data-theme="dark"] .hero-v3l-lede,
:root[data-theme="dark"] .hero-v3l-feature .num,
:root[data-theme="dark"] .hero-v3l-feature .lbl {
  text-shadow: none;
}
/* Filter затемнения нужен только в light-теме (где cream wash + bright
   photo competes c text). В dark и так dark scrim сверху — фильтр
   делал бы сцену слишком тусклой. */
:root[data-theme="dark"] .hero-v3l-bg img {
  filter: none;
}

/* ============================================================================
   /cabinet и /payment — личный кабинет и оплата
   ============================================================================ */

/* Hero — текст слева, иллюстрация справа. На мобиле картинка над текстом. */
.lk-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 580px);
  align-items: center;
  gap: 48px;
}
.lk-hero-text .section-head { margin-bottom: 0; }
.lk-hero-img {
  margin: 0;
  border-radius: 24px;
  overflow: hidden;
}
.lk-hero-img picture,
.lk-hero-img img {
  display: block;
  width: 100%;
  height: auto;
}
@media (max-width: 900px) {
  .lk-hero-grid { grid-template-columns: 1fr; gap: 24px; }
  .lk-hero-img { order: -1; max-width: 480px; margin: 0 auto; }
}

.lk-hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 28px;
}
.lk-hero-cta .btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

/* Bind section — two-column: image left, text right */
.lk-bind-split {
  display: flex;
  align-items: center;
  gap: 48px;
  margin-bottom: 28px;
}
.lk-bind-split .lk-bind-img {
  flex: 0 0 55%;
  max-width: 55%;
}
.lk-bind-split .section-head {
  flex: 1 1 0;
  text-align: left;
  max-width: none;
  margin-bottom: 0;
}
@media (max-width: 768px) {
  .lk-bind-split {
    flex-direction: column;
    gap: 24px;
  }
  .lk-bind-split .lk-bind-img {
    flex: none;
    max-width: 100%;
    width: 100%;
  }
}
.lk-bind-img {
  margin: 0;
  border-radius: 20px;
  overflow: hidden;
}
.lk-bind-img picture,
.lk-bind-img img {
  display: block;
  width: 100%;
  height: auto;
}

/* ---- Modal --------------------------------------------------------------- */
.tv-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  /* Mobile: dialog прибит к верху с фикс. отступом. При появлении клавиатуры
     search input в шапке dialog остаётся на одном месте — пользователь видит,
     что вводит. JS-listener на visualViewport дополнительно подстраивает
     top/height модалки, чтобы она совпадала с visible area. */
  align-items: flex-start;
  padding-top: max(16px, env(safe-area-inset-top, 16px));
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}
.tv-modal.is-open { opacity: 1; pointer-events: auto; }
.tv-modal__dialog {
  position: relative;
  width: 100%;
  max-width: 980px;
  /* dvh учитывает динамическую chrome-зону (URL bar) в мобильных Safari/Chrome.
     padding-top модалки уже съел top safe-area. */
  max-height: calc(100dvh - max(16px, env(safe-area-inset-top, 16px)) - 16px);
  background: var(--bg);
  color: var(--fg);
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding-bottom: env(safe-area-inset-bottom);
  transform: translateY(-16px);
  transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}
.tv-modal.is-open .tv-modal__dialog { transform: translateY(0); }
@media (min-width: 720px) {
  .tv-modal { align-items: center; padding-top: 0; }
  .tv-modal__dialog { border-radius: 18px; max-height: 86vh; box-shadow: var(--shadow-lg); }
}

.tv-modal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px 12px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.tv-modal__title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
}
.tv-modal__close {
  border: 0;
  background: transparent;
  padding: 0;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--fg-muted);
  border-radius: var(--radius-sm);
  transition: background 160ms ease, color 160ms ease;
}
.tv-modal__close:hover { background: var(--bg-soft); color: var(--fg); }
.tv-modal__close svg { width: 22px; height: 22px; display: block; }

.tv-modal__toolbar {
  padding: 12px 20px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.tv-modal__toolbar .tv-toolbar { margin: 0; }
.tv-modal__body {
  padding: 16px 20px 20px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.tv-modal__body .tv-channels-groups { gap: 24px; }
.tv-modal__body .tv-channels-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.tv-modal__loading {
  padding: 60px 20px;
  text-align: center;
  color: var(--fg-muted);
}
.tv-modal__loading.tv-modal__error {
  padding: 40px 24px;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
  color: var(--fg);
}
.tv-modal__loading.tv-modal__error p {
  margin: 0; max-width: 380px; line-height: 1.5; color: var(--fg-muted);
}
.tv-modal__retry {
  padding: 10px 22px;
}
.tv-modal__foot {
  padding: 12px 20px 16px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--fg-muted);
  line-height: 1.5;
  flex-shrink: 0;
}

body.tv-modal-open { overflow: hidden; }

/* ---- Dark theme overrides ----------------------------------------------- */
:root[data-theme="dark"] .tv-channel__hd {
  background: color-mix(in srgb, var(--color-brand) 22%, transparent);
  color: var(--color-brand-light);
}
:root[data-theme="dark"] .tv-modal__dialog {
  box-shadow: 0 -20px 60px rgba(0, 0, 0, 0.6);
}

/* На мобилке весь диалог сам становится скролл-контейнером, а body
   перестаёт скроллиться отдельно — благодаря этому дисклеймер уезжает
   в самый низ контента, а не «плавает» липкой полосой над списком.
   Шапка и тулбар остаются sticky, чтобы поиск и крестик всегда были под рукой. */
@media (max-width: 720px) {
  .tv-modal__dialog { overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; }
  .tv-modal__body { overflow: visible; }
  .tv-modal__head {
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 2;
  }
  .tv-modal__toolbar {
    position: sticky;
    /* head выше: padding 14+10 + title (~25px) ≈ 49px */
    top: 49px;
    background: var(--bg);
    z-index: 1;
  }
  .tv-modal__foot { border-top: 1px solid var(--border); }
}

@media (max-width: 600px) {
  .tv-toolbar { gap: 10px; }
  .tv-toolbar__filter { width: 100%; flex-wrap: wrap; }
  .tv-toolbar__filter button { flex: 1 1 calc(50% - 6px); justify-content: center; min-width: 0; font-size: 13px; padding: 8px 10px; }
  .tv-channels-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .tv-channel { padding: 9px 12px; font-size: 13px; min-width: 0; }
  .tv-channel__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tv-modal__head { padding: 14px 16px 10px; }
  .tv-modal__body { padding: 12px 16px 16px; }
  .tv-modal__foot { padding: 10px 16px 14px; }
}
@media (max-width: 420px) {
  .tv-channels-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

