/* Страница лабораторной: каркас, сайдбар, чек-лист, материалы */
.lab-layout{display:grid;grid-template-columns:300px minmax(0,1fr);gap:26px;align-items:start}
.side-sticky{position:sticky;top:74px;max-height:calc(100vh - 92px);overflow:auto;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:16px 18px;box-shadow:var(--sh)}
.side-sticky h3{margin:10px 0 2px;font-size:13px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.steps{list-style:none;padding:0;margin:10px 0}.steps li{padding:5px 0;font-size:13.5px;line-height:1.35}
.steps li label{display:flex;gap:9px;align-items:flex-start;font-weight:500;margin:0;color:var(--text)}.steps li input{margin-top:3px;flex:none;accent-color:var(--ok)}
.steps li a{color:var(--text)}.steps li a:hover{color:var(--accent);text-decoration:none}
.steps li.depth-1{padding-left:20px}.steps li.depth-2{padding-left:40px}.steps li.done a{color:var(--muted);text-decoration:line-through}
.progress-notice{font-size:12px;color:var(--bad);background:var(--bad-soft);border-radius:var(--r-sm);padding:6px 8px;margin:6px 0}
.lab-head{margin-bottom:16px}.lab-head h1{font-size:30px}
.lab-meta{display:flex;gap:18px;flex-wrap:wrap;color:var(--muted);font-size:14px;margin-top:8px}
.lab-main{min-width:0}
.lab-body{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);padding:28px 32px;box-shadow:var(--sh);font-size:15.5px;line-height:1.65}
.md h1{font-size:24px;margin:26px 0 10px}.md h2{font-size:21px;margin:30px 0 10px;padding-bottom:6px;border-bottom:1px solid var(--line)}
.md h3{font-size:18px;margin:26px 0 8px}.md h4{font-size:16px;margin:20px 0 6px}
.md h2.lab-step,.md h3.lab-step,.md h4.lab-step{padding-left:12px;border-left:4px solid var(--accent);border-radius:2px}
.md p,.md ul,.md ol{margin:8px 0}.md li{margin:4px 0}
.md img{max-width:100%;height:auto;border-radius:var(--r);border:1px solid var(--line);box-shadow:var(--sh-sm)}
.md table{border-collapse:collapse;margin:12px 0;font-size:14px;display:block;overflow-x:auto}.md th,.md td{border:1px solid var(--line);padding:6px 10px}.md th{background:var(--surface-2)}
.md blockquote{margin:14px 0;padding:10px 14px;border-left:4px solid var(--line-2);background:var(--surface-2);border-radius:0 var(--r) var(--r) 0}.md blockquote p{margin:4px 0}
.md blockquote.callout-warn{border-left-color:var(--warn);background:var(--warn-soft)}.md blockquote.callout-info{border-left-color:var(--info);background:var(--info-soft)}.md blockquote.callout-ok{border-left-color:var(--ok);background:var(--ok-soft)}
.md code{font:13px/1.5 var(--mono);background:var(--code-inline);padding:1px 6px;border-radius:5px}
.md pre{position:relative;background:var(--code-bg);color:var(--code-fg);padding:14px 16px;border-radius:var(--r);overflow-x:auto;margin:12px 0;border:1px solid color-mix(in srgb,var(--code-fg) 12%,transparent)}
.md pre code{background:none;padding:0;color:inherit;font-size:13px}
.md mark{background:var(--warn-soft);color:var(--text);padding:0 3px;border-radius:3px}
/* Блок кода: код и действия над ним не накладываются друг на друга. Раньше кнопки лежали
   поверх кода абсолютом, и длинная команда уезжала под них. */
