/* Proxier's own layout and components. Colours and sizes come from tokens.css;
   the markup carries classes only (the CSP forbids style attributes). */

/* Utilities */
.flex1 { flex: 1; min-width: 0; }
.subtle { color: var(--subtle); }
.muted { color: var(--muted); }
.love { color: var(--love); }
.gold { color: var(--gold); }
.bold { font-weight: 600; }
.sm { font-size: var(--fs-sm); line-height: 16px; }
.nowrap { white-space: nowrap; }
.hidden { display: none !important; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.k { color: var(--text); font-weight: 600; }
/* a line of facts ("Netherlands · 10.0.0.1 · nl-1.example.com") wraps between them, never inside one */
.facts > span { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* Shell */
.app { min-height: 100vh; display: flex; flex-direction: column; background: var(--black); }
.hdr { position: relative; z-index: 4; height: var(--header-h); flex: none; display: flex; align-items: stretch; border-bottom: 1px solid var(--overlay); }
.hdr-logo { width: var(--sidebar-w); flex: none; display: flex; align-items: center; gap: 8px; padding: 0 16px; border-right: 1px solid var(--overlay); font-weight: 700; text-decoration: none; }
.logo-mark { width: 10px; height: 10px; background: var(--text); flex: none; }
/* the search and a long name share what is left: neither squeezes the other to nothing */
.hdr-search { flex: 1 1 160px; min-width: 0; display: flex; align-items: center; gap: 10px; padding: 0 16px; border: 0; color: var(--muted); text-align: left; cursor: text; }
.hdr-search .slash { color: var(--subtle); font-weight: 600; }
.hdr-glass { display: none; flex: none; }
.hdr-cell { display: flex; align-items: center; gap: 8px; padding: 0 16px; border-left: 1px solid var(--overlay); }
.hdr-cell.quiet { color: var(--subtle); }
.hdr-menu { display: none; flex: none; align-items: center; justify-content: center; width: 48px; padding: 0; border-right: 1px solid var(--overlay); }
.hdr-warn { color: var(--gold); }
/* the admin's name, plain text, then Sign out, a square icon cell at the header's end;
   a username may be a long email: its cell gives way, so Sign out is never pushed off the screen */
.hdr-admin { min-width: 0; }
.admin-name, .hdr-ph { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-name { max-width: 32ch; color: var(--subtle); }
.hdr-out { flex: none; display: flex; }
.hdr-out .hdr-out-btn { width: 48px; display: flex; align-items: center; justify-content: center; padding: 0; border-left: 1px solid var(--overlay); cursor: pointer; }
.body { flex: 1; display: flex; align-items: stretch; min-height: 0; }
.side { width: var(--sidebar-w); flex: none; border-right: 1px solid var(--overlay); padding: 4px 0 24px; }
.side-group { padding: 16px 16px 6px; font-size: var(--fs-label); line-height: 16px; letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); }
.side a { display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 16px; text-decoration: none; color: var(--subtle); }
.side a:hover { background: var(--base); color: var(--text); }
.side a[aria-current="page"] { background: var(--overlay); color: var(--text); }
.side a .mark { width: 8px; flex: none; }
.side a .note { font-size: var(--fs-sm); color: var(--muted); }
/* the running build (APP_VERSION) under the links */
.side-ver { padding: 16px 16px 0; font-size: var(--fs-sm); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.titleblock { padding: 20px 16px 16px; border-bottom: 1px solid var(--overlay); display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: flex-start; }
.titleblock h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: 600; }
.titleblock .status { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 24px; margin-top: 8px; color: var(--subtle); width: 100%; }
/* the title keeps room for itself; many actions (the editor's) wrap below it */
.titleblock .actions { margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.titleblock .head { flex: 1 1 320px; min-width: 0; }
.area { border-bottom: 1px solid var(--overlay); padding-bottom: 8px; }
.area .pc-title .note { font-size: var(--fs-sm); line-height: 16px; color: var(--subtle); }
/* a title band's buttons stay at its right end, also when a long title and note wrap them onto a line of their own */
.pc-title > .pc-btn:last-child { margin-left: auto; }
.area-body { padding: 12px 16px; }
/* an area body of parts under each other (a URL and its buttons, a note, Show QR and the code, a button row): the gap is
   their only spacing, the body's 12 px, so text, a button row and the note under it never touch */
.area-body.stacked { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.area-body.stacked > * { margin: 0; }
/* a note under a page's table or area: the page column has no padding of its own */
.foot { padding: 12px 16px; font-size: var(--fs-sm); line-height: 16px; color: var(--subtle); }
.empty { padding: 20px 16px; color: var(--subtle); display: flex; flex-direction: column; gap: 4px; }
.empty .what { color: var(--text); }

/* Rows */
.row { position: relative; display: grid; gap: 16px; align-items: center; padding: 6px 16px; }
.row .caret { position: absolute; left: 4px; top: 6px; color: var(--text); visibility: hidden; }
.pc-cur .caret { visibility: visible; }
.row.sess, .row.pk { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr) auto; }
/* Removing a passkey asks for the password in place: the row's button opens a small form beside it and closes it again */
.pw-confirm { justify-self: end; }
.pw-confirm > summary { list-style: none; }
.pw-confirm > summary::-webkit-details-marker { display: none; }
.pw-confirm[open] { grid-column: 1 / -1; justify-self: stretch; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pw-confirm[open] > summary { order: 1; }
.pw-confirm .if-open, .pw-confirm[open] .if-closed { display: none; }
.pw-confirm[open] .if-open { display: inline; }
.pw-confirm form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.pw-confirm form .lbl { margin: 0; }
.pw-confirm form .pc-inp { width: 220px; }
.code-inp { font-variant-numeric: tabular-nums; letter-spacing: 0.2em; }
.totp-secret { word-break: break-all; color: var(--text); }
.row.int { grid-template-columns: 160px minmax(0, 1fr); text-decoration: none; color: inherit; }
.int-state { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; }
.row.chat { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; margin-top: 8px; }
.row.rule { grid-template-columns: 46px minmax(0, 1.1fr) minmax(0, 1.6fr) 140px; gap: 14px; }
.row.rule > span, .row.host > span { min-width: 0; }
.row.rule .pc-sw { margin-left: 6px; }
.row.failed-note { grid-template-columns: 110px minmax(0, 1fr) auto auto; }
.rules { border-bottom: 1px solid var(--overlay); padding-bottom: 6px; }
.rules > summary { list-style: none; cursor: pointer; }
.rules > summary::-webkit-details-marker { display: none; }
.rules > summary::after { content: "▾"; margin-left: auto; color: var(--subtle); }
.rules:not([open]) > summary::after { content: "▸"; }
.rules:not([open]) { padding-bottom: 0; }
.rules-foot { padding: 12px 16px; }
.row.attr { grid-template-columns: 160px minmax(0, 1fr); }
.row.host { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1.6fr) minmax(0, .9fr) minmax(0, .9fr) auto; }
.row.bk { grid-template-columns: minmax(0, 1.4fr) minmax(0, .6fr) minmax(0, 1fr); }
.row.mem, .colhead.mem { grid-template-columns: minmax(140px, 1.4fr) minmax(110px, 1fr) minmax(170px, 1.4fr) minmax(110px, .8fr); }
.access { border: 0; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.access .presets { display: flex; flex-wrap: wrap; gap: 8px; }
.access .access-row { display: grid; grid-template-columns: minmax(140px, 180px) minmax(140px, 1fr); gap: 4px 12px; align-items: center; }
.access .access-row label { margin: 0; }
.access .access-row .help { grid-column: 2; margin-top: 0; }
.colhead { display: grid; gap: 16px; padding: 12px 16px 6px; font-size: var(--fs-label); line-height: 16px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
/* A table (.tbl: column heads and rows) never squeezes a column below its minimum:
   when the page is narrower (zoomed in, a small window) it scrolls sideways in its
   own box. A cell keeps to one line and ends in "…"; the title attribute holds
   the whole value. Column minimums are in each table's grid-template-columns. */
.tbl { overflow-x: auto; overflow-y: hidden; }
.tbl .row, .tbl .colhead { min-width: min-content; }
.colhead > *, .tbl .row > :not(.caret, .handle, .actions, .acts, .meters, .state, .wrap, .err, form, input), .tbl .row > .col > :not(.wrap, .err) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* a message (an error, a reason) wraps between words instead */
.tbl .row .wrap { min-width: 0; white-space: normal; overflow-wrap: break-word; }
/* a long one (a version's notes) stops after three lines with "…"; its title holds the rest */
.tbl .row .clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.tbl .stat { max-width: 100%; }
.tbl .stat > :last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.cut { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .actions { display: flex; justify-content: flex-end; gap: 8px; }
.fp-cell code, .host-change code, .fp-line .subtle { word-break: break-all; }
.fp-line { min-width: 0; }
.host-change { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.keybox { display: block; padding: 8px 10px; background: var(--base); border: 1px solid var(--hl-med); color: var(--text); word-break: break-all; user-select: all; }
textarea.pc-ta { height: auto; min-height: 112px; padding: 8px 10px; width: 100%; resize: vertical; line-height: 1.4; }

/* Key line */
.keyline-in { flex: 1; min-width: 0; display: flex; align-items: center; gap: 20px; padding: 0 16px; overflow: hidden; color: var(--subtle); }
.keyline-in .msg { color: var(--text); }
.keyline-global { display: flex; align-items: center; gap: 20px; padding: 0 16px; border-left: 1px solid var(--overlay); color: var(--subtle); }
.keyline-live { display: flex; align-items: center; gap: 8px; padding: 0 16px; border-left: 1px solid var(--overlay); color: var(--subtle); }
/* g's which-key strip lies over the page on the key line's top border, out of
   the flow (in it, it lengthened a short page and covered the line), and a
   narrow window wraps it upwards */
.whichkey { position: absolute; left: 0; right: 0; bottom: calc(100% + 1px); display: flex; flex-wrap: wrap; background: var(--black); border-top: 1px solid var(--overlay); }
.whichkey a, .whichkey .wk-top { display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 16px; border-right: 1px solid var(--overlay); color: var(--subtle); text-decoration: none; }

/* Alerts and bands */
.alert { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border: 1px solid var(--hl-med); background: var(--base); color: var(--subtle); }
.alert.love { background: var(--love-bg); border-color: var(--love-border); color: var(--love); }
.alert.gold { background: var(--gold-bg); border-color: var(--gold-border); color: var(--gold); }
.alert.iris { background: var(--iris-bg); border-color: var(--iris-border); color: var(--iris); }
.alert.pine { background: var(--pine-bg); border-color: var(--pine-border); color: var(--foam); }
.band { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; padding: 12px 16px; border-bottom: 1px solid; }
.band.love { background: var(--love-bg); border-color: var(--love-border); }
.band.gold { background: var(--gold-bg); border-color: var(--gold-border); }
.band.iris { background: var(--iris-bg); border-color: var(--iris-border); }
.band.pine { background: var(--pine-bg); border-color: var(--pine-border); }

/* Forms */
.form { display: flex; flex-direction: column; gap: 16px; padding: 16px; max-width: 560px; }
.field label, .lbl { display: block; font-size: var(--fs-sm); color: var(--subtle); margin-bottom: 6px; }
.field .pc-inp, .field select.pc-inp { width: 100%; }
.field .help { margin-top: 4px; font-size: var(--fs-sm); color: var(--muted); }
.field .err { margin-top: 4px; font-size: var(--fs-sm); color: var(--love); }
.field .changed { color: var(--rose); }
.field label.check { display: flex; align-items: center; gap: 10px; margin: 0; padding: 6px 0; color: var(--text); font-size: var(--fs); cursor: pointer; }
.field .check input { accent-color: var(--rose); width: 16px; height: 16px; margin: 0; }
.field.row-h { display: flex; align-items: center; gap: 12px; }
.pc-inp.tall { height: 36px; }
.pc-inp[readonly] { color: var(--subtle); }
select.pc-inp { appearance: none; background-image: none; }
.ro { display: flex; flex-direction: column; gap: 2px; }
.ro .v { color: var(--text); word-break: break-all; }
.form-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* Settings */
.settings { flex: 1; display: flex; align-items: stretch; }
.settings-nav { width: 200px; flex: none; border-right: 1px solid var(--overlay); padding: 8px 0; }
.settings-nav a { display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 16px; color: var(--subtle); text-decoration: none; }
.settings-nav a:hover { background: var(--base); }
.settings-nav a[aria-current="page"] { background: var(--overlay); color: var(--text); }
.settings-nav .mark { width: 8px; }
/* a strip of tabs wider than the window fades at the end that has more (proxier.js
   sets the classes), so the tabs off the screen are seen to be there */
.settings-nav.more-end { mask-image: linear-gradient(to right, #000 calc(100% - 48px), transparent); }
.settings-nav.more-start { mask-image: linear-gradient(to left, #000 calc(100% - 48px), transparent); }
.settings-nav.more-start.more-end { mask-image: linear-gradient(to right, transparent, #000 48px, #000 calc(100% - 48px), transparent); }
.settings-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.set-head { padding: 14px 16px; border-bottom: 1px solid var(--overlay); }
.set-head h2 { font-size: var(--fs-dialog); line-height: 22px; font-weight: 600; }
.set-head p { color: var(--subtle); }
.set-section { border-bottom: 1px solid var(--overlay); padding-bottom: 12px; }
.set-section .form { padding-bottom: 4px; }

/* Pop-ups */
.pc-dialog { padding: 0; color: var(--text); margin: 72px auto auto; }
dialog.pc-dialog::backdrop { background: rgba(0, 0, 0, .7); }
.dlg-title { display: flex; align-items: stretch; border-bottom: 1px solid var(--overlay); }
.dlg-title h2 { flex: 1; padding: 10px 16px; font-size: var(--fs-dialog); line-height: 22px; font-weight: 600; }
.dlg-body { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.dlg-foot { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--overlay); }
.dlg-foot .hint { margin-left: auto; font-size: var(--fs-sm); color: var(--subtle); }
.dlg-list { margin: 0; padding-left: 18px; color: var(--subtle); }
.pal { position: fixed; inset: 0; z-index: 12; display: flex; justify-content: center; align-items: flex-start; padding: 72px 16px 16px; background: rgba(0, 0, 0, .6); }
.pal-box { width: min(680px, 100%); background: var(--black); border: 1px solid var(--hl-high); }
.pal-in { display: flex; align-items: center; gap: 10px; height: 52px; padding: 0 16px; background: var(--base); border-bottom: 1px solid var(--overlay); }
.pal-in .prompt { color: var(--subtle); font-weight: 600; font-size: var(--fs-dialog); }
.pal-in input { flex: 1; min-width: 0; height: 50px; padding: 0; background: transparent; border: 0; outline: 0; font-size: var(--fs-dialog); }
.pal-list { max-height: 440px; overflow: auto; padding: 4px 0 8px; }
.pal-group { padding: 10px 16px 4px; font-size: var(--fs-label); line-height: 16px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); }
.pal-row { position: relative; display: flex; align-items: baseline; gap: 12px; padding: 6px 16px; text-decoration: none; cursor: pointer; }
.pal-row .caret { position: absolute; left: 4px; top: 6px; visibility: hidden; }
.pal-row.pc-cur .caret { visibility: visible; }
.pal-row .meta { font-size: var(--fs-sm); color: var(--subtle); }
/* a phone or tablet has no keyboard to press these keys on: its touch screen is its
   only pointer (a laptop's touch screen keeps them, as its trackpad can hover) */
@media (hover: none) and (pointer: coarse) {
  .pc-keys-only { display: none !important; }
  /* Safari on an iPhone or iPad zooms into a field whose text is under 16 px as it
     takes focus, and stays zoomed: the setup page lost its right edge */
  input, select, textarea { font-size: 16px !important; }
}
.pal-foot { display: flex; flex-wrap: wrap; gap: 6px 20px; padding: 8px 16px; border-top: 1px solid var(--overlay); font-size: var(--fs-sm); color: var(--subtle); }
.keys-sheet { width: min(820px, 100%); margin-top: 8px; background: var(--black); border: 1px solid var(--hl-high); }
.keys-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: 1px; background: var(--overlay); }
.keys-grid > div { background: var(--black); padding: 12px 16px 14px; }
.keys-grid h3 { font-size: var(--fs-label); line-height: 16px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); margin-bottom: 6px; }
.keys-grid .kk { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 12px; padding: 3px 0; }
.keys-note { padding: 10px 16px; border-top: 1px solid var(--overlay); font-size: var(--fs-sm); color: var(--subtle); }

/* Sign-in */
.signin { flex: 1; display: flex; justify-content: center; padding: 120px 16px 48px; }
.signin form { width: min(380px, 100%); display: flex; flex-direction: column; gap: 16px; }
.signin h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: 600; }
.signin .help { font-size: var(--fs-sm); color: var(--muted); }
.signin .help code { color: var(--subtle); font-family: inherit; }
.signin .pc-inp { height: 36px; width: 100%; }
.signin .pc-pri { height: 36px; }
.signin-bar { height: var(--header-h); flex: none; display: flex; align-items: stretch; border-bottom: 1px solid var(--overlay); }
.signin-bar .hdr-logo { border-right: 0; width: auto; }

/* Lists, filters, jobs, activity */
.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 16px; border-bottom: 1px solid var(--overlay); }
.filter-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.sel { height: 26px; padding: 0 8px; font-size: var(--fs-sm); }
.pager { padding: 10px 16px; color: var(--subtle); display: block; }
.col { display: flex; flex-direction: column; min-width: 0; }
.jobrow { grid-template-columns: 60px minmax(160px, 1.1fr) minmax(120px, 1fr) minmax(150px, 1.5fr) 110px 90px; text-decoration: none; }
/* a long name in the crumbs ends in "…"; the crumbs wrap between items, never inside one */
.crumbs { display: flex; flex-wrap: wrap; gap: 0 8px; font-size: var(--fs-sm); color: var(--subtle); }
.crumbs > * { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crumbs a { color: var(--subtle); }
.jobtitle { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin-top: 6px; }
.jobcols { flex: 1; display: grid; grid-template-columns: 340px minmax(0, 1fr); }
.jobside { border-right: 1px solid var(--overlay); }
.jobside section { border-bottom: 1px solid var(--overlay); padding-bottom: 10px; }
.side-body { padding: 8px 16px 0; display: flex; flex-direction: column; gap: 4px; }
.steps { list-style: none; margin: 0; padding: 8px 0 0; }
.step { display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 5px 16px; }
.step .mk { display: flex; justify-content: center; }
.step[data-state="pending"] .nm { color: var(--muted); }
.payload { display: grid; grid-template-columns: 100px minmax(0, 1fr); gap: 4px 12px; padding: 10px 16px 0; margin: 0; }
.payload dd { margin: 0; word-break: break-word; }
/* The log box scrolls on its own, so what follows it is a short page scroll
   away however long the log is: at most 60 % of the window (240 px at least).
   Expanded, its column is as tall as the window above the key line and the
   box takes what the head (and "Show earlier lines") leave. Scrolling past
   its top or end goes on to the page (no overscroll-behavior: contain), so a
   wheel over the log never traps the page. The well colour is on the column
   too: beside a taller side panel the box ends and the well goes on below. */
.jobmain { display: flex; flex-direction: column; min-width: 0; background: var(--base); }
.jobmain > .pc-title { background: var(--black); }
.log { flex: 1; max-height: max(240px, 60vh); overflow-y: auto; background: var(--base); font-size: var(--fs-sm); line-height: 19px; padding: 8px 0; }
.jobmain.log-full { height: calc(100vh - var(--keyline-h)); }
.jobmain.log-full .log { flex: 1 1 0; min-height: 0; max-height: none; }
.log:focus-visible { outline-offset: -1px; }
.log-follow, .tool-check { display: flex; align-items: center; gap: 8px; font-size: var(--fs-sm); cursor: pointer; }
.log-follow input, .tool-check input { accent-color: var(--text); margin: 0; }
.ll { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 14px; padding: 0 16px; }
.ll .tx { white-space: pre-wrap; word-break: break-word; }
.ll-step { background: var(--overlay); font-weight: 600; }
.ll-error { background: var(--love-bg); color: var(--love); }
.ll-warn { color: var(--gold); }
.ll-debug { color: var(--muted); }
.ll-marker { color: var(--subtle); font-style: italic; }
/* the actor column is as wide as the page's longest actor, up to 260 px (a fixed 110 px let a member's
   email run over the sentence); rows share it (subgrid), a longer one ends in "…" with its title */
.actfeed { display: grid; grid-template-columns: 72px fit-content(260px) minmax(0, 1fr); }
.actfeed > * { grid-column: 1 / -1; }
.actrow { grid-template-columns: subgrid; }
.actrow .actor { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dayhead { padding: 14px 16px 4px; font-size: var(--fs-label); letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); }
.stat { display: inline-flex; align-items: center; gap: 7px; }
@media (max-width: 760px) {
  .row.chat, .row.failed-note, .row.int { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  /* a rule is the switch beside its name, description and default, not four rows */
  .row.rule { grid-template-columns: 48px minmax(0, 1fr); gap: 2px 8px; padding: 10px 16px 10px 10px; }
  .row.rule .pc-sw { grid-row: 1 / span 3; align-self: start; margin-top: 2px; }
  .row.rule > span:not(.caret) { grid-column: 2; }
  .row.rule > .subtle { font-size: var(--fs-sm); line-height: 18px; }
  .colhead.jobrow { display: none; }
  .jobrow { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .jobcols { grid-template-columns: minmax(0, 1fr); }
  .jobside { border-right: 0; }
  .jobmain.log-full { height: 100vh; } /* no key line on a phone */
  .actfeed { display: block; }
  .actrow { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* Error page */
.errpage { flex: 1; display: flex; flex-direction: column; gap: 8px; padding: 96px 16px; max-width: 560px; margin: 0 auto; width: 100%; }
.errpage h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: 600; }

@media (max-width: 760px) {
  :root { --header-h: 56px; }
  /* 16 px sides left "admin" 3 px short on the phone at 360 px */
  .hdr-logo { width: auto; border-right: 0; padding: 0 12px; }
  /* a field 60 px wide showed "/ S…": on a phone the search is a 48 px button with a
     magnifier, at the right next to the name, and the name has the rest of the row */
  .hdr-search { flex: 0 0 48px; margin-left: auto; justify-content: center; padding: 0; border-left: 1px solid var(--overlay); }
  .hdr-search .slash, .hdr-search .hdr-ph { display: none; }
  .hdr-search .hdr-glass { display: block; }
  .hdr-cell { padding: 0 12px; }
  .admin-name { max-width: none; }
  .settings { flex-direction: column; }
  .settings-nav { width: auto; border-right: 0; border-bottom: 1px solid var(--overlay); display: flex; overflow-x: auto; padding: 0; }
  .settings-nav a { flex: none; height: 44px; }
  .form { max-width: none; }
  .row.sess, .row.pk, .row.host, .row.bk { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .access .access-row { grid-template-columns: minmax(0, 1fr); }
  .access .access-row .help { grid-column: 1; }
  .pw-confirm { justify-self: start; }
  .pw-confirm form .pc-inp { width: 100%; }
  .row .actions { justify-content: flex-start; }
  .titleblock .actions { width: 100%; flex-direction: row; flex-wrap: wrap; }
  .titleblock .actions > * { flex: 1 1 auto; }
  .titleblock .actions .pc-btn { width: 100%; }
  /* the template editor's six actions took a screen as full-width rows: two to a row,
     40 px, Publish first across the row, and the server for Preview across the row */
  .titleblock .actions.ed-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .ed-actions .pc-btn { min-height: 40px; }
  .ed-actions > .pc-pri { order: -1; }
  .ed-actions > .pc-pri, .ed-actions > select { grid-column: 1 / -1; }
  /* a filter row's selects start at their own width and share each line they wrap to
     (five sharing one line were 39 px: "Люб"); Apply/Find are as tall as them */
  .filter-form { flex: 1 1 100%; }
  .filter-form .sel { flex: 1 1 auto; min-width: 0; }
  .filter-form .pc-btn, .search-form .pc-btn { min-height: 48px; }
  /* breadcrumbs and the links in a sentence (Activity) keep their line, with a taller tap area */
  .crumbs a { padding: 10px 0; margin: -10px 0; }
  .actrow a.text { padding: 10px 0; }
  .tabs { padding: 0; }
  .tabs a { padding: 12px 14px; }
  .signin { padding-top: 48px; }
  .pc-inp, .signin .pc-inp { min-height: 48px; }
  /* a label longer than the screen ("Add service to <a long name>") wraps inside its button */
  .pc-btn { max-width: 100%; height: auto; padding-top: 6px; padding-bottom: 6px; white-space: normal; text-align: center; }
  .drawer-open .pc-side { display: block !important; position: fixed; z-index: 11; top: var(--header-h); bottom: 0; left: 0; width: min(300px, 86vw); background: var(--black); border-right: 1px solid var(--hl-high); overflow: auto; }
  .drawer-open .side a { height: 44px; }
}

/* Read-only code and diffs (templates: version view, preview, diff) */
.code { background: var(--black); font-size: 12.5px; line-height: 20px; padding: 8px 0 16px; overflow-x: auto; }
.cl { display: grid; grid-template-columns: 54px minmax(0, 1fr); }
.cl .ln { text-align: right; padding-right: 14px; color: var(--muted); text-decoration: none; user-select: none; }
.cl .tx { white-space: pre; padding-right: 16px; }
.cl:target, .cl.has-err { background: var(--overlay); }
.cl.has-err .ln { color: var(--text); font-weight: 600; }
.cl-note { padding: 0 16px 6px 54px; white-space: normal; }
.cl-note.error { color: var(--love); }
.cl-note.warning { color: var(--gold); }
.hl .k, .hl .kc, .hl .kd, .hl .kn, .hl .kp, .hl .kr, .hl .kt { color: var(--iris); }
.hl .nt, .hl .na { color: var(--foam); font-style: italic; }
.hl .nb, .hl .nf, .hl .nv, .hl .nc, .hl .no { color: var(--rose); }
.hl .s, .hl .s1, .hl .s2, .hl .sb, .hl .sd, .hl .se, .hl .si, .hl .sx, .hl .sh { color: var(--gold); }
.hl .m, .hl .mi, .hl .mf, .hl .mh, .hl .mo, .hl .il { color: var(--rose); }
.hl .p, .hl .o, .hl .ow { color: var(--subtle); }
.hl .c, .hl .c1, .hl .ch, .hl .cm, .hl .cp, .hl .cpf, .hl .cs { color: var(--subtle); font-style: italic; }
/* a RouterOS script's # @annotations (only the routeros lexer emits .cs) */
.hl .cs { color: var(--iris); }
.hl .err { color: var(--iris); text-decoration: underline wavy var(--love); text-underline-offset: 4px; }
.diff { font-size: 12.5px; line-height: 20px; }
.diff-file { border-bottom: 1px solid var(--overlay); padding-bottom: 8px; }
.diff-head { display: flex; align-items: center; gap: 10px; padding: 10px 16px; }
.diff-chg { width: 10px; font-weight: 600; text-align: center; }
.diff-chg.added { color: var(--foam); }
.diff-chg.removed { color: var(--love); }
.diff-chg.changed { color: var(--rose); }
.diff-note { padding: 0 16px; }
.diff-hunk { padding: 2px 16px 2px 16px; color: var(--muted); background: var(--base); }
.dl { display: grid; grid-template-columns: 48px 48px 20px minmax(0, 1fr); }
.dl.half { grid-template-columns: 48px 20px minmax(0, 1fr); }
.dl .ln { text-align: right; padding-right: 10px; color: var(--muted); user-select: none; }
.dl .mk { text-align: center; user-select: none; }
.dl .tx { white-space: pre-wrap; word-break: break-word; padding-right: 12px; }
.dl.add { background: var(--pine-bg); }
.dl.add .mk { color: var(--foam); font-weight: 600; }
.dl.del { background: var(--love-bg); }
.dl.del .mk { color: var(--love); font-weight: 600; }
.dl.note { color: var(--muted); font-style: italic; }
.dl.empty { background: var(--base); }
.drow { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1px; background: var(--overlay); }
.drow .dl { background: var(--black); }
.drow .dl.add { background: var(--pine-bg); }
.drow .dl.del { background: var(--love-bg); }
.drow .dl.empty { background: var(--base); }
@media (max-width: 760px) {
  .diff.split .drow { grid-template-columns: minmax(0, 1fr); }
}

/* Templates */
.row.tpl, .colhead.tpl { grid-template-columns: minmax(200px, 1.4fr) 110px 90px minmax(140px, 1fr) minmax(140px, 1.2fr); align-items: start; }
a.row.tpl { text-decoration: none; color: inherit; }
.row.ver, .colhead.ver { grid-template-columns: 110px 120px minmax(190px, 1fr) minmax(120px, 170px); }
.row.ver .actions { grid-column: 2 / -1; flex-wrap: wrap; justify-content: flex-start; }
.row.ver .normal { font-weight: 400; }
.tgrid { display: grid; grid-template-columns: minmax(0, 1fr) 420px; gap: 1px; background: var(--overlay); border-bottom: 1px solid var(--overlay); }
.tgrid > .area { background: var(--black); border-bottom: 0; }
.kv { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 6px 12px; margin: 0 0 12px; }
.kv dt { color: var(--subtle); }
.kv dd { margin: 0; }
.btns { display: flex; flex-wrap: wrap; gap: 8px; }
.notes { margin-top: 6px; white-space: pre-wrap; }
.warnlist { list-style: none; margin: 0; padding: 8px 16px 12px; display: flex; flex-direction: column; gap: 4px; border-bottom: 1px solid var(--overlay); }
.warnlist li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.vcols { flex: 1; display: grid; grid-template-columns: 230px minmax(0, 1fr); }
.vtree { border-right: 1px solid var(--overlay); }
.vfile { min-width: 0; }
.ed-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 28px; padding: 0 16px; text-decoration: none; color: var(--subtle); overflow: hidden; }
.ed-row[aria-current="true"], .ed-row[aria-current="page"] { background: var(--overlay); color: var(--text); }
.ed-dir { color: var(--foam); font-weight: 600; }
.ed-row.d1 { padding-left: 30px; } .ed-row.d2 { padding-left: 44px; } .ed-row.d3 { padding-left: 58px; } .ed-row.d4 { padding-left: 72px; }
.ed-row.d5 { padding-left: 86px; } .ed-row.d6 { padding-left: 100px; } .ed-row.d7 { padding-left: 114px; } .ed-row.d8 { padding-left: 128px; }
.ed-row .ed-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ed-row.has-err { color: var(--love); }
.ed-row.has-warn { color: var(--gold); }
.ed-row .ed-count { color: inherit; }
.pub { display: flex; flex-direction: column; gap: 18px; padding: 16px; max-width: 680px; }
.pub .alert { flex-wrap: wrap; }
.pub-list { padding: 0; border: 0; }
.pub-happens { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.fs { border: 1px solid var(--overlay); padding: 12px 16px 16px; margin: 0; display: flex; flex-direction: column; gap: 12px; }
.fs legend { padding: 0 6px; font-size: var(--fs-label); letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); }
.radio { display: flex; align-items: center; gap: 8px; }
.radio input { accent-color: var(--text); }
.form input[type="file"].pc-inp { height: auto; padding: 6px 10px; width: 100%; }

/* Template editor */
.ed-msg:empty { display: none; }
/* The editor's three columns are a grid, so a narrow window never wraps one of them
   onto a line of its own (the results stuck under the code, a third as wide). */
.ed { flex: 1; display: grid; grid-template-columns: 230px minmax(0, 1fr) 330px; }
.ed-left { min-width: 0; min-height: 0; border-right: 1px solid var(--overlay); display: flex; flex-direction: column; }
.ed-head { display: flex; align-items: stretch; min-height: var(--title-band-h); border-bottom: 1px solid var(--overlay); }
.ed-head .pc-label { display: flex; align-items: center; padding: 0 16px; }
.ed-add { width: 36px; height: 36px; flex: none; padding: 0; border-left: 1px solid var(--overlay); font-size: 16px; color: var(--subtle); }
.ed-files { flex: 1; min-height: 0; overflow-y: auto; padding: 6px 0; }
.ed-tools { display: flex; gap: 8px; padding: 10px 16px; border-top: 1px solid var(--overlay); }
.ed-tools .pc-btn { cursor: pointer; }
.ed-main { min-width: 0; min-height: 0; display: flex; flex-direction: column; background: var(--black); }
.ed-file { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; min-height: var(--title-band-h); padding: 4px 16px; border-bottom: 1px solid var(--overlay); font-size: var(--fs-sm); }
.ed-host { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; min-width: 0; }
.ed-status { display: flex; align-items: center; gap: 14px; height: 24px; padding: 0 12px; border-top: 1px solid var(--overlay); font-size: var(--fs-sm); color: var(--subtle); }
.ed-side { min-width: 0; border-left: 1px solid var(--overlay); display: flex; flex-direction: column; overflow: auto; }
/* Validate focuses the results (proxier.js, data-reveal): the ring sits inside, on the panel's own edges */
.ed-side:focus-visible { outline-offset: -1px; }
.ed-side-head { display: flex; align-items: center; min-height: var(--title-band-h); padding: 0 16px; border-bottom: 1px solid var(--overlay); }
.ed-hint { padding: 12px 16px; }
.ed-counts { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 8px 16px; border-bottom: 1px solid var(--overlay); font-size: var(--fs-sm); }
.ed-report { padding: 6px 0; }
.ed-find { display: grid; grid-template-columns: 14px minmax(0, 1fr); gap: 8px; padding: 6px 16px; align-items: baseline; }
.ed-find a { word-break: break-all; }
.ed-foot { padding: 10px 16px; border-top: 1px solid var(--overlay); display: flex; flex-direction: column; gap: 6px; }
.pv-file { border-top: 1px solid var(--overlay); }
.pv-file .code { max-height: 360px; overflow: auto; }
.ed-sources .ed-src { display: block; width: 100%; min-height: 12em; background: var(--base); color: var(--text); border: 1px solid var(--hl-med); font: inherit; padding: 8px 10px; }
.ed.ed-on .ed-sources { display: none; }
.ed.ed-on .ed-tree .ed-file-row { cursor: pointer; }
.ed:not(.ed-on) .ed-host, .ed:not(.ed-on) .ed-status { display: none; }
/* The editor fills the window under the title (.code-fill, below); its columns scroll on
   their own. Without the script it is a form of text areas and the page scrolls. */
.ed.code-fill { display: grid; flex: 1 1 0; min-height: 480px; grid-template-rows: minmax(0, 1fr); }
.ed.code-fill:not(.ed-on) { flex: 1 0 auto; grid-template-rows: auto; }
.ed:not(.ed-on) .ed-files { overflow: visible; }

/* Code editors: a template's draft, a router script's draft, a Shadowrocket base config.
   The code runs flush from the page's edge (or the file tree) to its side panel, under a
   band holding Wrap lines and Full screen (ui.CodeTools), and CodeMirror is as tall as its
   box (editor.js sets no height). A page whose job is its editor (.code-fill: the template
   editor, New config, Edit base config) fills the window under its title down to the key
   line: the page doesn't scroll, the code scrolls in its box and the side panels on their
   own, and the actions in the title block stay in view; a window too short for 320 px of
   code lets the page scroll. The sidebar takes no part in that height (contain: size), so a
   nav longer than the window scrolls on its own instead of stretching the editor below it. */
.code-host { display: flex; flex-direction: column; min-width: 0; }
.code-host .cm-editor, .ed-host .cm-editor { flex: 1 1 0; min-height: 0; }
.app:has(.code-fill) .side { contain: size; overflow-y: auto; }
.code-fill { flex: 1 0 auto; display: flex; flex-direction: column; min-width: 0; }
.code-frame { flex: 1 1 0; min-height: 360px; display: flex; flex-direction: column; min-width: 0; }
.code-frame > .code-host, .code-frame > textarea { flex: 1 1 0; min-height: 0; }
.code-frame > textarea { width: 100%; resize: none; font-family: inherit; white-space: pre; }
.code-err { padding: 8px 16px; font-size: var(--fs-sm); line-height: 16px; color: var(--love); border-bottom: 1px solid var(--overlay); }
.code-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
/* Full screen (the band's button; esc outside the code leaves it): the header and the
   sidebar go and the editor takes the window under the page's title, whose actions stay.
   On a router script's page the areas after the draft go too, and the draft fills. */
.code-full .hdr, .code-full .side { display: none !important; }
.code-full .rs-area { flex: 1 1 0; min-height: 400px; display: flex; flex-direction: column; padding-bottom: 0; }
.code-full .rs-area ~ :not(dialog) { display: none; }
.code-full .rs-editor { flex: 1 1 0; min-height: 0; grid-template-rows: minmax(0, 1fr); }
.code-full .rs-draft > .code-host { flex: 1 1 0; min-height: 0; }
.code-full .rs-panel { min-height: 0; overflow-y: auto; }
.code-full .rs-panel .stick { position: static; max-height: none; overflow: visible; }
/* The versions table needs 620 px beside the 420 px draft panel, the sidebar and a scrollbar:
   below 1270 px (a 1440 px window zoomed to 125 %) the two stack instead of the
   table scrolling in a squeezed column. */
@media (max-width: 1270px) {
  .tgrid { grid-template-columns: minmax(0, 1fr); }
}
/* Narrower, the editor keeps the files beside the code and puts the results under both,
   at most 40 % of the window: the code takes the rest. */
@media (max-width: 1100px) {
  .ed { grid-template-columns: 230px minmax(0, 1fr); }
  .ed-side { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--overlay); max-height: 40vh; }
  .ed.code-fill { grid-template-rows: minmax(0, 1fr) auto; min-height: 560px; }
}
@media (max-width: 760px) {
  .row.tpl, .row.ver { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  /* one column: the buttons go under the row's facts, not into a column of their own */
  .row.ver .actions { grid-column: 1 / -1; }
  .colhead.tpl, .colhead.ver { display: none; }
  .ed { grid-template-columns: minmax(0, 1fr); }
  /* a phone stacks the files, the code and the results: the page scrolls, the code has a box of its own */
  .ed.code-fill { flex: none; grid-template-rows: auto; min-height: 0; }
  .ed-host { flex: none; height: max(320px, 70vh); }
  .ed-side { max-height: none; }
  .vcols { grid-template-columns: minmax(0, 1fr); }
  .vtree { border-right: 0; border-bottom: 1px solid var(--overlay); }
  .ed-left { border: 0; border-bottom: 1px solid var(--overlay); }
  /* the results keep the divider above them that they have under 1100 px */
  .ed-side { border: 0; border-top: 1px solid var(--overlay); }
}

/* QR codes: dark modules on a light tile, whatever the page's theme */
.qr { display: block; width: 100%; max-width: 280px; height: auto; border: 1px solid var(--hl-high); }
/* Show QR becomes Hide QR where it stands and the code opens under it, so toggling moves nothing above the code */
.qrslot { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.qr-bg { fill: var(--text); }
.qr-fg { fill: var(--black); }

/* Servers: list, new-server form, server page */
.row.srv, .colhead.srv { grid-template-columns: 20px 16px minmax(96px, 1.2fr) minmax(128px, 1.2fr) minmax(110px, .7fr) minmax(120px, 1.6fr) minmax(120px, 1.6fr) 60px 120px 76px 36px; gap: 14px; align-items: center; text-decoration: none; }
.row.srv a.bold { text-decoration: none; color: inherit; }
/* in the grid like the header's empty cell, not over the checkbox */
.row.srv .caret { position: static; }
.row.srv .meters { display: flex; gap: 6px; }
.row.srv .meter { display: inline-flex; flex-direction: column; gap: 2px; min-width: 0; }
.row.srv .meter .bar { width: 36px; }
.bulk { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 16px; border-bottom: 1px solid var(--overlay); }
.bulk .check { white-space: nowrap; }
.srv-cards { display: none; }
.row.srv-brief, .colhead.srv-brief { grid-template-columns: minmax(140px, 1.2fr) minmax(140px, 1fr) minmax(140px, 1fr); gap: 14px; align-items: center; }
.row.srv-card { display: flex; flex-direction: column; align-items: stretch; gap: 4px; padding: 10px 16px; text-decoration: none; color: inherit; }
.row.srv-card > .bold { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.newcols { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 0; }
.newform { max-width: 640px; }
.newform .grp, .newsum .grp { margin: 8px 0 0; font-size: var(--fs-label); line-height: 16px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.newsum { border-left: 1px solid var(--overlay); }
.newsum > .stick { padding: 16px; }
.newsum h2 { margin: 0 0 12px; font-size: var(--fs-label); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); font-weight: 600; }
.inline { display: flex; gap: 8px; align-items: stretch; }
.inline .pc-inp { flex: 1; min-width: 0; }
/* tabs never wrap or squeeze: a strip too wide for the page scrolls sideways */
.tabs { display: flex; gap: 0; border-bottom: 1px solid var(--overlay); padding: 0 16px; overflow-x: auto; }
.tabs a { flex: none; padding: 8px 14px; color: var(--subtle); text-decoration: none; white-space: nowrap; border-bottom: 2px solid transparent; }
.tabs a[aria-current="page"] { color: var(--text); border-bottom-color: var(--rose); }
.area-body { padding: 12px 16px; }
.row.ep { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: 4px 16px; padding: 10px 16px; border-top: 1px solid var(--overlay); }
.row.ep .uri { grid-column: 1 / -1; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.row.ep code { flex: 1 1 280px; min-width: 0; padding: 4px 8px; background: var(--base); border: 1px solid var(--overlay); overflow-wrap: anywhere; }
.row.ep code.masked { color: var(--muted); }
.row.evt { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 12px; padding: 6px 16px; border-top: 1px solid var(--overlay); }
.row.dashsrv, .row.dashfail { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: center; padding: 10px 16px; border-top: 1px solid var(--overlay); text-decoration: none; }
.row.dashsrv:first-child { border-top: 0; }
.warnlist { margin: 8px 0 0; padding-left: 18px; color: var(--gold); }
@media (max-width: 760px) {
  .srv-table, .bulk { display: none; }
  .srv-cards { display: block; }
  .newcols { grid-template-columns: minmax(0, 1fr); }
  .newsum { border-left: 0; border-top: 1px solid var(--overlay); }
  .row.ep { grid-template-columns: minmax(0, 1fr); }
  .row.evt { grid-template-columns: minmax(0, 1fr); gap: 2px; }
}

/* Changing a running server: plan screen, rollouts, Stack tab */
.actions-row { display: flex; flex-wrap: wrap; gap: 8px; }
.plan-sum { padding: 12px 16px; border-bottom: 1px solid var(--overlay); }
.plan-steps { margin: 0; padding: 12px 16px 12px 36px; display: flex; flex-direction: column; gap: 2px; }
.plan-actions { padding: 16px; }
.row.rollout, .colhead.rollout { grid-template-columns: 32px minmax(120px, 1fr) 150px 110px minmax(160px, 1.6fr); align-items: center; }
.row.rollout-plan { grid-template-columns: 32px minmax(0, 1fr) 110px minmax(0, 1.6fr); }
.rollout-params { border-top: 1px solid var(--overlay); max-width: 560px; }
.outdated .row { padding-left: 0; padding-right: 0; display: flex; gap: 16px; }
.stack-cols { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 16px; padding: 0; }
.stack-tree { border-right: 1px solid var(--overlay); padding: 8px 0; }
.stack-tree .row { display: flex; gap: 8px; align-items: center; text-decoration: none; padding: 3px 16px; }
.stack-tree .row.d1 { padding-left: 30px; }
.stack-tree .row.d2 { padding-left: 44px; }
.stack-tree .row.d3 { padding-left: 58px; }
.stack-file { min-width: 0; }
.stack-file-head { display: flex; gap: 12px; align-items: center; padding: 8px 16px 0; }
.row.dep { grid-template-columns: 170px minmax(0, 1fr) minmax(0, 1.3fr) 60px minmax(0, auto); }
.row.dep .dep-error { grid-column: 2 / -1; overflow-wrap: anywhere; }
@media (max-width: 760px) {
  .row.rollout, .row.rollout-plan, .row.dep { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .colhead.rollout { display: none; }
  .stack-cols { grid-template-columns: minmax(0, 1fr); }
  .stack-tree { border-right: 0; border-bottom: 1px solid var(--overlay); }
}

/* Charts: drawn on the server as SVG, coloured by class (no inline style). */
.chart { display: block; width: 100%; height: 120px; }
.chart-bg { fill: var(--base); }
.chart-grid { stroke: var(--overlay); stroke-width: 1; fill: none; }
.chart-line { stroke: var(--text); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-line.chart-b { stroke: var(--subtle); stroke-dasharray: 4 3; }
.spark { display: inline-block; width: 96px; height: 20px; vertical-align: middle; }
.spark .chart-line { stroke-width: 1.5; }
.strip { display: inline-block; width: 144px; height: 12px; vertical-align: middle; }
.strip-ok { fill: var(--pine); }
.strip-fail { fill: var(--love); }
.strip-none { fill: var(--overlay); }
.bar { display: inline-block; width: 64px; height: 6px; vertical-align: middle; }
.bar svg { display: block; width: 100%; height: 100%; }
.bar-bg { fill: var(--overlay); }
.bar-ok .bar-fill { fill: var(--subtle); }
.bar-warn .bar-fill { fill: var(--gold); }
.bar-bad .bar-fill { fill: var(--love); }
.timeline { display: block; width: 100%; height: 14px; }
.tl-bg { fill: var(--overlay); }
.tl-ok { fill: var(--pine); }
.tl-look { fill: var(--gold); }
.tl-blocked { fill: var(--iris); }
.tl-broken { fill: var(--love); }
.tl-unknown { fill: var(--muted); }
.tl-paused { fill: var(--foam); }

/* Health and stats */
.verdict { border-bottom: 1px solid var(--overlay); }
.verdict.v-blocked { background: var(--iris-bg); border-color: var(--iris-border); }
.verdict.v-broken { background: var(--love-bg); border-color: var(--love-border); }
.verdict.v-look { background: var(--gold-bg); border-color: var(--gold-border); }
.verdict-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; padding: 14px 16px; border-bottom: 1px solid var(--overlay); }
.verdict-head h2 { font-size: var(--fs-dialog); line-height: 22px; font-weight: 600; }
.verdict-head .actions { display: flex; flex-wrap: wrap; gap: 8px; }
.verdict-head:last-child { border-bottom: 0; }
.verdict-body { padding: 10px 16px 14px; display: flex; flex-direction: column; gap: 4px; max-width: 960px; }
.row.mx, .colhead.mx { grid-template-columns: minmax(140px, 1.1fr) minmax(130px, 1.1fr) minmax(160px, 1.4fr) 100px 150px; align-items: center; }
.row.mx-sub { padding-left: 32px; }
.mx-group { padding: 10px 16px 4px; font-size: var(--fs-label); letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); border-top: 1px solid var(--overlay); }
.row.chg { grid-template-columns: 200px minmax(0, 240px) minmax(0, 1fr); }
.axis { display: flex; justify-content: space-between; font-size: var(--fs-sm); color: var(--muted); padding: 4px 0 0; }
.chart-box .axis, .chart-box .area-pad { padding-left: 16px; padding-right: 16px; }
.legend { display: flex; flex-wrap: wrap; gap: 8px 24px; padding-top: 10px; }
.legend > span { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.filters + .timeline, .area-body .timeline { margin-top: 8px; }
.now { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px; background: var(--overlay); border-bottom: 1px solid var(--overlay); }
.now-cell { background: var(--black); padding: 10px 16px; }
.now-v { font-size: var(--fs-h1); line-height: 30px; font-weight: 600; }
.area-pad { padding: 4px 16px; }
.charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(440px, 100%), 1fr)); gap: 1px; background: var(--overlay); border-bottom: 1px solid var(--overlay); }
.charts .area { background: var(--black); border-bottom: 0; padding-bottom: 8px; }
.row.ct, .colhead.ct { grid-template-columns: minmax(120px, 1.2fr) 140px 90px minmax(160px, 2fr); align-items: center; }
.pause-opts { border: 0; margin: 12px 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.pause-opts legend { grid-column: 1 / -1; margin-bottom: 4px; }
.pc-opt { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--hl-high); cursor: pointer; }
.pc-opt:has(input:checked) { border-color: var(--text); }
ul.plain { list-style: none; padding: 12px 0 0; margin: 0; display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--overlay); }
.dashhome { display: flex; flex-direction: column; gap: 4px; }
.row.dashcnt { display: flex; flex-wrap: wrap; gap: 8px 24px; }
.row.dashcnt > span { display: inline-flex; align-items: baseline; gap: 6px; }
.row.dashsick { grid-template-columns: 16px minmax(0, 160px) minmax(0, 1fr) 140px; text-decoration: none; color: inherit; }
.row.dashrank { grid-template-columns: minmax(0, 1fr) 120px; text-decoration: none; color: inherit; }
@media (max-width: 760px) {
  .row.mx, .row.chg, .row.ct, .row.dashsick { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .colhead.mx, .colhead.ct { display: none; }
  .row.mx-sub { padding-left: 32px; }
  .pause-opts { grid-template-columns: minmax(0, 1fr); }
}

/* ---- agent hand-off ---- */
.agent-form { max-width: 760px; }
.agent-form .check { display: flex; align-items: center; gap: 10px; padding: 4px 0; cursor: pointer; }
.agent-form .check input { accent-color: var(--rose); width: 16px; height: 16px; margin: 0; }
.agent-scope { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin: 12px 0; }
.agent-prompt { margin: 0; padding: 12px 16px; max-height: 60vh; overflow: auto; white-space: pre-wrap; word-break: break-word; background: var(--base); color: var(--text); font: inherit; font-size: var(--fs); }
/* the prompt, its warning and the copy row are one block: the prompt runs to the warning strip, which spans the page like
   the prompt does, and the row under it has the page's 16 px gutter */
.area.agent-out { padding-bottom: 0; }
.agent-out .alert { padding: 10px 16px; border-width: 1px 0; }
.agent-out .alert p { margin: 0; }
.agent-out .alert b { font-weight: 600; }
.agent-out .form-actions { padding: 14px 16px; }
@media (max-width: 760px) { .agent-scope { grid-template-columns: minmax(0, 1fr); } }

/* Subscriptions: the list, the page's two columns, the sortable servers, the preview */
.row.sub, .colhead.sub { grid-template-columns: minmax(160px, 1.2fr) minmax(180px, 1.6fr) 64px minmax(110px, 1fr) 110px; align-items: start; }
a.row.sub { text-decoration: none; color: inherit; }
.sub-servers { display: flex; flex-wrap: wrap; gap: 4px 12px; }
.subcols { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: start; }
.subcols > .col-l, .subcols > .col-r { min-width: 0; }
.row.member { grid-template-columns: 24px 24px minmax(120px, 1fr) minmax(110px, 1fr) minmax(90px, 1fr) auto; gap: 10px; }
.row.member .handle { cursor: grab; color: var(--muted); user-select: none; white-space: nowrap; overflow: hidden; }
.row.member.dragging { opacity: .5; }
.row.member .acts { display: flex; gap: 4px; }
.row.addsrv { grid-template-columns: 24px minmax(0, 1fr) minmax(0, 1fr); }
.preview-out { margin: 0; padding: 12px 16px; overflow-x: auto; white-space: pre; background: var(--base); color: var(--text); font: inherit; font-size: var(--fs-sm); }
.preview-out .h { color: var(--subtle); }
/* a subscription's preview sits inside the area's padding, its edges those of the format and Reveal above, and wraps rather than
   scrolling sideways: the sideways scrollbar's box ran over the notes under it */
#preview-body .preview-out { margin: 0 16px 4px; white-space: pre-wrap; word-break: break-all; overflow-x: visible; }
.preview-notes { display: flex; flex-direction: column; gap: 4px; }
fieldset.field { border: 0; padding: 0; margin-left: 0; margin-right: 0; min-width: 0; }
fieldset.field legend { padding: 0; font-size: var(--fs-sm); color: var(--subtle); margin-bottom: 6px; }
.inline-fields .check.sm { font-size: var(--fs-sm); color: var(--subtle); }
.inline-fields { display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center; }
.inline-fields .pc-inp.num { width: 72px; }
@media (max-width: 760px) {
  .colhead.sub { display: none; }
  .row.sub { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .subcols { grid-template-columns: minmax(0, 1fr); }
  .row.member { grid-template-columns: 20px 24px minmax(0, 1fr) auto; }
  .row.member .hl, .row.member .out { grid-column: 3 / -1; }
}

/* Links: the list, the link page's columns, the URL field, the fetch log, the actions */
.row.lnk, .colhead.lnk { grid-template-columns: minmax(150px, 1.3fr) minmax(120px, 1fr) 150px minmax(110px, 1.2fr) minmax(120px, 1.4fr) 48px; align-items: center; }
a.row.lnk { text-decoration: none; color: inherit; }
.filter-form .pc-inp.name { height: 26px; font-size: var(--fs-sm); width: 180px; }
.list-foot { padding: 10px 16px; color: var(--subtle); font-size: var(--fs-sm); }
.row.sublink { grid-template-columns: minmax(0, 1.2fr) 110px minmax(0, 1fr); }
/* the buttons wrap together, under the URL with the rows' 12 px when it leaves them no room */
.urlfield { display: flex; flex-wrap: wrap; gap: 12px 8px; align-items: center; }
.url-btns { display: flex; flex-wrap: wrap; gap: 8px; }
/* ui.URLText marks a break after each slash; a part wider than the line (a token on a phone) breaks where it must */
.urlfield code { font-family: inherit; overflow-wrap: anywhere; }
.row.fetch, .colhead.fetch { grid-template-columns: 120px minmax(110px, 1fr) minmax(140px, 1fr) 104px; gap: 12px; align-items: start; font-size: var(--fs-sm); }
/* an action's button column is as wide as its longest button (a fixed 190 px let "Change routing list or policy…" run over
   its description); rows in .act-rows share that column (subgrid), so their descriptions line up */
.row.act { grid-template-columns: minmax(190px, max-content) minmax(0, 1fr); }
.act-rows { display: grid; grid-template-columns: max-content minmax(0, 1fr); }
.act-rows > .row.act { grid-column: 1 / -1; grid-template-columns: subgrid; }
.row.act .pc-btn { justify-self: start; }
.expiry-fields .pc-inp.date { width: 150px; }
.expiry-fields .pc-inp.clock { width: 90px; }
/* a phone's 15 px type left the time as "--:-" */
@media (max-width: 760px) { .expiry-fields .pc-inp.clock { width: 120px; } }
.lnk-status { display: flex; flex-wrap: wrap; gap: 2px 12px; }

/* Shared-link alerts: the band, "Who fetches it", the dashboard's Links area */
.alertband { background: var(--gold-bg); border-bottom: 1px solid var(--gold-border); }
.ab-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; padding: 12px 16px 0; }
.ab-head h2 { margin: 0; font-size: var(--fs); font-weight: 600; }
.ab-head h2 .stat > span:last-child { color: var(--gold); }
.ab-body { display: flex; flex-direction: column; gap: 4px; padding: 8px 16px 12px; }
.ab-body p { margin: 0; }
.ab-actions { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 16px 14px; }
.ab-what { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 6px 16px; margin: 0; padding: 10px 16px 12px; border-top: 1px solid var(--gold-line); font-size: var(--fs-sm); }
.ab-what dd { margin: 0; color: var(--subtle); }
.sbgroup { display: inline-flex; }
a.pc-sb { display: inline-flex; align-items: center; text-decoration: none; }
.whocols { display: grid; grid-template-columns: minmax(0, 1fr); }
.whocols > div:first-child > .mx-group { border-top: 0; }
.row.who { padding: 4px 16px; font-size: var(--fs-sm); }
.row.who-net { grid-template-columns: minmax(0, 1fr) 80px 90px; }
.row.who-app { grid-template-columns: minmax(0, 1fr) 90px; }
.row.fetch .cc { display: block; }
.colhead.fetch { align-items: end; }
.row.who .ua { word-break: break-word; }
.field .pc-inp.num { width: 100px; }
.row.dashlnk { display: grid; grid-template-columns: minmax(0, 1fr) 130px minmax(0, 1.4fr); gap: 16px; align-items: center; padding: 10px 16px; border-top: 1px solid var(--overlay); text-decoration: none; color: inherit; }
.row.dashlnk:first-child { border-top: 0; }
@media (max-width: 760px) {
  .colhead.lnk, .colhead.fetch { display: none; }
  .row.dashlnk { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .ab-what { grid-template-columns: minmax(0, 1fr); }
  .row.lnk, .row.fetch, .row.act, .row.sublink { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .act-rows { display: block; }
  .act-rows > .row.act { grid-template-columns: minmax(0, 1fr); }
}

/* Cut-off: the plan's servers, the link page's progress */
.row.cutoff { grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr); }
.row.cutoff-item { grid-template-columns: 120px minmax(0, 1fr) auto; gap: 4px 12px; }
.row.cutoff-item > span:nth-child(2) { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; }
.row.cutoff-item .detail { grid-column: 1 / -1; overflow-wrap: anywhere; }
.row.cutoff-item form { grid-column: 3; grid-row: 1; }

/* Routing services: the list, the service page, the snapshot diff, the domain editor */
.offscreen { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.row.svc, .colhead.svc { grid-template-columns: minmax(170px, 1.4fr) 70px 110px 110px 110px minmax(120px, 1fr); align-items: start; }
a.row.svc { text-decoration: none; color: inherit; }
.row.skip .seltext { overflow-wrap: anywhere; }
.row.dom { grid-template-columns: minmax(0, 1fr) 110px minmax(0, 1fr); border-top: 1px solid var(--overlay); }
.row.skip { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); border-top: 1px solid var(--overlay); }
.row.snap { grid-template-columns: 150px 120px 70px minmax(0, 1fr); text-decoration: none; color: inherit; border-top: 1px solid var(--overlay); }
.row.dline { grid-template-columns: 16px minmax(0, 1fr) 110px; border-top: 1px solid var(--overlay); }
.row.dline.add { background: var(--pine-bg); }
.row.dline.add .mk { color: var(--foam); font-weight: 600; }
.row.dline.del { background: var(--love-bg); }
.row.dline.del .mk { color: var(--love); font-weight: 600; }
.row.edrow, .colhead.edrow { grid-template-columns: 16px minmax(200px, 1.4fr) 200px minmax(120px, 1fr) 40px; gap: 12px; align-items: start; }
.row.edrow { border-top: 1px solid var(--overlay); }
.row.edrow .pc-inp { width: 100%; }
.row.edrow .mark { color: var(--foam); font-weight: 600; padding-top: 6px; }
.row.edrow .inline-fields { padding-top: 4px; }
.row.edrow.invalid { background: var(--love-bg); }
.form.wide { max-width: none; padding: 12px 16px; }
.form.wide textarea { width: 100%; }
.paste-report { display: flex; flex-direction: column; gap: 2px; }
/* Routing lists */
.row.rlist, .colhead.rlist { grid-template-columns: minmax(170px, 1.4fr) 90px 90px minmax(150px, 1.2fr) 140px; align-items: start; }
a.row.rlist { text-decoration: none; color: inherit; }
.row.pick { grid-template-columns: 20px minmax(0, 1fr) 70px 110px; align-items: start; border-top: 1px solid var(--overlay); padding-left: 0; padding-right: 0; cursor: pointer; }
.row.pick input { accent-color: var(--rose); width: 16px; height: 16px; margin: 3px 0 0; }
.row.pick > * { min-width: 0; }
.row.warn { grid-template-columns: 16px minmax(0, 1fr); align-items: start; gap: 8px; }
.row.warn a { overflow-wrap: anywhere; }
.band.undo { justify-content: space-between; border-top: 1px solid var(--pine-border); }
.dropped { padding: 4px 16px 10px; }
.dropped .row.dom { padding-left: 0; padding-right: 0; }
.cover-hint { color: var(--gold); }
/* Routing refresh and catalog */
.row.svc .state { display: flex; align-items: center; gap: 6px; }
.band.rejected { flex-direction: column; align-items: stretch; gap: 10px; border-top: 1px solid var(--gold-border); }
.band.rejected .row.dline { padding: 2px 8px; }
.rej-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.rej-acts { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.cause { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.search-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; padding: 12px 16px; }
.search-form input[type=search] { flex: 1 1 260px; }
.search-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px); }
.search-cols .preview:empty { display: none; }
.search-cols:has(.preview:empty) { grid-template-columns: minmax(0, 1fr); }
.preview { border-left: 1px solid var(--overlay); }
.row.cat, .colhead.cat { grid-template-columns: minmax(200px, 1.6fr) 70px minmax(120px, 1fr) auto; align-items: start; }
.row.cat .acts { display: flex; gap: 4px; }
.set-group { border: 0; padding: 0; margin: 0 0 20px; display: flex; flex-direction: column; gap: 16px; }
.set-group legend { font-size: var(--fs-label); letter-spacing: .08em; text-transform: uppercase; color: var(--muted); margin-bottom: 8px; }
@media (max-width: 760px) {
  .colhead.svc, .colhead.edrow, .colhead.rlist, .colhead.cat { display: none; }
  .search-cols { grid-template-columns: minmax(0, 1fr); }
  .preview { border-left: 0; border-top: 1px solid var(--overlay); }
  .rej-cols { grid-template-columns: minmax(0, 1fr); }
  .row.cat { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; padding: 10px 16px; }
  .row.rlist { grid-template-columns: minmax(0, 1fr) auto auto; gap: 4px 12px; padding: 10px 16px; }
  .row.rlist > :nth-child(n+5) { grid-column: 1 / -1; }
  .row.svc, .row.dom, .row.skip, .row.snap { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .row.pick { grid-template-columns: 20px minmax(0, 1fr); gap: 2px 8px; }
  .row.pick > :nth-child(n+3) { grid-column: 2; }
  .row.edrow { grid-template-columns: 16px minmax(0, 1fr) 40px; }
  .row.edrow > .inline-fields, .row.edrow > input.pc-inp { grid-column: 2 / 3; }
}
/* Shadowrocket configs and the mtvpn import */
.row.srcfg, .colhead.srcfg { grid-template-columns: minmax(160px, 1.3fr) 110px 120px minmax(140px, 1.2fr) minmax(140px, 1.2fr); align-items: start; }
a.row.srcfg { text-decoration: none; color: inherit; }
/* New config and Edit base config: the fields over and under the code wrap in strips */
.sr-strip { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px 24px; padding: 12px 16px; }
.sr-strip.top { border-bottom: 1px solid var(--overlay); }
.sr-strip.bottom { border-top: 1px solid var(--overlay); }
.sr-strip .field { flex: 1 1 220px; min-width: 0; }
.sr-strip .field.wide { flex: 2 1 320px; }
.sr-strip .inline-fields { flex-wrap: nowrap; }
.sr-strip .inline-fields .pc-inp { flex: 1 1 0; width: auto; min-width: 0; }
.sr-strip input[type="file"] { max-width: 100%; }
/* The config page: the preview beside versions, fetches and actions. That column needs 540 px for a version's three
   buttons beside its time, so the page stacks below 1270 px (after these rules). */
.subcols.sr-cols { grid-template-columns: minmax(0, 1.3fr) minmax(540px, 1fr); }
.sr-cols > .col-l { align-self: stretch; border-right: 1px solid var(--overlay); }
/* what the phone gets grows with the page (a box of its own put a second scrollbar beside the page's, and its end
   under the key line); a long line wraps anywhere, and its continuation is indented under the line's start */
.sr-preview { background: var(--black); padding: 8px 0; font-size: var(--fs-sm); }
.sr-line { display: grid; grid-template-columns: 48px minmax(0, 1fr); border-left: 3px solid transparent; padding-right: 16px; }
.sr-line .ln { text-align: right; padding-right: 12px; color: var(--muted); user-select: none; }
.sr-line .tx { white-space: pre-wrap; word-break: break-all; padding-left: 4ch; text-indent: -4ch; color: var(--subtle); }
.sr-line.sr-ours { border-left-color: var(--foam); background: var(--overlay); }
.sr-line.sr-ours .tx { color: var(--text); }
/* a version: "v4 · current", its time over its note (one line, the whole note in its title), its buttons 8 px apart */
.row.srver { grid-template-columns: 110px minmax(0, 1fr) auto; align-items: start; border-top: 1px solid var(--overlay); }
.row.srver .normal { font-weight: 400; }
.sr-acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
/* a fetch is one line: the user agent ends in "…", the whole of it in its title */
.row.srfetch { grid-template-columns: 120px 130px minmax(0, 1fr); gap: 12px; font-size: var(--fs-sm); }
.stepstrip { list-style: none; display: flex; flex-wrap: wrap; gap: 0; margin: 0 16px 16px; padding: 0; }
.stepstrip li { padding: 6px 14px; border: 1px solid var(--hl-med); margin-left: -1px; color: var(--muted); }
.stepstrip li.done { color: var(--subtle); }
.stepstrip li.on { color: var(--text); border-color: var(--text); position: relative; }
.row.improw, .colhead.improw { grid-template-columns: 20px minmax(180px, 1.4fr) minmax(100px, .8fr) minmax(130px, 1fr) minmax(120px, 1fr); align-items: start; border-top: 1px solid var(--overlay); padding-left: 0; padding-right: 0; }
.row.improw input { accent-color: var(--rose); width: 16px; height: 16px; margin: 3px 0 0; }
.row.impres { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: start; }
/* the counts over the preview and the result sit on the page's 16 px gutter, the next steps' bullets inside it */
.imp-sum { padding: 0 16px; }
.imp-next { padding-left: 36px; }
.sr-offer { border: 1px solid var(--hl-med); margin: 12px 0; padding: 12px 16px; display: flex; flex-direction: column; gap: 8px; }
.sr-offer .check { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.sr-offer .check input { accent-color: var(--rose); width: 16px; height: 16px; margin: 0; }
@media (max-width: 1270px) {
  .subcols.sr-cols { grid-template-columns: minmax(0, 1fr); }
  /* stacked, versions, fetches and actions come before the preview, which may run thousands of lines */
  .sr-cols > .col-r { order: -1; }
  .sr-cols > .col-l { border-right: 0; }
}
@media (max-width: 760px) {
  .colhead.srcfg, .colhead.improw { display: none; }
  .row.srcfg, .row.srver, .row.srfetch, .row.impres { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .sr-acts { justify-content: flex-start; }
  /* a fetch on a phone: its time and address, the user agent under them */
  .row.srfetch { grid-template-columns: 120px minmax(0, 1fr); gap: 4px 12px; }
  .row.srfetch .ua { grid-column: 1 / -1; }
  .row.improw { grid-template-columns: 20px minmax(0, 1fr); gap: 4px 8px; }
  .row.improw > :nth-child(n+3) { grid-column: 2 / 3; }
}
/* Routers */
.row.rtr, .colhead.rtr { grid-template-columns: minmax(160px, 1.4fr) 110px minmax(100px, .8fr) minmax(160px, 1.6fr) minmax(110px, 1fr) auto; align-items: start; }
.row.tagplan, .colhead.tagplan { grid-template-columns: minmax(120px, 1fr) minmax(130px, 1.2fr) 70px 80px minmax(150px, 1.2fr); align-items: start; border-top: 1px solid var(--overlay); }
.row.rtsync { grid-template-columns: 130px 100px minmax(0, 1fr) auto; gap: 12px; align-items: start; border-top: 1px solid var(--overlay); }
.row.rtsync > span { min-width: 0; overflow-wrap: anywhere; }
.checks { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.checks li { display: flex; flex-direction: column; gap: 2px; }
.snippet { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; align-items: flex-start; }
.snippet .preview-out { width: 100%; box-sizing: border-box; white-space: pre-wrap; word-break: break-all; }
#preview-script, #sync-script { max-height: 50vh; overflow: auto; }
/* a SHA256 fingerprint is one 50-character word: 498 px in a 360 px phone */
code.fp, span.fp { word-break: break-all; }
.band.rtr-band { display: flex; gap: 16px; align-items: flex-start; justify-content: space-between; }
/* Router lifecycle */
.hops { display: flex; flex-direction: column; margin-top: 8px; }
.row.hop { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr); gap: 12px; padding: 6px 0; border-top: 1px solid var(--overlay); align-items: start; }
.row.hop > span, .row.unmanaged > span { min-width: 0; overflow-wrap: anywhere; }
.row.unmanaged, .row.adopt { display: flex; gap: 16px; align-items: flex-start; justify-content: space-between; padding: 10px 16px; border-top: 1px solid var(--overlay); }
.row.adopt { padding: 10px 0; }
.choice { display: flex; gap: 10px; align-items: flex-start; padding: 10px 0; border-top: 1px solid var(--overlay); cursor: pointer; }
.choice input { accent-color: var(--rose); margin: 3px 0 0; }
.area-sub { font-size: inherit; margin: 12px 16px 4px; color: var(--subtle); }
.row.dashrtr { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) auto; gap: 16px; align-items: center; padding: 10px 16px; border-top: 1px solid var(--overlay); text-decoration: none; color: inherit; }
.set-group label.check { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.set-group label.check input { accent-color: var(--rose); margin: 0; }
@media (max-width: 760px) {
  .colhead.rtr, .colhead.tagplan { display: none; }
  .row.rtr, .row.tagplan, .row.rtsync { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .band.rtr-band { flex-direction: column; }
  .row.hop, .row.dashrtr { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .row.unmanaged { flex-direction: column; }
}
/* Discovery */
/* a recent run is one line: the site, its state, then "run #2 · se-1 · 6 h ago" (the
   caret is placed absolutely and takes no column); narrower, that line goes under the site */
.row.disc-recent { grid-template-columns: minmax(0, 1.2fr) 110px minmax(0, 1fr); gap: 4px 16px; align-items: baseline; }
.row.disc-sug { display: flex; gap: 16px; align-items: flex-start; justify-content: space-between; padding: 10px 16px; border-top: 1px solid var(--overlay); }
.disc-visit { border-top: 1px solid var(--overlay); }
.disc-shots { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.disc-shots img { display: block; width: 320px; max-width: 100%; height: auto; border: 1px solid var(--hl-med); background: var(--overlay); }
.disc-group > summary { list-style: none; cursor: pointer; }
.disc-group > summary::-webkit-details-marker { display: none; }
.row.disc-pick, .colhead.disc-pick { grid-template-columns: 20px minmax(200px, 1.4fr) 90px 50px minmax(110px, 1.2fr) minmax(110px, 1fr); align-items: start; border-top: 1px solid var(--overlay); }
.row.disc-pick input { accent-color: var(--rose); width: 16px; height: 16px; margin: 3px 0 0; }
/* a tick box alone in its cell: its label is the cell, with a tap area wider than 16 px */
.tick { display: flex; padding: 12px; margin: -12px; cursor: pointer; }
.row.disc-host { background: var(--base); }
.row.disc-host > .col { padding-left: 16px; }
.disc-form .form-actions { flex-wrap: wrap; align-items: center; }
@media (max-width: 1100px) {
  .row.disc-recent { grid-template-columns: minmax(0, 1fr) 110px; }
  .row.disc-recent .run-line { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
  .colhead.disc-pick { display: none; }
  .row.disc-pick { grid-template-columns: 20px minmax(0, 1fr); gap: 4px 8px; }
  .row.disc-pick > :nth-child(n+3) { grid-column: 2 / 3; }
  .row.disc-sug { flex-direction: column; }
}
/* Router scripts */
a.row.rscript { text-decoration: none; color: inherit; }
.row.rscript, .colhead.rscript { grid-template-columns: minmax(180px, 1.6fr) 110px 120px 100px minmax(120px, 1fr); align-items: start; }
.rs-form { max-width: 760px; }
.rs-form .rs-paste { min-height: 280px; font-family: inherit; }
.rs-editor { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); border-top: 1px solid var(--overlay); }
.rs-code { min-width: 0; padding: 12px 16px; display: flex; flex-direction: column; gap: 8px; }
/* the draft's code runs flush to the panel, as tall as the panel beside it and at least 78 % of the window */
.rs-draft { min-width: 0; display: flex; flex-direction: column; }
.rs-draft > .code-host { flex: 1 1 auto; min-height: max(480px, 78vh); }
.rs-draft > .inline-fields { padding: 10px 16px; border-top: 1px solid var(--overlay); }
.rs-draft .rs-body { min-height: 480px; font-family: inherit; white-space: pre; }
.rs-panel { min-width: 0; border-left: 1px solid var(--overlay); }
.rs-group { padding: 8px 16px; border-top: 1px solid var(--overlay); }
.rs-heading { color: var(--subtle); font-style: italic; margin-bottom: 4px; }
.rs-item { padding: 3px 0; }
.rs-item .rs-line { display: flex; flex-wrap: wrap; gap: 2px 10px; align-items: baseline; overflow-wrap: anywhere; }
.rs-item.computed .bold { color: var(--subtle); }
.rs-problems { list-style: none; margin: 0; padding: 8px 16px 12px; display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--overlay); }
.rs-problems li { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
.row.rsver { grid-template-columns: 110px minmax(0, 1fr); align-items: start; border-top: 1px solid var(--overlay); }
.row.rsver .actions { grid-column: 1 / -1; flex-wrap: wrap; justify-content: flex-start; }
.row.rsver .normal { font-weight: 400; }
/* generating: a choice's fields show only while it is chosen (:has; without it every field shows) */
.gen-form .newform { max-width: 680px; }
.gen-version { padding: 8px 16px; }
.gen-choice { display: flex; flex-direction: column; gap: 8px; }
.gen-choice > label.check { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.gen-choice > label.check input { accent-color: var(--rose); width: 16px; height: 16px; margin: 0; }
.gen-sub { display: flex; flex-direction: column; gap: 12px; margin-left: 26px; padding-left: 12px; border-left: 1px solid var(--overlay); }
.gen-choice:not(:has(> label input[type="radio"]:checked)) > .gen-sub { display: none; }
.gen-sub:not(:has(select[name="router_jump"] option[value="other"]:checked)) .gen-jump-other { display: none; }
.gen-sub .inline .field { flex: 1; min-width: 0; }
.gen-group { display: flex; flex-direction: column; gap: 12px; padding-top: 8px; border-top: 1px solid var(--overlay); }
.gen-ro { display: flex; flex-wrap: wrap; gap: 4px 8px; padding: 6px 0; overflow-wrap: anywhere; }
.gen-steps { margin: 0 0 12px; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; overflow-wrap: anywhere; }
.gen-problems { list-style: none; margin: 4px 0 12px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.gen-secret-note { margin-top: 12px; }
.gen-kv { grid-template-columns: 80px minmax(0, 1fr); margin: 0; }
.gen-kv dd { overflow-wrap: anywhere; }
.row.gen-val { grid-template-columns: 160px minmax(0, 1fr); align-items: baseline; border-top: 1px solid var(--overlay); }
.row.gen-val .gen-v { display: flex; flex-wrap: wrap; gap: 4px 8px; overflow-wrap: anywhere; min-width: 0; }
.gen-all > summary { cursor: pointer; color: var(--subtle); }
a.row.rsgen { grid-template-columns: minmax(0, 1fr) auto auto; text-decoration: none; color: inherit; border-top: 1px solid var(--overlay); }
/* the generation page: fetch areas on the left, the generation on the right; one column on phones, fetch first */
.gen-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1px; background: var(--overlay); border-bottom: 1px solid var(--overlay); }
.gen-col { background: var(--black); min-width: 0; }
.gen-col > .area:last-child { border-bottom: 0; }
.gen-fetch, .gen-fetchbox { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.gen-fstate { margin: 0; }
.gen-cmds { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; }
.gen-cmds li { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.gen-cmds code, .gen-key { font-family: inherit; overflow-wrap: anywhere; word-break: break-all; }
.gen-key { white-space: pre-wrap; margin: 0; padding: 8px 10px; background: var(--base); }
.gen-after { margin: 0; padding-left: 36px; display: flex; flex-direction: column; gap: 12px; overflow-wrap: anywhere; }
.gen-after li { display: flex; flex-direction: column; gap: 4px; }
.row.gen-hist { grid-template-columns: minmax(0, 1fr) minmax(0, .8fr) minmax(0, 1.2fr); border-top: 1px solid var(--overlay); overflow-wrap: anywhere; }
@media (max-width: 760px) {
  .colhead.rscript { display: none; }
  .row.rscript, .row.rsver { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 10px 16px; }
  .rs-editor { grid-template-columns: minmax(0, 1fr); }
  .rs-panel { border-left: 0; border-top: 1px solid var(--overlay); }
  .rs-draft .rs-body { min-height: 320px; }
  .rs-draft > .code-host { min-height: max(320px, 70vh); }
  .row.gen-val, a.row.rsgen { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 8px 16px; }
  .gen-sub .inline { flex-direction: column; }
  .gen-cols { grid-template-columns: minmax(0, 1fr); }
  .row.gen-hist { grid-template-columns: minmax(0, 1fr); gap: 4px; padding: 8px 16px; }
  .gen-fetch .btns > *, .gen-fetch .btns form, .gen-fetch .btns .pc-btn { width: 100%; }
}

/* A side panel beside a long form or list (New server's "Will be created", the
   generate form's summary, a script's parameters, a catalog preview) is a column as
   tall as the row, so its divider runs the whole height; its content (.stick) stays
   at the top of the window while the page scrolls. The header scrolls away, so the
   offset is 0 (an offset left a gap above the panel). Taller than the window above
   the key line, the panel scrolls on its own instead of hiding its end. */
.stick { position: sticky; top: 0; max-height: calc(100vh - var(--keyline-h)); overflow-y: auto; }

/* The link page: what a browser gets at a link's URL. Phone first: most people open
   it on the phone that will connect, so the recommended app's Add button is the one
   primary button, and every tap target is a finger's size. Beside the apps on a
   desktop, the link, Copy and the QR code for a phone to scan. */
.lp { flex: 1; width: 100%; max-width: 1080px; margin: 0 auto; padding: 24px 16px 48px; display: flex; flex-direction: column; gap: 20px; }
.lp h1 { font-size: var(--fs-h1); line-height: var(--lh-h1); font-weight: 600; overflow-wrap: anywhere; }
.lp-head { display: flex; flex-direction: column; gap: 6px; }
.lp-intro { color: var(--subtle); max-width: 640px; }
.lp-gone { display: flex; flex-direction: column; gap: 12px; padding-top: 72px; max-width: 560px; }
.lp-cols { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; align-items: start; }
.lp-apps { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.lp-tabs { display: flex; flex-wrap: wrap; }
.lp-tab { position: relative; margin-left: -1px; padding: 6px 14px; border: 1px solid var(--muted); color: var(--subtle); text-decoration: none; white-space: nowrap; }
.lp-tab:first-child { margin-left: 0; }
.lp-tab:hover { border-color: var(--subtle); color: var(--text); z-index: 1; }
.lp-js .lp-tab.lp-on { border-color: var(--text); color: var(--text); z-index: 2; }
.lp-tab:focus-visible { outline-offset: -1px; z-index: 3; }
.lp-plat { display: flex; flex-direction: column; gap: 12px; }
.lp-plat[hidden] { display: none; }
.lp-plat + .lp-plat { margin-top: 16px; }
.lp-plat-h { font-size: var(--fs-label); line-height: 16px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); }
/* with the tabs working, a section's tab names it */
.lp-js .lp-plat + .lp-plat { margin-top: 0; }
.lp-js .lp-plat-h { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.lp-app { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px 16px; border: 1px solid var(--overlay); }
.lp-rec { border-color: var(--hl-high); background: var(--base); }
.lp-app-h { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.lp-app-h h3 { font-size: var(--fs-dialog); line-height: 22px; font-weight: 600; }
.lp-badge { padding: 0 6px; border: 1px solid var(--text); font-size: var(--fs-label); line-height: 16px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.lp-note { color: var(--subtle); }
/* a step's number in a column of its own, its parts stacked beside it (a flex or grid
   li loses its marker) */
.lp-steps { margin: 0; padding: 0; list-style: none; counter-reset: lp-step; display: flex; flex-direction: column; gap: 14px; }
.lp-steps > li { counter-increment: lp-step; display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 8px 4px; }
.lp-steps > li::before { content: counter(lp-step) "."; grid-row: 1; color: var(--subtle); }
.lp-steps > li > * { grid-column: 2; }
.lp-btns { display: flex; flex-wrap: wrap; gap: 8px; }
.lp:not(.lp-js) .lp-copy { display: none; }
.lp-small { font-size: var(--fs-sm); line-height: 18px; color: var(--subtle); }
.lp-side { display: flex; flex-direction: column; gap: 12px; padding: 14px 16px 16px; border: 1px solid var(--overlay); position: sticky; top: 16px; }
.lp-label { font-size: var(--fs-label); line-height: 16px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--subtle); }
.lp-url { padding: 8px 10px; background: var(--base); border: 1px solid var(--hl-med); overflow-wrap: anywhere; user-select: all; }
.lp-qr summary { cursor: pointer; color: var(--subtle); }
.lp-qr summary:hover { color: var(--text); }
.lp-qr .qr { margin-top: 12px; max-width: 240px; }
@media (max-width: 760px) {
  .lp { padding-top: 20px; gap: 16px; }
  .lp-gone { padding-top: 24px; }
  .lp-cols { grid-template-columns: minmax(0, 1fr); }
  .lp-side { position: static; }
  /* six tabs in two rows of three, each a finger wide */
  .lp-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .lp-tab { display: flex; align-items: center; justify-content: center; min-height: 48px; margin: 0 0 -1px -1px; padding: 6px; text-align: center; white-space: normal; }
  .lp-tab:nth-child(3n + 1) { margin-left: 0; }
  .lp-add { width: 100%; }
  .lp-qr summary { padding: 12px 0; margin: -12px 0; }
}

/* Side-by-side page columns need room: below 1100 px (a laptop zoomed to 125 % and
   more, a narrow window) they stack, as on a phone, instead of squeezing their tables. */
@media (max-width: 1100px) {
  .subcols, .newcols, .search-cols, .rs-editor, .gen-cols, .rej-cols { grid-template-columns: minmax(0, 1fr); }
  .search-cols .preview, .rs-panel { border-left: 0; border-top: 1px solid var(--overlay); }
  .newsum { border-left: 0; border-top: 1px solid var(--overlay); }
  /* stacked, a panel is part of the page again */
  .stick { position: static; max-height: none; overflow: visible; }
  .settings { flex-direction: column; }
  .settings-nav { width: auto; border-right: 0; border-bottom: 1px solid var(--overlay); display: flex; overflow-x: auto; padding: 0; }
  .settings-nav a { flex: none; }
  /* full screen, stacked: the script's parameters go under the code, at most 30 % of the
     window, and the code keeps 280 px (a short window scrolls the page instead) */
  .code-full .rs-area { min-height: auto; }
  .code-full .rs-editor { grid-template-rows: minmax(280px, 1fr) auto; }
  .code-full .rs-panel { max-height: 30vh; }
}
