/* ==========================================================================
   Admin area — built on the same Paper tokens as the public site.
   ========================================================================== */

.admin { display: grid; grid-template-columns: 248px 1fr; min-height: 100vh; }

/* ---------- sidebar ---------- */
.admin-side {
  position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column;
  background: var(--paper-raised);
  border-right: 1px solid var(--paper-edge);
  padding: var(--space-4);
  overflow-y: auto;
}
.admin-brand { margin-bottom: var(--space-3); padding: var(--space-2); }
.admin-brand .brand-mark { width: 34px; height: 34px; }

.admin-nav { display: flex; flex-direction: column; gap: 2px; flex: 1; }
.admin-nav a {
  display: flex; align-items: center; gap: var(--space-3);
  padding: .55rem .7rem; border-radius: var(--radius);
  color: var(--ink-soft); text-decoration: none;
  font-size: .92rem; font-weight: 500;
  transition: background .15s var(--ease), color .15s var(--ease);
}
.admin-nav a:hover { background: var(--paper-sunk); color: var(--ink); }
.admin-nav a[aria-current="page"] { background: var(--accent-soft); color: var(--accent-ink); font-weight: 600; }
.admin-nav a[aria-current="page"] .icon { color: var(--accent); }
.nav-count {
  margin-left: auto; min-width: 1.4rem; padding: 0 .4rem;
  background: var(--accent); color: #fff; border-radius: var(--radius-pill);
  font-size: .74rem; font-weight: 700; text-align: center; line-height: 1.45rem;
}

/* Who is signed in, and the way out to the website: the two things somebody
   looks for without hunting, so they sit under the name of the place rather
   than at the foot of a column that scrolls. */
.side-who {
  border-block: 1px solid var(--paper-edge);
  padding-block: var(--space-2);
  margin-bottom: var(--space-4);
}
.side-visit {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2); border-radius: var(--radius);
  font-size: .84rem; font-weight: 500; text-decoration: none;
  color: var(--ink-muted);
  transition: background .15s var(--ease), color .15s var(--ease);
}
.side-visit span { flex: 1; }
.side-visit svg { flex: none; }
.side-visit:hover, .side-visit:focus-visible { background: var(--paper-sunk); color: var(--accent); }

.admin-side-foot { border-top: 1px solid var(--paper-edge); padding-top: var(--space-4); margin-top: var(--space-4); }
.admin-me { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2); border-radius: var(--radius); text-decoration: none; color: var(--ink); margin-bottom: var(--space-2); }
.admin-me:hover { background: var(--paper-sunk); color: var(--ink); }
.avatar {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent-ink);
  display: grid; place-items: center; font-weight: 700; font-size: .92rem;
}
.admin-me-name { display: block; font-size: .9rem; font-weight: 600; line-height: 1.2; }
.admin-me-role { display: block; font-size: .74rem; color: var(--ink-muted); }

/* ---------- main ---------- */
.admin-main { min-width: 0; display: flex; flex-direction: column; }
/* A thin strip across the top of every screen. On a desktop it carries only
   the live/hidden switch, on the right; the page's own title is already in
   the page head below it. On a phone it also carries the menu button and the
   title, because there is no sidebar in view. */
.admin-topbar {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-2) var(--space-6);
  background: var(--paper-raised); border-bottom: 1px solid var(--paper-edge);
  position: sticky; top: 0; z-index: 40; min-height: 2.6rem;
}
.admin-topbar > strong { display: none; }
.admin-topbar .nav-toggle { display: none; }
.admin-content { padding: var(--space-6); max-width: 1240px; width: 100%; }

.page-head { margin-bottom: var(--space-5); }
.page-head h1 { font-size: 1.6rem; margin-bottom: var(--space-1); }
.page-head p { color: var(--ink-muted); margin: 0; font-size: .95rem; }

