/* ══════════════════════════════════════════════════════════════════════════════════════════════
   Оформление по КУПЛЕННОМУ МАКЕТУ (trd.ic). Значения не подобраны на глаз — вынуты из .fig:
   переменные Figma с режимами Dark/Light, геометрия компонентов (кнопка 32px с padding 4/12 и
   radius 8, элемент рейла 36×36, карточка radius 12 с обводкой, шапка таблицы 45px), шкалы
   отступов 4-32 и радиусов 4-24.

   Тёмная и светлая равноправны: по умолчанию системная, тумблер её перекрывает.
   ══════════════════════════════════════════════════════════════════════════════════════════ */

@font-face {
	font-family: Inter;
	src: url("/fonts/inter-cyrillic-ext.woff2") format("woff2");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
	font-family: Inter;
	src: url("/fonts/inter-cyrillic.woff2") format("woff2");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}

@font-face {
	font-family: Inter;
	src: url("/fonts/inter-latin.woff2") format("woff2");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: Inter;
	src: url("/fonts/InterVariable.woff2") format("woff2");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Inter Fallback";
	src: local(Arial);
	ascent-override: 90.44%;
	descent-override: 22.52%;
	line-gap-override: 0.0%;
	size-adjust: 107.12%;
}

:root {
	/* ── Base: набор «Tokens», режим Dark ── */
	--base-1: #0b0b0c;   /* фон страницы */
	--base-2: #121214;   /* панель, карточка */
	--base-3: #1b1b1e;   /* граница карточки, приподнятая поверхность */
	--base-4: #2a2a2e;   /* разделитель */
	--text-1: #fafafa;
	--text-2: #b0b0ba;
	--text-3: #71717b; /* Bloom faint */
	--surface-alt: #101012; /* вторичная кнопка/поле из макета */
	/* ⛔ ПОВЕРХНОСТЬ ОРГАНА УПРАВЛЕНИЯ — замер из макета, а не подбор на глаз: там кнопка это
	   ЗАЛИВКА Base 3 (#1b1b1e) на Base 1 (#0b0b0c) и НИ ОДНОЙ ОБВОДКИ (92 кнопки из 92).
	   Наши кнопки лежат не на фоне страницы, а на панели Base 2, поэтому берётся тот же ШАГ
	   (+16 по каналу), то есть Base 4. Рамки нет: именно она и делала кнопку кричащей. */
	--ctl: #1b1b1e;
	--ctl-edge: transparent;
	--ctl-hover: #2a2a2e;
	--hover: #ffffff0d;

	/* ── Семантика рынка: из заливок макета (в переменные автор их не выносил) ── */
	/* «Рост» — травяной зелёный макета (#22fa5f, 27 заливок) вместо мятного неона #15ffab (999).
	   Неон верен ПЯТНОМ — на графиках и в плашках, где автор его и льёт; у нас же он почти всегда
	   ТЕКСТ (Landed, +8.1%, тикеры), а мелким текстом на чёрном он режет глаз. */
	--up: #7cffc0;
	--up-soft: #aeffd4;
	--up-bg: #0a281a;
	--up-bg-dim: #002c1a;
	--down: #ff9fbe;
	--down-soft: #ff9fbe;
	--down-bg: #42001f;
	--accent: #e4e4e7;   /* основной акцент макета */
	/* «Выстрелили, цепь ещё не ответила» — оранжевый макета (#f97822, 24 заливки). Отдельный цвет,
	   потому что это отдельное состояние: не рутина ворот, не ожидание на паузе и не исход. */
	--fired: #f9bb29;
	--fired-bg: #2d1301;
	--info: #52a3ff;
	--warn: #f9bb29;     /* Sunglow/500 */
	--lime: #aeffd4;

	/* ── Шкалы ── */
	/* ПОДСВЕТКА ОДНОГО АДРЕСА по всей странице (см. `addrhl.js`): само упоминание ярче, его строка —
	   едва заметно. Оба через акцент: это не тревога и не исход, а «вот он же». */
	--hot-bg: color-mix(in srgb, var(--accent) 34%, transparent);
	--hot-row: color-mix(in srgb, var(--accent) 9%, transparent);
	--r4: 4px; --r8: 8px; --r12: 12px; --r16: 16px; --r24: 24px; --pill: 360px;
	--s4: 4px; --s8: 8px; --s12: 12px; --s16: 16px; --s20: 20px; --s24: 24px; --s32: 32px;
	--topbar: 64px;

	color-scheme: dark;
}

/* ── Светлая тема: те же токены, режим Light ── */
:root[data-theme="light"] {
	--base-1: #ffffff;
	--base-2: #f8f7f7;
	--base-3: #e8e8e8;
	--base-4: #d9d9d9;
	--text-1: #1b1b1e;
	--text-2: #767678;
	--surface-alt: #f1f1f1;
	/* на белом заливка без края теряется, поэтому в светлой теме край есть — но тихий */
	--ctl: #ececec; --ctl-edge: #dedede; --ctl-hover: #e3e3e3;
	--hover: #0000000a;
	/* неон макета на белом нечитаем — берём те же тона, притемнённые до контраста */
	--up: #04aa33; --up-soft: #05d13f; --up-bg: #d9f7e0; --up-bg-dim: #eefaf1;
	--down: #de2323; --down-soft: #f23633; --down-bg: #fdeaea;
	--accent: #5b49d6; --info: #1657d8; --warn: #a97a06; --lime: #7f9a13;
	--fired: #b34a05; --fired-bg: #feeadc;
	color-scheme: light;
}
/* системная тема, пока оператор не выбрал вручную */
@media (prefers-color-scheme: light) {
	:root:not([data-theme="dark"]):not([data-theme="light"]) {
		--base-1: #ffffff; --base-2: #f8f7f7; --base-3: #e8e8e8; --base-4: #d9d9d9;
		--text-1: #1b1b1e; --text-2: #767678; --surface-alt: #f1f1f1; --hover: #0000000a;
		/* на белом заливка без края теряется, поэтому в светлой теме край есть — но тихий */
		--ctl: #ececec; --ctl-edge: #dedede; --ctl-hover: #e3e3e3;
		--up: #04aa33; --up-soft: #05d13f; --up-bg: #d9f7e0; --up-bg-dim: #eefaf1;
		--down: #de2323; --down-soft: #f23633; --down-bg: #fdeaea;
		--accent: #5b49d6; --info: #1657d8; --warn: #a97a06; --lime: #7f9a13;
		--fired: #b34a05; --fired-bg: #feeadc;
		color-scheme: light;
	}
}

* { box-sizing: border-box; margin: 0; scrollbar-width: thin; scrollbar-color: var(--base-4) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--base-4); border-radius: var(--r8); }
html, body, #root { height: 100%; }
body {
	background: var(--base-1); color: var(--text-1);
	font: 400 14px/1.45 Inter, "Inter Fallback", ui-sans-serif, system-ui, sans-serif;
	/* цифры столбиком — иначе таблица «дышит» на каждом апдейте состояния */
	font-variant-numeric: tabular-nums;
	-webkit-font-smoothing: antialiased;
}
#root { display: flex; flex-direction: column; }

.ok { color: var(--up); } .bad { color: var(--down); } .warn { color: var(--warn); } .dim { color: var(--text-2); }
.spacer { flex: 1; }

/* ── шапка: 64px, нижняя граница ── */
header {
	display: flex; align-items: center; gap: var(--s16);
	height: var(--topbar); padding: 0 var(--s20);
	background: var(--base-1); border-bottom: 1px solid var(--base-2); flex: 0 0 auto;
}
h1 { font-size: 15px; font-weight: 600; display: flex; align-items: center; gap: var(--s8); letter-spacing: -0.01em; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--down); display: inline-block; }
.dot.on { background: var(--up); }
.chip {
	display: inline-flex; align-items: center; gap: 6px;
	padding: 5px 12px; border: 1px solid var(--base-3); border-radius: var(--pill);
	color: var(--text-2); font-size: 12px; font-weight: 500; white-space: nowrap;
}
.chip b { color: var(--text-1); font-weight: 600; }
.chip.bad { color: var(--down); border-color: var(--down); }

/* Quiet meta + parser capacity meters in topbar */
.hdr-meta {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	color: var(--text-3);
	font-size: 12px;
	font-weight: 500;
	white-space: nowrap;
}
.hdr-meta b {
	color: var(--text-1);
	font-weight: 650;
	font-variant-numeric: tabular-nums;
	margin-left: 4px;
}
.hdr-parsers {
	display: inline-flex;
	align-items: stretch;
	gap: 8px;
	padding: 4px;
	border-radius: 10px;
	background: var(--base-2);
}
.hdr-parser {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-width: 118px;
	padding: 6px 10px;
	border-radius: 8px;
	background: var(--base-1);
}
.hdr-parser.off {
	opacity: 0.55;
}
.hdr-parser-body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
	flex: 1;
}
.hdr-parser-row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 10px;
}
.hdr-parser-row em {
	font-style: normal;
	font-size: 11px;
	font-weight: 600;
	color: var(--text-2);
	letter-spacing: 0.01em;
}
.hdr-parser-row b {
	font-size: 12px;
	font-weight: 700;
	color: var(--text-1);
	font-variant-numeric: tabular-nums;
}
.hdr-parser-row b i {
	font-style: normal;
	font-weight: 500;
	color: var(--text-3);
}
.hdr-parser-bar {
	display: block;
	height: 3px;
	border-radius: 999px;
	background: var(--base-3);
	overflow: hidden;
}
.hdr-parser-bar i {
	display: block;
	height: 100%;
	border-radius: inherit;
	background: color-mix(in srgb, var(--up) 75%, #fff 8%);
}
.hdr-parser.hot .hdr-parser-bar i {
	background: color-mix(in srgb, var(--warn) 80%, #fff 10%);
}
.hdr-parser.off .hdr-parser-bar i {
	background: var(--down);
}
.hdr-parser .lamp {
	width: 7px;
	height: 7px;
	flex: 0 0 auto;
}

/* ── переключатель процессов: пилюли ── */
.switcher { display: flex; gap: var(--s4); flex-wrap: wrap; }
.ptab {
	display: inline-flex; align-items: center; gap: var(--s8);
	background: transparent; border: 1px solid var(--base-3); border-radius: var(--pill);
	padding: 5px 14px; color: var(--text-2); font: inherit; font-size: 12px; font-weight: 500; cursor: pointer;
	transition: background .12s, color .12s, border-color .12s;
}
.ptab:hover { color: var(--text-1); background: var(--hover); }
.ptab.on { background: var(--base-2); color: var(--text-1); border-color: var(--base-3); }
.pbadge { background: var(--down); color: #fff; border-radius: var(--pill); padding: 0 6px; font-size: 10px; font-weight: 700; }
.lamp { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--text-2); }
.lamp.ok { background: var(--up); } .lamp.bad { background: var(--down); } .lamp.warn { background: var(--warn); } .lamp.dim { background: var(--text-2); }

/* ── полоса здоровья ── */
.alarmbar {
	display: flex; align-items: center; gap: var(--s8);
	padding: 7px var(--s20); font-size: 12px; font-weight: 500; cursor: pointer;
	border-bottom: 1px solid var(--base-2); flex: 0 0 auto;
}
.alarmbar.ok { color: var(--up-soft); background: color-mix(in srgb, var(--up-bg) 55%, var(--base-1)); }
.alarmbar.bad { color: var(--down); background: var(--down-bg); font-weight: 600; }
.alarmbar:hover { filter: brightness(1.12); }
/* ⚠ СЛЕД ОТ СПРЯТАННОЙ ТРЕВОГИ: тихая строчка вместо кричащей полосы. Совсем без следа экран врал бы
   («всё хорошо»), а в прежнем цвете прятать было бы незачем. */
.alarmbar.hushed { color: var(--text-2); background: var(--base-2); font-weight: 500; }
.alarmhush {
	flex: none; margin-left: var(--s12); width: 20px; height: 20px; padding: 0; border: none;
	border-radius: var(--r4); background: transparent; color: inherit; opacity: .65; cursor: pointer; font-size: 13px;
}
.alarmhush:hover { opacity: 1; background: #0002; }
.alarmdetail { padding: var(--s12) var(--s20) var(--s4); border-bottom: 1px solid var(--base-2); display: flex; flex-direction: column; gap: var(--s8); }

/* ── вкладки ── */
.tabs { display: flex; gap: var(--s4); align-items: center; padding: 0 var(--s20); background: var(--base-1); border-bottom: 1px solid var(--base-2); flex: 0 0 auto; }
.tab {
	background: transparent; border: none; border-bottom: 2px solid transparent;
	padding: 11px var(--s16); color: var(--text-2); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
}
.tab:hover { color: var(--text-1); }
.tab.on { color: var(--text-1); border-bottom-color: var(--accent); font-weight: 600; }

main { flex: 1; overflow: auto; min-height: 0; padding: var(--s16) var(--s20) var(--s24); }
main.stale { opacity: .6; filter: saturate(.65); }
.control, .settings { display: flex; flex-direction: column; gap: var(--s12); }

/* ── карточки и панели: radius 12, обводка base-3 ── */
.panel { border: 1px solid var(--base-3); border-radius: var(--r12); padding: var(--s12) var(--s16); background: var(--base-2); }
.paneltitle { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); margin-bottom: var(--s8); font-weight: 600; }
.okpanel { color: var(--up); border-color: color-mix(in srgb, var(--up) 30%, var(--base-3)); background: var(--up-bg-dim); }
.degpanel { border-color: var(--down); background: var(--down-bg); }
.blocked { border-color: var(--down); background: var(--down-bg); }
.degrow { display: flex; gap: var(--s12); align-items: baseline; padding: 3px 0; font-size: 13px; }
.degid { font-weight: 600; min-width: 190px; }
.degdetail { flex: 1; }
.kv { display: grid; grid-template-columns: auto 1fr auto 1fr; gap: 3px var(--s12); font-size: 13px; align-items: baseline; }
.kv .k { color: var(--text-2); } .kv .v { font-weight: 600; }
.note { color: var(--text-2); font-size: 12px; margin-top: 6px; }
/* ⛔ ЦВЕТ ПОЯСНЕНИЯ ЗАБИРАЛСЯ САМИМ `.note`. Специфичность у него та же, что у `.bad`/`.warn`, а
   правило стоит ниже — и «counters are stale, do not read them as the current picture» на экране
   горячего было того же тихого серого, что и любая справка. Тревога, выглядящая как справка, — это
   не тревога. */
.note.ok { color: var(--up); }
.note.warn { color: var(--warn); }
.note.bad { color: var(--down); }
.empty { color: var(--text-2); padding: var(--s12) 2px; }
.empty.big { padding: 56px 2px; font-size: 15px; text-align: center; }
.dhead { display: flex; align-items: center; gap: var(--s12); padding-bottom: var(--s12); border-bottom: 1px solid var(--base-3); flex-wrap: wrap; }
.dhead b { font-size: 15px; }

/* ── кнопки: 32px, radius 8, обводка base-3 (замер из макета) ── */
/* ⛔⛔ ОРГАН УПРАВЛЕНИЯ НИКОГДА НЕ СТАВИТСЯ НА ФОН, ОТЛИЧАЮЩИЙСЯ НА ПАРУ ПРОЦЕНТОВ.
   Кнопки стояли на `--surface-alt` (#141417) поверх панели `--base-2` (#161618): разница в две
   единицы яркости, да ещё и В МИНУС — кнопка темнее того, на чём лежит. Глаз такую границу не
   берёт и достраивает её сам, отчего к концу смены болят глаза, а кнопку ищут курсором.
   Правило: поверхность кнопки — ступень ВВЕРХ от своего фона (`--base-4`), плюс видимая рамка.
   Это касается любого нажимаемого: кнопок, выбранных сегментов, полей ввода. */
.btn {
	display: inline-flex; align-items: center; gap: var(--s4); justify-content: center;
	height: 32px; padding: 4px 12px;
	background: var(--ctl); color: var(--text-1);
	border: 1px solid var(--ctl-edge); border-radius: var(--r8);
	font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
	transition: border-color .12s, background .12s;
}
.btn:hover:not(:disabled) {
	background: var(--ctl-hover);
	border-color: var(--ctl-edge);
	box-shadow: none;
	outline: none;
}
.btn:focus,
.btn:focus-visible {
	outline: none;
	box-shadow: none;
	border-color: var(--ctl-edge);
}
.btn:disabled { opacity: .4; cursor: default; }
.btn.on {
	color: var(--text-1);
	background: var(--ctl-hover);
	border-color: var(--ctl-edge);
}
.btn.small { height: 24px; padding: 2px 10px; font-size: 11px; font-weight: 500; }
.btn.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, var(--base-3)); }
.btn.warn:hover:not(:disabled) { border-color: var(--warn); }
.btn.danger {
	color: color-mix(in srgb, var(--down) 78%, var(--text));
	background: var(--ctl);
	border-color: var(--line);
	font-weight: 600;
}
/* «Пуск» — единственная кнопка, которую ищут в спешке, поэтому она заливкой: пока торговля стоит,
   это ровно то действие, ради которого оператор смотрит на экран. */
