/* ── Variables ────────────────────────────────────────────── */
:root {
    --glass:        rgba(255,255,255,0.28);
    --glass-heavy:  rgba(255,255,255,0.42);
    --glass-border: rgba(255,255,255,0.55);
    --glass-border-soft: rgba(255,255,255,0.35);
    --glass-shadow: 0 8px 32px rgba(31,38,135,0.1);
    --blur:         blur(20px);
    --blur-heavy:   blur(28px);
    --r-xl:   20px;
    --r-lg:   16px;
    --r-md:   12px;
    --r-sm:    8px;
    --text-1: #0f172a;
    --text-2: #334155;
    --text-3: #64748b;
    --text-4: #94a3b8;
    --accent:      #3b82f6;
    --accent-dark: #2563eb;
    --danger:      #ef4444;
    --danger-dark: #b91c1c;
}

/* ── Reset ────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; scroll-padding-top: 64px; }

body {
    font-family: 'Montserrat', sans-serif;
    /* Matches background.png's edge tone -- a safety net so any sliver .site-bg
       doesn't cover (before it loads, or a stray sub-pixel row) reads as part of
       the design instead of a stark white gap. */
    background-color: #78c3f4;
    /* 100vh assumes the browser chrome (address bar etc.) is fully collapsed, which it
       isn't on page load -- on mobile that makes body taller than the actually visible
       viewport, so a vertically-centered element (e.g. .login-card) sits visibly below
       center until the user scrolls. 100dvh tracks the real visible height instead;
       kept as a second declaration so browsers without dvh support just keep the vh one. */
    min-height: 100vh;
    min-height: 100dvh;
    color: var(--text-1);
}

/* Genuinely position:fixed instead of background-attachment:fixed on body (same fix
   already shipped on the marketing site, see global.css's .site-bg). Second attempt --
   the first one landed at the same time as an unrelated, real grid-overflow bug
   (bare 1fr tracks, since fixed) whose symptoms looked identical to this technique
   failing (a "gap" near the footer, footer looking misaligned): that overflow made
   body's actual box wider than the viewport, so .site-bg (100vw, correctly sized to
   the *viewport*) legitimately didn't cover the extra width body's *content* pushed
   into. With the real overflow gone, width:100vw here is sized against a body that's
   never wider than the viewport, so it should cover cleanly all the way down.
   height:100dvh instead of a bare percentage is what tracks iOS Safari's *current*
   visible viewport as its address bar collapses/expands on scroll -- a stale/static
   height is what leaves a plain gap top or bottom equal to the toolbar's height. */
.site-bg {
    position: fixed;
    top: 0; left: 0;
    width: 100vw;
    height: 100dvh;
    z-index: -1;
    background: url('/static/background.png') no-repeat center center;
    background-size: cover;
}

/* ── Page Loader ──────────────────────────────────────────── */
#page-loader {
    position: fixed; inset: 0; z-index: 9999;
    background: rgba(255,255,255,0.92);
    backdrop-filter: var(--blur);
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 20px;
}
.spinner-wrapper { position: relative; width: 80px; height: 80px; }
.spinner-ring {
    width: 100%; height: 100%;
    border: 5px solid rgba(203,213,225,0.8);
    border-top-color: var(--accent);
    border-radius: 50%; animation: spin 0.9s linear infinite;
}
.spinner-logo {
    position: absolute; top: 50%; left: 50%;
    width: 44px; height: 44px; object-fit: contain;
    transform: translate(-50%,-50%); pointer-events: none;
}
.loader-text { font-size: 13px; color: var(--text-3); font-weight: 600; }
.spinner {
    display: inline-block; width: 12px; height: 12px;
    border: 2px solid rgba(255,255,255,0.4); border-top-color: #fff;
    border-radius: 50%; animation: spin 0.7s linear infinite;
    vertical-align: middle; margin-left: 5px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Header ───────────────────────────────────────────────── */
/* Floating glass pill, same visual language as the marketing site's Header.astro
   (see .pub-header) -- unified across the whole app instead of the old edge-to-edge
   flat bar. .adm-header and .dsh-tabbar (when present) stack as two pills inside one
   fixed flex-column wrapper, so the tabbar's position is never hand-coupled to the
   header's exact height (the old version hardcoded .dsh-tabbar's top to .adm-header's
   height in px -- one silent source of drift whenever either one's content changed). */
.adm-header-wrap {
    position: fixed; top: 0; left: 0; right: 0; z-index: 100;
    display: flex; flex-direction: column; align-items: center;
    padding: 0 20px; pointer-events: none;
}
.adm-header-wrap > * { pointer-events: auto; width: 100%; max-width: 1600px; }
.adm-header {
    margin-top: 16px; padding: 10px 20px; min-height: 48px;
    border-radius: var(--r-xl);
    background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
    border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow);
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 16px;
}
.adm-brand {
    display: flex; align-items: center; gap: 8px; flex-shrink: 0;
}
.adm-brand-lockup { height: 26px; width: auto; }
/* Three independent flex children of .adm-header now (brand, links, quick) instead of
   a brand+quick wrapper -- desktop wants logo far left, Биллинг/Помощь/Конструктор
   next to it, and the account/bell/Выйти cluster pushed to the far right (the usual
   place for account controls), which needs brand and quick decoupled. Plain DOM/source
   order (brand, links, quick) already gives that on desktop with .adm-header's
   space-between; only the mobile media query below re-groups brand+quick onto row 1
   via `order`, since there the phone needs them adjacent instead. */
.adm-header-quick { display: flex; align-items: center; gap: 4px; min-width: 0; }
.adm-header-links { display: flex; align-items: center; gap: 12px; }
/* Same 3-item header as the marketing site's (logo, nav, actions). A middle 1fr
   track only lands on the container's true center if the two side tracks are equal
   width -- brand and the account/bell/Выйти cluster never are, so both side tracks
   are 1fr too: equal to each other by definition, each sized up to whichever of
   brand/quick actually needs more room, which pins .adm-header-links (the auto
   middle column) to the real center regardless of that width difference. Scoped to
   this modifier class (dashboard.html only) so the plain two-child .adm-header used
   by every other page (help/billing/account/kb/onboarding) is untouched. */
.adm-header-3col { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; }
.adm-header-3col .adm-brand { justify-self: start; }
.adm-header-3col .adm-header-quick { justify-self: end; }

/* Second pill under .adm-header, same wrapper: one entry per (connection, adapter_type)
   an account owns, so switching agents and creating a new one share a single visual
   language instead of a <select> + arrow-links + a separate button (past attempts
   at this header kept mixing three different UI idioms for one job). */
.dsh-tabbar {
    margin-top: 8px; padding: 5px 12px;
    border-radius: var(--r-lg);
    display: flex; align-items: center; gap: 4px;
    background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
    border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow);
    overflow-x: auto; overflow-y: hidden; white-space: nowrap;
    scrollbar-width: none;
}
.dsh-tabbar::-webkit-scrollbar { display: none; }

.dsh-tab {
    display: inline-flex; align-items: baseline; gap: 6px; flex-shrink: 0;
    font-family: 'Montserrat', sans-serif; cursor: pointer;
    padding: 7px 12px; border-radius: var(--r-sm);
    background: transparent; border: 1px solid transparent;
    text-decoration: none; transition: background 0.15s;
}
.dsh-tab:hover { background: rgba(15,23,42,0.05); }
.dsh-tab-name { font-size: 13px; font-weight: 700; color: var(--text-2); }
.dsh-tab-adapter { font-size: 11px; font-weight: 700; color: var(--text-3); }
/* Real brand colors, not arbitrary ones -- Pyrus's primary is a warm amber, Telegram's
   is their well-known blue. Applies whether the tab is active or not (see the
   .dsh-tab-active overrides just below, which must NOT reset this). */