/* ---------- stat tiles ---------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--space-4); margin-bottom: var(--space-6); }
.stat { background: var(--paper-raised); border: 1px solid var(--paper-edge); border-radius: var(--radius-lg); padding: var(--space-4); }
.stat .n { font-size: 1.9rem; font-weight: 700; line-height: 1.1; letter-spacing: -.03em; }
.stat .k { font-size: .82rem; color: var(--ink-muted); margin-top: var(--space-1); }
.stat.is-accent .n { color: var(--accent); }
.stat.is-amber  .n { color: var(--amber); }
.stat.is-green  .n { color: var(--green); }
.stat.is-red    .n { color: var(--red); }
a.stat { text-decoration: none; color: inherit; transition: border-color .15s var(--ease), box-shadow .15s var(--ease); }
a.stat:hover { border-color: var(--accent); box-shadow: var(--shadow); }

/* ---------- toolbars and filters ---------- */
.toolbar {
  display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center;
  padding: var(--space-3) var(--space-4);
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); margin-bottom: var(--space-4);
}
.toolbar input, .toolbar select { width: auto; min-width: 8rem; }
.toolbar .grow { flex: 1; min-width: 12rem; }
.toolbar-right { margin-left: auto; display: flex; gap: var(--space-2); }

.tabs { display: flex; flex-wrap: wrap; gap: var(--space-1); border-bottom: 1px solid var(--paper-edge); margin-bottom: var(--space-5); }
.tabs a {
  padding: .6rem 1rem; text-decoration: none; color: var(--ink-muted);
  font-size: .92rem; font-weight: 500;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs a:hover { color: var(--ink); }
.tabs a[aria-current="page"] { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

/* ---------- data tables ---------- */
.table-card { background: var(--paper-raised); border: 1px solid var(--paper-edge); border-radius: var(--radius-lg); overflow: hidden; }
.table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.table th {
  text-align: left; padding: var(--space-3) var(--space-4);
  background: var(--paper-sunk); border-bottom: 1px solid var(--paper-edge);
  font-size: .78rem; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--ink-muted);
  white-space: nowrap;
}
.table th a { color: inherit; text-decoration: none; }
.table th a:hover { color: var(--accent); }
.table td { padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--paper-edge); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--paper-sunk); }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.table .shrink { width: 1%; white-space: nowrap; }
.table a.row-title { font-weight: 600; color: var(--ink); text-decoration: none; }
.table a.row-title:hover { color: var(--accent); }
.table .sub { display: block; font-size: .82rem; color: var(--ink-muted); font-weight: 400; }

.empty { text-align: center; padding: var(--space-8) var(--space-4); color: var(--ink-muted); }
.empty .icon { color: var(--ink-faint); margin-bottom: var(--space-3); }
.empty h3 { color: var(--ink-soft); font-size: 1.05rem; }

.bulk-bar {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--accent-soft); border-bottom: 1px solid var(--paper-edge);
  font-size: .9rem;
}
.bulk-bar select { width: auto; }

/* ---------- form layout ---------- */
.form-grid { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--space-5); align-items: start; }
@media (max-width: 1024px) { .form-grid { grid-template-columns: 1fr; } }
.panel { background: var(--paper-raised); border: 1px solid var(--paper-edge); border-radius: var(--radius-lg); padding: var(--space-5); margin-bottom: var(--space-4); }
.panel > h2, .panel > h3 { font-size: 1.02rem; margin-bottom: var(--space-4); padding-bottom: var(--space-3); border-bottom: 1px solid var(--paper-edge); }
.panel-sticky { position: sticky; top: var(--space-5); }
.form-actions {
  display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center;
  padding-top: var(--space-4); margin-top: var(--space-4); border-top: 1px solid var(--paper-edge);
}
.form-actions .spacer { margin-left: auto; }
.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
@media (max-width: 640px) { .row-2 { grid-template-columns: 1fr; } }
/* A date and its two times: three boxes that belong together, and that stay
   together longer than an ordinary pair before they stack. */
.row-3 { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: var(--space-4); }
@media (max-width: 560px) { .row-3 { grid-template-columns: 1fr 1fr; } .row-3 > :first-child { grid-column: 1 / -1; } }

/* Each session is edited in place, so it needs a line around it or the page
   reads as one very long form. */
.date-row {
  border: 1px solid var(--paper-edge); border-radius: var(--radius);
  padding: var(--space-4); margin-bottom: var(--space-4); background: var(--paper);
}
.date-row:last-child { margin-bottom: 0; }
.date-row .between { align-items: center; gap: var(--space-4); flex-wrap: wrap; }