.btn.go { color: #0b0b0c; background: var(--accent); border-color: var(--accent); font-weight: 700; }
.btn.go:hover:not(:disabled) { filter: brightness(1.1); background: var(--accent); }
.btn.danger:hover:not(:disabled) {
	filter: none;
	background: color-mix(in srgb, var(--down) 10%, var(--ctl));
	border-color: color-mix(in srgb, var(--down) 45%, var(--line));
	color: var(--down);
}

.cmdwrap { display: flex; flex-direction: column; gap: var(--s16); }
.cmdgroup { border: 1px solid var(--base-3); border-radius: var(--r12); padding: var(--s12) var(--s16); background: var(--base-2); }
.cmdhead { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); margin-bottom: var(--s12); font-weight: 600; }
.cmdrow { display: flex; flex-wrap: wrap; gap: var(--s8); }
.cmdlegend { margin-top: var(--s12); font-size: 12px; color: var(--text-2); display: flex; flex-direction: column; gap: 3px; }
.cmdlegend b { color: var(--text-1); font-weight: 600; }
/* ── инвентарь супервизора ──
   ⛔ БЫЛА ТАБЛИЦА ИЗ ШЕСТИ КОЛОНОК — и кнопки уезжали за край панели, стоило статусу стать длиннее
   «online». Теперь строка в два яруса: имя тянется и обрезается многоточием, кнопки не сжимаются,
   числа ушли вниз. Ширину панели тут не увеличить: она задана ящиком настроек. */
.invrow { padding: 7px 0; border-bottom: 1px solid var(--base-3); }
.invrow:last-of-type { border-bottom: none; }
.invtop { display: flex; align-items: center; gap: var(--s8); font-size: 12px; }
/* Имя — единственное, что можно ужать: остальное либо не сжимается, либо теряет смысл. */
.invname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.invstat { white-space: nowrap; }
.invtop .btn.small { flex: 0 0 auto; }
.invsub { font-size: 11px; margin-top: 3px; }

/* ── поля ──
   ⛔ КОНТУРА НЕТ — в макете у поля ни одного strokePaint. Рамка была моей отсебятиной, и на списке
   из тринадцати ручек она давала частокол одинаковых прямоугольников, между которыми глаз не
   цепляется ни за что.
   ⚠ Заливку макета (Base 3) тоже не берём: там поле стоит одиночным элементом на Base 1, а у нас их
   тринадцать подряд на панели, и тринадцать залитых плашек — тот же частокол, только мягче. Поле =
   ЗНАЧЕНИЕ + тонкая линия под ним; линия разгорается акцентом на фокусе, а строка целиком светлеет.
   Так на экране остаётся ровно одна яркая деталь — та, которую правят. */
input, select {
	background: transparent; color: var(--text-1);
	border: none; border-radius: 0;
	box-shadow: none;
	padding: 6px 2px; font: inherit; font-size: 13px; height: 32px;
	transition: background .12s, border-color .12s;
}
input:hover:not(:disabled), select:hover:not(:disabled) {
	background: transparent;
	box-shadow: none;
	outline: none;
}
input:focus, select:focus {
	outline: none;
	background: transparent;
	box-shadow: none;
}
/* ⛔ У ВЫПАДАЮЩЕГО СПИСКА ФОН БЕРЁТСЯ С САМОГО ПОЛЯ, а не со страницы. Наши поля прозрачные (по
   макету у них только линия снизу), и браузер читал прозрачность как БЕЛЫЙ: в тёмной теме список
   открывался белым по белому — выбрать можно было только вслепую.
   Поэтому у `select` фон непрозрачный. Выглядит он так же, как раньше: это цвет той самой панели,
   на которой поле и лежит, — а список наследует его и становится тёмным. */
select { background-color: var(--base-2); }
select:hover:not(:disabled) { background-color: var(--base-2); }
select:focus { background-color: var(--base-2); }
/* Сами пункты подписываем отдельно: часть браузеров не наследует цвет от поля. */
select option { background-color: var(--base-2); color: var(--text-1); }
input[type=checkbox] { width: 18px; height: 18px; accent-color: var(--accent); box-shadow: none; background: none; }
input.wide { width: 280px; }
::placeholder { color: var(--text-2); }

/* ── ростер прямо из ленты: запретить создателя и выпустить обратно ────────────────────────
   ⚠ МЕСТО ПОД ЗНАЧОК ДЕРЖИТСЯ ВСЕГДА. Появляться он может по наведению, но НЕ раздвигать строку:
   адрес, прыгающий под курсором, промахивается мимо ссылки. */
.creator { display: inline-flex; align-items: center; gap: 6px; }
.roster {
	flex: none; display: inline-flex; align-items: center; justify-content: center;
	width: 20px; height: 20px; padding: 0; border: none; border-radius: var(--r4);
	background: transparent; cursor: pointer; visibility: hidden; color: var(--text-2);
}
/* Показываем по наведению на СТРОКУ и по фокусу — иначе с клавиатуры до значка не добраться. */
.lrow:hover .roster, .roster:focus-visible { visibility: visible; }
/* Запрет — красный: это он останавливает будущие покупки. Снятие — тихое, зеленеет под курсором. */
.roster.ban { color: var(--down); }
/* ⚠ Подсветка «под курсором» — только у ДЕЙСТВИЯ. Секунда подтверждения не нажимается, и подложка
   под ней превращала галку в залитый значок — то есть в другое состояние. */
.roster.ban:not(.flash):hover { background: color-mix(in srgb, var(--down) 18%, transparent); }
.roster.clear:not(.flash):hover { color: var(--up); background: color-mix(in srgb, var(--up) 16%, transparent); }
/* ⚠ ЩИТ «ВЫПУСТИТЬ» — ТОЖЕ ПО НАВЕДЕНИЮ (24.08). Он висел всегда, пока был единственным способом
   сказать «этот в списке». Теперь это говорит САМ АДРЕС — серым, — и постоянный значок остался
   просто шумом в каждой такой строке. Действия показываются одинаково: наведением на строку.
   Без наведения видны только НЕ-действия: секунда подтверждения и метка «список чужой». */
.roster.static, .roster.flash { visibility: visible; }
.roster.static { cursor: default; opacity: .55; }
.roster.flash { cursor: default; }
.roster.flash.ban { color: var(--down); }
.roster.flash.clear { color: var(--up); }
/* ⛔ АДРЕС В ЧЁРНОМ СПИСКЕ — СЕРЫЙ, а не цвета ссылки: цвет ссылки зовёт нажать, а этого создателя
   уже отсеяли, и читать про него больше нечего. Ссылкой он остаётся — в обозреватель по нему ходят
   как раз тогда, когда разбираются, за что запретили. */
.launches .creator.denied a { color: var(--text-2); }

/* ── запрет ТИКЕРА: на месте значка площадки (07.09) ──────────────────────────────────────────
   ⚠ ОДНО МЕСТО, ДВА ЖИЛЬЦА. В покое стоит значок площадки, по наведению на строку он подменяется
   действием — ровно в тех же 16 пикселях, чтобы тикер не прыгал под курсором. Оба лежат в одной
   ячейке грида: строка не меняет ширину от того, есть ли команда у процесса. */
.padban { display: inline-grid; grid-template-areas: "slot"; width: 16px; height: 16px; margin-right: 6px; vertical-align: -3px; }
.padban > * { grid-area: slot; }
.padban .lpico { margin-right: 0; vertical-align: baseline; }
.tban {
	display: none; align-items: center; justify-content: center;
	width: 16px; height: 16px; padding: 0; border: none; border-radius: var(--r4);
	background: var(--base-2); cursor: pointer; color: var(--text-2);
}
/* Показываем по наведению на СТРОКУ и по фокусу — иначе с клавиатуры до значка не добраться. */
.lrow:hover .tban, .tban:focus-visible { display: inline-flex; }
.lrow:hover .tban ~ .lpico, .lrow:hover .padban:has(.tban) .lpico { visibility: hidden; }
/* Запрет — красный: это он останавливает будущие покупки. Снятие — тихое, зеленеет под курсором. */
.tban.ban { color: var(--down); }
.tban.ban:not(.flash):hover { background: color-mix(in srgb, var(--down) 18%, transparent); }
.tban.clear:not(.flash):hover { color: var(--up); background: color-mix(in srgb, var(--up) 16%, transparent); }
/* Секунда подтверждения не нажимается и видна БЕЗ наведения: она про случившееся, а не про состояние. */
.tban.flash { display: inline-flex; cursor: default; background: transparent; }
.tban.flash.ban { color: var(--down); }
.tban.flash.clear { color: var(--up); }
.padban:has(.tban.flash) .lpico { visibility: hidden; }
/* ⛔ ЗАПРЕЩЁННЫЙ ТИКЕР — СЕРЫЙ, ровно как запрещённый создатель: имя ещё читается (по нему и
   разбираются, за что закрыли), но цвет ссылки больше не зовёт нажать. */
.launches td.tickerbanned a, .launches td.tickerbanned b, .launches td.tickerbanned .noaddr { color: var(--text-2); }

/* ── лицо проекта: значки записи и аккаунта, карточка по наведению, счётчики ворот ──────────
   ⚠ КАРТОЧКА ЖИВАЯ: по ней водят мышью и жмут ссылку, поэтому она НЕ `pointer-events: none`,
   в отличие от подсказки. Живёт в портале с `position: fixed` — строка обрезает переполнение. */
/* Якорь карточки тоже обычный инлайн: он стоит в одном ряду с марками сетей. */
.hcanchor { display: inline; }
/* ⚠ ЗНАЧКИ ССЫЛОК — ОДНИ НА ОБА ЭКРАНА (08.09): в ленте и в позициях это один и тот же орган.
   Тихий цвет: ссылки есть почти у каждого токена, и цветными они забили бы строку.

   ⛔ КОНТЕЙНЕР НЕ БЛОК. Был `inline-flex` со сдвигом вниз — и в ленте, где вокруг обычный текст,
   значки садились НИЖЕ строки: у флекс-коробки своя базовая линия, и она не совпадает с текстовой.
   Теперь марки сетей — обычный текст на той же базовой линии, а картинкам даётся свой сдвиг. */
.socs { display: inline; margin-left: 4px; }
/* марки сетей — текстом, поэтому им нужен свой размер; значки макета уже 13px */
.soc { display: inline; color: var(--text-2); font-size: 12px; }
.soc + .soc, .socs > .hcanchor + .soc, .soc + .hcanchor { margin-left: 4px; }
.soc svg { vertical-align: -2px; }
.soc:hover { color: var(--accent); }
.socmark { margin-left: 5px; }
/* Марка сети в ссылке: текстовая, поэтому наследует цвет и не тянет картинок (см. NET в trading.jsx). */
.socglyph { font-size: 13px; line-height: 1; }
.socmark .socx { vertical-align: -2px; }
/* ── ЦВЕТ ССЫЛКИ = СОСТОЯНИЕ ЛИЦА ПРОЕКТА (08.09). Три цвета, три разных ответа: красный — потеря,
   янтарь — закрытый аккаунт, приглушённый — «мы не знаем». ⛔ Третий не красить первым: «не
   прочитали» это про нас, а не про проект. */
/* ⛔ КЛАССЫ НАЗВАНЫ ЦВЕТОМ, А НЕ СМЫСЛОМ (08.09): у красного теперь два повода — «снесено» и
   «запись старше часа», — и класс со смыслом в имени врал бы на половине строк. Что значит цвет
   в конкретном случае, сказано словами в карточке. */
.soc.red, .soc.red .socx, .soc.red .socglyph { color: var(--down); }
.soc.amber, .soc.amber .socx, .soc.amber .socglyph { color: var(--warn); }
.soc.muted { opacity: .42; }
/* Легенда цвета в карточке: та же тройка словами, чтобы её не приходилось помнить. */
.hctone { font-size: 11.5px; line-height: 1.35; }
.hctone.red { color: var(--down); }
.hctone.amber { color: var(--warn); }
.hctone.muted { color: var(--text-2); }
/* ⚠ ЗАПИСЬ — СВОЕЙ КОРОБКОЙ, КАК ЦИТАТА У X (решение оператора 08.09). Тонкой черты не хватало:
   описание аккаунта и текст поста шли одним столбцом и читались как один абзац одного автора.
   Коробка отвечает на вопрос без слов — вот это написано, а вот это про того, кто написал. */
.hcpost {
	margin-top: 2px; padding: 10px; display: flex; flex-direction: column; gap: 8px;
	border: 1px solid var(--base-3); border-radius: var(--r12); background: var(--base-1);
}
.hctext.dim { color: var(--text-2); }
.hclinks { display: flex; gap: 14px; }
.hcard {
	position: fixed; z-index: 220; width: 320px; max-width: calc(100vw - 16px);
	background: var(--base-2); border: 1px solid var(--ctl-edge, var(--base-4)); border-radius: var(--r12);
	box-shadow: 0 12px 32px #0009; overflow: hidden;
	animation: tipin .09s ease-out;
}
.hccard { display: flex; flex-direction: column; }
/* Баннер во всю ширину карточки — как у самого X. Высота фиксированная: у баннеров разные пропорции,
   и карточка не должна прыгать по высоте от того, чей это аккаунт. */
