:root{
  /* Light theme — warm palette inspired by Claude Desktop (cream bg, clay accent) */
  --bg:#faf9f4; --surface:#ffffff; --surface-2:#f1efe8; --border:#e9e5db;
  --text:#1f1e1c; --muted:#6b665d; --hint:#9c958a; --accent:#cd7a5c; --label:#403c34; --link:#1f5fa6;
  --danger:#b0452f; --danger-bg:#f7e7e1; --warning:#8a5712; --warning-bg:#f6ecd6;
  --success:#3f7a55; --success-bg:#e6f0e7; --info:#cd7a5c; --info-bg:#f3ebe2;
  --radius:10px; --radius-sm:7px;
}
[data-theme="dark"]{
  --bg:#15171c; --surface:#1d2026; --surface-2:#23272f; --border:#2e333c;
  --text:#e7e9ee; --muted:#9aa0ab; --hint:#6a6f7a; --accent:#85b7eb; --label:#aeb4bf; --link:#85b7eb;
  --danger:#f09595; --danger-bg:#3a1c1c; --warning:#f0c075; --warning-bg:#3a2e16;
  --success:#7fd6bb; --success-bg:#103a30; --info:#85b7eb; --info-bg:#11233a;
}
[data-theme^="space"]{
  --bg:#080B0D; --surface:#101318; --surface-2:#14171C; --border:#252B31;
  --text:#E8EBED; --muted:#8B939A; --hint:#5c646b; --accent:#9EB5C3; --label:#9aa3ab; --link:#9EB5C3;
  --danger:#d6908b; --danger-bg:#20140f; --warning:#c7a877; --warning-bg:#201c12;
  --success:#8fb7a6; --success-bg:#0d1b17; --info:#9EB5C3; --info-bg:#0f161b;
  --radius:4px; --radius-sm:3px;
}
[data-theme="space-cold"]{
  --bg:#F6F7F5; --surface:#FFFFFF; --surface-2:#F0F1EF; --border:#DADDE0;
  --text:#171A1D; --muted:#737B82; --hint:#9aa0a6; --accent:#5e7d8f; --label:#3a4147; --link:#4a6b7d;
  --danger:#9d4630; --danger-bg:#f0e4df; --warning:#7a5a1e; --warning-bg:#efe9db;
  --success:#3f6d59; --success-bg:#e6efe9; --info:#5e7d8f; --info-bg:#eaeef0;
  --radius:4px; --radius-sm:3px;
}
[data-theme="space-light"]{
  /* Warm palette borrowed from the plain Light theme; the Space themes' geometry
     and typography come from the [data-theme^="space"] rules below, so this is a
     colour swap and nothing more. */
  --bg:#faf9f4; --surface:#ffffff; --surface-2:#f1efe8; --border:#e9e5db;
  --text:#1f1e1c; --muted:#6b665d; --hint:#9c958a; --accent:#cd7a5c; --label:#403c34; --link:#1f5fa6;
  --danger:#b0452f; --danger-bg:#f7e7e1; --warning:#8a5712; --warning-bg:#f6ecd6;
  --success:#3f7a55; --success-bg:#e6f0e7; --info:#cd7a5c; --info-bg:#f3ebe2;
  --radius:4px; --radius-sm:3px;
}

/* ===== Space Minimalism / Aerospace UI — applies only to space-* themes ===== */
[data-theme^="space"]{
  font-family:'Inter',system-ui,-apple-system,'Helvetica Neue',sans-serif;
}
[data-theme^="space"] body{ letter-spacing:.01em; }
[data-theme^="space"] h1,
[data-theme^="space"] h2,
[data-theme^="space"] .title{
  font-weight:300; letter-spacing:.05em;
}
[data-theme^="space"] .brand{
  font-family:'Space Mono',monospace; font-size:11px; font-weight:400;
  letter-spacing:.18em; text-transform:uppercase;
}
[data-theme^="space"] .brand small{
  letter-spacing:.1em; text-transform:uppercase; font-size:9px; opacity:.5;
}
[data-theme^="space"] .nav a{
  border-left:2px solid transparent; letter-spacing:.03em; border-radius:0;
}
[data-theme^="space"] .nav a.active{
  border-left-color:var(--accent); background:transparent; color:var(--text);
}
[data-theme^="space"] thead th{
  font-family:'Space Mono',monospace; text-transform:uppercase;
  letter-spacing:.14em; font-size:10px; font-weight:400; color:var(--muted);
}
[data-theme^="space"] .sub,
[data-theme^="space"] .section-label,
[data-theme^="space"] .crumb,
[data-theme^="space"] .kpi .l,
[data-theme^="space"] .metric .label{
  font-family:'Space Mono',monospace; text-transform:uppercase; letter-spacing:.12em; font-size:10.5px;
}
[data-theme^="space"] .btn,
[data-theme^="space"] input,
[data-theme^="space"] select{ border-radius:4px; }
/* The page-load fade was removed on purpose: with animation-fill-mode "both" the
   content is pinned at opacity:0 until the animation actually runs, so a single
   dropped frame or a deprioritised tab left the text invisible until something
   forced a repaint (selecting it with the mouse). Decoration is not worth a page
   that sometimes does not show up. */

/* orbital arc — the visual signature, behind content */
.space-arc{display:none}
[data-theme^="space"] .space-arc{
  display:block; position:fixed; top:-42vh; right:-26vw; width:118vh; height:118vh;
  pointer-events:none; z-index:0;
}
[data-theme="space-light"] .space-arc{ opacity:.55 }
.space-arc svg{ width:100%; height:100% }
[data-theme^="space"] .layout,
[data-theme^="space"] .login-wrap{ position:relative; z-index:1 }
*{box-sizing:border-box}
body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  background:var(--bg);color:var(--text);font-size:14px;line-height:1.55}
a{color:var(--link);text-decoration:none}
a:hover{text-decoration:underline}
/* nav & buttons are anchors too -> no underline */
.nav a,.btn,.iconbtn{text-decoration:none}
.nav a:hover,.btn:hover,.iconbtn:hover{text-decoration:none}

/* ---- shared form controls (one look everywhere) ---- */
input[type="text"],input[type="date"],input[type="email"],input[type="password"],input[type="search"],input:not([type]),select,textarea{
  font-family:inherit;font-size:13px;color:var(--text);background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius-sm);padding:7px 10px;line-height:1.45}
textarea{min-height:60px;resize:vertical}
button{font-family:inherit}
input::placeholder,textarea::placeholder{color:var(--hint)}

.layout{display:flex;min-height:100vh}
.sidebar{width:210px;background:var(--surface);border-right:1px solid var(--border);
  padding:18px 14px;position:sticky;top:0;height:100vh;flex-shrink:0}
.brand{font-size:15px;font-weight:600;margin:0 0 2px}
.brand small{display:block;font-size:11px;color:var(--muted);font-weight:400;margin-top:2px}
.nav{margin-top:22px;display:flex;flex-direction:column;gap:4px}
.nav a{display:flex;align-items:center;gap:9px;padding:9px 11px;border-radius:var(--radius-sm);
  color:var(--text);font-size:14px}
.nav a:hover{background:var(--surface-2);text-decoration:none}
.nav a.active{background:var(--surface-2);color:var(--text);font-weight:500}
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:13px 26px;border-bottom:1px solid var(--border);background:var(--surface)}
.topbar .title{font-size:16px;font-weight:600}
.topbar .right{display:flex;align-items:center;gap:14px;font-size:13px;color:var(--muted)}
.content{padding:24px 26px;max-width:1280px;width:100%}

.role-chip{font-size:11px;padding:2px 8px;border-radius:6px;background:var(--info-bg);color:var(--info)}
.iconbtn{background:none;border:1px solid var(--border);color:var(--text);cursor:pointer;
  border-radius:var(--radius-sm);font-size:13px;height:30px;min-width:30px;padding:0 8px;
  display:inline-flex;align-items:center;justify-content:center;line-height:1}