/* A plain HTML editor. Honest about what it is, rather than a fake page. */
.editor { font-family: var(--font-mono); font-size: .88rem; line-height: 1.6; min-height: 26rem; }
.editor-bar { display: flex; flex-wrap: wrap; gap: var(--space-1); padding: var(--space-2); background: var(--paper-sunk); border: 1px solid var(--paper-line); border-bottom: 0; border-radius: var(--radius) var(--radius) 0 0; }
.editor-bar + .editor { border-radius: 0 0 var(--radius) var(--radius); }
.editor-bar button { padding: .3rem .6rem; font-size: .8rem; font-weight: 600; background: var(--paper-raised); border: 1px solid var(--paper-line); border-radius: var(--radius-sm); cursor: pointer; color: var(--ink-soft); }
.editor-bar button:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- the rota ---------- */
.rota-list { list-style: none; padding: 0; margin: 0; }
.rota-item {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--paper-edge); border-radius: var(--radius);
  background: var(--paper-raised); margin-bottom: var(--space-2);
}
.rota-item.is-next { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.rota-item.is-paused { opacity: .6; }
.rota-pos {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: var(--paper-sunk); color: var(--ink-muted);
  display: grid; place-items: center; font-weight: 700; font-size: .84rem;
}
.rota-item.is-next .rota-pos { background: var(--accent); color: #fff; }
.rota-grip { cursor: grab; color: var(--ink-faint); }

/* ---------- timeline ---------- */
.timeline { list-style: none; padding: 0; margin: 0; position: relative; }
.timeline::before { content: ''; position: absolute; left: 9px; top: 6px; bottom: 6px; width: 2px; background: var(--paper-edge); }
.timeline li { position: relative; padding: 0 0 var(--space-4) var(--space-6); font-size: .9rem; }
.timeline li::before {
  content: ''; position: absolute; left: 4px; top: .45rem;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--paper-raised); border: 2px solid var(--accent);
}
.timeline .when { display: block; font-size: .78rem; color: var(--ink-muted); }

/* ---------- key/value list ---------- */
/* Headings inside a side panel each start a new little section, so they need
   air above them — a run of them otherwise reads as one list. */
/* A bare trash icon in a row of Saves needs to read as the one that is not
   like the others, without shouting before it is reached for. */
.btn-remove:hover, .btn-remove:focus-visible { color: var(--red); background: var(--red-soft); }

/* The backup, running. A bar rather than a spinner, because this one takes
   long enough that "how much longer" is the question being asked. */
.backup-run { margin-top: var(--space-5); }
.backup-run .bar {
  height: 8px; border-radius: var(--radius-pill); overflow: hidden;
  background: var(--paper-sunk); border: 1px solid var(--paper-edge);
}
.backup-run .bar span {
  display: block; height: 100%; width: 2%;
  background: var(--accent); border-radius: var(--radius-pill);
  transition: width .35s var(--ease);
}
.backup-run .bar span.is-bad { background: var(--red); }
.backup-run .hint { margin-top: var(--space-2); }

/* Dates somebody has booked off. A short list, then the row that adds to it —
   the two together should read as "when I am away", not as a form. */
.away-list { list-style: none; margin: var(--space-3) 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.away-list li {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: .88rem; color: var(--ink);
  background: var(--paper-sunk); border-radius: var(--radius);
  padding: .3rem .3rem .3rem .55rem;
}
.away-list li > span { flex: 1; min-width: 0; }
.away-list svg { flex: none; color: var(--ink-muted); }

.away-more { margin-top: var(--space-3); }
.away-more > summary {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font-size: .85rem; color: var(--ink-muted); cursor: pointer;
  padding: .25rem .5rem; border-radius: var(--radius); list-style: none;
  border: 1px solid transparent;
}
.away-more > summary::-webkit-details-marker { display: none; }
.away-more > summary:hover { color: var(--accent); background: var(--paper-sunk); }
.away-more[open] > summary { color: var(--ink); border-color: var(--paper-edge); margin-bottom: var(--space-2); }

.away-add {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  margin-top: var(--space-2);
}
.away-add input[type="date"] { width: auto; }
.away-add input[type="text"] { width: auto; flex: 1; min-width: 10rem; }
.away-to { font-size: .85rem; color: var(--ink-muted); }

.panel-sticky h3 { margin-top: var(--space-6); }
.panel-sticky h3:first-of-type { margin-top: var(--space-5); }

.kv { display: grid; grid-template-columns: auto 1fr; gap: var(--space-2) var(--space-4); font-size: .93rem; margin: 0; }
.kv dt { color: var(--ink-muted); white-space: nowrap; }
.kv dd { margin: 0; font-weight: 500; word-break: break-word; }

/* ---------- the sign-in screens ---------- */
.auth-page { display: grid; place-items: center; min-height: 100vh; padding: var(--space-5); }
.auth-wrap { width: 100%; max-width: 400px; }
.auth-brand { justify-content: center; margin-bottom: var(--space-5); }
.auth-card { background: var(--paper-raised); border: 1px solid var(--paper-edge); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-6); }
.auth-card h1 { font-size: 1.35rem; margin-bottom: var(--space-2); }
.auth-card > p { color: var(--ink-muted); font-size: .93rem; margin-bottom: var(--space-5); }
.auth-foot { text-align: center; margin-top: var(--space-5); font-size: .88rem; }
.auth-foot a { color: var(--ink-muted); }

/* ---------- a small bar chart, drawn with divs ---------- */
.spark { display: flex; align-items: flex-end; gap: 3px; height: 60px; margin-top: var(--space-3); }
.spark i { flex: 1; background: var(--accent-soft); border-radius: 2px 2px 0 0; min-height: 2px; position: relative; }
.spark i:hover { background: var(--accent); }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .admin { grid-template-columns: 1fr; }
  .admin-side {
    position: fixed; inset: 0 auto 0 0; width: 260px; z-index: 60;
    transform: translateX(-100%); transition: transform .25s var(--ease);
    box-shadow: var(--shadow-lg);
  }
  .admin-side.is-open { transform: none; }
  .admin-topbar { padding: var(--space-3) var(--space-4); }
  .admin-topbar > strong { display: block; }
  .admin-topbar .nav-toggle { display: grid; }
  .admin-content { padding: var(--space-4); }
  .table-scroll-wrap { overflow-x: auto; }
}

