:root{

  --bg:#1e1f22;
  --bg-alt:#26282b;
  --bg-sidebar:#2b2d30;
  --bg-code:#1a1b1d;
  --bg-hover:rgba(255,255,255,0.04);
  --border:#393b40;
  --border-soft:#2f3134;
  --text:#c7cdd4;
  --text-dim:#82868c;
  --text-bright:#eef0f2;
  --accent:#ffc66d;
  --accent-dim:#c99a52;
  --blue:#6897bb;
  --purple:#cc7832;
  --string:#6a8759;
  --comment:#7c7c7c;
  --func:#ffc66d;
  --macro:#bbb529;
  --link:#5ea1f2;
  --warn:#ff6b68;
  --danger:#e5484d;
  --ok:#6fbf73;
  --tip:#5ea1f2;
  --scrollbar-thumb:#4a4d52;
  --scrollbar-thumb-hover:#5a5d63;

  --radius-sm:4px;
  --radius:8px;
  --radius-lg:12px;
  --sidebar-w:300px;
  --toc-w:240px;
  --content-max:1120px;

  
  --scale:1;
  --weight:400;
}

html[data-theme="light"]{
  --bg:#ffffff;
  --bg-alt:#f3f4f6;
  --bg-sidebar:#f7f8fa;
  --bg-code:#f0f1f3;
  --bg-hover:rgba(0,0,0,0.045);
  --border:#dde1e6;
  --border-soft:#e9ebee;
  --text:#2b2d30;
  --text-dim:#63676e;
  --text-bright:#101113;
  --accent:#a3670a;
  --accent-dim:#8a5808;
  --blue:#1a5fb4;
  --purple:#8250df;
  --string:#0f7b3b;
  --comment:#6e7781;
  --func:#a3670a;
  --macro:#8a6d00;
  --link:#0969da;
  --warn:#bc4c00;
  --danger:#cf222e;
  --ok:#1a7f37;
  --tip:#0969da;
  --scrollbar-thumb:#c7cbd1;
  --scrollbar-thumb-hover:#b3b8bf;
}
html[data-theme="light"] .callout.senior{background:rgba(163,103,10,0.07);}
html[data-theme="light"] .callout.senior-thoughts{background:rgba(130,80,223,0.06);}
html[data-theme="light"] .callout.architect{background:rgba(26,95,180,0.06);}

*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
html{background:var(--bg);
  /* Без этого правила мобильный WebKit (iOS Safari) сам решает, что "узкая
     колонка текста" — это, например, .bc-current в хлебных крошках или
     .lb-explain/.tag-pill — и автоматически увеличивает font-size ТОЛЬКО в
     этих местах (WebKit text-autosizing), меняя реальный размер шрифта
     независимо от --scale/CSS. Отсюда и заголовок хлебных крошек, вдруг
     занимающий половину экрана, и "узкий длинный столбик" текста в других
     местах — сам layout не сломан, WebKit просто раздувает шрифт в узких
     блоках. Отключаем эту эвристику полностью: размер шрифта = то, что
     реально написано в CSS, на всех устройствах одинаково.
  */
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
}
body{
  font-family:'Segoe UI',-apple-system,BlinkMacSystemFont,sans-serif;
  background:var(--bg);
  color:var(--text);
  font-size:calc(15px * var(--scale));
  font-weight:var(--weight);
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
  transition:background-color .15s ease, color .15s ease;
}
code,pre,.mono{font-family:'JetBrains Mono','Consolas','Courier New',monospace;}
a{color:var(--link); text-decoration:none;}
a:hover{text-decoration:underline;}
::-webkit-scrollbar{width:10px; height:10px;}
::-webkit-scrollbar-track{background:var(--bg-alt);}
::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb); border-radius:5px;}
::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover);}

#shell,#sidebar,#topbar,#page-toc,.callout,pre,table,th,td,.link-block,.exercise,.selfcheck,.tag-pill,.tag-cloud a,.cluster-topics a,#hero,.principle,.faq-item{
  transition:background-color .15s ease, border-color .15s ease, color .15s ease;
}
#shell{display:flex; min-height:100vh;}

#sidebar{
  width:var(--sidebar-w); min-width:var(--sidebar-w);
  background:var(--bg-sidebar); border-right:1px solid var(--border);
  display:flex; flex-direction:column; height:100vh; position:sticky; top:0; overflow:hidden;
}
#sidebar-brand{padding:18px 18px 14px 18px; border-bottom:1px solid var(--border);}
#sidebar-brand a{display:block; color:var(--text-bright); font-weight:700; font-size:14.5px; letter-spacing:.2px;}
#sidebar-brand .tagline{color:var(--text-dim); font-size:11px; margin-top:3px; line-height:1.4;}
#sidebar-search{padding:12px 14px; border-bottom:1px solid var(--border);}
#sidebar-search input{
  width:100%; background:var(--bg-code); border:1px solid var(--border); border-radius:var(--radius-sm);
  padding:8px 10px; color:var(--text); font-size:13px; outline:none;
}
#sidebar-search input:focus{border-color:var(--link);}
#sidebar-search-results{max-height:0; overflow:hidden; transition:max-height .15s ease;}
#sidebar-search-results.open{max-height:320px; overflow-y:auto;}
/* Общие стили результатов поиска — раньше были заведены ТОЛЬКО под
   #sidebar-search-results, из-за чего #hero-search-results (поиск в шапке
   главной страницы, bindSearch('hero-search-input','hero-search-results')
   в assets/app.js) рендерил те же .sr-item/.sr-title/.sr-snippet вообще без
   стилей — результаты сливались в один сплошной абзац. Теперь оба
   контейнера используют общее правило. */