.iconbtn i{font-size:15px;line-height:1}
.iconbtn:hover{background:var(--surface-2)}
/* The settings gear marks itself while you are inside that section — it is the
   only navigation left in the top bar, so it has to say where you are. */
.iconbtn.on{background:var(--surface-2);border-color:var(--accent);color:var(--accent)}

h1{font-size:20px;font-weight:600;margin:0 0 4px}
.sub{color:var(--muted);margin:0 0 20px;font-size:13px}

.metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(165px,1fr));gap:14px;margin-bottom:24px}
.metric{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:15px 17px}
.metric .label{font-size:12px;color:var(--muted)}
.metric .value{font-size:26px;font-weight:600;margin-top:3px}
.value.danger{color:var(--danger)} .value.warning{color:var(--warning)}

.section-label{font-size:12px;color:var(--muted);margin:0 0 11px;text-transform:none}
.risks{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:11px;margin-bottom:26px}
.risk{display:flex;align-items:center;gap:12px;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);padding:13px 15px;color:var(--text)}
.risk:hover{text-decoration:none;border-color:var(--accent)}
.risk .ic{font-size:20px;line-height:1}
.risk .n{font-size:19px;font-weight:600}
.risk .t{font-size:12px;color:var(--muted)}
.risk.sev-danger .ic{color:var(--danger)} .risk.sev-warning .ic{color:var(--warning)}

.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:18px 20px}
.bars{display:flex;flex-direction:column;gap:9px;margin-top:6px}
.bar-row{display:flex;align-items:center;gap:10px;font-size:13px}
.bar-row .name{width:120px;color:var(--muted);flex-shrink:0}
.bar-track{flex:1;background:var(--surface-2);border-radius:6px;height:16px;overflow:hidden;display:block}
/* display:block matters: .bar-fill is a <span>, and width/height do not apply
   to inline elements — without it the track stayed empty whatever the value. */
.bar-fill{display:block;height:100%;min-width:2px;background:var(--accent);border-radius:6px;
  transition:width .25s ease}
.bar-row .cnt{width:26px;text-align:right;font-weight:600}

.toolbar{display:flex;flex-wrap:wrap;gap:9px;align-items:center;margin-bottom:14px}
.toolbar input,.toolbar select{font-size:13px}
.toolbar .spacer{margin-left:auto}
.btn{padding:7px 12px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface);
  color:var(--text);font-size:13px;cursor:pointer}
.btn:hover{background:var(--surface-2)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.primary:hover{background:var(--accent);filter:brightness(.94)}

.table-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}
table{border-collapse:collapse;width:100%;font-size:13px;min-width:760px}
thead th{text-align:left;font-weight:500;color:var(--muted);background:var(--surface-2);padding:10px 6px 10px 12px;
  white-space:nowrap}
tbody td{padding:10px 6px;border-top:1px solid var(--border);vertical-align:middle}
tbody tr:hover{background:var(--surface-2);cursor:pointer}
.muted{color:var(--muted)} .hint{color:var(--hint)}

.badge{display:inline-block;padding:2px 9px;border-radius:6px;font-size:12px;white-space:nowrap}
.badge.crit{background:var(--danger-bg);color:var(--danger)}
.badge.high{background:var(--warning-bg);color:var(--warning)}
.badge.normal{background:var(--info-bg);color:var(--info)}
.badge.low{background:var(--surface-2);color:var(--muted)}
.badge.active{background:var(--success-bg);color:var(--success)}
.badge.unsubscribed,.badge.inactive{background:var(--surface-2);color:var(--muted)}
.badge.paid{background:var(--info-bg);color:var(--info)}
.badge.free{background:var(--surface-2);color:var(--muted)}
.badge.usage-based{background:var(--success-bg);color:var(--success)}
.ok{color:var(--success)} .no{color:var(--danger)}

.detail-head{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;flex-wrap:wrap}
.detail-head .meta{color:var(--muted);font-size:13px;margin-top:3px}
.badges{display:flex;gap:6px;flex-wrap:wrap}
.actions{display:flex;gap:8px;margin:14px 0 4px;flex-wrap:wrap}
.dsection{border-top:1px solid var(--border);margin-top:16px;padding-top:14px}
.dsection h3{font-size:13px;font-weight:600;color:var(--muted);margin:0 0 10px;display:flex;
  align-items:center;gap:8px}
.lock{font-size:11px;color:var(--hint);font-weight:400}
.fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:8px 26px;font-size:13px}
.field{display:flex;justify-content:space-between;gap:10px}
.field .k{color:var(--muted)} .field .v{text-align:right}
.fields .wide{grid-column:1/-1}
.changes{font-size:13px;color:var(--muted);line-height:1.9}
.tags{display:flex;gap:6px;flex-wrap:wrap}
.tag{background:var(--surface-2);color:var(--muted);padding:2px 9px;border-radius:6px;font-size:12px}