/* ---------- sortable column headings ---------- */
.table th a.is-sorted { color: var(--accent); }
.table th a .sort-asc { transform: rotate(180deg); }

/* A status that has run its course, said quietly. */
.badge-muted { color: var(--ink-muted); }

/* A shorter editor, for an area that is only ever a line or two. */
.editor-sm { min-height: 9rem; }

/* Row-level editing in a list, folded away until it is wanted. */
.row-editor { cursor: pointer; font-size: .88rem; font-weight: 600; color: var(--ink-soft); }
.row-editor:hover { color: var(--accent); }
details[open] > .row-editor { color: var(--accent); margin-bottom: var(--space-2); }

/* ---------- the import screen ---------- */
/* A table sitting directly inside a panel, rather than in its own card. */
.panel > .table { margin-top: var(--space-4); }
.panel > .table th:first-child, .panel > .table td:first-child { padding-left: 0; }
.panel > .table th:last-child,  .panel > .table td:last-child  { padding-right: 0; }
.panel > .table td .hint { display: block; margin-top: .2rem; }

.tick-list { list-style: none; margin: var(--space-3) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.tick-list li { display: flex; align-items: flex-start; gap: var(--space-3); font-size: .93rem; line-height: 1.5; }
.tick-list li .icon { flex: none; margin-top: 2px; color: var(--green); }
.tick-list.muted li .icon { color: var(--ink-faint); }

.steps { margin: var(--space-3) 0 0; padding-left: 1.3rem; display: flex; flex-direction: column; gap: var(--space-3); }
.steps li { font-size: .93rem; line-height: 1.55; }
.steps code { font-size: .85em; }

.swatch {
  display: inline-block; width: 14px; height: 14px; vertical-align: -2px;
  margin-right: .4rem; border-radius: 4px; border: 1px solid var(--paper-line);
}
.table .trunc { max-width: 26rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- the version line at the foot of the sidebar ---------- */
.side-version {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  /* The sidebar scrolls once the menu is taller than the window, which would
     leave this below the fold on a laptop. Pinned to the bottom of the
     sidebar, it is on screen whatever the height. */
  position: sticky; bottom: 0; z-index: 2;
  /* Pulled out to the sidebar's own edges so the background covers its full
     width and the menu scrolls underneath rather than showing through. */
  margin: var(--space-3) calc(var(--space-4) * -1) calc(var(--space-4) * -1);
  padding: var(--space-3) var(--space-4) var(--space-4);
  background: var(--paper-raised);
  border-top: 1px solid var(--paper-edge);
  font-size: .74rem; color: var(--ink-faint); font-variant-numeric: tabular-nums;
}
.side-version form { margin: 0; }
.side-version button {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .25rem .5rem; border-radius: var(--radius-sm); cursor: pointer;
  background: transparent; border: 1px solid transparent;
  color: var(--ink-faint); font: inherit; font-size: .74rem;
  transition: color .15s var(--ease), border-color .15s var(--ease), background .15s var(--ease);
}
.side-version button:hover { color: var(--accent); border-color: var(--paper-line); background: var(--paper-raised); }

/* ---------- the HTML editor and its live preview, side by side ---------- */
.editor-preview-toggle { margin-left: auto; }
.editor-bar .editor-preview-toggle.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }

.editor-split { display: grid; gap: var(--space-3); align-items: stretch; }
/* Two columns only where there is room for both to be worth reading. */
@media (min-width: 1080px) {
  .editor-split.is-open { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}
.editor-split .editor { margin: 0; min-height: 220px; }
/* The box keeps its square top edge under the toolbar; once the preview is
   beside it, it is a panel of its own and gets its corners back. */
.editor-bar + .editor-split .editor { border-radius: 0 0 var(--radius) var(--radius); }
.editor-bar + .editor-split.is-open .editor { border-radius: 0 0 0 var(--radius); }
@media (max-width: 1079px) {
  .editor-bar + .editor-split.is-open .editor { border-radius: 0 0 var(--radius) var(--radius); }
}

.editor-preview {
  padding: var(--space-4); overflow: auto;
  background: var(--paper); border: 1px dashed var(--paper-line); border-radius: var(--radius);
}
.editor-split.is-open .editor-preview { max-height: 60vh; }
.editor-preview .prose > :first-child { margin-top: 0; }
.editor-preview .prose > :last-child { margin-bottom: 0; }
.editor-preview video { max-width: 100%; border-radius: var(--radius); }

/* ---------- a table whose columns cannot be pushed off the screen ----------
   One long group name or a long address used to widen the whole table, which
   put the right-hand columns out of view and, because the edit form sits in a
   row of the same table, pushed half of that off too. Fixed columns keep the
   table inside the page whatever the content is; the overflowing cell is
   trimmed and its full text stays available on hover. */
.table-fixed { table-layout: fixed; width: 100%; }
.table-fixed > thead th,
.table-fixed > tbody > tr > td:not(.row-editor-cell) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The date line is short and reads better wrapped than trimmed. */
.table-fixed > tbody > tr > td:first-child { white-space: normal; }
.table-fixed .row-title, .table-fixed .badge, .table-fixed td a {
  display: inline-block; max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom;
}
/* A reason under a badge is a sentence, not a label: it wraps inside its
   column rather than being trimmed to one line the reader cannot finish. */
.table-fixed > tbody > tr > td:has(> .hint) { white-space: normal; }
.table-fixed td > .hint { display: block; margin-top: .2rem; white-space: normal; line-height: 1.35; }
/* The editor spans every column, so it is laid out as an ordinary block. */
.table-fixed .row-editor-cell { overflow: visible; white-space: normal; }
.table-fixed .row-editor-cell .row-2 { grid-template-columns: 1fr 1fr; }
/* The search box shrank once there were four things in the toolbar beside it. */
.toolbar .grow { min-width: 16rem; }
@media (max-width: 900px) { .table-fixed .row-editor-cell .row-2 { grid-template-columns: 1fr; } }

/* The module ticks on the people importer: two or three across so the whole
   set is visible at once rather than a column of six. */
.check-grid { display: grid; gap: var(--space-3); grid-template-columns: 1fr; }
@media (min-width: 720px)  { .check-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1200px) { .check-grid { grid-template-columns: repeat(3, 1fr); } }
.check-grid .check { padding: var(--space-3); border: 1px solid var(--paper-edge); border-radius: var(--radius); background: var(--paper); }
.check-grid .check:hover { border-color: var(--accent); }
.check-grid .check span { display: flex; align-items: baseline; gap: .4rem; flex-wrap: wrap; }

/* A panel that wants noticing — the site being hidden, mainly. */
.panel-warn { border-color: var(--amber); box-shadow: inset 3px 0 0 var(--amber); }

/* The strip across the top of every admin screen while the site is hidden.
   It carries its own way of switching back, so nobody has to go looking. */
.hidden-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-5); padding: var(--space-3) var(--space-4);
  background: var(--paper-raised); border: 1px solid var(--amber);
  border-left-width: 3px; border-radius: var(--radius);
  font-size: .88rem; color: var(--ink-soft);
}
.hidden-bar form { margin-left: auto; }