#sidebar-search-results .sr-item,
#hero-search-results .sr-item{display:block; padding:8px 14px; border-bottom:1px solid var(--border-soft); cursor:pointer;}
#sidebar-search-results .sr-item:hover,
#hero-search-results .sr-item:hover{background:var(--bg-hover);}
#sidebar-search-results .sr-title,
#hero-search-results .sr-title{color:var(--text-bright); font-size:12.5px; font-weight:600; display:block;}
#sidebar-search-results .sr-snippet,
#hero-search-results .sr-snippet{color:var(--text-dim); font-size:11px; display:block; margin-top:2px;}
#sidebar-search-results .sr-empty,
#hero-search-results .sr-empty{padding:14px; color:var(--text-dim); font-size:12px; text-align:center;}

#sidebar-tree{flex:1; overflow-y:auto; padding:8px 0 20px 0;}
.tree-group{color:var(--text-dim); font-size:10.5px; text-transform:uppercase; letter-spacing:.6px; font-weight:700; padding:14px 18px 6px 18px;}
.tree-group:first-child{padding-top:6px;}
.tree-item{
  display:flex; align-items:flex-start; gap:8px; padding:6px 18px 6px 22px;
  color:var(--text); font-size:13px; border-left:3px solid transparent; line-height:1.4;
}
.tree-item:hover{background:var(--bg-hover); text-decoration:none;}
.tree-item.active{background:rgba(94,161,242,0.12); border-left-color:var(--link); color:var(--text-bright);}
.tree-item .ti-num{color:var(--text-dim); font-family:'JetBrains Mono',monospace; font-size:10.5px; min-width:20px; margin-top:1px;}
.tree-item .ti-status{width:6px; height:6px; border-radius:50%; margin-top:6px; flex-shrink:0;}
.tree-item .ti-status.reference{background:var(--accent);}
.tree-item .ti-status.done{background:var(--ok);}
.tree-item .ti-status.planned{background:var(--border); border:1px solid var(--text-dim);}

/* margin-left:auto — держит блок иконок у правого края НЕЗАВИСИМО от того,
   перенёсся ли #topbar на две строки (см. #topbar{flex-wrap:wrap} в мобильном
   медиа-запросе ниже). Без этого правила: когда #topbar-actions переносится
   на свою отдельную строку как единственный flex-элемент, justify-content:
   space-between у родителя ставит единственный элемент в НАЧАЛО строки (т.е.
   к левому краю) — ровно то, из-за чего иконки на мобильном визуально
   оказывались слева, а не справа (см. обсуждение в чате). Это же смещение
   иконок влево было и корневой причиной ухода языкового меню за левый край
   экрана — #lang-menu позиционируется right:0 ОТНОСИТЕЛЬНО кнопки-переключателя,
   а не относительно viewport, так что если сама кнопка сидит у левого края,
   меню с min-width:200px неизбежно вылезает за границу. */
#topbar-actions{display:flex; align-items:center; gap:8px; margin-left:auto;}
#sidebar-burger,#settings-toggle{
  background:var(--bg-code); border:1px solid var(--border); color:var(--text);
  border-radius:var(--radius-sm); width:34px; height:34px; display:inline-flex; align-items:center; justify-content:center;
  font-size:15px; cursor:pointer; transition:background-color .15s ease, border-color .15s ease, color .15s ease;
}
/* На Desktop #sidebar виден всегда (см. #sidebar правило выше — sticky,
   часть постоянного flex-layout'а), toggle .open у него не даёт вообще
   никакого визуального эффекта (см. @media (max-width:860px) ниже — только
   там .open вообще что-то значит). Раньше burger был виден и кликабелен на
   любой ширине, но на Desktop нажатие ничего не делало — по требованию:
   "если на Desktop не нужна — скрывать". Прячем по умолчанию, показываем
   обратно только в мобильном медиа-запросе, где сайдбар реально скрыт по
   умолчанию и burger — единственный способ его открыть. */
#sidebar-burger{display:none;}
#sidebar-burger:hover,#settings-toggle:hover{border-color:var(--link); color:var(--text-bright);}
/* Текстовая подпись рядом с ☰-иконкой — существует в разметке только на
   мобильном (см. enhanceSidebarBurgerLabel() в app.js), но на всякий случай
   держим её скрытой по умолчанию и включаем только в @media(max-width:860px). */
.burger-label{display:none;}

