/* ============================================================================
   Unruin — дизайн-система «Спокойная консоль, в которой цвет — редкость».
   Портирована из design/Unruin - Дизайн-система.dc.html и хай-фай макетов.

   Правила системы:
     · цвет появляется только там, где утверждает факт о данных;
     · зелёный отдан статусу success, поэтому действие — циан;
     · теней нет: глубина только через шкалу поверхностей;
     · моноширинный — тип данных (пути, cron, id, адреса), а не украшение;
     · шаг 4 px, вертикальный ритм 8, рейл 212 px, строка таблицы 44 px;
     · motion: 120 мс на смену состояния, 180 мс на появление слоя.
   ============================================================================ */

/* IBM Plex Sans + Mono, self-hosted (latin + cyrillic) — прод не ходит наружу. */
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/ibm-plex-sans-cyrillic.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/ibm-plex-sans-cyrillic.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/ibm-plex-sans-cyrillic.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/ibm-plex-sans-cyrillic.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:'IBM Plex Sans';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/ibm-plex-sans-400.woff2) format('woff2');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:'IBM Plex Sans';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/ibm-plex-sans-500.woff2) format('woff2');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:'IBM Plex Sans';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/ibm-plex-sans-600.woff2) format('woff2');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:'IBM Plex Sans';font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/ibm-plex-sans-700.woff2) format('woff2');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:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/ibm-plex-mono-400-cyrillic.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/ibm-plex-mono-500-cyrillic.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/ibm-plex-mono-600-cyrillic.woff2) format('woff2');unicode-range:U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/ibm-plex-mono-400.woff2) format('woff2');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:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/ibm-plex-mono-500.woff2) format('woff2');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:'IBM Plex Mono';font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/ibm-plex-mono-600.woff2) format('woff2');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}

/* ---------------------------------------------------------------- токены -- */
:root{
  /* Поверхности — сине-графитовая шкала */
  --bg:#0b0e11;          /* фон полотна, рейл */
  --bg-work:#0f1216;     /* рабочая область */
  --s1:#101418;          /* вложенный фон, шапки таблиц, лог */
  --s2:#14181d;          /* панели, карточки */
  --s3:#191e24;          /* активный пункт рейла, «серьёзные» плашки */
  --line:#1f242b;        /* разделители */
  --line-soft:#191e24;   /* разделители строк внутри таблиц */
  --line-rail:#1a1f25;   /* границы рейла и шапок */
  --border:#2f3742;      /* границы полей и вторичных кнопок */
  --border-out:#262c34;  /* внешняя граница полотна */
  --bar:#232a31;         /* неактивный сегмент полосы */

  /* Текст */
  --text:#dfe4ea;        /* основной */
  --sec:#8b949e;         /* вторичный, пояснения */
  --muted:#5c6570;       /* приглушённый, mono-метки */
  --dim:#3f4750;         /* ярлыки групп, самое тихое */
  --label:#4a525b;       /* caps-ярлык в шапке таблицы */
  --nodata:#2b3138;      /* «нет данных» */

  /* Действие — циан. Единственный не-статусный цвет.
     Никогда не означает «хорошо» — только «здесь можно нажать». */
  --acc:#38bdf8;
  --acc-hi:#7dd3fc;
  --acc-ink:#08131a;

  /* Семантика — 4 сигнала */
  --ok:#22c55e;
  --warn:#f59e0b;
  --err:#ef4444;

  --mono:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
  --sans:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',sans-serif;

  --rail:212px;
  --pad:28px;
}