/* ---------- putting things in order by dragging ---------- */
/* The row being carried, the gap it will drop into, and the grip that starts
   it. The gap is what makes it read as "clicking into place": everything
   slides aside as you go, so the list always shows the outcome. */
.sortable { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.sort-row {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius); box-shadow: var(--shadow-sm);
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease);
}
.sort-row:hover { border-color: var(--paper-line); }
.sort-row.is-lifted {
  box-shadow: var(--shadow-lg); border-color: var(--accent);
  transform: scale(1.01); cursor: grabbing;
}
.sort-space {
  list-style: none; border: 1px dashed var(--accent); border-radius: var(--radius);
  background: var(--accent-soft); opacity: .55;
}
body.is-sorting { cursor: grabbing; user-select: none; }
.sort-grip {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; flex: 0 0 auto; cursor: grab;
  color: var(--ink-faint); background: none; border: 0; border-radius: var(--radius-sm);
  touch-action: none;
}
.sort-grip:hover { color: var(--accent); background: var(--paper-sunk); }
.sort-grip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; color: var(--accent); }
.sort-pos {
  min-width: 1.6rem; text-align: center; font-size: .78rem; font-weight: 600;
  color: var(--ink-faint); font-variant-numeric: tabular-nums;
}
.sort-said {
  display: inline-block; margin-left: var(--space-3); font-size: .78rem; font-weight: 600;
  color: var(--green); opacity: 0; transform: translateY(-2px);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.sort-said.is-on { opacity: 1; transform: none; }
/* The line that says a list is empty, which takes itself away as soon as
   something is dropped in — no script needed to keep it honest. */
.sort-empty {
  list-style: none;
  padding: var(--space-4); text-align: center; font-size: .84rem; color: var(--ink-faint);
  border: 1px dashed var(--paper-line); border-radius: var(--radius);
}
.sortable:has(> [data-id]) > .sort-empty { display: none; }
.sortable { min-height: 2.4rem; }
/* A group of buttons, with its own list nested inside it. */
.sort-group { padding: var(--space-4); }
.sort-group > .sort-head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-3); }
.sort-group .sortable { margin-left: var(--space-5); }