.dsh-tab-pyrus .dsh-tab-adapter { color: #b5870d; }
.dsh-tab-telegram .dsh-tab-adapter { color: #0088cc; }

/* No backdrop-filter here on purpose -- .dsh-tabbar (parent) already blurs the
   page background; a second blur on an element nested inside an already-
   blurred parent is a known WebKit/Safari compositing trap that can render as
   fully opaque instead of stacking (confirmed on Safari). Just the translucent
   tint is enough, compositing over the parent's already-blurred backdrop. */
.dsh-tab-active {
    background: rgba(255,255,255,0.32);
    border-color: var(--glass-border); cursor: default;
    box-shadow: var(--glass-shadow);
}
.dsh-tab-active .dsh-tab-name { color: var(--text-1); }
.dsh-tab-active:hover { background: rgba(255,255,255,0.32); }

.dsh-tab-add {
    padding: 7px 10px; background: transparent; border-color: transparent;
}
.dsh-tab-add:hover { background: rgba(15,23,42,0.05); }
.dsh-tab-add svg { width: 12px; height: 12px; color: var(--text-3); display: block; }

.adm-header-right { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.adm-user {
    font-size: 12px; font-weight: 600; color: var(--text-3);
    display: inline-flex; align-items: center; gap: 6px;
}
a.adm-user {
    text-decoration: none; transition: background 0.15s;
    padding: 5px 10px; border-radius: var(--r-sm);
    background: transparent;
}
a.adm-user:hover { background: rgba(15,23,42,0.05); }
.adm-user svg { flex-shrink: 0; opacity: 0.7; }
/* The account email is the one item here with genuinely unbounded length -- it's the
   only thing allowed to shrink/ellipsis when the header is tight, everything else
   (Биллинг/bell/Выйти) keeps its natural size. */
.adm-account-link { min-width: 0; }
.adm-account-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-logout {
    font-size: 12px; font-weight: 700; color: var(--danger);
    text-decoration: none; opacity: 0.85; transition: background 0.15s, opacity 0.15s;
    padding: 5px 10px; border-radius: var(--r-sm);
    background: transparent;
}
.adm-logout:hover { opacity: 1; background: rgba(239,68,68,0.08); }

/* ── Layout ───────────────────────────────────────────────── */
/* 126px clears the floating header+tabbar pill pair (dashboard.html always renders
   both -- see .adm-header-wrap above); the footer is no longer fixed, so nothing here
   needs to reserve room for it any more, it just flows after .dsh-layout in the DOM. */
.dsh-layout {
    display: flex;
    align-items: flex-start;
    padding-top: 134px;
    padding-left: 20px;
    padding-bottom: 24px;
    min-height: 100vh;
}

/* position: sticky (not fixed) -- a fixed sidebar stays pinned to the viewport
   regardless of scroll, so once a page's content is short enough that the footer
   (flows normally now, see .pub-footer) scrolls into the sidebar's screen band, the
   sidebar -- having no idea the footer exists -- just sits on top of it. Sticky keeps
   the same "stays put while scrolling" feel but is a flex child of .dsh-layout: it's
   naturally contained inside that box, which ends before the footer begins, so it
   scrolls out of the way on its own instead of floating independently forever. */
/* Floating glass card, same family as .adm-header/.dsh-tabbar/.pub-footer -- was a
   flush-left rectangle with a border on one side only, sitting flat against the
   viewport edge with no rounding, which is what read as "cut off" next to the
   rounded pills everywhere else on the page. */
.dsh-sidebar {
    width: 190px;
    flex-shrink: 0;
    position: sticky;
    top: 134px;
    align-self: flex-start;
    max-height: calc(100vh - 134px - 16px);
    overflow-y: auto;
    padding: 14px 10px;
    display: flex;
    flex-direction: column;
    gap: 1px;
    border-radius: var(--r-xl);
    border: 1px solid var(--glass-border);
    background: var(--glass);
    backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
    box-shadow: var(--glass-shadow);
    scrollbar-width: none;
}
.dsh-sidebar::-webkit-scrollbar { display: none; }

.dsh-navlink {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 12px;
    border-radius: var(--r-sm);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-2);
    text-decoration: none;
    transition: background 0.15s, color 0.15s;
    white-space: normal;
    word-break: break-word;
}
.dsh-navlink-icon { flex-shrink: 0; opacity: 0.6; transition: opacity 0.15s; }
.dsh-navlink-label { flex: 1; min-width: 0; }
.dsh-navlink:hover {
    background: rgba(255,255,255,0.5);
    color: var(--text-1);
}
.dsh-navlink:hover .dsh-navlink-icon { opacity: 0.85; }
.dsh-navlink-locked {
    opacity: 0.55;
}

/* ── Content ──────────────────────────────────────────────── */
.dsh-content {
    /* No margin-left hack any more -- .dsh-sidebar is a normal sticky flex sibling
       now (was position:fixed, taken clean out of flow, hence the old hack here). */
    flex: 1;
    min-width: 0;
    display: grid;
    /* minmax(0, 1fr), not bare 1fr -- a bare 1fr track has an automatic MINIMUM size
       equal to its content's min-content width, so a card with something wide inside
       (e.g. the KB JSON sample, a long HTTP-tool URL) grows its whole track past the
       viewport instead of shrinking, even though the card itself has min-width:0.
       That's the actual mechanism behind every "no right-side padding" mobile report
       so far -- min-width:0 on the grid *item* doesn't help if the *track* itself
       refuses to shrink. Same reasoning applies to every grid-template-columns below. */
    grid-template-columns: repeat(6, minmax(0, 1fr));
    grid-auto-rows: auto;
    align-items: start;
    gap: 14px;
    padding: 18px 72px 60px;
}

/* Строка 1: три равных блока через обёртку */
.dsh-row3 {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px;
}
.dsh-row3 > .gc {
    display: flex;
    flex-direction: column;
}
.dsh-row3 > .gc > .gc-body {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
/* Cards in the row are equal height — pin each Save to the card bottom so they line up. */
.dsh-row3 .fg1 { flex: 1; display: flex; flex-direction: column; }
.dsh-row3 .form-foot { margin-top: auto; }

/* Клиенты без доступа к ОФД: карточка ОФД вообще не рендерится (см.
   dashboard.html), поэтому вместо трёх равных третей — база знаний растянута
   на 4/6, «Другое» занимает 2/6, тот же принцип долей, что у Ядро (2) +
   Шаблон (4) ниже. */
.dsh-row3-2 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.dsh-row3-2 #knowledge-base { grid-column: 1 / 5; }
.dsh-row3-2 #other { grid-column: 5 / 7; }

#ofd .gc-body textarea {
    max-height: 100px;
    overflow-y: auto;
    resize: vertical;
}

/* Ядро (2 кол) + Шаблон (4 кол) — бок о бок, шаблон растянут по высоте ядра */
#core     { grid-column: 1 / 3; }
#template {
    grid-column: 3 / 7;
    align-self: stretch;
    display: flex;
    flex-direction: column;
}
#template .gc-body {
    flex: 1;
    display: flex;
    flex-direction: column;
}
#template .gc-body .fg1 {
    flex: 1;
    display: flex;
    flex-direction: column;
}
#template .gc-body textarea {
    flex: 1;
    min-height: 80px;
    resize: none;
    overflow-y: auto;
}
[id^="template-"] { grid-column: 1 / -1; }
#flow          { grid-column: 1 / -1; }
#flow .gc-body { padding: 0; }
#schedule { grid-column: 1 / 3; }

/* История обращений + HTTP-инструменты — бок о бок, по половине ширины */
.dsh-row-half {
    grid-column: 1 / -1;
    display: flex;
    align-items: start;
    gap: 14px;
}
.dsh-row-half > .gc { flex: 1; min-width: 0; }

.schedule-grid { display: flex; flex-direction: column; gap: 6px; }
.schedule-row { display: flex; align-items: center; gap: 8px; }
.schedule-day-label {
    display: flex; align-items: center; gap: 6px;
    width: 52px; flex-shrink: 0; cursor: pointer;
}
.schedule-day-label input[type="checkbox"] { margin: 0; }
.schedule-row input[type="time"] { flex: 1; min-width: 0; }
.schedule-sep { color: var(--text-muted); flex-shrink: 0; }
.schedule-row input[type="time"]:disabled { opacity: 0.35; }

.placeholder-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: -2px; }
.placeholder-chip {
    font-size: 12px; font-weight: 600; padding: 5px 12px;
    border-radius: var(--r-sm);
    border: 1px solid var(--glass-border);
    background: var(--glass-heavy);
    backdrop-filter: var(--blur);
    color: var(--text-2); cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.placeholder-chip:hover {
    border-color: var(--accent);
    color: var(--accent);
    background: rgba(59,130,246,0.12);
}
/* Заполнение — 3 колонки, бок о бок с расписанием */
.dsh-row-filling {
    grid-column: 3 / 7;
    display: flex;
    align-items: flex-start;
    gap: 14px;
}
.dsh-row-filling > .gc {
    flex: 1;
    min-width: 0;
}

/* Сохранение — оверлей на карточке */
.gc-saving {
    position: relative;
    pointer-events: none;
    user-select: none;
}
.gc-saving::after {
    content: '';
    position: absolute; inset: 0;
    background: rgba(255,255,255,0.32);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    border-radius: inherit;
    z-index: 5;
}

/* .gc/.gc-head/.gc-title/.gc-body — see static/css/cards.css (shared with admin.css) */

/* ── Form controls ────────────────────────────────────────── */
label {
    display: block;
    font-size: 11px; font-weight: 700;
    color: var(--text-3);
    text-transform: uppercase; letter-spacing: 0.5px;
}

label > input[type=text],
label > input[type=email],
label > input[type=password],
label > input[type=time],
label > select,
label > textarea { margin-top: 5px; }

input[type=text],
input[type=email],
input[type=password],
input[type=time],
input[type=number],
select,
textarea {
    display: block; width: 100%;
    padding: 8px 12px;
    background: rgba(255,255,255,0.45);
    border: 1px solid var(--glass-border-soft);
    border-radius: var(--r-sm);
    font-family: 'Montserrat', sans-serif;
    font-size: 13px; font-weight: 500;
    color: var(--text-1);
    outline: none;
    transition: border-color 0.18s, background 0.18s, box-shadow 0.18s;
}
input[type=text]:focus,
input[type=email]:focus,
input[type=password]:focus,
input[type=time]:focus,
input[type=number]:focus,
select:focus,
textarea:focus {
    border-color: rgba(59,130,246,0.6);
    background: rgba(255,255,255,0.65);
    box-shadow: 0 0 0 3px rgba(59,130,246,0.1);
}
input::placeholder { color: var(--text-4); font-weight: 500; }
textarea::placeholder { color: var(--text-4); font-weight: 500; }
select {
    cursor: pointer;
    -webkit-appearance: none; appearance: none;
    height: 38px !important;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6' fill='none' stroke='%2394a3b8' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 10px;
    padding-right: 30px;
}
textarea { resize: vertical; min-height: 68px; }
input:-webkit-autofill,
input:-webkit-autofill:focus {
    box-shadow: 0 0 0 1000px rgba(240,249,255,0.9) inset !important;
    -webkit-text-fill-color: var(--text-1) !important;
    transition-delay: 9999s;
}

/* ── Range sliders ────────────────────────────────────────── */
.range-field { display: flex; flex-direction: column; gap: 6px; }
.range-header {
    display: flex; align-items: center; justify-content: space-between;
}
.range-label {
    font-size: 11px; font-weight: 700;
    color: var(--text-3); text-transform: uppercase; letter-spacing: 0.5px;
}
.range-val {
    font-size: 13px; font-weight: 700; color: var(--accent);
    min-width: 36px; text-align: right;
}

input[type=range] {
    -webkit-appearance: none; appearance: none;
    width: 100%; height: 4px;
    background: rgba(255,255,255,0.5);
    border-radius: 2px; outline: none; cursor: pointer;
    border: none; padding: 0;
    box-shadow: none;
}
input[type=range]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 18px; height: 18px; border-radius: 50%;
    background: var(--accent);
    border: 2px solid #fff;
    box-shadow: 0 1px 6px rgba(59,130,246,0.35);
    cursor: pointer; transition: background 0.15s, box-shadow 0.15s;
}
input[type=range]::-webkit-slider-thumb:hover {
    background: var(--accent-dark);
    box-shadow: 0 2px 10px rgba(59,130,246,0.5);
}
input[type=range]::-moz-range-thumb {
    width: 18px; height: 18px; border-radius: 50%;
    background: var(--accent);
    border: 2px solid #fff;
    box-shadow: 0 1px 6px rgba(59,130,246,0.35);
    cursor: pointer;
}

/* ── Tags ─────────────────────────────────────────────────── */
.tag {
    display: inline-block; padding: 3px 10px;
    border-radius: 20px; font-size: 11px; font-weight: 700;
}
.tag-pyrus    { background: rgba(59,130,246,0.1);  color: #1d4ed8; border: 1px solid rgba(59,130,246,0.25); }
.tag-telegram { background: rgba(6,182,212,0.1);   color: #0e7490; border: 1px solid rgba(6,182,212,0.25); }

/* ── Layout helpers ───────────────────────────────────────── */
.fg1 { display: flex; flex-direction: column; gap: 10px; }
.fg2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 14px; }
.fg2 .s2 { grid-column: 1 / -1; }
.fg3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 14px; align-items: end; }
.fg3 + .fg2 { align-items: end; }

/* ── Checkbox ─────────────────────────────────────────────── */
.checkbox-label {
    display: flex; align-items: center; gap: 7px;
    font-size: 13px; font-weight: 600; color: var(--text-2);
    text-transform: none; letter-spacing: 0; opacity: 1; cursor: pointer;
}
.checkbox-label input[type=checkbox] {
    width: 15px; height: 15px; margin-top: 0;
    cursor: pointer; accent-color: var(--accent);
}
.checkbox-group {
    display: flex; flex-direction: column; gap: 7px;
}

/* ── Buttons ──────────────────────────────────────────────── */
.add-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    padding: 0 16px; height: 36px; border-radius: 20px; font-size: 12px;
    font-weight: 700; font-family: 'Montserrat', sans-serif;
    background: var(--accent); color: #fff;
    border: 1px solid rgba(255,255,255,0.2); cursor: pointer;
    box-shadow: 0 2px 10px rgba(59,130,246,0.28);
    transition: background 0.18s, box-shadow 0.18s;
    flex-shrink: 0; white-space: nowrap;
    text-decoration: none;
}
.add-btn:hover { background: var(--accent-dark); box-shadow: 0 3px 14px rgba(59,130,246,0.38); }

