/* Терминал (/terminal/). Палитра и раскладка живут здесь, а не в base.css:
   рабочее место занимает весь экран и не делит токены с сайтом.
   Вынесено из templates/content/terminal.html 01.09.2026 — 53 КБ ехали
   в каждом ответе и не попадали в кэш браузера. */
  /* ── Оболочка ───────────────────────────────────────────────────────────────
     Терминал живёт на своём экране: шапка сайта, лента котировок и подвал скрыты,
     иначе рабочее место оказывается «внутри страницы» и теряет высоту. */
  body:has(.trm) { background: #05070d; overflow: hidden; }
  /* Скрываем ЛЕНТУ САЙТА по её id: класс .tape общий с лентой терминала, и правило
     по классу гасило заодно нашу — оставалась пустая полоса в сетке. */
  body:has(.trm) #tickerTape,
  body:has(.trm) .navbar,
  body:has(.trm) .mnav,
  body:has(.trm) .mnav-overlay,
  body:has(.trm) > footer { display: none; }
  body:has(.trm) .page { padding: 0; max-width: none; }
  body:has(.trm) #main-content { height: 100vh; }

  .trm {
    /* Палитра: графит + один акцент. Зелёный и красный означают ТОЛЬКО динамику,
       синий — только действие; больше цветов на плотном экране читать нечем. */
    /* Терминал заметно темнее сайта (#0e1016 у base.css): переключение режима должно
       читаться мгновенно, а на почти чёрном фоне свечи и котировки контрастнее. */
    --trm-bg: #05070d;          /* фон-разделитель между панелями */
    --pane: #0a0e16;            /* панель */
    --pane2: #111823;           /* врезка: шапки таблиц, поля, активная строка */
    --line: #1a2230;            /* единственная линия интерфейса */
    --line2: #26303f;
    --tx: #e8ecf2;              /* данные */
    --tx2: #93a1b5;             /* подписи */
    --tx3: #63718a;             /* служебное */
    --acc: #4d8dff;
    --acc-soft: rgba(77,141,255,.12);
    --up: #26c281;
    --dn: #ef4d56;
    --mono: "JetBrains Mono", "Cascadia Code", Consolas, ui-monospace, monospace;
    --sans: "Inter", system-ui, -apple-system, sans-serif;

    position: fixed; inset: 0; z-index: 5;
    display: grid;
    grid-template-rows: 38px 26px 1fr;
    grid-template-columns: 264px 1fr 316px;
    grid-template-areas:
      "cmd  cmd   cmd"
      "tape tape  tape"
      "wl   main  side";
    gap: 1px; background: var(--line);
    font-family: var(--sans); font-size: 13px; color: var(--tx);
    -webkit-font-smoothing: antialiased;
  }
  .trm ::selection { background: var(--acc-soft); }
  .trm :focus-visible { outline: 2px solid var(--acc); outline-offset: -2px; }
  /* Скроллбары тонкие: полоса не должна отъедать ширину у данных. */
  .trm ::-webkit-scrollbar { width: 6px; height: 6px; }
  .trm ::-webkit-scrollbar-track { background: var(--pane); }
  .trm ::-webkit-scrollbar-thumb { background: #26303f; border-radius: 9999px; }
  .trm ::-webkit-scrollbar-thumb:hover { background: #35435a; }

  /* ── Командная строка ──────────────────────────────────────────────────── */
  .cmd { grid-area: cmd; display: flex; align-items: center; gap: 10px;
    padding: 0 10px; background: var(--pane); }
  .cmd__fv { font-weight: 700; font-size: 12px; letter-spacing: .16em; color: var(--tx);
    text-decoration: none; padding-right: 10px; border-right: 1px solid var(--line); }
  .cmd__fv b { color: var(--acc); font-weight: 700; }
  .cmd__box { position: relative; flex: 0 1 460px; display: flex; align-items: center; gap: 7px;
    height: 24px; padding: 0 8px; background: var(--pane2); border: 1px solid var(--line2); }
  .cmd__box:focus-within { border-color: var(--acc); }
  .cmd__box input { flex: 1; min-width: 0; height: 100%; border: 0; outline: 0; background: none;
    color: var(--tx); font: 400 13px/1 var(--mono); }
  .cmd__box input::placeholder { color: var(--tx3); }
  .cmd__box kbd { font: 500 10px/1 var(--mono); color: var(--tx3); }
  .cmd__hint { color: var(--tx3); font-size: 11px; white-space: nowrap; }
  .cmd__hint b { color: var(--tx2); font-weight: 600; font-family: var(--mono); }
  /* Подсказка команд — над всем, поэтому фон непрозрачный и своя рамка. */
  .cmd__drop { position: absolute; top: 23px; left: -1px; right: -1px; z-index: 300;
    display: none; max-height: 320px; overflow-y: auto;
    background: var(--pane2); border: 1px solid var(--line2); }
  .cmd__drop.open { display: block; }
  .cmd__drop b.grp { display: block; padding: 5px 9px 3px; font-size: 10px; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase; color: var(--tx3); }
  .cmd__row { display: flex; align-items: baseline; gap: 9px; padding: 4px 9px; cursor: pointer; }
  .cmd__row.sel, .cmd__row:hover { background: var(--acc-soft); }
  .cmd__row i { font-style: normal; font-family: var(--mono); font-weight: 700; color: var(--acc);
    min-width: 58px; }
  /* ISIN длиннее тикера — своя ширина, иначе описание выпуска съезжает. */
  .cmd__row.bond i { min-width: 108px; color: #9a8cff; }
  .cmd__more { padding: 5px 9px; font-size: 11px; color: var(--tx3);
    border-top: 1px solid var(--line); }
  .cmd__row span { color: var(--tx2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cmd__right { margin-left: auto; display: flex; align-items: center; gap: 12px;
    font-family: var(--mono); font-size: 11px; white-space: nowrap; }
  .cmd__sess { display: inline-flex; align-items: center; gap: 6px; color: var(--tx3);
    text-transform: uppercase; letter-spacing: .08em; }
  .cmd__sess.on { color: var(--tx2); }
  /* Точка состояния рынка 4px: зелёная — торги идут, серая — закрыто. Ничего больше:
     нормальную работу не аннотируют, помечают только отклонение. */
  .dot { width: 4px; height: 4px; border-radius: 50%; background: var(--tx3); flex: none; }
  .cmd__sess.on .dot { background: var(--up); }
  /* Режим данных одной буквой, как бейдж задержки в проф-терминалах: real-time не
     помечается вообще, у нас же ISS отдаёт котировки с задержкой — значит, честное «D». */
  .dmode { font: 700 11px/1 var(--mono); color: #f0a04b; cursor: help; }
  .cmd__clock { color: var(--tx); font-weight: 700; font-size: 12px; }
  /* Рабочие пространства: три независимых набора настроек — «утренний обзор»,
     «работа по бумаге», «облигации» — переключаются одним нажатием. */
  .ws { display: inline-flex; gap: 1px; }
  .ws button { width: 20px; height: 20px; border: 1px solid var(--line2); background: var(--pane2);
    color: var(--tx3); font: 600 10px/1 var(--mono); cursor: pointer; }
  .ws button.on { background: var(--acc); border-color: var(--acc); color: #06090f; }
  /* Кнопка возврата панелей к исходному порядку — рядом с рабочими пространствами:
     перетаскивание без «как было» превращается в ловушку. */
  .cmd__reset { background: none; border: 1px solid var(--line2); color: var(--tx3);
    font: inherit; font-size: 11px; padding: 2px 8px; border-radius: 4px; cursor: pointer; }
  .cmd__reset:hover { color: var(--tx); border-color: var(--acc); }
  /* На узком экране кнопка бесполезна и вредна: HTML5-перетаскивание на тач-устройствах
     не запускается вовсе, а сама кнопка добавляла 127px к и без того переполненному ряду
     командной строки (замер при ширине 420px: 947px против 820px без неё). */
  @media (max-width: 1100px) { .cmd__reset { display: none; } }
  .cmd__exit { color: var(--tx2); text-decoration: none; padding: 2px 8px;
    border: 1px solid var(--line2); font-family: var(--sans); font-size: 11px; }
  .cmd__exit:hover { color: var(--tx); border-color: var(--acc); }

  /* ── Лента котировок ───────────────────────────────────────────────────── */
  .trm .tape { grid-area: tape; display: flex; align-items: center; overflow: hidden;
    background: var(--pane); position: static; z-index: auto; }
  .tape__t { display: inline-flex; gap: 0; white-space: nowrap; animation: tapeRun 90s linear infinite; }
  .tape:hover .tape__t { animation-play-state: paused; }
  @keyframes tapeRun { from { transform: translateX(0); } to { transform: translateX(-50%); } }
  .tape__i { display: inline-flex; align-items: baseline; gap: 6px; padding: 0 13px;
    border-right: 1px solid var(--line); font-family: var(--mono); font-size: 12px; cursor: pointer; }
  .tape__i b { color: var(--tx); font-weight: 600; }
  .tape__i s { color: var(--tx2); text-decoration: none; }
  .tape__i u { text-decoration: none; }
  .up { color: var(--up); } .dn { color: var(--dn); } .fl { color: var(--tx2); }

  /* ── Общие части панелей ───────────────────────────────────────────────── */
  .pane { background: var(--pane); display: flex; flex-direction: column; min-height: 0; min-width: 0; }
  .ph { display: flex; align-items: center; gap: 8px; height: 28px; flex: none;
    padding: 0 10px; background: var(--pane); border-bottom: 1px solid var(--line);
    font-size: 12px; font-weight: 600; letter-spacing: .04em; color: var(--tx2); }
  /* Число справа (итог панели) не обрезаем: у трёхзначного результата отваливался знак
     процента — «53 сделки · +109,6» вместо «+109,6%». Место уступает ПОДПИСЬ слева. */
  .ph .n { margin-left: auto; font-family: var(--mono); font-weight: 400; color: var(--tx3);
    white-space: nowrap; flex: 0 0 auto; }
  .ph .ph__t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .ph a { color: var(--tx3); text-decoration: none; font-weight: 500; }
  .ph a:hover { color: var(--acc); }

  /* ── Watchlist ─────────────────────────────────────────────────────────── */
  .wl { grid-area: wl; }
  .wl__cls { display: flex; flex: none; height: 24px; border-bottom: 1px solid var(--line); }
  .wl__cls button { flex: 1; border: 0; background: var(--pane2); color: var(--tx2); cursor: pointer;
    font: 600 11px/1 var(--sans); border-right: 1px solid var(--line); }
  .wl__cls button:last-child { border-right: 0; }
  .wl__cls button.on { background: var(--pane); color: var(--tx); box-shadow: inset 0 -1px 0 var(--acc); }
  /* Колонки списка облигаций: доходность и дюрация вместо цены и дневного изменения —
     облигацию выбирают по доходности к погашению, а не по «сколько сегодня выросла». */
  .wl.bonds .wl__hd, .wl.bonds .wl__r { grid-template-columns: minmax(56px, 1fr) 52px 44px 46px; }
  .wl.bonds .wl__r svg.spk, .wl.bonds .wl__hd span.spkh { display: none; }

  .wl__f { display: flex; align-items: center; gap: 6px; height: 26px; flex: none;
    padding: 0 8px; border-bottom: 1px solid var(--line); background: var(--pane2); }
  .wl__f input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; color: var(--tx);
    font: 400 12px/1 var(--mono); }
  .wl__f input::placeholder { color: var(--tx3); }
  .wl__f button { border: 0; background: none; color: var(--tx3); cursor: pointer; font-size: 11px; padding: 0 2px; }
  .wl__f button.on { color: var(--acc); }
  /* Заголовок группы: сектор, число бумаг и средневзвешенное изменение по нему —
     видно, тянет сектор целиком или движется одна бумага. */
  .wl__g { display: flex; align-items: center; gap: 6px; height: 22px; padding: 0 10px;
    background: var(--pane2); border-bottom: 1px solid var(--line); cursor: pointer;
    font: 600 10px/22px var(--sans); letter-spacing: .04em; text-transform: uppercase;
    color: var(--tx2); position: sticky; top: 0; z-index: 2; }
  .wl__g em { font-style: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0; }
  .wl__g s { text-decoration: none; color: var(--tx3); font-weight: 400; flex: none; }
  .wl__g b { margin-left: auto; font-family: var(--mono); font-size: 11px; }
  .wl__g i { font-style: normal; color: var(--tx3); width: 8px; }
  /* Имя компании занимает остаток строки; спарклайн и числа — фиксированные колонки.
     Раньше 1fr делил место с ними и название ужималось до «С…», «Га…». */
  /* Имя получает нижнюю границу трека: без неё колонка ужималась до 45 px на 1920
     и до 5 px на 1280, то есть исчезала. Когда места мало, честнее убрать спарклайн,
     чем название бумаги. */
  .wl__hd, .wl__r { display: grid; grid-template-columns: minmax(56px, 1fr) 26px 60px 56px;
    align-items: center; gap: 4px; padding: 0 6px 0 10px; overflow: hidden; }
  .wl__r svg.spk { width: 26px; }   /* ровно ширина своего трека, иначе съезжает вправо */
  @media (max-width: 1500px) {
    .wl__hd, .wl__r { grid-template-columns: minmax(52px, 1fr) 58px 54px; }
    .wl__hd span:nth-child(2), .wl__r svg.spk { display: none; }
  }
  /* Спарклайн за год прямо в строке: тренд читается без открытия графика — приём Koyfin. */
  .wl__empty { padding: 14px 12px; color: var(--tx3); font-size: 11px; line-height: 1.5; }
  /* Матрица корреляций: колонки узкие, первая — с тикером и липкая при прокрутке. */
  .t.cor th, .t.cor td { padding: 3px 6px; font-size: 11px; }
  .t.cor td.s { position: sticky; left: 0; background: var(--pane); z-index: 1; }
  .t.cor thead th:first-child { position: sticky; left: 0; background: var(--pane2); z-index: 2; }
  /* Заметка по бумаге: поле растёт под текст, но не бесконечно. */
  #noteBox { display: block; width: calc(100% - 18px); margin: 7px 9px 9px; padding: 6px 7px;
    border: 1px solid var(--line2); background: var(--pane2); color: var(--tx);
    font: 12px/1.45 var(--sans); resize: vertical; min-height: 52px; max-height: 200px; }
  #noteBox:focus { outline: 0; border-color: var(--acc); }
  #noteBox::placeholder { color: var(--tx3); }
  .t td.hot { color: var(--warn, #f6c825); }
  /* Быстрые условия скринера: те же кнопки-переключатели, что у наборов колонок. */
  .sigf { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; padding: 5px 10px 7px;
    border-bottom: 1px solid var(--line); background: var(--pane2); }
  /* Поле фильтра в панели условий: узкое и в одну строку с кнопками — иначе оно
     растягивалось на всю ширину и «сбросить» уезжала на вторую строку. */
  .sigf input { flex: none; width: 148px; height: 22px; padding: 0 7px;
    border: 1px solid var(--line2); background: var(--pane); color: var(--tx);
    font: 500 11px/1 var(--mono); outline: none; }
  .sigf input:focus { border-color: var(--acc); }
  .sigf input::placeholder { color: var(--tx3); font-family: var(--sans); }
  .sigf button { border: 1px solid var(--line2); background: none; color: var(--tx2);
    font: 11px/1 var(--sans); padding: 4px 8px; cursor: pointer; }
  .sigf button:hover { color: var(--tx); border-color: var(--acc); }
  .sigf button.on { color: var(--bg); background: var(--acc); border-color: var(--acc); }
  .sigf__n { margin-left: auto; color: var(--tx3); font-size: 11px; }
  .sigf__n u { color: var(--acc); cursor: pointer; text-decoration: none; margin-left: 6px; }
  .cor__note { padding: 8px 10px 12px; color: var(--tx3); font-size: 11px; line-height: 1.5; }
  /* Финансы: строка на год - выручка, EBITDA, прибыль; ниже форвардные мультипликаторы
     по прогнозным годам. Те же числа, что в карточке бумаги (tickers/multiples.py). */
  .fin { padding: 6px 9px 4px; display: grid; gap: 3px; }
  .fin__r { display: grid; grid-template-columns: 40px 1fr 1fr 1fr; align-items: center;
    gap: 6px; font-size: 12px; color: var(--tx2); }
  .fin__r span { font-family: var(--mono); font-size: 11px; text-align: right; }
  .fin__r i { font-style: normal; font-family: var(--mono); font-size: 11px; color: var(--tx3); }
  .fin__r.hd { color: var(--tx3); font-size: 10px; text-transform: uppercase;
    letter-spacing: .03em; }
  .fin__r.hd span { font-family: inherit; font-size: 10px; }
  .fin__r.e i { color: var(--acc); }            /* прогнозный год - как на карточке */
  .fin__m { padding: 4px 9px 9px; display: grid; gap: 3px; }
  /* Подпись мультипликатора длиннее года («Дивдоходность»), поэтому колонка шире, а
     сама подпись усекается: иначе она распирала грид и колонки значений разъезжались
     относительно строки выше. */
  .fin__m .fin__r { grid-template-columns: 78px repeat(3, 1fr); }
  .fin__m .fin__r i { min-width: 0; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; }
  .fin__note { padding: 0 9px 9px; color: var(--tx3); font-size: 11px; line-height: 1.45; }
  /* Аналоги: строка на бумагу - форвардные мультипликаторы соседей по отрасли.
     Своя бумага помечена и стоит первой, чтобы сравнение читалось сверху вниз. */
  .peer { padding: 6px 9px 4px; display: grid; gap: 2px; }
  /* Колонка имени — 68px и БЕЗ переносов: при 52px названия с пробелом («ПКБ 1Р-05»,
     «АБЗ-1 2Р02») рвались на две строки, а слитные той же длины («Аэрфью2Р03») — нет, и
     строки в таблице разъезжались по высоте. Хвост длинного имени режем многоточием:
     полное название и так в подсказке строки. */
  .peer__r { display: grid; grid-template-columns: 68px repeat(3, 1fr); align-items: center;
    gap: 6px; font-size: 12px; color: var(--tx2); cursor: pointer; padding: 1px 0; }
  .peer__r:hover { background: var(--acc-soft); }
  .peer__r span { font-family: var(--mono); font-size: 11px; text-align: right; }
  .peer__r i { font-style: normal; font-family: var(--mono); font-size: 11px;
    color: var(--tx2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    min-width: 0; }
  .peer__r.hd { color: var(--tx3); font-size: 10px; text-transform: uppercase;
    letter-spacing: .03em; cursor: default; }
  .peer__r.hd:hover { background: none; }
  .peer__r.hd span, .peer__r.hd i { font-family: inherit; font-size: 10px; }
  .peer__r.me i, .peer__r.me span { color: var(--tx); }
  .peer__r.me { background: var(--pane2); }
  .peer__note { padding: 4px 9px 9px; color: var(--tx3); font-size: 11px; line-height: 1.45; }
  /* Риск в доходности: поправка на дефолт и состав премии к ОФЗ */
  .bcr { padding: 7px 9px 4px; }
  .bcr__v { font-family: var(--mono); font-size: 20px; font-weight: 600; line-height: 1.1; }
  .bcr__l { color: var(--tx2); font-size: 11px; margin-top: 2px; }
  .bcr__s { color: var(--tx3); font-size: 10.5px; margin-top: 3px; line-height: 1.4; }
  .bcr__bar { display: flex; height: 9px; border-radius: 5px; overflow: hidden;
    background: var(--bg2); margin-top: 8px; }
  .bcr__bar i { display: block; height: 100%; }
  .bcr__lg { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 6px;
    font-size: 10.5px; color: var(--tx3); font-family: var(--mono); }
  .bcr__lg span { display: inline-flex; align-items: center; gap: 4px; }
  .bcr__lg i { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
  .bcr--def { background: #d9705f; } .bcr--liq { background: #c9a33f; }
  .bcr--rsk { background: #5f8ed0; }
  .bcr__tr { margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--line);
    font-size: 10.5px; color: var(--tx2); line-height: 1.4; }
  .bcr__tr.bad { color: var(--warn, #c9a33f); }
  /* Разбор скора привлекательности на факторы */
  .bcr__sc { margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--line); }
  .bcr__sch { font-size: 10.5px; color: var(--tx2); margin-bottom: 5px; }
  .bcr__sch b { color: var(--tx); font-family: var(--mono); font-size: 12px; }
  .bcr__qr { display: grid; grid-template-columns: 84px 1fr 22px; align-items: center;
    gap: 6px; font-size: 10px; color: var(--tx3); margin-bottom: 3px; }
  .bcr__qr i { display: block; height: 5px; border-radius: 3px; background: var(--bg2);
    overflow: hidden; }
  .bcr__qr i b { display: block; height: 100%; background: #5f8ed0; }
  .bcr__qr u { text-decoration: none; text-align: right; font-family: var(--mono);
    color: var(--tx2); }
  .bcr__qr.na i b { background: var(--tx3); opacity: .4; }
  /* Кривая ОФЗ: линия - живая ZCYC (к ней считается премия), точки - сами госбумаги,
     крупная точка - выбранный выпуск. Ниже сдвиг ставок по срокам. */
  .cv { display: block; width: 100%; height: 124px; padding: 4px 4px 0; }
  .cv line { stroke: var(--line2); stroke-width: .6; }
  .cv text.ax { fill: var(--tx3); font-family: var(--mono); font-size: 8px; }
  .cv circle.d { fill: var(--tx3); opacity: .55; }
  .cv circle.me { fill: var(--acc); stroke: var(--bg); stroke-width: 1; }
  .cv polyline.ln { fill: none; stroke: var(--up); stroke-width: 1.4; }
  .cv__r, .cv__hd { display: grid; grid-template-columns: 62px repeat(4, 1fr);
    align-items: center; gap: 6px; padding: 0 9px 3px; font-size: 12px; color: var(--tx2); }
  .cv__r span { font-family: var(--mono); font-size: 11px; text-align: right; }
  .cv__r i { font-style: normal; color: var(--tx3); font-size: 11px; }
  .cv__r span.up { color: var(--up); }
  .cv__r span.dn { color: var(--dn); }
  .cv__hd { color: var(--tx3); font-size: 10px; padding-bottom: 6px; }
  .cv__hd span { text-align: right; font-family: var(--mono); }
  .cv__note { padding: 0 9px 9px; color: var(--tx3); font-size: 11px; line-height: 1.45; }
  /* Против сектора: период, динамика бумаги, разрыв с медианой соседей. */
  .sec2 { padding: 6px 9px 4px; display: grid; gap: 3px; }
  .sec2__r { display: grid; grid-template-columns: 1fr 58px 46px; align-items: center;
    gap: 6px; font-size: 12px; color: var(--tx2); }
  .sec2__r b, .sec2__r u { font-family: var(--mono); font-size: 11px; text-align: right;
    text-decoration: none; }
  .sec2__note { padding: 0 9px 9px; color: var(--tx3); font-size: 11px; line-height: 1.45; }
  /* Тренд по горизонтам: строка на горизонт — направление и RSI. */
  .mtf { padding: 6px 9px 9px; display: grid; gap: 3px; }
  .mtf__r { display: grid; grid-template-columns: 1fr 16px 26px; align-items: center;
    gap: 6px; font-size: 12px; color: var(--tx2); }
  .mtf__r b { font-family: var(--mono); font-size: 13px; text-align: center; }
  .mtf__r u { font-family: var(--mono); font-size: 11px; color: var(--tx3);
    text-decoration: none; text-align: right; }
  .mtf__r u.up { color: var(--up); }
  .mtf__r u.dn { color: var(--dn); }
  /* Сезонность: столбик на месяц, высота — средняя доходность этого месяца за все годы. */
  .season { display: grid; grid-template-columns: repeat(12, 1fr); gap: 2px; padding: 8px 9px 4px; }
  .season i { display: block; position: relative; height: 46px; font-style: normal; }
  .season i b { position: absolute; left: 0; right: 0; display: block; border-radius: 1px; }
  .season i.up b { background: var(--up); bottom: 50%; }
  .season i.dn b { background: var(--dn); top: 50%; }
  .season i::after { content: ''; position: absolute; left: 0; right: 0; top: 50%;
    border-top: 1px dashed var(--line2); }
  .season__m { display: grid; grid-template-columns: repeat(12, 1fr); gap: 2px; padding: 0 9px 8px;
    font-family: var(--mono); font-size: 9px; color: var(--tx3); text-align: center; }
  /* Теплокарта год x месяц: строка - год, ячейка - месячная доходность. Нужна затем,
     что средняя по месяцу не показывает, сложилась она из ровных лет или из одного выброса. */
  .sgrid { display: grid; grid-template-columns: 18px repeat(12, 1fr); gap: 1px;
    padding: 2px 9px 6px; align-items: center; }
  .sgrid b { font-family: var(--mono); font-size: 8px; color: var(--tx3); font-weight: 400; }
  .sgrid i { display: block; height: 9px; background: var(--pane2); }
  /* Разрез по дням недели — за последние три года: на длинном окне это другой рынок. */
  .sdow { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; padding: 2px 9px 8px;
    font-family: var(--mono); font-size: 9px; }
  .sdow span { display: flex; flex-direction: column; align-items: center; gap: 1px; }
  .sdow s { text-decoration: none; color: var(--tx3); }
  .sdow b { font-weight: 500; }
  .season__sum { padding: 0 9px 9px; font-size: 11px; color: var(--tx3); line-height: 1.5; }
  .season__sum b { color: var(--tx); }
  /* Сетапы на бумаге: строка — сетап, под ней два набора чисел (эта бумага и рынок).
     Клик по строке оставляет на графике сделки только этого сетапа. */
  .setl { padding: 7px 9px 4px; display: flex; flex-direction: column; gap: 5px; }
  .setl__r { border: 1px solid var(--line); padding: 5px 7px; cursor: pointer; }
  .setl__r:hover { border-color: var(--line2); }
  .setl__r.on { border-color: var(--acc); }
  .setl__r.mute { opacity: .4; }
  .setl__h { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--tx); }
  /* Сторона сделки — заливкой, а не тонкой рамкой: цветной текст 9px по цветной рамке
     на тёмном фоне читался хуже всего в блоке. */
  .setl__h i { font-style: normal; font-family: var(--mono); font-size: 10px; line-height: 1;
    font-weight: 700; letter-spacing: .3px; padding: 3px 5px; color: #0a0e16; }
  .setl__h i.l { background: var(--up); }
  .setl__h i.s { background: var(--dn); }
  .setl__h u { margin-left: auto; text-decoration: none; font-family: var(--mono);
    font-size: 10px; color: var(--tx3); white-space: nowrap; }
  /* Три колонки: подпись — эта бумага — рынок. Числа стоят строго друг под другом,
     иначе «здесь» и «рынок» глазом не сравнить, а ради этого блок и существует. */
  .setl__d { display: grid; grid-template-columns: auto 1fr 1fr; gap: 2px 6px; margin-top: 5px;
    font-family: var(--mono); font-size: 10px; color: var(--tx3); }
  .setl__d b { color: var(--tx); font-weight: 500; text-align: right; }
  .setl__d s { text-decoration: none; color: var(--tx3); }
  .setl__d s:nth-child(2), .setl__d s:nth-child(3) { text-align: right; color: var(--tx3); }
  .setl__note { padding: 0 9px 9px; font-size: 11px; color: var(--tx3); line-height: 1.5; }
  /* Калькулятор риска: три коротких поля в строку, ответ — обычным списком показателей. */
  .risk { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 8px 9px 4px; }
  .risk label { display: flex; flex-direction: column; gap: 3px; font-size: 10px; color: var(--tx3); }
  .risk input { border: 1px solid var(--line2); background: var(--pane2); color: var(--tx);
    font-family: var(--mono); font-size: 11px; padding: 3px 5px; width: 100%; min-width: 0; }
  .risk input:focus { outline: 0; border-color: var(--acc); }
  .wl__r svg.spk { height: 16px; overflow: visible; }
  .wl__r svg.spk path { fill: none; stroke-width: 1.2; vector-effect: non-scaling-stroke; }
  /* Звёздочка избранного проявляется на наведении и остаётся у отмеченных. */
  .wl__r .st { position: absolute; left: 2px; width: 12px; text-align: center; cursor: pointer;
    color: var(--tx3); opacity: 0; font-size: 11px; line-height: 1; }
  .wl__r { position: relative; }
  .wl__r:hover .st, .wl__r .st.on { opacity: 1; }
  .wl__r .st.on { color: #f0a04b; }
  .wl__hd { height: 22px; flex: none; font-size: 10px; letter-spacing: .04em; text-transform: uppercase;
    color: var(--tx3); background: var(--pane2); border-bottom: 1px solid var(--line);
    white-space: nowrap; overflow: hidden; }
  .wl__hd span { overflow: hidden; text-overflow: ellipsis; }
  .wl__hd span { cursor: pointer; user-select: none; }
  .wl__hd span:hover { color: var(--tx2); }
  /* Подпись активной сортировки: по умолчанию список идёт по обороту торгов —
     трейдер начинает с ликвидных бумаг, а не с алфавита. */
  .wl__hd .so { font-style: normal; color: var(--acc); font-size: 9px; margin-left: 4px;
    opacity: .85; }
  /* Ряд узкий: на самых тесных ширинах длинную подпись порядка прячем. */
  @media (max-width: 1500px) { .wl__hd .so { font-size: 8px; margin-left: 2px; } }
  .wl__hd .r, .wl__r .r { text-align: right; font-family: var(--mono); }
  .wl__b { flex: 1; overflow-y: auto; min-height: 0; }
  /* Строка 24px — как в проф-терминалах: на экран влезает ~30 бумаг без прокрутки. */
  .wl__r { height: 28px; cursor: pointer; border-bottom: 1px solid rgba(26,34,48,.8); }
  .wl__r:hover { background: var(--acc-soft); }
  /* Активная бумага — рамка, а не заливка: заливка зарезервирована под «вот эта строка»
     (переход по ссылке/поиску), иначе два разных смысла красятся одинаково. */
  .wl__r.on { box-shadow: inset 0 0 0 1px var(--acc); background: rgba(77,141,255,.08); }
  .wl__r .s { font-family: var(--mono); font-weight: 600; font-size: 13px; color: var(--tx);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* Название — вторым планом рядом с тикером; режется по фактической ширине колонки,
     а не по счётчику символов: обрезка «ROSNНК Роснефть…» получалась в середине слова. */
  .wl__r .s { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
  .wl__r .s u.own { text-decoration: none; color: var(--acc); font-size: 14px; line-height: 1;
    margin-left: 3px; flex: none; }
  .wl__r .s i { font-style: normal; color: var(--tx3); font-weight: 400; font-size: 11px;
    font-family: var(--sans); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
  .wl__hd .r, .wl__r .r { justify-self: end; }
  .wl__r .p, .wl__r .c { font-size: 12px; font-variant-numeric: tabular-nums;
    white-space: nowrap; overflow: hidden; }
  .wl__r .p { color: var(--tx); }
  .wl__r .c { font-weight: 600; }
  /* Вспышка при изменении цены: цвет текста, а не фон — иначе таблица «мигает». */
  @keyframes flashUp { from { color: var(--up); } to { color: var(--tx); } }
  @keyframes flashDn { from { color: var(--dn); } to { color: var(--tx); } }
  .wl__r .p.f-up { animation: flashUp 1.2s ease-out; }
  .wl__r .p.f-dn { animation: flashDn 1.2s ease-out; }

  /* ── Центр: инструмент, график, рабочая панель ─────────────────────────── */
  /* Высота рабочей панели — переменная: её тянут мышью за разделитель, значение
     переживает перезагрузку. На карте по умолчанию выше: при 232 px половина плиток
     оставалась без подписей. */
  .main.map-open { --work-h: 420px; }
  .main { grid-area: main; display: grid;
    grid-template-rows: 44px 1fr 5px var(--work-h, 232px);
    grid-template-columns: minmax(0, 1fr);      /* иначе min-content таблицы распирает трек */
    gap: 1px; background: var(--line); min-width: 0; min-height: 0; overflow: hidden; }
  /* Полоса захвата тонкая, но с крупной зоной попадания: мышью в 5 px не целятся. */
  .split { position: relative; background: var(--line); cursor: row-resize; z-index: 6;
    touch-action: none; }
  /* Зона попадания шире самой полосы и лежит ПОВЕРХ соседей: снизу к разделителю
     вплотную подходит панель со своими обработчиками, и клик у нижней кромки уходил ей. */
  .split::before { content: ''; position: absolute; left: 0; right: 0; top: -5px; bottom: -5px; }
  .split::after { content: ''; position: absolute; left: 50%; top: 1px; width: 46px; height: 3px;
    margin-left: -23px; background: var(--line2); border-radius: 2px; }
  .split:hover::after, .split.drag::after { background: var(--acc); }
  body.rowresize, body.rowresize * { cursor: row-resize !important; user-select: none; }
  .work, .chart, .inst { min-width: 0; }
  /* Широкая таблица скринера скроллится ВНУТРИ своей панели, а не растягивает колонку:
     на 1280 из-за неё уезжали за край кнопки таймфреймов, слоёв и выгрузка. */
  .work__b table.t { min-width: 860px; }
  .scr__views { display: flex; gap: 1px; padding: 4px 6px; position: sticky; top: 0; z-index: 4;
    background: var(--pane); border-bottom: 1px solid var(--line); }
  .scr__views button { height: 18px; padding: 0 10px; border: 1px solid var(--line2);
    background: var(--pane2); color: var(--tx2); font: 600 10px/1 var(--sans); cursor: pointer; }
  .scr__views button.on { background: var(--acc); border-color: var(--acc); color: #06090f; }
  /* 1fr = minmax(auto, 1fr): min-content широкой таблицы скринера распирал трек и
     средняя колонка залезала на правую. Явный minmax(0, 1fr) держит сетку. */
  .trm { grid-template-columns: 264px minmax(0, 1fr) 316px; }
  .inst { display: flex; align-items: center; gap: 14px; padding: 0 12px; background: var(--pane); }
  .inst__s { font: 700 17px/1 var(--mono); color: var(--tx); }
  .inst__n { color: var(--tx2); font-size: 13px; max-width: 220px; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; }
  .inst__p { font: 700 21px/1 var(--mono); color: var(--tx); font-variant-numeric: tabular-nums; }
  .inst__c { font: 600 15px/1 var(--mono); font-variant-numeric: tabular-nums; }
  .inst__sec { margin-left: auto; display: flex; align-items: center; gap: 10px;
    font-size: 11px; color: var(--tx3); }
  /* Возраст данных — абсолютным временем, а не «5 минут назад»: относительное время
     заставляет считать в уме и врёт при спящей вкладке. */
  .upd { font-family: var(--mono); }
  .inst__sec a { color: var(--tx2); text-decoration: none; border-bottom: 1px solid var(--line2); }
  .inst__sec a:hover { color: var(--acc); border-color: var(--acc); }

  .chart { position: relative; background: var(--pane); min-height: 0; }
  /* Тулбар переносится на вторую строку, когда не помещается: раньше он оставался
     одной строкой и уезжал под правую колонку — на 1600×900 кнопки слоёв и все
     таймфреймы становились некликабельными. */
  .chart__bar { position: absolute; top: 0; left: 34px; right: 0; z-index: 3;
    display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px;
    min-height: 24px; padding: 2px 10px; pointer-events: none; }
  .chart__bar > * { min-width: 0; }
  .chart__ohlc { font: 500 12px/1 var(--mono); color: var(--tx2); white-space: nowrap;
    font-variant-numeric: tabular-nums; }
  .chart__ohlc b { color: var(--tx); font-weight: 600; }
  .chart__span { font: 500 11px/1 var(--mono); color: var(--tx3); white-space: nowrap; }
  /* Оценка выпуска относительно собственной истории: у облигации «дорого» и «дёшево»
     определяются не ценой, а премией к ОФЗ по сравнению с её же средним. */
  .bstat { position: absolute; left: 44px; bottom: 34px; z-index: 3; display: flex; gap: 12px;
    padding: 6px 10px; background: rgba(10,14,22,.86); border: 1px solid var(--line2);
    font: 500 11px/1.5 var(--mono); color: var(--tx2); pointer-events: none; }
  .bstat b { color: var(--tx); }
  .bstat .rich { color: var(--dn); }
  .bstat .cheap { color: var(--up); }
  .bstat[hidden] { display: none; }
  /* Кнопки алерта внутри строки статистики: сама строка событий не ловит (pointer-events:
     none), поэтому кликабельность возвращаем точечно. */
  .bstat__al { pointer-events: auto; }
  .bstat__al b { cursor: pointer; border: 1px solid var(--line2); border-radius: 3px;
    padding: 0 4px; margin-left: 3px; }
  .bstat__al b:hover { border-color: var(--acc); color: var(--acc); }
  /* Легенда сравнения: у каждой бумаги свой цвет и текущее значение от базы 100. */
  .cmpleg { position: absolute; left: 44px; top: 52px; z-index: 3; display: flex; gap: 10px;
    font: 600 11px/1 var(--mono); pointer-events: auto; }
  .cmpleg[hidden] { display: none; }
  .cl { padding: 3px 7px; background: rgba(10,14,22,.86); border: 1px solid var(--line2); }
  .cl.base { color: var(--tx2); }
  .cl { display: inline-flex; align-items: center; gap: 6px; }
  .cl .dot { width: 9px; height: 9px; border-radius: 2px; cursor: pointer; display: inline-block; }
  .cl .dot:hover { outline: 1px solid var(--tx); outline-offset: 1px; }
  .cl .lbl { cursor: pointer; }
  .cl i { font-style: normal; cursor: pointer; opacity: .6; }
  .cl i:hover { opacity: 1; }
  /* Меню фигуры: появляется у выделенного построения, без диалогов и модалок. */
  .shmenu { position: fixed; z-index: 60; display: flex; align-items: center; gap: 4px;
    padding: 4px 5px; background: var(--pane2); border: 1px solid var(--line2); }
  .shmenu[hidden] { display: none; }
  .shmenu__c { display: flex; gap: 3px; }
  .shmenu__c b { width: 14px; height: 14px; border-radius: 2px; cursor: pointer; display: block; }
  .shmenu__c b:hover, .shmenu__c b.on { outline: 1px solid var(--tx); outline-offset: 1px; }
  .shmenu__sep { width: 1px; height: 16px; background: var(--line2); }
  .shmenu button { width: 20px; height: 18px; border: 1px solid var(--line2); background: var(--pane);
    color: var(--tx2); cursor: pointer; font-size: 11px; line-height: 1; padding: 0; }
  .shmenu button:hover { color: var(--tx); border-color: var(--acc); }

  /* Палитра цвета линии — рядом с легендой, без модалок. */
  .cpick { position: absolute; z-index: 40; display: flex; gap: 3px; padding: 5px;
    background: var(--pane2); border: 1px solid var(--line2); }
  .cpick b { width: 16px; height: 16px; border-radius: 2px; cursor: pointer; display: block; }
  .cpick b:hover { outline: 1px solid var(--tx); outline-offset: 1px; }
  .chart__tf { display: flex; gap: 1px; pointer-events: auto; }
  .chart__tf[hidden] { display: none; }
  #view { margin-left: auto; }
  #lay button.on { background: var(--pane2); border-color: var(--acc); color: var(--acc); }
  /* Недоступный слой должен выглядеть недоступным: одного атрибута disabled мало —
     кнопка оставалась подсвеченной и неотличимой от рабочей. */
  #lay button:disabled { opacity: .35; cursor: not-allowed;
    color: var(--tx3) !important; border-color: var(--line2) !important;
    background: none !important; }
  .chart__tf button { height: 20px; padding: 0 9px; border: 1px solid var(--line2);
    background: var(--pane2); color: var(--tx2); font: 600 11px/1 var(--mono); cursor: pointer; }
  .chart__tf button:hover { color: var(--tx); }
  .chart__tf button.on { background: var(--acc); border-color: var(--acc); color: #0f1420; }
  /* Кнопка, которая сейчас ничего не меняет (LOG на процентной шкале): гасим, но не
     прячем — иначе панель прыгает шириной. */
  .chart__tf button.off { opacity: .35; }
  .chart__cv { position: absolute; inset: 28px 0 0 34px; }
  /* Мультиграфик: четыре независимых полотна с общим таймфреймом. Нужен, когда
     сравниваешь корзину — по одному графику это делается перещёлкиванием и памятью. */
  .grid4 { position: absolute; inset: 28px 0 0 34px; z-index: 2; display: grid;
    grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 1px; background: var(--line); }
  .grid4[hidden] { display: none; }
  .g4 { position: relative; background: var(--pane); min-width: 0; min-height: 0; }
  .g4.on { box-shadow: inset 0 0 0 1px var(--acc); }
  .g4__hd { position: absolute; top: 0; left: 0; right: 0; height: 20px; z-index: 2;
    display: flex; align-items: center; gap: 8px; padding: 0 8px; pointer-events: none;
    font: 600 11px/20px var(--mono); color: var(--tx2); }
  .g4__hd b { color: var(--tx); }
  .g4__hd s { text-decoration: none; font-weight: 400; }
  .g4__cv { position: absolute; inset: 20px 0 0; }
  /* Палитра прижата к левому краю графика — там же, где она в проф-терминалах:
     рука идёт к инструменту, не пересекая данные. */
  /* Кнопок в панели тринадцать, а высота графика зависит от того, открыта ли панель
     индикатора и насколько развёрнута нижняя. При низком графике кнопки не помещались
     и вываливались наружу поверх тепловой карты (overflow был visible) — теперь панель
     прокручивается внутри себя. */
  .draw { position: absolute; left: 0; top: 28px; bottom: 0; width: 34px; z-index: 4;
    display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 4px 0;
    background: var(--pane); border-right: 1px solid var(--line);
    overflow-y: auto; overflow-x: hidden; scrollbar-width: none; }
  .draw::-webkit-scrollbar { width: 0; }
  .draw button { width: 26px; height: 26px; display: grid; place-items: center; cursor: pointer;
    border: 1px solid transparent; background: none; color: var(--tx2); padding: 0; }
  .draw button svg { width: 15px; height: 15px; fill: none; stroke: currentColor;
    stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
  .draw button:hover { color: var(--tx); background: var(--pane2); }
  .draw button.on { color: var(--acc); border-color: var(--acc); background: rgba(77,141,255,.10); }
  .draw__sep { width: 18px; height: 1px; background: var(--line2); margin: 4px 0; }
  .draw__n { margin-top: auto; font: 500 10px/1 var(--mono); color: var(--tx3); padding-bottom: 4px; }
  /* Холст построений лежит поверх графика. При курсоре события уходят графику
     (зум и кроссхейр работают), при активном инструменте — перехватываются. */
  /* Профиль объёма лежит между графиком и построениями: он часть картины рынка,
     но рисунки пользователя должны быть выше него. */
  .vp__cv { position: absolute; left: 34px; right: 0; top: 28px; bottom: 0; z-index: 2;
    width: auto; height: auto; pointer-events: none; }
  .draw__cv { position: absolute; left: 34px; right: 0; top: 28px; bottom: 0; z-index: 3;
    width: auto; height: auto; pointer-events: none; }
  .draw__cv.arm { pointer-events: auto; cursor: crosshair; }
  /* Канвы Lightweight Charts внутри #cv имеют свой z-index, поэтому без явного слоя
     сообщения («нет свечей», «премия не считается») оказывались под графиком. */
  .chart__wait { position: absolute; inset: 0; z-index: 4; display: flex; align-items: center;
    justify-content: center; color: var(--tx3); font-size: 11px; pointer-events: none; }
  /* Индикатор — отдельным окном снизу с общей осью времени, как sub-pane в проф-терминалах:
     на одной шкале с ценой RSI 0–100 и рубли несопоставимы. */
  /* На низком экране фиксированные 132 px съедали почти весь график — ограничиваем
     панель долей высоты, чтобы свечи всегда оставались главными. */
  .pane2 { position: absolute; left: 34px; right: 0; bottom: 0; height: min(132px, 38%);
    z-index: 2;
    background: var(--pane); border-top: 1px solid var(--line2); }
  .pane2__hd { display: flex; align-items: center; gap: 8px; height: 18px; padding: 0 8px;
    font: 600 10px/18px var(--sans); letter-spacing: .04em; color: var(--tx3); }
  .pane2__val { font-family: var(--mono); color: var(--tx2); font-weight: 400; }
  .pane2__x { margin-left: auto; cursor: pointer; font-size: 13px; line-height: 1; }
  .pane2__x:hover { color: var(--tx); }
  .pane2__cv { position: absolute; inset: 18px 0 0; }
  /* Основной график ужимается на высоту панели. Холст построений размеры получает
     инлайном из paintDraw (иначе canvas берёт свой внутренний размер), поэтому CSS
     для него здесь не задаём — правило всё равно было бы перебито. */
  .chart.has-pane2 .chart__cv { bottom: min(132px, 38%); }

  /* Рабочая панель снизу: таблицы одного вида под разными табами. */
  .work { background: var(--pane); display: flex; flex-direction: column; min-height: 0; }
  /* Строка табов и кнопка выгрузки — на одной полосе, но кнопка ВНЕ контейнера табов:
     иначе её клик всплывал в обработчик и «CSV» становился активным табом. */
  .work__hd { display: flex; align-items: stretch; height: 28px; flex: none;
    background: var(--pane2); border-bottom: 1px solid var(--line); min-width: 0; }
  .work__tabs { display: flex; align-items: stretch; overflow-x: auto; overflow-y: hidden;
    scrollbar-width: none; min-width: 0; }
  .work__tabs::-webkit-scrollbar { height: 0; }
  /* Полоса не влезает — жмём её и показываем тонкий скроллбар. Класс ставит JS по факту
     переполнения: на 1920 px окно широкое, но колонка узкая, и медиазапрос по ширине
     ЭКРАНА эту ситуацию не ловил — «Алерты» просто уезжали за край. */
  .work__tabs.tight button { padding: 0 5px; font-size: 10.5px; letter-spacing: -.1px; }
  .work__tabs.tight button i { display: none; }
  .work__tabs.tight { scrollbar-width: thin; }
  .work__tabs.tight::-webkit-scrollbar { height: 3px; }
  .work__tabs.tight::-webkit-scrollbar-thumb { background: var(--line2); }
  .work__tabs button { flex: none; }
  /* Отступ ужат с 14 до 10 пикселей: после появления вкладки «Объём» полоса перестала
     влезать в панель, и «Корреляции» с «Лентой» уезжали за край — попасть в них можно
     было только горизонтальной прокруткой, о которой ничто не сообщало. */
  .work__tabs button { border: 0; border-right: 1px solid var(--line); background: none;
    color: var(--tx2); padding: 0 10px; font: 600 12px/1 var(--sans); cursor: pointer; }
  .work__tabs button:hover { color: var(--tx); }
  .work__tabs button.on { background: var(--pane); color: var(--tx); box-shadow: inset 0 -1px 0 var(--acc); }
  /* Мнемокод рядом с названием: пользователь учит команды пассивно, просто глядя на табы. */
  .work__tabs button i { font-style: normal; font-family: var(--mono); font-size: 9px;
    color: var(--tx3); margin-left: 4px; letter-spacing: .04em; }
  .work__tabs button.on i { color: var(--acc); }
  #csv { margin-left: auto; border: 0; border-left: 1px solid var(--line); background: none;
    padding: 0 12px; cursor: pointer; font-family: var(--mono); font-size: 11px; color: var(--tx3); }
  #csv:hover { color: var(--acc); }
  .work__b { flex: 1; overflow: auto; min-height: 0; }
  table.t { width: 100%; border-collapse: separate; border-spacing: 0; }
  table.t th { position: sticky; top: 0; z-index: 2; height: 26px; padding: 0 10px;
    background: var(--pane2); border-bottom: 1px solid var(--line);
    font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
    color: var(--tx3); text-align: left; white-space: nowrap; cursor: pointer; user-select: none; }
  table.t th.r { text-align: right; }
  table.t th:hover { color: var(--tx2); }
  table.t th.srt { color: var(--tx2); }
  table.t th i { font-style: normal; color: var(--acc); }
  table.t td { height: 28px; padding: 0 10px; border-bottom: 1px solid rgba(26,34,48,.8);
    font-size: 13px; white-space: nowrap; }
  table.t td.r { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
  table.t td.s { font-family: var(--mono); font-weight: 600; color: var(--tx); }
  /* Тикер в таблице — ссылка на карточку бумаги; клик по остальной строке оставляет
     тебя в терминале и просто переключает график. Два действия, ни одно не мешает. */
  table.t td.s a.tk { color: var(--tx); text-decoration: none; border-bottom: 1px dotted var(--line2); }
  table.t td.s a.tk:hover { color: var(--acc); border-bottom-color: var(--acc); }
  table.t tbody tr { cursor: pointer; }
  table.t tbody tr:hover { background: var(--acc-soft); }
  table.t tbody tr.on { background: rgba(77,141,255,.18); }
  .muted { color: var(--tx2); }
  .u { font-size: 11px; color: var(--tx3); margin-left: 3px; font-weight: 400; }
  /* Календарь: строка-заголовок дня отделяет группы, ближайшая неделя выделена. */
  /* Шапка портфеля: итог по деньгам всегда перед глазами, а не в конце таблицы. */
  .pf__top { display: flex; align-items: center; gap: 16px; height: 26px; padding: 0 10px;
    position: sticky; top: 0; z-index: 3; background: var(--pane2);
    border-bottom: 1px solid var(--line); font-size: 11px; color: var(--tx3); white-space: nowrap;
    overflow-x: auto; }
  .pf__top b { color: var(--tx); font-family: var(--mono); font-weight: 600; margin-left: 4px; }
  /* На 1366 сводка не влезала в строку и уезжала за край без всякого скролла,
     а до последних вкладок нельзя было домотать: убираем мнемокоды и переносим. */
  @media (max-width: 1450px) {
    .pf__top { height: auto; flex-wrap: wrap; gap: 6px 14px; padding: 4px 10px; }
    /* Вкладок стало одиннадцать (добавился «Объём»), и полоса перестала влезать:
       «Корреляции» с «Лентой» уезжали за край, а о горизонтальной прокрутке
       ничто не сообщало. Жмём отступ и кегль — на 1258 px всё встаёт в строку. */
    .work__tabs button { padding: 0 3px; font-size: 10px; letter-spacing: -.2px; }
    .work__tabs button i { display: none; }
    /* Вкладок стало тринадцать («Фонды» и «Алерты»), и ужатыми они в строку уже не
       встают. Возвращаем тонкую полосу прокрутки: без неё последняя вкладка уезжает
       за край, а о том, что туда можно домотать, ничто не сообщает. */
    .work__tabs { scrollbar-width: thin; }
    .work__tabs::-webkit-scrollbar { height: 3px; }
    .work__tabs::-webkit-scrollbar-thumb { background: var(--line2); }
  }
  .wbar { display: inline-block; width: 34px; height: 4px; background: var(--pane2);
    margin-right: 6px; vertical-align: middle; }
  .wbar i { display: block; height: 100%; background: var(--acc); }

  .cal__bar { display: flex; align-items: center; gap: 1px; height: 24px; padding: 0 6px;
    border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 3; background: var(--pane2); }
  .cal__bar button { height: 18px; padding: 0 9px; border: 1px solid var(--line2);
    background: var(--pane2); color: var(--tx2); font: 600 10px/1 var(--sans); cursor: pointer; }
  .cal__bar button.on { background: var(--acc); border-color: var(--acc); color: #06090f; }
  tr.cal__day td { background: var(--pane2); color: var(--tx2); font-weight: 600; font-size: 11px;
    text-transform: capitalize; height: 22px; }
  tr.cal__day.soon td { color: var(--acc); }
  tr.cal__day i { font-style: normal; color: var(--tx3); font-weight: 400;
    text-transform: none; margin-left: 6px; font-size: 10px; }

  /* Тепловая карта: плитки во всю ширину панели, горизонт переключается сверху. */
  /* overflow: hidden — страховка от того же дрожания: даже если канва окажется на
     доли пикселя больше контейнера, полосы прокрутки у .work__b не появится, и
     обратной связи «полоса -> ResizeObserver -> перерисовка» не возникнет. */
  .hm { position: relative; width: 100%; height: 100%; overflow: hidden; }
  .hm__bar { display: flex; align-items: center; gap: 1px; height: 24px; padding: 0 6px;
    border-bottom: 1px solid var(--line); }
  .hm__bar button { height: 18px; padding: 0 9px; border: 1px solid var(--line2);
    background: var(--pane2); color: var(--tx2); font: 600 10px/1 var(--mono); cursor: pointer; }
  .hm__bar button.on { background: var(--acc); border-color: var(--acc); color: #06090f; }
  .hm__hint { margin-left: 10px; font-size: 11px; color: var(--tx3); }
  #hmCv { display: block; cursor: pointer; }

  .bar { position: relative; display: block; height: 4px; background: var(--pane2); min-width: 60px; }
  .bar i { position: absolute; top: 0; bottom: 0; }

  /* ── Правая колонка: карточка инструмента ──────────────────────────────── */
  .side { grid-area: side; overflow-y: auto; }
  .side__sec { border-bottom: 1px solid var(--line); }
  /* Панель тащится за заголовок: он не несёт действий (кнопки и ссылки живут в теле),
     поэтому курсор-хват на нём не спорит с кликом. */
  .side__sec > .ph { cursor: grab; }
  .side__sec > .ph:active { cursor: grabbing; }
  .side__sec.drag { opacity: .45; }
  /* Пока тянем — подсвечиваем границы панелей, иначе непонятно, куда встанет блок. */
  .side.dragging .side__sec { outline: 1px dashed var(--line2); outline-offset: -1px; }
  /* Панель, открытая командой (FA, RV, CRV, SET): короткая подсветка, чтобы взгляд
     нашёл блок. Прокрутки мало - если панель уже была на экране, ничего не меняется
     и непонятно, сработала ли команда. Гаснет сама за 1,4 с. */
  .side__sec.flash { animation: sideFlash 1.4s ease-out; }
  /* Заливка заметно плотнее обычного acc-soft (0.12): на почти чёрной панели
     подсветка должна читаться боковым зрением, иначе смысла в ней нет. */
  @keyframes sideFlash {
    0%   { background: rgba(77,141,255,.18); box-shadow: inset 3px 0 0 var(--acc); }
    70%  { background: rgba(77,141,255,.18); box-shadow: inset 3px 0 0 var(--acc); }
    100% { background: transparent; box-shadow: inset 3px 0 0 transparent; }
  }
  /* Кому анимация мешает - показываем ту же подсветку статично и коротко. */
  @media (prefers-reduced-motion: reduce) {
    .side__sec.flash { animation: none; background: rgba(77,141,255,.18);
      box-shadow: inset 3px 0 0 var(--acc); }
  }
  .kv { display: grid; grid-template-columns: minmax(96px, auto) minmax(0, 1fr);
    gap: 3px 10px; padding: 7px 9px; }
  /* Подпись сжимается многоточием, значение остаётся целым: перенос по буквам давал
     «Капита/лизаци/я» на узкой колонке. */
  .kv dt { color: var(--tx2); font-size: 12px; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .kv dd { min-width: 0; }
  .kv dd { margin: 0; font-family: var(--mono); font-size: 12px; color: var(--tx);
    text-align: right; font-variant-numeric: tabular-nums;
    overflow: hidden; text-overflow: ellipsis; }
  /* Дневной и годовой диапазон: положение цены важнее самих границ. */
  .rng { padding: 8px 9px; }
  .rng__t { display: flex; justify-content: space-between; font: 500 10px/1 var(--mono); color: var(--tx3); }
  .rng__b { position: relative; height: 4px; margin: 6px 0 4px; background: var(--pane2); }
  .rng__b i { position: absolute; top: -2px; width: 2px; height: 8px; background: var(--acc); }
  .rng__l { display: flex; justify-content: space-between; font-size: 10px; color: var(--tx3); }
  .prf { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: var(--line); }
  .prf div { background: var(--pane); padding: 6px 4px; text-align: center; }
  .prf span { display: block; font-size: 11px; color: var(--tx3); margin-bottom: 3px; }
  .prf b { font: 600 12px/1 var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .prf u { display: block; margin-top: 3px; text-decoration: none; font: 500 11px/1 var(--mono);
    font-variant-numeric: tabular-nums; white-space: nowrap; opacity: .85; }
  .prf-note { padding: 4px 10px 7px; font-size: 10px; color: var(--tx3); }
  .prf div { min-width: 0; }
  /* В узкой ячейке «+12,3 %» разрывался между числом и знаком — держим одной строкой. */
  .kv dd, .lvl b, .rsi__l, table.t td.r { white-space: nowrap; }
  /* Сигналы ТА: строка = что смотрим · вердикт. Цвет несёт направление, не украшение. */
  .sig { display: grid; grid-template-columns: 74px 1fr; gap: 4px 8px; padding: 7px 9px; }
  .sig dt { color: var(--tx2); font-size: 12px; }
  .sig dd { margin: 0; font-size: 12px; font-weight: 600; }
  .sig dd small { display: block; font-weight: 400; color: var(--tx3); font-size: 10px;
    margin-top: 2px; line-height: 1.35; }
  .lvls { padding: 0 9px 8px; }
  .lvl { display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
    padding: 4px 0; border-top: 1px solid rgba(26,34,48,.9); font-size: 12px; }
  .lvl b { font-family: var(--mono); font-variant-numeric: tabular-nums; }
  .lvl span { color: var(--tx3); font-size: 10px; }
  .rsi { padding: 7px 9px; }
  .rsi__b { position: relative; height: 4px; background: var(--pane2); margin: 5px 0 4px; }
  .rsi__b i { position: absolute; top: -2px; width: 2px; height: 8px; background: var(--acc); }
  .rsi__b u { position: absolute; top: 0; bottom: 0; background: rgba(139,152,174,.25); }
  .rsi__l { display: flex; justify-content: space-between; font-size: 10px; color: var(--tx3);
    font-family: var(--mono); }

  .al { display: flex; align-items: baseline; gap: 8px; padding: 5px 10px;
    border-bottom: 1px solid rgba(26,34,48,.8); font-size: 12px; }
  .al b { font-family: var(--mono); font-variant-numeric: tabular-nums; }
  .al span { color: var(--tx3); font-size: 11px; }
  .al i { margin-left: auto; font-style: normal; color: var(--tx3); cursor: pointer; }
  .al i:hover { color: var(--dn); }
  /* Сообщение о срабатывании — поверх графика, коротко и без модалок. */
  .al-note { position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%); z-index: 150;
    padding: 7px 14px; background: var(--acc); color: #06090f; font: 600 12px/1 var(--sans);
    border-radius: 3px; }
  .al-note[hidden] { display: none; }

  /* Переключатель внутри шапки панели: две узкие кнопки, как у наборов скринера,
     но мельче — шапка тут высотой в строку. */
  .ph__sw { display: inline-flex; gap: 1px; margin-left: 6px; }
  .ph__sw button { padding: 1px 6px; border: 1px solid var(--line2); background: var(--pane2);
    color: var(--tx3); font: 500 10px/1.5 var(--sans); text-transform: none;
    letter-spacing: 0; cursor: pointer; }
  .ph__sw button.on { background: var(--acc); border-color: var(--acc); color: #06090f; }
  /* Тикер в ленте новостей: кликается отдельно от строки — строка открывает саму
     новость, а этот чип ведёт к бумаге. */
  .tkchip { display: inline-block; padding: 0 5px; border: 1px solid var(--line2);
    background: var(--pane2); color: var(--acc); font: 600 11px/1.6 var(--mono);
    cursor: pointer; }
  .tkchip:hover { border-color: var(--acc); background: var(--acc-soft); }
  .nws { padding: 2px 0; }
  /* Строка ленты — не ссылка: на оригинал новости терминал не уводит.
     Селектор держим общим для старой разметки и новой. */
  .nws a, .nws__i { display: block; padding: 7px 10px; border-bottom: 1px solid rgba(26,34,48,.8);
    color: var(--tx); text-decoration: none; font-size: 12px; line-height: 1.4; }
  .nws a:hover { background: var(--acc-soft); }
  .nws time { display: block; font: 500 10px/1 var(--mono); color: var(--tx3); margin-bottom: 3px; }
  .empty { padding: 11px 10px; color: var(--tx3); font-size: 12px; }

  /* Шпаргалка поверх всего: терминал не уводит с рабочего места ради справки. */
  .hk { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center;
    background: rgba(5,7,13,.72); }
  .hk[hidden] { display: none; }
  /* Список горячих клавиш длиннее экрана: даём ему прокручиваться внутри окна,
     иначе последние строки просто исчезают за нижним краем. */
  .hk__box { width: min(760px, 92vw); max-height: 88vh; display: flex; flex-direction: column;
    background: var(--pane); border: 1px solid var(--line2); }
  .hk__body { overflow-y: auto; min-height: 0; }
  .hk__hd { display: flex; align-items: center; height: 30px; padding: 0 12px;
    border-bottom: 1px solid var(--line); background: var(--pane2);
    font: 600 12px/30px var(--sans); letter-spacing: .04em; color: var(--tx2); }
  .hk__x { margin-left: auto; cursor: pointer; font-size: 16px; }
  .hk__x:hover { color: var(--tx); }
  .hk__cols { column-count: 3; column-gap: 18px; padding: 12px; }
  .hk__g { break-inside: avoid; margin-bottom: 14px; }
  .hk__g h4 { margin: 0 0 6px; font: 600 10px/1 var(--sans); letter-spacing: .08em;
    text-transform: uppercase; color: var(--tx3, #63718a); }
  .hk__cols dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 6px 10px;
    align-content: start; }
  .hk__cols dt { font: 600 11px/1.5 var(--mono); color: var(--acc); white-space: nowrap; }
  .hk__cols dd { margin: 0; font-size: 12px; color: var(--tx2); }
  @media (max-width: 1100px) { .hk__cols { column-count: 2; } }
  @media (max-width: 760px) { .hk__cols { column-count: 1; } }

  /* Узкие экраны: правая колонка и watchlist ужимаются, ниже 1100px — вертикально. */
  @media (max-width: 2100px) {
    /* Сокращаем подписи кнопок заранее, а не когда ряд уже не влез. */
    .chart__tf button { padding: 0 6px; }
    #lay button[data-lay="vol"], #lay button[data-lay="lvl"] { font-size: 0; }
    #lay button[data-lay="vol"]::after { content: 'ОБ'; font-size: 11px; }
    #lay button[data-lay="lvl"]::after { content: 'УР'; font-size: 11px; }
    #lay button[data-lay="wknd"] { font-size: 0; }
    #lay button[data-lay="wknd"]::after { content: 'ВЫХ'; font-size: 11px; }
    #view button[data-view="bench"] { font-size: 0; }
    #view button[data-view="bench"]::after { content: 'IDX'; font-size: 11px; }
  }
  @media (max-width: 1500px) {
    .trm { grid-template-columns: 224px minmax(0, 1fr) 264px; }
    /* На узком экране прячем ещё и охват ряда — данные важнее служебной строки. */
    .chart__span { display: none; }
  }
  @media (max-width: 1100px) {
    body:has(.trm) { overflow: auto; }
    .trm { position: static; height: auto; grid-template-columns: 1fr;
      grid-template-areas: "cmd" "tape" "main" "wl" "side"; }
    .main { grid-template-rows: 40px 420px 240px; }
    .wl, .side { height: 420px; }
  }

/* Подсказка по сделке сетапа: на графике видно ЧТО произошло, а в ней — почему так
   посчитано (когда вошли, когда и по какой причине вышли, сколько получилось). */
.settip { position: absolute; z-index: 6; pointer-events: none; max-width: 280px;
  background: rgba(10,14,22,.97); border: 1px solid var(--line2); padding: 9px 11px;
  font-size: 11px; line-height: 1.55; color: var(--tx2);
  box-shadow: 0 6px 20px rgba(0,0,0,.45); }
.settip b { color: var(--tx); font-weight: 600; }
.settip .h { display: flex; align-items: center; gap: 6px; margin-bottom: 4px;
  font-size: 11px; color: var(--tx); }
.settip i { font-style: normal; font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: .3px; padding: 3px 5px; color: #0a0e16; }
.settip i.l { background: var(--up); }
.settip i.s { background: var(--dn); }
.settip .h { font-size: 12px; font-weight: 600; }
.settip .r { font-family: var(--mono); font-weight: 600; }
.settip .r.up { color: var(--up); } .settip .r.dn { color: var(--dn); }

/* Дефолт в списке выпусков: без метки цена в 3% номинала читается как «очень дёшево». */
.bdef { font-family: var(--mono); font-size: 8px; font-weight: 700; letter-spacing: .3px;
  color: #0a0e16; background: var(--dn); padding: 1px 3px; vertical-align: middle; }

/* Переключатель срезов панели соседних выпусков: похожие чужие или свои эмитента. */
.bpv { display: flex; gap: 1px; padding: 4px 9px 6px; }
.bpv button { border: 1px solid var(--line2); background: var(--pane2); color: var(--tx2);
  font: 600 10px/1 var(--sans); padding: 4px 8px; cursor: pointer; }
.bpv button.on { color: var(--bg); background: var(--acc); border-color: var(--acc); }

/* Кнопка «сравнить» в строке соседа-фонда: маленький «+» у тикера, «×» когда фонд
   уже на графике. Отдельный элемент, а не вся строка: клик по строке открывает фонд. */
.peer__cmp { display: inline-block; margin-left: 5px; width: 12px; height: 12px;
  line-height: 12px; text-align: center; color: var(--tx3); cursor: pointer;
  border: 1px solid var(--line2); font-style: normal; font-size: 10px; }
.peer__cmp:hover { color: var(--acc); border-color: var(--acc); }
.peer__cmp.on { color: var(--bg); background: var(--acc); border-color: var(--acc); }

/* Календарь бумаги: строка события — дата, суть, пояснение. Прогнозная дата и прошедшее
   событие приглушены: подтверждённая отсечка и ожидание аналитика не равны по весу. */
.evt { display: grid; grid-template-columns: 62px 1fr; gap: 0 8px; padding: 4px 9px;
  border-bottom: 1px solid var(--line); font-size: 11px; }
.evt b { color: var(--tx); font-family: var(--mono); font-weight: 600; }
.evt span { color: var(--tx2); }
.evt span b { font-family: var(--sans); }
.evt i { grid-column: 2; color: var(--tx3); font-style: normal; font-size: 10px; }
.evt--fc b { color: var(--tx2); }
.evt--past { opacity: .6; }
.evt--sub { padding-top: 2px; padding-bottom: 5px; border-bottom: 0; }
.evt--sub b, .evt--sub span { color: var(--tx3); }

/* Структура портфеля: две полосы (классы активов и отрасли внутри акций) и строка
   перекосов. Полоса читается быстрее пятнадцати строк таблицы: доли видно целиком. */
.pfstr { display: flex; flex-wrap: wrap; gap: 6px 22px; padding: 5px 10px 7px;
  border-bottom: 1px solid var(--line); background: var(--pane); }
/* Кнопка-заголовок блока: сворачивает структуру, когда нужна сама таблица позиций. */
.pfstr__t { flex: 1 1 100%; text-align: left; border: 0; background: none; cursor: pointer;
  color: var(--tx3); font: 600 10px/1.4 var(--sans); letter-spacing: .06em;
  text-transform: uppercase; padding: 0; }
.pfstr__t:hover { color: var(--acc); }
.pfstr--off { padding-bottom: 5px; }
.pfstr__c { flex: 1 1 320px; min-width: 0; }
.pfstr__h { color: var(--tx3); font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
  margin-bottom: 5px; }
.pfstr__h .n { text-transform: none; letter-spacing: 0; color: var(--tx3); opacity: .7; }
/* Факторный профиль облигационной части во вкладке портфеля */
.pfpr__r { display: grid; grid-template-columns: 104px 1fr 46px; align-items: center;
  gap: 6px; font-size: 10px; color: var(--tx3); margin-bottom: 3px; }
.pfpr__r i { display: block; height: 5px; border-radius: 3px; background: var(--pane2);
  overflow: hidden; }
.pfpr__r i b { display: block; height: 100%; background: #5f8ed0; }
.pfpr__r u { text-decoration: none; text-align: right; font-family: var(--mono);
  color: var(--tx2); }
.pfpr__r u em { font-style: normal; color: var(--tx3); opacity: .75; margin-left: 3px;
  font-size: 9px; }
.pfbar { display: flex; height: 8px; background: var(--pane2); overflow: hidden; }
.pfbar i { display: block; height: 100%; }
.pfleg { display: flex; flex-wrap: wrap; gap: 2px 12px; margin-top: 6px;
  color: var(--tx2); font-size: 11px; }
.pfleg span { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.pfleg b { width: 7px; height: 7px; display: inline-block; }
.pfstr__note { flex: 1 1 100%; color: var(--tx3); font-size: 11px; line-height: 1.5; }

/* Кривая стратегии в строке таблицы: узкая ячейка, координаты приходят с сервера
   на холсте 240x46 и растягиваются по ширине (preserveAspectRatio=none). */
.strspk { width: 64px; height: 15px; display: block; }

/* Действие в строке сводки алертов: убрать уровень или взвести его заново. Кнопка
   живёт в таблице, поэтому выглядит как ссылка, а не как элемент управления формой. */
.alrb { color: var(--tx3); cursor: pointer; font: 500 11px/1 var(--sans); }
.alrb:hover { color: var(--acc); }

/* Хвост длинного списка выпусков: честно говорим, сколько показано и что делать. */
.wl__more { padding: 8px 10px; font-size: 10px; line-height: 1.5; color: var(--tx3);
  border-top: 1px solid var(--line); }

/* Список сделок выбранного сетапа: дата, результат, срок. Клик — перемотка графика. */
.settr { padding: 2px 9px 6px; }
.settr__h { font-size: 10px; color: var(--tx3); margin: 4px 0 3px; }
.settr__r { display: grid; grid-template-columns: 1fr auto auto; gap: 8px; align-items: center;
  padding: 3px 5px; cursor: pointer; font-family: var(--mono); font-size: 10px;
  border: 1px solid transparent; }
.settr__r:hover { border-color: var(--line2); background: var(--pane2); }
.settr__r s { text-decoration: none; color: var(--tx2); }
.settr__r i { font-style: normal; font-weight: 600; }
.settr__r i.up { color: var(--up); } .settr__r i.dn { color: var(--dn); }
.settr__r i.op { color: var(--acc); }
.settr__r u { text-decoration: none; color: var(--tx3); min-width: 34px; text-align: right; }

/* Суммарный результат сделок в заголовке блока сетапов. */
.ph .n b { font-weight: 700; }
.ph .n b.up { color: var(--up); } .ph .n b.dn { color: var(--dn); }