/* ---------- the live / hidden switch in the topbar ---------- */
.vis-switch { display: inline-flex; align-items: center; gap: var(--space-2); }
.vis-switch button {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .3rem .7rem .3rem .5rem; font-size: .78rem; font-weight: 600;
  border-radius: var(--radius-pill); cursor: pointer;
  border: 1px solid var(--paper-edge); background: var(--paper-raised); color: var(--ink-soft);
  transition: border-color .16s var(--ease), color .16s var(--ease), background .16s var(--ease);
}
.vis-switch button:hover { border-color: var(--accent); color: var(--accent); }
.vis-dot { width: .55rem; height: .55rem; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 3px var(--green-soft); }
.vis-switch.is-hidden button { border-color: var(--amber); color: var(--amber); background: var(--amber-soft); }
.vis-switch.is-hidden .vis-dot { background: var(--amber); box-shadow: 0 0 0 3px rgba(168,106,26,.18); }
@media (max-width: 900px) { .vis-switch .vis-word { display: none; } }


/* ---------- diagnostics ---------- */
/* A trail of what really happened: kept monospaced so timings line up, and
   scrolling inside itself rather than stretching the page. */
.diag-trail {
  margin: 0; padding: var(--space-4);
  background: var(--paper-sunk); border: 1px solid var(--paper-line); border-radius: var(--radius);
  font-family: var(--font-mono); font-size: .82rem; line-height: 1.7;
  white-space: pre-wrap; word-break: break-word; overflow-x: auto; max-height: 32rem; overflow-y: auto;
}
.diag-report { min-height: 20rem; font-size: .8rem; }