.hcbanner { width: 100%; height: 78px; object-fit: cover; display: block; }
.hcbody { padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
.hchead { display: flex; align-items: flex-start; gap: 10px; }
.hcava { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; flex: none; background: var(--base-3); }
/* ⚠ Аватар наезжает на баннер, если баннер есть: так это и читается у X, и вертикали экономит.
   ⚠ Наезжает НЕМНОГО (решение оператора 08.09): задранный под самый баннер, он отрывался от имени,
   которое стоит рядом, и читался как часть картинки, а не как лицо аккаунта. */
.hcbanner + .hcbody .hcava { margin-top: -16px; border: 2px solid var(--base-2); }
/* Вложения: до четырёх в ряд, одинаковой высоты. Обложка видео — та же картинка, поэтому один тег. */
.hcmedia { display: grid; gap: 4px; grid-template-columns: repeat(2, 1fr); }
.hcmedia.n1 { grid-template-columns: 1fr; }
.hcmedia.n3 .hcshot:first-child, .hcmedia.n1 .hcshot { grid-column: span 2; }
.hcshot { position: relative; display: block; overflow: hidden; border-radius: var(--r8); background: var(--base-3); }
.hcimg { display: block; width: 100%; height: 96px; object-fit: cover; }
.hcmedia.n1 .hcimg { height: 150px; }
/* Ролик тут НЕ ИГРАЕТ и не притворяется: метка говорит, что это ролик и какой длины. */
.hcplay {
	position: absolute; left: 6px; bottom: 6px; padding: 1px 6px; border-radius: var(--r4);
	background: #000a; color: #fff; font-size: 10.5px; font-weight: 700; letter-spacing: .02em;
}
.hcname { display: flex; align-items: center; gap: 5px; font-size: 14px; font-weight: 700; color: var(--text-1); }
.hcver { color: var(--info); } .hclock { color: var(--text-2); }
.hchandle { font-size: 12px; color: var(--text-2); }
/* ⚠ Текст записи может быть любой длины и на любом языке: рвём по словам и держим потолок высоты,
   иначе один пост на десять абзацев закрывает собой экран. */
.hctext { font-size: 12.5px; line-height: 1.4; color: var(--text-1); white-space: pre-wrap; overflow-wrap: anywhere; max-height: 190px; overflow: hidden; }
.hcstats { display: flex; flex-wrap: wrap; gap: 12px; font-size: 12px; color: var(--text-2); }
.hcstat b { color: var(--text-1); font-weight: 700; }
.hcnote { font-size: 11.5px; color: var(--text-2); }
.hcnote.bad { color: var(--warn); font-weight: 600; }
.hcgone { color: var(--down); font-weight: 600; font-size: 12px; }
/* ⚠ «Не прочитали» и «закрытый» — НЕ ТРЕВОГА: это про нас и про настройки аккаунта, а не про то,
   что проект исчез. Поэтому тихий цвет, а красный остаётся за настоящей пропажей. */
.hcstate { color: var(--text-2); font-weight: 600; font-size: 12px; }
/* Возраст записи стоит среди счётчиков — той же мерой, но без слова: «5m» и так читается временем. */
.hcage { color: var(--text-2); }
.hclink { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 600; }
/* ⚠ СЧЁТЧИКИ ВОРОТ — СВОЕЙ ПЛАШКОЙ (08.09). В той же строке живут адрес и возраст, а это говорит
   ЦЕПЬ; здесь же — что знает про проект чужой сервис. Слитые в одну серую строку, они читались как
   продолжение адреса. Подложка отделяет их, не крича: цвет тот же, что у полей ввода. */
/* Ворота ответили, но сказать им нечего («не знаем такого» / «не дошли») — плашка та же, но тихая. */
.gates.quiet { background: transparent; }
.gates {
	/* ⛔ НЕ СЖИМАЕТСЯ: в верхней строке рядом стоит тикер, и место уступает он (у него многоточие),
	   а не числа — сплющенная плашка с обрезанным числом хуже короткого тикера. */
	flex: none;
	display: inline-flex; align-items: center; gap: 10px;
	padding: 2px 8px; border-radius: 999px;
	background: var(--base-2); border: 1px solid var(--base-3);
}
/* Число — ярко, значок — тихо: смотрят на число, значок только называет, какое оно. */
.gate { display: inline-flex; align-items: center; gap: 4px; color: var(--text-1); font-size: 11px; font-weight: 700; cursor: default; }
.gate svg { vertical-align: -2px; color: var(--text-2); }
/* Ноль — ответ, а не пустота: показываем, но тише прочего. */
.gate.zero { color: var(--text-2); font-weight: 500; opacity: .7; }

/* ГДЕ СОВПАЛО у строки из поиска: тихая подпись, как и всё справочное в строке. */
.launches .matched {
	margin-left: 6px; padding: 1px 6px; border-radius: 999px;
	background: var(--base-2); border: 1px solid var(--base-3);
	color: var(--text-2); font-size: 10px; white-space: nowrap; cursor: default;
}
/* Переключатель области поиска стоит рядом с полем и повторяет вид сегментов ленты. */
.segfilters.scopes { margin-left: var(--s8); flex: 0 0 auto; }
.segfilters.scopes .seg { padding: 3px 10px; font-size: 11.5px; }

/* ── настройки ── */
.toolbar { display: flex; align-items: center; gap: var(--s12); }
.ownerbox { border: 1px solid var(--base-3); border-radius: var(--r12); background: var(--base-2); overflow: hidden; }
.ownerhead { display: flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 700; padding: 10px var(--s16); border-bottom: 1px solid var(--base-3); color: var(--accent); letter-spacing: .01em; }
/* сырой скоуп — не подпись, а адрес записи: держим рядом, но мелким и тихим */
.ownerkey { font-weight: 500; font-size: 11px; color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.groupbox { padding: var(--s8) var(--s16) var(--s12); }
.grouphead { font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-2); margin: 6px 0; font-weight: 600; }
/* ⛔ КОЛОНКА ПОЛЕЙ — ФИКСИРОВАННОЙ ШИРИНЫ. Раньше она была `auto`, и ширина поля зависела от типа
   ручки, а кнопка «сброс» появлялась не у всех — правый край гулял от строки к строке, и список
   читался как мусор. Теперь все поля начинаются и кончаются на одной вертикали, а место под кнопку
   сброса зарезервировано ВСЕГДА. */
.knob { display: grid; grid-template-columns: 230px 1fr 264px; gap: var(--s12); align-items: center; padding: 4px 6px; border-radius: var(--r8); border-bottom: 1px solid color-mix(in srgb, var(--base-4) 55%, transparent); }
.knob:last-child { border-bottom: none; }
/* строка под курсором и строка с фокусом в поле — светлее: видно, что именно ты сейчас правишь */
.knob:hover { background: var(--hover); }
.knob:focus-within { background: color-mix(in srgb, var(--accent) 9%, transparent); }
.knob.pend { background: color-mix(in srgb, var(--warn) 12%, transparent); }
.knob.rejected { background: color-mix(in srgb, var(--down) 12%, transparent); }
.kname { font-weight: 600; cursor: help; display: flex; align-items: center; gap: 6px; font-size: 13px; }
.kdoc { color: var(--text-2); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kctl { display: flex; align-items: center; gap: 6px; }
.kctl input, .kctl select { flex: 1 1 auto; min-width: 0; width: 100%; }
/* ⚠ ПОЛЕ И ЕГО ЕДИНИЦА ВЫРОВНЕНЫ ПО БАЗОВОЙ ЛИНИИ, а не по серединам. Середины у них совпадали и
   без этого, но подпись мельче поля, и её базовая линия висела на 1 px выше числа — «25» и «%»
   стояли на разной высоте. Базовая линия держит любой кегль, поправка «на глаз» — нет. */
.kfield { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 6px; }
/* Галочка — к правому краю, как и числа: колонка значений одна, и рвать её нельзя. Выравнивание
   по базовой линии на неё не распространяется — у флажка её нет, ставим по середине поля. */
.kctl input[type=checkbox] { flex: 0 0 auto; width: 18px; margin-left: auto; align-self: center; }
/* Единица — тихой подписью справа от поля. Место под неё держится у всех строк, даже безымянных. */
/* ⚠ ЧИСЛО ПРИЖАТО ВПРАВО, к своей единице. Слева оно от неё отрывалось на всю ширину поля, и «25»
   с «%» читались как две разные вещи. Заодно колонка чисел выравнивается по разряду. */
.kctl input[type=number] { text-align: right; appearance: textfield; }
.kctl input[type=number]::-webkit-outer-spin-button,
.kctl input[type=number]::-webkit-inner-spin-button { appearance: none; margin: 0; }
/* Единица — тихой подписью справа от поля. Место под неё держится у всех строк, даже безымянных. */
/* ⛔ МЕСТО ПОД ЕДИНИЦУ — ФИКСИРОВАННОЕ, и шире, чем «%». Единицу теперь присылает процесс, и слова
   у неё длинные («records», «children», тикер монеты): на прежних 36px такая подпись раздвигала
   слот, поле уезжало влево на 12px, и столбец чисел ломался об одну строку. */
.kctl .kunit { flex: 0 0 56px; font-size: 11.5px; color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* место под «сброс» держится всегда — иначе поля соседних строк разной длины */
.kctl .rst { flex: 0 0 28px; width: 28px; padding: 0; }
.kctl .rst.ghost { visibility: hidden; }
.badge { font-size: 9.5px; padding: 1px 6px; border-radius: var(--pill); background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); font-weight: 600; }
.badge.warn { background: color-mix(in srgb, var(--warn) 20%, transparent); color: var(--warn); }
/* Метка-беда: режим блоков кошелька не тот, что нужен роли, — это промах мимо блока каждый раз. */
.badge.bad { background: color-mix(in srgb, var(--down) 20%, transparent); color: var(--down); }
/* Значок раздела настроек, присланный процессом: маска красится цветом текста, поэтому один и тот
   же файл живёт в обеих темах и не спорит с подписью. */
.gico { display: inline-block; flex: none; background: currentColor; vertical-align: -2px;
	mask-repeat: no-repeat; mask-position: center; mask-size: contain;
	-webkit-mask-repeat: no-repeat; -webkit-mask-position: center; -webkit-mask-size: contain; }

/* ── НАСТРОЙКИ: рубрикатор слева, один раздел справа ──────────────────────────────────────────
   Ручек больше полусотни. Одним списком в столбик они не читаются: оператор ищет ОДИН раздел, а
   не пролистывает всё подряд. Разделы — те же группы, что объявил процесс. */
.setshell { display: flex; gap: var(--s12); align-items: flex-start; }
.setrail {
	flex: 0 0 236px; align-self: stretch; display: flex; flex-direction: column; gap: var(--s12);
	border: 1px solid var(--base-3); border-radius: var(--r12); background: var(--base-2); padding: var(--s12);
}
.setrail input[type=search] { width: 100%; }
.setnav { display: flex; flex-direction: column; gap: 2px; }
.setnavhead {
	display: flex; align-items: center; gap: 6px; padding: var(--s12) 6px 4px;
	font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-2); font-weight: 600;
}
.setnavhead:first-child { padding-top: 0; }
.setnavitem {
	display: flex; align-items: center; gap: var(--s8); padding: 6px 8px; border-radius: var(--r8);
	font-size: 13px; color: var(--text-1); cursor: pointer;
}
.setnavitem:hover { background: var(--hover); }
.setnavitem.on { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent); }
/* Выключенный модуль и раздел без совпадений — тише, но НЕ спрятаны: спрятанное ищут руками. */
.setnavitem.off .lbl, .setnavitem.miss { color: var(--text-2); }
/* Значок раздела — тише подписи: он метка, а не сообщение. У выбранного берёт его цвет. */
.setico { flex: none; color: var(--text-2); }
.setnavitem.on .setico { color: inherit; }
.sethead > .setico { color: var(--accent); margin-top: 3px; }
.grouphead .setico { vertical-align: -2px; margin-right: 5px; }
.setnavitem .lbl { flex: 1; text-transform: capitalize; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.setnavitem .num b { color: var(--accent); font-weight: 600; }
.setnavitem .num { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--text-2); }
.setonlymod {
	margin-top: auto; padding-top: var(--s8); border-top: 1px solid var(--base-3);
	display: flex; align-items: center; gap: var(--s8); font-size: 12px; color: var(--text-2); cursor: pointer;
}
.setonlymod input { width: 15px; height: 15px; }

.setmain { flex: 1; min-width: 0; border: 1px solid var(--base-3); border-radius: var(--r12); background: var(--base-2); overflow: hidden; }
/* ── ГЛУБИНА КАК НА TRADING: страница base-1 → карточки base-2 → органы ctl (ступень вверх = то, что
   нажимается). Раньше вся вкладка лежала в ОДНОЙ панели base-2, и в ней рубрикатор, фильтры падов
   (сами base-2) и карточка ручек сливались в одну плоскость. Теперь шапка с названием, фильтрами и
   «✓ Apply» стоит прямо на странице, как «Launches», а рубрикатор и ручки — две карточки под ней. */
.settings { display: flex; flex-direction: column; gap: var(--s16); }
.setblock .blockhead { flex-wrap: wrap; }
.setblock .blockhead > .dim { font-size: 12px; }
.setblock .blockhead .warn { font-size: 12px; }
/* поиск по разделам — в той же оправе, что поиск по ленте: пилюля с иконкой, без подчёркивания */
.setsearch { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px; background: var(--ctl); border-radius: var(--r8); color: var(--text-2); }
.setsearch input, .setsearch input:hover, .setsearch input:focus { flex: 1; height: 28px; border: none; background: transparent; box-shadow: none; padding: 0; font-size: 13px; min-width: 0; }
.setsearch:focus-within { box-shadow: 0 0 0 1px var(--accent); }
/* поле ручки — коробка цвета органа, а не линия на плоскости: значение видно как то, что можно взять */
.kctl input:not([type=checkbox]), .kctl select, .kctl textarea {
	height: 30px; padding: 0 10px; border-radius: var(--r8); box-shadow: none;
	background: var(--ctl); border: 1px solid var(--ctl-edge); font-size: 12.5px;
}
.kctl select { background-color: var(--ctl); }
.kctl input:hover:not(:disabled):not([type=checkbox]), .kctl select:hover:not(:disabled), .kctl textarea:hover { background: var(--ctl-hover); box-shadow: none; }
.kctl input:focus:not([type=checkbox]), .kctl select:focus, .kctl textarea:focus { background: var(--ctl); box-shadow: 0 0 0 1px var(--accent); border-color: var(--accent); }
.kctl input[type=number] { padding-right: 8px; }
.sethead { display: flex; align-items: flex-start; gap: var(--s12); padding: var(--s12) var(--s16); border-bottom: 1px solid var(--base-3); }
.seth1 { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--s8); flex-wrap: wrap; }
.seth1 > b { font-size: 15px; font-weight: 700; text-transform: capitalize; }
.sethscope { font-size: 12px; color: var(--text-2); }
.sethdesc { flex: 1 1 100%; font-size: 12px; color: var(--text-2); line-height: 1.5; text-wrap: pretty; }
.sethhint { font-size: 12px; color: var(--text-2); white-space: nowrap; }
.pill {
	display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border-radius: var(--pill);
	font-size: 11px; font-weight: 600; background: var(--ctl); color: var(--text-2);
}
.pill i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.pill.good { color: var(--up-soft); background: var(--up-bg); border: none; }
.pill.warn { color: var(--warn); background: color-mix(in srgb, var(--warn) 16%, transparent); }
.pill.bad { color: var(--down); background: color-mix(in srgb, var(--down) 14%, transparent); }
.pill.dim { color: var(--text-2); background: var(--ctl); }
/* «Модуль выключен» — не ошибка и не тревога: значения целы, ими просто никто не пользуется. */
.setoff { padding: 8px var(--s16); border-bottom: 1px solid var(--base-3); font-size: 12px; color: var(--text-2); background: var(--base-1); }
.setbody { padding: var(--s8) var(--s16) var(--s12); }
.setbody.dim { opacity: .45; }
.setbody.dim .knob { pointer-events: none; }
.setgroup + .setgroup { margin-top: var(--s12); }