.topbar-dropdown{position:relative;}
.topbar-dropdown-toggle{
  background:var(--bg-code); border:1px solid var(--border); color:var(--text);
  border-radius:var(--radius-sm); height:34px; padding:0 12px; display:inline-flex; align-items:center; gap:6px;
  font-size:13px; font-weight:600; cursor:pointer; white-space:nowrap;
  transition:background-color .15s ease, border-color .15s ease, color .15s ease;
}
.topbar-dropdown-toggle:hover{border-color:var(--link); color:var(--text-bright);}
.topbar-dropdown-toggle .dd-caret{font-size:10px; color:var(--text-dim);}
.topbar-dropdown-menu{
  position:absolute; top:calc(100% + 6px); right:0; min-width:200px; max-width:calc(100vw - 24px);
  max-height:70vh; overflow-y:auto; background:var(--bg-alt);
  border:1px solid var(--border); border-radius:var(--radius-sm); box-shadow:0 8px 24px rgba(0,0,0,.25);
  padding:6px; display:none; flex-direction:column; gap:2px; z-index:50;
}
.topbar-dropdown-menu.open{display:flex;}
.dd-item{
  display:block; padding:8px 10px; border-radius:var(--radius-sm); font-size:13px; color:var(--text);
  cursor:pointer; text-decoration:none; white-space:nowrap;
}
.dd-item:hover{background:var(--bg-code); color:var(--text-bright);}
.dd-item.dd-current{color:var(--ok); font-weight:700;}
.dd-item.dd-disabled{color:var(--text-dim); cursor:default; opacity:.6;}
.dd-item.dd-disabled:hover{background:none; color:var(--text-dim);}
.topbar-ghost-btn,.topbar-cta-btn{
  height:34px; padding:0 14px; border-radius:var(--radius-sm); font-size:13px; font-weight:700; cursor:pointer;
  white-space:nowrap; transition:opacity .15s ease, border-color .15s ease;
}
.topbar-ghost-btn{background:transparent; border:1px solid var(--border); color:var(--text);}
.topbar-ghost-btn:hover{border-color:var(--link); color:var(--text-bright);}
.topbar-cta-btn{background:var(--link); border:none; color:#fff;}
.topbar-cta-btn:hover{opacity:.9;}
.topbar-account-loading{color:var(--text-dim); font-size:13px; padding:0 6px;}
@media (max-width:640px){
  .topbar-dropdown-toggle,.topbar-ghost-btn,.topbar-cta-btn{padding:0 9px; font-size:12px;}
}

.settings-overlay{
  position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:100;
  display:none; align-items:center; justify-content:center; padding:20px;
}
.settings-overlay.open{display:flex;}
#settings-modal{
  background:var(--bg-sidebar); border:1px solid var(--border); border-radius:var(--radius-lg);
  width:400px; max-width:100%; max-height:86vh; overflow-y:auto; padding:22px 24px;
  box-shadow:0 24px 60px rgba(0,0,0,.5);
}
html[data-theme="light"] #settings-modal{box-shadow:0 24px 60px rgba(20,21,23,.18);}
.settings-header{display:flex; align-items:center; justify-content:space-between; margin-bottom:18px; padding-bottom:14px; border-bottom:1px solid var(--border);}
.settings-title{color:var(--text-bright); font-size:15.5px; font-weight:700;}
.settings-close{background:none; border:none; color:var(--text-dim); font-size:18px; cursor:pointer; line-height:1; padding:4px 6px; border-radius:var(--radius-sm);}
.settings-close:hover{color:var(--text-bright); background:var(--bg-hover);}
.settings-block{margin-bottom:22px;}
.settings-block:last-child{margin-bottom:0;}
.settings-block-label{color:var(--text-dim); font-size:11px; text-transform:uppercase; letter-spacing:.5px; font-weight:700; margin-bottom:10px; display:flex; justify-content:space-between; align-items:center;}
.settings-reset{background:none; border:none; color:var(--link); font-size:11px; cursor:pointer; padding:0; text-transform:none; letter-spacing:0; font-weight:600;}
.settings-reset:hover{text-decoration:underline;}
.settings-slider-row{display:flex; align-items:center; gap:10px;}
.settings-slider-row input[type=range]{flex:1; accent-color:var(--link); height:4px;}
.settings-slider-row input[type=number]{
  width:58px; background:var(--bg-code); border:1px solid var(--border); border-radius:var(--radius-sm);
  color:var(--text-bright); font-size:12.5px; padding:6px 6px; text-align:center;
}
.settings-slider-row input[type=number]:focus{border-color:var(--link); outline:none;}
.settings-value{color:var(--text-dim); font-size:11.5px; margin-top:8px;}
#settings-theme-btn{
  width:100%; display:flex; align-items:center; justify-content:center; gap:8px; padding:11px 12px;
  font-size:13px; font-weight:600; background:var(--bg-code); border:1px solid var(--border);
  border-radius:var(--radius-sm); color:var(--text); cursor:pointer;
  transition:background-color .15s ease, border-color .15s ease, color .15s ease;
}
#settings-theme-btn:hover{border-color:var(--link); color:var(--text-bright);}

#main{flex:1; min-width:0; display:flex; flex-direction:column;}
#topbar{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:12px 32px; border-bottom:1px solid var(--border); background:var(--bg-alt);
  position:sticky; top:0; z-index:5;
  transition:transform .25s ease;
}
/* Скрытие панели при скролле вниз/показ при скролле вверх — см.
   bindTopbarAutoHide() в assets/app.js. Класс переключается на любой
   ширине, но визуальный эффект (translateY) включён только в мобильном
   медиа-запросе ниже: на Desktop панель и так занимает мало места, прятать
   её незачем и рискованно (sticky ToC/якоря используют её высоту). */
#breadcrumbs{font-size:12.5px; color:var(--text-dim); display:flex; align-items:center; gap:6px; flex-wrap:wrap; min-width:0;}
#breadcrumbs a{color:var(--text-dim);}
#breadcrumbs a:hover{color:var(--link);}
#breadcrumbs .bc-sep{color:var(--border);}
#breadcrumbs .bc-current{color:var(--text-bright);}

#page-body{flex:1; display:flex; justify-content:center; gap:36px; padding:40px 32px 100px 32px;}
#article{max-width:var(--content-max); width:100%; min-width:0;}

#page-toc{width:var(--toc-w); min-width:var(--toc-w); position:sticky; top:76px; align-self:flex-start; max-height:calc(100vh - 100px); overflow-y:auto;}
#page-toc .toc-label{color:var(--text-dim); font-size:10.5px; text-transform:uppercase; letter-spacing:.6px; font-weight:700; margin-bottom:10px;}
#page-toc a{display:block; color:var(--text-dim); font-size:12.5px; padding:4px 0 4px 12px; border-left:2px solid var(--border-soft); line-height:1.4;}
#page-toc a.toc-h3{padding-left:22px; font-size:12px;}
#page-toc a:hover{color:var(--text-bright); text-decoration:none;}
#page-toc a.active{color:var(--link); border-left-color:var(--link);}

