
:root {
  color-scheme: light;
  --surface:#fcfcfb; --plane:#f9f9f7; --ink:#0b0b0b; --ink-2:#52514e; --muted:#898781;
  --line:#e1e0d9; --ring:rgba(11,11,11,.10); --accent:#2a78d6;
  --ok:#0ca30c; --warn:#fab219; --bad:#d03b3b;
  --scrim:rgba(11,11,11,.34);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark;
    --surface:#1a1a19; --plane:#0d0d0d; --ink:#fff; --ink-2:#c3c2b7; --muted:#898781;
    --line:#2c2c2a; --ring:rgba(255,255,255,.10); --accent:#3987e5; --scrim:rgba(0,0,0,.55); }
}
:root[data-theme="dark"] { color-scheme: dark;
  --surface:#1a1a19; --plane:#0d0d0d; --ink:#fff; --ink-2:#c3c2b7; --muted:#898781;
  --line:#2c2c2a; --ring:rgba(255,255,255,.10); --accent:#3987e5; --scrim:rgba(0,0,0,.55); }

* { box-sizing:border-box; }
body { margin:0; background:var(--plane); color:var(--ink);
  font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif; -webkit-font-smoothing:antialiased; }
a { color:var(--accent); }

/* Three columns, so the title is centred on the page rather than in whatever
   space the two ends happen to leave. 1fr either side does that even when the
   right-hand group is wider than the left. */
.top { display:grid; grid-template-columns:minmax(0,1fr) auto minmax(0,1fr); align-items:center; gap:10px;
  padding:9px 14px; border-bottom:1px solid var(--line);
  background:var(--surface); position:sticky; top:0; z-index:20; font-size:14px; }
.top .l { display:flex; align-items:center; gap:8px; }
.top .r { display:flex; align-items:center; gap:8px; justify-content:flex-end; min-width:0; }
.brand { display:flex; align-items:center; gap:9px; font-weight:650; color:var(--ink);
  font-size:15px; text-decoration:none; }
/* The mark is line art on white, so in dark mode it needs its own light plate
   rather than being inverted — inverting would make the drawing a negative of
   itself, which is a different picture. */
.brand img { width:22px; height:22px; border-radius:5px; display:block; background:#fff;
  border:1px solid var(--ring); }
.iconbtn { width:34px; height:34px; display:grid; place-items:center; padding:0;
  border:1px solid var(--ring); border-radius:9px; background:transparent; color:var(--ink-2); cursor:pointer; }
.iconbtn:hover { color:var(--ink); border-color:var(--line); }
.iconbtn svg { display:block; }
.avatar { width:34px; height:34px; border-radius:50%; border:1px solid var(--ring); background:var(--accent);
  color:#fff; font-size:12.5px; font-weight:650; display:grid; place-items:center; cursor:pointer; padding:0; }

/* The trail gives way from the middle on a narrow screen, so the page you are
   on stays readable and the ancestors are what disappear.
   Left-aligned at the top of the page rather than centred in the header: it
   belongs to the page it describes, and a centred trail moves the current page
   sideways whenever an ancestor's name gets longer. */
.crumbs { display:flex; align-items:center; gap:7px; min-width:0; overflow:hidden;
  margin:0 0 14px; }
.crumbs a { color:var(--ink-2); text-decoration:none; white-space:nowrap; text-transform:uppercase;
  letter-spacing:.05em; font-size:11.5px; font-weight:600; overflow:hidden; text-overflow:ellipsis; }
.crumbs a:last-child { color:var(--ink); text-transform:none; letter-spacing:0; font-size:15px; font-weight:650; }
.crumbs a:hover { color:var(--ink); }
.crumbs .sep { color:var(--muted); flex:none; font-size:12px; }
@media (max-width:520px) { .crumbs a:not(:last-child):not(:first-child), .crumbs .sep:nth-of-type(n+2) { display:none; } }

.scrim { position:fixed; inset:0; background:var(--scrim); z-index:25; }
.scrim[hidden] { display:none; }
.drawer { position:fixed; top:0; left:0; bottom:0; width:246px; background:var(--surface);
  border-right:1px solid var(--line); padding:10px; z-index:30; overflow-y:auto; }
.drawer[hidden], .menu[hidden] { display:none; }
.drawer .hd, .menu .hd { font-size:11.5px; text-transform:uppercase; letter-spacing:.07em;
  color:var(--muted); padding:8px 10px 6px; }
.drawer a { display:flex; align-items:center; gap:10px; padding:9px 10px; border-radius:8px;
  color:var(--ink); font-size:14.5px; text-decoration:none; }
.drawer a.on { background:color-mix(in srgb,var(--accent) 12%,transparent); color:var(--accent); font-weight:600; }
.drawer a:hover:not(.on) { background:color-mix(in srgb,var(--ink) 6%,transparent); }
.menu { position:fixed; top:52px; right:12px; width:242px; background:var(--surface);
  border:1px solid var(--line); border-radius:11px; padding:6px; z-index:30;
  box-shadow:0 12px 30px rgba(0,0,0,.16); }
.menu .who2 { padding:9px 11px 10px; border-bottom:1px solid var(--line); margin-bottom:5px; }
.menu .who2 b { display:block; font-size:14px; overflow-wrap:anywhere; }
.menu .who2 span { color:var(--muted); font-size:12.5px; }
.menu a, .menu button { display:block; width:100%; text-align:left; padding:8px 11px; border-radius:7px;
  color:var(--ink); font-size:14px; background:none; border:0; cursor:pointer; font:inherit;
  text-decoration:none; margin:0; }
.menu a:hover, .menu button:hover { background:color-mix(in srgb,var(--ink) 6%,transparent); }
.menu hr { border:0; border-top:1px solid var(--line); margin:5px 0; }

main { margin:0 auto; }
main.wide { max-width:900px; padding:22px 16px 80px; }
/* The editor: the toolbar and the frame, and the frame takes what is left of
   the window so the page scrolls inside it rather than the screen scrolling. */
main.full { max-width:none; padding:14px 16px 20px; }
.edbar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:8px 0 10px; }
.edbar .tools { display:flex; gap:4px; flex-wrap:wrap; }
.edbar .tools button { min-width:34px; }
.edbar .js-state { flex:1; min-width:12em; }
.edbar .js-state.ok { color:var(--ok); }
.edbar .js-state.bad { color:var(--bad); }
.edbar .saves { display:flex; gap:6px; }
/* White whatever the theme: the page in the frame has its own colours, and a
   page that sets none expects the white a browser would give it. */
.edframe { display:block; width:100%; height:calc(100vh - 190px); min-height:320px;
  border:1px solid var(--ring); border-radius:10px; background:#fff; }
fieldset.sitepick { border:1px solid var(--ring); border-radius:8px; margin:14px 0 0; padding:6px 12px 10px;
  max-height:180px; overflow-y:auto; }
fieldset.sitepick legend { font-size:13px; color:var(--ink-2); padding:0 4px; }
fieldset.sitepick label.check { margin-top:6px; }
main.narrow { max-width:440px; min-height:100vh; display:flex; flex-direction:column;
  justify-content:center; padding:24px; }

h1 { font-size:22px; margin:0 0 4px; letter-spacing:-.015em; }
h2 { font-size:16px; margin:0 0 14px; }
h3 { font-size:11.5px; margin:26px 0 8px; color:var(--muted); text-transform:uppercase;
  letter-spacing:.07em; font-weight:600; display:flex; align-items:center; gap:8px; }
.sub { color:var(--ink-2); font-size:14px; margin:0 0 20px; }
.muted { color:var(--muted); font-size:13.5px; }
.small { font-size:12.5px; }
code { font:12.5px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace; background:var(--plane);
  border:1px solid var(--ring); border-radius:5px; padding:1px 5px; word-break:break-all; }

/* A secret to be copied: wrapped rather than scrolled, because a token half
   off the edge of a box is one that gets half selected. */
pre.tok { font:12.5px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace; background:var(--plane);
  border:1px solid var(--ring); border-radius:8px; padding:10px 12px; margin:6px 0 14px;
  white-space:pre-wrap; word-break:break-all; user-select:all; }

.card { background:var(--surface); border:1px solid var(--ring); border-radius:12px;
  padding:16px 18px; margin-bottom:12px; }
label { display:block; font-size:13px; color:var(--ink-2); margin:14px 0 0; }
label:first-of-type { margin-top:0; }
input, select { width:100%; margin-top:5px; font:inherit; padding:9px 11px;
  border-radius:8px; border:1px solid var(--ring); background:var(--plane); color:var(--ink); }
/* 16px on anything you can type into, and it is not a style choice.
   iOS Safari zooms the page when a focused field's text is under 16px and does
   not zoom back out, so the body's 15px was enough to make every form on a
   phone jump. The other fix, maximum-scale=1 in the viewport meta, works by
   taking pinch-zoom away from everybody -- a far worse trade than one pixel.
   A select counts, and so will a textarea before one exists.

   **After the rule above, deliberately.** That one sets font:inherit, and the
   shorthand resets font-size along with everything else -- so this declared
   before it would be silently overridden by the body's 15px, which is the whole
   bug it exists to fix.

   No backticks anywhere in this string: it is a template literal, and one would
   end it. */
input, select, textarea { font-size:16px; }
input:focus-visible, select:focus-visible { outline:2px solid var(--accent); outline-offset:1px; }

/* A checkbox reads as a row, not as a field with a caption above it. */
label.check { display:flex; align-items:center; gap:9px; font-size:14px; color:var(--ink);
  margin-top:14px; }
label.check input { width:18px; height:18px; margin:0; flex:none; }
/* The field a ticked checkbox has made irrelevant. */
label.off { opacity:.45; }
.row .meta .gone { color:var(--bad); font-weight:600; }
button, .btn { font:inherit; font-size:13.5px; padding:7px 14px; border-radius:8px; margin-top:0;
  border:1px solid var(--ring); background:var(--surface); color:var(--ink); cursor:pointer;
  text-decoration:none; display:inline-block; }
button:hover, .btn:hover { border-color:var(--muted); }
button.primary { background:var(--ink); color:var(--plane); border-color:var(--ink); font-weight:550; }
button.ghost { font-size:12.5px; padding:5px 10px; color:var(--ink-2); }
button.danger { color:var(--bad); }
button:disabled { opacity:.45; cursor:not-allowed; }
form button[type=submit] { margin-top:16px; }

.notice { border-radius:9px; padding:10px 13px; margin:0 0 14px; font-size:13.5px;
  border:1px solid var(--ring); background:var(--surface); }
.notice.ok { border-color:var(--ok); }
.notice.bad { border-color:var(--bad); }
.err { color:var(--bad); font-size:13px; margin:10px 0 0; }

.rows { border:1px solid var(--ring); border-radius:12px; overflow:hidden; background:var(--surface); }
.row { display:flex; align-items:center; gap:10px; padding:11px 14px; border-top:1px solid var(--line); }
.row:first-child { border-top:0; }
.row .grow { flex:1; min-width:0; }
.row .name { font-weight:550; }
.row .meta { color:var(--muted); font-size:12.5px; }
.empty { padding:20px 14px; color:var(--muted); font-size:13.5px; text-align:center; }

/* A whole card that opens something. The link covers the row rather than
   wrapping it, so the row can still hold its own buttons without nesting a link
   inside a link — which is invalid and behaves differently in every browser. */
.rows.clickable .row { position:relative; }
.rows.clickable .row:hover { background:color-mix(in srgb,var(--ink) 4%,transparent); }
.cover { position:absolute; inset:0; z-index:1; }
.rows.clickable .row > *:not(.cover) { position:relative; z-index:2; pointer-events:none; }
.chev { color:var(--muted); flex:none; }

.tag { font-size:11px; padding:2px 8px; border-radius:999px; border:1px solid var(--ring);
  color:var(--ink-2); white-space:nowrap; line-height:1.5; flex:none; }
.tag.live, .tag.ok { border-color:var(--ok); color:var(--ok); }
.tag.draft, .tag.warn, .tag.locked { border-color:var(--warn); color:var(--warn); }
.tag.bad { border-color:var(--bad); color:var(--bad); }
.tag.muted { color:var(--muted); }

/* The pills under a hostname: DNS and SSL. Buttons, because they open
   something, and sized so both plus the name fit a phone. */
.pills { display:flex; gap:6px; margin-top:5px; flex-wrap:wrap; }
.pill { font:inherit; font-size:10.5px; font-weight:600; letter-spacing:.04em; text-transform:uppercase;
  padding:2px 9px; border-radius:999px; border:1px solid var(--ring); background:transparent;
  color:var(--muted); cursor:pointer; margin:0; line-height:1.7; }
.pill.ok { border-color:var(--ok); color:var(--ok); }
.pill.bad { border-color:var(--bad); color:var(--bad); }
/* Working on it. Blue and breathing, so "not answered yet" never reads as
   "answered no" — which is the mistake a static grey pill invites. */
.pill.busy { border-color:var(--accent); color:var(--accent); animation:pulse 1.1s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity:1 } 50% { opacity:.35 } }

/* Dismissed by clicking anywhere, which the script does by listening on the
   document — so this needs no close button and no scrim of its own. */
.pop { position:absolute; z-index:40; max-width:min(340px,calc(100vw - 28px));
  background:var(--surface); border:1px solid var(--line); border-radius:10px;
  padding:11px 13px; box-shadow:0 12px 30px rgba(0,0,0,.18); font-size:13px; line-height:1.5; }
.pop b { display:block; font-size:11px; text-transform:uppercase; letter-spacing:.06em;
  color:var(--muted); margin-bottom:5px; }
.pop .act { margin-top:8px; padding-top:8px; border-top:1px solid var(--line); color:var(--ink-2); }

.host { display:flex; align-items:center; gap:8px; min-width:0; }
.host .name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:14px; }