.login-wrap{display:flex;min-height:100vh;align-items:center;justify-content:center}
.login-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:30px 32px;width:340px}
.login-card h1{margin:0 0 4px}
.login-card label{display:block;font-size:12px;color:var(--muted);margin:14px 0 5px}
.login-card input{width:100%;padding:9px 11px;border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--bg);color:var(--text);font-size:14px}
.login-card button{width:100%;margin-top:20px;padding:10px;border:none;border-radius:var(--radius-sm);
  background:var(--accent);color:#fff;font-size:14px;cursor:pointer}
.error{background:var(--danger-bg);color:var(--danger);padding:9px 12px;border-radius:var(--radius-sm);
  font-size:13px;margin-top:14px}
.demo-note{font-size:12px;color:var(--hint);margin-top:18px;line-height:1.6}

/* forms & admin */
.form-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px 18px}
.form-grid .full{grid-column:1/-1}
.fld label{display:block;font-size:12px;color:var(--muted);margin-bottom:4px}
.fld input,.fld select,.fld textarea{width:100%}
.fieldset{border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;margin:0 0 16px}
.fieldset legend{font-size:13px;font-weight:600;color:var(--text);padding:0 6px;text-transform:none}
.form-actions{margin-top:6px;display:flex;gap:10px}
.flash{padding:9px 13px;border-radius:var(--radius-sm);font-size:13px;margin-bottom:16px}
.flash.ok{background:var(--success-bg);color:var(--success)}
.flash.err{background:var(--danger-bg);color:var(--danger)}
.btn.sm{padding:4px 9px;font-size:12px}
.btn.danger{border-color:var(--danger);color:var(--danger)}
.inline-form{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.admin-table input,.admin-table select{padding:5px 8px}
.nav .group{font-size:11px;color:var(--hint);margin:16px 0 4px;padding-left:11px}
.checks{display:flex;flex-wrap:wrap;gap:8px 14px}
.checks label{font-size:12px;color:var(--text);display:flex;align-items:center;gap:5px}

/* View: separate each detail section into its own card */
.dsection{margin:0 0 14px;padding:16px 18px;border:1px solid var(--border);
  border-radius:var(--radius);background:var(--surface)}
.dsection h3{color:var(--text);font-size:14px;font-weight:600;margin:0 0 12px;
  padding-bottom:9px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px}
.dsection .lock{margin-left:auto}
.dsection .field{padding:3px 0}

/* Compact two-column detail with coloured section headers */
.detail-cols{display:flex;align-items:flex-start;gap:14px}
.detail-col{flex:1 1 0;min-width:0;display:flex;flex-direction:column}
.dsection{margin:0 0 14px;padding:0 0 14px;overflow:hidden}
.dsection h3{background:var(--surface-2);margin:0 0 10px;padding:9px 16px;
  border-bottom:1px solid var(--border);border-radius:var(--radius) var(--radius) 0 0;font-size:13px}
.dsection.sensitive h3{background:var(--danger-bg);color:var(--danger);border-bottom-color:transparent}
.dsection > *:not(h3){padding-left:16px;padding-right:16px}
.fields{grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:8px 16px}
.field{display:flex;flex-direction:column;gap:0;padding:2px 0}
.field .k{font-size:11px;font-weight:600;color:var(--label);letter-spacing:.01em}
.field .v{font-size:13px;text-align:left}
@media (max-width:900px){.detail-cols{flex-direction:column}}

/* column editor */
.col-editor{list-style:none;display:flex;flex-wrap:wrap;gap:7px;padding:0;margin:0 0 12px}
.col-editor li{border:1px solid var(--border);border-radius:7px;padding:5px 9px;background:var(--surface);
  cursor:grab;font-size:12px;display:flex;align-items:center;gap:7px;user-select:none}
.col-editor li:active{cursor:grabbing}
.col-editor .drag{color:var(--hint);display:flex}
.col-editor label{display:flex;align-items:center;gap:5px;cursor:pointer}

/* collapsible sidebar */
.brand-row{display:flex;align-items:center;justify-content:space-between;gap:8px}
.collapse-btn i{transition:transform .15s}
.show-when-collapsed{display:none;margin-right:8px}
.sb-collapsed .sidebar{width:56px;padding:18px 8px}
.sb-collapsed .sidebar .lbl,.sb-collapsed .brand,.sb-collapsed .nav .group{display:none}
.sb-collapsed .nav a{justify-content:center;padding:10px 0;gap:0}
.sb-collapsed .brand-row{justify-content:center}
.sb-collapsed .collapse-btn i{transform:rotate(180deg)}
.sb-collapsed .show-when-collapsed{display:inline-flex}

/* Excel-like resizable columns (services table) */
table.resizable{table-layout:fixed}
table.resizable th{position:relative}
table.resizable th,table.resizable td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
table.resizable td .tags{flex-wrap:nowrap;overflow:hidden}
.col-grip{position:absolute;top:0;right:0;width:7px;height:100%;cursor:col-resize;z-index:2}
.col-grip:hover{background:var(--accent)}

/* full-width tables + Excel-like visible column borders / grips */
.content{max-width:none}
table.resizable th,table.resizable td{border-right:1px solid var(--border)}
table.resizable th:last-child,table.resizable td:last-child{border-right:0}
/* Поле правки обязано следовать за шириной своего столбца. Иначе при сужении
   оно вылезает за границу ячейки и обрезается посередине, а при расширении
   остаётся узким, и освободившееся место пропадает зря — то есть тянуть
   столбец было бы бессмысленно. */
table.resizable td input[type="text"],table.resizable td input[type="date"],
table.resizable td input[type="email"],table.resizable td input[type="search"],
table.resizable td input:not([type]),table.resizable td select,
table.resizable td .combo{width:100%;min-width:0;box-sizing:border-box}
/* Клетка, где рядом стоят поле и кнопка (потребление, учётка). Правило выше
   писалось для клеток с ОДНИМ полем: там «на всю ширину» — ровно то, что
   нужно. Где за полем идёт ещё что-то, оно выдавливало соседа за границу
   ячейки, а `overflow:hidden` довершал дело — кнопка ключей пропадала с
   экрана целиком, и завести ключ было нечем. Здесь ширину делят: кнопка
   держит свой размер, поле забирает остаток и сжимается первым. */
table.resizable td .cellrow{display:flex;align-items:center;gap:4px;min-width:0}
table.resizable td .cellrow>input,
table.resizable td .cellrow>select{flex:1 1 40px;width:auto;min-width:0}
table.resizable td .cellrow>.btn{flex:0 0 auto}
table.resizable td .cellrow>span{flex:0 1 auto;overflow:hidden;text-overflow:ellipsis}
/* «Что получится» — пересчёт цены строки в базовую валюту по курсу месяца
   (№44). Это подсказка, а не данные: она не сохраняется, не участвует в
   разносе и меняется вместе с курсом месяца. Поэтому и выглядит как
   подсказка — приглушённо и мелко, чтобы её не приняли за вторую цену. */
.cur-was{flex:0 1 auto;color:var(--muted);font-size:11px;white-space:nowrap;
         overflow:hidden;text-overflow:ellipsis}
.col-grip{width:10px;right:-3px;background:transparent;border-radius:2px}
.col-grip:hover,.col-grip:active{background:var(--accent)}
.table-wrap{overflow-x:auto;overflow-y:hidden}

/* subtle themed horizontal scrollbar + table fills to page bottom */
.table-wrap{scrollbar-width:thin;scrollbar-color:var(--border) transparent}
.table-wrap::-webkit-scrollbar{height:10px}
.table-wrap::-webkit-scrollbar-track{background:transparent}
.table-wrap::-webkit-scrollbar-thumb{background:var(--border);border-radius:6px}
.table-wrap::-webkit-scrollbar-thumb:hover{background:var(--muted)}
.content.fill{display:flex;flex-direction:column;min-height:calc(100vh - 58px)}
.content.fill .table-wrap{flex:1 1 auto}

/* wrap long field values in detail/version cards; highlight changed fields */
.field .v{overflow-wrap:anywhere;white-space:normal}
.v.changed{color:var(--danger);font-weight:500}
details.fieldset summary{list-style:revert}

/* detail header split + button alignment */
.head-split{display:flex;gap:18px;flex-wrap:wrap;align-items:flex-start}
.head-main{flex:1 1 320px;min-width:0}
.head-links{flex:0 0 auto;min-width:190px;border-left:1px solid var(--border);padding-left:16px}
.actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:14px 0 0}
.actions form{display:inline-flex;margin:0}
.btn{display:inline-flex;align-items:center;gap:6px;line-height:1.1;vertical-align:middle}

.link-row{display:flex;flex-wrap:wrap;gap:14px;font-size:13px}

.badges-col{display:flex;flex-direction:column;align-items:flex-end;gap:4px}

.v.removed{color:var(--danger);text-decoration:line-through;opacity:.85}

/* density (compact/normal/comfortable)

   Высоту строки в таблицах с правкой задаёт НЕ отступ ячейки, а поле внутри
   неё: select и input были 35 px при отступе ячейки в 3 px, и переключатель
   плотности на них не влиял вовсе — жал он 6 px из 41. Поэтому те же три
   уровня управляют и полем: --ctl-pad-y и --ctl-fs. Так кнопка плотности в
   верхней панели наконец делает то, что обещает. */
:root{--row-pad-y:6px;--field-pad-y:2px;--ctl-pad-y:6px;--ctl-fs:13px}
[data-density="compact"]{--row-pad-y:3px;--field-pad-y:1px;--ctl-pad-y:3px;--ctl-fs:12.5px}
[data-density="normal"]{--row-pad-y:7px;--field-pad-y:3px;--ctl-pad-y:6px;--ctl-fs:13px}
[data-density="comfortable"]{--row-pad-y:11px;--field-pad-y:6px;--ctl-pad-y:8px;--ctl-fs:13px}
tbody td{padding:var(--row-pad-y) 6px}
/* Поля ВНУТРИ таблиц. Формы карточек и страниц не трогаем: там поле читают и
   заполняют по одному, а в таблице их семьдесят штук на экран, и лишние
   четыре пикселя на каждом — это минус три строки видимых данных. */
table td input[type="text"],table td input[type="date"],table td input[type="email"],
table td input[type="search"],table td input:not([type]),table td select{
  padding:var(--ctl-pad-y) 7px;font-size:var(--ctl-fs);line-height:1.3}
.field{padding:var(--field-pad-y) 0}
.dsection h3{font-size:14px}

/* per-section access badges */
/* pushed to the right edge; the fold chevron follows it with a fixed gap,
   otherwise both fight for the same auto margin and the badge lands mid-header */
.acc-badge{font-size:11px;font-weight:400;padding:1px 8px;border-radius:6px;margin-left:auto}
.acc-badge.ok{background:var(--success-bg);color:var(--success)}
.acc-badge.hid{background:var(--warning-bg);color:var(--warning)}
.acc-badge.adm{background:var(--danger-bg);color:var(--danger)}
.dsection h3{display:flex;align-items:center;gap:8px}

/* inline link fields (label + Open on one line) */
.field.row{flex-direction:row;justify-content:flex-start;align-items:baseline;gap:6px;flex-wrap:wrap}
.field.row .k{flex:0 0 auto}
.field.row .v{flex:0 0 auto;text-align:left}