.eyebrow{color:var(--accent); font-size:calc(11px * var(--scale)); text-transform:uppercase; letter-spacing:1px; font-weight:700; margin-bottom:10px;}
h1.article-title{color:var(--text-bright); font-size:calc(30px * var(--scale)); font-weight:700; margin:0 0 12px 0; line-height:1.25;}
.article-lead{color:var(--text-dim); font-size:calc(16px * var(--scale)); line-height:1.6; margin:0 0 20px 0;}
.tag-row{display:flex; flex-wrap:wrap; gap:6px; margin:14px 0 28px 0;}
.tag-pill{
  font-size:calc(11px * var(--scale)); color:var(--text-dim); background:var(--bg-alt); border:1px solid var(--border);
  border-radius:12px; padding:3px 10px;
}
.tag-pill:hover{color:var(--text-bright); border-color:var(--link); text-decoration:none;}

article h2{color:var(--text-bright); font-size:calc(21px * var(--scale)); font-weight:700; margin:44px 0 14px 0; padding-bottom:10px; border-bottom:1px solid var(--border); scroll-margin-top:80px;}
article h2 .h-num{color:var(--accent); font-family:'JetBrains Mono',monospace; margin-right:10px;}
article h3{color:var(--text-bright); font-size:calc(16.5px * var(--scale)); font-weight:700; margin:28px 0 10px 0; scroll-margin-top:80px;}
article h4{color:var(--text-bright); font-size:calc(14.5px * var(--scale)); font-weight:700; margin:20px 0 8px 0;}
article p{margin:12px 0; color:var(--text); line-height:1.75;}
article strong{color:var(--text-bright); font-weight:700;}
article ul, article ol{line-height:1.85; padding-left:24px; margin:12px 0;}
article li{margin:5px 0;}
article hr{border:none; border-top:1px solid var(--border); margin:36px 0;}
article img, article svg.diagram-svg{max-width:100%; border-radius:var(--radius); border:1px solid var(--border);}

.callout{background:var(--bg-alt); border-left:3px solid var(--link); padding:14px 18px; margin:18px 0; border-radius:0 var(--radius-sm) var(--radius-sm) 0; line-height:1.7;}
.callout .cal-title{font-weight:700; color:var(--text-bright); font-size:11.5px; text-transform:uppercase; letter-spacing:.5px; margin-bottom:7px; display:flex; align-items:center; gap:6px;}
.callout.important{border-left-color:var(--tip);}
.callout.error{border-left-color:var(--danger);}
.callout.tip{border-left-color:var(--ok);}
.callout.senior{border-left-color:var(--accent); background:rgba(255,198,109,0.06);}
.callout.senior-thoughts{border-left-color:var(--purple); background:rgba(204,120,50,0.06); padding:11px 16px; margin:16px 0; font-size:calc(13.5px * var(--scale)); line-height:1.65;}
.callout.senior-thoughts .cal-title{color:var(--purple); font-size:11px;}
.callout.senior-thoughts p{margin:4px 0;}
.callout.architect{border-left-color:var(--blue); background:rgba(104,151,187,0.07);}
.callout.architect .cal-title{color:var(--blue);}
.callout p:first-child{margin-top:0;}
.callout p:last-child{margin-bottom:0;}

