/* Атрибут hidden обязан побеждать любой display из класса. Без этого правила
   строка с `display: flex` остаётся на экране, хотя код её «спрятал» - на этом
   уже попались скрытые поля конструктора cron. */
[hidden] { display: none !important; }

/* Раздел «Полезные штучки».
   Опирается на переменные из main.css: свой файл нужен только ради разметки
   инструментов, палитра и типографика общие с сайтом. */

.to-hub, .to-tool { max-width: 62rem; }

.to-shell-line {
  font-family: var(--font-mono); font-size: .9rem; color: var(--text-muted);
  margin: 1.4rem 0 .6rem;
}

/* Список утилит - как каталог в терминале: имя, описание, стрелка. */
.to-dir { padding: .4rem; }
.to-entry {
  /* Четвёртая колонка - метки категорий. Без неё они уезжали на вторую
     строку сетки и растягивали карточку вдвое; ширина фиксированная, а
     не auto, иначе описание у каждой строки своей ширины. */
  display: grid; grid-template-columns: 10rem 1fr 11rem 2rem; align-items: baseline;
  gap: .6rem; padding: .9rem 1rem; border-radius: var(--radius-md);
  text-decoration: none; color: inherit; transition: background .15s ease;
}
.to-entry:hover { background: var(--accent-soft); text-decoration: none; }
.to-entry-name { font-family: var(--font-mono); font-weight: 600; color: var(--accent); }
.to-entry-desc { color: var(--text-muted); font-size: .95rem; }
.to-entry .hub-chips { margin: 0; justify-content: flex-end; }
.to-entry-meta { font-family: var(--font-mono); color: var(--accent); text-align: right; }

.to-crumbs { font-family: var(--font-mono); font-size: .9rem; margin-bottom: 1rem; }

.to-panel { padding: 1.2rem 1.4rem; margin-top: 1rem; }
.to-panel-text { line-height: 1.65; }
.to-h2 { margin: 0 0 .6rem; font-size: 1.15rem; }
.to-list { margin: 0; padding-left: 1.1rem; }
.to-list li { margin: .35rem 0; }

.to-label {
  display: block; font-family: var(--font-mono); font-size: .82rem;
  color: var(--text-muted); margin-bottom: .4rem;
}

/* Список паролей: у каждого своя строка и своя кнопка копирования, потому что
   копируют их по одному - «выдели нужную строку в общем поле» это работа,
   которую машина должна делать сама. */
.pw-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .4rem; }
.pw-item {
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .5rem .5rem .8rem;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface);
}
.pw-item:hover { border-color: var(--accent); }
.pw-value {
  flex: 1 1 auto; font-family: var(--font-mono); font-size: 1.05rem;
  word-break: break-all; user-select: all;   /* один клик выделяет пароль целиком */
}
.pw-value:focus { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }
.pw-item-copy {
  flex: 0 0 auto; padding: .3rem .7rem;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted);
  font: inherit; font-size: .82rem; font-family: var(--font-mono); cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.pw-item-copy:hover { border-color: var(--accent); color: var(--accent); }