.btn-save {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 22px; height: 36px; border-radius: 20px; cursor: pointer;
    background: var(--accent); color: #fff; font-weight: 700; font-size: 13px;
    border: 1px solid rgba(255,255,255,0.2);
    font-family: 'Montserrat', sans-serif;
    text-decoration: none;
    box-shadow: 0 2px 10px rgba(59,130,246,0.28);
    transition: background 0.18s, box-shadow 0.18s;
    white-space: nowrap;
}
.btn-save:hover { background: var(--accent-dark); box-shadow: 0 3px 14px rgba(59,130,246,0.38); }
.btn-save:disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; }
.btn-save.saved { background: #22c55e; box-shadow: 0 2px 10px rgba(34,197,94,0.3); }

.btn-cancel {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 22px; height: 36px; border-radius: 20px; cursor: pointer;
    background: rgba(255,255,255,0.35); color: var(--text-2); font-size: 13px;
    border: 1px solid var(--glass-border-soft);
    font-family: 'Montserrat', sans-serif; transition: background 0.18s;
    text-decoration: none;
}
.btn-cancel:hover { background: rgba(255,255,255,0.55); }

.btn-del {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 18px; height: 32px; border-radius: 20px; cursor: pointer;
    background: var(--danger); color: #fff; font-weight: 700; font-size: 12px;
    border: 1px solid rgba(255,255,255,0.2);
    font-family: 'Montserrat', sans-serif;
    text-decoration: none;
    box-shadow: 0 2px 10px rgba(239,68,68,0.28);
    transition: background 0.18s, box-shadow 0.18s;
}
.btn-del:hover { background: var(--danger-dark); box-shadow: 0 3px 14px rgba(239,68,68,0.38); }

/* ── Form footer ──────────────────────────────────────────── */
.form-foot {
    display: flex; justify-content: flex-end;
    padding-top: 14px;
    border-top: 1px solid var(--glass-border-soft);
    margin-top: 6px;
}

/* ── Section divider ──────────────────────────────────────── */
.md-sec { border-top: 1px solid var(--glass-border-soft); padding-top: 14px; margin-top: 14px; }
.md-sec-label {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 1px; color: var(--text-4); margin-bottom: 10px;
}

/* ── Channels block ───────────────────────────────────────── */
.channels-block {
    padding: 12px 14px;
    background: rgba(255,255,255,0.2);
    border: 1px solid var(--glass-border-soft);
    border-radius: var(--r-md);
    display: flex; flex-direction: column; gap: 7px;
}
.channels-label {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.8px; color: var(--text-4);
}
.channel-row {
    display: flex; justify-content: space-between; align-items: center;
}

/* ── Disabled setting ─────────────────────────────────────── */
.disabled-setting { opacity: 0.4; }

/* .gc-locked/.gc-lock-badge/.locked-inline — see static/css/cards.css */

/* ── Knowledge Base ───────────────────────────────────────── */
.kb-channel {
    padding: 12px 14px;
    background: rgba(255,255,255,0.18);
    border: 1px solid var(--glass-border-soft);
    border-radius: var(--r-md);
    display: flex; flex-direction: column; gap: 10px;
}
.kb-channel-head {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.kb-dot {
    width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0;
}
.kb-dot-active { background: #22c55e; }
.kb-dot-empty  { background: #f59e0b; }
.kb-channel-name {
    font-size: 12px; font-weight: 700;
    color: var(--text-2);
    text-transform: uppercase; letter-spacing: 0.5px;
}
.kb-channel-count {
    font-size: 12px; color: var(--text-3);
}
.kb-channel-empty {
    font-size: 11px; color: var(--text-4); font-weight: 600;
}
.kb-channel-btns {
    display: flex; gap: 6px; margin-left: auto; align-items: center;
}
.kb-btn {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 12px; height: 26px; border-radius: 13px; font-size: 11px; font-weight: 700;
    font-family: 'Montserrat', sans-serif; cursor: pointer; text-decoration: none;
    border: none; white-space: nowrap;
}
.kb-btn-dl {
    background: var(--accent); color: #fff;
    box-shadow: 0 1px 6px rgba(59,130,246,0.25);
    transition: background 0.15s;
}
.kb-btn-dl:hover { background: var(--accent-dark); }
/* Icon button, matches the admin panel's .ib/.ib.trash (30x30, subtle border, red on hover). */
.ib {
    display: inline-flex; align-items: center; justify-content: center;
    width: 30px; height: 26px; border-radius: var(--r-sm); cursor: pointer;
    background: rgba(255,255,255,0.3); color: var(--text-3);
    border: 1px solid var(--glass-border-soft); padding: 0;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    text-decoration: none; flex-shrink: 0;
}
.ib.trash:hover {
    background: rgba(239,68,68,0.1); color: var(--danger);
    border-color: rgba(239,68,68,0.3);
}
.kb-upload {
    display: flex; gap: 8px; align-items: center;
}
.kb-upload .file-drop { flex: 1; min-width: 0; }
.kb-upload .file-drop-label {
    padding: 8px 12px; font-size: 12px;
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.kb-upload .btn-save { height: 34px; flex-shrink: 0; }

/* ── File drop ────────────────────────────────────────────── */
.file-drop { position: relative; }
.file-drop input[type=file] {
    position: absolute; opacity: 0; width: 0; height: 0;
    pointer-events: none;
}
.file-drop-label {
    display: block; width: 100%;
    padding: 11px 16px;
    border: 2px dashed rgba(59,130,246,0.4);
    border-radius: var(--r-sm);
    background: rgba(59,130,246,0.04);
    color: var(--accent); font-size: 13px; font-weight: 600;
    text-align: center; cursor: pointer;
    transition: border-color 0.18s, background 0.18s;
}
.file-drop-label:hover {
    border-color: var(--accent);
    background: rgba(59,130,246,0.08);
}
.file-drop-label.has-file {
    border-color: #22c55e;
    background: rgba(34,197,94,0.06);
    color: #16a34a;
}

/* ── Dynamic fields ───────────────────────────────────────── */
.collapsed-field,
.expanded-field {
    background: rgba(255,255,255,0.22);
    border: 1px solid var(--glass-border-soft);
    border-radius: var(--r-md);
    padding: 10px 14px;
    display: flex;
    font-size: 13px;
    transition: transform 0.2s, box-shadow 0.2s;
}
.collapsed-field {
    justify-content: space-between;
    align-items: center;
    cursor: pointer;
}
.collapsed-field:hover {
    transform: scale(1.005);
    box-shadow: 0 4px 14px rgba(0,0,0,0.08);
}
.expanded-field {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
}
.expanded-field label { text-transform: uppercase; }
.field-del-btn {
    background: none;
    border: none;
    color: var(--text-4);
    font-size: 18px;
    line-height: 1;
    padding: 0 2px;
    cursor: pointer;
    flex-shrink: 0;
    margin-left: 8px;
    transition: color 0.15s;
}
.field-del-btn:hover { color: var(--danger); }

.btn-add-label {
    display: flex; align-items: center; justify-content: center;
    width: 100%; height: 36px; border-radius: 20px;
    background: var(--accent); color: #fff;
    font-size: 13px; font-weight: 700;
    font-family: 'Montserrat', sans-serif;
    border: 1px solid rgba(255,255,255,0.2);
    box-shadow: 0 2px 10px rgba(59,130,246,0.28);
    cursor: pointer; transition: background 0.18s, box-shadow 0.18s;
}
.btn-add-label:hover { background: var(--accent-dark); box-shadow: 0 3px 14px rgba(59,130,246,0.38); }

.done-button {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 16px; height: 30px; border-radius: 20px;
    background: var(--accent); color: #fff;
    font-size: 12px; font-weight: 700;
    font-family: 'Montserrat', sans-serif;
    border: 1px solid rgba(255,255,255,0.2);
    cursor: pointer; transition: background 0.18s;
    align-self: flex-end;
}
.done-button:hover { background: var(--accent-dark); }

/* ── Utilities ────────────────────────────────────────────── */
.ok  { color: #16a34a; font-weight: 700; }
.nok { color: var(--text-4); }

/* ── Knowledge Base hint ──────────────────────────────────── */
.kb-hint {
    padding: 12px 14px;
    background: rgba(255,255,255,0.2);
    border: 1px solid var(--glass-border-soft);
    border-radius: var(--r-md);
}
.kb-hint-label {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.8px; color: var(--text-2); margin-bottom: 8px;
}
.kb-hint-code {
    font-family: 'Courier New', monospace; font-size: 11px;
    color: var(--text-1); line-height: 1.6;
    white-space: pre; overflow-x: auto; margin: 0;
}

/* ── Flow Canvas ──────────────────────────────────────────── */
#flow-canvas-wrap {
    position: relative;
    height: 580px;
    overflow: hidden;
    cursor: grab;
    background-image:
        repeating-linear-gradient(0deg, transparent, transparent 24px, rgba(0,0,0,0.06) 24px, rgba(0,0,0,0.06) 25px),
        repeating-linear-gradient(90deg, transparent, transparent 24px, rgba(0,0,0,0.06) 24px, rgba(0,0,0,0.06) 25px);
    border-radius: 0 0 var(--r-xl) var(--r-xl);
    border-top: 1px solid var(--glass-border-soft);
    user-select: none;
    touch-action: none;
}
#flow-canvas-wrap.grabbing { cursor: grabbing; }
#flow-viewport { position: absolute; inset: 0; transform-origin: 0 0; }
#flow-svg {
    position: absolute; left: 0; top: 0;
    width: 6000px; height: 6000px;
    overflow: visible; pointer-events: none;
}
#flow-canvas { position: absolute; inset: 0; }
#flow-hint {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--text-4); font-size: 13px; font-weight: 600;
    pointer-events: none;
}

.fn-card {
    width: 280px;
    background: rgba(255,255,255,0.88);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border: 1.5px solid var(--glass-border);
    border-radius: var(--r-md);
    box-shadow: 0 4px 20px rgba(31,38,135,0.1);
    font-size: 12px;
    color: var(--text-1);
    z-index: 10;
    transition: box-shadow 0.15s;
}
.fn-card:hover { box-shadow: 0 6px 28px rgba(31,38,135,0.15); }
.fn-card.is-start { border-color: var(--accent); box-shadow: 0 4px 20px rgba(59,130,246,0.22); }
.fn-card.selected { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(59,130,246,0.2), 0 4px 20px rgba(59,130,246,0.18); }

#flow-node-preview { border-top: 1px solid var(--glass-border-soft); padding: 12px 16px 14px; background: rgba(248,250,252,0.6); }
.fnp-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.fnp-head-title { font-size: 12px; font-weight: 600; color: var(--text-2); flex: 1; }
.fnp-hint { font-size: 11px; color: var(--text-3); }
.fnp-close { background: none; border: none; color: var(--text-3); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px; }
.fnp-close:hover { color: var(--text-1); }
#fnp-content { font-family: 'SF Mono','Fira Code','Consolas',monospace; font-size: 12px; line-height: 1.65; color: var(--text-2); background: rgba(255,255,255,0.65); border: 1px solid var(--glass-border-soft); border-radius: 6px; padding: 10px 12px; margin: 0; white-space: pre-wrap; word-break: break-word; }

.fn-header {
    position: relative;
    display: flex; align-items: center; gap: 6px;
    padding: 9px 10px 9px 20px;
    background: rgba(255,255,255,0.5);
    border-radius: var(--r-md) var(--r-md) 0 0;
    cursor: move;
    border-bottom: 1px solid var(--glass-border-soft);
}
.fn-port-in {
    position: absolute; left: -7px; top: 50%; transform: translateY(-50%);
    width: 13px; height: 13px; border-radius: 50%;
    background: #fff; border: 2.5px solid var(--accent);
    box-shadow: 0 1px 4px rgba(59,130,246,0.3);
    z-index: 11;
}
.fn-name {
    flex: 1; min-width: 0;
    background: transparent; border: none;
    font-size: 12px; font-weight: 700; color: var(--text-1);
    font-family: 'Montserrat', sans-serif; outline: none; cursor: text;
}
.fn-start-badge {
    font-size: 9px; font-weight: 700; color: var(--accent);
    background: rgba(59,130,246,0.1); border: 1px solid rgba(59,130,246,0.3);
    border-radius: 10px; padding: 1px 6px; flex-shrink: 0;
}
.fn-mkstart, .fn-del {
    background: none; border: none; cursor: pointer;
    padding: 2px; flex-shrink: 0; line-height: 1;
    transition: color 0.15s; color: var(--text-4);
    display: flex; align-items: center; justify-content: center;
    opacity: 0.5;
}
.fn-card:hover .fn-mkstart,
.fn-card:hover .fn-del { opacity: 1; }
.fn-mkstart:hover { color: var(--accent); }
.fn-del:hover { color: var(--danger); }

.fn-body { padding: 8px 10px; }
.fn-instr {
    width: 100%; box-sizing: border-box;
    background: rgba(255,255,255,0.6);
    border: 1px solid var(--glass-border-soft);
    border-radius: var(--r-sm);
    padding: 6px 8px;
    font-size: 11px; font-family: 'Montserrat', sans-serif;
    color: var(--text-1); resize: vertical; min-height: 58px; outline: none;
    transition: border-color 0.15s;
}
.fn-instr:focus { border-color: rgba(59,130,246,0.5); background: rgba(255,255,255,0.88); }

.fn-section-label { font-size: 10px; font-weight: 600; color: var(--text-4); text-transform: uppercase; letter-spacing: 0.05em; padding-bottom: 5px; }
.fn-body .fn-section-label { padding-bottom: 4px; }
.fn-tools-section { padding: 8px 10px; border-top: 1px solid var(--glass-border-soft); }
.fn-tools { display: flex; gap: 10px; flex-wrap: wrap; }
.fn-tool-label { display: flex; align-items: center; gap: 3px; font-size: 11px; color: var(--text-3); cursor: pointer; user-select: none; }
.fn-tool-label input { margin: 0; cursor: pointer; accent-color: var(--accent); }
.fn-tool-label:hover { color: var(--text-2); }
.fn-tool-http { font-family: monospace; font-size: 10px; color: var(--accent); opacity: .75; }
.fn-tool-http:hover { opacity: 1; }

.fn-transitions { padding: 8px 10px; border-top: 1px solid var(--glass-border-soft); display: flex; flex-direction: column; gap: 4px; }
.fn-trans-row { position: relative; display: flex; align-items: center; gap: 4px; padding-right: 14px; }
.ft-cond, .ft-tgt {
    min-width: 0;
    background: rgba(255,255,255,0.6);
    border: 1px solid var(--glass-border-soft);
    border-radius: 4px; padding: 3px 6px;
    font-size: 10px; font-family: 'Montserrat', sans-serif; color: var(--text-2);
    outline: none; transition: border-color 0.15s;
}
.ft-cond { flex: 1; }
.ft-tgt  { flex: 2; cursor: pointer; padding: 3px 20px 3px 4px; }
.ft-cond:focus, .ft-tgt:focus { border-color: rgba(59,130,246,0.4); background: rgba(255,255,255,0.88); }
.ft-arr { color: var(--text-4); flex-shrink: 0; font-size: 10px; }
.ft-del-btn {
    background: none; border: none; color: var(--text-4);
    cursor: pointer; padding: 0; font-size: 15px; flex-shrink: 0;
    line-height: 1; transition: color 0.15s;
}
.ft-del-btn:hover { color: var(--danger); }
.fn-trans-port {
    position: absolute; right: -7px; top: 50%; transform: translateY(-50%);
    width: 12px; height: 12px; border-radius: 50%;
    background: var(--accent); border: 2px solid #fff;
    box-shadow: 0 1px 4px rgba(59,130,246,0.35);
    pointer-events: none;
}
.fn-addtr {
    width: 100%; background: none;
    border: 1px dashed rgba(148,163,184,0.55);
    border-radius: var(--r-sm); padding: 4px;
    font-size: 11px; font-family: 'Montserrat', sans-serif; color: var(--text-3);
    cursor: pointer; transition: border-color 0.15s, color 0.15s;
}
.fn-addtr:hover { border-color: var(--accent); color: var(--accent); }


#flow-help-side {
    position: absolute; top: 0; right: 0;
    width: 240px; height: 100%;
    background: rgba(255,255,255,0.97);
    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
    border-left: 1px solid var(--glass-border-soft);
    z-index: 30; padding: 16px 14px;
    transform: translateX(100%);
    transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
    overflow-y: auto; box-sizing: border-box;
}
#flow-help-side.open { transform: translateX(0); }
#flow-help-side ul { font-size: 12px; color: var(--text-2); line-height: 2.1; margin: 0; padding-left: 14px; }
#flow-help-side li { margin-bottom: 2px; }

#flow-zoom-controls {
    position: absolute; bottom: 14px; right: 14px;
    display: flex; align-items: center; gap: 2px;
    z-index: 20;
    background: rgba(255,255,255,0.88);
    backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--glass-border-soft);
    border-radius: 20px; padding: 3px 8px;
    box-shadow: 0 2px 10px rgba(31,38,135,0.08);
}
#flow-zoom-controls button {
    background: none; border: none;
    color: var(--text-2); font-size: 15px; font-weight: 700;
    cursor: pointer; width: 24px; height: 24px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    transition: background 0.15s, color 0.15s;
    font-family: 'Montserrat', sans-serif; line-height: 1;
}
#flow-zoom-controls button:hover { background: rgba(59,130,246,0.1); color: var(--accent); }
#flow-zoom-val {
    font-size: 11px; font-weight: 700; color: var(--text-3);
    min-width: 36px; text-align: center; user-select: none;
}

