/* Base components of the cabinet. Ported from design/prototype-v2/assets/app.css (v2.1).
   Rules: radius 0, no shadows, 1px lines, no icons except the brand square and the status dot,
   no animations, no chips / tiles / segments / caps labels. Tokens live in tokens.css. */

* { box-sizing: border-box; }
html, body { margin: 0; background: var(--bg); color: var(--fg); }
body { font: var(--fs-base)/1.55 var(--sans); -webkit-font-smoothing: antialiased; }
a { color: inherit; text-underline-offset: 3px; }
code, pre, .mono, input, select, button, textarea, table { font-family: var(--mono); }
code { font-size: 12.5px; background: var(--soft); padding: 1px 5px; }
h1 { font: 500 var(--fs-h1)/1.3 var(--sans); letter-spacing: -0.01em; margin: 0; }
h2 { font: 500 var(--fs-h2)/1.4 var(--sans); margin: 0 0 4px; }
p { margin: 8px 0; }
.muted { color: var(--muted); }
.faint { color: var(--faint); }
.bad { color: var(--bad); }
.small { font-size: var(--fs-small); }
.num { font-variant-numeric: tabular-nums; }
[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
:focus-visible { outline: 1px solid var(--line-strong); outline-offset: 2px; }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: none; } /* the border already shows focus */
#app:focus, .main:focus, h1:focus { outline: none; }
.skip { position: absolute; left: 16px; top: -100px; z-index: 30; background: var(--fg); color: var(--bg); padding: 8px 12px; font: 12.5px var(--mono); text-decoration: none; }
.skip:focus { top: 12px; }
.nw { white-space: nowrap; }

/* ---------- shell ---------- */
.shell { display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr); min-height: 100vh; min-height: 100dvh;
  background: linear-gradient(var(--line), var(--line)) calc(var(--side-w) - 1px) 0 / 1px 100% no-repeat; }
.side { padding: 22px 16px; display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh; }
.brand { font: 500 14px var(--mono); padding: 0 10px 28px; display: flex; align-items: center; gap: 8px; text-decoration: none; }
.brand i { width: 10px; height: 10px; background: var(--accent); display: inline-block; flex: none; }
.side .brand { order: 0; }
.switch { order: 1; padding: 0 10px 18px; margin-top: -14px; position: relative; }
.switch .sw-cur { border: 0; padding: 4px 0; background: none; font: 12.5px/1.45 var(--mono); color: var(--muted); text-align: left; width: 100%; white-space: normal; overflow-wrap: anywhere; }
.switch .sw-cur:hover, .switch .sw-cur[aria-expanded="true"] { color: var(--fg); background: none; }
.switch .sw-list { list-style: none; margin: 4px 0 0; padding: 0; border-left: 1px solid var(--line); }
.switch .sw-list a { display: block; padding: 6px 0 6px 10px; font: 12.5px/1.45 var(--mono); color: var(--muted); text-decoration: none; overflow-wrap: anywhere; }
.switch .sw-list a:hover { color: var(--fg); }
.side .nav { order: 2; }
.nav a { display: block; padding: 7px 10px; text-decoration: none; font: 13px var(--mono); color: var(--muted); }
.nav a:hover { color: var(--fg); }
.nav a.on { color: var(--fg); background: var(--soft); }
.nav .sep { height: 1px; background: var(--line); margin: 12px 10px; }
.side .bottom { order: 9; margin-top: auto; padding: 0 10px; display: flex; flex-direction: column; gap: 12px; }
/* «Выйти» is a text link everywhere: sidebar, login, invite, 404 */
.out { font: 12px var(--mono); color: var(--muted); background: none; border: 0; padding: 0; text-decoration: underline; text-underline-offset: 3px; text-align: left; cursor: pointer; }
.out:hover { color: var(--fg); background: none; }
.lang { font: 12px var(--mono); color: var(--faint); display: flex; gap: 10px; }
.lang button { font: inherit; color: var(--muted); background: none; border: 0; padding: 0; cursor: pointer; }
.lang button:hover { color: var(--fg); background: none; }
.lang button.on { color: var(--fg); text-decoration: underline; text-underline-offset: 4px; }
/* in the cabinet the language switch is one quiet line, no underline */
.side .lang button { color: var(--faint); }
.side .lang button.on { color: var(--muted); text-decoration: none; }
.side .lang button:hover { color: var(--fg); }
.main { padding: var(--page-top) var(--page-x) 80px; max-width: 1040px; width: 100%; min-width: 0; }
.main.narrow { max-width: 820px; }
.head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: var(--after-head); }
.head .sub { font: var(--fs-cap)/1.7 var(--mono); color: var(--muted); margin-top: 6px; }