/* One line per page, on a phone too: the path takes the room and everything
   else is fixed width and never wraps. */
.pagerow { display:flex; align-items:center; gap:8px; min-width:0; width:100%; }
.pagerow .path { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:13.5px; }
.pagerow .acts { display:flex; gap:6px; flex:none; align-items:center; }

/* The checkbox on a page row, and the bar that acts on a selection of them.
   The box is given a hit area rather than left at its intrinsic size: this list
   is read on a phone, where a bare checkbox is the smallest thing on the screen
   and sits next to a Delete button. */
.pick { display:flex; align-items:center; flex:none; cursor:pointer; padding:4px; margin:-4px; }
.pick input { width:16px; height:16px; margin:0; cursor:pointer; }
.bulkbar { display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:8px 14px; border-bottom:1px solid var(--line); flex-wrap:wrap; }
.bulkbar .pick { gap:8px; font-size:12.5px; color:var(--muted); }
.bulkbar .acts { display:flex; gap:6px; }
/* Disabled rather than hidden. A control that appears when a box is ticked
   moves the buttons under the pointer as they are being reached for, and the
   count beside them is the thing that says why they are inert. */
.bulkbar button[disabled] { opacity:.45; cursor:default; }

@media (max-width:520px) {
  .pagerow .acts button, .pagerow .acts .btn { font-size:11px; padding:3px 7px; }
  .bulkbar { padding:8px 12px; }
  .row { padding:10px 12px; gap:8px; }
  main.wide { padding:18px 12px 70px; }
}