/* ---------- choosing a picture ---------- */
/* The preview sits beside the buttons so it is obvious what is currently set
   and what pressing a button will change. */
/* The same field appears in a wide form and in the narrow sidebar of the post
   editor. Wrapping on a minimum width means it sits side by side where there
   is room and stacks where there is not, without guessing at viewport sizes —
   the sidebar is narrow at every viewport. */
.image-field-row { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-start; }
.image-field-preview {
  flex: none; width: 132px; height: 132px; display: grid; place-items: center;
  background: var(--paper-sunk); border: 1px solid var(--paper-line);
  border-radius: var(--radius); overflow: hidden;
}
.image-field-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.image-field-empty { font-size: .78rem; color: var(--ink-faint); text-align: center; padding: 0 .5rem; }
.image-field-controls { flex: 1 1 13rem; min-width: 0; }
.image-field-buttons { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }

.image-field-status { margin: 0 0 var(--space-2); font-size: .82rem; }
.image-field-status.is-busy { color: var(--ink-muted); }
.image-field-status.is-good { color: var(--green); }
.image-field-status.is-bad  { color: var(--amber); }

/* The address box is kept, folded away: it is still the field that submits,
   so anyone who would rather paste a path can, and the form still works with
   no JavaScript at all. */
.image-field-address summary {
  cursor: pointer; font-size: .8rem; color: var(--ink-muted);
  padding: .2rem 0; user-select: none;
}
.image-field-address summary:hover { color: var(--accent); }
.image-field-address input { margin-top: var(--space-2); }

.image-library {
  margin-top: var(--space-4); padding: var(--space-4);
  background: var(--paper-sunk); border: 1px solid var(--paper-line); border-radius: var(--radius);
}
.image-library-head { display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-3); }
/* In the post editor this panel sits in a narrow sidebar, where "Close" was
   breaking across two lines. */
.image-library-head .btn { white-space: nowrap; }
.image-library-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  gap: var(--space-2); max-height: 22rem; overflow-y: auto;
}
.image-library-item {
  padding: 0; border: 2px solid transparent; border-radius: var(--radius);
  background: var(--paper); cursor: pointer; overflow: hidden; aspect-ratio: 1 / 1;
}
.image-library-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.image-library-item:hover, .image-library-item:focus-visible { border-color: var(--accent); }

.image-field-row > .image-field-preview:only-child,
.image-field-row.is-stacked .image-field-preview { width: 100%; }

@media (max-width: 620px) {
  .image-field-preview { width: 100%; height: 180px; }
}

/* ---------------------------------------------------------------------------
   The home page films and pictures.

   A row shows enough to recognise the item without opening it — a thumbnail,
   its name, what kind it is, and whether it is showing — because the common
   job here is reordering and hiding, not editing. The form is behind a
   disclosure so the list stays a list.
   --------------------------------------------------------------------------- */
.mediarow-thumb {
  flex: 0 0 auto; width: 3.4rem; height: 2.15rem; border-radius: var(--radius-sm);
  background: var(--paper-sunk) center/cover no-repeat;
  border: 1px solid var(--paper-edge);
  display: grid; place-items: center; color: var(--ink-faint);
}
.mediarow-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mediarow-edit { margin-top: var(--space-3); }
.mediarow-edit[open] { padding-top: var(--space-3); border-top: 1px solid var(--paper-edge); }
.mediarow-edit > summary { list-style: none; }
.mediarow-edit > summary::-webkit-details-marker { display: none; }

/* ---------------------------------------------------------------------------
   Page sections: the list, the "add a section" menu, and repeating rows.

   The list is deliberately a summary rather than a set of forms. The job on
   this screen is ordering and hiding; editing happens one section at a time,
   where there is room to see what you are doing.
   --------------------------------------------------------------------------- */