/* bare layout: login, invite code, join, 404 */
.bare { min-height: 100vh; min-height: 100dvh; display: grid; place-items: center; padding: 24px 16px; }
.bare .box { width: 100%; max-width: 360px; }
.bare .brand { padding: 0 0 28px; font-size: 15px; }
.bare h1 { margin-bottom: 8px; }
.bare .lead { color: var(--muted); font-size: 13.5px; margin: 0 0 8px; }
.bare form .primary, .bare form button[type=submit] { width: 100%; margin-top: 18px; padding: 10px; }
.bare .alt { margin-top: 28px; font: 12px var(--mono); color: var(--muted); display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.bare .alt a { color: var(--muted); }
.tg { min-height: 40px; margin-top: 8px; }

/* ---------- controls ---------- */
button, .btn { font: 12.5px var(--mono); background: transparent; color: var(--fg); border: 1px solid var(--line-strong); padding: 7px 14px; cursor: pointer; border-radius: 0; text-decoration: none; display: inline-block; line-height: 1.5; }
button:hover, .btn:hover { background: var(--soft); }
button:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: default; }
button:disabled:hover { background: transparent; }
.primary { background: var(--fg); color: var(--bg); }
.primary:hover { background: var(--fg); opacity: .88; }
.primary:disabled:hover { background: var(--fg); }
.ghost { border-color: var(--line); color: var(--fg-2); }
.ghost:hover { border-color: var(--line-strong); color: var(--fg); }
.link { border: 0; padding: 0; background: none; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.link:hover { background: none; color: var(--fg); }
input, select, textarea { font-size: 13px; color: var(--fg); background: var(--bg); border: 1px solid var(--field); padding: 8px 10px; border-radius: 0; outline: none; width: 100%; }
input:focus, select:focus, textarea:focus { border-color: var(--line-strong); }
input::placeholder, textarea::placeholder { color: var(--faint); }
textarea { resize: vertical; line-height: 1.5; }
select { width: auto; appearance: none; padding-right: 28px; cursor: pointer;
  background: var(--bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%238a8a8a'/%3E%3C/svg%3E") no-repeat right 10px center; }
label { display: block; font: 12px var(--mono); color: var(--muted); margin: 16px 0 6px; }
.err { color: var(--bad); font: 12px var(--mono); margin-top: 12px; min-height: 18px; }

/* text switches instead of segmented controls */
.links { font: 12.5px var(--mono); color: var(--faint); display: flex; gap: 6px 16px; flex-wrap: wrap; }
.links a, .links button { color: var(--muted); text-decoration: none; background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.links a:hover, .links button:hover { color: var(--fg); background: none; }
.links .on { color: var(--fg); text-decoration: underline; text-underline-offset: 5px; }

/* status */
.dot { display: inline-block; width: 7px; height: 7px; background: var(--accent); margin-right: 8px; vertical-align: 1px; }
.dot.bad { background: var(--bad); }
.dot.off { background: var(--faint); }
.status { font: 12.5px var(--mono); color: var(--muted); margin-top: 8px; }
.status .st { color: var(--fg); }
.status .st.bad { color: var(--bad); }
.todo { font: 13px var(--mono); margin-top: 20px; }
.todo a { color: var(--fg); }
.todo .calm { color: var(--muted); }
.today { font: 12.5px var(--mono); color: var(--muted); margin-top: 6px; }
.today a { color: var(--muted); }
.today a:hover { color: var(--fg); }
.saved { font: 12px var(--mono); color: var(--muted); padding-top: 6px; }

/* ---------- feed rows (Server) ---------- */
.sect { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 40px 0 10px; }
.feed { border-top: 1px solid var(--line); font: var(--fs-row)/1.5 var(--mono); }
.msg { display: grid; grid-template-columns: 48px 140px minmax(0, 1fr) auto; gap: 16px; padding: 9px 0; border-bottom: 1px solid var(--line); align-items: baseline; text-decoration: none; }
.msg .t { color: var(--faint); font-variant-numeric: tabular-nums; }
.msg.open .t, .it[open] > summary .t { color: var(--muted); }   /* on --soft --faint drops below 4.5:1 */
.msg .n { color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.msg .x { min-width: 0; overflow-wrap: anywhere; }
.msg .m { color: var(--muted); font-size: 12px; white-space: nowrap; }
a.msg:hover { background: var(--soft); }
.msg.hid .x { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--faint); }
.msg.sys .x { color: var(--muted); }
.foot { font: 12px var(--mono); color: var(--faint); padding: 16px 0; }
.foot a { color: var(--muted); }

/* ---------- journal entries ---------- */
.day { font: 12px var(--mono); color: var(--faint); padding: 28px 0 8px; border-bottom: 1px solid var(--line); }
.day:first-child { padding-top: 0; }
.log { font: var(--fs-row)/1.5 var(--mono); }
.it > summary { list-style: none; cursor: pointer; display: grid; grid-template-columns: 48px 140px minmax(0, 1fr) auto; gap: 16px; padding: 10px 0; border-bottom: 1px solid var(--line); align-items: baseline; }
.it > summary::-webkit-details-marker { display: none; }
.it > summary:hover { background: var(--soft); }
.it .t { color: var(--faint); font-variant-numeric: tabular-nums; }
.it .n { color: var(--fg-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.it .x { min-width: 0; overflow-wrap: anywhere; }
.it .m { color: var(--muted); font-size: 12px; white-space: nowrap; text-align: right; }
.it[open] > summary { border-bottom-color: transparent; background: var(--soft); }
.it.fp .x { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--faint); }
.ctx { background: var(--soft); border-bottom: 1px solid var(--line); padding: 2px 16px 16px 220px; }
.ctx .l { padding: 2px 0; color: var(--muted); overflow-wrap: anywhere; }
.ctx .l b { font-weight: 400; color: var(--muted); margin-right: 10px; }
.ctx .l.me { color: var(--fg); }
.ctx .l.me b { color: var(--fg-2); }
.ctx .meta { margin-top: 14px; display: flex; gap: 10px 16px; align-items: center; flex-wrap: wrap; font-size: 12.5px; color: var(--muted); }
.ctx .meta .sp { flex: 1; }
.ctx .meta button { padding: 5px 12px; }
.ctx .meta a { color: var(--muted); }

/* ---------- rules ---------- */
.rules { border-top: 1px solid var(--line); }
.rule { display: grid; grid-template-columns: minmax(0, 1fr) 220px; gap: 20px; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--line); }
.rule .nm { font: 13.5px var(--mono); }
.rule .ds { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.rule select { width: 100%; }
.more { border-bottom: 1px solid var(--line); }
.more > summary { list-style: none; cursor: pointer; padding: 14px 0; font: 13px var(--mono); color: var(--muted); }
.more > summary:hover { color: var(--fg); }
.more > summary::-webkit-details-marker { display: none; }
.more > summary::after { content: '\00a0↓'; color: var(--faint); }
.more[open] > summary::after { content: '\00a0↑'; }
.more > .rule:first-of-type { border-top: 1px solid var(--line); }
.more .rule:last-child { border-bottom: 0; }
.probe { margin-top: 56px; max-width: 560px; }
.probe textarea { font-size: 13.5px; }
.probe .row { display: flex; gap: 16px; align-items: baseline; margin-top: 10px; flex-wrap: wrap; font: 12.5px var(--mono); color: var(--muted); }
.probe .row b { font-weight: 400; color: var(--fg); }

/* ---------- connect ---------- */
.steps { border-top: 1px solid var(--line); max-width: 680px; }
.step { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 8px; padding: 26px 0; border-bottom: 1px solid var(--line); }
.step .no { font: 13px var(--mono); color: var(--faint); padding-top: 1px; }
.step p { color: var(--muted); margin: 0 0 14px; font-size: 13.5px; }
.step .ver { font: 12px var(--mono); color: var(--faint); margin-left: 12px; }
.code { display: flex; align-items: stretch; border: 1px solid var(--line); background: var(--soft); margin-top: 10px; }
.code pre { margin: 0; flex: 1; min-width: 0; padding: 12px 14px; font-size: 13.5px; line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.code button { border: 0; border-left: 1px solid var(--line); color: var(--muted); padding: 0 14px; flex: none; }
.wait { font: 13px var(--mono); color: var(--muted); }
.check { margin: 14px 0 0; padding: 0 0 0 18px; color: var(--muted); font-size: 13px; line-height: 1.8; }

/* ---------- admin ---------- */
.big { display: flex; gap: 64px; flex-wrap: wrap; margin-bottom: 40px; }
.big .k { font: 12.5px var(--mono); color: var(--muted); }
.big .v { font: 500 var(--fs-big)/1.2 var(--mono); margin-top: 6px; font-variant-numeric: tabular-nums; }
.big .d { font: 12.5px var(--mono); color: var(--muted); margin-top: 4px; }
.tbl { width: 100%; overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 13px; font-variant-numeric: tabular-nums; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); white-space: nowrap; }
th:first-child, td:first-child { padding-left: 0; }
th:last-child, td:last-child { padding-right: 0; }
th { font-weight: 400; color: var(--muted); font-size: 12px; }
th.sort { cursor: pointer; }
th.sort:hover { color: var(--fg); }
td.r, th.r { text-align: right; }
td.nm { white-space: normal; overflow-wrap: anywhere; }
tr.row { cursor: pointer; }
tr.row:hover td { background: var(--soft); }
tr.row.open td { background: var(--soft); border-bottom-color: transparent; }
tr.card > td { background: var(--soft); padding: 0 16px 18px; }
tr.card .ip { font-size: 12px; color: var(--muted); padding: 2px 0 10px; }
tr.card table { font-size: 12.5px; }
tr.card th, tr.card td { padding: 6px 12px; }
tr.grp td { color: var(--muted); font-size: 12px; padding-top: 22px; }
tr.fold td { color: var(--muted); cursor: pointer; }
tr.fold:hover td { color: var(--fg); }
tr.off td { color: var(--muted); }
tfoot td { border-bottom: 0; border-top: 1px solid var(--fg-2); }
.note { font: 12px/1.7 var(--mono); color: var(--faint); margin-top: 16px; }

/* ---------- states: loading placeholder, empty, error, 404 ----------
   The design forbids shimmer skeletons and animations. The placeholder below is a static set of
   empty rows with the same height as .msg rows, so the page does not jump when data arrives.
   ui.placeholder() shows it only when loading takes longer than 400 ms. */
.skel { border-top: 1px solid var(--line); }
.skel .r { height: 41px; border-bottom: 1px solid var(--line); display: grid; grid-template-columns: 48px 140px minmax(0, 1fr); gap: 16px; align-items: center; }
.skel .r i { display: block; height: 9px; background: var(--soft); }
.skel .r i:nth-child(1) { width: 36px; }
.skel .r i:nth-child(2) { width: 70%; }
.skel .r:nth-child(3n+1) i:nth-child(3) { width: 58%; }
.skel .r:nth-child(3n+2) i:nth-child(3) { width: 34%; }
.skel .r:nth-child(3n) i:nth-child(3) { width: 46%; }
.skel.bare-rows { border-top: 0; }
.empty { font: 13px var(--mono); color: var(--muted); padding: 28px 0; }
.empty .act { margin-top: 14px; }
.failed { font: 13px var(--mono); color: var(--bad); padding: 28px 0; }
.failed button { margin-left: 12px; }
.nf { font: 13px var(--mono); color: var(--muted); }
.nf .code404 { font: 12.5px var(--mono); color: var(--faint); margin-bottom: 8px; }
.stub { font: 12.5px/1.7 var(--mono); color: var(--faint); border-top: 1px solid var(--line); padding-top: 16px; margin-top: 40px; }

/* ---------- toast ----------
   One quiet line at the bottom, used for errors and "undo". No shadow, no animation, no colours
   except --bad for errors. Pages prefer inline states; the toast is for things with no place on screen. */
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 20; max-width: min(560px, calc(100vw - 32px));
  background: var(--soft); border: 1px solid var(--line); color: var(--fg); font: 12.5px/1.5 var(--mono); padding: 10px 14px;
  display: flex; gap: 16px; align-items: baseline; }
.toast.error .tx { color: var(--bad); }
.toast button { padding: 0; border: 0; background: none; color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.toast button:hover { color: var(--fg); background: none; }

/* ---------- mobile ---------- */
@media (max-width: 900px) {
  :root { --page-top: 24px; --page-x: 16px; }
  .shell { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; background: none; }
  .side { min-width: 0; }   /* five menu items (Подключение + 4) scroll inside the nav instead of widening the page */
  .side { position: static; height: auto; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--line); padding: 14px 16px 0; }
  .brand { padding: 0; min-height: var(--tap); }
  .switch { order: 4; width: 100%; padding: 0; margin: 4px 0 0; }
  .switch .sw-cur { min-height: var(--tap); padding: 8px 0; }
  .switch .sw-list a { min-height: var(--tap); display: flex; align-items: center; }
  .side .bottom { margin: 0; padding: 0; order: 2; flex-direction: row; align-items: center; gap: 16px; }
  .side .lang { display: none; }            /* phones: brand and «Выйти» only (prototype) */
  .out, .lang button { min-height: var(--tap); }
  .lang button { min-width: 32px; display: inline-flex; align-items: center; justify-content: center; }
  .side .nav { display: flex; width: 100%; order: 5; margin: 6px 0 0 -10px; overflow-x: auto; padding-block: 2px; }
  .nav a { white-space: nowrap; padding: 9px 10px; min-height: var(--tap); }
  .nav a:focus-visible { outline-offset: -2px; }
  .nav a.on { background: none; box-shadow: inset 0 -1px 0 var(--fg); }
  .nav .sep { display: none; }
  .main { padding: var(--page-top) var(--page-x) 60px; }
  .head { margin-bottom: 24px; }
  .sect { margin-top: 32px; }
  button, .btn { min-height: var(--tap); }
  input, textarea { min-height: var(--tap); }
  .link, .links a, .links button { min-height: var(--tap); display: inline-flex; align-items: center; }
  /* stand-alone links (not inside a sentence) get a 36px tap target (DESIGN_V2 rule 12) */
  .todo a, .foot a, .foot .link, .nf a, .foot-link a, .jr-more a, .note a, .empty .act a { display: inline-flex; align-items: center; min-height: var(--tap); }
  details > summary { min-height: var(--tap); display: flex; align-items: center; }
  .it > summary { display: grid; }
  .msg { grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px; }
  .msg .n { grid-column: 1; grid-row: 1; }
  .msg .t { grid-column: 2; grid-row: 1; font-size: 12px; text-align: right; }
  .msg .x { grid-column: 1 / 3; }
  .msg .m { grid-column: 1 / 3; white-space: normal; }
  .it > summary { grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px; padding: 12px 0; }
  .it .n { grid-column: 1; grid-row: 1; }
  .it .t { grid-column: 2; grid-row: 1; font-size: 12px; text-align: right; }
  .it .x { grid-column: 1 / 3; }
  .it .m { grid-column: 1 / 3; text-align: left; white-space: normal; }
  .ctx { padding: 4px 12px 16px; }
  .ctx .meta .sp { display: none; }
  .ctx .meta button { padding: 9px 14px; }
  .rule { grid-template-columns: minmax(0, 1fr) 168px; gap: 12px; }
  .rule select { font-size: 12.5px; padding-left: 9px; padding-right: 22px; background-position: right 8px center; min-height: var(--tap); }
  .big { gap: 32px; }
  .big .v { font-size: 24px; }
  .hide-m { display: none; }
  .skel .r { grid-template-columns: minmax(0, 1fr) 40px; }
  .skel .r i:nth-child(1) { display: none; }
}
/* iOS Safari zooms into any field with a font below 16px and leaves the page wider than the screen.
   Never disable zoom through the viewport; make touch-screen fields 16px instead. */
@media (max-width: 900px) and (pointer: coarse) {
  input, select, textarea, .rule select, .probe textarea { font-size: 16px; }
}
.nf h1 { color: var(--fg); }
