/* ============================================================================
   dampy.ru — app.css
   Минимализм: воздух и типографика вместо рамок. Тёмная база, оранжевый акцент.
   Главный «характер» интерфейса — dock-магнификация плиток (assets/dock.js).

   Типографика (v6):
     - Space Grotesk — дисплейная (вордмарк, заголовки, имя проекта). С характером,
       но дозированно: только крупные акценты.
     - Inter        — основной UI-текст. Читается каждый день — ставка на легибильность.
     - JetBrains Mono — данные и код (слаги, время, дамп, патч). tabular-nums везде,
       где есть цифры, чтобы колонки не «плясали».
   Шрифты подключаются в ui/layout.php (Google Fonts с preconnect).

   Разделы:
     1. Токены и база
     2. Топбар (плавающая стеклянная панель)
     3. Сетка проектов (.dock) и плитки (.tile)
     4. Унаследованные компоненты (вьюха проекта, формы, дамп/патч)
     5. Вьюха проекта: шапка, вкладки-плитки (dock), панели вкладок
   ========================================================================== */

/* ── 1. Токены и база ───────────────────────────────────────────────────── */
:root {
    --bg:#0b0b0c;                  /* тёплый near-black, мягче чистого #000 */
    --fg:#f2f2f4;                  /* ярче ради «премиальной» чистоты на тёмном */
    --muted:#98989f;               /* вторичные подписи (Apple secondary label) */
    --faint:#646468;               /* совсем тихие подписи (tertiary) */
    --accent:#ff6600;              /* бренд */
    --accent-soft:rgba(255,102,0,.14);
    --accent-ink:#1a0c00;          /* текст на оранжевой заливке (тёплый, не чёрный) */
    --info:#5e9eff;                /* системный синий: состояние «патч готов», графики, info-тосты */
    --info-ink:#06101d;            /* текст на синей заливке (парный к --accent-ink) */
    --phase-decompose:#b07cff;     /* фаза «декомпозиция» в графике расходов LLM */
    --phase-test:#3fbf86;          /* фаза «тесты» (график + точка разбивки); НЕ --ok, другой зелёный */

    --panel:#161618;               /* приподнятый материал карточек */
    --panel-2:#101012;             /* поля ввода, код */
    --border:#2a2a2e;
    --hair:rgba(255,255,255,.07);  /* волосяные разделители вместо рамок */

    /* Системные цвета статусов (Apple dark) — единая семантика везде */
    --ok:#30d158;
    --idle:#48484a;
    --warn:#ffd60a;
    --err:#ff453a;

    /* Типографика (семейства не трогаем — это бренд) */
    --font-sans:'Inter','Inter var',-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    --font-display:'Space Grotesk',var(--font-sans);
    --font-mono:'JetBrains Mono',ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;

    --r:18px;                /* карточки/панели */
    --r-sm:12px;             /* кнопки, поля, мелкие плашки */
    /* Лесенка радиусов (канон: xs→sm→md→r→xl→pill). Добавлено аддитивно;
       разрозненные 6–16px в коде мигрируем к этим токенам следующим заходом. */
    --r-xs:8px;              /* мелкие чипы/плашки, тесные контролы */
    --r-md:14px;             /* бары, тосты, средние панели */
    --r-xl:24px;             /* app-иконочные квадраты (крупнее карточки) */
    --r-pill:999px;          /* полностью скруглённые: бейджи, тумблеры */
    --gap:24px;
    --tile:148px;            /* ширина плитки */
    --ease:cubic-bezier(.22,.61,.36,1);
    --ease-spring:cubic-bezier(.32,.72,0,1);  /* мягкая «пружина» для интеракций */

    /* dock-эффект (читается из dock.js через getComputedStyle при желании) */
    --dock-radius:150px;

    /* Слоистые мягкие тени (Apple-вектор: близкий контактный слой + дальний воздух) */
    --shadow-1:0 1px 2px rgba(0,0,0,.36), 0 6px 18px -10px rgba(0,0,0,.55);
    --shadow-2:0 2px 6px rgba(0,0,0,.4), 0 18px 44px -18px rgba(0,0,0,.7);
    --edge:inset 0 1px 0 rgba(255,255,255,.05);  /* верхний световой кант материала */
}

* { box-sizing:border-box; }

html {
    -webkit-text-size-adjust:100%;
    scroll-behavior:smooth;
    accent-color:var(--accent);     /* нативные контролы — в фирменный оранж */
}

body {
    margin:0;
    min-height:100vh;
    background:var(--bg);
    color:var(--fg);
    font-family:var(--font-sans);
    font-size:15px;
    line-height:1.6;
    letter-spacing:-.006em;                     /* лёгкая оптическая подгонка, как у системного текста */
    font-feature-settings:"cv05" 1, "ss01" 1;  /* Inter: одноэтажная a/g, аккуратнее на чёрном */
    -webkit-font-smoothing:antialiased;
    -moz-osx-font-smoothing:grayscale;
    text-rendering:optimizeLegibility;
    padding:20px 28px 96px;
}

.shell { max-width:1040px; margin:0 auto; }

a { color:var(--accent); text-underline-offset:3px; text-decoration-thickness:1px; }

::selection { background:rgba(255,102,0,.26); }