/* version view: mark the SECTION header red where a change occurred */
.dsection h3.sec-changed{background:var(--danger-bg);color:var(--danger);border-bottom-color:transparent}
.sec-changed-tag{margin-left:auto;font-size:11px;font-weight:500;color:var(--danger);display:inline-flex;align-items:center;gap:4px}

/* access section: show only active by default, toggle reveals history */
/* ВНИМАНИЕ: acc-inactive ПРЯЧЕТ строку целиком. Ставить его можно только там,
   где рядом, в том же разделе, есть галочка data-toggle-showall — иначе данные
   останутся в разметке и исчезнут с экрана навсегда. Это уже случалось дважды
   (история на /my, отозванные лицензии). Сторожит scripts/hidden_rows_check.py.
   Если строку надо просто пригасить, а не прятать, — есть .row-off ниже. */
.acc-table .acc-inactive{display:none}
.acc-table.show-all .acc-inactive{display:table-row}
.acc-table.show-all .acc-empty{display:none}
.show-all-toggle{display:inline-flex;align-items:center;gap:6px;margin:0 0 8px;font-size:12px;color:var(--muted);cursor:pointer}

/* Приглушённая, но ВИДИМАЯ строка: архивная карта в форме, снятый доступ в
   «где используется». Такие строки нельзя прятать: именно на них смотрят,
   когда разбираются, что переподключить и что восстановить. */
.row-off{opacity:.55}
.row-off td:first-child::before{content:"\00D7 ";opacity:.7}

/* checkboxes inside .fld must render as normal checkboxes, not full-width inputs */
.fld input[type="checkbox"]{width:auto;padding:0;margin:0;border:0;vertical-align:middle}

/* collapsible fieldset (details) summary */
details.fieldset > summary{list-style:revert;padding:2px 0}
details.fieldset > summary:hover{color:var(--text)}

/* deep-search "matched in" mark on the service name */
.match-mark{color:var(--info);font-size:11px;margin-left:4px;cursor:help}

/* ─────────────────────────────────────────────────────────────────────────
   Телефон.

   Приложение остаётся десктопным: таблица сервисов на двадцать колонок и
   рабочая таблица на пяти дюймах бесполезны. Но три страницы человек открывает
   именно с телефона — «Мои подписки», «Инструкция» и страница пересмотра,
   которая вообще приходит ссылкой в письме. Они помечены `m-ready`, и заслон
   перед ними не встаёт.

   Всё ниже живёт внутри @media, поэтому десктопная вёрстка не меняется ни на
   пиксель.
   ───────────────────────────────────────────────────────────────────────── */
.mobile-notice{display:none}
.mobile-notice > div{margin:auto;width:100%;max-width:420px}
.mobile-links{display:flex;gap:8px;justify-content:center;margin:0 0 18px;flex-wrap:wrap}

/* Страховка на случай, если правило заслона снова станет шире, чем нужно.
   На бумаге напоминания про телефон не бывает никогда — это утверждение, а
   не оптимизация, и место ему в собственном правиле, а не в одном условии
   с шириной экрана. */
@media print{
  /* Селекторы намеренно длиннее необходимого: правило заслона ниже по файлу,
     и при равной силе побеждало бы оно. Здесь мы хотим победить всегда. */
  html .mobile-notice,html body.m-wall .mobile-notice{display:none !important}
  html body.m-wall{overflow:visible !important}
  html body.m-wall .layout{display:flex !important}
  html body.m-wall .ws-bar,html body.m-wall .ws-wrap{display:block !important}
}

/* `screen and` здесь — не украшение, а починка. Без него правило срабатывало
   ПРИ ПЕЧАТИ: лист A4 в книжной ориентации — это около 794 CSS-пикселей, то
   есть меньше 820, и браузер честно считал бумагу узким экраном. Владелец
   нажимал «Печать / сохранить в PDF» на отчёте разноса и получал лист с
   надписью «Этот раздел работает на компьютере» вместо отчёта.
   Бумага — не экран, и напоминание про телефон к ней не относится. */
@media screen and (max-width:820px),
       screen and (pointer:coarse) and (max-width:1024px){
  /* Прячем только под .m-wall — то есть там, где напоминание ДЕЙСТВИТЕЛЬНО
     нарисовано. Правило «прятать везде, где нет мобильного вида» оставляло
     форму входа пустым белым экраном: до входа напоминание не рисуется. */
  body.m-wall .mobile-notice{display:flex !important;position:fixed;
    top:0;left:0;right:0;bottom:0;width:100%;height:100vh;height:100dvh;
    z-index:9999;background:var(--bg);flex-direction:column;align-items:center;
    justify-content:center;text-align:center;padding:24px;margin:0;overflow:auto}
  body.m-wall{overflow:hidden}
  /* .ws-bar/.ws-wrap — рабочая таблица: у неё свой шаблон без .layout, и без
     этой строки она просто рисовалась бы под напоминанием. */
  body.m-wall .layout,body.m-wall .ws-bar,body.m-wall .ws-wrap{display:none}
  html.mobile-ok .mobile-notice{display:none !important}
  html.mobile-ok body{overflow:auto}
  html.mobile-ok .layout{display:flex}
  html.mobile-ok .ws-bar{display:flex}
  html.mobile-ok .ws-wrap{display:block}

  /* Меню уезжает вниз узкой полосой: боковая колонка съедала треть экрана. */
  body.m-ready .layout{flex-direction:column;min-height:100dvh}
  body.m-ready .sidebar{width:auto;position:sticky;bottom:0;order:2;height:auto;
    border-right:0;border-top:1px solid var(--border);padding:6px 8px;
    z-index:50;flex-shrink:0}
  body.m-ready .sidebar .brand-row,
  body.m-ready .sidebar .group,
  body.m-ready .collapse-btn{display:none}
  body.m-ready .nav{flex-direction:row;justify-content:space-around;gap:0}
  body.m-ready .nav a{flex-direction:column;gap:2px;font-size:11px;padding:6px 4px;
    text-align:center;flex:1;min-width:0}
  body.m-ready .nav a i{font-size:20px}
  body.m-ready .nav a .lbl{display:block;font-size:11px;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap;max-width:100%}
  body.m-ready .main{order:1}

  /* Верхняя строка: имя, роль и полдюжины кнопок настроек в один ряд не влезают
     и вытесняют заголовок. Оставляем язык и выход. */
  body.m-ready .topbar{padding:8px 12px;gap:8px}
  body.m-ready .topbar .crumb{display:none}
  body.m-ready .topbar .right > span:first-child,
  body.m-ready .fscale-btn,
  body.m-ready .theme-dd,
  body.m-ready .topbar .right [data-act="cycleDensity"]{display:none}
  body.m-ready .content{padding:14px 12px}
  body.m-ready h1{font-size:20px}
  body.m-ready .fieldset{padding:12px 12px}

  /* Таблица разворачивается в карточки: горизонтальная прокрутка на телефоне
     означает, что половину строки человек просто не увидит. Подпись столбца
     берётся из data-l, потому что шапки таблицы больше нет. */
  body.m-ready table.mtable,
  body.m-ready table.mtable thead,
  body.m-ready table.mtable tbody,
  body.m-ready table.mtable tr,
  body.m-ready table.mtable td{display:block;width:auto;min-width:0}
  body.m-ready table.mtable{min-width:0}
  body.m-ready table.mtable thead{display:none}
  body.m-ready table.mtable tr{border:1px solid var(--border);border-radius:8px;
    padding:8px 10px;margin:0 0 10px;background:var(--surface)}
  body.m-ready table.mtable td{border:0;padding:4px 0;display:flex;
    justify-content:space-between;align-items:baseline;gap:12px;white-space:normal}
  body.m-ready table.mtable td::before{content:attr(data-l);color:var(--muted);
    font-size:12px;flex:0 0 auto}
  body.m-ready table.mtable td[data-l=""]{justify-content:flex-end}
  body.m-ready table.mtable td[data-l=""]::before{content:none}
  body.m-ready table.mtable .rn{display:none}
  body.m-ready table.mtable form{margin:0}

  /* Кнопки и поля под палец, а не под курсор. */
  body.m-ready .btn{min-height:38px;padding:8px 14px}
  body.m-ready input[type="checkbox"]{width:20px;height:20px}
  body.m-ready .help-doc table{display:block;overflow-x:auto}
}