.md .code-block{margin:12px 0;background:var(--code-bg);border:1px solid color-mix(in srgb,var(--code-fg) 12%,transparent);border-radius:var(--r);overflow:hidden}
.md .code-block>pre{margin:0;border:0;border-radius:0;background:none;padding-top:6px}
.md .code-actions{display:flex;justify-content:flex-end;gap:6px;padding:8px 10px 0}
.copy-btn{font:12px var(--font);padding:4px 9px;border-radius:6px;border:1px solid rgba(148,163,184,.35);background:rgba(30,41,59,.85);color:#cbd5e1;cursor:pointer;opacity:.75}.copy-btn:hover{opacity:1}
.hljs-comment,.hljs-quote{color:#94a3b8;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-built_in,.hljs-name{color:#93c5fd}.hljs-string,.hljs-attr,.hljs-template-tag{color:#86efac}.hljs-number,.hljs-literal{color:#fca5a5}.hljs-title,.hljs-section{color:#fde68a}.hljs-variable,.hljs-template-variable{color:#fdba74}.hljs-meta{color:#c4b5fd}
/* Учебная среда, автопроверки, отчёт, редактор, адаптив */
.sandbox{border-top:4px solid var(--accent)}
.sandbox-controls{gap:6px}
.terminal{margin:12px 0;border-radius:var(--r);padding:10px;background:#0b1020;min-height:360px;border:1px solid #1e293b;box-shadow:inset 0 0 0 1px rgba(255,255,255,.03)}
.terminal .xterm{height:360px}
.checks{margin-top:16px;border-top:1px solid var(--line);padding-top:12px}
.check-list{list-style:none;padding:0;margin:8px 0}
.check-list li{display:flex;gap:10px;align-items:flex-start;padding:8px 10px;border-radius:var(--r-sm);font-size:14px;border:1px solid transparent}
.check-list li+li{margin-top:5px}
.check-mark{flex:none;width:1.3em;height:1.3em;border-radius:50%;display:inline-grid;place-items:center;font-weight:700;font-size:12px}
.check-idle{background:var(--surface-2);color:var(--muted)}.check-idle .check-mark{background:var(--surface-3)}
.check-ok{background:var(--ok-soft);color:var(--ok);border-color:color-mix(in srgb,var(--ok) 25%,transparent)}.check-ok .check-mark{background:var(--ok);color:#fff}
.check-fail{background:var(--bad-soft);color:var(--bad);border-color:color-mix(in srgb,var(--bad) 25%,transparent)}.check-fail .check-mark{background:var(--bad);color:#fff}
.report{margin-top:24px}.report summary{cursor:pointer;font-weight:600;padding:8px 0;color:var(--accent-ink)}.report-form{margin-top:12px}
.q{font-weight:500;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r);padding:12px 14px}
.q-num{font-weight:700;color:var(--accent)}.q-text{display:inline}.q textarea{font-weight:400;background:var(--surface)}
.feedback{margin-top:8px;padding:10px 12px;background:var(--surface);border-radius:var(--r-sm);border:1px solid var(--line)}
.history{margin-top:10px}
.lab-nav{display:flex;justify-content:space-between;gap:12px;margin-top:20px;flex-wrap:wrap}
.answer{padding:12px 0;border-bottom:1px solid var(--line)}.answer-body{background:var(--surface-2);padding:10px 12px;border-radius:var(--r-sm);margin-top:6px}
.editor-split{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}
.editor-src textarea{font:13px/1.5 var(--mono);min-height:600px}
.editor-preview{max-height:80vh;overflow:auto;position:sticky;top:74px}
.preview-structure{font-size:13px;padding-bottom:8px;margin-bottom:8px;border-bottom:1px solid var(--line)}
.course-desc{font-size:15px}
.hero{display:grid;grid-template-columns:1.2fr .8fr;gap:36px;align-items:center;padding:34px 0}
.hero h1{font-size:38px;letter-spacing:-.02em;line-height:1.1}
.hero-list{padding-left:0;list-style:none;margin:16px 0 0}.hero-list li{margin:10px 0;padding-left:0;color:var(--text-2)}
.login-card{margin:0;box-shadow:var(--sh-lg)}
@media (max-width:900px){.lab-layout{grid-template-columns:1fr}.side-sticky{position:static;max-height:none}.hero{grid-template-columns:1fr;padding:16px 0}.hero h1{font-size:30px}.editor-split,.grid-2,.grid-3,.grid-4{grid-template-columns:1fr}.editor-preview{position:static;max-height:none}.grid-2>.card{margin-bottom:18px}.lab-body{padding:18px}.terminal,.terminal .xterm{min-height:280px;height:280px}h1{font-size:24px}}
/* iximiuz-подобные детали: счётчик задач, подсказки, таймер, индикатор связи, каталог */
.task-counter{font:600 13px/1 var(--mono);background:var(--surface-3);color:var(--text-2);padding:3px 9px;border-radius:999px;margin-left:8px}
.task-counter.all-done{background:var(--ok-soft);color:var(--ok)}
.autocheck{font-size:13px;color:var(--muted);font-weight:500}
.check-body{display:flex;flex-direction:column;gap:4px;min-width:0}
.check-hint{font:12px/1.5 var(--mono);white-space:pre-wrap;background:color-mix(in srgb,var(--warn-soft) 70%,var(--surface));border:1px dashed color-mix(in srgb,var(--warn) 40%,transparent);color:var(--text-2);padding:6px 8px;border-radius:var(--r-sm);margin-top:2px}
.checks.checking .check-list{opacity:.6;transition:opacity .2s}
.checks.checking h3::after{content:" · проверяю…";font-weight:400;font-size:13px;color:var(--muted)}
.conn{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;vertical-align:middle;margin-left:8px}
.conn-dot{width:9px;height:9px;border-radius:50%;background:var(--muted)}
.conn-online{color:var(--ok)}.conn-online .conn-dot{background:var(--ok);box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 22%,transparent)}
.conn-connecting{color:var(--warn)}.conn-connecting .conn-dot{background:var(--warn);animation:pulse 1.2s infinite}
.conn-gone{color:var(--bad)}.conn-gone .conn-dot{background:var(--bad)}
.solution{margin-top:16px;border-top:1px solid var(--line);padding-top:8px}
.solution summary{cursor:pointer;font-weight:600;color:var(--accent-ink)}
.solution-body{margin-top:10px;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r);padding:14px 16px}
.solution-locked{margin-top:16px;border-top:1px solid var(--line);padding-top:12px}
/* Каталог курса: поиск + чипы категорий + пустое состояние */
.catalog-filter{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}
.catalog-filter input[type=search]{max-width:560px}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{display:inline-flex;align-items:center;padding:5px 12px;border-radius:999px;border:1px solid var(--line-2);background:var(--surface);color:var(--text-2);font-size:13px;font-weight:600}
.chip:hover{text-decoration:none;border-color:var(--accent);color:var(--accent-ink)}
.chip-on{background:var(--accent-soft);color:var(--accent-ink);border-color:transparent}

/* Каталог карточками (анатомия карточки референса: полоса категории, заголовок, описание clamp 3, CTA внизу справа) */
/* На телефоне длинное описание курса сворачивается, чтобы список лабораторных был виден сразу */
.lab-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(340px,1fr));gap:20px}
.lab-card{display:flex;flex-direction:column;min-height:212px;background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r);overflow:hidden;box-shadow:var(--sh);transition:border-color .12s,box-shadow .12s}
.lab-card:hover{border-color:var(--accent);box-shadow:var(--sh-lg)}
.lab-card.row-draft{opacity:.7}
/* Задание CTF отличается от лабораторной с первого взгляда: своя полоса, свой цвет рамки при
   наведении и подпись вида работы. Метка в полосе дублирует цвет словом — цвет один не считается. */