/* Аккуратная современная прокрутка во всём приложении (задумка ee50a028): тонкая,
   полупрозрачная, скруглённая, с отступом (парящий бегунок), без стрелок. Раньше
   так были оформлены только длинные дампы/код — теперь и главный скролл окна, и
   любые прокручиваемые панели. Приём — как у скролла Пилота (задумка e648d89f):
   в Chromium/Safari заданные scrollbar-width/color ГАСЯТ ::-webkit-* и возвращают
   нативную полосу со стрелками, поэтому стандартные свойства отдаём ТОЛЬКО Firefox
   (@supports -moz-appearance), а Chromium/Safari едут на ::-webkit-* — там и
   скругление, и явно занулённые кнопки-стрелки. Специфичные правила (напр. свой
   скролл Пилота) перебивают это как более точные — общий стиль лишь для остального. */
@supports (-moz-appearance: none) {
    html { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.20) transparent; }
}
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: rgba(255,255,255,.16);
    border-radius: 9px;
    border: 3px solid transparent;
    background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.30); background-clip: padding-box; }
::-webkit-scrollbar-button { width: 0; height: 0; display: none; }
::-webkit-scrollbar-corner { background: transparent; }

/* ── 2. Топбар ──────────────────────────────────────────────────────────── */
/* Плавающая стеклянная панель: липнет к верху, чтобы возврат на дашборд и
   вордмарк всегда были под рукой даже на длинной странице дампа. */
.topbar {
    --bar-h:46px;            /* единая высота блоков шапки (задумка e3980b3d): лого, кнопка, пилюли */
    position:sticky;
    top:14px;
    z-index:50;
    display:flex;
    align-items:center;
    gap:14px;
    margin:0 0 36px;
    padding:10px 14px;
    border-radius:16px;
    background:rgba(22,22,24,.62);
    border:1px solid var(--hair);
    box-shadow:var(--shadow-1), var(--edge);
    -webkit-backdrop-filter:blur(20px) saturate(180%);
    backdrop-filter:blur(20px) saturate(180%);
}
/* Задумка 76ddc10c: шапка одинаковая везде. Сама .topbar и её стекло
   (backdrop-filter) на всех страницах идентичны; на дашборде она «стеклянная»,
   потому что за ней цветные плитки, а на внутренних страницах фон плоско-тёмный —
   размывать нечего, и полоса кажется глухой. Даём стеклу что размывать и там:
   мягкое цветное свечение у верхней кромки. ТОЛЬКО на страницах без сетки-дока
   (внутренние) — дашборд не трогаем, у него плитки. Слой позади всего (z-index:-1),
   кликов не ловит; если браузер не знает :has()/:not() — правило просто отбросится,
   поведение как раньше (честная деградация). */
body:not(:has(.dock))::before {
    content:'';
    position:fixed;
    top:0;
    left:0;
    right:0;
    height:220px;
    z-index:-1;
    pointer-events:none;
    background:
        radial-gradient(90% 200px at 22% -60px, rgba(255,102,0,.13), rgba(255,102,0,0) 72%),
        radial-gradient(90% 200px at 82% -70px, rgba(94,158,255,.10), rgba(94,158,255,0) 72%);
}
.wordmark {
    font-family:var(--font-display);
    font-size:20px;
    font-weight:600;
    letter-spacing:-.02em;
    color:var(--fg);
    text-decoration:none;
}
.wordmark b { color:var(--accent); font-weight:700; }

.brand {
    display:inline-block;
    width:104px;
    height:var(--bar-h,46px);
    background:#fff;
    background-image:url('/assets/dampy-logo.png?v=8');
    background-repeat:no-repeat;
    background-position:center;
    background-size:72px 30px;
    border-radius:12px;
    box-shadow:0 6px 22px rgba(0,0,0,.40);
    flex:0 0 auto;
}
.brand:focus-visible { outline:2px solid var(--accent); outline-offset:4px; }
/* Слоган убран из шапки (задумка e3980b3d) — правило .topbar__sub ушло вместе с ним. */
.spacer { flex:1; }

/* Ревизия шапки (задумка e3980b3d): ВСЕ элементы — блоки одной высоты --bar-h,
   даже если рамка не рисуется; контент центрируется по вертикали. Стили пилюль
   раньше жили инлайном в ui/layout.php — теперь единый источник правды здесь. */
.topbar__balance {
    display:inline-flex;
    align-items:center;
    height:var(--bar-h,46px);
    padding:0 14px;
    border:1px solid var(--hair);
    border-radius:999px;
    font-family:var(--font-mono);
    font-size:.82em;
    color:var(--muted);
    line-height:1;
    white-space:nowrap;
    cursor:pointer;
    transition:color .15s var(--ease), border-color .15s var(--ease);
}
.topbar__balance:hover { color:var(--fg); border-color:rgba(255,255,255,.16); }
.topbar__gear {
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:var(--bar-h,46px);
    height:var(--bar-h,46px);
    border:1px solid var(--hair);
    border-radius:999px;
    color:var(--muted);
    text-decoration:none;
    font-size:1.05em;
    line-height:1;
    transition:color .15s var(--ease), border-color .15s var(--ease);
}
.topbar__gear:hover { color:var(--fg); border-color:rgba(255,255,255,.16); }
.topbar__slot { display:inline-flex; align-items:center; height:var(--bar-h,46px); }
/* Кнопка вставки в шапке — той же высоты, что логотип (задумка e3980b3d); базовый
   .patch-paste (30×30) остаётся для строки действий панели «Патч» на странице проекта. */