.code-block{margin:16px 0;}
.code-block .code-caption{
  display:flex; justify-content:space-between; align-items:center;
  background:var(--bg-alt); border:1px solid var(--border); border-bottom:none;
  border-radius:var(--radius-sm) var(--radius-sm) 0 0; padding:8px 14px; font-size:11.5px; color:var(--text-dim);
}
.code-block .code-caption .cc-file{font-family:'JetBrains Mono',monospace; color:var(--text-bright);}
pre{background:var(--bg-code); border:1px solid var(--border); border-radius:var(--radius-sm); padding:16px 18px; overflow-x:auto; margin:0; line-height:1.6; font-size:calc(13px * var(--scale));}
.code-block .code-caption + pre{border-radius:0 0 var(--radius-sm) var(--radius-sm);}
pre code{color:var(--text); white-space:pre;}
.tok-kw{color:var(--purple);}
.tok-type{color:#c7cdd4; font-weight:600;}
.tok-str{color:var(--string);}
.tok-com{color:var(--comment); font-style:italic;}
.tok-func{color:var(--func);}
.tok-macro{color:var(--macro);}
.tok-num{color:#6897bb;}
.diagram{color:#8fbf8f;}

.line-breakdown{margin:14px 0 24px 0; border:1px solid var(--border); border-radius:var(--radius-sm); overflow:hidden;}
.lb-row{display:flex; align-items:flex-start; flex-wrap:wrap; gap:6px 14px; padding:10px 14px; border-bottom:1px solid var(--border-soft); font-size:calc(13px * var(--scale));}
.lb-row:last-child{border-bottom:none;}
.lb-row:nth-child(odd){background:var(--bg-alt);}
.lb-line{font-family:'JetBrains Mono',monospace; color:var(--accent); white-space:normal; overflow-wrap:anywhere; flex:0 0 220px; max-width:100%; line-height:1.5; font-size:calc(12.5px * var(--scale));}
.lb-explain{color:var(--text); line-height:1.6; flex:1 1 260px; min-width:0;}

code.inline, p code, li code, td code{background:var(--bg-alt); border:1px solid var(--border); border-radius:3px; padding:1px 6px; font-size:calc(12.5px * var(--scale)); color:var(--accent);}

table{border-collapse:collapse; width:100%; margin:18px 0; font-size:calc(13.5px * var(--scale));}
th,td{border:1px solid var(--border); padding:9px 13px; text-align:left; vertical-align:top;}
th{background:var(--bg-alt); color:var(--text-bright); font-weight:700; font-size:calc(12px * var(--scale)); text-transform:uppercase; letter-spacing:.3px;}

.link-block{background:var(--bg-alt); border:1px solid var(--border); border-radius:var(--radius); padding:16px 20px; margin:20px 0;}
.link-block .lb-title{font-weight:700; color:var(--text-bright); font-size:calc(13px * var(--scale)); text-transform:uppercase; letter-spacing:.4px; margin-bottom:10px; display:flex; align-items:center; gap:8px;}
.link-block.prereq{border-left:3px solid var(--warn);}
.link-block.next{border-left:3px solid var(--ok);}
.link-block.related{border-left:3px solid var(--link);}
.link-block ul{list-style:none; padding:0; margin:0;}
.link-block li{margin:8px 0;}
.link-block a.ll{color:var(--text-bright); font-weight:600; font-size:calc(14px * var(--scale));}
.link-block .ll-desc{color:var(--text-dim); font-size:calc(12.5px * var(--scale)); margin-top:2px; display:block;}

/* Издательская отметка авторства в конце статьи (см. обсуждение в чате про
   защиту от копирования контента) — намеренно НЕ .callout: без цветной
   рамки/фона, минимум визуального веса, как выходные данные в книге, а не
   призыв "подпишись". Ссылки внутри — АБСОЛЮТНЫЕ (https://www.uecppacademy.com/...),
   а не относительные: весь смысл блока в том, чтобы он продолжал указывать
   на оригинал, даже если статью скопируют на другой домен целиком. */
.article-attribution{
  margin:36px 0 4px 0; padding-top:16px; border-top:1px solid var(--border);
  color:var(--text-dim); font-size:calc(12.5px * var(--scale)); line-height:1.7;
}
.article-attribution a{color:var(--text-dim); text-decoration:underline;}
.article-attribution a:hover{color:var(--link);}

.faq-item{border-bottom:1px solid var(--border); padding:16px 0;}
.faq-item:last-child{border-bottom:none;}
.faq-q{color:var(--text-bright); font-weight:700; margin-bottom:8px; line-height:1.5; display:flex; gap:8px;}
.faq-q .faq-mark{color:var(--accent);}
.faq-a{color:var(--text); line-height:1.75; margin:0;}

.checklist{list-style:none; padding:0; margin:16px 0;}
.checklist li{display:flex; align-items:flex-start; gap:10px; padding:8px 0; border-bottom:1px solid var(--border-soft); line-height:1.6;}
.checklist li:last-child{border-bottom:none;}
.checklist li::before{content:'☐'; color:var(--accent); font-size:15px; flex-shrink:0; margin-top:1px;}

.exercise{background:var(--bg-alt); border-left:3px solid var(--accent); padding:16px 20px; margin:20px 0; border-radius:0 var(--radius-sm) var(--radius-sm) 0;}
.exercise-tag{font-size:10.5px; text-transform:uppercase; letter-spacing:.5px; color:var(--accent); font-weight:700; margin-bottom:8px;}
.exercise-task{color:var(--text-bright); line-height:1.65;}
details.exercise-answer{margin-top:12px;}
details.exercise-answer summary{cursor:pointer; color:var(--link); font-size:13px; padding:6px 0; user-select:none; font-weight:600;}
details.exercise-answer summary:hover{text-decoration:underline;}
details.exercise-answer[open] summary{margin-bottom:6px;}

.selfcheck{background:var(--bg-code); border:1px dashed var(--border); border-radius:var(--radius); padding:16px 20px; margin:24px 0; font-size:12.5px; color:var(--text-dim);}
.selfcheck .sc-title{color:var(--text-bright); font-weight:700; margin-bottom:8px; font-size:12px; text-transform:uppercase; letter-spacing:.4px;}

.pager{display:flex; justify-content:space-between; gap:16px; margin-top:56px; padding-top:24px; border-top:1px solid var(--border);}
.pager a{color:var(--text-dim); font-size:calc(13px * var(--scale)); border:1px solid var(--border); padding:10px 16px; border-radius:var(--radius-sm); max-width:45%;}
.pager a:hover{color:var(--text-bright); border-color:var(--link); text-decoration:none;}
.pager .dir{display:block; font-size:10px; text-transform:uppercase; color:var(--text-dim); margin-bottom:3px; letter-spacing:.3px;}
.pager .pg-title{color:var(--text-bright); font-weight:600;}

#hero{padding:64px 48px 44px 48px; border-bottom:1px solid var(--border); background:var(--bg-sidebar);}
#hero .eyebrow{margin-bottom:12px;}
#hero h1{color:var(--text-bright); font-size:34px; margin:0 0 16px 0; font-weight:700; max-width:820px;}
#hero p.sub{color:var(--text); font-size:16px; max-width:760px; margin:0 0 10px 0; line-height:1.65;}
#hero-search{max-width:560px; margin-top:24px; position:relative;}
#hero-search input{
  width:100%; background:var(--bg-code); border:1px solid var(--border); border-radius:var(--radius);
  padding:14px 18px; color:var(--text-bright); font-size:15px; outline:none;
}
#hero-search input:focus{border-color:var(--link);}
#hero-search-results{position:absolute; left:0; right:0; top:calc(100% + 6px); background:var(--bg-alt); border:1px solid var(--border); border-radius:var(--radius); max-height:0; overflow:hidden; transition:max-height .15s ease; z-index:10;}
#hero-search-results.open{max-height:400px; overflow-y:auto;}

.home-wrap{max-width:1180px; margin:0 auto; padding:44px 48px 100px 48px;}
.section-h{color:var(--text-bright); font-size:21px; margin:52px 0 8px 0; border-bottom:1px solid var(--border); padding-bottom:10px;}
.section-sub{color:var(--text-dim); font-size:13px; margin-bottom:22px;}

.principle-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin:20px 0 10px 0;}
.principle{background:var(--bg-alt); border:1px solid var(--border); border-radius:var(--radius); padding:16px 18px;}
.principle .ptitle{color:var(--text-bright); font-weight:700; font-size:13.5px; margin-bottom:5px;}
.principle .pdesc{color:var(--text-dim); font-size:12.5px; line-height:1.55;}

.tag-cloud{display:flex; flex-wrap:wrap; gap:8px; margin:10px 0 10px 0;}
.tag-cloud a{font-size:12.5px; color:var(--text); background:var(--bg-alt); border:1px solid var(--border); border-radius:14px; padding:5px 13px;}
.tag-cloud a:hover{color:var(--text-bright); border-color:var(--link); text-decoration:none;}

.cluster{display:flex; gap:18px; padding:20px 0; border-bottom:1px solid var(--border);}
.cluster:last-child{border-bottom:none;}
.cluster-num{min-width:44px; flex-shrink:0; color:var(--text-dim); font-family:'JetBrains Mono',monospace; font-size:20px; font-weight:700;}
.cluster-body{flex:1; min-width:0;}
.cluster-title{color:var(--text-bright); font-size:16px; font-weight:700; margin-bottom:4px;}
.cluster-desc{color:var(--text-dim); font-size:13px; margin-bottom:8px; line-height:1.55;}
.cluster-topics{display:flex; flex-wrap:wrap; gap:8px;}
.cluster-topics a{font-size:12.5px; color:var(--text); background:var(--bg-code); border:1px solid var(--border); border-radius:6px; padding:5px 10px;}
.cluster-topics a:hover{border-color:var(--link); color:var(--text-bright); text-decoration:none;}
.cluster-topics a.status-planned{color:var(--text-dim); border-style:dashed;}
.cluster-topics a .badge-ref{color:var(--accent); font-size:10px; margin-left:4px;}

.phil-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:16px; margin:22px 0 10px 0;}
.phil-card{background:var(--bg-alt); border:1px solid var(--border); border-left:3px solid var(--link); border-radius:0 var(--radius) var(--radius) 0; padding:18px 20px; display:flex; flex-direction:column; gap:8px;}
.phil-card.soon{border-left-color:var(--text-dim);}
.phil-q{color:var(--text-bright); font-weight:700; font-size:15px; line-height:1.4;}
.phil-a{color:var(--text); font-size:13.5px; line-height:1.65; flex:1;}
.phil-link{font-size:12.5px; color:var(--link); margin-top:2px;}
.phil-soon-badge{display:inline-block; color:var(--text-dim); font-size:10.5px; text-transform:uppercase; letter-spacing:.4px; border:1px dashed var(--border); border-radius:10px; padding:2px 9px; margin-top:2px; width:fit-content;}