/* Рубильник: два состояния, видно издалека. */
.swtch {
	position: relative; flex: none; width: 28px; height: 16px; padding: 0; border: none;
	border-radius: var(--pill); background: var(--base-4); cursor: pointer; transition: background .12s;
}
.swtch i { position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: var(--text-2); transition: left .12s, background .12s; }
.swtch.on { background: var(--accent); }
.swtch.on i { left: 14px; background: #fff; }
.swtch.big { width: 38px; height: 22px; }
.swtch.big i { width: 18px; height: 18px; }
.swtch.big.on i { left: 18px; }
/* Тронутый, но не сохранённый рубильник — той же тревожной каймой, что и строка-черновик: на
   экране одно правило, «жёлтое значит ещё не записано». */
.swtch.pend { box-shadow: 0 0 0 2px color-mix(in srgb, var(--warn) 60%, transparent); }

.tablewrap { overflow: auto; border: 1px solid var(--base-3); border-radius: var(--r12); }
.tablewrap table { border-collapse: collapse; width: 100%; font-size: 12px; }
.tablewrap th { text-align: left; color: var(--text-2); font-weight: 500; background: var(--base-2); position: sticky; top: 0; padding: 8px 12px; border-bottom: 1px solid var(--base-3); }
.tablewrap td { padding: 7px 12px; border-bottom: 1px solid var(--base-3); white-space: nowrap; }

/* ══════════════ ТОРГОВЫЕ СТРОКИ ══════════════
   Скелет из макета: карточка radius 12 с обводкой base-3, ряды с разделителем, колонки
   «капшн над значением», крупный PnL как главное число строки. */
.striplist { border: 1px solid var(--base-3); border-radius: var(--r12); background: var(--base-2); overflow: hidden; min-width: 1224px; }
.strip { border-bottom: 1px solid var(--base-3); }
.strip:last-child { border-bottom: none; }
.strip .striprow { display: flex; align-items: center; gap: var(--s16); padding: var(--s12) var(--s16); }
.strip:hover { background: var(--hover); }
/* Строка доживает пять секунд после закрытия сделки — приглушённая, чтобы её не спутали с открытой. */
.strip.closing { opacity: .55; }
.strip.hasdet .striprow { cursor: pointer; }
.strip a { text-decoration: none; }
/* ⚠ Подчёркивание в таблице — шум: ссылок в строке несколько, и каждая тянет на себя внимание
   линией, которая ничего не сообщает. Ссылку выдаёт цвет и курсор, а подчёркивание появляется под
   курсором — там, где оно и нужно. */
/* Метка охоты: строка взята по вайтлисту, мимо ворот. Тихая, но своя — рядом со значком пада. */
/* Дев-бай и бандл — две доли саплая в одной колонке. Значок различает их без подписей. */
.devbuy { display: inline-flex; align-items: center; gap: 10px; }
.devbuy .dpart { display: inline-flex; align-items: center; gap: 3px; cursor: help; }
.devbuy .dpart svg { opacity: .65; }
/* Числа причины: слово отвечает «что», числа — «насколько». Мельче и тише слова. */
.verdict .rnums { font-size: 10px; font-weight: 500; opacity: .8; margin-left: 5px; }
/* Необычность лаунча значком: налог мимо деплоера, выкуп холдерам. ⚠ Рамки у них нет нарочно —
   значок стоит вплотную к имени токена, и обведённый в пилюлю он спорил бы с ним за внимание. */
.launches .lmark { display: inline-flex; align-items: center; color: var(--warn);
	margin-left: 5px; vertical-align: -2px; cursor: help; }
.launches .lmark svg { opacity: .8; }
.launches .hunt { font-size: 9.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
	color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
	border-radius: var(--pill); padding: 0 5px; margin-right: 5px; vertical-align: 1px; }
/* Период, за который посчитаны сегменты исхода: число без периода не значит ничего, а место в ряду
   стоит трёх символов. ⚠ Меняется на `loaded`, когда счёт идёт по загруженному, — смена смысла видна. */
.segnote { font-size: 10px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-2);
	align-self: center; margin: 0 2px 0 -2px; cursor: help; }
/* ── ЛЕНТА, УДЕРЖАННАЯ НА МЕСТЕ: счётчик пришедшего сверху ──
   Липнет к кромке ПРОКРУТЧИКА (`main`), а не таблицы: у `.tablewrap` свой overflow, и всё липкое
   внутри него липло бы к нему — то есть никуда. Высоты у полосы нет — она не двигает таблицу. */
.feedwrap { position: relative; }
/* ⚠ `top` — минус отступ прокрутчика: липкое считается от КОНТЕНТНОЙ кромки `main`, а его верхний
   отступ (`--s16`) — та полоса, сквозь которую строки видны выше «нуля». Без поправки свечение
   висело на полряда ниже кромки, и первая видимая строка оставалась неподсвеченной. */
.feednew { position: sticky; top: calc(0px - var(--s16)); height: 0; z-index: 5; pointer-events: none; }
/* свечение по кромке: «сверху что-то накопилось» видно и боковым зрением, без чтения */
.feednew::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 34px;
	background: linear-gradient(color-mix(in srgb, var(--accent) 28%, transparent), transparent); }
.feedpill { pointer-events: auto; position: absolute; top: 7px; left: 50%; transform: translateX(-50%);
	font: inherit; font-size: 11.5px; font-weight: 600; letter-spacing: .02em; cursor: pointer;
	color: #fff; background: var(--accent); border: 0; border-radius: var(--pill); padding: 4px 12px;
	box-shadow: 0 4px 16px color-mix(in srgb, var(--accent) 45%, transparent); }
.feedpill:hover { filter: brightness(1.08); }
/* Значок продавца рядом с итогом: тише числа, но читаемый — он отвечает на «кем», а не «сколько». */
.sellby { vertical-align: -1px; opacity: .75; }
.launches a { text-decoration: none; }
.launches a:hover { text-decoration: underline; }
/* Тикер без ссылки: у токена ЕЩЁ НЕТ адреса (лаунч виден из мемпула). Пунктир говорит, что ссылки
   тут не забыли, а её пока не из чего строить — как монограмма у пада без значка. */
.launches .noaddr { border-bottom: 1px dotted var(--text-2); cursor: help; }

/* та же беда, что была у колонок: ширина висела на строке и в шапку не попадала */
/* ⚠ ШИРЕ С 07.09: под адресом теперь ещё и три счётчика ворот (заметные читатели, упомянутые
   контракты, переименования). В прежних 236 пикселях адрес разрывался посередине на две строки. */