*{box-sizing:border-box}
html,body{margin:0;padding:0;background:var(--bg);height:100%}
body{font-family:var(--sans);color:var(--text);font-size:13px;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
#app{height:100%}
::selection{background:rgba(56,189,248,.26)}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:#242b34;border-radius:5px;border:2px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:#2f3742;background-clip:padding-box}
::-webkit-scrollbar-track{background:transparent}
button,input,select,textarea{font-family:inherit;font-size:inherit;color:inherit}
a{color:var(--acc);text-decoration:none}
a:hover{color:var(--acc-hi)}

/* Пульс — одна дышащая точка на 5 с. Весь «пульс» продукта. */
@keyframes unruin-breathe{0%,100%{opacity:1}50%{opacity:.34}}
@keyframes unruin-caret{0%,100%{opacity:0}50%{opacity:1}}
@keyframes unruin-layer{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}
@keyframes unruin-fade{from{opacity:0}to{opacity:1}}
@keyframes unruin-pop{from{opacity:0;transform:translate(-50%,-50%) scale(.985)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}
@keyframes unruin-toast{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
@keyframes unruin-spin{to{transform:rotate(360deg)}}

/* ------------------------------------------------------------ типографика -- */
.mono{font-family:var(--mono)}
.t-canvas{font-size:34px;font-weight:600;letter-spacing:-.02em;line-height:1.15}
.t-verdict{font-size:21px;font-weight:600;letter-spacing:-.015em;line-height:1.25}
.t-page{font-size:23px;font-weight:600;letter-spacing:-.02em}
.t-job{font-size:25px;font-weight:600;letter-spacing:-.02em}
.t-screen{font-size:16px;font-weight:600;letter-spacing:-.01em}
.t-card{font-size:13px;font-weight:600}
.t-body{font-size:13px}
.t-note{font-size:11.5px;color:var(--sec);line-height:1.55}
.t-quiet{font-size:11.5px;color:var(--muted);line-height:1.55}
.t-group{font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:var(--dim)}
.t-th{font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--label)}
.sec{color:var(--sec)}
.muted{color:var(--muted)}
.dim{color:var(--dim)}
.ok{color:var(--ok)}
.warn{color:var(--warn)}
.err{color:var(--err)}
.acc{color:var(--acc)}
/* Длинные пути обрезаются: начало и конец информативнее середины. */
.trunc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.pretty{text-wrap:pretty}

/* ------------------------------------------------------------- статусы --- */
/* Фигура несёт состояние даже без цвета: круг — успех, ромб — оговорки,
   квадрат — сбой, обводка — идёт, пунктир — ни разу не шло. */
.dot{flex:none;display:inline-block}
.dot-success{width:9px;height:9px;border-radius:50%;background:var(--ok)}
.dot-partial{width:9px;height:9px;background:var(--warn);transform:rotate(45deg)}
.dot-failed{width:9px;height:9px;background:var(--err)}
.dot-running{width:9px;height:9px;border-radius:50%;border:2px solid var(--acc)}
.dot-never{width:9px;height:9px;border-radius:50%;border:1px dashed var(--muted)}
.dot-unknown{width:9px;height:9px;border-radius:50%;background:var(--nodata)}
.dot-offsite{width:9px;height:9px;background:var(--warn);transform:rotate(45deg);box-shadow:0 0 0 3px rgba(245,158,11,.18)}
.dot-s{width:7px;height:7px}
.dot-s.dot-running{border-width:2px}
.dot-l{width:12px;height:12px}
.dot-l.dot-running{border-width:2px}
.dot-xs{width:6px;height:6px}
.breathe{animation:unruin-breathe 5s ease-in-out infinite}

/* ---------------------------------------------------------------- каркас -- */
.shell{display:flex;height:100%;background:var(--bg-work);overflow:hidden}

.rail{width:var(--rail);flex:none;background:var(--bg);border-right:1px solid var(--line-rail);display:flex;flex-direction:column;padding:20px 0 16px;overflow:hidden}
.rail-brand{padding:0 18px 22px;display:flex;align-items:center;gap:10px}
.rail-mark{width:22px;height:22px;background:var(--ok);border-radius:4px;display:flex;align-items:center;justify-content:center;flex:none}
.rail-mark i{width:8px;height:8px;background:var(--bg);border-radius:1px;display:block}
.rail-name{font-size:14.5px;font-weight:600;letter-spacing:-.01em}
.rail-group{display:flex;flex-direction:column;gap:2px;padding:0 8px}
.rail-sep{margin:22px 18px 14px;border-top:1px solid var(--line-rail)}
.rail-sep.tight{margin:18px 8px 10px}
.rail-caption{padding:0 18px 9px;font-family:var(--mono);font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:var(--dim)}
.rail-item{padding:9px 11px;border-radius:4px;font-size:13px;color:var(--sec);display:flex;align-items:center;justify-content:space-between;gap:9px;cursor:pointer;border:0;background:none;width:100%;text-align:left;transition:background .12s,color .12s}
.rail-item:hover{background:#141a20;color:var(--text)}
.rail-item.is-active{background:var(--s3);color:var(--text)}
.rail-item .cursor{width:3px;height:14px;background:var(--acc);border-radius:2px;margin-left:-4px;flex:none}
.rail-item .count{font-family:var(--mono);font-size:11px;color:var(--muted)}
.rail-jobs{display:flex;flex-direction:column;padding:0 8px;gap:1px;overflow-y:auto;min-height:0}
.rail-job{padding:7px 11px;border-radius:4px;display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--sec);cursor:pointer;border:0;background:none;width:100%;text-align:left;transition:background .12s,color .12s}
.rail-job:hover{background:#141a20;color:var(--text)}
.rail-job.is-active{background:var(--s3);color:var(--text)}
.rail-job span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rail-foot{margin-top:auto;padding:14px 18px 0;display:flex;flex-direction:column;gap:9px}
.rail-pulse{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--muted);font-family:var(--mono);background:none;border:0;padding:0;cursor:pointer;text-align:left}
.rail-pulse:hover{color:var(--sec)}
.rail-version{font-size:11px;color:var(--dim);font-family:var(--mono)}
/* Короткое имя пункта живёт только в нижних вкладках телефона. */
.tab-short{display:none}

.main{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}
.topbar{height:60px;flex:none;border-bottom:1px solid var(--line-rail);display:flex;align-items:center;justify-content:space-between;padding:0 var(--pad);background:var(--bg-work);gap:16px}
.scroll{flex:1;overflow-y:auto;min-height:0}
.page{padding:24px var(--pad) 32px;display:flex;flex-direction:column;gap:20px}

/* ---------------------------------------------------------------- кнопки -- */
.btn{padding:8px 15px;border-radius:4px;border:1px solid transparent;font-size:12.5px;font-weight:500;cursor:pointer;background:none;color:var(--text);white-space:nowrap;transition:background .12s,border-color .12s,color .12s;display:inline-flex;align-items:center;gap:8px;line-height:1.3}
.btn-primary{background:var(--acc);color:var(--acc-ink);font-weight:600}
.btn-primary:hover{background:var(--acc-hi)}
.btn-secondary{border-color:var(--border)}
.btn-secondary:hover{border-color:#3d4653;background:#171c22}
.btn-ghost{color:var(--sec)}
.btn-ghost:hover{color:var(--text);background:#171c22}
.btn-danger{border-color:rgba(239,68,68,.33);color:var(--err)}
.btn-danger:hover{border-color:rgba(239,68,68,.6);background:rgba(239,68,68,.08)}
.btn-lg{padding:9px 16px}
.btn-xl{padding:10px 20px;font-size:13px}
.btn-sm{padding:7px 12px;font-size:12px}
.btn:disabled{background:var(--nodata);color:var(--muted);border-color:transparent;cursor:not-allowed}
.btn:disabled:hover{background:var(--nodata);color:var(--muted)}
.btn-link{background:none;border:0;padding:0;color:var(--acc);font-size:12px;cursor:pointer;text-align:left}
.btn-link:hover{color:var(--acc-hi)}
.btn-link.sm{font-size:11.5px}
.spin{display:inline-block;width:11px;height:11px;border:2px solid rgba(255,255,255,.25);border-top-color:currentColor;border-radius:50%;animation:unruin-spin .7s linear infinite}

/* ------------------------------------------------------------------ поля -- */
.field{display:flex;flex-direction:column;gap:10px}
.field-label{font-size:12.5px;color:var(--sec)}
.input{width:100%;padding:11px 14px;border:1px solid var(--border);border-radius:4px;background:transparent;color:var(--text);font-size:13.5px;transition:border-color .12s,box-shadow .12s}
.input::placeholder{color:var(--muted)}
.input:focus{outline:none;border-color:var(--acc);box-shadow:0 0 0 3px rgba(56,189,248,.13)}
.input.mono{font-family:var(--mono)}
.input.is-error{border-color:var(--err)}
.input-sm{padding:7px 12px;font-size:12.5px}
textarea.input{resize:vertical;min-height:96px;line-height:1.55}
select.input{appearance:none;background-image:linear-gradient(45deg,transparent 50%,#5c6570 50%),linear-gradient(135deg,#5c6570 50%,transparent 50%);background-position:calc(100% - 16px) 52%,calc(100% - 11px) 52%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:34px;cursor:pointer}
select.input option{background:var(--s1);color:var(--text)}
.field-error{font-size:11.5px;color:var(--err)}
.field-hint{font-size:11.5px;color:var(--muted);line-height:1.55}

.check{display:flex;gap:11px;align-items:flex-start;font-size:12.5px;line-height:1.55;cursor:pointer}
.check-box{width:16px;height:16px;border-radius:3px;border:1px solid var(--border);flex:none;margin-top:1px;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;color:transparent;transition:background .12s,border-color .12s}
.check.is-on .check-box{background:var(--acc);border-color:var(--acc);color:var(--acc-ink)}

/* Выбор из плиток: карта источника, пресет расписания, вид хранилища. */
.tile{padding:14px;border:1px solid var(--line);background:var(--s2);border-radius:5px;display:flex;flex-direction:column;gap:4px;cursor:pointer;text-align:left;transition:border-color .12s,background .12s}
.tile:hover{border-color:#333c47}
.tile.is-on{border-color:var(--acc);background:rgba(56,189,248,.06)}
.tile-title{font-size:13.5px;color:var(--text)}
.tile-note{font-size:11.5px;color:var(--muted)}
.tile.is-on .tile-note{color:var(--sec)}
.chip{padding:9px 14px;border:1px solid var(--line);background:var(--s2);border-radius:4px;font-size:12.5px;color:var(--text);cursor:pointer;transition:border-color .12s,background .12s}
.chip:hover{border-color:#333c47}
.chip.is-on{border-color:var(--acc);background:rgba(56,189,248,.06)}

/* ----------------------------------------------------------------- блоки -- */
.panel{background:var(--s2);border:1px solid var(--line);border-radius:6px;display:flex;flex-direction:column;min-width:0}
.panel-pad{padding:18px;gap:14px}
.panel-pad-lg{padding:20px;gap:14px}
.panel-head{padding:14px 18px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;gap:16px;flex:none}
.panel-body{padding:18px;display:flex;flex-direction:column;gap:14px;min-height:0}
.panel-serious{background:var(--s3);border-color:var(--border)}
.panel-ok{border-color:rgba(34,197,94,.17)}
.panel-warn{border-color:rgba(245,158,11,.2)}
.panel-err{border-color:rgba(239,68,68,.33);background:rgba(239,68,68,.05)}
.tint-ok{background:rgba(34,197,94,.04);border:1px solid rgba(34,197,94,.17);border-radius:5px}
.tint-warn{background:rgba(245,158,11,.04);border:1px solid rgba(245,158,11,.2);border-radius:5px}

.kv{display:flex;justify-content:space-between;align-items:center;gap:14px;font-size:12.5px}
.kv .k{color:var(--sec)}
.kv .v{color:var(--text)}
.rowline{display:flex;align-items:baseline;gap:12px;font-size:13px}
.rowline .k{color:var(--sec);flex:none}

/* Вердикт парка: деградация занимает место и говорит предложением. */
.verdict{border-radius:6px;padding:22px 24px;display:flex;align-items:center;gap:22px;flex:none;border:1px solid var(--line)}
.verdict-ok{border-color:rgba(34,197,94,.2);background:linear-gradient(180deg,rgba(34,197,94,.05),rgba(34,197,94,.02))}
.verdict-warn{border-color:rgba(245,158,11,.2);background:linear-gradient(180deg,rgba(245,158,11,.06),rgba(245,158,11,.02))}
.verdict-err{border-color:rgba(239,68,68,.25);background:linear-gradient(180deg,rgba(239,68,68,.07),rgba(239,68,68,.02))}
.verdict-sign{width:38px;height:38px;flex:none;display:flex;align-items:center;justify-content:center}
.verdict-sign .glyph-ok{width:22px;height:22px;border-radius:50%;background:var(--ok)}
.verdict-sign .glyph-warn{width:22px;height:22px;background:var(--warn);transform:rotate(45deg);border-radius:2px}
.verdict-sign .glyph-err{width:22px;height:22px;background:var(--err);border-radius:2px}
.tally{display:flex;gap:1px;background:var(--line-rail);border-radius:4px;overflow:hidden;flex:none}
.tally-cell{background:var(--bg);padding:11px 17px;text-align:center;min-width:74px;border:0;cursor:pointer;transition:background .12s}
.tally-cell:hover{background:#101418}
.tally-cell.is-on{background:#151b21}
.tally-num{font-size:21px;font-weight:600;line-height:1.1}
.tally-cap{font-size:10px;color:var(--muted);font-family:var(--mono);margin-top:3px}

/* «Требует внимания» — последствие крупно, причина мельче, действие справа. */
.attn{background:var(--s2);border:1px solid var(--line);border-radius:4px;padding:16px 20px;display:flex;align-items:center;gap:20px}
.attn-err{border-left:3px solid var(--err)}
.attn-warn{border-left:3px solid var(--warn)}
.attn-acc{border-left:3px solid var(--acc)}
.attn-title{font-size:14.5px;font-weight:600;letter-spacing:-.005em}
.attn-why{font-size:12.5px;color:var(--sec);line-height:1.5}

/* Таблицы: строка 44 px, разделители тише границ панели. */
.tbl{display:flex;flex-direction:column;min-width:0}
.tbl-row{display:grid;align-items:center;gap:16px;padding:11px 18px;border-bottom:1px solid var(--line-soft);font-size:12.5px;min-height:44px}
.tbl-row:last-child{border-bottom:0}
.tbl-row.is-click{cursor:pointer;transition:background .12s}
.tbl-row.is-click:hover{background:#171c22}
.tbl-row.tint-failed{background:rgba(239,68,68,.04)}
.tbl-row.tint-partial{background:rgba(245,158,11,.03)}
.tbl-row.is-sel{background:rgba(56,189,248,.04);border-left:3px solid var(--acc);padding-left:15px}
.tbl-foot{padding:12px 18px;border-top:1px solid var(--line);display:flex;justify-content:space-between;align-items:center;font-size:11.5px;color:var(--muted)}

/* Полоса последних запусков: 12 засечек, ширина делится поровну. */
.spark{display:flex;gap:3px;min-width:0}
.spark i{flex:1;height:22px;border-radius:2px;display:block;min-width:2px}
.spark-sm i{height:5px;border-radius:3px}
.sp-success{background:var(--ok)}
.sp-partial{background:var(--warn)}
.sp-failed{background:var(--err)}
.sp-running{border:1px solid var(--acc);background:rgba(56,189,248,.1)}
.sp-none{background:var(--bar)}

/* Маршрут копии: откуда → пишем сюда → обязательная → по возможности. */
.route{display:flex;align-items:stretch;gap:10px;min-width:0}
.route-node{flex:1;background:var(--s2);border:1px solid var(--line);border-radius:5px;padding:14px;display:flex;flex-direction:column;gap:6px;min-width:0}
.route-node.is-src{width:132px;flex:none}
.route-node.is-live{border-color:rgba(34,197,94,.2)}
.route-node.is-best{border-style:dashed;border-color:var(--border)}
.route-node.is-down{border-color:rgba(245,158,11,.33)}
.route-role{font-size:10.5px;font-family:var(--mono);color:var(--sec)}
.route-name{font-size:12.5px}
.route-where{font-size:11px;color:var(--muted);font-family:var(--mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.route-arrow{flex:none;display:flex;align-items:center;color:var(--border);font-size:14px}
.route-arrow.labelled{flex-direction:column;justify-content:center;gap:2px;color:var(--muted)}
.route-arrow.labelled span{font-size:10px}

/* Лог: моноширинный, метки времени тише строк, каретка живёт. */
.log{flex:1;background:var(--bg);border:1px solid var(--line);border-radius:6px;padding:16px 18px;font-family:var(--mono);font-size:12px;line-height:1.95;color:var(--sec);overflow-y:auto;min-height:0;white-space:pre-wrap;word-break:break-word}
.log-time{color:var(--dim)}
.log-live{color:var(--acc)}
.log-caret{animation:unruin-caret 1.1s steps(1) infinite}
.code{background:var(--s1);border:1px solid var(--line);border-radius:4px;padding:12px 14px;font-family:var(--mono);font-size:11.5px;line-height:1.8;color:var(--sec);white-space:pre-wrap;word-break:break-word;overflow-x:auto}
.code-cm{color:var(--dim)}

/* Шаги прогресса первого запуска. */
.stage{flex:1;display:flex;flex-direction:column;gap:7px;min-width:0}
.stage-head{display:flex;align-items:center;gap:9px;font-size:12.5px}
.stage-mark{width:16px;height:16px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600}
.stage-done .stage-mark{background:var(--ok);color:var(--acc-ink)}
.stage-live{color:var(--acc)}
.stage-live .stage-mark{border:2px solid var(--acc)}
.stage-wait{color:var(--muted)}
.stage-wait .stage-mark{border:1px solid var(--border)}
.stage-bar{height:3px;background:var(--bar);border-radius:2px;overflow:hidden}
.stage-bar i{display:block;height:3px;border-radius:2px;background:var(--acc);transition:width .18s linear}
.stage-done .stage-bar{background:var(--ok)}

/* --------------------------------------------------------------- слои ----- */
/* Слой поверх слоя, не переход: видно, что мы никуда не ушли. */
.veil{position:fixed;inset:0;background:#07090b;opacity:.72;z-index:40;animation:unruin-fade .18s ease-out}
.layer{position:fixed;top:0;right:0;bottom:0;background:var(--bg-work);border-left:1px solid var(--border-out);display:flex;flex-direction:column;z-index:41;animation:unruin-layer .18s ease-out;max-width:100vw}
.layer-1{width:640px}
.layer-2{width:520px;background:var(--s1);z-index:42}
.layer-3{width:700px}
.layer-head{padding:22px 28px 18px;border-bottom:1px solid var(--line-rail);display:flex;flex-direction:column;gap:16px;flex:none}
.layer-body{flex:1;padding:24px 28px;display:flex;flex-direction:column;gap:24px;overflow-y:auto;min-height:0}
.layer-foot{padding:18px 28px;border-top:1px solid var(--line-rail);display:flex;justify-content:space-between;align-items:center;gap:16px;flex:none}
.layer-title{font-size:22px;font-weight:600;letter-spacing:-.015em}
.layer-lead{font-size:13px;color:var(--sec);line-height:1.55}
.steps{display:flex;gap:6px}
.steps i{flex:1;height:3px;background:var(--bar);border-radius:2px;transition:background .12s}
.steps i.is-on{background:var(--acc)}

.modal-wrap{position:fixed;inset:0;z-index:45;display:flex;align-items:center;justify-content:center;padding:24px}
.modal{position:relative;width:640px;max-width:100%;max-height:100%;background:var(--bg-work);border:1px solid var(--border);border-radius:8px;overflow:hidden;display:flex;flex-direction:column;animation:unruin-fade .18s ease-out}
.modal-head{padding:24px 28px 20px;border-bottom:1px solid var(--line-rail);display:flex;flex-direction:column;gap:9px;flex:none}
.modal-body{padding:22px 28px;display:flex;flex-direction:column;gap:20px;overflow-y:auto;min-height:0}
.modal-foot{padding:18px 28px;border-top:1px solid var(--line-rail);display:flex;justify-content:space-between;align-items:center;gap:16px;flex:none}
.modal-title{font-size:20px;font-weight:600;letter-spacing:-.015em}

.toasts{position:fixed;top:16px;right:16px;z-index:60;display:flex;flex-direction:column;gap:8px;max-width:420px}
.toast{background:var(--s2);border:1px solid var(--line);border-left-width:3px;border-radius:4px;padding:12px 15px;font-size:12.5px;line-height:1.5;animation:unruin-toast .18s ease-out;cursor:pointer}
.toast-ok{border-left-color:var(--ok)}
.toast-err{border-left-color:var(--err)}
.toast-warn{border-left-color:var(--warn)}
.toast-info{border-left-color:var(--acc)}

/* --------------------------------------------------------------- прочее -- */
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.stack{display:flex;flex-direction:column}
.gap-4{gap:4px}.gap-6{gap:6px}.gap-8{gap:8px}.gap-9{gap:9px}.gap-10{gap:10px}
.gap-11{gap:11px}.gap-12{gap:12px}.gap-14{gap:14px}.gap-16{gap:16px}
.gap-18{gap:18px}.gap-20{gap:20px}.gap-22{gap:22px}.gap-24{gap:24px}
.row{display:flex;align-items:center}
.row-top{display:flex;align-items:flex-start}
.between{justify-content:space-between}
.grow{flex:1;min-width:0}
.none{flex:none}
.wrap{flex-wrap:wrap}
.push{margin-top:auto}
.divide-top{border-top:1px solid var(--line);padding-top:14px}
.crumbs{font-size:11.5px;color:var(--muted)}
.crumbs i{color:var(--dim);font-style:normal;margin:0 5px}
.crumbs button{background:none;border:0;padding:0;color:var(--muted);cursor:pointer;font-size:11.5px}
.crumbs button:hover{color:var(--sec)}

/* Данные устарели — вся таблица гаснет до 55 %, но цифры не пропадают. */
.is-stale{opacity:.55;transition:opacity .18s}

.empty{display:flex;flex-direction:column;gap:12px;align-items:flex-start;padding:40px 0;max-width:640px}
.empty-title{font-size:19px;font-weight:600;letter-spacing:-.015em}

/* ============================================================================
   Мобильный взгляд (design/Unruin - Мобильный взгляд.dc.html).

   Три часа ночи, телефон в руке. Экран делает ровно три вещи: показывает, всё
   ли зелёное, объясняет причину сбоя и даёт перезапустить или восстановить.
   Конфигурации здесь нет вовсе — не спрятана за серыми кнопками, а не
   показана, и об этом сказано словами.

   Это адаптив той же SPA, а не второй продукт: рейл становится нижними
   вкладками, две колонки — одной, слои — полноэкранными.
   ============================================================================ */
@media (max-width:900px){
  :root{--pad:16px}
  .shell{flex-direction:column;height:auto;min-height:100%;overflow:visible}

  /* Рейл уезжает вниз и становится вкладками: большой палец живёт там. */
  .rail{
    position:fixed;left:0;right:0;bottom:0;top:auto;width:100%;
    flex-direction:row;align-items:stretch;gap:0;padding:0 0 env(safe-area-inset-bottom);
    border-right:0;border-top:1px solid var(--line-rail);background:var(--bg);
    z-index:30;overflow:visible
  }
  .rail-brand,.rail-sep,.rail-caption,.rail-jobs,.rail-version,.rail-inv,.rail-foot{display:none}
  .rail-tabs{flex-direction:row;padding:0;gap:0;width:100%}
  .rail-tabs .rail-item{
    flex:1;min-width:0;min-height:56px;padding:8px 6px;border-radius:0;
    justify-content:center;gap:7px;white-space:nowrap
  }
  .rail-item .cursor{display:none}
  .rail-tabs .count{display:none}
  .rail-tabs .rail-item.is-active{background:none;color:var(--acc);box-shadow:inset 0 2px 0 var(--acc)}
  .rail-tabs .rail-item:hover{background:none}
  .tab-long{display:none}
  .tab-short{display:inline}

  /* Место под вкладки: контент не должен уезжать под них. */
  .main{overflow:visible;padding-bottom:calc(60px + env(safe-area-inset-bottom))}
  .topbar{height:auto;padding:12px var(--pad);flex-wrap:wrap;gap:10px;position:sticky;top:0;z-index:20}
  .scroll{overflow:visible}
  .card-head{padding:16px var(--pad)!important;gap:14px!important}
  .card-body{padding:16px var(--pad) 24px!important}

  /* Пальцы, а не курсор: 44 px — нижняя граница всего, что нажимается. */
  .btn{min-height:44px;padding-top:10px;padding-bottom:10px}
  .btn-sm{min-height:44px;font-size:12.5px}
  .chip{min-height:44px;display:inline-flex;align-items:center}
  .input,.input-sm{min-height:44px}
  .rail-item,.rail-job{min-height:44px}
  .tbl-row{min-height:48px}
  .crumbs{font-size:13px}
  .crumbs button{font-size:13px;min-height:44px;padding-right:10px;color:var(--acc)}
  .crumbs button::before{content:'← '}

  /* Основное действие — во всю ширину и первым. На широком экране главная
     кнопка стоит справа, то есть последней; в столбик это переворачивается,
     и большой палец упирался бы во второстепенное. */
  .act-wide{width:100%;flex-direction:column;align-items:stretch;gap:9px}
  .act-wide .btn{width:100%;justify-content:center}
  .act-wide .btn-primary{order:-1}

  /* Вердикт разворачивается в стопку карточек: сбой, оговорки, «остальные
     здоровы». Порядок всегда один — от страшного к спокойному. */
  .verdict{flex-direction:column;align-items:flex-start;gap:16px;padding:18px}
  .tally{width:100%}
  .tally-cell{flex:1;min-width:0;padding:11px 8px}
  .attn{flex-direction:column;align-items:flex-start;gap:14px;padding:16px}
  .attn>div:last-child{width:100%}
  .attn-calm{flex-direction:row;align-items:center;gap:13px;border-left:3px solid var(--ok)}
  .attn-calm>div:last-child{width:auto}

  /* Список парка: от семи колонок остаются состояние, имя и когда было. */
  .ov-row{grid-template-columns:1fr auto!important;padding:12px var(--pad)!important;min-height:52px!important}
  .job-row{grid-template-columns:16px 1fr auto!important;padding:12px var(--pad)!important;min-height:52px}
  .tbl-foot,.panel-head,.panel-pad,.panel-body{padding-left:var(--pad);padding-right:var(--pad)}
  .search-box{width:100%!important}

  .split,.split-wide{flex-direction:column!important}
  .split>*,.split-wide>*{flex:none!important;width:100%!important}
  .route{flex-direction:column}
  .route-node,.route-node.is-src{width:100%;flex:none}
  .route-arrow{transform:rotate(90deg);justify-content:center;padding:2px 0}
  .stage{flex:1 1 100%}

  /* Лог не переносится, а скроллится вбок: рвать пути и адреса нельзя. */
  .log{white-space:pre;word-break:normal;overflow-x:auto;min-height:300px;max-height:60vh}
  .code{white-space:pre;word-break:normal}

  .layer,.layer-1,.layer-2,.layer-3{width:100%;left:0;border-left:0}
  .layer-head,.layer-body,.layer-foot,.modal-head,.modal-body,.modal-foot{padding-left:var(--pad);padding-right:var(--pad)}
  /* Кнопки слоя не должны жить под полосой-«домой». */
  .layer-foot,.modal-foot{padding-bottom:calc(18px + env(safe-area-inset-bottom))}
  .modal-wrap{padding:0;align-items:stretch}
  .modal{width:100%;max-height:none;border-radius:0;border:0}
  .grid-2{grid-template-columns:1fr}
  .toasts{left:12px;right:12px;max-width:none}
  .hide-sm{display:none!important}
}
@media (min-width:901px){
  .only-sm{display:none!important}
}

/* В продукте про спокойствие анимация только сглаживает. Если система просит
   меньше движения — убираем его полностью, включая дышащую точку пульса. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;
  }
}

/* Печать: аварийный конверт и runbook читаются с бумаги при выключенном
   интернете, поэтому на печать уходит только сам документ. */
@media print{
  body{background:#fff;color:#000}
  .rail,.topbar,.toasts,.veil,.no-print{display:none!important}
  .shell,.main,.scroll,.page{display:block;overflow:visible;height:auto;padding:0}
  .layer,.modal,.modal-wrap{position:static;width:auto;border:0;animation:none}
  .panel,.code,.tint-ok,.panel-serious{background:#fff;border-color:#bbb;color:#000}
  .t-note,.t-quiet,.sec,.muted,.dim{color:#333}
  .mono,.code{font-family:var(--mono)}
  a{color:#000}
}
