/* ==========================================================================
   Balter Admin — prototype
   Tokens are the landing page's, verbatim (landing/styles.css :root).
   Structure follows TailAdmin: fixed sidebar, sticky topbar, card grid,
   data table with a right-hand editor drawer.
   Motion follows emil-design-eng: transform/opacity only, <300ms, no ease-in.
   ========================================================================== */

/* Vertical rhythm, decided once
 * ---------------------------------------------------------------------------
 * Text in Canaro sits high in its own line box: the font reserves 834 units
 * above the baseline and 366 below, while the ink of a capital only reaches
 * 680. Anything centred honestly — a flex row, a button with equal padding, a
 * badge — therefore looked a little low, and every place that mattered grew its
 * own nudge. Dozens of them, each right on the day it was written and wrong the
 * next time a sibling changed.
 *
 * The correction belongs to the font, not to the components. These overrides
 * re-cut the line box so the capital band sits in the middle of it:
 *
 *     box centre = (ascent - descent) / 2   must equal   cap / 2
 *     so ascent - descent = cap, with ascent + descent kept at the
 *     font's own 1.2 em.
 *
 * Canaro    cap 680 → 94.00% / 26.00%
 * Zen Dots  cap 715 → 95.75% / 24.25%
 *
 * From here on, centring is centring: `align-items: center` and equal padding
 * are correct on their own, an icon beside a label needs nothing but
 * `align-items: center`, and no rule in this sheet may add a vertical nudge to
 * make text look centred.
 * They also make the result identical on every platform, since a browser
 * otherwise picks hhea or OS/2 metrics depending on the operating system. */
@font-face { font-family:'Zen Dots'; src:url('ui/fonts/ZenDots-Regular.woff2') format('woff2'); font-weight:400; font-display:swap;
  ascent-override: 95.75%;
  descent-override: 24.25%;
  line-gap-override: 0%;
}
@font-face { font-family:'Canaro'; src:url('ui/fonts/Canaro-Book.woff2') format('woff2'); font-weight:400; font-display:swap;
  ascent-override: 94%;
  descent-override: 26%;
  line-gap-override: 0%;
}
@font-face { font-family:'Canaro'; src:url('ui/fonts/Canaro-Medium.woff2') format('woff2'); font-weight:500; font-display:swap;
  ascent-override: 94%;
  descent-override: 26%;
  line-gap-override: 0%;
}
@font-face { font-family:'Canaro'; src:url('ui/fonts/Canaro-SemiBold.woff2') format('woff2'); font-weight:600; font-display:swap;
  ascent-override: 94%;
  descent-override: 26%;
  line-gap-override: 0%;
}
@font-face { font-family:'Canaro'; src:url('ui/fonts/Canaro-Bold.woff2') format('woff2'); font-weight:700; font-display:swap;
  ascent-override: 94%;
  descent-override: 26%;
  line-gap-override: 0%;
}

:root {
  --accent:#fb824b; --accent-text:#fb824b; --accent-2:#6699cc;
  --bg:#0f0f0f; --surface:#151515; --surface-2:#1c1c1c;
  --line:rgba(255,255,255,.1); --line-strong:rgba(255,255,255,.2);
  --fg:#fff; --fg-muted:#959595; --fg-dim:rgba(255,255,255,.45);
  --tint:rgba(255,255,255,.06); --scrim:rgba(5,5,5,.72);
  --mono:ui-monospace,'SF Mono',Menlo,monospace;
  --shadow:rgba(0,0,0,.45); --shadow-strong:rgba(0,0,0,.64);
  --ok:#4a9d6a; --warn:#c9922f; --err:#c4553f;
  --ok-text:#6fc48d; --warn-text:#e0b45c; --err-text:#e07d66;
  --r-sm:2px; --r:4px; --r-lg:8px;
  --ease-out:cubic-bezier(.23,1,.32,1);
  --t-fast:140ms; --t:200ms; --t-slow:280ms;
  --side-w:248px; --top-h:60px;
}

/* `hidden` must win.
 *
 * The attribute only carries `display: none` from the user-agent stylesheet,
 * which any component rule with its own `display` silently outranks. This has
 * cost time four times in this repository — the mega-menu sheet, the "show
 * more" button, the prototype tag and the sign-in divider — each time as an
 * element that was hidden in JavaScript and stayed on screen anyway.
 *
 * One rule ends the whole class of it. Use `hidden` to hide things. */
[hidden] { display: none !important; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) {
    --accent-text:#b5491a; --bg:#fff; --surface:#f7f7f7; --surface-2:#f0f0f0;
    --line:rgba(0,0,0,.12); --line-strong:rgba(0,0,0,.26);
    --fg:#0f0f0f; --fg-muted:#5a5a5a; --fg-dim:rgba(0,0,0,.5);
    --tint:rgba(0,0,0,.05); --shadow:rgba(0,0,0,.14); --shadow-strong:rgba(0,0,0,.2);
    --ok-text:#2c7048; --warn-text:#8a6108; --err-text:#a63b26;
  }
}
:root[data-theme='light'] {
  --accent-text:#b5491a; --bg:#fff; --surface:#f7f7f7; --surface-2:#f0f0f0;
  --line:rgba(0,0,0,.12); --line-strong:rgba(0,0,0,.26);
  --fg:#0f0f0f; --fg-muted:#5a5a5a; --fg-dim:rgba(0,0,0,.5);
  --tint:rgba(0,0,0,.05); --shadow:rgba(0,0,0,.14); --shadow-strong:rgba(0,0,0,.2);
  --ok-text:#2c7048; --warn-text:#8a6108; --err-text:#a63b26;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) .side__brand img { filter:invert(1); }
}
:root[data-theme='light'] .side__brand img { filter:invert(1); }

*,*::before,*::after { box-sizing:border-box; }
html { scrollbar-gutter:stable; }
body {
  margin:0; background:var(--bg); color:var(--fg);
  font:400 14px/1.5 'Canaro',system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
}
svg { fill:none; stroke:currentColor; stroke-width:1.4; stroke-linecap:round; stroke-linejoin:round; }
button,input,select,textarea { font:inherit; color:inherit; }
:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
::-webkit-scrollbar { width:10px; height:10px; }
::-webkit-scrollbar-thumb { background:var(--line-strong); border-radius:99px; border:3px solid var(--bg); }

/* ---------- prototype flag ------------------------------------------------ */

/* ---------- shell --------------------------------------------------------- */
.shell { display:grid; grid-template-columns:var(--side-w) 1fr; min-height:100vh; }
.main { min-width:0; display:flex; flex-direction:column; }