/* font-size / zoom toggle (A button): default / +10% / +25% */
html[data-fscale="1"] body{zoom:1.10}
html[data-fscale="2"] body{zoom:1.25}
.fscale-btn{font-weight:700;line-height:1;font-size:14px}
html[data-fscale="1"] .fscale-btn::after{content:"+";font-size:9px;vertical-align:super}
html[data-fscale="2"] .fscale-btn::after{content:"++";font-size:9px;vertical-align:super}

/* change-log rows in the service card */
.changes .chg-row{padding:5px 0;border-bottom:0.5px solid var(--border);font-size:12px;line-height:1.5;color:var(--text)}
.changes .chg-row:last-child{border-bottom:0}
.changes .chg-meta{font-size:11px;color:var(--muted)}

/* work log add form */
.worklog-add{display:flex;flex-direction:column;gap:6px;margin:0 0 8px}
.worklog-add .wl-row{display:flex;gap:6px;flex-wrap:wrap}
.worklog-add .wl-row input{flex:1 1 200px}
.worklog-add textarea{width:100%}
.worklog-add button{align-self:flex-start}

/* services table: roomier first column + 12px header indent */
#svcTable tbody td:first-child{padding-left:8px}

/* ===== Theme dropdown ===== */
.theme-dd{position:relative;display:inline-block}
.theme-menu{position:absolute;right:0;top:calc(100% + 6px);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:0 10px 28px rgba(0,0,0,.16);padding:6px;display:none;z-index:60;min-width:176px}
.theme-menu.open{display:block}
.theme-menu .tm-h{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);padding:5px 8px 7px}
.theme-menu button{display:flex;align-items:center;gap:9px;width:100%;text-align:left;background:transparent;border:0;color:var(--text);font:inherit;font-size:13px;padding:7px 8px;border-radius:var(--radius-sm);cursor:pointer}
.theme-menu button:hover{background:var(--surface-2)}
.theme-menu button.on{color:var(--accent)}
.theme-menu button.on::after{content:"";width:6px;height:6px;border-radius:50%;background:var(--accent);margin-left:auto}
.theme-menu button i{font-size:15px;opacity:.85}

/* ===== ACCESS GATE login ===== */
.login-wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;position:relative;z-index:1}
.gate{width:100%;max-width:384px;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:42px 34px 34px;text-align:center;position:relative;z-index:2}
.gate-title{font-weight:300;font-size:19px;letter-spacing:.4em;padding-left:.4em;color:var(--text);text-transform:uppercase}
.gate-sub{font-family:'Space Mono',monospace;font-size:11px;letter-spacing:.14em;color:var(--muted);margin-top:12px}
.gate-line{height:1px;background:var(--border);width:70px;margin:22px auto}
.gate-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;height:46px;border:1px solid var(--border);border-radius:6px;background:transparent;color:var(--text);font:inherit;font-size:14px;text-decoration:none;cursor:pointer;margin-top:10px;transition:background .15s,border-color .15s}
.gate-btn:hover{background:var(--surface-2);border-color:var(--muted)}
.gate-btn.primary{background:var(--text);color:var(--surface);border-color:var(--text)}
.gate-btn.primary:hover{background:var(--text);opacity:.9}
.gate-magic,.gate-pw{margin-top:12px;text-align:left}
.gate-magic input,.gate-pw input{width:100%;height:44px;margin-bottom:8px}
.gate-code{display:inline-block;margin-top:16px;font-family:'Space Mono',monospace;font-size:11px;letter-spacing:.08em;color:var(--muted);text-decoration:underline;text-underline-offset:3px;cursor:pointer;background:none;border:0}
.gate-code:hover{color:var(--text)}
.gate-foot{margin-top:26px;font-family:'Space Mono',monospace;font-size:9.5px;letter-spacing:.13em;color:var(--hint);line-height:1.95;text-transform:uppercase}
.gate .error{color:var(--danger);font-size:12px;margin-bottom:10px}
.gate .ok{color:var(--accent);font-size:12px;margin-bottom:10px}

/* ===== The Moving Target — the login quietly drifts (login only) ===== */
@media (prefers-reduced-motion: no-preference){
  .gate{animation:gateFloat 13s ease-in-out infinite}
  @media (prefers-reduced-motion:reduce){
    .gate,.gate-title,.gate-line,.gate-sub,body.anon .space-arc{animation:none}
  }
  .gate-title{animation:titleDrift 9s ease-in-out infinite;will-change:transform}
  .gate-line{animation:lineSlide 8s ease-in-out infinite}
  .gate-sub{animation:subDrift 11s ease-in-out infinite}
  .gate-btn{transition:transform .4s cubic-bezier(.2,.8,.2,1),background .15s,border-color .15s,opacity .15s}
  .gate-btn:hover{transform:translate(6px,-4px)}
  body.anon .space-arc{animation:arcDrift 34s ease-in-out infinite}
}
@keyframes gateFloat{0%,100%{transform:translate(0,0)}50%{transform:translate(-3px,-6px)}}
@keyframes titleDrift{0%,100%{transform:translate(0,0)}50%{transform:translate(5px,-2px)}}
@keyframes subDrift{0%,100%{transform:translate(0,0)}50%{transform:translate(-4px,1px)}}
@keyframes lineSlide{0%,100%{transform:translateX(-8px);opacity:.5}50%{transform:translateX(8px);opacity:1}}
@keyframes arcDrift{0%,100%{transform:translate(0,0) rotate(0deg)}50%{transform:translate(-16px,12px) rotate(.6deg)}}

/* ---- Audit Log badges ---- */
.aud-badge{display:inline-block;font-size:10px;line-height:1.5;padding:1px 6px;border-radius:10px;
  border:1px solid var(--border);letter-spacing:.03em;white-space:nowrap;vertical-align:middle}