.block-row.is-off { opacity: .6; }
.block-row .sort-head { flex-wrap: wrap; }
.block-icon { flex: 0 0 auto; display: grid; place-items: center; color: var(--ink-muted); }
.block-name { flex: 0 0 auto; }
.block-summary { flex: 1 1 8rem; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.block-actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-2); }

/* The add menu. A <details> rather than a script, so it opens with the keyboard
   and works before any JavaScript has run. */
.add-block { position: relative; }
.add-block > summary { list-style: none; cursor: pointer; }
.add-block > summary::-webkit-details-marker { display: none; }
.add-block-menu {
  position: absolute; right: 0; z-index: 30; margin-top: var(--space-2);
  width: min(26rem, calc(100vw - 2rem)); max-height: 70vh; overflow-y: auto;
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: var(--space-3);
}
.add-block-group {
  margin: var(--space-3) var(--space-2) var(--space-2);
  font-size: .75rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-muted);
}
.add-block-group:first-child { margin-top: var(--space-1); }
.add-block-item {
  display: flex; gap: var(--space-3); width: 100%; text-align: left;
  padding: var(--space-3); border: 0; border-radius: var(--radius);
  background: transparent; cursor: pointer; color: inherit; font: inherit;
  align-items: flex-start;
}
.add-block-item:hover, .add-block-item:focus-visible { background: var(--paper-sunk); }
.add-block-item svg { flex: 0 0 auto; margin-top: .15rem; color: var(--accent); }
.add-block-item strong { display: block; font-size: .95rem; }
.add-block-item .sub { display: block; font-size: .84rem; color: var(--ink-muted); white-space: normal; }

/* Repeating rows inside a section. */
.repeater-row {
  border: 1px solid var(--paper-edge); border-radius: var(--radius);
  padding: var(--space-4); margin-bottom: var(--space-3);
  background: var(--paper-sunk);
}
.repeater-head {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-3); padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--paper-edge);
}
.repeater-num {
  display: grid; place-items: center; width: 1.6rem; height: 1.6rem;
  border-radius: 50%; background: var(--paper-raised); border: 1px solid var(--paper-edge);
  font-size: .8rem; font-weight: 600; font-variant-numeric: tabular-nums;
}
.repeater-head .btn-remove { margin-left: auto; }
/* The last field in a row has nothing after it, so its margin is dead space. */
.repeater-row > .field:last-child { margin-bottom: 0; }

.revert-blocks { margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--paper-edge); }
.revert-blocks > summary { list-style: none; cursor: pointer; }
.revert-blocks > summary::-webkit-details-marker { display: none; }

/* A slider with its value beside it, and a button to put it back.
   The number matters as much as the slider: a slider alone never tells you
   what you have chosen, and the number is what gets read back over the phone. */
.range-field { display: flex; align-items: center; gap: var(--space-3); }
.range-field input[type="range"] { flex: 1 1 auto; min-width: 0; accent-color: var(--accent); }
.range-value {
  flex: 0 0 auto; min-width: 3.4rem; text-align: right;
  font-variant-numeric: tabular-nums; font-weight: 600; font-size: .9rem;
}
.range-field [data-range-reset] { flex: 0 0 auto; padding: .3rem .5rem; }

/* Typing in the preview.

   Every run of words is its own little editable, so the tags around them
   cannot be reached from here. The hover outline is what tells you which
   piece you are about to change — without it, a contenteditable region is
   invisible until you have already clicked into it. */
.editor-preview-hint {
  margin: 0 0 var(--space-4); padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--paper-edge);
  font-size: .82rem; color: var(--ink-muted);
}
.ed-text {
  border-radius: 3px;
  outline: 1px dashed transparent;
  outline-offset: 2px;
  transition: background .12s var(--ease), outline-color .12s var(--ease);
}
.ed-text:hover { background: var(--accent-soft); outline-color: var(--accent); cursor: text; }
.ed-text:focus {
  background: var(--accent-soft); outline: 2px solid var(--accent); outline-offset: 2px;
}
/* An empty run still needs somewhere to click, or deleting every word in a
   heading leaves nothing to put them back into. */
.ed-text:empty::before {
  content: 'empty'; color: var(--ink-faint); font-style: italic; font-size: .85em;
}