.lab-card.ctf-card:hover{border-color:var(--ctf);box-shadow:var(--sh-lg)}
.ctf-card .lab-strip{background:var(--ctf)}
.ctf-card .lab-card-title a:hover{color:var(--ctf-ink)}
.ctf-section .page-head h2{color:var(--ctf-ink)}
/* Разделитель между лабораторными и заданиями в списке курса на дашборде. */
.lab-list-sep{display:flex;align-items:center;gap:10px;margin:14px 0 6px;color:var(--ctf-ink);font-weight:600;font-size:14px}
.lab-list-sep::after{content:"";flex:1;height:1px;background:var(--line-2)}
.lab-row.ctf-row .lab-row-mark{background:var(--ctf-soft);color:var(--ctf-ink)}
/* Страница задания: та же вёрстка, но заголовок и метка вида окрашены своим цветом. */
.lab-layout.is-ctf .lab-head{border-left:4px solid var(--ctf);padding-left:14px}
.kind-mark{display:inline-block;background:var(--ctf-soft);color:var(--ctf-ink);border-radius:999px;padding:1px 10px;font-weight:600}
/* Выбор игровой учётной записи задания в шапке рабочей панели. */
.wb-entry{display:inline-flex;align-items:center;gap:6px;font-size:13px}
.wb-entry select{font:inherit;padding:2px 6px;border-radius:6px;border:1px solid var(--line-2);background:var(--surface);color:var(--text)}
/* Адрес сетевой службы задания: его копируют, поэтому он крупный и моноширинный. */
/* Разбор задания: поля ответов во всю ширину, вопросы читаются как текст, а не как подписи. */
.report-form{display:flex;flex-direction:column;gap:14px}
.report-q{display:flex;flex-direction:column;gap:6px}
.report-q-text{font-weight:500;line-height:1.5}
.report-form textarea{font:inherit;width:100%;min-width:0;padding:8px 10px;border:1px solid var(--line-2);border-radius:8px;background:var(--surface);color:var(--text);resize:vertical}
.report-row{border-top:1px solid var(--line);padding:10px 0}
.report-row summary{display:flex;gap:10px;align-items:center;flex-wrap:wrap;cursor:pointer}
.report-answer{white-space:pre-wrap;margin:0 0 10px}
.report-journal{border-left:3px solid var(--line-2);padding-left:12px;margin:8px 0}
.report-journal h3,.report-answers h3{font-size:15px;margin:6px 0}
.report-grade{display:flex;gap:10px;align-items:end;flex-wrap:wrap;margin-top:8px}
.report-grade .grow{flex:1 1 260px;display:flex;flex-direction:column;gap:4px}
.report-grade input{font:inherit;padding:6px 8px;border:1px solid var(--line-2);border-radius:8px;background:var(--surface);color:var(--text)}
.net-target .net-addr code{font-size:16px;padding:6px 10px;background:var(--code-bg,var(--surface-2,#0000000d));border-radius:8px;display:inline-block}
/* Полоса карточки берёт акцент: на странице курса это акцент курса, и карточки лабораторных
   оказываются в его цвете, а не в общем синем платформы. */
.lab-strip{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:6px 10px;background:var(--accent);color:#ffffff;font-size:13px;font-weight:500;line-height:20px}
.lab-strip .env-chip{margin:0;background:rgba(255,255,255,.18);color:#fff}
.lab-card-body{display:flex;flex-direction:column;gap:8px;padding:18px 20px;flex:1}
.lab-card-title{font-size:19px;font-weight:600;line-height:1.35;margin:0}.lab-card-title a{color:var(--text)}.lab-card-title a:hover{color:var(--accent-ink);text-decoration:none}
.lab-card-desc{color:var(--muted);font-size:14.5px;line-height:1.5;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;margin:0}
.lab-card-meta{display:flex;gap:12px;align-items:center;flex-wrap:wrap;font-size:13px;color:var(--muted);margin-top:auto;padding-top:6px}
.lab-card-meta .bar{flex:1 1 100px;min-width:80px}
.lab-card-foot{display:flex;justify-content:space-between;align-items:center;gap:8px;padding-top:8px}
.btn-start{text-transform:uppercase;letter-spacing:.04em;font-size:13px;padding:6px 20px}
/* Рабочее пространство: материалы слева, терминал+задачи справа (закреплены), как challenge-workspace референса */
.ws-toggle{margin-left:0}
@media (min-width:1280px){
  .lab-layout.ws-on{grid-template-columns:220px minmax(0,1fr) var(--ws-right,480px);gap:20px}
  .lab-layout.ws-on .ws-right{position:relative}
  /* Ручка ширины: узкая полоса на левой кромке колонки, заметная только при наведении. */
  .ws-resize{display:none;position:absolute;left:-12px;top:0;bottom:0;width:10px;cursor:col-resize;border-radius:4px}
  .lab-layout.ws-on .ws-resize{display:block}
  .ws-resize:hover,.ws-resize:focus-visible{background:var(--accent-soft);outline:none}
  .lab-layout.ws-on .ws-right{position:sticky;top:70px;max-height:calc(100vh - 86px);overflow:auto;display:flex;flex-direction:column}
  /* Колонка со средой — гибкая и ограничена высотой экрана, а карточка внутри режет всё лишнее
     (overflow:hidden ради скруглённых углов). Без запрета на сжатие карточка ужималась до высоты
     колонки, и список задач обрывался на середине: докрутить до него было нельзя. Теперь карточка
     сохраняет свою высоту, а прокручивается сама колонка. */
  .lab-layout.ws-on .ws-right .workbench{margin:0;border-top:none;border-radius:var(--r-lg);flex:0 0 auto}
  .lab-layout.ws-on .ws-right .terminal{min-height:0;height:52vh}
  .lab-layout.ws-on .ws-right .terminal .xterm{height:calc(52vh - 20px)}
  .lab-layout.ws-on .ws-right .workbench>p.muted{display:none}
  .lab-layout.ws-on .ws-right .check-list li{padding:6px 8px;font-size:13.5px}
  .lab-layout.ws-on .lab-body{padding:22px 24px}
}
.ws-right:empty{display:none}
/* Задачи с вводом, фатальные проверки, блок «В каждой лабораторной есть» */
.check-fatal{background:var(--bad-soft);color:var(--bad);border-color:var(--bad)}.check-fatal .check-mark{background:var(--bad);color:#fff}
.input-task{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-top:6px}
.input-task input{margin:0;flex:1 1 180px;max-width:320px;padding:6px 10px;font:13px var(--mono)}
.input-task input[readonly]{background:var(--surface-3);color:var(--text-2)}
.input-msg{flex-basis:100%}
.includes{margin:22px 0 4px}.includes h3{margin:0 0 10px;font-size:13px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.includes-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}
.inc{display:flex;flex-direction:column;gap:3px;padding:10px 12px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);font-size:13px}
.inc b{font-size:13.5px}.inc span{color:var(--muted)}
/* ===== Рабочая панель (workbench): планка, терминал, экран запуска ===== */
.workbench{margin:24px 0 0;background:#0f1522;border:1px solid #1f2a3d;border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-lg);color:#e2e8f0}
.wb-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 12px;background:#141c2c;border-bottom:1px solid #1f2a3d;flex-wrap:wrap}
.wb-left,.wb-right{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.wb-title{font-weight:650;font-size:14px;color:#f1f5f9}
.wb-state{font-size:12px;padding:2px 9px;border-radius:999px;background:#1e293b;color:#cbd5e1}
.wb-state.is-running{background:#0f3d24;color:#86efac}.wb-state.is-busy{background:#3b2f0b;color:#fde68a}.wb-state.is-error{background:#3f1515;color:#fca5a5}
.wb-timer{font:600 12px var(--mono);color:#94a3b8}.wb-timer.warn{color:#fbbf24}
.workbench .conn{margin:0}
/* В панели среды состояние показывает точка, но текст должен остаться в дереве страницы:
   display:none убрал бы его и из программы чтения с экрана, оставив состояние одним цветом (B-4). */
.workbench .conn-text{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.wb-tasks-pill{font-size:12.5px;color:#cbd5e1;background:#1e293b;padding:3px 10px;border-radius:999px}.wb-tasks-pill b{font-family:var(--mono);color:#f8fafc;margin-left:4px}
.wb-tasks-pill.all-done{background:#0f3d24;color:#86efac}.wb-tasks-pill.all-done b{color:#bbf7d0}
.wb-switch{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:#cbd5e1;margin:0;font-weight:500;cursor:pointer}.wb-switch input{accent-color:#4ade80;margin:0}
.wb-ib{width:34px;height:32px;border-radius:7px;border:1px solid #2a3650;background:#1b2436;color:#cbd5e1;font:600 12px var(--font);cursor:pointer;display:inline-grid;place-items:center;padding:0;list-style:none;box-shadow:none}
.wb-ib:hover{background:#243049;color:#fff}.wb-ib[hidden]{display:none!important}
.wb-menu{position:relative}.wb-menu summary::-webkit-details-marker{display:none}.wb-menu summary{list-style:none}
.wb-menu-list{position:absolute;right:0;top:34px;z-index:5;background:#141c2c;border:1px solid #2a3650;border-radius:var(--r);padding:8px;display:flex;flex-direction:column;gap:6px;min-width:200px;box-shadow:var(--sh-lg)}
.wb-menu-list .btn{justify-content:flex-start}
.wb-body{display:grid;grid-template-columns:minmax(0,1fr);gap:0}
@media (min-width:1100px){.lab-layout:not(.ws-on) .wb-body{grid-template-columns:minmax(0,1.6fr) minmax(320px,1fr)}.lab-layout:not(.ws-on) .wb-tasks{border-left:1px solid #1f2a3d}}
.wb-pane{min-width:0}
.wb-term{position:relative;display:flex;flex-direction:column;min-width:0;background:#0b1020}
.workbench .terminal{margin:0;border:0;border-radius:0;background:#0b1020;padding:10px 6px 6px 12px;height:var(--term-h,420px);min-height:220px;box-shadow:none}
.workbench .terminal .xterm{height:100%}
.workbench .xterm .xterm-viewport{background:#0b1020!important;scrollbar-width:thin;scrollbar-color:#334155 transparent}
.wb-resize{height:8px;cursor:ns-resize;background:linear-gradient(#0b1020,#141c2c);border-top:1px solid #1f2a3d;position:relative}
.wb-resize::after{content:"";position:absolute;left:50%;top:2px;width:36px;height:3px;margin-left:-18px;border-radius:2px;background:#334155}
.wb-launch{display:flex;align-items:center;justify-content:center;min-height:var(--term-h,420px);padding:24px;background:radial-gradient(60% 60% at 50% 30%,#152038 0%,#0b1020 70%)}
.wb-launch-inner{max-width:440px;text-align:center}.wb-launch-icon{font-size:40px;margin-bottom:6px}
.wb-launch h3{margin:0 0 6px;color:#f1f5f9;font-size:18px}.wb-launch p{font-size:14px;color:#94a3b8;margin:0 0 14px}
.wb-launch-actions{display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
.wb-launch .alert{text-align:left;margin:0 0 12px}
.wb-spinner{margin-top:14px;font-size:13px;color:#cbd5e1;display:inline-flex;align-items:center;gap:8px}
.wb-spinner span{width:14px;height:14px;border:2px solid #334155;border-top-color:#86efac;border-radius:50%;animation:spin .8s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
.workbench.is-full{position:fixed;inset:0;z-index:100;border-radius:0;margin:0;display:flex;flex-direction:column}
.workbench.is-full .wb-body{flex:1;min-height:0;grid-template-columns:minmax(0,1.6fr) minmax(320px,1fr)}
.workbench.is-full .terminal,.workbench.is-full .wb-launch{height:auto;flex:1}.workbench.is-full .wb-term{height:100%}.workbench.is-full .wb-resize{display:none}
.workbench.is-full .wb-tasks{overflow:auto}
/* ===== Задачи как карточки ===== */
.wb-tasks{background:var(--surface);color:var(--text);padding:14px 14px 10px;border-top:1px solid #1f2a3d}
.workbench .checks{margin:0;border-top:0;padding-top:0}
.tasks-head{margin-bottom:10px}
.tasks-progress-text{font-size:13px;color:var(--text-2)}.tasks-progress-text b{color:var(--text)}
.tasks-progress .bar{margin-top:6px;height:6px}
.task-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:8px}
.task{display:grid;grid-template-columns:26px minmax(0,1fr) 24px;gap:10px;align-items:start;padding:10px 12px;border:1px solid var(--line-2);border-radius:var(--r);background:var(--surface);transition:border-color .15s,background .15s}
.task-num{width:24px;height:24px;border-radius:50%;background:var(--surface-3);color:var(--text-2);font:600 12px var(--mono);display:grid;place-items:center;margin-top:1px}
.task-title{font-size:14px;font-weight:500;line-height:1.4;color:var(--text)}
.task-status{width:22px;height:22px;border-radius:50%;display:grid;place-items:center;font-size:12px;font-weight:700;margin-top:1px;border:2px solid var(--line-2);color:transparent}
.task.check-ok{border-color:color-mix(in srgb,var(--ok) 45%,transparent);background:color-mix(in srgb,var(--ok-soft) 55%,var(--surface))}
.task.check-ok .task-num{background:var(--ok);color:#fff}.task.check-ok .task-status{background:var(--ok);border-color:var(--ok);color:#fff}.task.check-ok .task-status::before{content:"✓"}
.task.check-ok .task-title{color:var(--text-2);text-decoration:line-through;text-decoration-color:color-mix(in srgb,var(--ok) 50%,transparent)}
.task.check-fail{border-color:color-mix(in srgb,var(--bad) 40%,transparent)}
.task.check-fail .task-status{background:var(--bad-soft);border-color:var(--bad);color:var(--bad)}.task.check-fail .task-status::before{content:"✕"}
.task.check-fatal{border-color:var(--bad);background:var(--bad-soft)}
.task.check-fatal .task-status{background:var(--bad);border-color:var(--bad);color:#fff}.task.check-fatal .task-status::before{content:"!"}
.task.check-idle .task-status{border-style:dashed}
.checks.checking .task.check-idle .task-status,.checks.checking .task.check-fail .task-status{border-top-color:var(--accent);animation:spin .9s linear infinite;border-style:solid;color:transparent}
.checks.checking .task .task-status::before{content:""}
.task .check-hint{margin-top:8px;font:12.5px/1.5 var(--mono);white-space:pre-wrap;background:var(--surface-2);border-left:3px solid var(--warn);border-radius:0 var(--r-sm) var(--r-sm) 0;padding:8px 10px;color:var(--text-2)}
.task.check-fatal .check-hint{border-left-color:var(--bad)}
.task .input-task{margin-top:8px}.task .input-task input{max-width:260px}
.tasks-foot{margin:10px 0 0;font-size:12px}
.checks.checking .tasks-progress-text::after{content:" · проверяю…";color:var(--muted)}
/* тёмная тема: карточки задач внутри панели */
:root[data-theme="dark"] .wb-tasks{background:#0f1522;border-top-color:#1f2a3d}
:root[data-theme="dark"] .task{background:#141c2c;border-color:#2a3650}
/* Практики: кликабельные команды, лестница подсказок, стадии запуска, задачи под шагом */
.run-btn{font:12px var(--font);padding:4px 9px;border-radius:6px;border:1px solid rgba(134,239,172,.45);background:rgba(20,83,45,.6);color:#bbf7d0;cursor:pointer;opacity:.9}.run-btn:hover{opacity:1}
.md pre.ran,.md .code-block:has(pre.ran){outline:2px solid rgba(74,222,128,.4)}
.hint-ladder{margin-top:8px;display:flex;flex-direction:column;gap:6px}
.hint-list{display:flex;flex-direction:column;gap:6px}.wb-tasks .task,.hint-list>*,.task pre,.task code{overflow-wrap:anywhere;word-break:break-word}
.hint-item{font-size:13px;line-height:1.5;color:var(--text-2);background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-sm);padding:8px 10px}
.hint-item b{color:var(--muted);font-weight:600;margin-right:6px;font-size:12px}
.hint-btn{align-self:flex-start;background:transparent;border:1px dashed var(--line-2);color:var(--accent-ink);font:600 12.5px var(--font);padding:5px 10px;border-radius:999px;cursor:pointer}
.hint-btn:hover{border-style:solid;background:var(--accent-soft)}
.wb-extend{width:auto;padding:0 8px;font-family:var(--mono);font-size:11.5px}
.wb-stages{display:flex;justify-content:center;gap:14px;margin-top:10px;font-size:12px;color:#94a3b8}
.wb-stages span{position:relative;padding-left:14px}.wb-stages span::before{content:"";position:absolute;left:0;top:5px;width:8px;height:8px;border-radius:50%;background:#334155}
.wb-stages span.on{color:#e2e8f0}.wb-stages span.on::before{background:#86efac;box-shadow:0 0 0 3px rgba(134,239,172,.2)}.wb-stages span.done{color:#94a3b8}.wb-stages span.done::before{background:#22a06b}
.wb-read{margin:10px 0 0;color:#94a3b8}
.step-tasks{display:flex;flex-wrap:wrap;gap:6px;margin:-4px 0 12px}
.step-task{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:500;padding:3px 9px;border-radius:999px;border:1px solid var(--line-2);background:var(--surface);color:var(--text-2)}
.step-task::before{content:"";width:8px;height:8px;border-radius:50%;border:1.5px dashed var(--line-2)}
.step-task.ok{border-color:color-mix(in srgb,var(--ok) 40%,transparent);color:var(--ok);background:var(--ok-soft)}.step-task.ok::before{border:0;background:var(--ok)}
.step-task.fail{border-color:color-mix(in srgb,var(--bad) 40%,transparent);color:var(--bad)}.step-task.fail::before{border:0;background:var(--bad)}
.step-done{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:4px 0 14px;padding:10px 12px;border-radius:var(--r);background:var(--ok-soft);border:1px solid color-mix(in srgb,var(--ok) 35%,transparent);color:var(--ok);font-weight:600;font-size:13.5px}
.step-done a{color:inherit}
/* На узком экране действия занимают всю строку и не жмутся в угол. */
@media (max-width:700px){.md .code-actions{justify-content:flex-start;flex-wrap:wrap}}
/* Режим «по шагам» */
.step-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 10px;padding:8px 10px;background:var(--surface);border:1px solid var(--line);border-radius:var(--r);position:sticky;top:62px;z-index:5}
.step-bar-left{display:flex;align-items:center;gap:8px;min-width:0}
.step-bar-title{font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.step-bar-mode{margin:0;color:var(--muted)}
.step-bar .btn:disabled{opacity:.4}
body.step-mode .lab-body .step-sec>.lab-step:first-child{margin-top:4px}
#steps li.current>label{background:var(--accent-soft);border-radius:6px;padding:2px 6px;margin:0 -6px}
#steps li.current a{color:var(--accent-ink);font-weight:600}
/* Телефон: вкладки и клавиши */
.mtabs{position:fixed;left:0;right:0;bottom:0;z-index:40;display:flex;background:var(--surface);border-top:1px solid var(--line);padding-bottom:env(safe-area-inset-bottom)}
.mtabs button{flex:1;min-height:52px;border:0;background:transparent;font:600 12.5px var(--font);color:var(--muted);cursor:pointer}
.mtabs button.on{color:var(--accent-ink);box-shadow:inset 0 2px 0 var(--accent)}
.mkeys{display:flex;gap:6px;padding:8px 10px;background:#0b1020;border-top:1px solid #1f2a3d;overflow-x:auto}
.mkeys button{flex:1 0 auto;min-width:44px;min-height:40px;border-radius:6px;border:1px solid #2a3650;background:#1b2436;color:#cbd5e1;font:600 12.5px var(--mono);cursor:pointer}
.mkeys button.on{background:#0f3d24;color:#86efac;border-color:#22a06b}
@media (max-width:900px){
  body.mobile-lab main{padding-bottom:72px}
  body.mobile-lab .lab-side{display:none}
  body.mobile-lab .lab-layout{gap:12px}
  body.mobile-lab[data-mtab="materials"] #sandbox,body.mobile-lab[data-mtab="materials"] #report,body.mobile-lab[data-mtab="materials"] .includes,body.mobile-lab[data-mtab="materials"] .lab-nav{display:none}
  body.mobile-lab[data-mtab="term"] .lab-head,body.mobile-lab[data-mtab="term"] .step-bar,body.mobile-lab[data-mtab="term"] .lab-body,body.mobile-lab[data-mtab="term"] #report,body.mobile-lab[data-mtab="term"] .includes,body.mobile-lab[data-mtab="term"] .lab-nav,body.mobile-lab[data-mtab="term"] .wb-tasks{display:none}
  body.mobile-lab[data-mtab="term"] .workbench{margin:0;border-radius:var(--r)}
  body.mobile-lab[data-mtab="term"] .terminal,body.mobile-lab[data-mtab="term"] .wb-launch{height:calc(100vh - 300px)!important;min-height:260px}
  body.mobile-lab[data-mtab="tasks"] .lab-head,body.mobile-lab[data-mtab="tasks"] .step-bar,body.mobile-lab[data-mtab="tasks"] .lab-body,body.mobile-lab[data-mtab="tasks"] #report,body.mobile-lab[data-mtab="tasks"] .includes,body.mobile-lab[data-mtab="tasks"] .lab-nav,body.mobile-lab[data-mtab="tasks"] .wb-term,body.mobile-lab[data-mtab="tasks"] .wb-resize{display:none}
  body.mobile-lab[data-mtab="report"] .lab-head,body.mobile-lab[data-mtab="report"] .step-bar,body.mobile-lab[data-mtab="report"] .lab-body,body.mobile-lab[data-mtab="report"] #sandbox,body.mobile-lab[data-mtab="report"] .includes{display:none}
  body.mobile-lab .wb-bar .wb-right{gap:4px}
}
@media (max-width:900px){
  .wb-bar{padding:6px 8px;gap:6px}.wb-title{font-size:13px}
  #wb-font-dn,#wb-font-up,#ws-toggle,.wb-tasks-pill{display:none!important}
  body.mobile-lab[data-mtab="term"] .terminal,body.mobile-lab[data-mtab="term"] .wb-launch{height:calc(100vh - 380px)!important}
  .step-bar{top:56px}
}
/* Панель среды: компактнее в правой колонке и на телефоне */
.wb-menu-row{display:flex;align-items:center;gap:6px}
.lab-layout.ws-on .ws-right .wb-tasks-pill{display:none}
.lab-layout.ws-on .ws-right .wb-left{flex:1 1 100%}
.lab-layout.ws-on .ws-right .wb-right{width:100%;justify-content:flex-end}
body.step-mode .step-sec>:first-child{margin-top:0}
.lab-body>.step-sec:first-child>:first-child{margin-top:0}
@media (max-width:900px){
  body.mobile-lab .footer{display:none}
  .wb-bar{row-gap:4px}.wb-left{flex:1 1 100%}.wb-right{width:100%;justify-content:flex-end;flex-wrap:nowrap}
  .wb-timer{font-size:11.5px}
}
/* Аудит 2 */
.step-bar{position:static}
.includes{margin:18px 0 4px}.includes h3{display:inline;margin:0 10px 0 0}
.includes-grid{display:inline-flex;flex-wrap:wrap;gap:6px;vertical-align:middle}
.inc{flex-direction:row;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;font-size:12.5px}.inc b{font-size:12.5px;font-weight:600}.inc span{display:none}
.resume-body .muted{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:820px}
.scoreboard td[class^="cell-"]{text-align:center;font-size:15px}
.scoreboard td.cell-pass,.scoreboard td.cell-fail,.scoreboard td.cell-submitted{font-weight:700}
.scoreboard td.cell-none{color:var(--line-2)}

@media (max-width:900px){.wb-ib{width:40px;height:38px}.btn-sm{min-height:36px}.steps input[type=checkbox]{width:18px;height:18px}}
.steps li{display:flex;gap:8px;align-items:flex-start}.steps input[type=checkbox]{margin-top:4px;flex:none}

/* Группа вариантов квиза. min-inline-size у fieldset по умолчанию min-content: без сброса
   карточка задачи ужималась до ширины самого длинного слова, и текст вопроса вставал колонкой. */
.quiz-task{display:flex;flex-direction:column;gap:5px;margin-top:8px;min-inline-size:0}
.quiz-set{border:0;margin:0;padding:0;min-inline-size:0;display:flex;flex-direction:column;gap:5px}
.quiz-opt{display:flex;gap:8px;align-items:flex-start;font-weight:400;margin:0;cursor:pointer;color:var(--text);line-height:1.4}
.quiz-opt input{margin-top:3px;flex:none}
.quiz-actions{display:flex;gap:10px;align-items:center;margin-top:4px}
.quiz-explain{margin-top:6px;padding:8px 10px;border-left:3px solid var(--ok);background:var(--ok-soft);border-radius:var(--r-sm);color:var(--text)}
.task.check-ok .quiz-opt{opacity:.9}

/* Вкладки терминалов внутри верстака */
.workbench .terminal{display:flex;flex-direction:column;padding:0}
/* Полоса вкладок: padding сверху и по бокам, чтобы кольцо фокуса не срезалось краем полосы (A-1). */
.term-tabs{display:flex;gap:4px;padding:6px 8px 0;background:#0b1020;border-bottom:1px solid #1f2a3d;flex:none;overflow-x:auto}
.term-tab-wrap{display:inline-flex;align-items:center;background:#111827;border:1px solid #1f2a3d;border-bottom:0;border-radius:6px 6px 0 0;white-space:nowrap}
.term-tab-wrap:has(.term-tab.on){background:#0b1020;border-color:#334155}
.term-tab{display:inline-flex;align-items:center;gap:6px;border:0;background:none;color:#94a3b8;font:600 12px var(--font);padding:5px 4px 5px 10px;cursor:pointer;white-space:nowrap;outline-offset:-2px}
.term-tab.on{color:#e2e8f0}
/* Отключённая вкладка: приглушённый цвет и зачёркивание, а не прозрачность — прозрачность роняла
   контраст ниже читаемого, а слова «нет связи» дописывает клиент (B-4). */
.term-tab.off{color:#9aa4b2;text-decoration:line-through}
.term-tab-state{font-weight:400;text-decoration:none;font-size:11px}
.term-x{border:0;background:none;color:#9aa4b2;font-size:11px;line-height:1;padding:6px 8px;cursor:pointer;outline-offset:-2px}
.term-x:hover,.term-x:focus-visible{color:#f87171}
.term-add{padding:5px 10px;font-size:14px;border:1px solid #1f2a3d;border-bottom:0;background:#111827;color:#94a3b8;border-radius:6px 6px 0 0;cursor:pointer;outline-offset:-2px}
/* min-width:0 обязателен всей цепочке: без него xterm, посчитавший ширину по умолчанию (80
   колонок), распирает панель шире карточки — и вывод обрезается её краем. С нулевым минимумом
   панель всегда равна карточке, а fit() считает колонки по фактической ширине. */
.term-panes{flex:1;min-height:0;min-width:0;display:flex}
.term-pane{flex:1;min-height:0;min-width:0;display:flex;flex-direction:column;padding:8px 6px 6px 12px}
.term-pane[hidden]{display:none}
.workbench .terminal .term-pane .xterm{flex:1;min-height:0;min-width:0;max-width:100%;height:auto}

/* Проверка, чей результат относился к уничтоженной среде: виден как история, но не считается выполненной. */
.task.check-stale .task-num { background: var(--surface-2); color: var(--muted); border-color: var(--line); }
.task.check-stale .task-title { color: var(--text-2); }
.check-stale-note { margin-top: 4px; }
/* Блок самопроверки на лабораторной без учебной среды. */
.selfcheck .task-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.selfcheck .task { padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); }
.selfcheck .task-title { font-weight: 600; margin-bottom: 6px; }

/* Кнопка отметки шага в заголовке: не подменяет роль заголовка, поэтому оглавление страницы для
   программ чтения с экрана остаётся целым (A-8). */
.md .lab-step{position:relative}
.step-mark{margin-left:8px;border:1px solid var(--line);background:none;color:var(--muted);font-size:13px;line-height:1;padding:3px 7px;border-radius:6px;cursor:pointer;vertical-align:middle}
.step-mark:hover,.step-mark:focus-visible{color:var(--ok);border-color:var(--ok)}
.step-mark[aria-pressed="true"]{color:var(--ok);border-color:var(--ok);background:color-mix(in srgb,var(--ok) 12%,transparent)}

/* Итог лабораторной: короткая карточка вместо раздела отчёта. */
.result-card .alert{margin:0}
.result-card .feedback{margin-top:10px}

/* Вопрос преподавателю — кнопка в углу экрана, как чат на сайте (правка по замечанию автора:
   раздел внизу страницы никто не находил). Раскрывается через <details>, без скриптов. */
.help-fab{position:fixed;right:18px;bottom:18px;z-index:60}
.help-fab>summary{list-style:none;cursor:pointer}
.help-fab>summary::-webkit-details-marker{display:none}
.help-fab-btn{display:flex;align-items:center;justify-content:center;width:52px;height:52px;margin-left:auto;border-radius:50%;
  background:var(--accent);color:#fff;font-size:24px;font-weight:700;box-shadow:var(--sh-md);border:1px solid rgba(0,0,0,.08);transition:transform .12s ease}
.help-fab-btn:hover{transform:translateY(-1px)}
.help-fab[open] .help-fab-btn{background:var(--surface-3);color:var(--text)}
.help-fab .help-dot{position:absolute;top:2px;right:2px;width:12px;height:12px;border-radius:50%;background:var(--ok);border:2px solid var(--surface)}
.help-fab-panel{position:absolute;right:0;bottom:64px;width:min(380px,calc(100vw - 36px));max-height:min(70vh,560px);overflow:auto;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-lg);padding:14px 16px}
.help-fab-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.help-fab-panel label{display:block;margin:8px 0}
.help-fab-panel .ticket-list{margin:0 0 10px}
@media (max-width:640px){.help-fab{right:12px;bottom:12px}.help-fab-btn{width:46px;height:46px;font-size:21px}}

/* Решение: обычная карточка статьи. Раньше блок лежал внутри тёмной карточки среды и наследовал
   её фон — на светлой теме он выглядел как оторванная чёрная полоса (скриншот автора). */
.solution{margin-top:18px;padding:14px 18px}
.solution>summary{cursor:pointer;font-weight:600;color:var(--accent-ink);display:flex;align-items:center;gap:8px}
.solution[open]>summary{margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.solution-body{margin:0}

/* Шаги в боковой панели: навигация, а не чек-лист. Отметку ставит автопроверка. */
.steps li{display:flex;gap:6px;align-items:baseline}
.steps li.done>a{color:var(--text-2)}
.steps li.done::before{content:"✓";color:var(--ok);font-weight:700;font-size:12px;line-height:1.6}
.steps li:not(.done)::before{content:"";width:9px}

/* --- Страница задания CTF под длительное решение (docs/UX-CTF-TASK-PAGE.md) --- */


/* Граница «что переживёт снос среды»: свёрнута по умолчанию — читается один раз, а место
   в липкой колонке дорогое. Причины две (простой и прерываемая машина), и обе внутри. */
.note-preempt{margin:0 0 12px;border:1px solid var(--line);border-radius:var(--r);background:var(--surface-2)}
.note-preempt>summary{cursor:pointer;padding:8px 12px;font-size:13px;font-weight:600;color:var(--text-2)}
.note-preempt[open]>summary{border-bottom:1px solid var(--line)}
.note-preempt p{margin:8px 12px}

/* Журнал работы: рабочая поверхность рядом с терминалом, а не форма в конце страницы. */
.task-journal .page-head{margin-bottom:8px}
.journal-saved{white-space:nowrap}
.journal-saved.is-bad{color:var(--bad)}
.journal-field{display:block;margin:0}
#journal-notes{width:100%;min-height:180px;resize:vertical;font:13px/1.55 var(--mono)}
.journal-note{margin-top:8px}

/* Вехи: отмечает сам студент, поэтому выглядят как его список, а не как автопроверки —
   без номеров, статусов и цветных значков проверки. */
.milestones{list-style:none;margin:0 0 6px;padding:0;display:grid;gap:2px}
.milestone label{display:flex;gap:9px;align-items:baseline;padding:5px 8px;border-radius:var(--r-sm);cursor:pointer}
.milestone label:hover{background:var(--surface-2)}
.milestone input{margin:0;flex:none}
.milestone.done>label>span{color:var(--muted);text-decoration:line-through}

@media (max-width:900px){.conn-card{grid-template-columns:1fr;gap:2px}.conn-card dt{margin-top:6px}}

/* Подсказки задания: лестница на всю работу. Свёрнуты — открыть подсказку должно быть решением,
   а не тем, что попалось на глаза по дороге к терминалу. */
.task-hints>summary{cursor:pointer;font-weight:600;color:var(--ctf-ink)}
.task-hints[open]>summary{margin-bottom:8px}
.task-hints .hint-ladder{margin-top:8px}


/* --- Рабочее место задания: терминал главный, материал вторичен --- */
/* Полноэкранный режим — и есть режим долгой работы над заданием: условие прочитано, дальше
   студент неделями живёт в оболочке. У лабораторной рядом с терминалом нужен список задач, у
   задания задача одна — флаг, и отдавать ей треть экрана незачем: терминал занимает всю ширину,
   флаг ложится полосой под ним. Отдельной кнопки для этого не завожу — их на панели и так много,
   а ⛶ уже есть. */
.lab-layout.is-ctf .workbench.is-full .wb-body{grid-template-columns:minmax(0,1fr)}
.lab-layout.is-ctf .workbench.is-full .wb-tasks{border-left:none;border-top:1px solid #1f2a3d;max-height:34vh}
/* У задания CTF правой панели задач в верстаке нет вовсе: терминал занимает всю ширину, а
   флаг стоит полосой под ним. */
.lab-layout.is-ctf .wb-body{grid-template-columns:minmax(0,1fr)}
.conn-card dt{font-size:11px;text-transform:uppercase;letter-spacing:.04em;opacity:.85}
.conn-card dd+dt{margin-top:5px}

/* Сетевое задание: среда есть, оболочки в ней нет. Терминальную обвязку убираем из вида —
   полный экран, переключатель раскладки, размер шрифта, ручку высоты и выбор учётной записи:
   всё это про терминал, которого здесь не будет. Из разметки не вырезаем: часть этих узлов
   трогает общий клиент среды, и его поломка стоила бы дороже лишнего скрытого узла. */
.workbench.is-netonly #wb-full,
.workbench.is-netonly #ws-toggle,
.workbench.is-netonly .wb-menu-row,
.workbench.is-netonly .wb-entry,
.workbench.is-netonly #wb-resize{display:none}
.net-service{padding:18px 20px;color:var(--code-fg);background:var(--code-bg)}
.net-service h3{margin:0 0 8px;font-size:15px;color:#fff}
.net-service p{margin:0 0 8px}
.net-service .muted{color:#94a3b8}
.net-service code{font:13px var(--mono);background:rgba(255,255,255,.08);padding:2px 6px;border-radius:6px}
.net-service .net-addr code{font-size:17px;padding:8px 12px;display:inline-block;color:#fff}
/* Пока адреса нет — висит объяснение; как только клиент его подставил, объяснение лишнее. */
.net-service .net-addr:not([hidden])~.net-service-wait{display:none}


/* ===== Задание CTF: страница из горизонтальных полос =======================
   Колоночная раскладка лабораторной заданию не подошла по трём причинам сразу, и все три видны
   на скриншотах автора от 15.09. Узкая колонка ломала данные входа: «chris-knight» вставал
   столбиком по одной букве, потому что значения рубились по символам (word-break:break-all) в
   колонке шириной 180 px. «Ход работы» оказывался разорван: полоса вех — в колонке, сами вехи —
   в журнале внизу экрана. А флаг сидел пунктом списка проверок, приклеенным к нижнему краю
   чёрного терминала, с номером и красным крестом — сдача флага выглядела как непройденная
   проверка. Полосы во всю ширину снимают все три: каждая про одно и занимает столько, сколько
   ей нужно. */
.lab-layout.ctf-stack{grid-template-columns:minmax(0,1fr);gap:0}
.ctf-stack .lab-main{display:flex;flex-direction:column;gap:16px}
.ctf-stack .lab-main>*{margin:0}
.ctf-stack .lab-head{margin:0}
.lab-head-staff{display:inline-flex;gap:8px;margin-left:auto}

/* Полоса подключения: четыре факта в строку. Значения моноширинные и переносятся только там,
   где иначе не помещаются, — рубить логин по буквам нельзя ни при какой ширине. */
.ctf-conn{padding:12px 18px}
.conn-row{display:flex;flex-wrap:wrap;gap:10px 30px;margin:0}
.conn-row>div{display:flex;align-items:baseline;gap:8px;min-width:0}
.conn-row dt{margin:0;font-size:11.5px;letter-spacing:.05em;text-transform:uppercase;color:var(--ctf-ink);font-weight:600;white-space:nowrap}
.conn-row dd{margin:0;min-width:0;font-size:14px}
.conn-row code{font:13.5px var(--mono);background:transparent;padding:0;word-break:normal;overflow-wrap:anywhere}

/* Условие: полоса, которая сворачивается. До первого действия открыта, дальше — по требованию. */
.ctf-brief{padding:0}
.ctf-brief>summary{display:flex;align-items:baseline;gap:10px;padding:14px 18px;cursor:pointer;list-style:none}
.ctf-brief>summary::-webkit-details-marker{display:none}
.ctf-brief>summary::before{content:'▸';color:var(--muted);font-size:12px}
.ctf-brief[open]>summary::before{content:'▾'}
.ctf-brief[open]>summary{border-bottom:1px solid var(--line)}
.ctf-brief .lab-body{background:transparent;border:0;box-shadow:none;border-radius:0;padding:18px 26px 26px}
.ctf-brief .lab-body>:first-child{margin-top:0}
.ctf-brief .md{max-width:80ch}

/* Полоса флага: это действие, а не пункт списка. Поле во всю ширину, кнопка рядом, ответ под
   ними. Ни номера, ни отметки проверки: их красный крест до сдачи читался как «вы ошиблись». */
.ctf-flag{padding:16px 18px;border-left:4px solid var(--ctf)}
.ctf-flag.is-done{border-left-color:var(--ok)}
.ctf-flag-head h2{margin:0;font-size:19px}
.ctf-flag-head p{margin:4px 0 0}
.ctf-task-list{list-style:none;margin:12px 0 0;padding:0;display:flex;flex-direction:column;gap:12px}
.ctf-task-list>.task{display:block;padding:0;border:0;background:none;box-shadow:none}
.ctf-task-list>.task::before,.ctf-task-list>.task::after{content:none}
.ctf-flag .flag-task{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.ctf-flag .flag-task input{flex:1 1 320px;min-width:0;font:15px var(--mono);padding:10px 12px;border:1px solid var(--line-2);border-radius:8px;background:var(--surface);color:var(--text)}
.ctf-flag .flag-msg{flex:1 1 100%}
.ctf-strip-note{margin:0}

/* «Ход работы»: полоса прогресса стоит над теми вехами, которые её двигают. */
.journal-progress{margin:0 0 14px}
.journal-field-h{display:block;font-weight:600;margin-bottom:6px}

@media (max-width:900px){
  .ctf-conn{padding:10px 12px}
  .conn-row{gap:8px 18px}
  .ctf-brief .lab-body{padding:14px 16px 18px}
}

/* Мобильные вкладки у задания CTF: те же полосы, разложенные по вкладкам. Правила для
   лабораторной построены вокруг панели задач внутри верстака, а у задания её нет — флаг стоит
   отдельной полосой, и вкладка «Флаг» показывает именно её. */
@media (max-width:900px){
  body.mobile-lab[data-mtab="materials"] .is-ctf .ctf-flag,
  body.mobile-lab[data-mtab="materials"] .is-ctf .ctf-strip-note,
  body.mobile-lab[data-mtab="materials"] .is-ctf #journal{display:none}
  body.mobile-lab[data-mtab="term"] .is-ctf .ctf-conn,
  body.mobile-lab[data-mtab="term"] .is-ctf .ctf-brief,
  body.mobile-lab[data-mtab="term"] .is-ctf .ctf-flag,
  body.mobile-lab[data-mtab="term"] .is-ctf .ctf-strip-note,
  body.mobile-lab[data-mtab="term"] .is-ctf #journal{display:none}
  body.mobile-lab[data-mtab="tasks"] .is-ctf .ctf-conn,
  body.mobile-lab[data-mtab="tasks"] .is-ctf .ctf-brief,
  body.mobile-lab[data-mtab="tasks"] .is-ctf #sandbox,
  body.mobile-lab[data-mtab="tasks"] .is-ctf #journal{display:none}
  body.mobile-lab[data-mtab="report"] .is-ctf .ctf-conn,
  body.mobile-lab[data-mtab="report"] .is-ctf .ctf-brief,
  body.mobile-lab[data-mtab="report"] .is-ctf .ctf-flag,
  body.mobile-lab[data-mtab="report"] .is-ctf .ctf-strip-note{display:none}
}

/* Колонка задания CTF в таблице результатов: имя вместо номера, поэтому ширину ограничиваем —
   иначе восемь названий растягивают таблицу и номера лабораторных уезжают за край. */
.scoreboard th.col-ctf{white-space:nowrap}
.scoreboard th.col-ctf .col-name{display:inline-block;max-width:12ch;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom}

/* Итоговые столбцы таблицы результатов: отделены чертой от столбцов работ, чтобы «Баллы» не
   читались как ещё одна работа, и не сжимаются при прокрутке длинной таблицы. */
.scoreboard th.col-total,.scoreboard td.col-total{white-space:nowrap;background:var(--surface-2,transparent)}
.scoreboard th.col-total:last-of-type,.scoreboard td.col-total:last-of-type{border-right:2px solid var(--line)}

/* Подписи кнопок панели среды: видимая подсказка при наведении и фокусе, не зависящая от
   секундной задержки системного title. Панель тёмная, подсказка светлая — контраст в обе темы. */
.workbench [data-tip]{position:relative}
.workbench [data-tip]:hover::after,.workbench [data-tip]:focus-visible::after{content:attr(data-tip);position:absolute;top:calc(100% + 6px);left:50%;transform:translateX(-50%);white-space:nowrap;background:#e2e8f0;color:#0f1522;font:500 12px var(--font);padding:4px 8px;border-radius:6px;box-shadow:var(--sh-md);z-index:30;pointer-events:none}
.workbench .wb-right [data-tip]:hover::after,.workbench .wb-right [data-tip]:focus-visible::after{left:auto;right:0;transform:none}

/* Квиз, перенесённый под шаг: та же карточка задачи, но в потоке материала — с отступом и
   левой чертой, чтобы читался как вопрос к прочитанному, а не как ещё один абзац. */
.lab-body .quiz-inline{margin:14px 0 18px;padding:0 0 0 12px;border-left:3px solid var(--accent-soft);list-style:none}
.lab-body .quiz-inline .task{margin:0}