.aud-badge + .aud-badge{margin-left:4px}
.aud-lvl-1{background:#e8f0fe;color:#1a4b8c;border-color:#c6d9f5}
.aud-lvl-2{background:#eaf7ee;color:#1f6b39;border-color:#cbe8d5}
.aud-lvl-3{background:#f4f0fb;color:#5b3b8c;border-color:#e0d5f2}
.aud-lvl-4{background:#f3f4f6;color:#5b636e;border-color:#dcdfe4}
.aud-src-auth{background:#fef3e8;color:#8a5a1e;border-color:#f5dcc0}
.aud-src-slack{background:#f3eefb;color:#5b3b8c;border-color:#e0d5f2}
.aud-src-scheduler,.aud-src-system{background:#f3f4f6;color:#5b636e;border-color:#dcdfe4}
.aud-src-web{background:transparent;color:var(--muted)}
/* dark & space-dark: soften badge fills */
[data-theme="dark"] .aud-badge,[data-theme^="space"] .aud-badge{background:rgba(255,255,255,.05);color:var(--text);border-color:var(--border)}
[data-theme="dark"] .aud-lvl-1,[data-theme^="space"] .aud-lvl-1{color:#9ec1ff}
[data-theme="dark"] .aud-lvl-2,[data-theme^="space"] .aud-lvl-2{color:#8fdca6}
[data-theme="dark"] .aud-lvl-3,[data-theme^="space"] .aud-lvl-3{color:#c3a8ee}

/* ---- Topbar title: keep the collapse button and the heading on one line ---- */
.topbar .title{display:flex;align-items:center;gap:10px;min-width:0}
.ttl-wrap{display:flex;flex-direction:column;justify-content:center;min-width:0}
.ttl{font-size:16px;font-weight:600;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crumb{display:none}   /* breadcrumb belongs to the Space themes only */

/* ---- Space themes: aerospace breadcrumbs + status glyphs ---- */
[data-theme^="space"] .crumb{display:block;font-family:'Space Mono',ui-monospace,monospace;
  font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;opacity:.5;line-height:1.4;margin-bottom:1px}
[data-theme^="space"] .ttl{font-weight:400;letter-spacing:.01em}
/* status glyphs, scoped to table cells so flash messages stay clean */
[data-theme^="space"] td .ok::before{content:"\25CF ";font-size:9px;vertical-align:middle}
[data-theme^="space"] td .badge.high::before{content:"\25CB ";font-size:9px;vertical-align:middle}
[data-theme^="space"] td .acc-inactive .muted::before,
[data-theme^="space"] tr.acc-inactive td:first-child::before{content:"\00D7 ";opacity:.6}

/* ---- Onboarding ("start here") page ---------------------------------- */
.onb-hero{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:20px 24px;margin-bottom:18px;max-width:1100px}
.onb-hero h2{font-size:19px;font-weight:600;margin:0 0 8px}
.onb-hero h3,.onb-hero h4{font-size:15px;font-weight:600;margin:14px 0 6px}
.onb-hero p{margin:0 0 8px;line-height:1.62;color:var(--text)}
.onb-hero ul,.onb-hero ol{margin:6px 0 10px;padding-left:20px;line-height:1.62}
.onb-hero li{margin:2px 0}
.onb-hero code{background:var(--surface-2);padding:1px 5px;border-radius:4px;font-size:12.5px}
.onb-hero hr{border:none;border-top:1px solid var(--border);margin:14px 0}
.onb-empty{display:flex;align-items:center;justify-content:space-between;gap:16px}

.onb-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:16px;max-width:1100px}
.onb-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:16px 18px;display:flex;flex-direction:column}
.onb-card header{display:flex;gap:12px;align-items:flex-start;margin-bottom:10px}
.onb-card header > i{font-size:20px;color:var(--accent);line-height:1.2;flex-shrink:0;margin-top:1px}
.onb-card h3{font-size:15px;font-weight:600;margin:0}
.onb-card header p{margin:2px 0 0;font-size:12.5px;color:var(--muted);line-height:1.45}

.onb-links{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
.onb-links a{display:grid;grid-template-columns:auto 1fr;gap:2px 10px;align-items:baseline;
  padding:8px 10px;margin:0 -10px;border-radius:var(--radius-sm);text-decoration:none;color:var(--text)}
.onb-links a:hover{background:var(--surface-2)}
.onb-links a > i{grid-row:1/3;align-self:center;font-size:16px;color:var(--muted)}
.onb-links a:hover > i{color:var(--accent)}
.onb-links .ttl{font-size:13.5px;font-weight:500}
.onb-links .ttl .ext{font-size:11px;margin-left:5px;opacity:.45}
.onb-links .dsc{font-size:12px;color:var(--muted);line-height:1.45}

.onb-notes textarea{width:100%;resize:vertical;font:inherit;font-size:13px;line-height:1.55;
  border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg);
  color:var(--text);padding:9px 11px}
.onb-notes textarea:focus{outline:none;border-color:var(--accent)}
.onb-status{font-size:11.5px;color:var(--muted);height:15px;margin-top:5px}
.onb-foot{font-size:12.5px;color:var(--muted);margin-top:16px}

.onb-admin-sec{border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px;margin-bottom:10px}
.onb-admin-sec.off{opacity:.55}
.onb-admin-links{width:100%;margin-top:6px}
.onb-admin-links tr.off{opacity:.5}
.onb-admin-links td{padding:3px 0;border:0}

/* Space themes: flatter cards, the accent does the talking */
[data-theme^="space"] .onb-card,[data-theme^="space"] .onb-hero{border-radius:4px}
[data-theme^="space"] .onb-card h3{font-weight:500;letter-spacing:.01em}

/* ---- "Open the worksheet" button with a hover explanation ---------------- */
/* ---- Services page toolbar -------------------------------------------------
   One height for every control in both rows. They used to disagree: an input
   carries line-height 1.45 and a button 1.1, so with identical padding the
   button came out five pixels shorter than the field beside it — small enough
   to look like a mistake rather than a choice, and it was. Setting the box
   explicitly means neither can drift again when padding changes. */
:root{--ctl-h:34px}
.toolbar input,.toolbar select{height:var(--ctl-h);box-sizing:border-box}
/* display belongs in the same rule as the size it makes work — otherwise the
   two can be separated by a later edit and the height silently stops applying. */
.toolbar .btn,.svc-tools .btn{display:inline-flex;align-items:center;justify-content:center;
  height:var(--ctl-h);box-sizing:border-box}

/* Filters on the left, tools on the right, one baseline. align-items:center
   rather than the default stretch: the two sides have different heights when
   the filters wrap, and stretching would pull the icons out of line. */
.svc-bar{display:flex;align-items:center;justify-content:space-between;
  gap:12px;flex-wrap:wrap;margin-bottom:14px}
.svc-bar-left{display:flex;align-items:center;gap:9px;flex-wrap:wrap;min-width:0}
/* The form no longer owns the bottom margin — the bar does, so both sides move
   together. */
.svc-bar .toolbar{margin-bottom:0}
/* Twice the default width: the placeholder now carries an instruction rather
   than a label, and a field that truncates its own instructions is worse than
   no instructions. Shrinks on narrow screens instead of pushing the row apart. */
.svc-search{width:340px;max-width:100%}
.svc-tools{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
/* Icon-only: square, so a row of tools reads as one group and the labelled
   primary action stands out from it. */
.tool-btn{display:inline-flex;width:var(--ctl-h);padding:0}
.tool-btn i{font-size:16px}
/* Marks the archive view as on — otherwise the only clue that the list is
   showing archived services is the list itself. */
.tool-btn.on{background:var(--surface-2);border-color:var(--accent);color:var(--accent)}

.ws-open{position:relative}
.ws-tip{position:absolute;top:calc(100% + 8px);right:0;z-index:20;width:250px;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:9px 11px;font-size:12px;font-weight:400;line-height:1.45;color:var(--muted);
  box-shadow:0 6px 20px rgba(0,0,0,.10);opacity:0;visibility:hidden;transform:translateY(-3px);
  transition:opacity .16s ease,transform .16s ease,visibility .16s;pointer-events:none;text-align:left;
  font-weight:400}
.ws-tip strong{color:var(--text);font-weight:600}
.ws-open:hover .ws-tip{opacity:1;visibility:visible;transform:translateY(0)}
@media (max-width:700px){.ws-tip{display:none}}

/* Countdown on the mobile notice: the button appears only when it reaches zero */
.mobile-wait{font-size:13px;color:var(--muted);letter-spacing:.02em}
.mobile-wait span{font-weight:600;color:var(--text)}

/* ---- User guide: readable hierarchy + collapsible contents -------------- */
.help-doc{scroll-behavior:smooth}
.help-doc h1{margin-bottom:4px}
.help-doc h2{font-size:19px;font-weight:600;margin:26px 0 4px;padding-top:6px}
.help-doc fieldset > legend{font-size:16px;font-weight:600;color:var(--text);
  padding:0 8px;letter-spacing:.005em}
.help-doc fieldset{padding-top:6px}
.help-doc h3{font-size:14.5px;font-weight:600;margin:14px 0 4px;color:var(--text)}
.help-doc p{line-height:1.62}
.help-doc table.acc-table th{font-weight:600}

.help-toc{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);
  margin:0 0 18px;overflow:hidden}
.help-toc > summary{cursor:pointer;padding:11px 16px;font-size:13.5px;font-weight:600;
  list-style:none;display:flex;align-items:center;gap:8px;user-select:none}
.help-toc > summary::-webkit-details-marker{display:none}
.help-toc > summary::before{content:"\25B8";font-size:11px;color:var(--muted);transition:transform .15s ease}
.help-toc[open] > summary::before{transform:rotate(90deg)}
.help-toc > summary:hover{background:var(--surface-2)}
.help-toc nav{display:flex;flex-direction:column;padding:2px 10px 12px;border-top:1px solid var(--border)}
.help-toc nav a{padding:5px 10px 5px 22px;font-size:13px;color:var(--link);text-decoration:none;
  border-radius:var(--radius-sm)}
.help-toc nav a:hover{background:var(--surface-2)}
.help-toc nav a.grp{margin-top:8px;padding-left:10px;font-weight:600;color:var(--text);
  text-transform:uppercase;font-size:11.5px;letter-spacing:.08em}
[data-theme^="space"] .help-doc fieldset > legend{font-weight:500;letter-spacing:.02em}

/* ---- Activity feed: clickable rows and the unfolded entry --------------- */
tr.act-row{cursor:pointer}
tr.act-row:hover{background:var(--surface-2)}
tr.act-row.open{background:var(--surface-2)}
tr.act-row.open td{border-bottom:0}
tr.act-detail > td{padding:0 0 12px;background:var(--surface-2)}
.act-card{padding:12px 16px;border-left:2px solid var(--accent);margin:0 6px 0 12px;
  background:var(--surface);border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.act-meta{display:flex;flex-wrap:wrap;gap:14px;font-size:12px;color:var(--muted);margin-bottom:8px}
.act-meta i{margin-right:3px}
.act-text{font-size:13.5px;line-height:1.6;white-space:pre-wrap;word-break:break-word}
.act-comment{font-size:13px;line-height:1.55;color:var(--muted);margin-top:6px;white-space:pre-wrap}
.act-parts{font-size:12.5px;margin-top:8px}
.act-parts a{color:var(--link);text-decoration:none}
/* Clip long cells so the grid stays scannable — the full text lives in the card */
table.act-table td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
table.act-table tr.act-detail td{overflow:visible;white-space:normal}

/* ---- Service card: layout switcher, folding, arrangements -------------- */
.card-toolbar{display:flex;justify-content:flex-end;margin:0 0 10px}
.lay-pick{position:relative}
.lay-menu{position:absolute;right:0;top:calc(100% + 6px);z-index:30;min-width:190px;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:5px;display:none;box-shadow:0 8px 24px rgba(0,0,0,.10)}
.lay-menu.open{display:block}
.lay-menu .tm-h{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);padding:5px 9px}
.lay-menu button{display:block;width:100%;text-align:left;font:inherit;font-size:13px;padding:7px 9px;
  border:0;background:none;color:var(--text);border-radius:var(--radius-sm);cursor:pointer}
.lay-menu button:hover{background:var(--surface-2)}
.lay-menu button.on{background:var(--accent);color:#fff}

.card-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(118px,1fr));gap:10px;margin-bottom:14px}
.card-kpis .kpi{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:9px 12px}
.card-kpis .kpi .l{font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.card-kpis .kpi .v{font-size:17px;font-weight:600;margin-top:2px}

.card-tabs{display:flex;gap:4px;flex-wrap:wrap;border-bottom:1px solid var(--border);margin-bottom:14px}
.card-tabs button{font:inherit;font-size:13px;padding:8px 13px;border:0;background:none;color:var(--muted);
  cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px}
.card-tabs button.on{color:var(--text);border-bottom-color:var(--accent);font-weight:500}

.card-nav{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:5px;
  align-self:start;position:sticky;top:64px}
.card-nav button{display:flex;align-items:center;gap:8px;width:100%;text-align:left;font:inherit;font-size:13px;
  padding:7px 10px;border:0;background:none;color:var(--text);border-radius:var(--radius-sm);cursor:pointer}
.card-nav button:hover{background:var(--surface-2)}
.card-nav button.on{background:var(--accent);color:#fff}
.content.has-nav #cardNav{float:left;width:196px;margin-right:14px}
.content.has-nav .card-stage{overflow:hidden}

.card-cfg{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:11px 14px;margin-bottom:14px}
.card-cfg .cfg-row{display:flex;flex-wrap:wrap;gap:6px 16px;align-items:center;font-size:12.5px}
.card-cfg .cfg-row + .cfg-row{margin-top:8px;padding-top:8px;border-top:1px solid var(--border)}
.card-cfg label{display:inline-flex;align-items:center;gap:6px}

.dsection > h3{cursor:pointer;user-select:none}
.dsection .fold-chev{margin-left:8px;font-size:15px;color:var(--muted);transition:transform .15s ease}
.dsection.closed .fold-chev{transform:rotate(-90deg)}
.dsection.closed > *:not(h3){display:none}
.card-stage .detail-cols{align-items:start}

/* ---- Field width scale (replaces hand-set inline widths) ---------------- */
.w-xs{width:80px}.w-sm{width:120px}.w-md{width:150px}


/* ---- Section groups: chips that add up, not tabs that navigate --------- */
/* Group filters look exactly like the tab bar — the underline reads as "this one
   is on" just as well as a pill did, and two switchers in the same product that
   do the same job should not look like two different controls. The difference in
   behaviour stays: here several can be on at once. */
.card-tabs.multi{align-items:center}
.card-tabs.multi button.on{font-weight:600}
.card-tabs.multi .grp-hint{font-size:12px;color:var(--muted);margin-left:8px;align-self:center}

/* Card is hidden only while the layout engine places the blocks (class added by
   script, removed by the engine and by a failsafe timer) — no flash of blocks
   jumping into position, and no way to end up with a permanently blank card. */
#cardWrap.card-booting{visibility:hidden}
.lay-pick{position:relative;display:inline-flex}

/* ---- Billing links: the label IS the link ------------------------------- */
/* "Open" said nothing — four rows all reading "Open" told you where you were
   going only via the label next to them. Now the label itself is the target. */
.bill-link .v{text-align:right}
.bill-link a{display:inline-flex;align-items:center;gap:7px;text-decoration:none}
.bill-link .bl-ico{font-size:15px;opacity:.65}
.bill-link .bl-go{font-size:12px;opacity:.45}
.bill-link a:hover .bl-go,.bill-link a:hover .bl-ico{opacity:.9}
/* the name lives inside the link, so the duplicate label on the left goes away:
   one clickable item that says where it leads */
.bill-link .k{display:none}
.bill-link .bl-lbl{display:inline}
.bill-link .v{text-align:left}

/* Links as tiles for every layout: the whole tile is the target.
   auto-FILL, not auto-fit, and a width capped at a fifth of the row: five tiles
   fit across, and two links stay two normal tiles with empty space after them
   instead of stretching into two huge banners. When the block is too narrow for
   five, the cap falls below the 150px minimum, minmax() then uses the minimum and
   the tiles simply wrap — so it degrades on its own without a media query. */
.fields:has(.bill-link){display:grid;
  grid-template-columns:repeat(auto-fill,minmax(150px,calc(20% - 7px)));
  gap:8px}
/* The rule under the tiles separates them from what follows — the billing email
   and the cards. In External links the tiles ARE the section, so a line there
   divides nothing and just hangs above the section border. Hence :not(:last-child):
   the separator appears only when there is something to separate from. */
.fields:has(.bill-link):not(:last-child){padding-bottom:12px;
  border-bottom:1px solid var(--border);margin-bottom:10px}
.bill-link{display:block}
.bill-link a{display:flex;width:100%;padding:9px 12px;border:1px solid var(--border);
  border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text);
  font-size:13px;line-height:1.2}
.bill-link a:hover{border-color:var(--accent);color:var(--accent)}
.bill-link .bl-go{margin-left:auto}

/* Cards sit on their own panel so the section reads as two parts: where to go,
   and what pays for it. */
.bill-cards{background:var(--surface-2);border-radius:var(--radius);padding:10px 13px}
.bill-cards .field{align-items:baseline}
.bill-cards .k{color:var(--muted)}

/* role chip on a billing account (all layouts) */
.bill-role{font-size:10.5px;padding:1px 7px;border-radius:20px;vertical-align:middle}

/* ---- Section groups on the edit form ------------------------------------ */
.form-groups{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:0 0 14px}
.form-groups button{border:1px solid var(--border);border-radius:20px;padding:5px 14px;font:inherit;
  font-size:12.5px;color:var(--muted);background:var(--surface);cursor:pointer}
.form-groups button:hover{background:var(--surface-2);color:var(--text)}
.form-groups button.on{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:500}
.form-groups .grp-hint{font-size:12px;color:var(--muted)}

/* Individual account model: the shared-billing block is replaced by a note, and
   a subscription with no note gets a quiet nudge instead of a blocking error. */
.am-off{border:1px dashed var(--border);background:var(--surface-2);border-radius:var(--radius-sm);padding:12px 14px}
.am-warn{margin-left:6px;font-size:11px;padding:1px 7px;border-radius:99px;background:var(--warning-bg);color:var(--warning);white-space:nowrap}

/* ---- One row, one height ------------------------------------------------ */
/* Inline forms mix inputs, selects and buttons on a single line. The inputs are
   ~35px tall while .btn.sm was ~23px, so every "Save" and "Add" sat visibly lower
   and smaller than the field it belonged to. The buttons grow to match the field
   rather than the fields shrinking: a control you click deserves the bigger
   target, and icon-only buttons stop looking like an afterthought. */
.inline-form input,.inline-form select,.inline-form .btn,.inline-form button{
  min-height:34px;box-sizing:border-box}
.inline-form .btn,.inline-form button{
  padding:0 12px;font-size:13px;display:inline-flex;align-items:center;gap:6px}

/* Activity-log entry: the row itself is the target, so it needs to look like one. */
.changes .chg-row.wl-entry{cursor:pointer;border-radius:var(--radius-sm);
  padding-left:6px;padding-right:6px;margin-left:-6px;margin-right:-6px}
.changes .chg-row.wl-entry:hover{background:var(--surface-2)}
/* Same "one row, one height" rule as .inline-form — the activity form mixes
   inputs, selects, buttons and link-buttons on one line too. */
.wl-row input,.wl-row select,.wl-row .btn,.wl-row button,.wl-row .iconbtn,
.worklog-add > .btn,.worklog-add button[type="submit"]{
  min-height:34px;box-sizing:border-box}
.wl-row .btn,.wl-row button,.worklog-add button[type="submit"]{
  padding:0 12px;font-size:13px;display:inline-flex;align-items:center;gap:6px}
.cc-card .iconbtn{min-height:30px;min-width:30px;display:inline-flex;
  align-items:center;justify-content:center}

/* Row numbering in people lists: quiet, monospaced, never wider than it needs. */
.num-col{width:44px;text-align:right;color:var(--hint);font-variant-numeric:tabular-nums;
  font-size:12px;padding-right:10px !important;white-space:nowrap}

/* Reveal-hidden-rows toggle: the all-seeing eye, quiet until you hover it. */
.eye-toggle{color:var(--hint);text-decoration:none;line-height:1;display:inline-flex}
.eye-toggle:hover{color:var(--accent)}
.eye-provi{vertical-align:middle;opacity:.75;transition:opacity .12s}
.eye-toggle:hover .eye-provi{opacity:1}

/* Change-log entry: meta on one line, the change itself on the next, and the whole
   row opens in the side panel — long values no longer have to fit on one line. */
.changes .chg-row.chg-entry{cursor:pointer;border-radius:var(--radius-sm);
  padding:6px;margin:0 -6px}
.changes .chg-row.chg-entry:hover{background:var(--surface-2)}
.changes .chg-text{font-size:12px;line-height:1.5;margin-top:1px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* Нумерация строк (список сервисов, подписки внутри карточки).
   Счётчик CSS, а не индекс цикла в шаблоне: строка со скрытой подпиской
   (display:none) бокс не создаёт и счётчик не двигает, поэтому номера всегда
   идут 1..N по тому, что видно на экране, — и после включения «показать все»
   пересчитываются сами. Номер рисуется через ::before, так что при копировании
   таблицы в буфер он не попадает. */
table.rownums tbody{counter-reset:rn}
table.rownums tbody>tr{counter-increment:rn}
/* Строки ключей номера НЕ получают. Нумеруются подписки, а ключ — не подписка:
   раскрыл человека под номером 2 — и следующий за ним становился четвёртым,
   пятым, седьмым, в зависимости от того, кого раскрыли выше. Находка владельца
   11.09.2026. Скрытая строка счётчик и так не двигает, поэтому до раскрытия
   всё выглядело правильно — и тем неприятнее прыгало после. */
table.rownums tbody>tr.u-key-row,
table.rownums tbody>tr.u-orphan,
table.rownums tbody>tr.u-key-addline,
table.rownums tbody>tr.u-key-new{counter-increment:none}
table.rownums td.rn::before{content:counter(rn)}
table.rownums th.rn,table.rownums td.rn{
  width:34px;text-align:right;padding-left:6px;padding-right:8px;
  color:var(--muted);font-variant-numeric:tabular-nums;
  -webkit-user-select:none;user-select:none}

/* Выпадающий список с поиском (combo.js).

   .combo-native — это сам <select>. Он НЕ display:none: спрятанное так поле
   браузер не может сфокусировать, и обязательное поле молча перестаёт
   отправляться — форма не уходит, а на экране ничего не происходит. Поэтому
   крошечный прозрачный элемент: поле остаётся в форме и остаётся фокусируемым,
   а подсказка о незаполненном обязательном поле показывается рядом с поиском. */
.combo{position:relative;display:inline-block;vertical-align:middle}
.combo-native{position:absolute;left:8px;bottom:0;width:1px;height:1px;
  opacity:0;pointer-events:none;border:0;padding:0;margin:0}
.combo-input{min-width:230px}
/* position:fixed, а не absolute: внутри .dsection и .table-wrap стоит
   overflow:hidden, и абсолютный список обрезался по краю блока. Координаты
   ставит combo.js по месту поля. */
.combo-list{display:none;position:fixed;z-index:900;margin-top:0;
  min-width:180px;max-width:420px;max-height:280px;overflow:auto;
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius-sm);box-shadow:0 6px 20px rgba(0,0,0,.12)}
.combo-list.open{display:block}
.combo-item{padding:6px 10px;font-size:13px;cursor:pointer;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;color:var(--text)}
.combo-item:hover,.combo-item.on{background:var(--surface-2)}
.combo-none{color:var(--muted);cursor:default}
.combo-none:hover{background:transparent}

/* Значок тарификации сервиса. «Не задано» намеренно бледное: это не ошибка, а
   «ещё не разметили», и кричать об этом не нужно. */
.badge.unset{background:var(--surface-2);color:var(--muted)}
.badge.per_seat{background:#e6f4ec;color:#1d7a4c}
.badge.mixed{background:#fdf3e3;color:#8a5a10}
.badge.usage,.badge.flat{background:#eef3fb;color:#1a4a8a}

/* Даты выдачи и отзыва не должны переноситься: «01.09.» на одной строке
   и «2026» на другой читается как две разные даты. */
.acc-table td.nowrap,.acc-table th.nowrap{white-space:nowrap}


/* Полоса «только чтение». Намеренно спокойная, не тревожная: это не ошибка и
   не авария, это постоянный режим работы человека — красная лента сверху
   каждый день быстро перестаёт читаться. */
.ro-bar{display:flex;align-items:center;gap:8px;padding:7px 14px;font-size:12.5px;
        background:var(--warn-bg,#fff7e6);color:var(--warn,#8a6100);
        border-bottom:1px solid var(--line)}

/* Код сервиса в списке. По нему идут выгрузка и импорт сумм, его переносят в
   чужие таблицы — поэтому он кликабельный и выглядит как то, что можно нажать.
   .copied на секунду подтверждает: без ответа непонятно, сработало или мимо. */
.keycode{font-family:Consolas,ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:600;
         letter-spacing:.5px;cursor:pointer;padding:1px 6px;border-radius:5px;
         border:1px solid var(--line);background:var(--chip-bg,rgba(0,0,0,.04));
         white-space:nowrap;user-select:all;transition:background .15s,color .15s}
.keycode:hover{background:var(--accent-bg,rgba(0,0,0,.08))}
.keycode.copied{background:var(--ok-bg,#e6f6ea);color:var(--ok,#1a7f37);border-color:currentColor}
.keycode.copied::after{content:" \2713"}