.side {
  position:sticky; top:0; align-self:start; height:100vh;
  display:flex; flex-direction:column;
  background:var(--surface); border-right:1px solid var(--line);
}
.side__brand {
  height:var(--top-h); flex:none; display:flex; align-items:center; gap:10px;
  padding:0 18px; border-bottom:1px solid var(--line);
}
.side__brand img { height:16px; width:auto; }
.side__env {
  font:400 9px/1 'Zen Dots',sans-serif; letter-spacing:.16em;
  color:var(--fg-dim); padding-top:2px;
}
.side__nav { flex:1; overflow-y:auto; padding:14px 10px 20px; }
.navgroup { margin-bottom:14px; }
.navgroup__title {
  font-size:10px; letter-spacing:.14em; font-weight:600; color:var(--fg-dim);
  padding:6px 10px; text-transform:uppercase;
}
.navitem {
  display:flex; align-items:center; gap:10px; width:100%;
  padding:8px 10px; border:0; border-radius:var(--r);
  background:none; text-align:left; cursor:pointer; color:var(--fg-muted);
  transition:background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.navitem svg { width:16px; height:16px; flex:none; }
.navitem__label { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Same rule as the tab counters: a whole number of pixels, centred by the box.
   A height that falls out of line-height lands on a fraction, and a fraction is
   what puts a digit one device pixel high on a retina screen. */
.navitem__count {
  display:block; box-sizing:border-box; min-width:20px; height:18px; padding:0 5px;
  font-size:10px; line-height:16px; text-align:center;
  color:var(--fg-dim); font-variant-numeric:tabular-nums;
  border:1px solid var(--line); border-radius:var(--r-sm);
}
.navitem__count[data-tone='accent'] { color:var(--accent-text); border-color:var(--accent-text); }
@media (hover:hover) and (pointer:fine) { .navitem:hover { background:var(--tint); color:var(--fg); } }
.navitem:active { transform:scale(.97); }
.navitem[aria-current='page'] {
  background:var(--tint); color:var(--fg); box-shadow:inset 2px 0 0 var(--accent);
}
.navitem[disabled] { opacity:.32; cursor:not-allowed; }
.navitem[disabled]:active { transform:none; }
.side__foot { flex:none; padding:12px 18px; border-top:1px solid var(--line); }
.side__ver { font-size:11px; color:var(--fg-dim); }
.side__ver b { color:var(--fg-muted); font-weight:500; }

/* ---------- topbar -------------------------------------------------------- */
.top {
  position:sticky; top:0; z-index:20; height:var(--top-h); flex:none;
  display:flex; align-items:center; gap:10px; padding:0 20px;
  background:var(--bg); border-bottom:1px solid var(--line);
}
.top__spacer { flex:1; }
.top__burger { display:none; }
.crumb { display:flex; align-items:center; gap:8px; font-size:13px; color:var(--fg-muted); min-width:0; }
.crumb b { color:var(--fg); font-weight:600; }
.crumb i { font-style:normal; color:var(--fg-dim); }

.rolesim { display:flex; align-items:center; gap:8px; }
.rolesim__label { font-size:11px; color:var(--fg-dim); }
.me {
  width:32px; height:32px; border-radius:99px; flex:none;
  display:grid; place-items:center; font-size:10px; font-weight:600;
  background:var(--surface-2); border:1px solid var(--line);
}

/* ---------- controls ------------------------------------------------------ */
.btn {
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  height:36px; padding:0 14px; border-radius:var(--r);
  border:1px solid var(--line-strong); background:transparent; color:var(--fg);
  font-weight:500; cursor:pointer; white-space:nowrap;
  transition:background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out), opacity var(--t-fast) var(--ease-out);
}
.btn svg { width:15px; height:15px; display:block; flex:none; }
/* An icon wrapped in a span — the shape the panel builds when the mark comes
   from a string of SVG. Without this the span is an inline box and the icon
   inside it rides on the baseline. */
.ico { display:flex; align-items:center; flex:none; }
.ico svg { display:block; }
@media (hover:hover) and (pointer:fine) { .btn:hover { background:var(--tint); } }
.btn:active { transform:scale(.97); }
.btn--sm { height:30px; padding:0 10px; font-size:13px; }
.btn--accent { background:var(--accent); border-color:var(--accent); color:#0f0f0f; font-weight:600; }
@media (hover:hover) and (pointer:fine) { .btn--accent:hover { background:#ff9264; } }
.btn--ghost { border-color:var(--line); color:var(--fg-muted); }
.btn--danger { border-color:var(--err); color:var(--err-text); }
.btn[disabled] { opacity:.4; cursor:not-allowed; }
.btn[disabled]:active { transform:none; }

.icon-btn {
  width:32px; height:32px; flex:none; display:grid; place-items:center;
  border:1px solid var(--line); border-radius:var(--r); background:transparent;
  cursor:pointer; color:var(--fg-muted);
  transition:background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.icon-btn svg { width:16px; height:16px; }
@media (hover:hover) and (pointer:fine) { .icon-btn:hover { background:var(--tint); color:var(--fg); } }
.icon-btn:active { transform:scale(.97); }

.input,.select,.textarea {
  width:100%; background:var(--surface); color:var(--fg);
  border:1px solid var(--line); border-radius:var(--r);
  padding:9px 11px; transition:border-color var(--t-fast) var(--ease-out);
}
.select { padding:8px 11px; cursor:pointer; }
.select--sm { width:auto; height:30px; padding:4px 8px; font-size:13px; }
.textarea { min-height:96px; resize:vertical; line-height:1.6; }
.input:focus,.select:focus,.textarea:focus { border-color:var(--line-strong); }
.field { display:block; margin-bottom:16px; }
.field__label { display:block; font-size:12px; font-weight:600; color:var(--fg-muted); margin-bottom:6px; }
.field__hint { font-size:11px; color:var(--fg-dim); margin-top:5px; }
.field__row { display:grid; grid-template-columns:1fr 1fr; gap:14px; }

.switch { display:flex; align-items:center; gap:10px; cursor:pointer; }
.switch input { position:absolute; opacity:0; pointer-events:none; }
.switch__track {
  width:36px; height:20px; border-radius:99px; background:var(--surface-2);
  border:1px solid var(--line-strong); position:relative; flex:none;
  transition:background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.switch__track::after {
  content:''; position:absolute; inset:2px auto 2px 2px; width:14px; border-radius:99px;
  background:var(--fg-muted); transition:transform var(--t) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.switch input:checked + .switch__track { background:var(--accent); border-color:var(--accent); }
.switch input:checked + .switch__track::after { transform:translateX(16px); background:#0f0f0f; }
.switch input:focus-visible + .switch__track { outline:2px solid var(--accent); outline-offset:2px; }
/* A switch that cannot be moved says so: the three landing-page slots are full,
   and the label beside it names what is holding them. */
.switch:has(input:disabled) { cursor:not-allowed; color:var(--fg-dim); }
.switch input:disabled + .switch__track { opacity:.45; }
/* Standing on its own in a form, a switch needs the same air as a field. */
.drawer .switch { margin-bottom:16px; }

/* ---------- page ---------------------------------------------------------- */
.page { padding:24px 24px 64px; max-width:1560px; width:100%; }
.page:focus { outline:none; }
.pagehead { display:flex; align-items:flex-end; gap:16px; flex-wrap:wrap; margin-bottom:20px; }
.pagehead__t { flex:1; min-width:240px; }
.pagehead h1 { margin:0 0 5px; font-size:22px; font-weight:600; letter-spacing:-.01em; }
.pagehead p { margin:0; color:var(--fg-muted); font-size:13px; max-width:76ch; }
.pagehead__actions { display:flex; gap:8px; flex-wrap:wrap; }

.card {
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r-lg);
}
.card__head {
  display:flex; align-items:center; gap:12px; padding:14px 16px; border-bottom:1px solid var(--line);
}
.card__head h2 { margin:0; font-size:14px; font-weight:600; flex:1; }
.card__body { padding:16px; }
.card__foot { padding:12px 16px; border-top:1px solid var(--line); display:flex; gap:8px; align-items:center; }

.grid { display:grid; gap:16px; }
.grid--4 { grid-template-columns:repeat(4,1fr); }
.grid--3 { grid-template-columns:repeat(3,1fr); }
.grid--2 { grid-template-columns:repeat(2,1fr); }
.grid--sidebar { grid-template-columns:minmax(0,1fr) 340px; align-items:start; }

.stat { padding:16px; }
.stat__k { font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--fg-dim); }
.stat__v { font-size:30px; font-weight:600; margin:8px 0 4px; font-variant-numeric:tabular-nums; letter-spacing:-.02em; }
.stat__n { font-size:12px; color:var(--fg-muted); }
.stat__n[data-tone='warn'] { color:var(--warn-text); }
.stat__n[data-tone='err'] { color:var(--err-text); }
.stat__n[data-tone='ok'] { color:var(--ok-text); }

.meter { height:4px; background:var(--surface-2); border-radius:99px; overflow:hidden; margin-top:10px; }
.meter i { display:block; height:100%; background:var(--accent); border-radius:99px; }
.meter i[data-tone='ok'] { background:var(--ok); }
.meter i[data-tone='err'] { background:var(--err); }

/* ---------- table --------------------------------------------------------- */
.tablewrap { overflow-x:auto; }
table.data { width:100%; border-collapse:collapse; font-size:13px; }
table.data th {
  text-align:left; font-size:11px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--fg-dim); font-weight:600; padding:10px 12px;
  border-bottom:1px solid var(--line); white-space:nowrap; position:sticky; top:0;
  background:var(--surface); z-index:1;
}
table.data td { padding:10px 12px; border-bottom:1px solid var(--line); vertical-align:middle; }
table.data tr:last-child td { border-bottom:0; }
table.data tbody tr { transition:background var(--t-fast) var(--ease-out); }
/* Only rows that do something may react to the pointer. Highlighting every row
   made the tables in Schaltpläne, Material, Partnerwand, Wissensbasis and
   Fachpartner look clickable — they are not, their actions are buttons in the
   last column — so the row lit up under the cursor and then swallowed the
   click. */
@media (hover:hover) and (pointer:fine) {
  table.data tbody tr[data-clickable]:hover { background:var(--tint); }
}
table.data tbody tr[data-clickable] { cursor:pointer; }
.cell-main { font-weight:500; }
.cell-sub {
  font-size:11px; color:var(--fg-dim); margin-top:2px;
  /* One line, always. A row that sizes to its longest text turns a 186-article
     table into a page nobody can scan. */
  display:-webkit-box; -webkit-line-clamp:1; -webkit-box-orient:vertical;
  overflow:hidden;
}
.cell-ref { font-family:ui-monospace,'SF Mono',Menlo,monospace; font-size:11px; color:var(--fg-muted); }
.cell-num { text-align:right; font-variant-numeric:tabular-nums; }
/* Centred, because a row of actions is not always a row of buttons: a pill
   standing in for a button it does not have — "fest" beside Bearbeiten — is
   22px against 30 and sat four pixels high with the default stretch. */
.rowactions { display:flex; align-items:center; gap:6px; justify-content:flex-end; }

.thumb {
  width:38px; height:38px; flex:none; border-radius:var(--r-sm);
  background:var(--surface-2); border:1px solid var(--line);
  object-fit:contain; padding:2px;
}
/* Half the shop's shots are on white and half on black — the plate carries the
   tone the photograph was taken on, or a pale product vanishes into a dark row. */
.thumb[data-tone='light'] { background:#f2f2f2; }
.thumb[data-tone='dark']  { background:#141414; }
.rowflex { display:flex; align-items:center; gap:10px; min-width:0; }

/* ---------- pills & badges ------------------------------------------------ */
.pill {
  display:inline-flex; align-items:center; gap:5px; height:22px;
  padding:0 8px; border-radius:var(--r-sm);
  border:1px solid var(--line); font-size:10px; letter-spacing:.01em;
  color:var(--fg-muted); white-space:nowrap;
}
/* Several pills in one cell are appended as siblings with no whitespace
   between them, and inline-flex leaves none of its own — five system tags read
   as "EVOEVO HDEVO HD PROENTRIERA". */
.pill + .pill { margin-left:4px; }
.pill[data-tone='ok'] { color:var(--ok-text); border-color:color-mix(in srgb,var(--ok) 55%,transparent); }
.pill[data-tone='warn'] { color:var(--warn-text); border-color:color-mix(in srgb,var(--warn) 55%,transparent); }
.pill[data-tone='err'] { color:var(--err-text); border-color:color-mix(in srgb,var(--err) 55%,transparent); }
.pill[data-tone='accent'] { color:var(--accent-text); border-color:var(--accent-text); }
.pill[data-tone='draft'] { color:var(--fg-dim); border-style:dashed; }
/* A bullet belongs on the x-height, not on the cap band.
   The box is centred on the capital band — right for the box, wrong for a dot
   standing next to lower-case words: at cap centre it rides above the word's
   own middle and the pair reads as two lines rather than one. Canaro's
   x-height is 467 and its cap 680, so the dot comes down by half the
   difference: 0.107em. This is aligning a graphic to text, not faking the
   centring of text. */
.dot {
  width:6px; height:6px; border-radius:99px; background:currentColor; flex:none;
  margin-top:0.107em;
}

.chips { display:flex; gap:6px; flex-wrap:wrap; }
.chip {
  display:inline-flex; align-items:center; gap:6px; height:28px;
  padding:0 10px; border:1px solid var(--line); border-radius:var(--r);
  background:transparent; font-size:13px; color:var(--fg-muted); cursor:pointer;
  transition:border-color var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
@media (hover:hover) and (pointer:fine) { .chip:hover { border-color:var(--line-strong); color:var(--fg); } }
.chip:active { transform:scale(.97); }
.chip[aria-pressed='true'] { border-color:var(--accent); color:var(--accent-text); }
.chip__n { font-size:11px; color:var(--fg-dim); font-variant-numeric:tabular-nums; }

/* A row of controls, on the page's own grid.
   It used to carry a card's inset — 16px each side and a rule underneath —
   because it was first written as a strip inside a card. Used at page level, as
   the blog and the catalogue use it, that pushed the search field 16px right of
   everything above and below it, and drew a line across the page that belonged
   to no box. A toolbar sits where its neighbours sit; a card's own padding is
   the card's business. */
.toolbar { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-bottom:14px; }
.toolbar .input { max-width:280px; }
.toolbar__spacer { flex:1; }

/* ---------- lists & misc -------------------------------------------------- */
.list { display:flex; flex-direction:column; }
.list__row {
  display:flex; align-items:flex-start; gap:12px; padding:12px 16px;
  border-bottom:1px solid var(--line);
}
.list__row:last-child { border-bottom:0; }
.list__main { flex:1; min-width:0; }
.list__t { font-weight:500; }
.list__s { font-size:12px; color:var(--fg-dim); margin-top:3px; }
.list__time { font-size:11px; color:var(--fg-dim); white-space:nowrap; font-variant-numeric:tabular-nums; }

.empty { padding:56px 24px; text-align:center; color:var(--fg-dim); }
.empty h3 { margin:0 0 6px; font-size:14px; color:var(--fg-muted); font-weight:600; }
.empty p { margin:0 auto; max-width:44ch; font-size:13px; }

/* Block, not flex: a note is a sentence with <b> and <code> in it, and under
   flex every one of those becomes a flex item and the sentence breaks apart. */
/* A note is not a field. With a hairline on all four sides it reads as an
   empty input at a glance, which is exactly what it looked like above the
   capability list; the left edge carries the difference. */
.note {
  display:block; padding:12px 14px; border-radius:var(--r);
  border:1px solid var(--line); border-left:2px solid var(--line-strong);
  background:var(--surface-2);
  font-size:12.5px; line-height:1.6; color:var(--fg-muted);
}
.note[data-tone='warn'] { border-color:color-mix(in srgb,var(--warn) 45%,transparent); }
.note[data-tone='err'] { border-color:color-mix(in srgb,var(--err) 45%,transparent); }
.note[data-tone='accent'] { border-color:color-mix(in srgb,var(--accent) 45%,transparent); }
.note[data-tone='warn'] { border-left-color:var(--warn-text); }
.note[data-tone='err'] { border-left-color:var(--err-text); }
.note[data-tone='accent'] { border-left-color:var(--accent); }
.note b { color:var(--fg); font-weight:600; }

.kv { display:grid; grid-template-columns:auto 1fr; gap:8px 16px; font-size:13px; }
.kv dt { color:var(--fg-dim); }
.kv dd { margin:0; }

/* ---------- drawer -------------------------------------------------------- */
.scrim {
  position:fixed; inset:0; background:var(--scrim); z-index:60;
  animation:fade var(--t) var(--ease-out);
}
.scrim[hidden] { display:none; }
@keyframes fade { from { opacity:0 } }

.drawer {
  position:fixed; top:0; right:0; bottom:0; width:min(560px,100vw); z-index:70;
  display:flex; flex-direction:column;
  background:var(--bg); border-left:1px solid var(--line); box-shadow:-24px 0 64px var(--shadow-strong);
  animation:slidein var(--t-slow) var(--ease-out);
}
.drawer[hidden] { display:none; }
.drawer--wide { width:min(880px,100vw); }
@keyframes slidein { from { transform:translateX(24px); opacity:0 } }
.drawer__head {
  flex:none; height:var(--top-h); display:flex; align-items:center; gap:12px;
  padding:0 18px; border-bottom:1px solid var(--line);
}
.drawer__head h2 { margin:0; font-size:15px; font-weight:600; flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.drawer__body { flex:1; overflow-y:auto; padding:20px 18px; min-height:0; }
.drawer__foot {
  flex:none; padding:12px 18px; border-top:1px solid var(--line);
  display:flex; gap:8px; align-items:center;
}
.drawer__foot .grow { flex:1; }

.section-t {
  font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:var(--fg-dim);
  font-weight:600; margin:24px 0 12px; padding-bottom:8px; border-bottom:1px solid var(--line);
}
.section-t:first-child { margin-top:0; }

/* ---------- permission matrix -------------------------------------------- */
.matrix { width:100%; border-collapse:collapse; font-size:12.5px; }
.matrix th { padding:8px 6px; font-size:10px; letter-spacing:.08em; text-transform:uppercase; color:var(--fg-dim); font-weight:600; }
.matrix th:first-child { text-align:left; }
.matrix td { padding:7px 6px; border-top:1px solid var(--line); text-align:center; }
.matrix td:first-child { text-align:left; color:var(--fg-muted); }
.matrix input[type=checkbox] { accent-color:var(--accent); width:15px; height:15px; cursor:pointer; }
.matrix tr[data-locked] td { opacity:.45; }

/* ---------- diff / validation -------------------------------------------- */
.check { display:flex; gap:10px; padding:10px 0; border-bottom:1px solid var(--line); font-size:13px; }
.check:last-child { border-bottom:0; }
.check__i { width:16px; height:16px; flex:none; margin-top:2px; }
.check__i[data-s='ok'] { color:var(--ok-text); }
.check__i[data-s='warn'] { color:var(--warn-text); }
.check__i[data-s='err'] { color:var(--err-text); }
.check__m { flex:1; min-width:0; }
.check__m b { display:block; font-weight:500; }
.check__m span { display:block; font-size:12px; color:var(--fg-dim); margin-top:2px; }

.diff { font-family:ui-monospace,'SF Mono',Menlo,monospace; font-size:12px; line-height:1.7; }
.diff div { padding:1px 8px; border-radius:var(--r-sm); }
.diff .add { color:var(--ok-text); background:color-mix(in srgb,var(--ok) 12%,transparent); }
.diff .del { color:var(--err-text); background:color-mix(in srgb,var(--err) 12%,transparent); text-decoration:line-through; }

/* ---------- toasts -------------------------------------------------------- */
.toasts { position:fixed; right:20px; bottom:20px; z-index:90; display:flex; flex-direction:column; gap:8px; }
.toast {
  display:flex; align-items:center; gap:10px; padding:11px 14px;
  background:var(--surface-2); border:1px solid var(--line-strong); border-radius:var(--r);
  box-shadow:0 12px 32px var(--shadow); font-size:13px; max-width:380px;
  animation:toastin var(--t) var(--ease-out);
}
@keyframes toastin { from { transform:translateY(8px); opacity:0 } }
.toast[data-tone='ok'] { border-color:color-mix(in srgb,var(--ok) 60%,transparent); }
.toast[data-tone='err'] { border-color:color-mix(in srgb,var(--err) 60%,transparent); }

/* ---------- responsive ---------------------------------------------------- */
@media (max-width:1200px) { .grid--4 { grid-template-columns:repeat(2,1fr); } .grid--sidebar { grid-template-columns:1fr; } }
@media (max-width:1024px) {
  .shell { grid-template-columns:1fr; }
  .side {
    position:fixed; inset:0 auto 0 0; z-index:80; width:var(--side-w);
    transform:translateX(-100%); transition:transform var(--t-slow) var(--ease-out);
  }
  .shell[data-nav='open'] .side { transform:none; }
  /* An overlay nav needs a ground to close against: it covers the burger that
     opened it, so without this the only way back out is a route change. */
  .shell[data-nav='open']::before {
    content:''; position:fixed; inset:0; z-index:70;
    background:var(--scrim); animation:fade var(--t) var(--ease-out);
  }
  .top__burger { display:grid; }
  .rolesim__label { display:none; }
}
@media (max-width:760px) {
  .page { padding:16px 16px 48px; }
  .grid--4,.grid--3,.grid--2 { grid-template-columns:1fr; }
  .crumb i,.crumb span:not(:last-child) { display:none; }
  #preview-site { display:none; }
}
@media (prefers-reduced-motion: reduce) {
  *,*::before,*::after { animation-duration:.01ms !important; transition-duration:.01ms !important; }
}

/* --- locale coverage: six codes, lit or not ------------------------------- */
/* Not `.dot` — that one is a 6px status circle and these carry a label. */
.locdots { display:inline-flex; gap:3px; }
.locdot {
  font-size:9.5px; line-height:1; letter-spacing:.04em; text-transform:uppercase;
  padding:4px; border:1px solid var(--line);
  color:var(--fg-dim); border-radius:2px;
}
.locdot[data-on='1'] { color:var(--fg); border-color:var(--line-strong); }

/* --- a list of rules, read as prose --------------------------------------- */
.rules { margin:0; padding-left:18px; display:grid; gap:8px; font-size:13px; color:var(--fg-muted); }
.rules li { line-height:1.55; }
.rules b { color:var(--fg); font-weight:500; }
.rules code { font-family:var(--mono); font-size:11.5px; background:var(--tint); padding:1px 4px; border-radius:2px; }

/* Inline code inside notes and prose. */
code { font-family:var(--mono); font-size:.88em; background:var(--tint); padding:1px 4px; border-radius:2px; }

/* A short list of checkboxes inside a drawer field. Two columns, because five
   system names in one column pushes the file input below the fold. */
.checks { display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:0 18px; }
.checks .check:last-child, .checks .check:nth-last-child(2) { border-bottom:0; }
@media (max-width: 520px) { .checks { grid-template-columns:1fr; } }

/* Language of the panel ----------------------------------------------------
   Two words, not a dropdown: there are exactly two, and a select for two
   options hides one of them behind a click. */
.langsim { display:flex; gap:2px; padding:2px; border:1px solid var(--line); border-radius:var(--r-sm); }
.langsim__b {
  min-width:32px; padding:4px 6px; border:0; border-radius:calc(var(--r-sm) - 2px);
  background:transparent; color:var(--fg-dim); font:inherit; font-size:11px; font-weight:600;
  letter-spacing:.06em; cursor:pointer; transition:background var(--t-fast), color var(--t-fast);
}
.langsim__b[aria-pressed='true'] { background:var(--tint); color:var(--fg); }
@media (hover:hover) and (pointer:fine) { .langsim__b:hover { color:var(--fg); } }
@media (max-width:900px) { .langsim { display:none; } }

/* Row order ----------------------------------------------------------------
   The grip is the only part of the row that starts a drag: a whole row that
   drags cannot also be a row you click. */
.grip-col { width:28px; padding-right:0 !important; }
.grip {
  display:grid; place-items:center; width:22px; height:26px; padding:0;
  border:0; background:transparent; color:var(--fg-dim); cursor:grab;
  border-radius:var(--r-sm); transition:color var(--t-fast), background var(--t-fast);
}
.grip:active { cursor:grabbing; }
.grip svg { fill:currentColor; }
.grip:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
@media (hover:hover) and (pointer:fine) { .grip:hover { color:var(--fg); background:var(--tint); } }
table.data tbody tr.is-dragging { opacity:.5; background:var(--tint); }

/* Nothing to show yet ------------------------------------------------------
   Quiet on purpose: it is on screen for a few hundred milliseconds and a
   spinner would draw more attention than the wait deserves. */
.loading { padding:48px 4px; color:var(--fg-dim); font-size:13px; }

/* Select --------------------------------------------------------------------
   The list is ours, not the operating system's: a native <select> opens a
   white system sheet on top of a dark panel and none of it can be styled. */
.sel { position:relative; width:100%; }
.sel__btn {
  width:100%; display:flex; align-items:center; gap:10px; justify-content:space-between;
  background:var(--surface); color:var(--fg); font:inherit; text-align:left;
  border:1px solid var(--line); border-radius:var(--r); padding:8px 11px; cursor:pointer;
  transition:border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.sel__btn:disabled { opacity:.5; cursor:not-allowed; }
.sel__label { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.sel__caret { display:grid; place-items:center; color:var(--fg-dim); transition:transform var(--t-fast) var(--ease-out); }
.sel.is-open .sel__caret { transform:rotate(180deg); }
.sel.is-open .sel__btn, .sel__btn:focus-visible { border-color:var(--accent); outline:none; }
@media (hover:hover) and (pointer:fine) { .sel__btn:hover { border-color:var(--line-strong); } }

.sel__list {
  position:absolute; z-index:40; left:0; top:calc(100% + 4px); min-width:100%;
  max-height:280px; overflow-y:auto; padding:4px;
  background:var(--surface-2); border:1px solid var(--line-strong); border-radius:var(--r);
  box-shadow:0 18px 40px rgba(0,0,0,.45);
}
.sel--up .sel__list { top:auto; bottom:calc(100% + 4px); }
.sel__opt {
  padding:7px 10px; border-radius:var(--r-sm); white-space:nowrap; cursor:pointer;
  color:var(--fg-muted);
}
.sel__opt.is-active { background:var(--tint); color:var(--fg); }
/* The chosen one keeps its mark when the pointer is somewhere else in the list. */
.sel__opt[aria-selected='true'] { color:var(--fg); font-weight:600; }
.sel__opt[aria-selected='true']::after { content:'·'; margin-left:8px; color:var(--accent); }
.sel--sm .sel__btn { height:30px; padding:4px 8px; font-size:13px; }
.sel--sm { width:auto; min-width:220px; }

/* Checkbox ------------------------------------------------------------------
   The native box is the operating system's blue, which is nobody's brand and
   the one colour on the screen that is not ours. */
.check input[type='checkbox'] {
  appearance:none; flex:none; width:17px; height:17px; margin:1px 0 0;
  border:1px solid var(--line-strong); border-radius:5px; background:var(--surface);
  cursor:pointer; position:relative;
  transition:background var(--t-fast) var(--ease-out), border-color var(--t-fast) var(--ease-out);
}
.check input[type='checkbox']:checked { background:var(--accent); border-color:var(--accent); }
/* Drawn, not a glyph: a tick character sits differently in every font and is
   off-centre in most of them. */
.check input[type='checkbox']:checked::after {
  content:''; position:absolute; left:5px; top:1.5px; width:4px; height:9px;
  border:solid #0f0f0f; border-width:0 2px 2px 0; transform:rotate(42deg);
}
.check input[type='checkbox']:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
.check input[type='checkbox']:disabled { opacity:.45; cursor:not-allowed; }
@media (hover:hover) and (pointer:fine) {
  .check:hover input[type='checkbox']:not(:checked) { border-color:var(--fg-dim); }
}

/* File field ----------------------------------------------------------------
   A plate that takes a drop, a click, or the button inside it. */
.drop {
  display:flex; align-items:center; gap:12px; text-align:left;
  padding:14px 14px; border:1px dashed var(--line-strong); border-radius:var(--r);
  background:var(--surface); cursor:pointer;
  transition:border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out);
}
.drop.is-over { border-color:var(--accent); background:var(--tint); border-style:solid; }
.drop[data-state='full'] { border-style:solid; }
@media (hover:hover) and (pointer:fine) { .drop:hover { border-color:var(--fg-dim); } }
.drop__icon { display:grid; place-items:center; width:38px; height:38px; flex:none;
  border-radius:var(--r-sm); background:var(--surface-2); color:var(--fg-dim); }
.drop[data-state='full'] .drop__icon { color:var(--accent); }
.drop__text { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
.drop__text b { font-size:13px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.drop__text span { font-size:11px; color:var(--fg-dim); }
.drop__actions { display:flex; gap:6px; align-items:center; flex:none; }
.drop__clear { border:0; background:transparent; color:var(--fg-dim); font:inherit; font-size:11px;
  cursor:pointer; padding:4px 6px; border-radius:var(--r-sm); }
@media (hover:hover) and (pointer:fine) { .drop__clear:hover { color:var(--err-text); background:var(--tint); } }
@media (max-width:560px) {
  .drop { flex-wrap:wrap; }
  .drop__actions { width:100%; justify-content:flex-end; }
}

/* Sign-in -------------------------------------------------------------------
   Split screen: what this is on the left, the form on the right.

   The pattern is the ordinary one for an admin sign-in, and it is ordinary
   because it answers the question a bare form cannot — which panel is this.
   On a phone the brand side goes underneath: the form is what the visit is for. */
/* The body only holds the page; the split is on the element inside it, or the
   body's own grid makes the split a column of itself. */
.signin { min-height:100vh; }
.signin__split { min-height:100vh; display:grid; grid-template-columns:1.05fr 1fr; }

.signin__brand {
  position:relative; overflow:hidden; display:flex; align-items:center;
  /* Centred in its half, not pinned to the left edge of the window: on a wide
     screen the block was flush left with the form far away across a gap. */
  justify-content:center;
  padding:clamp(28px,5vw,64px); background:var(--bg); border-right:1px solid var(--line);
}
.signin__grid {
  position:absolute; inset:0; pointer-events:none; opacity:.5;
  background-image:linear-gradient(var(--line) 1px, transparent 1px),
                   linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(ellipse 80% 70% at 50% 45%, #000 5%, transparent 76%);
}
/* Round, and behind the words rather than under the page: width and height set
   separately gave a flattened ellipse that stopped at the card's edges. */
.signin__glow {
  position:absolute; left:50%; top:50%; pointer-events:none;
  width:min(900px,120%); aspect-ratio:1; transform:translate(-50%,-50%);
  background:radial-gradient(circle at 50% 50%,
    rgba(251,130,75,.20) 0%, rgba(251,130,75,.08) 34%, transparent 66%);
  animation:signin-breathe 9s var(--ease-out, ease-in-out) infinite;
}
@keyframes signin-breathe {
  0%,100% { opacity:.85; transform:translate(-50%,-50%) scale(1); }
  50%     { opacity:1;   transform:translate(-50%,-50%) scale(1.06); }
}
@media (prefers-reduced-motion:reduce) { .signin__glow { animation:none; } }

.signin__brandinner { position:relative; display:flex; flex-direction:column; gap:clamp(20px,3vw,34px);
  max-width:440px; }
.signin__logo { display:block; opacity:.92; height:auto; }
[data-theme='light'] .signin__logo { filter:invert(1); }
.signin__eyebrow { margin:0 0 10px; font:400 9px/1 'Zen Dots',sans-serif; letter-spacing:.18em;
  text-transform:uppercase; color:var(--accent-text); }
.signin__h1 { margin:0 0 14px; font:400 clamp(26px,3.4vw,40px)/1.12 'Zen Dots',sans-serif; }
.signin__what { margin:0; color:var(--fg-muted); font-size:14px; line-height:1.65; }
.signin__what b { color:var(--fg); font-weight:600; }

.signin__list { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:8px; }
.signin__list li { position:relative; padding-left:18px; font-size:13px; color:var(--fg-muted); }
.signin__list li::before { content:''; position:absolute; left:0; top:8px; width:6px; height:6px;
  border-radius:50%; background:var(--accent); opacity:.8; }

/* The one line that stops a password being typed into the wrong door. */
.signin__not { margin:0; padding:12px 14px; border:1px dashed var(--line-strong); border-radius:var(--r);
  font-size:12px; line-height:1.6; color:var(--fg-dim); }
.signin__not span { display:block; }
.signin__not { font-weight:600; color:var(--fg-muted); }
.signin__not span { font-weight:400; color:var(--fg-dim); margin-top:3px; }

.signin__panel { display:grid; place-items:center; padding:clamp(28px,5vw,64px); background:var(--surface); }
.signin__form-wrap { width:min(360px,100%); }
.signin__title { margin:0 0 6px; font-size:21px; font-weight:600; letter-spacing:-.01em; }
.signin__lead { margin:0 0 24px; color:var(--fg-muted); font-size:13px; line-height:1.6; }
.signin__submit { width:100%; justify-content:center; min-height:42px; margin-top:4px; }
.signin__err {
  margin:0 0 12px; padding:9px 11px; border-radius:var(--r); font-size:12px;
  background:rgba(220,80,80,.12); color:var(--err-text); border:1px solid var(--err);
}
.signin__ok {
  margin:0 0 12px; padding:9px 11px; border-radius:var(--r); font-size:12px;
  background:rgba(90,180,120,.12); color:var(--ok-text, #7bd1a0); border:1px solid var(--ok, #3f7f5c);
}
.signin__forgot { display:block; margin-top:14px; padding:0; border:0; background:transparent;
  color:var(--fg-dim); font:inherit; font-size:13px; cursor:pointer; text-decoration:underline;
  text-underline-offset:3px; }
@media (hover:hover) and (pointer:fine) { .signin__forgot:hover { color:var(--fg-muted); } }
.signin__foot { margin:22px 0 0; padding-top:18px; border-top:1px solid var(--line);
  font-size:12px; color:var(--fg-dim); }
.signin__foot a { color:var(--fg-muted); margin-left:6px; }

@media (max-width:900px) {
  .signin__split { grid-template-columns:1fr; }
  /* The form first: the brand panel is context, not the reason for the visit. */
  .signin__panel { order:-1; min-height:100vh; }
  .signin__brand { border-right:0; border-top:1px solid var(--line); }
  .signin__h1 { font-size:28px; }
}

/* The eye, in a field that has one. */
.pw { position:relative; display:block; }
.pw .input { padding-right:42px; }
.pw__eye {
  position:absolute; right:4px; top:50%; transform:translateY(-50%);
  display:grid; place-items:center; width:32px; height:32px; padding:0;
  border:0; background:transparent; color:var(--fg-dim); cursor:pointer; border-radius:var(--r-sm);
}
@media (hover:hover) and (pointer:fine) { .pw__eye:hover { color:var(--fg); background:var(--tint); } }
.pw__eye:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }

/* Who is signed in ---------------------------------------------------------- */
.who { position:relative; }
.who__btn {
  display:flex; flex-direction:column; align-items:flex-end; gap:1px;
  border:0; background:transparent; color:var(--fg); font:inherit; cursor:pointer;
  padding:4px 8px; border-radius:var(--r-sm); line-height:1.25;
}
@media (hover:hover) and (pointer:fine) { .who__btn:hover { background:var(--tint); } }
.who__name { font-size:12px; font-weight:600; }
.who__role { font-size:10px; color:var(--fg-dim); letter-spacing:.04em; text-transform:uppercase; }
.who__menu {
  position:absolute; right:0; top:calc(100% + 6px); z-index:40; min-width:220px; padding:4px;
  background:var(--surface-2); border:1px solid var(--line-strong); border-radius:var(--r);
  box-shadow:0 18px 40px rgba(0,0,0,.45);
}
.who__mail { padding:8px 10px 10px; font-size:11px; color:var(--fg-dim);
  border-bottom:1px solid var(--line); margin-bottom:4px; overflow:hidden; text-overflow:ellipsis; }
.who__item {
  display:block; width:100%; text-align:left; border:0; background:transparent; color:var(--fg-muted);
  font:inherit; font-size:13px; padding:7px 10px; border-radius:var(--r-sm); cursor:pointer;
}
@media (hover:hover) and (pointer:fine) { .who__item:hover { background:var(--tint); color:var(--fg); } }
@media (max-width:720px) { .who__name { max-width:120px; overflow:hidden; text-overflow:ellipsis; } }

/* The picture on a line's card, while it is being chosen. */
.coverpic {
  display:block; width:100%; max-height:200px; object-fit:cover;
  border:1px solid var(--line); border-radius:var(--r); background:var(--surface-2);
}

/* Post editor ---------------------------------------------------------------
   A writing surface, not a form: the title and the text get the width, and
   everything a post also needs sits in a column beside them. */
.editor { display:flex; flex-direction:column; gap:16px; }
.editor__bar {
  position:sticky; top:56px; z-index:20; display:flex; align-items:center; gap:10px;
  padding:10px 12px; border:1px solid var(--line); border-radius:var(--r);
  background:var(--surface); backdrop-filter:blur(6px);
}
.editor__saved { font-size:11px; color:var(--fg-dim); }
.editor__saved[data-state='dirty'] { color:var(--accent-text); }
.editor__saved[data-state='busy'] { color:var(--fg-muted); }
.editor__grid { display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:24px; align-items:start; }
.editor__main { min-width:0; }
.editor__side { position:sticky; top:120px; display:flex; flex-direction:column; gap:2px; }

.editor__title {
  width:100%; border:0; background:transparent; color:var(--fg); resize:none; overflow:hidden;
  font:600 26px/1.25 inherit; letter-spacing:-.01em; padding:6px 0 14px;
  border-bottom:1px solid var(--line); margin-bottom:16px;
}
.editor__title:focus { outline:none; border-bottom-color:var(--line-strong); }
.editor__title::placeholder { color:var(--fg-dim); }

.blocks { display:flex; flex-direction:column; gap:6px; }
.blk { border:1px solid transparent; border-radius:var(--r); padding:4px 6px 8px; }
.blk:focus-within { border-color:var(--line); background:var(--surface); }
.blk.is-dragging { opacity:.5; background:var(--tint); }
.blk__bar { display:flex; align-items:center; gap:8px; height:24px; opacity:0; transition:opacity var(--t-fast); }
.blk:hover .blk__bar, .blk:focus-within .blk__bar { opacity:1; }
.blk__grip { border:0; background:transparent; color:var(--fg-dim); cursor:grab; padding:2px;
  border-radius:var(--r-sm); }
.blk__grip:active { cursor:grabbing; }
.blk__grip:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }
.blk__kind { font-size:10px; letter-spacing:.06em; text-transform:uppercase; color:var(--fg-dim); }
.blk__x { border:0; background:transparent; color:var(--fg-dim); font-size:16px; line-height:1;
  cursor:pointer; padding:0 4px; border-radius:var(--r-sm); }
@media (hover:hover) and (pointer:fine) { .blk__x:hover { color:var(--err-text); background:var(--tint); } }

.blk__text {
  width:100%; border:0; background:transparent; color:var(--fg); resize:none; overflow:hidden;
  font:inherit; font-size:15px; line-height:1.7; padding:2px 0; min-height:0;
}
.blk__text:focus { outline:none; }
.blk__text--h { font-size:19px; font-weight:600; line-height:1.4; }
.blk__text--quote { font-style:italic; color:var(--fg-muted); border-left:2px solid var(--accent);
  padding-left:12px; }
.blk__shot { display:block; width:100%; max-height:220px; object-fit:cover; margin-bottom:8px;
  border:1px solid var(--line); border-radius:var(--r); }

.blocks__add {
  margin-top:10px; width:100%; padding:10px; border:1px dashed var(--line-strong);
  border-radius:var(--r); background:transparent; color:var(--fg-dim); font:inherit; font-size:13px;
  cursor:pointer; transition:color var(--t-fast), border-color var(--t-fast);
}
@media (hover:hover) and (pointer:fine) {
  .blocks__add:hover { color:var(--fg); border-color:var(--fg-dim); }
}

.blockmenu {
  margin:6px 0; padding:4px; border:1px solid var(--line-strong); border-radius:var(--r);
  background:var(--surface-2); box-shadow:0 18px 40px rgba(0,0,0,.45);
  display:grid; grid-template-columns:repeat(auto-fill,minmax(180px,1fr)); gap:2px;
}
.blockmenu__item {
  display:flex; flex-direction:column; gap:2px; text-align:left; border:0; background:transparent;
  color:var(--fg-muted); font:inherit; padding:8px 10px; border-radius:var(--r-sm); cursor:pointer;
}
.blockmenu__item b { font-size:13px; color:var(--fg); font-weight:600; }
.blockmenu__item span { font-size:11px; color:var(--fg-dim); }
@media (hover:hover) and (pointer:fine) { .blockmenu__item:hover { background:var(--tint); } }

@media (max-width:1100px) {
  .editor__grid { grid-template-columns:1fr; }
  .editor__side { position:static; }
}

/* Cover picture in the editor's sidebar ------------------------------------- */
.cover__wrap { display:flex; flex-direction:column; gap:8px; }
.cover {
  display:block; width:100%; padding:0; border:1px dashed var(--line-strong); border-radius:var(--r);
  background:var(--surface); color:inherit; cursor:pointer; overflow:hidden;
  transition:border-color var(--t-fast), background var(--t-fast);
}
.cover.is-over { border-style:solid; border-color:var(--accent); background:var(--tint); }
.cover[data-state='busy'] { opacity:.6; }
@media (hover:hover) and (pointer:fine) { .cover:hover { border-color:var(--fg-dim); } }
.cover__shot { display:block; width:100%; aspect-ratio:16/10; object-fit:cover; }
.cover__empty { display:flex; flex-direction:column; gap:3px; align-items:center; justify-content:center;
  aspect-ratio:16/10; color:var(--fg-dim); }
.cover__empty b { font-size:12px; font-weight:600; color:var(--fg-muted); }
.cover__empty span { font-size:11px; }
.cover__row { display:flex; gap:6px; align-items:center; }
.cover__clear { border:0; background:transparent; color:var(--fg-dim); font:inherit; font-size:11px;
  cursor:pointer; padding:4px 6px; border-radius:var(--r-sm); }
@media (hover:hover) and (pointer:fine) {
  .cover__clear:hover { color:var(--err-text); background:var(--tint); }
}

/* Preview -------------------------------------------------------------------
   The piece as a reader gets it — and in the reader's typefaces. The panel
   ships the same two faces the website does, so the preview sets Canaro for
   the text and Zen Dots for the headings rather than the panel's UI stack. A
   preview in the wrong font tells you nothing about the line breaks, and line
   breaks are half of what a preview is for. */
.preview {
  position:fixed; inset:0; z-index:60; display:grid; place-items:start center;
  padding:32px 20px; overflow-y:auto; background:rgba(0,0,0,.6); backdrop-filter:blur(3px);
}
.preview__sheet {
  width:min(720px,100%); border:1px solid var(--line-strong); border-radius:var(--r-lg);
  background:var(--surface); box-shadow:0 30px 80px rgba(0,0,0,.5); overflow:hidden;
}
.preview__bar { display:flex; align-items:center; gap:10px; padding:10px 14px;
  border-bottom:1px solid var(--line); background:var(--surface-2); }
.preview__badge { font:400 9px/1 'Zen Dots',sans-serif; letter-spacing:.16em; text-transform:uppercase;
  color:var(--accent-text); }
.preview__meta { font-size:11px; color:var(--fg-dim); }

/* From here down it is the website's typography, not the panel's. */
.preview__article {
  font-family:'Canaro',system-ui,-apple-system,sans-serif; font-size:16px; line-height:1.6;
  color:var(--fg);
}
.preview__cover { position:relative; aspect-ratio:21/9; border-bottom:1px solid var(--line); }
.preview__cover[data-tone='light'] { background:#f2f2f2; }
.preview__cover[data-tone='dark'] { background:#0b0b0b; }
.preview__cover img { position:absolute; inset:16px; width:calc(100% - 32px); height:calc(100% - 32px);
  object-fit:contain; }
.preview__cover[data-missing] { display:grid; place-items:center; border-style:dashed;
  border:1px dashed var(--line-strong); }
.preview__nocover { font-size:12px; color:var(--fg-dim); text-align:center; padding:0 20px; }

.preview__inner { padding:30px 28px; }
.preview__metaline { margin:0 0 10px; font-size:12px; color:var(--fg-dim);
  letter-spacing:.04em; text-transform:uppercase; }
.preview__title {
  margin:0 0 12px; font-family:'Zen Dots','Canaro',sans-serif; font-weight:400;
  font-size:clamp(19px,2.6vw,25px); line-height:1.1; letter-spacing:.02em; text-transform:uppercase;
}
.preview__teaser { margin:0; color:var(--fg-muted); font-size:16px; line-height:1.6; }
.preview__body { color:var(--fg-muted); margin-top:16px; }
.preview__body > * + * { margin-top:14px; }
.preview__h { margin:26px 0 0; font-family:'Zen Dots','Canaro',sans-serif; font-weight:400;
  font-size:clamp(16px,2vw,20px); line-height:1.1; letter-spacing:.02em; text-transform:uppercase;
  color:var(--fg); }
.preview__list { display:grid; gap:6px; padding-left:18px; list-style:disc; }
.preview__quote { margin-left:0; padding-left:16px; border-left:2px solid var(--accent);
  font-size:clamp(15px,1.8vw,18px); color:var(--fg); }
.preview__figure { margin:20px 0; border:1px solid var(--line); border-radius:var(--r); overflow:hidden; }
.preview__figure img { display:block; width:100%; }
.preview__empty { color:var(--fg-dim); font-style:italic; }

/* A video is a still until it is asked for — the same rule the site follows,
   so a preview cannot be the thing that tells YouTube who is reading. */
.preview__video { position:relative; margin:20px 0; border:1px solid var(--line);
  border-radius:var(--r); overflow:hidden; background:var(--plate-dark, #0b0b0b); }
.preview__playbtn { position:relative; display:block; width:100%; aspect-ratio:16/9; padding:0;
  border:0; background:transparent; color:#0f0f0f; cursor:pointer; }
.preview__playbtn img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.preview__playbtn svg { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  width:46px; height:46px; padding:12px; border-radius:50%; background:var(--accent);
  box-shadow:0 8px 26px rgba(0,0,0,.45); }
.preview__pending { position:absolute; inset:0; display:grid; place-items:center; padding:0 20px;
  font-size:12px; color:var(--fg-dim); text-align:center; }
.preview__frame { display:block; width:100%; aspect-ratio:16/9; border:0; }

/* Calendar ------------------------------------------------------------------
   `<input type="date">` opens the operating system's own picker: unstylable,
   in the system's language, on a dark panel. */
.cal { position:relative; }
.cal__btn {
  width:100%; text-align:left; background:var(--surface); color:var(--fg); font:inherit;
  border:1px solid var(--line); border-radius:var(--r); padding:8px 11px; cursor:pointer;
  transition:border-color var(--t-fast);
}
.cal.is-open .cal__btn, .cal__btn:focus-visible { border-color:var(--accent); outline:none; }
@media (hover:hover) and (pointer:fine) { .cal__btn:hover { border-color:var(--line-strong); } }
.cal__pop {
  position:absolute; z-index:40; right:0; top:calc(100% + 4px); width:262px; padding:10px;
  background:var(--surface-2); border:1px solid var(--line-strong); border-radius:var(--r);
  box-shadow:0 18px 40px rgba(0,0,0,.45);
}
.cal__head { display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; }
.cal__month { font-size:13px; font-weight:600; }
.cal__nav { width:26px; height:26px; border:0; border-radius:var(--r-sm); background:transparent;
  color:var(--fg-muted); font-size:16px; cursor:pointer; }
@media (hover:hover) and (pointer:fine) { .cal__nav:hover { background:var(--tint); color:var(--fg); } }
.cal__grid { display:grid; grid-template-columns:repeat(7,1fr); gap:2px; }
.cal__wd { display:grid; place-items:center; height:22px; font-size:10px; color:var(--fg-dim); }
.cal__day {
  display:grid; place-items:center; height:30px; border:0; border-radius:var(--r-sm);
  background:transparent; color:var(--fg-muted); font:inherit; font-size:13px; cursor:pointer;
}
@media (hover:hover) and (pointer:fine) { .cal__day:hover { background:var(--tint); color:var(--fg); } }
.cal__day[data-today] { color:var(--accent-text); font-weight:600; }
.cal__day[data-on] { background:var(--accent); color:#0f0f0f; font-weight:600; }
.cal__day:focus-visible { outline:2px solid var(--accent); outline-offset:-2px; }
.cal__foot { display:flex; justify-content:flex-end; margin-top:8px; padding-top:8px;
  border-top:1px solid var(--line); }
.cal__today { border:0; background:transparent; color:var(--fg-dim); font:inherit; font-size:11px;
  cursor:pointer; padding:4px 6px; border-radius:var(--r-sm); }
@media (hover:hover) and (pointer:fine) { .cal__today:hover { color:var(--fg); background:var(--tint); } }

/* The cover a post cannot be published without. */
.cover.is-missing { border-color:var(--err); border-style:solid; animation:cover-nudge 500ms; }
@keyframes cover-nudge { 0%,100% { transform:translateX(0); } 25% { transform:translateX(-4px); }
  75% { transform:translateX(4px); } }
.btn[data-blocked] { opacity:.6; }

/* An image block's drop zone ------------------------------------------------ */
.imgzone { display:flex; flex-direction:column; gap:6px; }
.imgzone__drop { aspect-ratio:auto; }
.imgzone__drop .cover__shot { aspect-ratio:auto; max-height:260px; object-fit:contain;
  background:var(--surface-2); }
.imgzone__drop .cover__empty { aspect-ratio:16/6; }
.imgzone__row { display:flex; align-items:center; gap:8px; min-height:20px; }
.imgzone__note { font-size:11px; color:var(--fg-dim); }

/* Status tabs ---------------------------------------------------------------
   With counts: three drafts and one scheduled post is the state of the desk,
   and finding that out should not take a click. */
.tabs { display:flex; gap:4px; flex-wrap:wrap; margin-bottom:14px; }
.tab {
  display:flex; align-items:center; gap:7px; height:34px; padding:0 11px;
  font:inherit; font-size:13px;
  border:1px solid var(--line); border-radius:99px; background:transparent; color:var(--fg-muted);
  cursor:pointer; transition:background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
/* A whole number of pixels, and the digit centred by the box rather than by the
   line box inside it. The height used to come out of line-height — 18.5px — and
   half a pixel is exactly the kind of rounding that lands a digit one device
   pixel high on a retina screen and nowhere else. */
.tab i {
  /* 10px, not 11: at eleven the em box rounds to a half pixel and the digit
     lands 0.4px above the middle — measured, not guessed. At ten the numbers
     come out whole. */
  font-style:normal; font-size:10px; letter-spacing:.02em;
  display:block; box-sizing:border-box; min-width:18px; height:18px;
  line-height:18px; text-align:center; padding:0 5px;
  border-radius:99px; background:var(--surface-2); color:var(--fg-dim);
}
.tab[aria-pressed='true'] { background:var(--tint); border-color:var(--line-strong); color:var(--fg); }
.tab[aria-pressed='true'] i { background:var(--accent); color:#0f0f0f; }
@media (hover:hover) and (pointer:fine) { .tab:hover { border-color:var(--line-strong); color:var(--fg); } }

/* Sizes on these small boxes are not arbitrary.
   Chrome rounds a font's em box to half pixels, so a size whose 1.2em is
   fractional cannot centre exactly in a fixed-height box: 12px is off by 0.30,
   11px by 0.15, while 10px (em 12.0) and 13px (em 15.6 → 15.5) come out at
   0.00 and 0.05. Hence pills and avatars at 10px, chips and calendar days at
   13px. Measured on the bench, not guessed.

   Optical centring lived here.
   Sixty-odd rules that added 0.22em to the top of anything whose text was
   centred, because Canaro sits high in its own line box. The font's metrics are
   overridden at the top of this sheet now, so the box itself is right and every
   one of those rules was moving text that was already in the middle. Centring
   is centring again: equal padding, `align-items: center`, nothing else. */

/* A partner's mark, in the table and in its form. */
.logoshot { display:block; width:auto; max-width:150px; object-fit:contain; }
.logoshot--big { max-width:100%; margin-bottom:12px; }

/* The question being answered, quoted in its own box. */
.quotebox {
  margin: 0 0 16px; padding: 12px 14px; border-left: 2px solid var(--accent);
  background: var(--surface-2); border-radius: var(--r-sm);
  font-size: 14px; line-height: 1.6; color: var(--fg-muted); white-space: pre-wrap;
}

/* Comments -------------------------------------------------------------------
   The desk shows a conversation the way the page shows it. Anything else — a
   row per line, the thread two clicks away — turns answering the right person
   into detective work, and the reply gets written against a quote instead of
   against the conversation it belongs to. */
.cmts {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.cmt--thread {
  padding: 16px 0 0;
  border-top: 1px solid var(--line);
}
.cmt--thread:first-child {
  padding-top: 0;
  border-top: 0;
}
/* Hidden here means hidden on the site. It stays legible — this is where it is
   read back — but it should not look like it is live. */
.cmt--hidden {
  opacity: 0.62;
}

.cmt__line + .cmt__line {
  margin-top: 12px;
}
/* One level of indent and never two: past that a thread is a staircase. */
.cmt__line--reply {
  margin-left: 26px;
  padding-left: 16px;
  border-left: 2px solid var(--line);
}
.cmt__line--ours {
  border-left-color: var(--accent);
}

.cmt__head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 5px;
}
.cmt__who {
  font-size: 13px;
}
.cmt__firm,
.cmt__when {
  font-size: 11px;
  color: var(--fg-dim);
}
.cmt__text {
  margin: 0;
  font-size: 14px;
  line-height: 1.65;
  color: var(--fg-muted);
  white-space: pre-wrap;
}

/* The seal: an answer of ours is marked as ours, in the panel exactly as it is
   marked on the page, so what the desk sees and what the reader sees agree. */
.cmt__seal {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 18px;
  padding: 0 7px;
  border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent-text);
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* Which desk answered — the only other thing an answer of ours is signed with. */
.cmt__desk {
  font-size: 13px;
  color: var(--accent-text);
}

.cmt__acts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.cmt__write {
  margin: 12px 0 0 26px;
  padding: 12px 14px;
  border-left: 2px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
.cmt__write textarea {
  margin-bottom: 10px;
}

/* The blog row's own count, with a dot when something is waiting. Without the
   dot the number says how much has been said, never that anything is new. */
.cmtbtn {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cmtbtn svg {
  width: 14px;
  height: 14px;
}
.cmtbtn__n {
  font-variant-numeric: tabular-nums;
}
.cmtbtn--empty {
  opacity: 0.55;
}
.cmtbtn[data-open]::after {
  content: '';
  position: absolute;
  top: -3px;
  right: -3px;
  width: 8px;
  height: 8px;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--accent);
}

/* A message in a table cell is two lines at most: the row is a list, and the
   whole text is one click away in the drawer. */
.cell-clip {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-width: 42ch;
  font-size: 13px;
  color: var(--fg-muted);
}

/* A row whose right-hand side is a control, not a second line of text: the
   controls belong on the middle of the row, not at the top of it. The default
   .list__row aligns to the top because most rows are two lines of text beside
   a timestamp; these are not. */
.list__row--mid { align-items: center; }

/* The area is a column, not a word in front of the sentence. In front of the
   text it left the row's second line starting under the tag instead of under
   the title, so no two rows in the list lined up. */
/* Wide enough for the longest area name — "Google-Bewertung" measures 112px —
   so no tag pushes its row's title out of the column. */
.vtag { flex: none; width: 120px; }
.vline__t {
  font-size: 13px;
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A commit hash is a code, not a number: it reads better in the face the rest
   of the panel uses for identifiers. */
.stat__v--mono { font-family: var(--mono); font-size: 20px; letter-spacing: .01em; }

/* The button and the count on one line, on the list's own left edge. */
.vfoot {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
}

/* Versions --------------------------------------------------------------------
   A day is a heading, not a column: "when" is how anybody looks for a change
   they remember making. */
.daymark {
  margin: 18px 0 8px;
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.daymark:first-child { margin-top: 0; }

.diffhead {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 18px 0 8px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.diffhead:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.diffhead b { font-size: 13px; }

.diff__field { margin-bottom: 12px; }
.diff__name {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .04em;
  color: var(--fg-dim);
  margin-bottom: 7px;
}
.diff__cols { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 900px) { .diff__cols { grid-template-columns: 1fr; } }
.diff__col {
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-left-width: 2px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--fg-muted);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* Removed on the left, added on the right — the colours every diff uses, so
   nobody has to read the labels to know which side is which. */
.diff__col--old { border-left-color: var(--err); }
.diff__col--new { border-left-color: var(--ok); }
.diff__tag {
  display: block;
  margin-bottom: 4px;
  font-size: 10px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

/* Roles ----------------------------------------------------------------------
   A role card answers "what will this person be able to do?" in words. The
   matrix beside it answers "how do the four compare?" — two different
   questions, and the old screen only had the second one. */
.rolecard__h {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.rolecard__h b { font-size: 14px; }
.rolecard__p {
  margin: 0 0 12px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--fg-muted);
}
.rolecard__who {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  color: var(--fg-dim);
}

.capsum { display: flex; flex-direction: column; gap: 7px; }
.capsum__g { display: grid; grid-template-columns: 104px 1fr; gap: 10px; align-items: baseline; }
@media (max-width: 640px) { .capsum__g { grid-template-columns: 1fr; gap: 2px; } }
.capsum__t {
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.capsum__v { font-size: 12.5px; line-height: 1.5; color: var(--fg-muted); }
/* The same summary inside the drawer, where the role is chosen. */
.capsum__box {
  margin-top: -6px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent);
  border-radius: var(--r);
  background: var(--surface-2);
}
.capsum__lead {
  margin-bottom: 10px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--fg-muted);
}

/* The matrix reads in groups, and a dot is a state, not a decoration. */
.matrix__group td {
  padding-top: 16px;
  padding-bottom: 4px;
  border-top: 0;
  text-align: left;
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.matrix__on { color: var(--accent-text); text-align: center; }
.matrix__off { color: var(--fg-dim); text-align: center; }

/* A page with two subjects — the accounts, then the roles — needs a heading
   between them, and the action that belongs to what follows. */
.pagesub {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0 12px;
}
.pagesub h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
}

/* Capabilities, ticked in groups. Read before write inside each group, so the
   list answers "what will this person be able to do?" in reading order. */
.capedit { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 24px; }
@media (max-width: 720px) { .capedit { grid-template-columns: 1fr; } }
.capedit__g { display: flex; flex-direction: column; gap: 2px; }
/* .check carries a rule underneath, which is right in a single column of
   choices and wrong in four short groups side by side — it striped every line
   and made the groups read as one long table. */
.capedit .check { padding: 6px 0; border-bottom: 0; }
.capedit__t {
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

/* The person is the last column of a log line: it is what the eye returns to
   when scanning, and it should sit at the edge rather than in the middle. */
.audit__by {
  flex: none;
  min-width: 150px;
  text-align: right;
  font-size: 11px;
  color: var(--fg-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@media (max-width: 900px) { .audit__by { display: none; } }

/* The waiting queue: the number is the first thing read, so it gets a column
   of its own rather than a place inside the sentence. */
.waits__n {
  flex: none;
  width: 40px;
  font-size: 20px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  line-height: 1;
}
.waits__n[data-tone='accent'] { color: var(--accent-text); }
.waits__n[data-tone='warn'] { color: var(--warn-text); }

/* A figure that is also a way in. */
.stat--go { cursor: pointer; transition: border-color var(--t-fast) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .stat--go:hover { border-color: var(--line-strong); }
}
.stat--go:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The assistant's suggested questions: a row is a field and its removal. */
.qlist { display: flex; flex-direction: column; gap: 8px; }
.qlist__row { display: flex; align-items: center; gap: 8px; }
.qlist__row .input { flex: 1; }