.pricing-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:16px; margin:24px 0;}
.pricing-card{background:var(--bg-alt); border:1px solid var(--border); border-radius:var(--radius); padding:26px 20px 24px; display:flex; flex-direction:column; align-items:center; gap:8px; text-align:center;}
.pricing-card.featured{border-color:var(--accent); box-shadow:0 0 0 1px var(--accent);}
.pricing-plan{color:var(--text-bright); font-size:23px; font-weight:800; letter-spacing:.2px; line-height:1.2;}
.pricing-desc{color:var(--text-dim); font-size:13px; line-height:1.55; max-width:230px; margin-bottom:4px;}
.pricing-price{color:var(--text-bright); font-size:32px; font-weight:700; line-height:1.1;}
.pricing-period{color:var(--text-dim); font-size:13px;}
.pricing-badge{align-self:center; color:var(--accent); font-size:10.5px; text-transform:uppercase; letter-spacing:.4px; border:1px solid var(--accent-dim); border-radius:10px; padding:2px 10px;}
.pricing-cta-slot{margin-top:6px; width:100%; display:flex; justify-content:center;}
.pricing-cta-slot stripe-buy-button{width:100%; max-width:260px; transform:scale(1.08); transform-origin:top center;}
.pricing-cta{
  margin-top:8px; background:var(--link); color:#fff; border:none; border-radius:var(--radius-sm);
  padding:11px 16px; font-size:13.5px; font-weight:700; cursor:pointer;
  transition:background-color .15s ease, opacity .15s ease;
}
.pricing-cta:hover{opacity:.9;}
.pricing-cta:disabled{opacity:.5; cursor:not-allowed;}
.account-status-card{background:var(--bg-alt); border:1px solid var(--border); border-radius:var(--radius); padding:20px 24px; margin:20px 0;}
.account-status-row{display:flex; justify-content:space-between; align-items:center; padding:8px 0; border-bottom:1px solid var(--border-soft);}
.account-status-row:last-child{border-bottom:none;}
.account-status-label{color:var(--text-dim); font-size:12.5px; text-transform:uppercase; letter-spacing:.3px;}
.account-status-value{color:var(--text-bright); font-weight:700;}
.account-status-value.role-premium,.account-status-value.role-admin{color:var(--ok);}
.account-status-value.role-guest,.account-status-value.role-registered{color:var(--warn);}
#clerk-auth-widget{margin:20px 0;}
.form-message{font-size:13px; padding:10px 14px; border-radius:var(--radius-sm); margin:14px 0;}
.form-message.error{background:rgba(229,72,77,0.12); color:var(--danger); border:1px solid var(--danger);}
.form-message.info{background:rgba(94,161,242,0.12); color:var(--link); border:1px solid var(--link);}