.patch-paste--bar { width:var(--bar-h,46px); height:var(--bar-h,46px); border-radius:12px; }
.patch-paste--bar svg { width:19px; height:19px; }

/* ── 3. Сетка и плитки ──────────────────────────────────────────────────── */
.dock-wrap { min-height:40px; }

.dock {
    display:grid;
    grid-template-columns:repeat(auto-fill, var(--tile));
    gap:var(--gap);
    justify-content:center;
}

.tile {
    position:relative;
    display:flex;
    flex-direction:column;
    align-items:center;
    width:var(--tile);
    padding:8px 6px 6px;
    border-radius:var(--r);
    text-decoration:none;
    color:inherit;
    transform-origin:center;
    transition:scale .42s var(--ease), filter .42s var(--ease);
    will-change:scale, filter;
    outline:none;
}
/* Во время активного движения курсора dock.js ставит scale покадрово —
   убираем transition, чтобы следование было мгновенным. На уходе курсора
   класс снимается и плитки плавно возвращаются. */
.dock.is-dock-live > * { transition:none; } /* tile и tab — оба прямые дети .dock */

.tile:focus-visible { outline:2px solid var(--accent); outline-offset:4px; border-radius:var(--r); }

.tile__icon {
    width:96px;
    height:96px;
    border-radius:24px;
    overflow:hidden;            /* квадратная иконка клипается под скругление плитки */
    display:grid;
    place-items:center;
    font-family:var(--font-display);
    font-size:40px;
    font-weight:600;
    line-height:1;
    color:#0a0a0a;
    background:var(--ic, #444);
    box-shadow:var(--shadow-1), var(--edge);
    user-select:none;
}

/* Фавиконка проекта — на весь тайл (full-bleed).
   object-fit:cover заполняет квадрат целиком: логотипы с собственным фоном
   (apple-touch) смотрятся как иконка приложения, без видимой подложки и рамки.
   overflow:hidden у .tile__icon клипает углы под скругление плитки.
   Цена честная: мелкую favicon (16/32px) браузер тянет на 96px → мягковато
   при увеличении. «Крупно И резко» = только если сайт отдаёт иконку ≥180px. */
.tile__img {
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
}

.tile__name {
    margin-top:13px;
    font-size:13.5px;
    font-weight:550;
    letter-spacing:-.005em;
    line-height:1.25;
    text-align:center;
    max-width:100%;
    display:-webkit-box;
    -webkit-line-clamp:2;
    -webkit-box-orient:vertical;
    overflow:hidden;
}

.tile__meta {
    margin-top:5px;
    display:inline-flex;
    align-items:center;
    gap:6px;
    font-size:11px;
    color:var(--muted);
    font-variant-numeric:tabular-nums;
}

/* Подпись суммарной байтовой дельты проекта под метой плитки. */
.tile__delta {
    margin-top:2px;
    font-family:var(--font-mono);
    font-size:10.5px;
    font-variant-numeric:tabular-nums;
    color:var(--muted);
    opacity:.85;
}

.dot {
    width:7px; height:7px;
    border-radius:50%;
    background:var(--idle);
    flex:none;
}
.dot--on {
    background:var(--ok);
    animation:dot-pulse 2.4s ease-out infinite;
}
@keyframes dot-pulse {
    0%   { box-shadow:0 0 0 0 rgba(48,209,88,.5); }
    70%  { box-shadow:0 0 0 6px rgba(48,209,88,0); }
    100% { box-shadow:0 0 0 0 rgba(48,209,88,0); }
}

/* Плитка «добавить» */
.tile--add .tile__icon {
    background:transparent;
    border:1.5px dashed rgba(255,255,255,.16);
    color:var(--faint);
    font-weight:300;
    box-shadow:none;
    transition:border-color .2s var(--ease), color .2s var(--ease);
}
.tile--add:hover .tile__icon { border-color:var(--accent); color:var(--accent); }
.tile--add .tile__name { color:var(--muted); }

.empty { color:var(--muted); text-align:center; padding:64px 0; font-size:14px; }

/* Затемнение сетки на htmx-request УБРАНО (задумка ff7dbcb1): .dock-wrap сам
   опрашивает ?r=dashboard_grid каждые 15с, htmx на время запроса вешал на него
   класс htmx-request — и вся сетка «мигала» (иконки темнели и возвращались).
   Единственный запрос, который инициирует .dock-wrap, — этот фоновый опрос
   (клики по плиткам идут hx-boost'ом с самих якорей), так что индикация тут
   не нужна вовсе: свап мгновенный, пусть сетка стоит ровно. */

/* Тач / отсутствие точного указателя: dock-эффект отключён в JS, оставляем
   честный hover как обратную связь. */
@media (hover:hover) and (pointer:fine) {
    .tile:hover .tile__icon { box-shadow:var(--shadow-2), inset 0 1px 0 rgba(255,255,255,.22); }
}

/* ── 4. Унаследованные компоненты (вьюха проекта, формы, дамп/патч) ──────── */
h1 { font-family:var(--font-display); color:var(--fg); margin:0 0 .2em; font-size:1.8em; font-weight:600; letter-spacing:-.025em; }
h1 a { color:inherit; text-decoration:none; }
.sub { color:var(--muted); margin-bottom:2em; }

.panel {
    background:var(--panel);
    border:1px solid var(--hair);
    border-radius:var(--r);
    padding:1.4em 1.6em;
    margin-bottom:1.5em;
    box-shadow:var(--shadow-1), var(--edge);
}
.panel h2 {
    font-family:var(--font-display);
    margin:0 0 .7em;
    font-size:1.15em;
    color:var(--fg);
    font-weight:600;
    letter-spacing:-.015em;
}

dl { margin:0; display:grid; grid-template-columns:max-content 1fr; gap:.55em 1.2em; font-variant-numeric:tabular-nums; }
dt { color:var(--muted); }
dd { margin:0; }

.mono { font-family:var(--font-mono); font-variant-numeric:tabular-nums; font-size:.92em; }
.ok { color:var(--ok); }
.warn { color:var(--warn); }
.err { color:var(--err); }
.muted { color:var(--muted); }

.btn {
    display:inline-flex;
    align-items:center;
    gap:.5em;
    background:var(--accent);
    color:var(--accent-ink);
    padding:.62em 1.2em;
    border-radius:999px; /* пилюля — единое скругление всех кнопок (как у .btn-next / в прототипе) */
    text-decoration:none;
    font-family:var(--font-sans);
    font-weight:600;
    letter-spacing:-.01em;
    border:none;
    cursor:pointer;
    font-size:.95em;
    line-height:1.2;
    box-shadow:var(--shadow-1);
    position:relative;
    isolation:isolate; /* свой stacking context: радужный ::before (z-index:-1) ложится НАД заливкой, но ПОД текстом */
    transition:filter .18s var(--ease), transform .14s var(--ease-spring), box-shadow .18s var(--ease), color .5s var(--ease);
}
.btn:hover { filter:brightness(1.06); box-shadow:0 6px 20px -10px rgba(255,102,0,.55); }
.btn:active { transform:scale(.97); }
.btn:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }

table.list { width:100%; border-collapse:collapse; font-variant-numeric:tabular-nums; }
table.list th, table.list td {
    text-align:left;
    padding:.6em .7em;
    border-bottom:1px solid var(--hair);
    vertical-align:top;
}
table.list th { color:var(--faint); font-weight:500; font-size:.76em; letter-spacing:.06em; text-transform:uppercase; }
table.list tbody tr { transition:background .14s var(--ease); }
table.list tbody tr:hover { background:rgba(255,255,255,.03); }

.field { margin-bottom:1em; }
.field label { display:block; color:var(--muted); margin-bottom:.4em; font-size:.9em; }
.inp,
.field input:not([type="radio"]):not([type="checkbox"]), .field textarea {
    width:100%;
    background:var(--panel-2);
    color:var(--fg);
    border:1px solid var(--border);
    border-radius:var(--r-sm);
    padding:.66em .85em;
    font-family:inherit;
    font-size:.95em;
    transition:border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.inp:focus,
.field input:not([type="radio"]):not([type="checkbox"]):focus, .field textarea:focus {
    outline:none;
    border-color:var(--accent);
    box-shadow:0 0 0 3.5px var(--accent-soft);
}
.field .hint { color:var(--muted); font-size:.82em; margin-top:.35em; }
/* .inp — тот же канонический вид инпута вне обёртки .field (единый источник правды). */
.inp.mono { font-family:var(--font-mono); }

/* Переключатель схемы https/http в форме проекта.
   Нативные радио оставляем источником правды (и фолбэком), но сегмент целиком
   подсвечивается по :checked. Анимируем только цвет/фон — никакой геометрии,
   поэтому при наведении и переключении ничего не «дёргается». */
.scheme-toggle label { transition:background-color .15s var(--ease), color .15s var(--ease); }
.scheme-toggle label:has(input:checked) { background:var(--accent-soft); color:var(--accent); }
.scheme-toggle label:has(input:focus-visible) { outline:2px solid var(--accent); outline-offset:-2px; }
@media (prefers-reduced-motion:reduce) { .scheme-toggle label { transition:none; } }

ol.steps { margin:.5em 0 0; padding-left:1.3em; line-height:1.85; }

.tree-pre { background:var(--bg); padding:.9em; border-radius:var(--r-sm); overflow-x:auto; font-size:12px; line-height:1.5; font-family:var(--font-mono); border:1px solid var(--hair); }
.dump-files { margin-top:1em; }
.file-detail { background:var(--panel-2); border:1px solid var(--hair); border-radius:var(--r-sm); margin-bottom:8px; }
.file-detail summary { padding:9px 13px; cursor:pointer; font-family:var(--font-mono); font-size:13px; transition:background .14s var(--ease); border-radius:var(--r-sm); }
.file-detail summary:hover { background:rgba(255,255,255,.04); }
.file-content { background:var(--bg); padding:11px 13px; margin:0; border-top:1px solid var(--hair); font-size:12px; line-height:1.55; overflow-x:auto; white-space:pre-wrap; font-family:var(--font-mono); }

.patch-textarea {
    font-family:var(--font-mono); font-size:13px; line-height:1.55;
    background:var(--bg); color:#e6e6e6; border:1px solid var(--border);
    width:100%; padding:12px; border-radius:var(--r-sm);
    transition:border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.patch-textarea:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3.5px var(--accent-soft); }
/* Родной уголок-резайзер textarea в тёмной теме светится белым треугольником —
   гасим у всех полей; тянуть за угол по-прежнему можно, просто без кляксы. */
textarea::-webkit-resizer { background: transparent; }
/* «Применить патч»: по умолчанию ghost — пока превью патча не досчитано, жать
   нечего, и сплошная заливка кричала раньше времени. Готовность подсвечивает
   радужный .btn-next (кроссфейд): его тёмный слой ложится поверх прозрачности. */
.apply-btn { background:transparent; color:var(--accent); border:1px solid var(--hair); box-shadow:none; }
.apply-btn:hover { border-color:var(--accent); background:var(--accent-soft); filter:none; box-shadow:none; }

.dump-result-area, .patch-result-area { margin-top:12px; }
.htmx-indicator { display:inline-block; opacity:0; transition:opacity .2s; color:var(--muted); font-size:.9em; }
.htmx-request .htmx-indicator { opacity:1; }
.error { color:#ffb4ad; background:rgba(255,69,58,.1); border:1px solid rgba(255,69,58,.24); padding:11px 14px; border-radius:var(--r-sm); }
.success { color:#9be8af; background:rgba(48,209,88,.1); border:1px solid rgba(48,209,88,.24); padding:11px 14px; border-radius:var(--r-sm); }
.patch-result pre { background:var(--bg); padding:11px; border-radius:var(--r-sm); overflow-x:auto; font-size:12px; font-family:var(--font-mono); line-height:1.5; }

/* Уважение к prefers-reduced-motion: глушим пульс и переходы плиток */
@media (prefers-reduced-motion:reduce) {
    html { scroll-behavior:auto; }
    .tile { transition:none; }
    .dot--on { animation:none; }
}

/* ============================================================================
   5. Вьюха проекта: шапка, вкладки-плитки (dock), панели вкладок
   ========================================================================== */

.project { /* контейнер вьюхи проекта */ }

/* ── Шапка ──────────────────────────────────────────────────────────────── */
/* align-items:flex-start — иконка прижата к верху, её верх совпадает с верхом
   облачка-имени (а не центрируется против всего стека имя+бейджи, из-за чего
   раньше уезжала ниже верха облака). Высота иконки ≈ высоте стека имя+мета. */
.phead { display:flex; align-items:flex-start; gap:16px; margin:4px 0 28px; }
.phead__icon {
    width:64px; height:64px; border-radius:18px;
    overflow:hidden;            /* фавиконка клипается под скругление */
    display:grid; place-items:center;
    font-family:var(--font-display);
    font-size:24px; font-weight:600; color:#0a0a0a;
    background:var(--ic, #444);
    box-shadow:var(--shadow-1), var(--edge);
    flex:none; user-select:none;
}
.phead__img { width:100%; height:100%; object-fit:cover; display:block; }
.phead__main { min-width:0; }
.phead__name {
    font-family:var(--font-display);
    margin:0; font-size:23px; font-weight:700; letter-spacing:-.02em; color:var(--fg);
    display:flex; align-items:center; gap:10px; flex-wrap:wrap;
}
/* Имя проекта «как в логотипе»: гелевое белое облачко + текст градиентом,
   точно повторяющим перелив логотипа dampy (цвета сняты с dampy-transparent.png):
   ярко-оранжевый → янтарь → лайм → зелёный → циан → синий → тёмно-синий, слева
   направо. Облачко и чернила — разные слои: белый фон не может одновременно быть
   градиентом текста, поэтому ink — child. */
.phead__title {
    display:inline-block;
    background:#fff;
    border-radius:999px;
    padding:2px 16px;
    box-shadow:0 8px 22px -12px rgba(0,0,0,.7), inset 0 1px 0 rgba(255,255,255,.7);
}
.phead__title-ink {
    background:linear-gradient(95deg,#ff5400 0%,#ff8c00 16%,#ffb300 28%,#a7c100 40%,#2a9f55 49%,#007dad 58%,#0060b4 68%,#00337f 82%,#001951 100%);
    -webkit-background-clip:text;
    background-clip:text;
    -webkit-text-fill-color:transparent;
    color:transparent;
    font-weight:700;
    letter-spacing:-.02em;
}
.phead__seen { font-family:var(--font-sans); font-size:12px; font-weight:400; color:var(--muted); }
.phead__meta { margin-top:9px; display:flex; flex-wrap:wrap; align-items:center; gap:8px 14px; font-size:12.5px; color:var(--muted); }
.phead__slug { color:var(--muted); }
.phead__url { color:var(--accent); text-decoration:none; }
.phead__url:hover { text-decoration:underline; }

.badge {
    display:inline-flex; align-items:center; gap:5px;
    padding:3px 11px; border-radius:999px;
    font-size:11px; font-weight:500; letter-spacing:.01em;
    background:rgba(255,255,255,.05); border:1px solid var(--hair); color:var(--fg);
}

/* ── Вкладки ───────────────────────────────────────────────────────────── */
.ptabs__r { position:absolute; width:1px; height:1px; opacity:0; pointer-events:none; } /* sr-only, кликаем по label */

.dock--tabs {
    display:flex; grid-template-columns:none;       /* перебиваем grid из .dock */
    justify-content:flex-start; gap:16px;
    margin:0 0 26px;
}
.tab {
    display:flex; flex-direction:column; align-items:center; gap:8px;
    width:80px; padding:10px 4px 8px;
    border-radius:16px; cursor:pointer;
    transform-origin:center;
    transition:scale .42s var(--ease), filter .42s var(--ease);
    will-change:scale, filter; user-select:none;
}
.tab__icon {
    width:52px; height:52px; border-radius:15px;
    display:grid; place-items:center; font-size:25px; line-height:1;
    background:rgba(255,255,255,.05); border:1px solid var(--hair);
    box-shadow:var(--edge);
    transition:background .2s var(--ease), border-color .2s var(--ease);
}
.tab__label { font-size:11.5px; color:var(--muted); transition:color .2s; }
.tab:hover .tab__label { color:var(--fg); }
.ptabs__r:focus-visible + input + input + input + input + .dock--tabs .tab:first-of-type .tab__icon { outline:2px solid var(--accent); outline-offset:3px; }

/* активная вкладка — подсветка фоном/рамкой (не filter, чтобы не конфликтовать
   с brightness, который dock.js ставит инлайном при наведении) */
#ptab-work:checked ~ .dock--tabs .tab[for="ptab-work"] .tab__icon,
#ptab-llm:checked  ~ .dock--tabs .tab[for="ptab-llm"]  .tab__icon,
#ptab-act:checked  ~ .dock--tabs .tab[for="ptab-act"]  .tab__icon,
#ptab-conn:checked ~ .dock--tabs .tab[for="ptab-conn"] .tab__icon,
#ptab-set:checked  ~ .dock--tabs .tab[for="ptab-set"]  .tab__icon {
    background:rgba(255,102,0,.16); border-color:var(--accent);
}
#ptab-work:checked ~ .dock--tabs .tab[for="ptab-work"] .tab__label,
#ptab-llm:checked  ~ .dock--tabs .tab[for="ptab-llm"]  .tab__label,
#ptab-act:checked  ~ .dock--tabs .tab[for="ptab-act"]  .tab__label,
#ptab-conn:checked ~ .dock--tabs .tab[for="ptab-conn"] .tab__label,
#ptab-set:checked  ~ .dock--tabs .tab[for="ptab-set"]  .tab__label {
    color:var(--fg);
}

/* ── Панели вкладок ────────────────────────────────────────────────────── */
.tpanel { display:none; }
#ptab-work:checked ~ .tpanel--work,
#ptab-llm:checked  ~ .tpanel--llm,
#ptab-act:checked  ~ .tpanel--act,
#ptab-conn:checked ~ .tpanel--conn,
#ptab-set:checked  ~ .tpanel--set {
    display:block;
    animation:tab-in .26s var(--ease);
}
@keyframes tab-in {
    from { opacity:0; transform:translateY(5px); }
    to   { opacity:1; transform:none; }
}

/* ── Рабочая область ───────────────────────────────────────────────────── */
.actions { display:flex; flex-wrap:wrap; align-items:center; gap:12px; }
.btn--ghost { background:transparent; color:var(--accent); border:1px solid var(--hair); box-shadow:none; }
.btn--ghost:hover { border-color:var(--accent); background:var(--accent-soft); filter:none; box-shadow:none; }

/* ── .btn-next: «нажми меня следующей» — радужный бегущий бордер ────────── */
/* Единый маркер главного действия текущего экрана. Визуал — 1:1 «Вариант 4:
   Перелив цветов» из прототипа animated-buttons: тёмная кнопка, вокруг неё
   3px градиентный бордер, который непрерывно переливается слева направо
   (linear-gradient шириной 300% + анимация background-position 0%→300%,
   3s linear infinite; цвета #ff6b00→#ff006e→#8338ec→#3a86ff→#ff6b00 — замкнуты
   на первый, чтобы не было скачка на стыке цикла). Форма — пилюля, как у всех .btn.

   Кроссфейд: радужный вид живёт на ::before КАЖДОЙ .btn (невидим: opacity:0,
   анимация на паузе — не ест ресурсы), а класс .btn-next лишь проявляет слой
   через transition opacity. Оранжевая/зелёная заливка остаётся под слоем и
   просвечивает по мере затухания → взаимный фейд на месте, в обе стороны,
   без прыжков геометрии (кнопка сама не меняет ни паддинги, ни бордер).
   Пауза вместо отключения анимации — чтобы при фейд-ауте градиент замирал,
   а не скакал в нулевую позицию. Цвет текста едет синхронно (color .5s на .btn).
   Где вешается класс:
   · «🚀 Применить патч» (вкладка «Работа») — ставит/снимает patch-preview.js,
     ТОЛЬКО когда дельта патча досчитана (см. markApplyNext там);
   · «↪ Вставить патч…» (Нейросеть, готовая задача) и «↪ Применить патч»
     кодед-шага плана — статично в разметке: раз кнопка отрисована, патч готов. */
.btn::before {
    content:'';
    position:absolute;
    inset:0;
    z-index:-1;
    border-radius:inherit;
    border:3px solid transparent;
    background:
        linear-gradient(#1a1a1a, #1a1a1a) padding-box,
        linear-gradient(90deg, #ff6b00, #ff006e, #8338ec, #3a86ff, #ff6b00) border-box;
    background-size:100% 100%, 300% 100%;
    animation:btn-next-shift 3s linear infinite paused;
    opacity:0;
    transition:opacity .5s var(--ease);
    pointer-events:none;
}
.btn-next { color:#fff; }
.btn-next::before { opacity:1; animation-play-state:running; }
/* Радужный слой живёт в padding-box (inset:0 у ::before) и НЕ накрывает
   собственный бордер кнопки. У ghost-основ (apply, «Открыть dampy.php»…) этот
   1px на ховере вспыхивал оранжевым кольцом ВОКРУГ радуги — в радужном
   состоянии родной бордер гасим совсем (правило ниже .btn--ghost/.apply-btn —
   при равной специфичности побеждает порядком). */
.btn-next, .btn-next:hover { border-color:transparent; }
/* Ховер как в прототипе: лёгкий scale, без оранжевого/зелёного glow базовых кнопок. */
.btn-next:hover { filter:none; box-shadow:var(--shadow-1); transform:scale(1.05); }
.btn-next:active { transform:scale(.97); }
/* Радужный подсвет ТОЛЬКО при наведении (постоянного состояния нет): пока
   курсор на кнопке, слой ::before проявляется тем же кроссфейдом; увёл — гаснет.
   Вешается на «⬇ Скачать дамп (для LLM)»: в покое кнопка спокойно-оранжевая,
   а ховер намекает, что это вход в основной LLM-флоу. */
.btn-next-hover:hover, .btn-next-hover:focus-visible { color:#fff; filter:none; box-shadow:var(--shadow-1); }
.btn-next-hover:hover::before, .btn-next-hover:focus-visible::before { opacity:1; animation-play-state:running; }
@keyframes btn-next-shift {
    0%   { background-position:0 0, 0% 50%; }
    100% { background-position:0 0, 300% 50%; }
}
/* Уважение к reduced-motion: бордер остаётся радужным (и фейд остаётся), но не бежит. */
@media (prefers-reduced-motion: reduce) {
    .btn::before { animation:none; }
}

/* Кнопка-иконка «вставить патч из буфера»: в строке действий панели «Патч» и
   глобальная в шапке (ui/layout.php) — потому и живёт тут, а не инлайном.
   Тёмный чип 30×30 без подписи; тинт ховера кладём слоем ПОВЕРХ непрозрачной
   основы: --accent-soft полупрозрачный и сам по себе пропускал бы фон насквозь. */
.patch-paste {
    flex:0 0 auto;
    width:30px; height:30px; padding:0;
    display:inline-flex; align-items:center; justify-content:center;
    border-radius:9px;
    border:1px solid var(--hair);
    background:var(--bg);
    color:var(--muted);
    cursor:pointer;
    transition:color .15s var(--ease), border-color .15s var(--ease), background .15s var(--ease), opacity .15s var(--ease);
}
.patch-paste:hover { color:var(--accent); border-color:var(--accent); background:linear-gradient(var(--accent-soft),var(--accent-soft)),var(--bg); }
.patch-paste svg { width:15px; height:15px; pointer-events:none; }
.patch-paste.is-ok { color:var(--ok); border-color:rgba(48,209,88,.45); }
.patch-paste.is-busy { opacity:.55; pointer-events:none; } /* пока ищем проект по slug */

.settings-warn {
    margin-top:6px; font-size:.85em; line-height:1.5;
    color:#e8c66a; background:rgba(255,214,10,.08);
    border:1px solid rgba(255,214,10,.24); border-radius:var(--r-sm);
    padding:11px 14px;
}

.live-tag {
    font-size:10px; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
    color:var(--ok); border:1px solid rgba(48,209,88,.4); border-radius:999px;
    padding:1px 7px; margin-left:8px; vertical-align:middle;
}

.backlink { margin-top:8px; }
.backlink a { text-decoration:none; }
.backlink a:hover { text-decoration:underline; }

@media (prefers-reduced-motion:reduce) {
    .tab { transition:none; }
    #ptab-work:checked ~ .tpanel--work,
    #ptab-llm:checked  ~ .tpanel--llm,
    #ptab-act:checked  ~ .tpanel--act,
    #ptab-conn:checked ~ .tpanel--conn,
    #ptab-set:checked  ~ .tpanel--set { animation:none; }
}

/* ── Мобильный: топбар не липнет (экономим высоту), плитки чуть теснее ───── */
@media (max-width:560px) {
    body { padding:14px 16px 80px; }
    .topbar { position:static; top:auto; }
    :root { --gap:18px; }
}

/* ── Дашборд: общая статистика «налито по дням» (под сеткой проектов) ───── */
.dash-stats { margin-top:44px; }
.dash-stats__head { display:flex; align-items:baseline; justify-content:space-between; gap:12px; flex-wrap:wrap; margin:0 0 16px; }
.dash-stats__total { font-family:var(--font-mono); font-variant-numeric:tabular-nums; color:var(--fg); font-weight:600; font-size:14px; }
.dash-stats__canvas-wrap { position:relative; height:280px; }

/* ── Превью патча: список файлов с байтовой дельтой (вкладка «Работа») ──── */
/* JS — assets/patch-preview.js (подключается в <head>, ui/layout.php). */
.patch-preview { margin-top: 10px; }
.patch-preview__head { font-size: .82em; color: var(--muted); margin: 0 0 6px; }
.patch-preview__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.patch-preview__item { display: flex; align-items: center; gap: 8px; font-size: .9em; }
.patch-preview__file { font-family: var(--font-mono, ui-monospace), SFMono-Regular, Menlo, monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.patch-preview__act { font-size: .72em; padding: 1px 7px; border-radius: 999px; line-height: 1.5; white-space: nowrap; }
.patch-preview__act--create { background: rgba(84,217,140,.16); color: #54d98c; }
.patch-preview__act--update { background: rgba(120,170,255,.16); color: #8ab4ff; }
.patch-preview__act--delete { background: rgba(255,110,110,.16); color: #ff7a7a; }
.patch-preview__act--unknown { background: rgba(160,160,160,.16); color: var(--muted); }
.patch-preview__delta { margin-left: auto; padding-left: 10px; font-family: var(--font-mono, ui-monospace), monospace; font-variant-numeric: tabular-nums; font-size: .82em; white-space: nowrap; }
.patch-preview__delta--pos { color: #54d98c; }
.patch-preview__delta--neg { color: #ff7a7a; }
.patch-preview__delta--zero { color: var(--muted); }
.patch-preview__delta--approx { color: var(--muted); opacity: .85; }
.patch-preview__delta--pending { color: var(--muted); opacity: .55; }
.patch-preview__hint { font-size: .82em; color: var(--muted); }
.patch-preview__hint--warn { color: #d6a14a; }
/* «Закроет задумки» — блок НАД списком файлов: сначала что сделано, потом чем.
   Воздуха больше, чем у файлов: шире межстрочный зазор и отступ снизу. */
.patch-preview__closes { margin: 2px 0 18px; }
.patch-preview__closes .patch-preview__list { gap: 8px; }
.patch-preview__closes-head { display: flex; align-items: center; gap: 9px; margin: 0 0 10px; }
/* «Радостная звёздочка» счётчика: восьмилучевая — квадрат и его копия
   (::before), повёрнутая на 45°, число поверх. position:relative + z-index:0
   создают звёздочке свой контекст: лучи (z-index:-1) прячутся под её фон,
   а не под фон панели. Лёгкое свечение — для радости. */
.patch-preview__star { position: relative; z-index: 0; display: inline-flex; align-items: center; justify-content: center; width: 21px; height: 21px; border-radius: 5px; background: var(--accent, #ff6600); color: #fff; font-style: normal; font-weight: 800; font-size: .8em; line-height: 1; font-variant-numeric: tabular-nums; box-shadow: 0 0 14px rgba(255,102,0,.4); }
.patch-preview__star::before { content: ''; position: absolute; inset: 0; z-index: -1; background: inherit; border-radius: inherit; transform: rotate(45deg); }
/* Дашборд превью: слева изменения (закрываемые задумки), справа файлы и байты;
   на узком экране колонки складываются. */
.patch-preview__dash { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 4px 28px; align-items: start; }
.patch-preview__dash .patch-preview__closes { margin: 2px 0 0; }
@media (max-width: 760px) { .patch-preview__dash { grid-template-columns: minmax(0,1fr); gap: 14px; } }
/* Индикатор наливки — шапка превью: крупная цифра в целых КБ, под ней две
   полоски (оранжевая — этот проект, серая — парк). Текстовой подписи нет —
   цифры средних и множители живут в title-подсказках полосок. Шкала
   0..2×среднего, засечка посередине — средний (для каждой полоски свой);
   хвост длиннее шкалы обрезается. */
.patch-preview__gauge--top { margin: 2px 0 16px; }
.patch-preview__gauge-num { margin: 0 0 7px; font-size: 1.3em; font-weight: 800; color: var(--fg); font-variant-numeric: tabular-nums; letter-spacing: .01em; }
.patch-preview__gauge-bar { position: relative; height: 8px; border-radius: 999px; background: rgba(255,255,255,.07); }
/* Пробег до места — инерциальный: резкий старт и долгое торможение (expo-out).
   Ширину из 0 в цель ставит patch-preview.js после первой отрисовки. */
.patch-preview__gauge-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0; border-radius: 999px; background: var(--accent, #ff6600); transition: width .9s cubic-bezier(.16, 1, .3, 1); }
/* Серая полоска — против среднего всего парка; лежит ПОД оранжевой (порядок в
   DOM), оранжевая длиннее — просто обгоняет её. */
.patch-preview__gauge-fill--fleet { background: rgba(255,255,255,.25); }
.patch-preview__gauge-avg { position: absolute; left: 50%; top: -3px; bottom: -3px; width: 2px; border-radius: 2px; background: rgba(255,255,255,.35); }
@media (prefers-reduced-motion: reduce) { .patch-preview__gauge-fill { transition: none; } }
/* Повтор патча (идемпотентность): единственный индикатор — сама текстария.
   Зелёная заливка + гашёный текст, а поверх — надпись «Патч уже применён ·
   N назад» с живым тиканием (setAppliedOverlay в patch-preview.js кладёт её
   по геометрии поля и обновляет раз в секунду). pointer-events:none — клики
   проходят в поле: вставил другой патч, и всё ожило. */
#patch_json.patch-ta--applied { background: rgba(84,217,140,.10); border-color: rgba(84,217,140,.55); color: rgba(232,232,234,.28); }
.patch-ta-overlay { position: absolute; display: flex; align-items: center; justify-content: center; text-align: center; padding: 16px; pointer-events: none; color: #54d98c; font-weight: 800; font-size: 1.25em; line-height: 1.45; text-shadow: 0 1px 10px rgba(0,0,0,.6); z-index: 2; }