/* A section that starts closed. <details> rather than a script-driven toggle:
   it works without JavaScript, keeps its own state, and needs no attribute. */
/* The row of buttons under a list. Its own class rather than a paragraph with a
   margin, because a button inside a <p class="muted small"> inherits the size
   of prose and reads as a footnote. */
.actions { display:flex; gap:8px; flex-wrap:wrap; margin-top:12px; }
.card.spaced { margin-top:12px; }

details.sect { margin-top:22px; }
details.sect > summary { list-style:none; cursor:pointer; }
details.sect > summary::-webkit-details-marker { display:none; }
details.sect > summary h3 { margin:0 0 8px; }
details.sect > summary h3::after { content:"\25b8"; color:var(--muted); font-size:9px; }
details.sect[open] > summary h3::after { content:"\25be"; }

.drop { border:1.5px dashed var(--ring); border-radius:12px; padding:22px 16px; text-align:center;
  color:var(--ink-2); background:var(--surface); transition:border-color .12s, background .12s; }
.drop.over { border-color:var(--accent); background:var(--plane); }
.drop input[type=file] { display:none; }
.queue { margin-top:10px; font-size:13px; }
.queue div { display:flex; gap:10px; padding:4px 0; border-top:1px solid var(--line); }
.queue div:first-child { border-top:0; }
.queue .ok { color:var(--ok); }
.queue .bad { color:var(--bad); }

.modal { border:1px solid var(--line); border-radius:14px; padding:20px 22px 22px;
  width:min(420px,calc(100vw - 28px)); background:var(--surface); color:var(--ink);
  box-shadow:0 24px 60px rgba(0,0,0,.28); position:relative; }
.modal::backdrop { background:var(--scrim); }
.modal .x { position:absolute; top:8px; right:10px; margin:0; }
.modal .x button { border:0; background:none; color:var(--muted); font-size:15px; padding:4px 6px; margin:0; }
.modal h2 { margin:0 0 14px; }

.alt { text-align:center; margin-top:2px; }
[hidden] { display:none !important; }