.locked-screen{max-width:520px; margin:64px auto; text-align:center; padding:0 20px;}
.locked-icon{font-size:44px; line-height:1; margin-bottom:14px;}
.locked-actions{margin-top:24px; display:flex; justify-content:center; flex-wrap:wrap; gap:12px;}
.locked-actions .pricing-cta{margin-top:0;}

#graph-wrap{max-width:1200px; margin:0 auto; padding:40px 48px 100px 48px;}
#graph-canvas{background:var(--bg-alt); border:1px solid var(--border); border-radius:var(--radius); padding:20px; overflow:auto;}
.gnode{fill:var(--bg-code); stroke:var(--border); stroke-width:1.5;}
.gnode.reference{stroke:var(--accent); stroke-width:2;}
.gnode.planned{stroke-dasharray:4,3;}
.gnode-label{fill:var(--text-bright); font-size:12px; font-family:'Segoe UI',sans-serif;}
.gnode-sub{fill:var(--text-dim); font-size:10px;}
.gedge{stroke:var(--border); stroke-width:1.5; fill:none; marker-end:url(#arrow);}
.gnode-group{cursor:pointer;}
.gnode-group:hover .gnode{stroke:var(--link);}

.favorite-star-btn{
  display:inline-block; margin-left:10px; vertical-align:middle;
  background:none; border:none; cursor:pointer; font-size:22px; line-height:1;
  color:var(--text-dim); padding:2px 4px;
}
.favorite-star-btn:hover{color:var(--accent);}
.favorite-star-btn.is-favorite{color:var(--accent);}
.favorite-star-btn:disabled{opacity:.5; cursor:default;}

#dynamic-home-blocks{max-width:1200px; margin:0 auto; padding:0 48px;}
.dh-grid{display:grid; grid-template-columns:repeat(auto-fit, minmax(240px, 1fr)); gap:16px; margin:24px 0 8px 0;}
.dh-block{background:var(--bg-alt); border:1px solid var(--border); border-radius:var(--radius); padding:16px 18px;}
.dh-title{color:var(--text-bright); font-size:13px; font-weight:700; margin-bottom:10px;}
.dh-list{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:7px;}
.dh-item a{color:var(--link); font-size:13px; line-height:1.4;}
.dh-item a:hover{text-decoration:underline;}
.dh-item.dh-missing{color:var(--text-dim); font-size:12px; font-style:italic;}
.dh-empty{color:var(--text-dim); font-size:12.5px; line-height:1.5;}
.dh-progress{margin-top:12px;}
.dh-progress-bar{background:var(--bg-code); border:1px solid var(--border); border-radius:999px; height:6px; overflow:hidden;}
.dh-progress-fill{background:var(--accent); height:100%; border-radius:999px; transition:width .3s;}
.dh-progress-label{display:block; color:var(--text-dim); font-size:11px; margin-top:6px;}

@media (max-width:1200px){
  #page-toc{display:none;}
}
@media (max-width:860px){
  #sidebar{position:fixed; left:-320px; z-index:20; transition:left .2s; box-shadow:4px 0 20px rgba(0,0,0,.4);}
  #sidebar.open{left:0;}
  #sidebar-burger{display:inline-flex;}
  #page-body{padding:28px 18px 80px 18px;}
  #topbar{padding:10px 14px; flex-wrap:wrap; row-gap:8px;}
  #hero{padding:40px 20px 32px 20px;}

  table{display:block; overflow-x:auto; -webkit-overflow-scrolling:touch;}

  /* Скрытие топбара при скролле вниз (см. bindTopbarAutoHide() в app.js) —
     только на мобильных: на Desktop панель компактна и так, прятать её там
     не нужно и рискованно для sticky ToC/якорей. */
  #topbar.topbar-hidden{transform:translateY(-100%);}

  /* Тач-таргеты по гайдлайну Apple (44×44pt) — было 34×34, слишком мелко
     для пальца; см. жалобу пользователя "кнопка Home/Menu слишком маленькая". */
  #sidebar-burger,#settings-toggle{width:42px; height:42px; font-size:16px;}
  .topbar-dropdown-toggle,.topbar-ghost-btn,.topbar-cta-btn{height:40px;}
  #topbar-actions{gap:6px;}

  /* Бургер на мобильном не просто ☰-иконка без подписи (см. жалобу
     "боковая панель непонятна пользователю") — показываем рядом с иконкой
     тот же текст, что уже лежит в aria-label (переведён на локали, см.
     enhanceSidebarBurgerLabel() в app.js), так что не нужен отдельный ключ
     в t()-словаре. */
  #sidebar-burger{width:auto; padding:0 12px; gap:6px;}
  .burger-label{display:inline; font-size:11.5px; font-weight:600; white-space:nowrap;}

  /* Увеличиваем невидимую область попадания у ссылки "Home" в хлебных
     крошках, не сдвигая видимый текст (отрицательные margin компенсируют
     добавленный padding). */
  #breadcrumbs a{display:inline-block; padding:9px 3px; margin:-9px -3px;}

  /* Гостю (Login+Sign Up — два широких элемента) вместе с языковым
     переключателем и бургером/шестерёнкой может не хватить одной строки —
     раньше это просто вылезало за правый край экрана (бургер/шестерёнка
     оказывались за пределами viewport и физически недоступны пальцу — см.
     обсуждение в чате про "Menu недоступен для гостя"). flex-wrap здесь
     даёт этому же ряду перенестись на вторую строку ВНУТРИ себя, а не
     обрезаться — при этом margin-left:auto у #topbar-actions (см. выше)
     держит уже перенёсшийся ряд прижатым к правому краю. */
  #topbar-actions{flex-wrap:wrap; justify-content:flex-end; row-gap:8px;}

  /* Затемняющая подложка под открытым боковым меню — раньше её не было
     вообще: тап мимо меню ничего не закрывал, а фон статьи спокойно
     скроллился под открытой панелью (см. обсуждение в чате). Появляется
     только вместе с #sidebar.open (см. setSidebarOpen() в app.js), лежит
     МЕЖДУ статьёй и самой панелью (z-index чуть меньше, чем у #sidebar). */
  #sidebar-overlay{
    display:none; position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:19;
  }
  #sidebar-overlay.open{display:block;}

  /* Кнопка закрытия ВНУТРИ панели — не полагается на то, что бургер вообще
     виден/достижим (а раньше это было именно так, см. жалобу про недоступный
     Menu у гостя): у пользователя всегда есть явный, видимый способ закрыть
     меню, не только тап по подложке. Создаётся в JS (ensureSidebarCloseButton),
     на Desktop не показывается (сам #sidebar там не является выезжающей
     панелью, см. комментарий у #sidebar-burger{display:none} выше). */
  #sidebar-close{
    display:inline-flex; align-items:center; justify-content:center;
    position:absolute; top:14px; right:14px; width:34px; height:34px;
    background:var(--bg-code); border:1px solid var(--border); border-radius:var(--radius-sm);
    color:var(--text-dim); font-size:16px; cursor:pointer; z-index:1;
  }
  #sidebar-close:hover{color:var(--text-bright); border-color:var(--link);}

  /* Пока меню открыто, страница за ним не должна скроллиться (см. жалобу
     "можно листать статью под открытым меню") — класс вешается/снимается
     вместе с setSidebarOpen() в app.js. */
  html.sidebar-locked, html.sidebar-locked body{overflow:hidden; height:100%;}

  /* Языковое (и, для единообразия, аккаунт-) меню на мобильном.
     ВАЖНО: позиция (top/left) больше НЕ решается здесь через CSS — первая
     попытка (position:fixed; bottom:0; right:16px, "bottom sheet") визуально
     отвязывала попап от кнопки-переключателя и читалась как "открывается
     где-то по центру экрана" (см. обсуждение в чате со скриншотом). Кнопка
     может физически оказаться где угодно (перенос строки в #topbar-actions,
     разная ширина гостевых/авторизованных кнопок), поэтому единственный
     надёжный вариант — вычислять top/left от РЕАЛЬНОГО прямоугольника
     кнопки через getBoundingClientRect() (см. positionDropdownMenu() в
     app.js, вызывается при каждом открытии). Здесь только position:fixed
     как база (чтобы top/left из JS считались от viewport, а не от
     случайного relative-родителя) и ограничения по ширине/высоте — сами
     координаты каждый раз проставляет JS инлайн-стилем. */
  .topbar-dropdown-menu{
    position:fixed;
    width:calc(100vw - 32px); max-width:280px; max-height:60vh;
  }

  /* Затемнение фона под открытым языковым/аккаунт-меню — просто эстетика
     (модальное ощущение), с позицией попапа не связано никак: закрывается
     тем же кликом, что и раньше (см. ensureDropdownBackdrop()/
     closeAllDropdowns() в app.js).

     РЕГРЕССИЯ, найденная и исправленная здесь (реальный баг, не JS-порядок
     событий, как показалось на первый взгляд по симптому "открывается и
     тут же закрывается, выбрать язык нельзя" — см. обсуждение в чате):
     z-index:45 здесь СРАВНИВАЛСЯ мысленно напрямую с z-index:50 у самого
     .topbar-dropdown-menu (см. старый комментарий "z-index ниже, чем у
     самого меню") — но это сравнение неверно. #topbar — position:sticky
     С СОБСТВЕННЫМ z-index:5 (см. #topbar{} выше), а значит создаёт СВОЙ
     stacking context: z-index:50 у вложенного в него .topbar-dropdown-menu
     сравнивается ТОЛЬКО с другими элементами ВНУТРИ #topbar, а СНАРУЖИ
     весь #topbar (включая меню внутри) считается единым слоем на уровне
     z-index:5. #dropdown-backdrop же добавляется напрямую в <body>
     (соседний с #shell элемент, вне #topbar), поэтому реальное сравнение —
     не 45 против 50, а 45 против 5: подложка рисовалась (и перехватывала
     клики) ПОВЕРХ всего топбара вместе с меню, что и выглядело как "меню
     видно, но тап по нему тут же закрывает всё" (фактически тап попадал по
     подложке, лежащей выше). Значение здесь должно быть МЕНЬШЕ z-index:5
     у #topbar (чтобы топбар и открытое в нём меню стабильно оказывались
     выше подложки), но больше 0/auto у обычного контента страницы (статья,
     сайдбар-контент и т.п.), который подложка и должна затемнять. */
  #dropdown-backdrop{
    display:none; position:fixed; inset:0; background:rgba(0,0,0,.45); z-index:3;
  }
  #dropdown-backdrop.open{display:block;}
}
@media (max-width:640px){
  /* Длинный заголовок статьи в хлебных крошках на узком экране — то, что
     раньше (в связке с багом text-size-adjust) раздувало топбар на пол-
     экрана. Даже с исправленным шрифтом длинное название всё ещё может
     занимать 2-3 строки — прячем промежуточный сегмент кластера и
     обрезаем сам заголовок многоточием, чтобы хлебные крошки гарантированно
     были одной строкой. */
  #breadcrumbs{flex-wrap:nowrap; overflow:hidden;}
  #breadcrumbs .bc-cluster{display:none;}
  #breadcrumbs .bc-current{
    display:inline-block; max-width:46vw; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    vertical-align:bottom;
  }
}
@media (max-width:480px){
  h1.article-title{font-size:calc(24px * var(--scale));}
  .pager{flex-direction:column;}
  .pager a{max-width:100%;}
}