/* ── Channel pills ────────────────────────────────────────── */
.ch-pills {
    display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
}
.ch-pill {
    padding: 3px 10px; border-radius: 20px;
    font-size: 11px; font-weight: 600; font-family: 'Montserrat', sans-serif;
    border: 1px solid var(--glass-border-soft);
    background: rgba(255,255,255,0.4);
    color: var(--text-3); cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    white-space: nowrap;
}
.ch-pill:hover { color: var(--text-2); background: rgba(255,255,255,0.65); }
.ch-pill-active {
    background: var(--accent); color: #fff; border-color: var(--accent);
}
.ch-pill-active:hover { background: var(--accent-dark, #2563eb); color: #fff; }

.tpl-tabs { display: flex; gap: 2px; background: rgba(255,255,255,0.3); border-radius: 20px; padding: 3px; }
.tpl-tab {
    padding: 3px 12px; border-radius: 20px; border: none;
    font-size: 11px; font-weight: 600; font-family: 'Montserrat', sans-serif;
    color: var(--text-3); background: transparent; cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.tpl-tab-active { background: var(--accent); color: #fff; }

/* ── Header (all authenticated + public pages, see public_header() in _macros.html) ──
   Floating glass pill, visually identical to the marketing site's Header.astro on
   barryagent.com. Same component everywhere now -- .adm-header above shares this
   exact visual language rather than a separate flat full-width bar. */
.pub-header-wrap {
    position: fixed; top: 0; left: 0; right: 0; z-index: 100;
    display: flex; justify-content: center; padding: 0 20px;
}
.pub-header {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    width: 100%; max-width: 1152px; margin-top: 16px; padding: 10px 20px;
    border-radius: var(--r-xl);
    background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
    border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow);
}
.pub-header-brand img { height: 28px; width: auto; display: block; }
.pub-header-actions { display: flex; align-items: center; gap: 10px; }
.pub-header-back {
    font-size: 12px; font-weight: 700; color: var(--text-3); text-decoration: none;
    opacity: 0.8; transition: opacity 0.18s; padding: 5px 14px; border-radius: 20px;
    border: 1px solid rgba(100,116,139,0.22); background: rgba(100,116,139,0.06);
}
.pub-header-back:hover { opacity: 1; }
.pub-header-cta {
    font-size: 12.5px; font-weight: 700; font-family: 'Montserrat', sans-serif;
    color: #fff; text-decoration: none; white-space: nowrap;
    padding: 8px 16px; border-radius: 20px;
    background: var(--accent); border: 1px solid rgba(255,255,255,0.2);
    box-shadow: 0 2px 10px rgba(59,130,246,0.28);
    transition: background 0.18s, box-shadow 0.18s;
}
.pub-header-cta:hover { background: var(--accent-dark); box-shadow: 0 3px 14px rgba(59,130,246,0.38); }

/* ── Footer (all authenticated + public pages, see public_footer() in _macros.html) ──
   Flows normally at the end of the page instead of pinning to the viewport bottom,
   matching the glass-card footer on barryagent.com. Used app-wide now -- nothing
   below needs to reserve fixed screen space for a permanently-visible footer bar
   any more (see .dsh-layout, .sc-toggle/.sc-panel and the removed mobile-wrap
   override that used to exist here for the old always-fixed .site-footer). */
.pub-footer-wrap { max-width: 760px; margin: 24px auto 32px; padding: 0 20px; }
.pub-footer {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
    gap: 12px; padding: 14px 20px; border-radius: var(--r-xl);
    background: var(--glass); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
    border: 1px solid var(--glass-border); box-shadow: var(--glass-shadow);
    font-size: 12px; color: var(--text-3);
}
.pub-footer-brand { display: flex; align-items: center; gap: 8px; font-weight: 700; color: var(--text-2); }
.pub-footer-wordmark { display: inline-flex; color: var(--text-2); }
.pub-footer-wordmark svg { height: 16px; width: auto; display: block; }
.pub-footer-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 16px; }
.pub-footer-link { color: var(--text-3); font-weight: 600; text-decoration: none; transition: color 0.15s; }
.pub-footer-link:hover { color: var(--accent); }

/* ── Responsive ───────────────────────────────────────────── */
@media (max-width: 1024px) {
    .dsh-content { padding: 14px 36px 50px; }
}

@media (max-width: 860px) {
    .dsh-sidebar { display: none; }
    .dsh-layout { padding-left: 0; }
    .adm-header-wrap { padding: 0 14px; }
    .adm-header { padding: 8px 14px; }
    .dsh-content { padding: 14px 16px 40px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .dsh-row3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .dsh-row3-2 #knowledge-base, .dsh-row3-2 #other { grid-column: auto; }
    #core, #template, [id^="template-"], #schedule, .dsh-row-filling { grid-column: 1 / -1; }
    .dsh-row-filling { flex-wrap: wrap; }
    .dsh-row-filling > .gc { flex: 1 1 calc(50% - 7px); }
    .dsh-row-half { flex-wrap: wrap; }
    .dsh-row-half > .gc { flex: 1 1 calc(50% - 7px); }
    .fg2 { grid-template-columns: minmax(0, 1fr); }
    .fg3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 600px) {
    /* .adm-header-right's own children (Биллинг/username/bell/Выйти) never wrapped
       internally (flex-wrap defaulting to nowrap), so on a narrow phone they just
       overflowed the header pill instead of dropping to a second line. */
    /* Wraps as ONE unit onto its own full-width row below the logo, instead of
       letting individual items wrap one at a time (a lone "Выйти" stranding itself
       on a second line, disconnected from the rest of the row -- what "kind of
       crooked" turned out to mean). Items stay on a single line within that row;
       .adm-account-label is the only one allowed to shrink/ellipsis if still tight. */
    /* flex-shrink:0 in the base rule (needed on desktop so it never competes with the
       logo for space) is exactly what let this overflow its own header pill instead
       of shrinking to fit -- flex-basis:100% is only a *starting* size, it doesn't
       override flex-shrink:0 refusing to go below the content's natural width. */
    .adm-header-right { flex-basis: 100%; min-width: 0; flex-shrink: 1; justify-content: space-between; gap: 8px; }
    /* dashboard.html's own header groups: on desktop the DOM order (brand, links,
       quick) is already brand-left/links-next/quick-right via .adm-header's
       space-between. On a narrow phone .adm-header-links can't share a line with
       both -- it's reordered after .adm-header-quick and forced onto its own full
       row below, so row 1 keeps exactly two items (brand, quick) and .adm-header's
       same space-between then pushes quick to the row's right edge, brand to the
       left -- account/bell/Выйти belong on the right by the same convention as
       desktop, not crammed next to the logo. */
    /* The desktop grid (.adm-header-3col) is what centers .adm-header-links between
       two unequal side columns -- on a phone that column no longer exists (row 2 is
       its own full-width line), so back to plain flex + order for the row1/row2
       split described above. */
    .adm-header-3col { display: flex; }
    .adm-header-quick { order: 2; min-width: 0; flex-shrink: 1; }
    .adm-header-links { order: 3; flex-basis: 100%; min-width: 0; justify-content: space-between; gap: 8px; }
    .adm-header-links .adm-user { min-width: 0; }
    /* iOS Safari auto-zooms the page on focus for any input/select/textarea with a
       computed font-size under 16px -- the login form (13px) is what triggers it.
       16px here only, desktop keeps the compact 13px. */
    input[type=text], input[type=email], input[type=password], input[type=time],
    input[type=number], select, textarea { font-size: 16px; }
    .dsh-content { padding: 12px 12px 32px; grid-template-columns: minmax(0, 1fr); }
    .dsh-row3 { grid-template-columns: minmax(0, 1fr); }
    .dsh-row3-2 #knowledge-base, .dsh-row3-2 #other { grid-column: auto; }
    .dsh-row3 > .gc { max-height: none; }
    .dsh-row-filling { flex-direction: column; }
    .dsh-row-filling > .gc { flex: none; width: 100%; }
    .dsh-row-half { flex-direction: column; }
    .dsh-row-half > .gc { flex: none; width: 100%; }
    .fg3 { grid-template-columns: minmax(0, 1fr); }
    .adm-header-wrap { padding: 0 10px; }
    .adm-header { min-height: 42px; margin-top: 10px; padding: 7px 12px; gap: 8px; }
    .dsh-tabbar { margin-top: 6px; padding: 4px 10px; }
    .dsh-layout { padding-top: 120px; } /* .dsh-sidebar itself is display:none already at 860px */
    .dsh-tab { padding: 5px 11px; }
    .dsh-tab-name { font-size: 12px; }
    #flow-canvas-wrap { height: 420px; }
    .fn-card { width: 220px; }
    /* Flow header: stack vertically */
    #flow .gc-head {
        flex-wrap: wrap;
        justify-content: flex-start;
        gap: 8px;
        padding: 10px 14px;
    }
    #flow .gc-title { flex: 0 0 100%; }
    #flow-btn-row {
        flex: 0 0 100%;
        gap: 6px;
    }
    #flow-ch-pills { flex: 0 0 100%; }
    /* Template header: allow pills to wrap */
    #template .gc-head { flex-wrap: wrap; gap: 6px; }
    #tpl-pills { flex: 0 0 100%; }

}

/* ── KB Constructor page ──────────────────────────────────── */
.kbc-layout {
    max-width: 1100px;
    margin: 0 auto;
    padding: 80px 32px 60px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.kbc-page-header {
    padding: 4px 0 8px;
}
.kbc-title {
    font-size: 17px;
    font-weight: 700;
    color: var(--text-1);
}
.kbc-section .gc-body { display: flex; flex-direction: column; gap: 12px; }

/* Search panel */
.kbc-search-row {
    display: flex; gap: 8px; align-items: center;
}
.kbc-search-row input[type=text] { flex: 1; }
.kbc-search-row select { width: 140px; flex-shrink: 0; }
.kbc-search-row .btn-save { flex-shrink: 0; }
.kbc-search-results {
    display: flex; flex-direction: column; gap: 8px;
}
.kbc-result-item {
    background: rgba(255,255,255,0.18);
    border: 1px solid var(--glass-border-soft);
    border-radius: var(--r-md);
    padding: 10px 14px;
}
.kbc-result-num {
    font-size: 10px; font-weight: 700; color: var(--text-4);
    text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 2px;
}
.kbc-result-cat {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.6px; color: var(--accent); margin-bottom: 3px;
}
.kbc-result-problem {
    font-size: 13px; font-weight: 600; color: var(--text-1); margin-bottom: 6px;
}
.kbc-result-solution {
    font-size: 12px; color: var(--text-2); line-height: 1.5;
    white-space: pre-wrap; max-height: 120px; overflow-y: auto;
}
.kbc-search-empty {
    font-size: 13px; color: var(--text-3); font-weight: 600; padding: 4px 0;
}

/* Filter bar */
.kbc-filter-bar {
    display: flex; gap: 8px;
}
.kbc-filter-input { flex: 1; }
.kbc-filter-select { width: 180px; flex-shrink: 0; }

/* Table */
.kbc-table-wrap { overflow-x: auto; }
.kbc-table {
    width: 100%; border-collapse: collapse; font-size: 13px;
}
.kbc-table th {
    text-align: left; font-size: 10px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-3);
    padding: 8px 12px; border-bottom: 1px solid var(--glass-border-soft);
}
.kbc-table td {
    padding: 9px 12px; border-bottom: 1px solid rgba(255,255,255,0.18);
    vertical-align: middle; color: var(--text-1);
}
.kbc-table tr:last-child td { border-bottom: none; }
.kbc-table tr:hover td { background: rgba(255,255,255,0.1); }
.kbc-td-id {
    font-size: 11px; font-family: 'Courier New', monospace; color: var(--text-3);
    max-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kbc-td-cat { font-weight: 600; white-space: nowrap; }
.kbc-td-problem {
    max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kbc-td-kw {
    font-size: 11px; color: var(--text-3);
    max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kbc-td-ch {
    font-size: 11px; font-weight: 700; color: var(--text-3);
    text-transform: uppercase; white-space: nowrap;
}
.kbc-td-actions { white-space: nowrap; text-align: right; width: 1%; }
.kbc-btn-edit, .kbc-btn-del {
    background: none; border: none; cursor: pointer;
    font-size: 15px; padding: 4px 6px; border-radius: var(--r-sm);
    transition: background 0.15s; font-family: 'Montserrat', sans-serif; line-height: 1;
}
.kbc-btn-edit { color: var(--accent); }
.kbc-btn-edit:hover { background: rgba(59,130,246,0.1); }
.kbc-btn-del { color: var(--danger); }
.kbc-btn-del:hover { background: rgba(239,68,68,0.1); }

/* Modal chrome (.mo/.md) — see static/css/cards.css. Only the error box stays here. */
.kbc-modal-error {
    font-size: 12px; color: var(--danger); font-weight: 600;
    padding: 8px 12px; background: rgba(239,68,68,0.08); border-radius: var(--r-sm);
}

/* ── KB Constructor Pro (3-panel layout) ───────────────────────────── */
body.kbc-pro-page {
    display: flex; flex-direction: column; height: 100vh; overflow: hidden;
}
body.kbc-pro-page .adm-header-wrap { position: relative; left: auto; right: auto; padding: 0 20px; flex-shrink: 0; }
.kbc-pro-body {
    flex: 1; display: flex; overflow: hidden; min-height: 0;
}
body.kbc-pro-page .pub-footer-wrap { flex-shrink: 0; }

/* Left panel */
.kbc-pro-left {
    width: 260px; flex-shrink: 0; display: flex; flex-direction: column;
    border-right: 1px solid var(--glass-border-soft);
    background: var(--glass-heavy);
    backdrop-filter: var(--blur-heavy); -webkit-backdrop-filter: var(--blur-heavy);
    overflow: hidden;
}
.kbc-pro-search-wrap {
    display: flex; align-items: center; gap: 8px;
    padding: 12px 14px; border-bottom: 1px solid var(--glass-border-soft);
    flex-shrink: 0;
}
.kbc-pro-search-wrap svg { color: var(--text-4); flex-shrink: 0; }
.kbc-pro-search-wrap input {
    flex: 1; border: none; background: transparent; outline: none;
    font-family: 'Montserrat', sans-serif; font-size: 12px; color: var(--text-1);
}
.kbc-pro-search-wrap input::placeholder { color: var(--text-4); }
.kbc-pro-tree { flex: 1; overflow-y: auto; padding: 8px 0; }
.kbc-tree-empty { padding: 20px 14px; font-size: 12px; color: var(--text-4); }

.kbc-tree-block { }
.kbc-tree-cat {
    display: flex; align-items: center; gap: 6px;
    padding: 7px 14px; cursor: pointer; user-select: none;
    font-size: 11px; font-weight: 700; color: var(--text-3);
    text-transform: uppercase; letter-spacing: 0.04em;
    transition: background 0.12s;
}
.kbc-tree-cat:hover { background: rgba(255,255,255,0.12); }
.kbc-tree-arrow { flex-shrink: 0; transition: transform 0.15s; }
.kbc-tree-cat-name { flex: 1; }
.kbc-tree-count {
    font-size: 10px; font-weight: 700; color: var(--text-2);
    background: rgba(255,255,255,0.28); padding: 1px 7px; border-radius: 8px;
}
.kbc-tree-items { }
.kbc-tree-item {
    padding: 6px 14px 6px 30px;
    font-size: 12px; color: var(--text-2); cursor: pointer;
    border-left: 2px solid transparent;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
    line-height: 1.4;
}
.kbc-tree-item:hover { background: rgba(255,255,255,0.1); color: var(--text-1); }
.kbc-tree-item-active {
    background: rgba(59,130,246,0.12); color: var(--accent);
    border-left-color: var(--accent); font-weight: 600;
}

/* Center panel */
.kbc-pro-center {
    flex: 1; display: flex; flex-direction: column; overflow: hidden;
    background: rgba(248,250,252,0.65);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
}
.kbc-pro-n8n-ph {
    flex: 1; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 10px; color: var(--text-4);
}
.kbc-pro-n8n-title { font-size: 15px; font-weight: 700; color: var(--text-3); }
.kbc-pro-n8n-sub { font-size: 12px; color: var(--text-4); text-align: center; line-height: 1.6; }
.kbc-pro-n8n-active { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.kbc-pro-n8n-item-title {
    padding: 14px 20px; font-size: 13px; font-weight: 600; color: var(--text-2);
    border-bottom: 1px solid var(--glass-border-soft); flex-shrink: 0;
    background: var(--glass);
}
.kbc-pro-n8n-workspace {
    flex: 1; display: flex; align-items: center; justify-content: center;
}
.kbc-pro-n8n-coming {
    font-size: 13px; color: var(--text-4); font-weight: 600;
}

/* Right panel */
.kbc-pro-right {
    width: 320px; flex-shrink: 0; display: flex; flex-direction: column;
    border-left: 1px solid var(--glass-border-soft);
    background: var(--glass-heavy);
    backdrop-filter: var(--blur-heavy); -webkit-backdrop-filter: var(--blur-heavy);
    overflow: hidden;
}
.kbc-pro-form-empty {
    flex: 1; display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 10px; color: var(--text-4);
    font-size: 13px; text-align: center; line-height: 1.6;
}
.kbc-pro-form {
    flex: 1; display: flex; flex-direction: column; overflow: hidden;
}
.kbc-pro-form-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 16px; border-bottom: 1px solid var(--glass-border-soft);
    flex-shrink: 0; font-size: 13px; font-weight: 700; color: var(--text-1);
}
.kbc-pro-form-body {
    flex: 1; overflow-y: auto; padding: 14px 16px;
    display: flex; flex-direction: column; gap: 12px;
}
.kbc-pro-form-body label {
    display: flex; flex-direction: column; gap: 4px;
    font-size: 11px; font-weight: 700; color: var(--text-2);
    text-transform: uppercase; letter-spacing: 0.04em;
}
.kbc-pro-form-body input[type=text],
.kbc-pro-form-body textarea,
.kbc-pro-form-body select {
    width: 100%; box-sizing: border-box;
    background: rgba(255,255,255,0.75); border: 1px solid rgba(0,0,0,0.15);
    border-radius: 8px; padding: 7px 10px;
    font-family: 'Montserrat', sans-serif; font-size: 12px; color: var(--text-1);
    resize: vertical; outline: none; transition: border-color 0.15s, background 0.15s;
}
.kbc-pro-form-body input[type=text]:focus,
.kbc-pro-form-body textarea:focus,
.kbc-pro-form-body select:focus {
    background: #fff; border-color: var(--accent);
}
.kbc-pro-opt { font-size: 10px; font-weight: 400; color: var(--text-4); text-transform: none; letter-spacing: 0; }
.kbc-pro-form-actions { margin-top: 4px; }
.kbc-pro-form-actions .btn-save { width: 100%; justify-content: center; }

/* ── KB Pro: flow canvas layout ──────────────────────────────────────────── */
.kbc-flow-active {
    flex: 1; display: flex; flex-direction: column; overflow: hidden;
}
.kbc-flow-toolbar {
    display: flex; align-items: center; gap: 12px;
    padding: 9px 14px; border-bottom: 1px solid rgba(0,0,0,0.08);
    background: rgba(255,255,255,0.35); backdrop-filter: blur(8px); flex-shrink: 0;
}
.kbc-flow-article-title {
    flex: 1; min-width: 0;
    font-size: 12px; font-weight: 600; color: var(--text-2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kbc-flow-toolbar-right { display: flex; gap: 7px; flex-shrink: 0; }
.kbc-flow-btn {
    padding: 5px 11px; border-radius: 7px; font-size: 11.5px; font-weight: 600;
    border: 1px solid rgba(0,0,0,0.14); background: rgba(255,255,255,0.65);
    color: var(--text-2); cursor: pointer; font-family: inherit; transition: background 0.12s;
}
.kbc-flow-btn:hover { background: rgba(255,255,255,0.92); }
.kbc-flow-btn-primary { background: var(--accent); border-color: var(--accent-dark); color: #fff; }
.kbc-flow-btn-primary:hover { background: var(--accent-dark); }
.kbc-flow-btn:disabled { opacity: 0.55; cursor: not-allowed; }

.kbc-flow-hint {
    position: absolute; inset: 0; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 12px; color: var(--text-4);
    z-index: 10; pointer-events: none;
}
.kbc-flow-hint p { font-size: 13px; }

.kbc-flow-canvas-wrap {
    position: relative; flex: 1; overflow: hidden; cursor: default; min-height: 0;
    backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur);
    background-image:
        repeating-linear-gradient(0deg, transparent, transparent 24px, rgba(0,0,0,0.06) 24px, rgba(0,0,0,0.06) 25px),
        repeating-linear-gradient(90deg, transparent, transparent 24px, rgba(0,0,0,0.06) 24px, rgba(0,0,0,0.06) 25px);
}
.kbc-flow-svg {
    position: absolute; left: 0; top: 0;
    width: 4000px; height: 4000px;
    overflow: visible; pointer-events: none; z-index: 0;
}
.kbc-flow-viewport { position: absolute; inset: 0; transform-origin: 0 0; }
.kbc-flow-canvas  { position: relative; width: 4000px; height: 4000px; z-index: 1; }

/* ── KB flow node cards ──────────────────────────────────────────────────── */
.kbf-card {
    width: 260px;
    background: #fff; border: 1.5px solid #e2e8f0;
    border-radius: 10px; box-shadow: 0 1px 4px rgba(0,0,0,0.07), 0 4px 16px rgba(0,0,0,0.05);
    cursor: default; user-select: none; font-size: 12px;
    transition: box-shadow 0.15s;
}
.kbf-card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.1), 0 6px 20px rgba(0,0,0,0.07); }
.kbf-card.is-start { border-color: #3b82f6; box-shadow: 0 0 0 3px rgba(59,130,246,0.15), 0 4px 16px rgba(0,0,0,0.08); }

/* Link: violet */
.kbf-card.kbf-link { border-color: #7c3aed; }
.kbf-card.kbf-link .kbf-header { background: #ede9fe; }
.kbf-card.kbf-link .kbf-port-in { border-color: #7c3aed; }
.kbf-card.kbf-link .kbf-type-pill.active { background: #7c3aed; border-color: #6d28d9; color: #fff; }

/* End: emerald */
.kbf-card.kbf-end { border-color: #10b981; }
.kbf-card.kbf-end .kbf-header { background: #ecfdf5; }
.kbf-card.kbf-end .kbf-port-in { border-color: #10b981; }
.kbf-card.kbf-end .kbf-type-pill.active { background: #10b981; border-color: #059669; color: #fff; }

/* ── Node header ─────────────────────────────────────────────────────────── */
.kbf-header {
    display: flex; align-items: center; gap: 5px;
    padding: 8px 8px 8px 10px;
    border-bottom: 1px solid #f1f5f9;
    border-radius: 9px 9px 0 0;
    background: #f8fafc;
    cursor: move;
}
.kbf-port-in {
    width: 10px; height: 10px; flex-shrink: 0;
    border-radius: 50%; border: 2px solid #3b82f6; background: #fff;
    cursor: default;
}
.kbf-name-input {
    flex: 1; min-width: 0;
    border: none; background: transparent; outline: none;
    font-family: inherit; font-size: 12px; font-weight: 700;
    color: var(--text-1); padding: 0;
}
.kbf-name-input::placeholder { color: var(--text-4); font-weight: 400; }
.kbf-start-badge {
    font-size: 9px; font-weight: 700; letter-spacing: 0.6px;
    color: var(--accent); background: rgba(59,130,246,0.1);
    border-radius: 4px; padding: 2px 5px; flex-shrink: 0; white-space: nowrap;
}
.kbf-mkstart {
    border: none; background: none; color: var(--text-4);
    cursor: pointer; padding: 2px; flex-shrink: 0; line-height: 1;
    display: flex; align-items: center;
}
.kbf-mkstart:hover { color: #f59e0b; }
.kbf-del {
    border: none; background: none; color: var(--text-4);
    cursor: pointer; padding: 2px; flex-shrink: 0; line-height: 1;
    display: flex; align-items: center; opacity: 0;
    transition: opacity 0.12s;
}
.kbf-card:hover .kbf-del { opacity: 1; }
.kbf-del:hover { color: var(--danger); }

/* ── Type pills ─────────────────────────────────────────────────────────── */
.kbf-type-pills {
    display: flex; gap: 4px;
    padding: 6px 10px 0;
}
.kbf-type-pill {
    flex: 1; padding: 3px 0; border-radius: 5px; font-size: 10px; font-weight: 700;
    border: 1.5px solid #e2e8f0; background: none; color: var(--text-4);
    cursor: pointer; font-family: inherit; text-align: center;
    transition: all 0.12s;
}
.kbf-type-pill:hover { border-color: #cbd5e1; color: var(--text-3); }
.kbf-card .kbf-type-pill.active { background: #3b82f6; border-color: #2563eb; color: #fff; }

/* ── Node body (instruction) ─────────────────────────────────────────────── */
.kbf-body { padding: 8px 10px; }
.kbf-sec-label {
    font-size: 9.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.6px; color: var(--text-4); margin-bottom: 4px;
}
.kbf-instr {
    width: 100%; box-sizing: border-box; resize: vertical; overflow: auto;
    border: 1px solid #e2e8f0; border-radius: 6px;
    background: #f8fafc; padding: 6px 8px;
    font-family: inherit; font-size: 11px; color: var(--text-2); line-height: 1.5;
    outline: none; transition: border-color 0.12s, background 0.12s;
    min-height: 54px;
}
.kbf-instr:focus { border-color: #94a3b8; background: #fff; }
.kbf-instr::placeholder { color: var(--text-4); }
.kbf-link-sel {
    width: 100%; box-sizing: border-box;
    border: 1px solid #e2e8f0; border-radius: 6px;
    background: #f8fafc; padding: 5px 8px;
    font-family: inherit; font-size: 11px; color: var(--text-2);
    outline: none; cursor: pointer;
    transition: border-color 0.12s, background 0.12s;
}
.kbf-link-sel:focus { border-color: #7c3aed; background: #fff; }

/* ── HTTP tools in KB flow node ─────────────────────────────────────────── */
.kbf-tools-section {
    padding: 6px 10px 8px 10px;
    border-top: 1px solid #f1f5f9;
}

/* ── Transitions ─────────────────────────────────────────────────────────── */
.kbf-transitions {
    padding: 6px 10px 8px 10px;
    border-top: 1px solid #f1f5f9;
}
.kbf-trans-row {
    display: flex; align-items: center; gap: 4px; margin-bottom: 4px;
}
.kbft-cond, .kbft-tgt {
    min-width: 0; box-sizing: border-box;
    font-size: 10px; padding: 3px 6px; border-radius: 5px;
    border: 1px solid #e2e8f0; background: #f8fafc;
    font-family: inherit; color: var(--text-1); outline: none;
    transition: border-color 0.12s;
}
.kbft-cond { flex: 1; }
.kbft-tgt  { flex: 1.4; cursor: pointer; padding: 3px 20px 3px 6px; }
.kbft-cond:focus, .kbft-tgt:focus { border-color: #94a3b8; background: #fff; }
.kbft-cond::placeholder { color: var(--text-4); }
.kbft-arrow-icon { color: var(--text-4); flex-shrink: 0; }
.kbft-del {
    border: none; background: none; color: var(--text-4); cursor: pointer;
    padding: 2px; display: flex; align-items: center; justify-content: center;
    opacity: 0.5; transition: opacity 0.12s;
}
.kbf-trans-row:hover .kbft-del { opacity: 1; }
.kbft-del:hover { color: var(--danger); }

.kbf-addtr {
    font-size: 10px; color: var(--accent); background: none; border: none;
    cursor: pointer; padding: 2px 0; font-family: inherit; font-weight: 600;
}
.kbf-addtr:hover { color: var(--accent-dark); }


/* ── Drawflow overrides ──────────────────────────────────────────────────── */

#kbc-drawflow, #flow-drawflow {
    width: 100%; height: 100%;
}

.drawflow { background: transparent !important; }

.drawflow .drawflow-node {
    background: #fff;
    border: 1.5px solid #e2e8f0 !important;
    border-radius: 10px;
    box-shadow: 0 1px 4px rgba(0,0,0,0.07), 0 4px 16px rgba(0,0,0,0.05) !important;
    padding: 0 !important;
    cursor: move;
    transition: box-shadow 0.15s;
    font-family: 'Montserrat', sans-serif;
    font-size: 12px;
    min-width: unset !important;
    width: auto !important;
}
.drawflow .drawflow-node:hover {
    box-shadow: 0 2px 8px rgba(0,0,0,0.1), 0 6px 20px rgba(0,0,0,0.07) !important;
}
.drawflow .drawflow-node:hover .kbf-del,
.drawflow .drawflow-node:hover .fn-del { opacity: 1; }
.drawflow .drawflow-node.selected { outline: none; }

.drawflow .drawflow-node.kbf-dfend  { border-color: #10b981 !important; }
.drawflow .drawflow-node.kbf-dflink { border-color: #7c3aed !important; }
.drawflow .drawflow-node.kbf-dfstart {
    border-color: #3b82f6 !important;
    box-shadow: 0 0 0 3px rgba(59,130,246,0.15), 0 4px 16px rgba(0,0,0,0.08) !important;
}
.drawflow .drawflow-node.fn-dfend  { border-color: #10b981 !important; }
.drawflow .drawflow-node.fn-dfstart {
    border-color: #3b82f6 !important;
    box-shadow: 0 0 0 3px rgba(59,130,246,0.15), 0 4px 16px rgba(0,0,0,0.08) !important;
}

.drawflow .drawflow_content_node {
    padding: 0 !important;
    width: 260px;
}

.drawflow .input, .drawflow .output {
    width: 10px !important;
    height: 10px !important;
    border-radius: 50%;
    border: 2px solid #64748b !important;
    background: #fff !important;
    cursor: crosshair;
    top: 50%;
}
.drawflow .output {
    background: #64748b !important;
    right: -6px;
}
.drawflow .input { left: -6px; }

.drawflow .connection .main-path {
    stroke: #64748b;
    stroke-width: 2px;
    fill: none;
}
.drawflow .connection .main-path:hover {
    stroke: var(--accent);
    stroke-width: 2.5px;
    cursor: pointer;
}
.drawflow .connection.selected .main-path { stroke: var(--accent); }

.drawflow-delete { display: none !important; }

.kbc-flow-canvas-wrap #kbc-drawflow { height: 100%; }

/* ── Billing (client-facing, read-only) ──────────────────────
   Card-list pattern reused from the HTTP-tools list (.ct-card) rather than
   a new table component -- consistent with the rest of this page. ── */
.dsh-billing-summary { display: flex; gap: 32px; flex-wrap: wrap; margin-bottom: 18px; }
.dsh-billing-stat-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-3); margin-bottom: 4px; }
.dsh-billing-stat-value { font-size: 20px; font-weight: 700; color: var(--text-1); }
.dsh-billing-stat-sub { font-size: 11px; color: var(--text-3); margin-top: 2px; }
/* Plain text, not a colored banner -- a price-change heads-up isn't a warning/error
   state, just information, so it reads like the rest of the receipt (quiet typography)
   rather than a decorative alert box. Collapsed by default via <details>. */
.dsh-price-note { font-size: 12.5px; color: var(--text-3); margin-top: 10px; }
.dsh-price-note summary {
    cursor: pointer; color: var(--accent); font-weight: 600; display: inline;
}
.dsh-price-note summary:hover { color: var(--accent-dark); }
.dsh-price-note[open] summary { margin-bottom: 4px; }
.dsh-price-note-detail { margin-top: 2px; }

.dsh-billing-invoices { display: flex; flex-direction: column; gap: 8px; }
.dsh-billing-invoice {
    background: rgba(255,255,255,0.45); border: 1px solid rgba(255,255,255,0.7);
    border-radius: 12px; padding: 12px 14px;
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.dsh-billing-invoice-main { flex: 1; min-width: 160px; display: flex; flex-direction: column; gap: 2px; }
.dsh-billing-invoice-number { font-size: 13px; font-weight: 600; }
.dsh-billing-invoice-period { font-size: 12px; color: var(--text-3); }
.dsh-billing-invoice-amount { font-size: 14px; font-weight: 700; color: var(--text-1); flex-shrink: 0; }
.dsh-billing-invoice-due { font-size: 12px; color: var(--text-3); flex-shrink: 0; }

.dsh-billing-badge { display: inline-block; padding: 3px 9px; border-radius: 20px; font-size: 11px; font-weight: 700; flex-shrink: 0; }
.dsh-billing-badge-issued    { background: #d1ecf1; color: #0c5460; }
.dsh-billing-badge-paid      { background: #d4edda; color: #155724; }
.dsh-billing-badge-overdue   { background: #f8d7da; color: #721c24; }
.dsh-billing-badge-cancelled { background: rgba(0,0,0,0.06); color: var(--text-3); text-decoration: line-through; }

.dsh-billing-pay-note { font-size: 11px; color: var(--text-3); width: 100%; }
.dsh-billing-empty { text-align: center; padding: 24px 16px; color: var(--text-3); font-size: 13px; }

/* Generic semantic tag colors (same .tag base as .tag-pyrus/.tag-telegram above),
   for subscription/invoice status where the meaning is good/critical, not a channel. */
.tag-good     { background: rgba(34,197,94,0.1);  color: #15803d; border: 1px solid rgba(34,197,94,0.22); }
.tag-critical { background: rgba(239,68,68,0.1);  color: #b91c1c; border: 1px solid rgba(239,68,68,0.22); }
.tag-neutral  { background: rgba(100,116,139,0.1); color: var(--text-3); border: 1px solid rgba(100,116,139,0.2); }

/* ── /dashboard/billing (dedicated page) ──────────────────────── */
/* 80px clears the floating header-only pill (no tabbar on this page). The footer
   is no longer fixed, so min-height no longer needs to reserve room for it either. */
.dsh-billing-page {
    max-width: 860px; margin: 0 auto; padding: 80px 20px 40px;
    min-height: calc(100vh - 80px); min-height: calc(100dvh - 80px); box-sizing: border-box;
    display: flex; flex-direction: column; gap: 16px;
}
/* Shared "back to my dashboard" affordance for every client page one level below
   the dashboard (billing, account, help, knowledge-base constructor) -- one look,
   not a different treatment per page. */
.dsh-page-back {
    font-size: 12px; font-weight: 700; color: var(--text-3);
    text-decoration: none; display: inline-block; padding: 5px 12px; border-radius: 12px;
    background: rgba(255,255,255,0.28); border: 1px solid var(--glass-border-soft);
    transition: background 0.15s, color 0.15s;
}
.dsh-page-back:hover { background: rgba(255,255,255,0.55); color: var(--text-1); }

.dsh-sub-top { display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 16px; margin-bottom: 18px; }
.dsh-sub-plan-name { font-size: 14px; font-weight: 500; color: var(--text-1); }
.dsh-sub-plan-desc { font-size: 12px; color: var(--text-3); margin-top: 3px; }

/* No border-top here on purpose -- on the one page that uses this
   (dashboard_billing.html), the adapter switch directly above it already has
   its own border-bottom; a second border right under it read as two stacked
   lines with barely any gap, not one clean rule. */
.dsh-figures { display: flex; gap: 32px; flex-wrap: wrap; padding: 14px 0; border-bottom: 1px solid var(--glass-border-soft); margin-bottom: 16px; }

.dsh-field-label { font-size: 11px; font-weight: 700; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 8px; }
.dsh-mode-radios { display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 6px; }
.dsh-radio { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; color: var(--text-2); cursor: pointer; }
.dsh-radio input[type=radio] { width: 15px; height: 15px; cursor: pointer; accent-color: var(--accent); }
.dsh-pending-note { font-size: 11.5px; color: var(--text-3); margin-top: 6px; }

.dsh-cancel-note {
    margin-top: 16px; padding: 12px 14px; border-radius: var(--r-md);
    background: rgba(239,68,68,0.06); border: 1px solid rgba(239,68,68,0.18);
    font-size: 12.5px; color: var(--text-2); line-height: 1.6;
}

.dsh-section-divider { border-top: 1px solid var(--glass-border-soft); margin: 18px 0; }

/* Cost breakdown reads as a receipt (muted rows, one rule before the total,
   only the total bold/dark) -- deliberately not color-coded or bar-charted,
   see BILLING_ADAPTER_SCOPE_TODO.md design notes: plain typography over
   decorative category colors. */
.receipt { font-variant-numeric: tabular-nums; }
.receipt-row { display: flex; justify-content: space-between; align-items: center; padding: 5px 0; font-size: 13px; color: var(--text-2); }
.receipt-row.total { padding-top: 10px; margin-top: 6px; border-top: 1px solid var(--glass-border); font-weight: 700; font-size: 14px; color: var(--text-1); }

/* ── Итого: per-adapter split, plain stacked rows (not a grid -- an
   auto-fill grid gives every row a different cell width at low counts,
   which puts the label/amount gap at a different place per row and reads
   as broken alignment, not "adaptive"). Scales to any adapter count by
   just getting taller, never by hiding rows. ── */
.hero-split { font-variant-numeric: tabular-nums; }
.hero-split-row { display: flex; justify-content: space-between; gap: 10px; padding: 4px 0; font-size: 13px; color: var(--text-3); }
.hero-split-row b { color: var(--text-1); font-weight: 700; }

/* ── Adapter switch: plain text tabs (not a pill/segment control -- see
   BILLING_ADAPTER_SCOPE_TODO.md), same idiom the header tabbar already
   uses for adapter identity (colored sub-label), a 2px underline instead
   of a filled chip. Wraps to horizontal scroll past MANY_ADAPTERS
   (dashboard_billing.js) instead of ragged multi-row wrapping. ── */
.adapter-switch-wrap { position: relative; margin-bottom: 22px; }
.adapter-switch {
    display: flex; flex-wrap: nowrap; gap: 26px; overflow-x: auto; scrollbar-width: none;
    border-bottom: 1px solid var(--glass-border-soft); padding-bottom: 12px;
}
.adapter-switch::-webkit-scrollbar { display: none; }
.adapter-seg {
    all: unset; cursor: pointer; padding: 2px 1px 10px; display: flex; align-items: baseline; gap: 7px;
    border-bottom: 2px solid transparent; transition: border-color 0.15s; flex-shrink: 0; white-space: nowrap;
}
.adapter-seg .a-name { font-size: 14px; font-weight: 600; color: var(--text-3); transition: color 0.15s; }
.adapter-seg .a-amount { font-size: 12px; color: var(--text-4); font-variant-numeric: tabular-nums; transition: color 0.15s; }
.adapter-seg.active { border-bottom-color: currentColor; }
.adapter-seg.pyrus.active { color: #b5870d; }
.adapter-seg.telegram.active { color: #0088cc; }
.adapter-seg.active .a-name { color: var(--text-1); }
.adapter-seg.active .a-amount { color: var(--text-2); }
.adapter-seg .a-note { font-size: 11px; color: var(--text-3); font-style: italic; }

/* Shown instead of the tab row once there are more adapters than a row of
   tabs stays scannable at -- a plain native select, not a custom dropdown,
   because "pick one from a long list" is exactly what a select is for. */
.adapter-select {
    display: none; width: 100%; max-width: 320px; height: 38px; margin-bottom: 22px;
    -webkit-appearance: none; appearance: none; cursor: pointer;
    font-family: 'Montserrat', sans-serif; font-size: 13.5px; font-weight: 600; color: var(--text-1);
    padding: 0 30px 0 12px; border-radius: var(--r-sm);
    border: 1px solid var(--glass-border-soft); background-color: rgba(255,255,255,0.5);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6' fill='none' stroke='%2364748b' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 12px center; background-size: 10px;
    transition: border-color 0.18s, background-color 0.18s;
}
.adapter-select:focus { outline: none; border-color: rgba(59,130,246,0.6); box-shadow: 0 0 0 3px rgba(59,130,246,0.12); }
.dsh-billing-page.many-adapters .adapter-switch-wrap { display: none; }
.dsh-billing-page.many-adapters .adapter-select { display: block; }

/* Only one adapter's panel is ever visible at a time -- dashboard_billing.js's
   switchAdapterPanel() only toggles the .active class, this is what actually
   hides/shows the panel content behind it. */
.adapter-panel { display: none; }
.adapter-panel.active { display: block; }

/* Connected features, one grid, symmetric affordance both directions: a
   real switch (not a checkmark circle) so turning something OFF reads as
   exactly as first-class an action as turning it ON. */
.dsh-feat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 10px; }
.dsh-feat-tile {
    display: flex; flex-direction: column; gap: 8px; padding: 13px 14px;
    border-radius: var(--r-md); border: 1.5px solid var(--glass-border-soft); background: rgba(255,255,255,0.32);
    text-align: left; font-family: inherit;
    transition: border-color .15s, background .15s, box-shadow .15s;
}
.dsh-feat-tile.on { border-color: rgba(59,130,246,0.55); background: rgba(59,130,246,0.10); }
/* Landed here from a locked-section badge (#feat-<key> in the URL) -- a couple of
   pulses so the relevant tile is obvious, not just "somewhere on this page". */
.dsh-feat-tile.dsh-feat-highlight { animation: dsh-feat-pulse 1.4s ease-out 2; }
@keyframes dsh-feat-pulse {
    0% { box-shadow: 0 0 0 0 rgba(59,130,246,0.55); }
    100% { box-shadow: 0 0 0 12px rgba(59,130,246,0); }
}
.dsh-feat-tile .tile-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.dsh-feat-tile .tile-name-wrap { display: flex; flex-direction: column; gap: 1px; }
.dsh-feat-tile .tile-name { font-size: 14px; font-weight: 700; color: var(--text-1); line-height: 1.3; }
.dsh-feat-tile .tile-price { font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }
.dsh-feat-tile.on .tile-price { color: var(--accent-dark); }
.dsh-feat-tile .tile-desc { font-size: 12px; color: var(--text-3); line-height: 1.45; }
.dsh-feature-note { font-size: 12px; color: var(--text-3); line-height: 1.5; margin-top: 18px; }

.fswitch { all: unset; cursor: pointer; flex-shrink: 0; width: 36px; height: 21px; border-radius: 999px; background: rgba(15,23,42,0.18); position: relative; transition: background 0.18s; }
.fswitch::after { content: ''; position: absolute; top: 2px; left: 2px; width: 17px; height: 17px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(15,23,42,0.3); transition: transform 0.18s; }
.fswitch.on { background: var(--accent); }
.fswitch.on::after { transform: translateX(15px); }
.fswitch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dsh-feature-price { font-size: 12px; color: var(--text-3); }
.dsh-feature-pending { font-size: 10.5px; color: var(--text-3); width: 100%; margin-left: 22px; margin-top: -4px; }

/* ── Support chat widget (templates/_support_chat.html) ────── */
/* Footer no longer pins to the viewport bottom, so these just sit near the true
   bottom edge now -- no more footer-clearing math. */
.sc-toggle {
    position: fixed; right: 20px; bottom: 20px; z-index: 200;
    width: 52px; height: 52px; border-radius: 50%; border: none; cursor: pointer;
    background: linear-gradient(155deg, var(--accent), var(--accent-dark)); color: #fff;
    display: flex; align-items: center; justify-content: center;
    box-shadow: 0 6px 20px rgba(59,130,246,0.35); transition: transform 0.15s;
}
.sc-toggle:hover { transform: scale(1.06); }
.sc-toggle svg { width: 24px; height: 24px; }
.sc-panel {
    display: none; flex-direction: column; position: fixed; right: 20px; bottom: 84px; z-index: 200;
    width: 320px; max-width: calc(100vw - 40px); height: 440px;
    max-height: calc(100vh - 120px); max-height: calc(100dvh - 120px);
    background: var(--glass-heavy); backdrop-filter: var(--blur-heavy); -webkit-backdrop-filter: var(--blur-heavy);
    border: 1px solid var(--glass-border); border-radius: var(--r-xl); box-shadow: var(--glass-shadow);
    overflow: hidden;
}
.sc-panel.open { display: flex; }
.sc-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 14px; font-size: 13px; font-weight: 700; color: var(--text-1);
    border-bottom: 1px solid var(--glass-border-soft); flex-shrink: 0;
}
.sc-head-title { display: flex; align-items: center; gap: 8px; }
.sc-head-title img { width: 20px; height: 20px; border-radius: 5px; }
.sc-head-actions { display: flex; align-items: center; gap: 10px; }
.sc-clear, .sc-close {
    all: unset; cursor: pointer; color: var(--text-3); font-size: 13px; padding: 2px 4px;
}
.sc-clear:hover, .sc-close:hover { color: var(--text-1); }
.sc-messages {
    flex: 1; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px;
}
.sc-msg {
    max-width: 85%; padding: 8px 11px; border-radius: 12px; font-size: 13px; line-height: 1.45;
    word-break: break-word;
}
.sc-msg-agent { align-self: flex-start; background: rgba(255,255,255,0.55); color: var(--text-1); border-bottom-left-radius: 3px; }
.sc-msg-user { align-self: flex-end; background: var(--accent); color: #fff; border-bottom-right-radius: 3px; white-space: pre-wrap; }
.sc-msg-agent ul { margin: 4px 0; padding-left: 20px; }
.sc-msg-agent li { margin: 2px 0; }
.sc-msg-agent code { background: rgba(0,0,0,0.08); padding: 1px 4px; border-radius: 4px; font-size: 0.92em; }
.sc-action-row { align-self: flex-start; display: flex; gap: 6px; flex-wrap: wrap; max-width: 90%; }
.sc-action-btn {
    border: none; border-radius: 12px; padding: 6px 10px; font-family: inherit;
    font-size: 12px; font-weight: 700; cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
}
.sc-action-btn svg { flex-shrink: 0; }
.sc-action-btn:disabled { opacity: 0.5; cursor: default; }
.sc-action-confirm { background: var(--accent); color: #fff; }
.sc-action-confirm:hover:not(:disabled) { background: var(--accent-dark); }
.sc-action-cancel { background: rgba(255,255,255,0.55); color: var(--text-2); }
.sc-action-cancel:hover:not(:disabled) { background: rgba(255,255,255,0.75); }
.sc-input-row {
    display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--glass-border-soft); flex-shrink: 0;
}
.sc-input-row input {
    flex: 1; height: 36px; padding: 0 12px; border-radius: 18px; border: 1px solid var(--glass-border);
    background: rgba(255,255,255,0.45); font-family: inherit; font-size: 13px; color: var(--text-1); outline: none;
}
.sc-input-row input:focus { border-color: var(--accent); }
.sc-input-row button {
    height: 36px; padding: 0 16px; border-radius: 18px; border: none; cursor: pointer;
    background: var(--accent); color: #fff; font-family: inherit; font-size: 12.5px; font-weight: 700;
}
.sc-input-row button:hover { background: var(--accent-dark); }
@media (max-width: 480px) {
    /* bottom values inherit the base rule above (footer no longer pins to the
       viewport bottom at any width) -- only the side margin tightens further here. */
    .sc-panel { right: 12px; }
    .sc-toggle { right: 12px; }
}

/* ── Payment gate card — /dashboard, shown while requires_paddle_subscription and no
   active Paddle subscription yet. Lives inside .dsh-content's grid (not above
   .dsh-layout) so it inherits the same top/side clearance every other card already
   gets for the fixed header/tabbar and sidebar, instead of re-deriving those offsets
   by hand. grid-column spans the full row, same idiom #core/#template etc. already
   use at the narrow breakpoint. A left accent stripe is enough to make it stand out
   among the other .gc cards without turning it into a colored alert box. ── */
.gc-pay {
    grid-column: 1 / -1;
    border-left: 4px solid var(--accent);
}
.gc-pay-row {
    display: flex; align-items: center; justify-content: space-between; gap: 20px;
    padding: 16px 20px; flex-wrap: wrap;
}
.gc-pay-title { font-size: 14px; font-weight: 700; color: var(--text-1); margin-bottom: 4px; }
.gc-pay-desc { font-size: 12.5px; color: var(--text-3); max-width: 560px; }
.gc-pay-btn { flex-shrink: 0; padding: 10px 20px; font-size: 13px; }
/* Paddle's own form content is a fixed, narrower reading width -- letting the frame
   stretch across this full-width card just leaves empty margins either side of it, so
   the wrapper itself stays narrow and centered instead of matching the card's width.
   680px, not 480 -- Paddle's inline checkout "Max width" setting won't go below 643px,
   so a narrower wrapper here would just squeeze/clip their form instead of matching it. */
.paddle-gate-frame { max-width: 680px; margin: 0 auto; padding: 0 20px 18px; }

/* ── Notifications bell — .adm-header-right button + modal list (see
   templates/_notifications.html, static/js/notifications.js) ── */
button.adm-user {
    text-decoration: none; transition: background 0.15s;
    padding: 5px 10px; border-radius: var(--r-sm);
    background: transparent; border: none; cursor: pointer; font-family: inherit;
    position: relative;
}
button.adm-user:hover { background: rgba(15,23,42,0.05); }
.notif-dot {
    display: none; position: absolute; top: 1px; right: 2px;
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--danger); border: 1.5px solid #fff;
}
.nf-list { display: flex; flex-direction: column; gap: 10px; max-height: 60vh; overflow-y: auto; }
.nf-item {
    padding: 12px 14px; border-radius: var(--r-md);
    background: rgba(255,255,255,0.5); border: 1px solid var(--glass-border-soft);
}
.nf-item-title { font-size: 13px; font-weight: 700; color: var(--text-1); margin-bottom: 2px; }
.nf-item-date { font-size: 11px; color: var(--text-4); margin-bottom: 6px; }
.nf-item-msg { font-size: 13px; color: var(--text-2); line-height: 1.5; white-space: pre-wrap; }

/* iOS Safari auto-zoom on focus, part 2: the class-qualified selectors below (.sc-input-row
   input, .adapter-select, etc.) each carry the same or higher specificity than the generic
   input[type=text]/select mobile fix earlier in this file, and are declared later in the
   file, so they silently won the cascade and kept their sub-16px size on every width. Each
   one needs its own override, placed after its own declaration, to actually take effect. */
@media (max-width: 600px) {
    .sc-input-row input { font-size: 16px; }
    .adapter-select { font-size: 16px; }
    .kbc-pro-search-wrap input { font-size: 16px; }
    .kbc-pro-form-body input[type=text],
    .kbc-pro-form-body textarea,
    .kbc-pro-form-body select { font-size: 16px; }
    .kbf-name-input { font-size: 16px; }
}