.pw-item-copy:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pw-item-copy.is-done { border-color: #1f9254; color: #1f9254; background: rgba(31,146,84,.1); }
[data-theme="dark"] .pw-item-copy.is-done { border-color: #6ddf9f; color: #6ddf9f; background: rgba(109,223,159,.12); }

.to-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin-top: .9rem; }
.to-hint { font-family: var(--font-mono); font-size: .8rem; color: var(--text-muted); }
.to-note { color: var(--text-muted); font-size: .88rem; margin: .8rem 0 0; }
.to-hub-note { margin-top: 1.2rem; }

.to-copy {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .5rem .9rem; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: transparent; color: var(--text); font: inherit; font-size: .9rem; cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.to-copy:hover { border-color: var(--accent); color: var(--accent); }
.to-copy.is-done { border-color: #1f9254; color: #1f9254; background: rgba(31, 146, 84, .1); }
[data-theme="dark"] .to-copy.is-done { border-color: #6ddf9f; color: #6ddf9f; background: rgba(109, 223, 159, .12); }

/* ---------- генератор паролей ---------- */

.pw-row { display: flex; flex-wrap: wrap; align-items: center; gap: .8rem; margin-bottom: .9rem; }
.pw-row .to-label { margin-bottom: 0; min-width: 9rem; }
.pw-range { flex: 1 1 16rem; accent-color: var(--accent); }
.pw-number { width: 5rem; padding: .4rem .5rem; border-radius: var(--radius-sm); }

.pw-sets { border: none; padding: 0; margin: .4rem 0 0; display: flex; flex-wrap: wrap; gap: .6rem 1.2rem; }
.pw-sets legend { padding: 0; }
.pw-check { display: inline-flex; align-items: center; gap: .4rem; font-size: .92rem; cursor: pointer; }
/* Галочки и переключатели - в цвет темы, иначе браузер рисует их своим синим. */
.pw-check input, .chmod-grid input, .to-mode-options input { accent-color: var(--accent); cursor: pointer; }
.pw-check code { font-size: .82rem; color: var(--text-muted); }

.pw-error { color: #d94b4b; font-size: .9rem; margin: .7rem 0 0; }

.pw-strength { display: flex; flex-wrap: wrap; align-items: baseline; gap: .8rem; }
.pw-bits { font-family: var(--font-mono); font-size: 1.1rem; font-weight: 600; }
.pw-verdict { font-family: var(--font-mono); font-size: .9rem; }
.pw-crack { color: var(--text-muted); font-size: .88rem; }

.pw-meter {
  height: 6px; border-radius: 999px; background: var(--border);
  margin-top: .7rem; overflow: hidden;
}
.pw-meter-fill { display: block; height: 100%; width: 0; transition: width .2s ease, background .2s ease; }

/* Цвет говорит то же, что и слово рядом: полагаться на один цвет нельзя -
   дальтонизм и чёрно-белая печать существуют. */
.pw-meter-fill.is-weak,   .pw-verdict.is-weak   { background: #d94b4b; }
.pw-meter-fill.is-fair,   .pw-verdict.is-fair   { background: #e0a13a; }
.pw-meter-fill.is-good,   .pw-verdict.is-good   { background: #3aa4e0; }
.pw-meter-fill.is-strong, .pw-verdict.is-strong { background: #1f9254; }
.pw-verdict { background: none !important; }
.pw-verdict.is-weak   { color: #d94b4b; }
.pw-verdict.is-fair   { color: #b9791f; }
.pw-verdict.is-good   { color: #2b7fb0; }
.pw-verdict.is-strong { color: #1f9254; }
[data-theme="dark"] .pw-verdict.is-fair { color: #e0a13a; }
[data-theme="dark"] .pw-verdict.is-good { color: #6cc0f0; }
[data-theme="dark"] .pw-verdict.is-strong { color: #6ddf9f; }

@media (max-width: 640px) {
  .to-entry { grid-template-columns: 1fr; gap: .25rem; }
  /* В одну колонку метки прижимать вправо не к чему. */
  .to-entry .hub-chips { justify-content: flex-start; margin-top: .3rem; }
  .pw-item { flex-wrap: wrap; }
  .pw-item-copy { margin-left: auto; }
  .to-entry-meta { display: none; }
  .pw-row .to-label { min-width: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .pw-meter-fill, .to-copy, .to-entry, .pw-item-copy { transition: none; }
}


/* ---------- общие элементы утилит ---------- */

/* Поля ввода раздела - один облик на все виды. Раньше textarea оставалась
   системной (белый прямоугольник с чёрным текстом посреди тёмной страницы):
   класс на ней стоял, а правила для него не существовало. Поэтому перечислены
   все элементы разом - добавить поле и забыть про стиль больше нельзя. */
.to-input,
.to-output,
.to-select,
.pw-number {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-mono);
  transition: border-color .15s ease, box-shadow .15s ease;
}

.to-input,
.to-output {
  width: 100%;
  padding: .6rem .8rem;
  font-size: 1rem;
}

/* Многострочное поле: те же отступы и рамка, но с ручкой изменения размера по
   вертикали - токены и JSON бывают длиннее четырёх строк. */
.to-output {
  display: block;
  resize: vertical;
  min-height: 4.5rem;
  line-height: 1.5;
  font-size: .92rem;
}

/* Поле вывода не редактируют - приглушённый фон говорит об этом раньше, чем
   человек попробует туда напечатать. */
.to-output[readonly] {
  background: var(--bg-soft);
  color: var(--text-muted);
}

.to-input::placeholder,
.to-output::placeholder { color: var(--text-muted); opacity: .75; }

.to-input:focus,
.to-output:focus,
.to-select:focus,
.pw-number:focus {
  border-color: var(--accent);
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.to-input-inline { width: auto; min-width: 12rem; flex: 0 1 auto; }

.to-select {
  padding: .45rem .6rem;
  font-family: var(--font-sans);
  font-size: .92rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

/* Вкладки режимов: три-четыре штуки, поэтому просто ряд кнопок, а не
   выпадающий список - выбор виден целиком. */
.to-tabs { display: flex; flex-wrap: wrap; gap: .4rem; margin: 1rem 0 0; }
.to-tab {
  padding: .45rem .9rem; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: transparent; color: var(--text-muted);
  font: inherit; font-size: .9rem; font-family: var(--font-mono); cursor: pointer;
}
.to-tab:hover { border-color: var(--accent); color: var(--accent); }
.to-tab.is-active { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

.to-mode-options { display: flex; flex-wrap: wrap; gap: .6rem 1.2rem; margin: .8rem 0; }

/* Готовые примеры: нажал - подставилось. Пустое поле в утилите всегда хуже
   заполненного: по примеру сразу понятен ожидаемый формат. */
.to-presets { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-top: .8rem; }
.to-chip {
  padding: .25rem .6rem; border: 1px dashed var(--border); border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted);
  font-family: var(--font-mono); font-size: .8rem; cursor: pointer;
}
.to-chip:hover { border-style: solid; border-color: var(--accent); color: var(--accent); }

.to-table { width: 100%; border-collapse: collapse; font-size: .93rem; }
.to-table td { padding: .35rem .5rem; border-bottom: 1px solid var(--border); vertical-align: top; }
.to-table tr:last-child td { border-bottom: none; }
.to-cell-key { color: var(--text-muted); white-space: nowrap; }
.to-cell-mono, .to-cell-raw { font-family: var(--font-mono); }
.to-cell-raw { color: var(--accent); }

.to-pre {
  margin: .6rem 0 0; padding: .7rem .9rem; border-radius: var(--radius-md);
  background: var(--bg-soft); border: 1px solid var(--border);
  font-family: var(--font-mono); font-size: .85rem; overflow-x: auto;
}

.to-runs { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; }
.to-run { display: flex; flex-wrap: wrap; gap: .8rem; font-family: var(--font-mono); font-size: .9rem; }
.to-run-rel { color: var(--text-muted); }

.cron-human { font-size: 1.05rem; margin: 0 0 .8rem; }

.cidr-verdict, .jwt-status { font-family: var(--font-mono); font-size: .9rem; }
.cidr-verdict.is-strong, .jwt-status.is-valid { color: #1f9254; }
.cidr-verdict.is-fair, .jwt-status.is-early { color: #b9791f; }
.cidr-verdict.is-weak, .jwt-status.is-expired { color: #d94b4b; }
.jwt-status.is-unknown { color: var(--text-muted); }
[data-theme="dark"] .cidr-verdict.is-strong, [data-theme="dark"] .jwt-status.is-valid { color: #6ddf9f; }
[data-theme="dark"] .cidr-verdict.is-fair, [data-theme="dark"] .jwt-status.is-early { color: #e0a13a; }

.hash-name { flex: 0 0 5.5rem; font-family: var(--font-mono); font-size: .82rem; color: var(--text-muted); }
.hash-value { font-size: .85rem; }

.pw-notes { margin-top: .8rem; }
.pw-notes li { margin: .3rem 0; }

@media (max-width: 640px) {
  .to-input-inline { width: 100%; min-width: 0; }
  .hash-name { flex-basis: 100%; }
  .to-table { font-size: .85rem; }
}

/* Разбор чужого пароля на куски: видно, за что снята оценка. */
.pw-parts {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: .9rem;
}
.pw-part {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  padding: .4rem .6rem;
  border-radius: .5rem;
  border: 1px solid var(--border);
  background: var(--bg-soft);
}
.pw-part code {
  font-size: .95rem;
  word-break: break-all;
}
.pw-part small {
  font-size: .72rem;
  color: var(--muted);
}
/* Цвета те же, что у вердикта шкалы: красный - предсказуемый кусок,
   зелёный - тот, который правда придётся перебирать. */
.pw-part.is-weak { border-color: #d94b4b; }
.pw-part.is-weak small { color: #d94b4b; }
.pw-part.is-ok { border-color: #1f9254; }
[data-theme="dark"] .pw-part.is-weak small { color: #ef7d7d; }
.pw-parts .to-note {
  flex-basis: 100%;
  margin: .2rem 0 0;
}

/* Конструктор cron: строка настройки, время «ЧЧ:ММ» и готовое выражение. */
.cron-row {
  display: flex;
  align-items: center;
  gap: .6rem;
  margin-top: .7rem;
  flex-wrap: wrap;
}
.cron-row .to-label { margin: 0; }
.cron-time {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
}
.cron-result {
  display: flex;
  align-items: center;
  gap: .6rem;
  margin-top: 1rem;
  flex-wrap: wrap;
}
.cron-expr {
  flex: 1 1 12rem;
  padding: .55rem .7rem;
  border-radius: var(--radius-md);
  background: var(--code-bg);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 1.05rem;
  word-break: break-all;
}
/* Раскрытие сокращения: это ответ на «а в какой именно день @weekly?», и он
   должен читаться раньше самой фразы. */
.cron-alias {
  margin: 0 0 .4rem;
  font-size: .85rem;
  color: var(--accent);
  font-family: var(--font-mono);
}

/* Результат подбора: строка-ответ с кнопкой копирования. */
.cidr-result {
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
  margin: 1rem 0 .3rem;
}

/* Сетка прав: заголовки колонок мелкие, чекбоксы по центру ячейки. */
.chmod-grid th {
  font-size: .78rem;
  font-weight: 500;
  color: var(--text-muted);
  text-align: center;
  padding: .3rem .4rem;
}
.chmod-grid td { text-align: center; }
.chmod-grid td.to-cell-key { text-align: left; }

/* Поле года шире прочих: четыре знака в узкой ячейке обрезаются. */
.pw-number-wide { width: 5.5rem; }

/* Предупреждение о неровном шаге: заметное, но не тревожное - выражение верное,
   просто значит не то, что человек думает. */
.cron-warnings { margin: .6rem 0 0; }
.cron-warnings li { color: #b9791f; }
[data-theme="dark"] .cron-warnings li { color: #e0a13a; }
.cron-warn { color: #b9791f; }
[data-theme="dark"] .cron-warn { color: #e0a13a; }

/* Пояснение про setuid/setgid/sticky - предупреждающего тона: это биты, из-за
   которых файл ведёт себя не так, как ожидает большинство. */
.chmod-special { margin: .6rem 0 0; }
.chmod-special li { color: #b9791f; }
.chmod-special li.to-note { color: var(--text-muted); }
[data-theme="dark"] .chmod-special li { color: #e0a13a; }
[data-theme="dark"] .chmod-special li.to-note { color: var(--text-muted); }

/* ===================================================== тест способностей */
/* Задание показывается по одному, поэтому вся страница - одна колонка с
   крупной фигурой и шестью вариантами. Ширина ограничена: матрица в ширину
   экрана читается хуже, а не лучше. */
.iq-h2 { font-size: 1.05rem; margin: 0 0 .6rem; }
.iq-h3 { font-size: .95rem; margin: 1.1rem 0 .4rem; }
#iq-tool .iq-list { margin: .4rem 0 .9rem; padding-left: 1.1rem; }
#iq-tool .iq-list li { margin-bottom: .4rem; }
.iq-src { font-size: .84rem; color: var(--text-muted); }

.iq-progress { margin-bottom: 1rem; }
.iq-progress-bar {
  height: 5px; border-radius: 3px; background: var(--border); overflow: hidden;
}
.iq-progress-bar span {
  display: block; height: 100%; background: var(--accent);
  transition: width .25s ease;
}
.iq-prompt { font-weight: 600; margin: .2rem 0 .9rem; }
/* Фокус переводится сюда программно после каждого ответа - рамка тут была бы
   шумом. У кнопок вариантов фокус, наоборот, виден: по ним ходят с клавиатуры. */
.iq-prompt:focus { outline: none; }

.iq-stimulus { display: flex; justify-content: center; margin-bottom: 1.2rem; }
.iq-stimulus .iq-fig { width: 100%; max-width: 22.5rem; height: auto; }
.iq-target { width: 100%; max-width: 15rem; }
/* Ряд фигур и панели со сгибами шире матрицы: они вытянуты по горизонтали, и
   в колонке под матрицу клетки становятся с ноготь. */
.iq-wide { width: 100%; display: flex; justify-content: center; }
.iq-stimulus .iq-wide .iq-fig { max-width: 34rem; }
.iq-series {
  font-family: var(--font-mono); font-size: 1.35rem; letter-spacing: .04em;
  text-align: center; margin: .6rem 0;
}
.iq-series-gap {
  display: inline-block; margin-left: 1.1rem; padding: 0 .55rem;
  border-radius: var(--radius-md); background: var(--accent-soft); color: var(--accent);
}

.iq-options {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .7rem;
}
.iq-option {
  position: relative; padding: .55rem; min-height: 6rem; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text);
}
.iq-option:hover { border-color: var(--accent); }
.iq-option:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.iq-option .iq-fig { width: 100%; max-width: 7rem; height: auto; }
.iq-option-no {
  position: absolute; top: .3rem; left: .45rem;
  font-family: var(--font-mono); font-size: .72rem; color: var(--text-muted);
}
.iq-series-opt { font-family: var(--font-mono); font-size: 1.25rem; }
.iq-hint { margin-top: .9rem; }

/* --------------------------------------------------------- результат */
.iq-score {
  display: flex; flex-wrap: wrap; align-items: center; gap: 1.6rem;
  margin: .4rem 0 1.2rem;
}
.iq-score-main { display: flex; flex-direction: column; }
.iq-score-num { font-size: 3.2rem; line-height: 1; font-weight: 700; color: var(--accent); }
.iq-score-cap { font-size: .78rem; color: var(--text-muted); margin-top: .2rem; }
.iq-score-ci, .iq-score-pc { font-size: .84rem; color: var(--text-muted); }
.iq-score-ci b, .iq-score-pc b { font-size: 1.15rem; color: var(--text); }

.iq-scale { margin: 1rem 0 1.3rem; }
.iq-scale-track {
  position: relative; height: 10px; border-radius: 5px;
  background: linear-gradient(90deg, var(--border), var(--accent-soft), var(--border));
}
.iq-scale-band {
  position: absolute; top: 0; height: 100%; border-radius: 5px;
  background: var(--accent); opacity: .35;
}
.iq-scale-dot {
  position: absolute; top: -3px; width: 16px; height: 16px; margin-left: -8px;
  border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 3px var(--surface);
}
.iq-scale-marks { position: relative; height: 1.2rem; margin-top: .35rem; }
.iq-scale-mark {
  position: absolute; transform: translateX(-50%);
  font-family: var(--font-mono); font-size: .72rem; color: var(--text-muted);
}
.iq-warn {
  padding: .7rem .9rem; border-left: 3px solid var(--accent);
  background: var(--accent-soft); border-radius: var(--radius-md);
  margin: 1rem 0;
}
.iq-table { border-collapse: collapse; margin: .4rem 0 .6rem; }
.iq-table td { padding: .25rem .9rem .25rem 0; }
.iq-table td:last-child { font-family: var(--font-mono); color: var(--text-muted); }

@media (max-width: 640px) {
  .iq-options { grid-template-columns: repeat(2, 1fr); }
  .iq-stimulus .iq-wide .iq-fig { max-width: 100%; }
  .iq-score { gap: 1rem; }
  .iq-score-num { font-size: 2.6rem; }
  .iq-series { font-size: 1.1rem; }
}

/* Грани кубиков. Подложка непрозрачная - иначе дальние кубики просвечивают
   сквозь ближние. Сама заливка через currentColor, поэтому фигура одинаково
   читается в обеих темах. */
.iq-face-base { fill: var(--surface); stroke: none; }
.iq-face {
  fill: currentColor; stroke: currentColor;
  stroke-width: 1.1; stroke-linejoin: round;
}
/* Разница между гранями должна быть ЗАМЕТНОЙ, иначе объём не читается и
   фигура выглядит плоской сеткой треугольников. Три сильно разных уровня. */
.iq-face-top { fill-opacity: .06; }
.iq-face-left { fill-opacity: .28; }
.iq-face-right { fill-opacity: .50; }

/* Ряд цифр в задании на память: крупно и в одном месте, чтобы не приходилось
   вести глазами - иначе меряется не память, а траектория взгляда. */
.iq-span-digits {
  height: 5.5rem; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 3.4rem; font-weight: 600;
  color: var(--accent); letter-spacing: .05em;
}
.iq-span-input {
  font-family: var(--font-mono); font-size: 1.3rem; letter-spacing: .12em;
  max-width: 16rem;
}

/* --- Калькулятор Factorio ------------------------------------------------ */
/* Форма в несколько колонок: полей много, и в один столбец они дают простыню
   на весь экран, из-за которой результат уезжает за сгиб. */
.fa-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: .8rem 1rem;
}
.fa-field { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
/* Название предмета вместе с английским именем в одну колонку не влезает и
   обрезается многоточием - а искать предмет надо именно по имени. */
.fa-field-wide { grid-column: span 2; }
.fa-field-check { justify-content: flex-end; }
.fa-field-check .to-label { display: flex; align-items: center; gap: .45rem; cursor: pointer; }
.fa-inline { display: flex; gap: .4rem; }
.fa-inline .pw-number { flex: 1 1 5rem; min-width: 0; }
.fa-inline .to-select { flex: 1 1 7rem; min-width: 0; }

.fa-choices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: .6rem 1rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}
.fa-choice { display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.fa-choice-item { font-size: .82rem; color: var(--muted); font-family: var(--font-mono); }

.fa-result { margin-top: 1rem; }
.fa-h { font-size: 1.05rem; margin: 1.4rem 0 .6rem; }
.fa-error { color: var(--danger, #e5484d); margin: 1rem 0; }
.fa-note { color: var(--muted); font-size: .9rem; margin: .4rem 0 .8rem; line-height: 1.55; }

/* Карточки итога: четыре числа, ради которых калькулятор и открывают. */
.fa-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: .7rem;
}
.fa-card {
  display: flex; flex-direction: column; gap: .15rem;
  padding: .7rem .85rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}
.fa-card-label { font-size: .78rem; color: var(--muted); text-transform: lowercase; }
.fa-card-value { font-size: 1.35rem; font-weight: 600; font-family: var(--font-mono); }
.fa-card-note { font-size: .78rem; color: var(--muted); }

.fa-scroll { overflow-x: auto; }
.fa-table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.fa-table th {
  text-align: left; font-weight: 500; font-size: .78rem; color: var(--muted);
  padding: .4rem .6rem; border-bottom: 1px solid var(--border); white-space: nowrap;
}
.fa-table td { padding: .45rem .6rem; border-bottom: 1px solid var(--border-soft, var(--border)); }
.fa-table tbody tr:last-child td { border-bottom: none; }
.fa-cell-num { font-family: var(--font-mono); white-space: nowrap; }
.fa-name-ru { line-height: 1.25; }
/* Английское имя рядом с русским - не украшение: половина играет на английском,
   и без него предмет не найти ни в игре, ни в чужом гайде. */
.fa-name-en { font-size: .76rem; color: var(--muted); font-family: var(--font-mono); }

@media (max-width: 640px) {
  .fa-field-wide { grid-column: span 1; }
  .fa-summary { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
  .fa-card-value { font-size: 1.15rem; }
}

/* --- Factorio: выбор предмета сеткой иконок ------------------------------ */
.fa-picked { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-bottom: .7rem; }
.fa-current {
  display: flex; align-items: center; gap: .5rem;
  padding: .35rem .7rem .35rem .45rem;
  border: 1px solid var(--accent-soft, var(--border)); border-radius: 999px;
  background: var(--surface);
}
.fa-current-name { font-weight: 600; }
.fa-current-en { font-size: .78rem; color: var(--muted); font-family: var(--font-mono); }
.fa-search { flex: 1 1 12rem; min-width: 0; }

/* Сетка прокручивается: девяносто предметов на весь экран оттеснили бы форму и
   результат за сгиб, а выбор делают один раз. */
.fa-picker {
  max-height: 236px; overflow-y: auto;
  padding: .6rem .7rem; margin-bottom: 1rem;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface);
}
.fa-pick-group + .fa-pick-group { margin-top: .7rem; }
.fa-pick-title {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin-bottom: .35rem;
}
.fa-pick-grid { display: flex; flex-wrap: wrap; gap: .3rem; }
.fa-pick {
  display: flex; align-items: center; gap: .35rem;
  padding: .25rem .5rem .25rem .3rem;
  border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: inherit; cursor: pointer;
  font: inherit; font-size: .84rem; line-height: 1.2;
}
.fa-pick:hover { border-color: var(--border); background: var(--surface-2, var(--bg)); }
.fa-pick.is-active { border-color: var(--accent); background: var(--accent-soft); }
.fa-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fa-pick-name { white-space: nowrap; }

/* --- Factorio: иконки в таблицах ----------------------------------------- */
/* Направление задаём явно: первая версия таблицы была без иконок, и правило с
   колонкой осталось бы в силе - иконка встала бы НАД названием. */
.fa-name { display: flex; flex-direction: row; align-items: center; gap: .45rem; }
.fa-name-text { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.fa-machine { display: inline-flex; align-items: center; gap: .35rem; }

/* --- Factorio: дерево цепочки -------------------------------------------- */
/* Граф со стрелками на этой задаче превращается в паутину: у цепочки из
   пятнадцати рецептов линии пересекаются, и связь «что откуда» теряется.
   Дерево с отступами пересечений не имеет по устройству. */
.fa-tree {
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); padding: .5rem .2rem .5rem 0;
  overflow-x: auto;
}
.fa-tree-row {
  display: flex; align-items: center; gap: .4rem;
  padding: .18rem .8rem .18rem .5rem;
  white-space: nowrap; font-size: .9rem;
}
.fa-tree-row:hover { background: var(--accent-soft); }
.fa-tree-row.is-root { font-weight: 600; }
.fa-tree-rail {
  font-family: var(--font-mono); color: var(--muted);
  white-space: pre; opacity: .7; font-size: .85rem;
}
.fa-tree-name { flex: 0 1 auto; }
/* Поток и машины прижаты к правому краю строки, а не идут сразу за названием:
   иначе числа встают лесенкой по длине названий и их не сравнить глазами. */
.fa-tree-rate {
  margin-left: auto; font-family: var(--font-mono); font-size: .85rem;
  color: var(--muted); min-width: 6.5rem; text-align: right;
}
.fa-tree-machine {
  display: inline-flex; align-items: center; gap: .3rem;
  min-width: 9.5rem; font-size: .85rem;
}
.fa-tree-machine.is-raw { color: var(--muted); }
.fa-tree-count { font-family: var(--font-mono); }
.fa-tree-mname { color: var(--muted); }
.fa-tree-repeat {
  font-size: .74rem; color: var(--muted);
  border: 1px dashed var(--border); border-radius: 999px; padding: 0 .4rem;
}

@media (max-width: 640px) {
  .fa-picker { max-height: 200px; }
  .fa-pick-name { display: none; }
  .fa-pick { padding: .25rem; }
  /* На узком экране ASCII-направляющие уводят строку за экран. Отступ рисуем
     padding-ом по глубине узла, а строке разрешаем перенос: боковой прокрутки
     не остаётся. */
  .fa-tree-rail { display: none; }
  .fa-tree-row {
    font-size: .82rem; gap: .3rem; flex-wrap: wrap; white-space: normal;
    padding-left: calc(.5rem + var(--d, 0) * .55rem);
    border-left: 2px solid var(--border);
  }
  .fa-tree-row.is-root { border-left-color: var(--accent); }
  .fa-tree-rate { min-width: 0; margin-left: auto; }
  .fa-tree-machine { min-width: 0; width: 100%; padding-left: 1.6rem; }
}
.fa-credit { color: var(--muted); font-size: .82rem; margin: 1.2rem 0 0; line-height: 1.5; }

/* Форма разбита на два шага: девять полей подряд читаются как приборная панель
   самолёта, а решений здесь всего два - что нужно и на чём делать. */
.fa-step { display: flex; align-items: baseline; gap: .5rem; margin: 1.2rem 0 .6rem; flex-wrap: wrap; }
.fa-step:first-child { margin-top: 0; }
.fa-step-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.35rem; height: 1.35rem; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  font-size: .8rem; font-weight: 600; font-family: var(--font-mono);
}
.fa-step-title { font-weight: 600; }
.fa-step-hint { color: var(--muted); font-size: .82rem; }
.fa-form-goal { max-width: 26rem; }
/* Галочка дополнения стоит рядом с первым шагом, а не среди настроек машин:
   она меняет весь набор данных, а не одну настройку. */
.fa-sa-toggle {
  margin-left: auto; display: inline-flex; align-items: center; gap: .4rem;
  font-size: .85rem; color: var(--muted); cursor: pointer;
  border: 1px solid var(--border); border-radius: 999px; padding: .2rem .7rem .2rem .5rem;
}
.fa-sa-toggle:has(input:checked) { color: var(--accent); border-color: var(--accent); }