.strip .idc, .striphead .idc { flex: 0 0 318px; width: 318px; display: flex; align-items: center; gap: var(--s12); min-width: 0; }
.strip .avaw { position: relative; flex: 0 0 40px; width: 40px; height: 40px; }
.strip .avaw .avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; display: block; background: var(--base-3); }
.strip .avaw .avatar.loading { animation: pulse 1.1s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }
.strip .avaw .avatar.broken { display: flex; align-items: center; justify-content: center; font-size: 16px; color: var(--text-2); border: 1px dashed var(--down); }
.strip .avaw .avatar.padicon { padding: 8px; background: var(--base-3); }
.strip .avaw .lpbadge { position: absolute; left: -2px; bottom: -2px; width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--base-2); background: var(--base-2); }
.strip .idt { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.strip .nm { display: flex; align-items: center; gap: 6px; min-width: 0; }
.strip .nm .nmlink { color: var(--text-1); font-weight: 600; font-size: 16px; letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.strip .nm .nmlink:hover { color: var(--accent); }
.strip .tmk { flex: 0 0 auto; cursor: help; }

.strip .idsub { display: flex; align-items: center; gap: var(--s8); font-size: 11px; min-width: 0; white-space: nowrap; overflow: hidden; }
/* ⛔ Адрес НЕ РВЁТСЯ: разорванный посередине токен нечитаем и выглядит как поломка вёрстки. */
.strip .taddr { color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; }
.strip .taddr:hover { color: var(--accent); }
.strip .age { color: var(--text-2); }

/* ⛔ ШИРИНЫ ЗАДАЮТСЯ КОЛОНКЕ, А НЕ СТРОКЕ. Раньше они висели на `.strip .col…`, то есть в шапку
   таблицы не попадали вовсе: подписи вставали по содержимому и оказывались где угодно, только не над
   своими столбцами. Шапка и строка обязаны мериться ОДНИМИ правилами. */
.strip .cols, .striphead .cols { flex: 0 0 auto; display: flex; align-items: center; gap: var(--s20); }
.strip .col, .striphead .col { display: flex; flex-direction: column; gap: 3px; min-width: 0; overflow: hidden; }
/* ⚠ ШИРЕ, ЧЕМ ЧИСЛО ВХОДА: под ним стоит «сколько имеем» (06.09), а это снайперские суммы в
   пятнадцать знаков — в прежних 96 пикселях подпись обрезалась многоточием прямо на деньгах. */
.col.c-in { flex: 0 0 128px; width: 128px; }
/* ⚠ Ширина под СНАЙПЕРСКИЕ суммы: «-0.00000004988 (-0.5%) ✓» — двадцать четыре знака со значком
   закрытой сделки, и обрезать их нельзя: это деньги. */
.col.c-pnl { flex: 0 0 252px; width: 252px; }
.col.c-st { flex: 0 0 190px; width: 190px; }
.col.c-pad { flex: 0 0 118px; width: 118px; }
.col.c-fund { flex: 0 0 182px; width: 182px; margin-left: auto; }
.strip .cap { font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-2); font-weight: 600; white-space: nowrap; }
.strip .val { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.strip .col.c-pnl .val { font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
.strip .col.c-pnl .val .pnl-na { font-size: 13px; font-weight: 500; }
.strip .col.c-st .val { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: 12.5px; }
.strip .colsub { font-size: 10.5px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.pnl-pos { color: var(--up); } .pnl-neg { color: var(--down); } .pnl-na { color: var(--text-2); }
.st-hold { color: var(--up); } .st-sell { color: var(--warn); } .st-sold { color: var(--text-2); }
.st-dip { color: var(--accent); } .st-manual { color: var(--warn); font-weight: 600; }
.st-queue { color: var(--info); } .st-spam { color: var(--warn); font-weight: 600; }
/* ⚠ Тон `warn` от процесса: «смотреть сюда». Отдельно от `st-manual`, у которого есть своё значение. */
.st-warn { color: var(--warn); font-weight: 600; }
.qfund { color: var(--text-2); } .qfund.relay { color: var(--warn); font-weight: 600; }
.lpico { width: 16px; height: 16px; border-radius: var(--r4); vertical-align: -3px; margin-right: 6px; }
/* Пад неизвестен — место под иконку ОСТАЁТСЯ: колонка не должна ездить от строки к строке. */
.lpico.none { display: inline-block; border: 1px dashed var(--base-3); opacity: .5; }
.lpico.mono { display: inline-flex; align-items: center; justify-content: center; background: var(--base-3); color: var(--text-2); font-size: 10px; font-weight: 700; }
/* Пад назван строкой, но не объявлен манифестом: монограмма есть, но пунктиром — это не значок
   площадки, а честная заметка «подписи не прислали». */
.lpico.undeclared { background: transparent; border: 1px dashed var(--base-4); }
/* иконка внутри кнопки фильтра стоит в ряд с подписью, а не «перед строкой текста» */
.segf .lpico { margin-right: 0; vertical-align: baseline; }

/* кнопки строки: те же 32px из макета, красная для полного выхода */
/* Кнопки — колонка ФИКСИРОВАННОЙ ширины и место под неё держится, даже когда кнопок нет: иначе
   соседние строки и шапка разъезжаются по горизонтали. */
/* ⚠ ШИРИНА ПОД ПЯТЬ ОРГАНОВ. Четыре доли продажи плюс переключатель ручного управления в 248px не
   влезали, а `nowrap` не переносит — кнопка молча наезжала на соседнюю колонку с дев-баем. Замер по
   макету: 54+54+54+58 на доли, 34 на переключатель, четыре зазора по 6 = 286, плюс кольцо нажатого. */
.strip .acts, .striphead .acts.head { flex: 0 0 292px; width: 292px; display: flex; flex-wrap: nowrap; align-items: center; gap: 6px; }
/* та же ступень вверх, что и у `.btn`: см. правило выше */
.strip .acts button { height: 32px; padding: 4px 12px; font: inherit; font-size: 12px; font-weight: 600; border-radius: var(--r8); cursor: pointer; border: 1px solid var(--ctl-edge); background: var(--ctl); color: var(--text-1); }
.strip .acts button:hover:not(:disabled) { border-color: var(--accent); background: var(--ctl-hover); }
/* «Продать всё» — обводкой, а не заливкой: это не запретная кнопка, а самая обычная работа, просто
   последняя из возможных. Заливка кричит громче, чем нужно, и тянет глаз на себя всю смену. */
.strip .acts button.sellall { border-color: var(--down); color: var(--down); }
.strip .acts button.sellall:hover:not(:disabled) { border-color: var(--down); background: var(--down-bg); }
.strip .acts button:disabled { opacity: .4; cursor: default; }
.strip .acts button.sell { background: var(--down); border-color: var(--down); color: #fff; }
.strip .acts button.sell:hover:not(:disabled) { filter: brightness(1.12); }
.strip .acts button.act.warn { color: var(--warn); }
.strip .acts button.guard { padding: 0 10px; display: inline-flex; align-items: center; }
.strip .acts button.guard.on { color: var(--up); border-color: color-mix(in srgb, var(--up) 45%, var(--base-3)); background: var(--up-bg-dim); }
.strip .acts button.guard.off { color: var(--text-2); }
/* ⛔ НАЖАТО — ЭТО ДРУГОЕ СОСТОЯНИЕ ПОЗИЦИИ, А НЕ ОТТЕНОК КНОПКИ. Ручное управление снимает с позиции
   всех автоматических продавцов: такую кнопку нельзя отличать от соседних одним лишь цветом обводки,
   иначе включённой её не заметят. Поэтому — СПЛОШНАЯ ЗАЛИВКА тревожным, значок цветом фона страницы
   и кольцо вокруг: видно боковым зрением, не читая.
   ⚠ Тревожный, а не зелёный: позиция без автоматики — не «хорошо» и не «плохо», это «смотрит только
   человек». Зелёный сторож рага рядом значит именно «хорошо», и путать их нельзя. */
.strip .acts button.guard { white-space: nowrap; }
.strip .acts button.guard.manual.off { color: var(--text-2); }
.strip .acts button.guard.manual.on {
	color: var(--base-1); background: var(--warn); border-color: var(--warn);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 30%, transparent);
}
.strip .acts button.guard.manual.on:hover:not(:disabled) { background: var(--warn); border-color: var(--warn); filter: brightness(1.06); }
.strip .acts button.guard.manual.on svg { opacity: 1; }

.strip .detchev { flex: 0 0 auto; color: var(--text-2); font-size: 12px; }
.strip.open .detchev { color: var(--accent); }
.detwrap { display: flex; flex-wrap: wrap; gap: var(--s12) var(--s32); padding: 0 var(--s16) var(--s16) 72px; background: var(--base-1); }
.detsec { min-width: 200px; }
.dethead { font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-2); font-weight: 600; margin-bottom: var(--s4); }
.detitem { display: flex; gap: var(--s12); justify-content: space-between; font-size: 12px; padding: 2px 0; }
.detlbl { color: var(--text-2); white-space: nowrap; }
.detval { text-align: right; word-break: break-word; }
.detval a { color: var(--accent); }

/* ── тосты и вход ── */
.toasts { position: fixed; right: var(--s20); bottom: var(--s20); z-index: 50; display: flex; flex-direction: column; gap: var(--s8); align-items: flex-end; pointer-events: none; }
.toast { background: var(--base-2); border: 1px solid var(--base-3); padding: 10px var(--s16); border-radius: var(--r8); font-size: 12.5px; max-width: 440px; box-shadow: 0 8px 28px #0006; opacity: 0; transform: translateY(8px); transition: opacity .15s, transform .15s; }
.toast.show { opacity: 1; transform: none; }
.toast.ok { border-color: var(--up); } .toast.err { border-color: var(--down); color: var(--down); } .toast.info { border-color: var(--accent); }

/* ── плашка о чужой правке: маленькая таблица, а не фраза ──
   ⛔ Одной строкой это не читалось: восемь секунд жизни плашки уходили на то, чтобы разобрать, где
   кончается ключ и начинается значение. Теперь «где» — заголовком группы, «что» — слева, «сколько» —
   СТОЛБИКОМ справа: значения видно взглядом, не читая. */
.tnotice { display: flex; flex-direction: column; gap: 8px; min-width: 250px; }
.tnotice .thead { display: flex; align-items: baseline; gap: var(--s12); }
.tnotice .thead b { font-weight: 600; }
.tnotice .thead .dim { font-size: 11px; margin-left: auto; white-space: nowrap; }
.tnotice .tgroup { display: flex; flex-direction: column; gap: 1px; }
.tnotice .tscope { font-size: 10px; color: var(--text-2); text-transform: uppercase; letter-spacing: .06em; font-weight: 600; margin-bottom: 2px; }
.tnotice .trow { display: flex; align-items: baseline; gap: var(--s16); padding: 2px 0; }
.tnotice .trow + .trow { border-top: 1px solid var(--base-3); }
.tnotice .tk { font-weight: 500; }
.tnotice .tv { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; }
.tnotice .tmore { font-size: 11px; }
.auth { position: fixed; inset: 0; background: #000c; display: flex; align-items: center; justify-content: center; z-index: 100; backdrop-filter: blur(3px); }
.auth form { background: var(--base-2); border: 1px solid var(--base-3); border-radius: var(--r16); padding: var(--s24); display: flex; flex-direction: column; gap: var(--s12); width: 360px; max-width: calc(100vw - 40px); }
.auth button { background: var(--accent); color: #fff; border: none; border-radius: var(--r8); height: 36px; font: inherit; font-weight: 600; cursor: pointer; }

@media (max-width: 900px) {
	header { flex-wrap: wrap; height: auto; padding: var(--s12); gap: var(--s8); }
	main { padding: var(--s12); }
	.striplist { min-width: 0; }
	.strip .striprow { flex-wrap: wrap; align-items: flex-start; gap: var(--s8) var(--s12); }
	.strip .cols { display: contents; }
	.strip .idc { order: 1; flex: 1 1 100%; width: auto; }
	.strip .col.c-in { order: 2; } .strip .col.c-pnl { order: 3; }
	.strip .col.c-fund { order: 4; margin-left: 0; }
	.strip .col.c-st { order: 5; flex: 1 1 100%; }
	.strip .acts { order: 6; flex: 1 1 100%; flex-wrap: wrap; }
	.strip .col, .strip .col.c-fund { flex: 0 1 auto; width: auto; }
	.detwrap { padding-left: var(--s16); }
	.setshell { flex-direction: column; }
	.setrail { flex: none; width: 100%; }
	.knob { grid-template-columns: 1fr 200px; }
	.kdoc { display: none; }
}

/* ══════════ ШАПКА В ТРИ УРОВНЯ (раскладка с экрана Crypto Pairs Screener) ══════════ */
/* 1-й уровень: цепи с иконками */
.chaintabs { display: flex; gap: var(--s4); align-items: center; }
.chaintab {
	display: inline-flex; align-items: center; gap: var(--s8);
	height: 40px; padding: 0 14px 0 10px;
	background: transparent; border: 1px solid transparent; border-radius: var(--r8);
	color: var(--text-2); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
	transition: background .12s, color .12s;
}
.chaintab:hover { background: var(--hover); color: var(--text-1); }
.chaintab.on { background: var(--base-2); color: var(--text-1); border-color: var(--base-3); font-weight: 600; }
.chainicon { width: 20px; height: 20px; border-radius: var(--r4); display: block; }
span.chainicon {
	display: inline-flex; align-items: center; justify-content: center;
	background: var(--base-3); color: var(--text-2); font-size: 11px; font-weight: 700; border-radius: 50%;
}
.chaintab.on .chainicon { color: var(--text-1); }
.chainname { white-space: nowrap; }
.pbadge.soft { background: var(--warn); color: #000; }

/* 2-й уровень: процессы цепи — ряд 45px с нижней границей, как ряд разделов в макете */
.procrow {
	display: flex; align-items: center; gap: var(--s4);
	height: 45px; padding: 0 var(--s20);
	border-bottom: 1px solid var(--base-2); background: var(--base-1); flex: 0 0 auto;
}
.proctab {
	display: inline-flex; align-items: center; gap: 7px;
	height: 30px; padding: 0 12px;
	background: transparent; border: 1px solid transparent; border-radius: var(--r8);
	color: var(--text-2); font: inherit; font-size: 12.5px; font-weight: 500; cursor: pointer;
}
.proctab:hover { color: var(--text-1); background: var(--hover); }
.proctab.on { background: var(--base-2); border-color: var(--base-3); color: var(--text-1); font-weight: 600; }

/* 3-й уровень: сегменты слева, поиск и фильтры справа */
/* ⚠ gap 12 между «инструментами» справа (фильтры, поиск, выключатель) и 4 между вкладками — иначе
   выключатель липнет к фильтру и читается как его часть. */
.segrow {
	display: flex; align-items: center; gap: var(--s4);
	padding: var(--s8) var(--s20); border-bottom: 1px solid var(--base-2); flex: 0 0 auto;
}
.seg {
	display: inline-flex; align-items: center; gap: 7px;
	height: 32px; padding: 0 14px;
	background: transparent; border: none; border-radius: var(--r8);
	color: var(--text-2); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
}
.seg:hover { color: var(--text-1); background: var(--hover); }
.seg.on { background: var(--base-2); color: var(--text-1); font-weight: 600; }
.seg svg { opacity: .85; }
.segrow > .btn, .segrow > .segsearch { margin-left: var(--s8); }
.segfilters { display: flex; gap: 2px; background: var(--base-2); border-radius: var(--r8); padding: 3px; }
.segf {
	display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 11px;
	background: transparent; border: none; border-radius: 6px;
	color: var(--text-2); font: inherit; font-size: 12px; font-weight: 500; cursor: pointer;
}
.segf:hover { color: var(--text-1); }
/* выбранный сегмент — тоже орган управления: ступень вверх от подложки ряда, а не вниз */
.segf.on { background: var(--ctl); color: var(--text-1); font-weight: 600; }
.segn { font-size: 10.5px; color: var(--text-2); background: var(--base-3); border-radius: var(--pill); padding: 0 5px; }
.segf.on .segn { color: var(--text-1); }
/* ⚠ Поиск и ряд фильтров стоят рядом, значит меряются ОДИНАКОВО: та же подложка, та же высота, тот
   же радиус, те же внутренние поля. Разные отступы у соседей читаются как сбитая вёрстка. */
.segsearch { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 3px 12px; background: var(--base-2); border: none; border-radius: var(--r8); color: var(--text-2); }
/* ⚠ Это поле уже стоит В СВОЕЙ ОПРАВЕ (пилюля с иконкой), поэтому общего подчёркивания у него нет:
   линия внутри пилюли читается как брак вёрстки. Фокус показывает сама оправа. */
.segsearch input, .segsearch input:hover, .segsearch input:focus { height: 28px; border: none; background: transparent; box-shadow: none; padding: 0; width: 210px; font-size: 13px; }
.segsearch input:focus { outline: none; }
.segsearch:focus-within { border-color: var(--accent); }
.btn.icon { width: 32px; padding: 0; }

/* заголовок таблицы: 14px SemiBold + нижняя граница (замер из макета) */
.striphead {
	display: flex; align-items: center; gap: var(--s16);
	padding: 0 var(--s16); height: 45px;
	border-bottom: 1px solid var(--base-3); background: var(--base-2);
	font-size: 13px; font-weight: 600; color: var(--text-2);
	position: sticky; top: 0; z-index: 2;
}
.striphead .cols { display: flex; align-items: center; gap: var(--s20); flex: 0 0 auto; }
/* с заголовком капшны в ячейках лишние — на узком экране они возвращаются */
@media (min-width: 901px) { .strip .cap { display: none; } }
@media (max-width: 900px) { .striphead { display: none; } }

/* ── модуль цепи (вкладки Control и Settings): карточка с шапкой ── */
.module { border: 1px solid var(--base-3); border-radius: var(--r12); background: var(--base-2); padding: var(--s12) var(--s16); display: flex; flex-direction: column; gap: var(--s12); }
.modhead { display: flex; align-items: center; gap: var(--s12); flex-wrap: wrap; padding-bottom: var(--s8); border-bottom: 1px solid var(--base-3); }
.modhead b { font-size: 14px; }
/* метка модуля в торговой строке — только когда строки пришли из разных модулей */
.modtag { font-size: 10px; color: var(--text-2); background: var(--base-3); border-radius: var(--pill); padding: 1px 7px; }

/* ── лента лаунчей ── */
.tradingwrap { display: flex; flex-direction: column; gap: var(--s16); }
.block { display: flex; flex-direction: column; gap: var(--s8); }
/* ⚠ center, а не baseline: в шапке стоят коробки (поиск, фильтры), и по базовой линии текста они
   разъезжались по вертикали на 4px — ровно то, что читается как «отступы разные». */
.blockhead { display: flex; align-items: center; gap: var(--s12); font-size: 13px; }
.blockhead b { font-size: 15px; }
.launches td { font-size: 12.5px; }
.launches tbody tr:hover td { background: var(--hover); }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
/* вердикт: свой цвет у «купили бы», приглушённый у штатных отказов, ЯНТАРЬ у незнакомого */
.verdict { display: inline-block; padding: 2px 9px; border-radius: var(--pill); font-size: 11.5px; font-weight: 600; }
.v-fire { color: var(--up); background: var(--up-bg-dim); border: 1px solid color-mix(in srgb, var(--up) 40%, transparent); }
.v-skip { color: var(--text-2); background: var(--surface-alt); border: 1px solid var(--base-3); }
/* ⛔ «Смотрим» — НЕ отказ ворот (сплошной серый) и не исход: решения по этой строке ещё не было.
   Пунктир и говорит об этом — состояние незавершённое, а не результат. */
.v-watch { color: var(--text-2); background: transparent; border: 1px dashed var(--base-4); }
.v-deny { color: var(--down); background: var(--down-bg); border: 1px solid color-mix(in srgb, var(--down) 35%, transparent); }
.v-new  { color: var(--warn); background: color-mix(in srgb, var(--warn) 14%, transparent); border: 1px solid var(--warn); }
/* ИСХОД — та же метка, что и вердикт, но заполненная: попали / не попали. Промах красным не «на
   всякий случай», а потому, что это проигранная гонка, и видеть её надо мгновенно. */
/* Выстрел в пути: между «решили» и «узнали». */
.v-fired { color: var(--fired); background: var(--fired-bg); border: 1px solid color-mix(in srgb, var(--fired) 50%, transparent); }
.v-landed { color: var(--up); background: var(--up-bg-dim); border: 1px solid color-mix(in srgb, var(--up) 55%, transparent); }
.v-miss { color: var(--down); background: var(--down-bg); border: 1px solid color-mix(in srgb, var(--down) 45%, transparent); }
a.verdict:hover { filter: brightness(1.2); text-decoration: none; }

/* счётчики хранилища */
.stats { display: flex; flex-wrap: wrap; gap: var(--s8); margin-bottom: var(--s12); }
.stat { display: inline-flex; align-items: baseline; gap: 6px; padding: 4px 11px; border: 1px solid var(--base-3); border-radius: var(--r8); background: var(--surface-alt); font-size: 12px; }
.statk { color: var(--text-2); text-transform: uppercase; letter-spacing: .05em; font-size: 10px; }
.stat b { font-size: 13px; font-weight: 600; }

/* ростер */
.rosterrow { display: flex; flex-wrap: wrap; gap: var(--s8); align-items: center; }
.rosterrow input { flex: 0 1 auto; }

/* торговля остановлена */
.alarmbar.halted { color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, var(--base-1)); font-weight: 600; cursor: default; }

/* ── счётчики горячего ── */
.hage { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: var(--pill); }
.hage.ok { color: var(--up); background: var(--up-bg-dim); }
.hage.bad { color: var(--down); background: var(--down-bg); }
.staleblock { border-color: var(--down); }
.hstats { display: flex; flex-wrap: wrap; gap: 6px; }
.hstat { display: inline-flex; align-items: baseline; gap: 6px; padding: 3px 10px; border: 1px solid var(--base-3); border-radius: var(--r8); background: var(--surface-alt); font-size: 12px; }
.hk { color: var(--text-2); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; }
.hstat b { font-weight: 600; }
.hgroup { margin-top: var(--s8); }
.hlabel { font-size: 10px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-2); margin-bottom: 4px; font-weight: 600; }
.cmdhead { display: flex; align-items: center; gap: var(--s8); }
/* «прошёл ворота, но придержан» — не победа и не отказ: отдельный вид, не зелёный */
/* «Прошёл ворота, но выстрела ещё нет» — янтарь: не успех и не отказ, а ожидание. */
.v-wait { color: var(--warn); background: color-mix(in srgb, var(--warn) 12%, transparent); border: 1px solid color-mix(in srgb, var(--warn) 55%, transparent); }

/* «всё хорошо» — компактным чипом в шапке, а не полосой во весь экран: постоянный зелёный баннер
   перестают читать через день. Тревога по-прежнему занимает полосу и кричит. */
.hchip {
	display: inline-flex; align-items: center; gap: 7px;
	height: 28px; padding: 0 12px;
	background: transparent; border: 1px solid var(--base-3); border-radius: var(--pill);
	color: var(--text-2); font: inherit; font-size: 12px; font-weight: 500; cursor: pointer;
}
.hchip:hover, .hchip.on { color: var(--text-1); border-color: color-mix(in srgb, var(--up) 45%, var(--base-3)); }
/* состояние цепи видно по самой вкладке: тревога — красная кромка, спокойствие — ничего лишнего */
.chaintab.alarm { border-color: var(--down); }
.chaintab.alarm.on { background: color-mix(in srgb, var(--down) 10%, var(--base-2)); }

/* ── панель настроек терминала: выезжает справа, поверх экрана ── */
.drawer { position: fixed; inset: 0; z-index: 90; display: flex; justify-content: flex-end; background: #0009; backdrop-filter: blur(2px); }
.drawerbody {
	width: 520px; max-width: 100vw; height: 100%; overflow: auto;
	background: var(--base-1); border-left: 1px solid var(--base-3);
	padding: var(--s16) var(--s20) var(--s24); display: flex; flex-direction: column; gap: var(--s20);
}
.drawerhead { display: flex; align-items: center; gap: var(--s12); font-size: 15px; }
.drawersec { display: flex; flex-direction: column; gap: var(--s8); }
.kvlist { display: flex; flex-direction: column; gap: 6px; font-size: 12px; }
.kvlist > div { display: flex; gap: var(--s12); align-items: baseline; }
.kvlist .dim { min-width: 74px; }
.kvlist b { font-weight: 500; word-break: break-all; }

/* 🔑 Место в блоке: за первое и идёт гонка, поэтому оно единственное красится. */
/* Обычное место — просто число рядом: без коробки, без полей. */
.launches .idx { margin-left: 6px; font-size: 10.5px; font-weight: 700; color: inherit; opacity: .72; }
/* ⚠ У первого места коробка есть, но она НЕ РАСТИТ таблетку: фиксированная высота строки и
   выравнивание по середине — иначе «Landed #1» оказывался выше соседних строк, и таблица дышала. */
.launches .idx.first {
	display: inline-block; height: 14px; line-height: 14px; padding: 0 6px; vertical-align: middle;
	border-radius: var(--pill); opacity: 1; color: var(--base-1); background: var(--up);
}
.launches .idx.first { color: var(--base-1); background: var(--up); font-weight: 700; }

/* ── балансы в ряду цепи ── */
.bals { position: relative; display: inline-flex; align-items: center; gap: var(--s4); background: var(--base-2); border-radius: var(--r8); padding: 3px; }
.bal { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border-radius: 6px; font-size: 12px; color: var(--text-1); cursor: help; }
.bal .balk { color: var(--text-2); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
.bal b { font-weight: 600; }
/* ⚠ Цвет — от деградаций процесса, а не от порогов терминала: пороги считает тот, кто знает цену
   газа и размер покупки. */
.bal.bad { color: var(--down); background: var(--down-bg); }
/* итог сделок: цвет — знак прибыли, а не тревога */
.bal.up b { color: var(--up); } .bal.down b { color: var(--down); }
.bal .balw.dim { color: var(--text-2); font-weight: 500; }
.bal .balw { color: var(--warn); font-weight: 700; font-size: 10.5px; }

/* ── подсказки: свои, а не браузерные (см. tip.jsx) ── */
.tip {
	position: fixed; z-index: 200; pointer-events: none; left: 0;
	/* ширина по содержимому, но не шире экрана: см. про сдвиг вместо `left` в tip.jsx */
	width: max-content; max-width: min(380px, calc(100vw - 16px)); padding: 8px 10px;
	background: var(--base-2); border: 1px solid var(--ctl-edge, var(--base-4)); border-radius: var(--r8);
	box-shadow: 0 8px 24px #0009;
	font-size: 12px; line-height: 1.35; color: var(--text-1);
	white-space: pre-wrap; overflow-wrap: anywhere;
	animation: tipin .09s ease-out;
}
/* Первая строка — суть, остальные — подробности: у подсказки тоже есть главное и второстепенное. */
.tip .tipmain { font-weight: 500; }
.tip .tipsub { color: var(--text-2); }
.tip .tipsub:first-child { color: var(--text-1); }
@keyframes tipin { from { opacity: 0; } }

/* ── звук событий ── */
.soundrows { display: flex; flex-direction: column; gap: 2px; }
.soundrows.off { opacity: .45; pointer-events: none; }
.soundrow { display: flex; align-items: center; gap: var(--s8); padding: 3px 2px; font-size: 12.5px; cursor: pointer; }
.soundvol { display: flex; align-items: center; gap: var(--s8); font-size: 12.5px; padding: 4px 2px 8px; }
.soundvol input[type=range] { flex: 1; accent-color: var(--accent); background: none; box-shadow: none; height: 20px; padding: 0; }
.soundvol b { min-width: 42px; text-align: right; }

/* запрет фида — единственное, что важнее счётчиков, когда он есть */
.blindbar { font-size: 13px; font-weight: 700; padding: 8px 10px; border-radius: var(--r8); background: var(--down-bg); border: 1px solid var(--down); }

/* догрузка старых лаунчей: кнопка под таблицей, по центру */
.loadmore { display: flex; align-items: center; justify-content: center; gap: var(--s12); padding: var(--s12) 0 var(--s4); font-size: 12px; }

/* раскрытие строки ленты: та же разметка подробностей, что у позиции */
.launches tbody tr.lrow { cursor: pointer; }
/* ⚠ Строка без единой отправки не раскрывается — и курсор об этом говорит ЗАРАНЕЕ, до клика в пустоту. */
.launches tbody tr.lrow.flat { cursor: default; }
.launches tbody tr.lrow.open { background: var(--hover); }
.launches tbody tr.ldet > td { padding: 0 0 var(--s8); border-bottom: 1px solid var(--base-3); background: var(--hover); }
.launches tbody tr.ldet .detwrap { padding: var(--s8) var(--s12); }

/* ── движения: строка на действие, как выписка ── */
.moves { display: flex; flex-direction: column; gap: 1px; padding: var(--s8) var(--s12) var(--s4); }
/* шесть колонок: действие, деньги, кто, исход, когда, хеш — выписка читается сверху вниз */
.moverow { display: grid; grid-template-columns: 96px 150px 132px 1fr 92px 116px; gap: var(--s12); align-items: baseline; font-size: 12.5px; padding: 3px 0; }
.moverow + .moverow { border-top: 1px solid color-mix(in srgb, var(--base-4) 55%, transparent); }
.movact { font-weight: 600; }
.mv-buy .movact { color: var(--up); }
.mv-sell .movact { color: var(--down-soft); }
.movamt { text-align: right; font-variant-numeric: tabular-nums; }
.movsrc, .movwhen { color: var(--text-2); }
.movwhen { text-align: right; }
.movtx { text-align: right; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; }
.movout { color: var(--text-2); font-size: 11.5px; }
.movout.bad { color: var(--down); }
/* отбитая отправка — приглушённая: она была, но денег не двигала */
.moverow.mv-lost .movamt, .moverow.mv-lost .movact { opacity: .6; }

/* ══ ЭКРАН КОШЕЛЬКОВ ══════════════════════════════════════════════════════════════════════════
   Две половины: слева выбор и группы (что мы РЕШИЛИ), справа сами кошельки (что ЕСТЬ). Читают их
   вместе — «этот набор вообще выстрелит?» — поэтому они рядом, а не на разных вкладках. */
.wallets { display: flex; flex-direction: column; gap: var(--s16); }
.wcols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s16); align-items: start; }
@media (max-width: 1100px) { .wcols { grid-template-columns: minmax(0, 1fr); } }
.wcol { display: flex; flex-direction: column; gap: var(--s8); min-width: 0; }

.pick { border: 1px solid var(--base-3); border-radius: var(--r12); padding: var(--s12); background: var(--base-2); display: flex; flex-direction: column; gap: 6px; }
/* Выбор в пустоту — красным по краю: это не мелкий шрифт, это «действие стреляет никем». */
.pick.bad { border-color: color-mix(in srgb, var(--down) 55%, transparent); background: var(--down-bg); }
/* Пустой выбор — законное «не стреляем»: приглушаем целиком, как выключенный тумблер. */
.pick.off { opacity: .72; }
.pickhead { display: flex; align-items: baseline; gap: var(--s8); font-size: 13px; }
.pickhead .mono { font-size: 11px; }
.pickctl { display: flex; gap: var(--s8); align-items: center; }
.pickctl input { flex: 1; min-width: 0; }
.pickinfo { display: flex; flex-wrap: wrap; gap: 6px; font-size: 11.5px; align-items: baseline; }

/* ── карта строк группы: клетка на строку файла ──
   ⛔ Клетка — это НОМЕР, и только: ни адреса, ни содержимого файла на карте нет. */
/* Нет карты — поле строк на её месте: выбор новой группы не должен упираться в объяснение. */
.nomap { display: flex; flex-direction: column; gap: 6px; margin: var(--s8) 0; }
.nomap input { width: 180px; }
.linemap { display: flex; flex-wrap: wrap; gap: 3px; margin: var(--s8) 0; }
.lcell {
	min-width: 26px; height: 22px; padding: 0 4px; border-radius: var(--r4);
	background: var(--surface-alt); border: 1px solid var(--base-3); color: var(--text-2);
	font: inherit; font-size: 10.5px; font-variant-numeric: tabular-nums; cursor: default;
}
/* Выбрана и поднята — обычная рабочая клетка. */
.lcell.picked { background: color-mix(in srgb, var(--accent) 22%, transparent); border-color: var(--accent); color: var(--text-1); }
/* Выбрана, но стрелок её не поднял: строка в файле пустая. Это не «пусто», это несостоявшийся билет. */
.lcell.missing { background: var(--down-bg); border-color: color-mix(in srgb, var(--down) 45%, transparent); color: var(--down); }
/* Из выбора убрали, кошелёк ещё держится — гаснет само. */
.lcell.waiting { background: color-mix(in srgb, var(--warn) 16%, transparent); border-color: var(--warn); color: var(--warn); }
/* Строка ПРАВИМОГО СЕЙЧАС выбора: щелчок её снимет. */
.lcell.mine { background: var(--accent); border-color: var(--accent); color: #fff; }
/* Чужая строка, пока правим свой выбор: забрать можно, но видно, что она занята. */
.linemap.arming .lcell.taken { border-style: dotted; opacity: .75; }
/* Поднята, но никем не выбрана. */
.lcell.raised { border-style: dashed; }
.linemap.arming .lcell { cursor: pointer; }
.linemap.arming .lcell:hover { border-color: var(--text-1); color: var(--text-1); }

/* значок котировки: размером с текст рядом, без своей рамки */
.qico { vertical-align: -2px; opacity: .9; }

/* ── деньги на экране кошельков: по действиям, а не списком ── */
.wmoney { display: flex; gap: var(--s8); flex-wrap: wrap; margin-bottom: var(--s4); }
.wbucket { border: 1px solid var(--base-3); border-radius: var(--r12); background: var(--base-2); overflow: hidden; }
.wbhead { display: flex; align-items: baseline; gap: var(--s8); padding: 8px var(--s12); border-bottom: 1px solid var(--base-3); font-size: 12.5px; }
.wbhead .dim { font-size: 11px; }
.wbucket .tablewrap { border: none; border-radius: 0; }
.wbucket table { table-layout: fixed; }
.wbucket table td { font-size: 12px; overflow: hidden; text-overflow: ellipsis; }
/* Заголовок колонки — тише содержимого: он подсказка, а не данные. */
.wbucket table th { font-size: 10.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--text-2); text-align: left; padding: 4px var(--s8); }
.wbucket .btn.small { margin: 6px var(--s12) 8px; }
/* Пояснение внутри карточки живёт по её полям, а не по краю экрана. */
.wbucket .note { padding: 0 var(--s12) 8px; margin-top: 4px; }
/* Селектор группы в поле выбора: он тут главный орган, а не поле ввода. */
.pickctl select { min-width: 190px; }

/* плашка денег, ведущая на экран кошельков: она кликабельна, и это должно быть видно */
.bal.go { cursor: pointer; }
.bal.go:hover { background: var(--hover); border-radius: var(--r8); }

/* ── рубильник входа на плашке площадки ── */
.padpause { margin-left: 6px; opacity: .55; font-size: 11px; cursor: pointer; }
.padpause:hover { opacity: 1; }
/* Выключенная площадка — янтарём: «хотели бы, но не заходим» это то же семейство, что общая пауза. */
.padpause.on { opacity: 1; color: var(--warn); }
.segf.paused { border-color: color-mix(in srgb, var(--warn) 55%, transparent); color: var(--warn); }

/* площадка, за которой только смотрят: тише торгуемых, но на виду */
.padwatch { margin-left: 6px; font-size: 10px; opacity: .6; }

/* Площадка без кошельков: не прячем и не гасим до неразличимости — называем причину словом. */
.segf.dry { opacity: .8; }
/* ⛔ БЕЗ ПЛАШКИ И БЕЗ КАПСА: ряд площадок читают боковым зрением, и подпись, которая громче самого
   пада, размывает весь ряд. Остался один знак — «пусто», словами объясняет подсказка. */
.paddry { font-size: 13px; line-height: 1; color: var(--warn); margin-left: 5px; cursor: help; }
.padhalf { font-size: 10px; font-weight: 600; color: var(--warn); margin-left: 5px; cursor: help; }.segf.watching { border-style: dashed; }

/* ── выбор момента, от которого считается итог ── */
.bal.clickable { cursor: pointer; }
.bal.clickable:hover { background: var(--hover); border-radius: var(--r8); }
.balsince { font-size: 9.5px; margin-left: 5px; }
.sincebox { position: absolute; z-index: 60; top: 100%; right: 0; margin-top: 6px; width: max-content;
	background: var(--base-2); border: 1px solid var(--base-3); border-radius: var(--r12);
	box-shadow: 0 10px 30px rgba(0, 0, 0, .45); padding: var(--s8); }
.sincehead { display: flex; align-items: center; gap: 6px; padding: 2px 4px 8px; font-size: 12px; }
.sincebody { display: flex; gap: var(--s8); }
.cal { display: grid; grid-template-columns: repeat(7, 26px); gap: 2px; }
.calwd { font-size: 9.5px; color: var(--text-2); text-align: center; padding-bottom: 2px; }
.calday { height: 24px; border: none; border-radius: var(--r8); background: transparent; color: var(--text-1);
	font-size: 11.5px; cursor: pointer; font-family: inherit; }
.calday:hover:not(:disabled) { background: var(--ctl); }
.calday:disabled { color: transparent; cursor: default; }
.calday.today { box-shadow: inset 0 0 0 1px var(--base-4); }
.calday.on { background: var(--accent); color: #fff; }
.timecols { display: flex; gap: 4px; }
.timecol { display: flex; flex-direction: column; gap: 2px; max-height: 186px; overflow-y: auto; padding-right: 2px; }
.timecell { width: 30px; height: 22px; border: none; border-radius: var(--r8); background: transparent;
	color: var(--text-2); font-size: 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; cursor: pointer; }
.timecell:hover { background: var(--ctl); color: var(--text-1); }
.timecell.on { background: var(--accent); color: #fff; }
.sincefoot { display: flex; align-items: center; gap: var(--s8); padding-top: 8px; font-size: 11px; }

/* ══════════════ ПРАВИЛА ПРОДАЖИ — по макету оператора rule-groups-builder-v9 (05.09) ══════════════
   ОДНА ОБОЛОЧКА (карточка раздела). Правила — не карточки, а СТРОКИ через волосяные линии: шапка
   (ручка, имя, «matches all», код AND, доля, счёт условий, шеврон; под ней приоритет и сводка; справа
   корзина и переключатель), ТЕЛО — конструктор на УТОПЛЕННОЙ поверхности (цвет страницы). Лестница:
   карточка раздела (base-2) → тело правила (base-1) → карточка группы (base-2) → органы (ctl с тенью).
   Внизу — «+ Add rule» во всю ширину и строка счёта. Линии — 10% цвета текста, как у образца. */
.rules { display: flex; flex-direction: column; --rb-line: color-mix(in srgb, var(--text-1) 10%, transparent); --rb-comb: 4rem; }
.rules .rshead { display: flex; align-items: center; gap: var(--s8); padding: 10px 16px; font-size: 12px; color: var(--text-2); border-bottom: 1px solid var(--rb-line); }
.rules .rshead .spacer { flex: 1; }
.rules .rsmeta { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.rules .rsmeta .dot { width: 6px; height: 6px; }
/* ── строка правила ── */
.rule { position: relative; border-bottom: 1px solid var(--rb-line); transition: opacity .15s; }
.rule.off { opacity: .5; }
.rule.dragging { opacity: .32; }
.rule.drop-before::before, .rule.drop-after::after { content: ""; position: absolute; left: 8px; right: 8px; height: 2px; border-radius: 999px; background: var(--accent); z-index: 5; }
.rule.drop-before::before { top: -1px; }
.rule.drop-after::after { bottom: -1px; }
/* шапка правила — ступень ВВЕРХ от карточки раздела (base-3), чтобы глубина читалась и у свёрнутого:
   в макете свёрнутый список плоский, у нас правила чаще свёрнуты, чем раскрыты */
.rhead { display: flex; align-items: center; gap: 8px; min-height: 48px; padding: 6px 12px; background: var(--base-3); }
.rhead .rgrip { flex: 0 0 24px; width: 24px; height: 32px; border: 0; background: transparent; padding: 0; display: grid; place-items: center; margin-left: -4px; border-radius: 6px; color: color-mix(in srgb, var(--text-2) 50%, transparent); cursor: grab; }
.rhead .rgrip:hover, .rhead .rgrip:focus-visible { background: color-mix(in srgb, var(--ctl) 60%, transparent); color: var(--text-2); outline: none; }
.rhead .rgrip:active { cursor: grabbing; }
.rhit { flex: 1; min-width: 0; border: 0; background: transparent; padding: 4px 6px; margin: -4px 0 -4px -6px; text-align: left; color: inherit; font: inherit; cursor: pointer; border-radius: 6px; }
.rhit:hover { background: color-mix(in srgb, var(--ctl) 40%, transparent); }
.rline { display: flex; align-items: center; gap: 10px; min-height: 20px; min-width: 0; }
.rtitle { font-size: 14px; font-weight: 500; }
/* имя правится прямо в заголовке: поле по ширине текста, рамка и подложка — только в фокусе/при наведении */
.rtitlein { min-width: 6ch; max-width: 26ch; height: 24px; margin: -2px 0; padding: 0 4px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: inherit; font: inherit; font-size: 14px; font-weight: 500; outline: none; }
.rtitlein::placeholder { color: var(--text-2); font-style: italic; font-weight: 400; }
.rtitlein:hover { border-color: var(--rb-line); }
.rtitlein:focus { border-color: var(--accent); background: var(--ctl); }
.rule.off .rtitlein { color: inherit; }
.rule.bad .rtitle { color: var(--down); }
.rop { font-size: 12px; color: var(--text-2); }
.rcode { border-radius: 4px; background: color-mix(in srgb, var(--ctl) 70%, transparent); padding: 2px 6px; font: 500 12px/16px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--text-1); }
/* действие — словами, нейтрально: это не тревога, а содержание; цвет оставлен тому, что требует внимания */
.rsell { font-size: 12px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.rnum { flex: 0 0 auto; min-width: 1.6ch; text-align: right; font: 500 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text-2); opacity: .8; cursor: help; }
.rline .spacer { flex: 1; }
.rline .rcount { flex: 0 0 auto; font-size: 11px; color: var(--text-2); opacity: .8; cursor: help; }
.rtag { display: inline-flex; align-items: center; border-radius: 4px; background: color-mix(in srgb, var(--ctl) 55%, transparent); padding: 2px 6px; font-size: 10px; line-height: 14px; color: var(--text-2); white-space: nowrap; }
.rline .rchev { margin-left: 2px; color: var(--text-2); opacity: .65; transition: transform .2s; }
.rule.collapsed .rline .rchev { transform: rotate(-90deg); }
.rsub { margin-top: 4px; padding-left: calc(1.6ch + 10px); display: flex; align-items: center; gap: 8px; min-width: 0; }
.rsub .rsum { font: 12px/16px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.rhacts { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.rtrash { width: 28px; height: 28px; border: 0; background: transparent; border-radius: 6px; display: grid; place-items: center; color: color-mix(in srgb, var(--text-2) 70%, transparent); cursor: pointer; }
.rtrash:hover { background: var(--ctl); color: var(--down); }
.rerr { padding: 0 12px 10px 44px; font-size: 11.5px; color: var(--down); }
/* ── тело правила: утопленная поверхность ── */
.rbody { padding: 14px 14px 12px 38px; border-top: 1px solid var(--rb-line); background: var(--base-1); }
/* КОРОБКА RULE (макет §13): имя и действие блоками «Size & floor · Stream · Safety»; колонка подписей —
   по самой длинной, у продажи (один блок) она равна колонке связки */
/* коробка Rule — строками как обычные настройки (06.09): имя | описание | поле с единицей и сбросом */
/* без своей подложки (решение оператора 06.09): строки лежат прямо в теле карточки, как и условия; от Where
   их отделяет одна линия */
.rtake.rknobs { display: block; margin: -8px 0 10px; padding: 0 0 6px; border-bottom: 1px solid var(--rb-line); }
.rkblock { display: contents; }
.rkhead { padding: 10px 8px 3px; font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-2); cursor: help; }
.rkrow { display: grid; grid-template-columns: 170px minmax(0, 1fr) 272px; gap: 12px; align-items: center; padding: 3px 8px; border-radius: 6px; }
.rkrow:hover { background: var(--hover); }
.rkrow:focus-within { background: color-mix(in srgb, var(--accent) 9%, transparent); }
.rkname { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; cursor: help; white-space: nowrap; }
.rkdoc { color: var(--text-2); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rkctl { display: flex; align-items: center; gap: 6px; min-width: 0; }
.rkctl .rctl { flex: 1 1 auto; height: 28px; }
.rkctl .rctl.rsellin { flex: 1 1 auto; }
.rkctl .rctl.rsellin input { text-align: right; }
.rkctl .rctl.rname input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.rkctl .rkswitch { flex: 1 1 auto; display: flex; justify-content: flex-end; }
.rkctl .rkunit { flex: 0 0 64px; font-size: 11px; color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rkctl .rst { flex: 0 0 28px; width: 28px; padding: 0; }
.rkctl .rst.ghost { visibility: hidden; }
.rkrow.dflt .rctl input::placeholder { color: var(--text-2); opacity: .9; }
.rtake { display: grid; grid-template-columns: minmax(var(--rb-comb), max-content) minmax(0, 1fr); align-items: center; row-gap: 6px; margin-bottom: 10px; }
.rtake.blocks { padding: 8px 10px 8px 0; border: 1px solid var(--rb-line); border-radius: 8px; background: color-mix(in srgb, var(--base-2) 60%, transparent); }
.rtake .rtakerow { display: contents; }
.rtake > .rword, .rtake .rtakerow > .rword { padding-left: 8px; padding-right: 10px; white-space: nowrap; }
.rtake.blocks .rtakerow > .rword { font-size: 11px; }
/* незаполненное действие: умолчание площадки серым плейсхолдером и слово «default» у переключателя */
.ractn.dflt .rctl input::placeholder { color: var(--text-2); opacity: .9; }
.rdflt { font-size: 10px; color: var(--text-2); }
.rtag.rone { color: var(--text-2); }
/* «взяло бы N» у ВЫКЛЮЧЕННОГО правила: цена выключения там, где включают */
.rtag.rwould { font-style: italic; }
/* «взяло бы» у строки лаунча — той же формой, что политика («auto · Paused»): имя главным словом, исход
   мельче; имя курсивом — единственный знак, что правило выключено и приказа не было */
.verdict .wlead { font-style: italic; font-weight: 500; }
.rvico { border-radius: 3px; flex: 0 0 auto; }
.rctl > .rvico { margin-left: 8px; }
.rchip .rvico { margin-right: 2px; }
.rvico.rvlucide { display: inline-flex; align-items: center; color: var(--text-2); }
.ritem .rvico { margin-right: 6px; }
.ritem .rname { margin-left: auto; padding-left: 10px; font-size: 10px; color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.rfstage.purchase, .pstage.purchase { color: var(--accent); opacity: 1; }
.rmeta { display: grid; grid-template-columns: var(--rb-comb) minmax(0, 1fr); align-items: center; margin-bottom: 8px; }
.rmetacells { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.rmetacells .rctl.rname { flex: 0 1 11rem; }
.rmetacells .rctl.rsellin { flex: 0 0 5.5rem; }
.rmetacells .ractn { margin-right: 6px; }
.rmetacells .rctl.rname input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.rmetacells .rctl.rsellin input { text-align: right; }
.rmetaword { font-size: 12px; color: var(--text-2); white-space: nowrap; }
.rnotline { display: flex; align-items: center; gap: 8px; padding-left: var(--rb-comb); margin-bottom: 6px; }
/* кнопка отрицания в подвале группы: видна всегда, нажатая горит акцентом — отрицание меняет смысл
   всей группы, и прятать его в кебаб значило прятать самое важное */
.rghost.rnot { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing: .04em; }
.rghost.rnot.on { background: color-mix(in srgb, var(--accent) 16%, transparent); border-color: color-mix(in srgb, var(--accent) 55%, transparent); color: var(--accent); }
.rghost.rnot.on:hover { background: color-mix(in srgb, var(--accent) 24%, transparent); color: var(--accent); }
.rnotline .rcode { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); font-weight: 600; }
/* ── конструктор: сетка «связка | строка» ── */
.rroot { display: flex; flex-direction: column; min-width: 0; border-radius: 8px; }
.rroot.bad > .rlist { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--down) 50%, transparent); border-radius: 8px; }
.rroot.drop-inside > .rlist { box-shadow: 0 0 0 2px var(--accent); border-radius: 8px; }
.rlist { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.rrow, .rgrow { position: relative; display: grid; grid-template-columns: var(--rb-comb) minmax(0, 1fr); align-items: center; min-width: 0; }
.rccell { min-height: 38px; display: flex; align-items: center; padding-right: 8px; }
.rword { display: flex; align-items: center; height: 32px; padding-left: 8px; font-size: 12px; font-weight: 500; color: var(--text-2); }
/* кнопка связки — одна на группу, но на КАЖДОЙ строке после первой (макет): слово группы, клик меняет её всю */
.rcomb { width: 56px; height: 32px; border: 1px solid transparent; border-radius: 6px; background: transparent; padding: 0 6px 0 8px; text-align: left;
	color: var(--text-2); font: inherit; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; cursor: pointer; transition: background-color .15s, border-color .15s, color .15s; }
.rcomb:hover { background: var(--ctl); color: var(--text-1); border-color: var(--rb-line); }
.rcond { position: relative; min-height: 38px; display: flex; align-items: center; gap: 8px; padding: 3px 4px 3px 0; border-radius: 6px; transition: opacity .15s; }
.rcond.dragging, .rgrow.dragging { opacity: .36; }
.rcond.drop-before::before, .rcond.drop-after::after, .rgrow.drop-before > .rcard::before, .rgrow.drop-after > .rcard::after {
	content: ""; position: absolute; left: 0; right: 0; height: 2px; background: var(--accent); border-radius: 999px; z-index: 25; }
.rcond.drop-before::before, .rgrow.drop-before > .rcard::before { top: -3px; }
.rcond.drop-after::after, .rgrow.drop-after > .rcard::after { bottom: -3px; }
/* ⚠ полоса ячеек ЗАПОЛНЯЕТ строку, а не жмётся к содержимому: у `select` с одним «=» своей ширины нет,
   и полоса по содержимому схлопывала его до одного шеврона; основы ячеек держатся только в широкой полосе */
.rmain { min-width: 0; display: flex; align-items: center; gap: 6px; flex: 1 1 auto; }
/* основы ячеек — селектором сильнее общего `.rctl { flex: 1 }`, иначе поле и оператор растягивались на всю полосу */
.rmain > .rctl.rfield { flex: 0 1 12rem; }
.rmain > .rctl.ropc { flex: 0 1 9rem; }
.rval { flex: 0 1 12rem; display: flex; align-items: center; gap: 6px; min-width: 0; }
.rval:has(.rchips) { flex-basis: 22rem; }
/* орган — отдельная приподнятая поверхность, а не прозрачное поле на карточке */
.rctl { position: relative; height: 32px; min-width: 0; overflow: hidden; border: 1px solid var(--rb-line); border-radius: 6px; background: var(--ctl); display: flex; align-items: center; flex: 1 1 auto;
	box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 3%, transparent), 0 1px 1px color-mix(in srgb, #000 18%, transparent);
	transition: background-color .15s, border-color .15s, box-shadow .15s; }
.rctl:hover { background: var(--ctl-hover); border-color: color-mix(in srgb, var(--text-1) 16%, transparent); }
.rctl:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent), inset 0 1px 0 color-mix(in srgb, #fff 3%, transparent); }
.rctl select, .rctl input, .rctl select:hover, .rctl input:hover, .rctl select:focus, .rctl input:focus {
	width: 100%; height: 100%; min-width: 0; border: 0; outline: 0; background: transparent; box-shadow: none; color: var(--text-1); font-size: 12px; padding: 0 10px; border-radius: 0; }
.rctl select { appearance: none; padding-right: 27px; cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; background-color: transparent; }
.rctl select:hover:not(:disabled), .rctl select:focus { background-color: transparent; }
.rctl input::placeholder { color: var(--text-2); }
.rctl input[type=number] { appearance: textfield; }
.rctl input[type=number]::-webkit-outer-spin-button, .rctl input[type=number]::-webkit-inner-spin-button { appearance: none; margin: 0; }
.rctl .rchev { position: absolute; right: 8px; pointer-events: none; color: var(--text-2); opacity: .78; }
/* негодная ячейка — кольцом, не рамкой: рамка меняет бокс и сдвинула бы соседей */
.rval.bad .rctl { border-color: color-mix(in srgb, var(--down) 60%, transparent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--down) 25%, transparent); }
.rval .runit { font-size: 10.5px; color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; flex: 0 0 auto; }
.rval .rdash { color: var(--text-2); flex: 0 0 auto; }
/* действия строки — видны, когда строка под курсором */
.rband { margin-left: auto; flex: 0 0 auto; display: flex; align-items: center; gap: 2px; padding-right: 4px; color: var(--text-2); opacity: .46; transition: opacity .15s; }
.rcond:hover > .rband, .rgfoot:hover > .rband, .rfoot:hover > .rband, .rband:has(.rkebab.open), .rband:focus-within { opacity: 1; }
.ract { width: 28px; height: 28px; border: 0; border-radius: 6px; background: transparent; display: grid; place-items: center; color: inherit; cursor: pointer; transition: background-color .15s, color .15s; }
.ract:hover, .rkebab.open .ract { background: var(--ctl); color: var(--text-1); }
.ract.grip { cursor: grab; }
.ract.grip:active { cursor: grabbing; }
/* ── вложенная группа: карточка на утопленном теле ── */
.rcard { position: relative; min-width: 0; border: 1px solid var(--rb-line); border-radius: 8px; background: var(--base-2); padding: 10px;
	box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 2.5%, transparent), 0 1px 2px color-mix(in srgb, #000 20%, transparent);
	transition: border-color .12s, box-shadow .12s, background-color .12s; }
.rcard .rcard { background: var(--base-3); border-color: color-mix(in srgb, var(--text-1) 12%, transparent); }
.rcard.bad { border-color: color-mix(in srgb, var(--down) 60%, transparent); }
.rcard.drop-inside { box-shadow: 0 0 0 2px var(--accent), 0 8px 20px color-mix(in srgb, #000 28%, transparent); }
.rempty { min-height: 52px; display: grid; place-items: center; border: 1px dashed var(--rb-line); border-radius: 6px; background: color-mix(in srgb, var(--base-1) 60%, var(--base-2)); color: var(--text-2); font-size: 11px; }
.rgfoot { min-height: 32px; display: flex; align-items: center; gap: 4px; margin-top: 8px; padding: 7px 0 0 var(--rb-comb); border-top: 1px solid var(--rb-line); }
.rgfoot .spacer, .rfoot .spacer { flex: 1; }
.rfoot { display: flex; align-items: center; gap: 4px; margin-top: 12px; padding: 10px 4px 0 var(--rb-comb); border-top: 1px solid var(--rb-line); }
/* «призраки» подвала: без коробки, пока не наведёшь — они подпись, а не орган */
.rghost { height: 28px; border: 1px solid transparent; border-radius: 6px; background: transparent; padding: 0 7px; display: inline-flex; align-items: center; gap: 6px; color: var(--text-2);
	font: inherit; font-size: 11px; line-height: 1; font-weight: 500; cursor: pointer; transition: background-color .15s, color .15s, border-color .15s; }
.rghost:hover { background: var(--ctl); border-color: var(--rb-line); color: var(--text-1); }
.rghost.icon { width: 28px; padding: 0; justify-content: center; }
.rbempty { min-height: 96px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; margin-left: var(--rb-comb); border: 1px dashed var(--rb-line); border-radius: 8px;
	background: color-mix(in srgb, var(--base-1) 60%, var(--base-2)); color: var(--text-2); text-align: center; }
.rbempty svg { opacity: .65; margin-bottom: 4px; }
.rbempty b { color: var(--text-1); font-size: 12px; font-weight: 500; }
.rbempty span { font-size: 11px; opacity: .8; }
/* ── меню ── */
.rkebab { position: relative; display: inline-flex; }
/* меню кебаба — порталом в body, `position: fixed` под кнопкой правым краем; карточка его не режет */
.rmenu.rfloat { position: fixed; z-index: 200; }
.rmenu { position: absolute; right: 0; top: 30px; z-index: 100; min-width: 154px; padding: 4px; background: var(--base-2); color: var(--text-1); border: 1px solid var(--rb-line); border-radius: 8px;
	box-shadow: 0 12px 32px color-mix(in srgb, #000 42%, transparent); display: flex; flex-direction: column; }
.ritem { width: 100%; height: 31px; border: 0; border-radius: 5px; background: transparent; padding: 0 8px; display: flex; align-items: center; gap: 8px; text-align: left; font: inherit; font-size: 11px; color: var(--text-1); cursor: pointer; white-space: nowrap; }
.ritem:hover { background: var(--ctl); }
.ritem.danger { color: var(--down); }
.ritem .rico { display: inline-flex; color: inherit; opacity: .8; }
.ritem .rlabel { flex: 1; }
.ritem .rtick { color: var(--accent); }
.rsep { height: 1px; background: var(--rb-line); margin: 4px -1px; }
/* ── чипы `in / not in` — внутри той же коробки ── */
.rctl.rchips { height: auto; min-height: 32px; flex-wrap: wrap; gap: 4px; padding: 2px 6px; overflow: visible; cursor: text; }
.rchip { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; padding: 1px 6px; border-radius: 999px; background: var(--base-3); border: 1px solid var(--rb-line); }
.rchip button { border: 0; background: none; color: var(--text-2); cursor: pointer; padding: 0 2px; font: inherit; line-height: 1; }
.rchip button:hover { color: var(--down); }
.rctl.rchips input, .rctl.rchips input:hover, .rctl.rchips input:focus { width: auto; flex: 1 1 60px; min-width: 60px; height: 24px; padding: 0 2px; }
/* ── низ оболочки: «+ Add rule» во всю ширину и строка счёта ── */
.raddrow { border-top: 1px solid var(--rb-line); }
.raddrow button { width: 100%; height: 42px; border: 0; background: transparent; padding: 0 16px; display: flex; align-items: center; gap: 8px; text-align: left; color: var(--text-2); font: inherit; font-size: 12px; font-weight: 500; cursor: pointer; transition: background-color .15s, color .15s; }
.raddrow button:hover { background: color-mix(in srgb, var(--ctl) 40%, transparent); color: var(--text-1); }
/* модалка импорта правил: одно поле, одна кнопка */
.rmodal { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, .55); display: grid; place-items: center; padding: 24px; }
.rdialog { width: min(720px, 100%); background: var(--base-2, var(--panel)); border: 1px solid var(--rb-line); border-radius: 10px; box-shadow: 0 18px 48px rgba(0,0,0,.45); padding: 14px 16px 12px; display: grid; gap: 10px; }
.rdhead { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.rdhead b { font-size: 13px; }
.rdsub { font-size: 11px; color: var(--text-2); }
.rdialog textarea { width: 100%; min-height: 220px; resize: vertical; box-sizing: border-box; padding: 8px 10px; border-radius: 6px; border: 1px solid var(--rb-line); background: var(--ctl); color: var(--text-1); font: 11.5px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace; }
.rdialog textarea:focus { outline: none; border-color: var(--accent); }
.rdbtns { display: flex; justify-content: flex-end; gap: 8px; }
.rprimary { height: 28px; border: 0; border-radius: 6px; background: var(--accent); color: #fff; padding: 0 12px; display: inline-flex; align-items: center; gap: 6px; font: inherit; font-size: 12px; cursor: pointer; }
.rprimary:disabled { opacity: .45; cursor: default; }
.rprimary:not(:disabled):hover { filter: brightness(1.1); }
/* строка добавления: «Add rule» во всю ширину, «Import» справа */
.raddrow { display: flex; }
.raddrow button.rimport { width: auto; flex: 0 0 auto; }
.rstatus { min-height: 34px; border-top: 1px solid var(--rb-line); padding: 0 16px; display: flex; align-items: center; gap: 12px; color: var(--text-2); font-size: 10.5px; }
.rstatus .rhash { font-size: 11px; margin-right: -8px; }
/* ── кнопка поля (→ палитра), значок стадии, действия правила, запертая связка ── */
.rctl.rfbtn { justify-content: flex-start; gap: 6px; padding: 0 26px 0 8px; cursor: pointer; text-align: left; font: inherit; color: var(--text-1); }
.rctl.rfbtn.open { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 28%, transparent); }
.rfbtn .rfico { color: var(--text-2); flex: 0 0 auto; display: inline-flex; }
.rfbtn .rftitle { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.rfbtn .rfunit { font-size: 10px; color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; flex: 0 0 auto; }
.rfstage, .pstage { display: inline-flex; align-items: center; color: var(--text-2); flex: 0 0 auto; opacity: .85; }
/* поле квитанции — предупреждение: условие по нему не остановит поток на кадре */
.rfstage.receipt, .pstage.receipt { color: var(--warn); opacity: 1; }
.lmono { display: inline-grid; place-items: center; border-radius: 4px; background: var(--ctl); color: var(--text-2); font-weight: 700; line-height: 1; }
.ractn { display: inline-flex; align-items: center; gap: 8px; }
.rword.rlocked { text-transform: uppercase; font-size: 11px; letter-spacing: .04em; cursor: help; }
/* ── ПАЛИТРА ПОЛЯ (shadcn command-palette-4: поиск + группы слева, предпросмотр справа) ── */
.pal { position: fixed; z-index: 200; width: 640px; height: 400px; display: grid; grid-template-columns: 1fr 260px; overflow: hidden; border-radius: 8px;
	border: 1px solid color-mix(in srgb, var(--text-1) 10%, transparent); background: var(--base-2); color: var(--text-1); box-shadow: 0 16px 48px color-mix(in srgb, #000 45%, transparent); }
/* ⚠ `min-height: 0` на колонке и списке: без него флекс-ребёнок не ужимается ниже содержимого, список
   вырастает за 400px, `overflow: auto` не срабатывает и колесо крутит страницу под палитрой */
.pal .pleft { display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: hidden; }
/* `flex: 0 0 auto`: строка поиска — не резина; иначе длинный список ужимал её до полосы */
.pal .psearch { display: flex; flex: 0 0 auto; align-items: center; gap: 8px; padding: 0 12px; height: 44px; border-bottom: 1px solid color-mix(in srgb, var(--text-1) 10%, transparent); color: var(--text-2); cursor: text; }
.pal .psearch input, .pal .psearch input:hover, .pal .psearch input:focus { flex: 1; min-width: 0; height: 100%; border: 0; background: transparent; box-shadow: none; padding: 0; font-size: 13px; color: var(--text-1); }
.pal .plist { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 6px; overscroll-behavior: contain; }
.pal .pgroup { padding: 4px 0 2px; }
.pal .pghead { padding: 6px 12px 4px; font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-2); }
.pal .pitem { width: 100%; display: flex; align-items: center; gap: 10px; padding: 8px 12px; border: 0; background: transparent; border-radius: 6px; color: var(--text-1); font: inherit; font-size: 13px; cursor: pointer; text-align: left; }
.pal .pitem.on { background: var(--ctl); }
.pal .pitem .pico { color: var(--text-2); display: inline-flex; flex: 0 0 auto; }
.pal .pitem .ptitle { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pal .pitem .pname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10.5px; color: var(--text-2); }
.pal .pitem .punit { font-size: 10.5px; color: var(--text-2); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; flex: 0 0 auto; }
.pal .pempty { padding: 24px; text-align: center; color: var(--text-2); font-size: 13px; }
.pal .pright { border-left: 1px solid color-mix(in srgb, var(--text-1) 10%, transparent); background: var(--base-1); padding: 20px; display: flex; flex-direction: column; min-width: 0; min-height: 0; overflow: auto; overscroll-behavior: contain; }
.pal .pright .pempty { margin: auto; }
.pal .pbig { width: 44px; height: 44px; flex: 0 0 auto; border-radius: 8px; border: 1px solid color-mix(in srgb, var(--text-1) 10%, transparent); background: var(--ctl); display: grid; place-items: center; }
.pal .phead { margin-top: 14px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pal .phead b { font-size: 13px; font-weight: 600; }
.pal .pbadge { font-size: 10px; padding: 2px 6px; border-radius: 4px; background: var(--ctl); color: var(--text-2); white-space: nowrap; }
.pal .pdoc { margin: 8px 0 0; font-size: 12px; color: var(--text-2); line-height: 1.5; text-wrap: pretty; }
.pal dl { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid color-mix(in srgb, var(--text-1) 10%, transparent); display: flex; flex-direction: column; gap: 6px; }
.pal dl div { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; min-width: 0; }
.pal dt { font-size: 11px; color: var(--text-2); flex: 0 0 auto; }
.pal dd { margin: 0; font-size: 11px; font-weight: 500; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; text-align: right; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; justify-content: flex-end; }
.pal .pdetail { margin: 10px 0 0; font-size: 11px; color: var(--text-2); line-height: 1.5; flex: 1; text-wrap: pretty; }
.pal .puse { margin-top: 12px; height: 32px; width: 100%; flex: 0 0 auto; border: 0; border-radius: 6px; background: var(--accent); color: #fff; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; }
.pal .puse:hover { filter: brightness(1.1); }
.pal .pkbd { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 4px; background: color-mix(in srgb, #fff 18%, transparent); }
.rstatus .spacer { flex: 1; }
.rstatus .warn { font-size: 11px; }
.knobwide.rejected .rstatus { color: var(--down); }
/* «какое правило ждёт» под статусом позиции: приглушённо; держится — тревожным, оно вот-вот уйдёт */
.rnext { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.rnext.ready { color: var(--warn); font-weight: 600; }
/* список правил — на всю ширину карточки раздела и до её низа: строки через линии, как у оболочки макета */
.knobwide { margin: 0 calc(-1 * var(--s16)) 8px; border-bottom: 1px solid var(--rb-line); }
/* ручки после таблицы правил (потолок размера и т.п.) — отделены линией и воздухом */
.knobwide + .knob { margin-top: 6px; }
.knobwide .rules { border-top: 1px solid color-mix(in srgb, var(--text-1) 10%, transparent); }
.setgroup:last-child .knobwide { margin-bottom: calc(-1 * var(--s12)); }
.setgroup:last-child .knobwide .rstatus { border-bottom: 0; }

/* ── фандинг отправителя (05.09): мост → сеть значками у адреса, подпись «chainName · age» ── */
.funding { display: inline-flex; align-items: center; gap: 4px; margin-left: 6px; vertical-align: middle; text-decoration: none; color: var(--text-2); font-size: 10.5px; }
.funding img { width: 14px; height: 14px; border-radius: 3px; display: block; }
.funding .fword { font-size: 10px; padding: 0 4px; border-radius: 3px; background: var(--ctl); color: var(--text-2); }
.funding:hover { color: var(--accent); text-decoration: none; }
/* кто платил (direct): значок семантический, наш; колпак у deployer — тот же, что у доли дева */
.funding .fkind { display: inline-flex; align-items: center; color: var(--text-2); }
.funding .fkind.deployer { color: var(--warn); }
/* строковое поле со списком подсказок — свой список в стиле меню кебаба (нативный datalist браузер рисует
   по-своему и ставит вторую стрелку); шеврон — кнопка «весь список» */
.rctl.rpick { overflow: visible; }
.rctl.rpick input { padding-right: 26px; }
.rpickbtn { position: absolute; right: 2px; top: 2px; width: 24px; height: 26px; border: 0; background: transparent; color: var(--text-2); cursor: pointer; display: grid; place-items: center; border-radius: 5px; }
.rpickbtn:hover { background: var(--ctl-hover); color: var(--text-1); }
/* список подсказок — порталом в body, `position: fixed` под полем (или над ним — `.up`); карточка правила его не режет */
.rmenu.rsuggest { position: fixed; right: auto; z-index: 200; max-height: 240px; overflow: auto; box-sizing: border-box; }
.rmenu.rsuggest .ritem.on { background: var(--ctl); }
.rmenu.rsuggest .ritem.rany { color: var(--text-2); }
/* чипы: вложенная коробка подсказок сидит внутри коробки чипов без своей рамки */
.rctl.rchips .rctl.rpick { flex: 1 1 80px; min-width: 80px; height: 24px; border: 0; background: transparent; box-shadow: none; }
.rctl.rchips .rctl.rpick input { height: 24px; padding: 0 22px 0 2px; }
.rctl.rchips .rpickbtn { top: 0; height: 24px; }

/* квота лаунча (handoff-quotes, 06.09): значок из манифеста рядом с тикером; нет значка — тикер словом; не в реестре — тревожно */
.qmark { display: inline-block; vertical-align: -3px; margin-left: 5px; border-radius: 50%; cursor: help; }
.qmark.word { font-size: 9.5px; padding: 0 4px; border-radius: 3px; background: var(--ctl); color: var(--text-2); vertical-align: 1px; line-height: 14px; }
.qmark.unknown { outline: 1px solid var(--warn); }
.qmark.word.unknown { color: var(--warn); outline: none; background: color-mix(in srgb, var(--warn) 14%, transparent); }
/* панель маршрутов */
.routes .cmdhead .dim { font-weight: 400; text-transform: none; letter-spacing: 0; }
.routes .note.bad { color: var(--down); }
.routes .tablewrap { margin-top: var(--s8); overflow-x: auto; }
.routes .rtable { width: 100%; border-collapse: collapse; font-size: 12px; }
.routes .rtable th { text-align: left; font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); font-weight: 600; padding: 4px 8px; border-bottom: 1px solid var(--base-3); }
.routes .rtable td { padding: 4px 8px; border-bottom: 1px solid color-mix(in srgb, var(--base-3) 60%, transparent); white-space: nowrap; }
.routes .rtable th.num, .routes .rtable td.num { text-align: right; font-variant-numeric: tabular-nums; }
.routes .rtable td.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; }
.routes .rtable tr.stale td { color: var(--text-2); }
.routes .rtable .bad, .routes .rtable tr.stale td.bad { color: var(--down); }
.routes .qcell { display: inline-flex; align-items: center; gap: 6px; cursor: help; }
.routes .qcell .qmark { margin: 0; }

/* List tables: identical column headers (Tasks / Limits / Wallets / Team) */
#root .tasks-table > thead > tr > th,
#root .tasks-table .tt-h {
  font-size: 11px;
  font-weight: 500;
  line-height: 18px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-2);
  padding: 12px 14px;
  vertical-align: middle;
  white-space: nowrap;
  background: var(--base-2);
  border-bottom: 1px solid var(--base-3);
}
#root .tasks-table > thead > tr > th.sticky-type,
#root .tasks-table .tt-h.sticky-type {
  padding-left: 12px;
  padding-right: 8px;
  text-align: center;
  width: 44px;
}
#root .tasks-table > thead > tr > th.lo-num,
#root .tasks-table .tt-h.lo-num {
  text-align: center;
  padding-left: 8px;
  padding-right: 8px;
}

/* List checkboxes: fixed 14px, absolute — do not drive row/header height */
#root .tasks-table .sticky-type input.row-check[type=checkbox] {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 14px;
  height: 14px;
  min-width: 14px;
  min-height: 14px;
  max-width: 14px;
  max-height: 14px;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  accent-color: var(--text-1);
  box-shadow: none;
}
