/* ============================================================================
   JustAudit admin, layered on top of style.css, which supplies every token.

   Same identity, different job. The customer pages are airy because they are being read;
   this is a working register that gets scanned, so it stays dense where it must (the
   licence list) and breathes everywhere else (the cards, the sections, the dialog).

   What changed in this pass — the panel reads as one thing with motion, not as four
   stacked sub-pages:
   • the counter strip is its own row of elevated stat cards, not a wall of numbers;
   • the header is a glass band that fades the content under it;
   • every block enters with a soft rise-and-fade, staggered, so a page load reads as a
     single sweep rather than a static sheet;
   • the dialog is a proper sheet: frosted backdrop, spring entrance, and a two-column
     body that is divided into named, separate sections instead of one crowded grid.

   Two things hold regardless of the polish:
   • The licence list is a real <table> inside .ledger-wrap. Nothing about a row expands
     in place, every action lives in that licence's own <dialog>, so the register never
     resizes under the cursor.
   • The header inverts the palette (navy ground, paper text). Every tint on it is mixed
     from --navy-ink, never hardcoded white: in dark mode --navy is the light colour, and
     a white placeholder on a pale bar is invisible.

   Motion is a preference, not a requirement. Every animation is CSS-only and off under
   prefers-reduced-motion, and nothing depends on it to be usable.
   ============================================================================ */

/* ── A thin top rule so the page never looks like it starts mid-air ─────── */
body { background: var(--canvas); color: var(--ink); }

:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; border-radius: 2px; }

/* ── Header ───────────────────────────────────────────────────────────────
   Sticky glass band on navy. The brand sits left, the search scopes the register, the
   nav trails. On a phone the sequence stacks with the search full-width. */
.admin-bar {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--navy-2) 88%, transparent);
  -webkit-backdrop-filter: blur(10px) saturate(1.15);
  backdrop-filter: blur(10px) saturate(1.15);
  color: color-mix(in srgb, var(--navy-ink) 84%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--oxide) 42%, transparent);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--navy-ink) 8%, transparent), var(--lift-1);
  padding: 12px 18px;
  display: flex; align-items: center; gap: 12px 20px; flex-wrap: wrap;
}
@media (min-width: 980px) { .admin-bar { padding-inline: 28px; flex-wrap: nowrap; } }

.admin-brand {
  display: inline-flex; align-items: center; gap: 11px; margin-right: auto;
  color: var(--navy-ink); text-decoration: none;
}
.admin-brand .logo { width: 27px; height: 27px; display: block; transition: transform var(--t); }
.admin-brand:hover .logo { transform: rotate(-4deg); }
.admin-brand b {
  font: 700 19px/1 var(--serif); font-variation-settings: "opsz" 30; letter-spacing: -.015em;
}
.admin-brand em {
  font: 500 11px/1 var(--sans); font-style: normal; letter-spacing: .12em;
  text-transform: uppercase; opacity: .62;
  border-left: 1px solid color-mix(in srgb, var(--navy-ink) 26%, transparent);
  padding-left: 11px; margin-left: 2px;
}

.admin-nav { display: flex; gap: 2px; flex-wrap: wrap; order: 3; }
@media (min-width: 980px) { .admin-nav { order: 3; flex-wrap: nowrap; } }
.admin-bar a:not(.admin-brand) {
  color: inherit; text-decoration: none; white-space: nowrap;
  font-size: 13px; font-weight: 500; padding: 8px 12px; border-radius: var(--r);
  transition: color var(--t), background var(--t), transform var(--t);
}
.admin-bar a:not(.admin-brand):hover {
  color: var(--navy-ink); background: color-mix(in srgb, var(--navy-ink) 12%, transparent);
  transform: translateY(-1px);
}

.admin-search { display: flex; gap: 7px; align-items: center; order: 2; flex: 1 1 260px; }
@media (min-width: 980px) { .admin-search { flex: 0 1 400px; margin-left: auto; } }
.admin-search input[type=search] {
  flex: 1 1 auto; min-width: 0; padding: 10px 14px; font-size: 14.5px;
  color: var(--navy-ink);
  background: color-mix(in srgb, var(--navy-ink) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--navy-ink) 22%, transparent);
  border-radius: var(--r);
  transition: background var(--t), border-color var(--t), box-shadow var(--t);
}
.admin-search input[type=search]::placeholder { color: color-mix(in srgb, var(--navy-ink) 52%, transparent); }
.admin-search input[type=search]:focus {
  background: color-mix(in srgb, var(--navy-ink) 15%, transparent);
  border-color: color-mix(in srgb, var(--navy-ink) 55%, transparent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--navy-ink) 18%, transparent);
}
.admin-search button {
  padding: 10px 16px; white-space: nowrap; border-radius: var(--r);
  font: 600 13px var(--sans); color: var(--navy-ink);
  border: 1px solid color-mix(in srgb, var(--navy-ink) 30%, transparent);
  background: color-mix(in srgb, var(--navy-ink) 6%, transparent);
  transition: background var(--t), transform var(--t);
}
.admin-search button:hover { background: color-mix(in srgb, var(--navy-ink) 14%, transparent); transform: translateY(-1px); }

/* ── Page frame ────────────────────────────────────────────────────────────
   style.css already sizes .wrap (720px — a form reads well narrow) and .wrap-wide
   (1200px). This only adds the vertical breathing room the panel needs; the widths stay
   the site's. tiers.php and manual.php carry their own inline padding on .wrap. */
.wrap-wide { padding-top: 22px; padding-bottom: 64px; }

/* An in-page title, so a page is introduced rather than just begins. */
.panel-head, .page-title {
  margin: 4px 0 6px; font: 700 22px/1.2 var(--serif);
  font-variation-settings: "opsz" 34; letter-spacing: -.015em; color: var(--ink);
}
.page-sub { margin: 0 0 22px; color: var(--ink-3); font-size: 14px; }

/* A section divider that sits above a sub-block (the register), smaller than the page title
   and carrying a muted count, so a long page reads as chapters rather than one sheet. */
.ledger-title {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin: 26px 0 12px; font: 700 17px/1.2 var(--serif);
  font-variation-settings: "opsz" 28; letter-spacing: -.01em; color: var(--ink);
}

/* ── Notices ─────────────────────────────────────────────────────────────── */
.note {
  background: var(--surface-2); border: 1px solid var(--rule); border-radius: var(--r);
  padding: 12px 15px; margin: 14px 0 18px; font-size: 13.5px; line-height: 1.5;
  border-left: 3px solid var(--navy);
}
.note-ok    { border-left-color: var(--ok);  background: color-mix(in srgb, var(--ok) 9%, var(--surface)); }
.note-err   { border-left-color: var(--bad); background: color-mix(in srgb, var(--bad) 9%, var(--surface)); }
.note-warn  { border-left-color: var(--warn); background: color-mix(in srgb, var(--warn) 9%, var(--surface)); }

/* ── The counter strip ──────────────────────────────────────────────────────
   Eight cards, not a seamless wall: each gets its own ground, an accent rail and a soft
   lift. Typographic — the number is the story, the label is the caption. Cards enter
   staggered so the strip reads as one sweep. */
.counts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 14px; margin: 18px 0 26px;
}
.count {
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg);
  padding: 16px 18px 15px; position: relative; overflow: hidden;
  text-decoration: none; display: block;
  box-shadow: 0 1px 2px color-mix(in srgb, var(--ink) 4%, transparent);
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
  animation: sreise .5s var(--ease) both;
}
.count:hover { transform: translateY(-3px); box-shadow: var(--lift-2); border-color: color-mix(in srgb, var(--navy) 28%, var(--rule)); }
.count::after {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px;
  background: var(--n, var(--navy)); opacity: .9;
}
.count b {
  display: block; font: 700 30px/1.05 var(--serif); font-variation-settings: "opsz" 42;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: var(--ink);
}
.count span {
  display: block; margin-top: 6px; font-size: 11px; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
}
.count.is-brand { --n: var(--navy); }
.count.is-ok    { --n: var(--ok); }
.count.is-warn  { --n: var(--warn); }
.count.is-bad   { --n: var(--bad); }
/* stagger */
.counts .count:nth-child(1){animation-delay:.02s}
.counts .count:nth-child(2){animation-delay:.07s}
.counts .count:nth-child(3){animation-delay:.12s}
.counts .count:nth-child(4){animation-delay:.17s}
.counts .count:nth-child(5){animation-delay:.22s}
.counts .count:nth-child(6){animation-delay:.27s}
.counts .count:nth-child(7){animation-delay:.32s}
.counts .count:nth-child(8){animation-delay:.37s}

/* ── Daily active devices ────────────────────────────────────────────────── */
.usage {
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg);
  padding: 20px 22px; margin-bottom: 26px;
  display: grid; gap: 22px; align-items: center; box-shadow: var(--lift-1);
  animation: sreise .55s var(--ease) both; animation-delay: .2s;
}
@media (min-width: 800px) {
  .usage { grid-template-columns: minmax(250px, 1fr) minmax(230px, 1.2fr); }
  .usage-note { grid-column: 1 / -1; }
}
.usage-nums { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.usage .count { background: none; border: 0; padding: 0; box-shadow: none; animation: none; }
.usage .count::after { display: none; }
.usage .count b { font-size: 25px; }
.delta {
  display: block; margin-top: 5px; font: 600 11.5px/1 var(--sans); font-style: normal;
  letter-spacing: 0; text-transform: none; color: var(--ink-3);
}
.delta.up   { color: var(--ok); }
.delta.down { color: var(--warn); }

/* Fourteen spans, no library. Each bar grows from the baseline on load, the current day
   is oxide and the rest navy; the hover lifts a bar so the strip answers a pointer. */
.spark { display: flex; align-items: flex-end; gap: 4px; height: 74px; padding-bottom: 20px; position: relative; }
.spark .bar {
  flex: 1 1 0; min-width: 6px; height: var(--h);
  border-radius: 2px 2px 0 0;
  background: color-mix(in srgb, var(--navy) 36%, transparent);
  transform-origin: bottom;
  animation: growbar .7s var(--ease) both;
  animation-delay: var(--i, 0ms);
  transition: background var(--t), transform var(--t), filter var(--t);
}
.spark .bar:hover { background: color-mix(in srgb, var(--navy) 64%, transparent); filter: brightness(1.04); transform: translateY(-2px); }
.spark .bar.is-today { background: var(--oxide); }
.spark .bar.is-today:hover { background: var(--oxide); }
@keyframes growbar { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.spark-cap {
  position: absolute; right: 0; bottom: 0;
  font: 500 11px var(--mono); letter-spacing: .04em; color: var(--ink-3);
}
.usage-note { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-3); }

.result-count { margin: 0 0 14px; color: var(--ink-3); font-size: 13px; }

/* ── Issue-a-key panel ──────────────────────────────────────────────────── */
.panel {
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg);
  padding: 18px 22px; margin-bottom: 26px; box-shadow: var(--lift-1);
  animation: sreise .5s var(--ease) both; animation-delay: .28s;
}
.panel > summary {
  cursor: pointer; list-style: none; display: flex; align-items: center; gap: 12px;
  font-weight: 600; font-size: 15.5px; color: var(--ink);
}
.panel > summary::-webkit-details-marker { display: none; }
.panel > summary::before {
  content: "+"; flex: none; width: 26px; height: 26px; display: grid; place-items: center;
  font: 700 16px/1 var(--sans); color: var(--navy-ink);
  background: var(--navy); border-radius: var(--r);
  transition: transform var(--t), background var(--t);
}
.panel > summary:hover::before { background: var(--navy-2); }
.panel[open] > summary::before { content: "−"; transform: rotate(180deg); }
.panel > summary .muted { font-weight: 400; }
.panel form {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px; margin-top: 20px; align-items: end;
  animation: sreise .4s var(--ease) both;
}
.panel label {
  display: block; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3);
}
.panel label input { margin-top: 6px; }
.panel > form > button {
  min-height: 46px; padding: 12px 22px; border-radius: var(--r);
  background: var(--navy); color: var(--navy-ink); border: 1px solid var(--navy);
  font: 600 14px var(--sans); box-shadow: var(--lift-1);
  transition: background var(--t), transform var(--t), box-shadow var(--t);
}
.panel > form > button:hover { background: var(--navy-2); transform: translateY(-1px); box-shadow: var(--lift-2); }

/* ── Generic form bits (shared by tiers.php, manual.php, setup.php) ─────── */
.field { display: block; margin: 0 0 16px; }
.field label {
  display: block; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 6px;
}
.field input, .field textarea, .act-row input, .panel input:not([type=radio]):not([type=checkbox]) {
  width: 100%; padding: 10px 12px; font-size: 14.5px; color: var(--ink);
  background: var(--surface); border: 1px solid var(--rule-2); border-radius: var(--r);
  transition: border-color var(--t), box-shadow var(--t), background var(--t);
}
.field input:focus, .act-row input:focus, .panel input:not([type=radio]):not([type=checkbox]):focus {
  border-color: var(--navy); box-shadow: 0 0 0 3px color-mix(in srgb, var(--navy) 16%, transparent);
  outline: none;
}
.field input[type=number] { width: auto; }
.field .opt { font-weight: 400; text-transform: none; color: var(--ink-3); }
.hint { margin: 6px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }

.field-full { grid-column: 1 / -1; }
.field-full .hint { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }

/* Generic card (manual.php result, tiers.php plan card). */
.card {
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg);
  padding: 20px 22px; box-shadow: var(--lift-1);
}
.card-work { padding: 22px 24px; }
.card .subtitle, .card h2.subtitle { margin-top: 0; }
.subtitle { font: 700 19px/1.25 var(--serif); font-variation-settings: "opsz" 30; letter-spacing: -.01em; color: var(--ink); }

button, .btn {
  border: 1px solid var(--rule-2); border-radius: var(--r);
  padding: 10px 16px; font: 600 14px var(--sans); color: var(--ink); background: var(--surface);
  cursor: pointer; transition: color var(--t), background var(--t), border-color var(--t), transform var(--t), box-shadow var(--t);
}
button:hover, .btn:hover { transform: translateY(-1px); }
.btn-primary { background: var(--navy); color: var(--navy-ink); border-color: var(--navy); box-shadow: var(--lift-1); }
.btn-primary:hover { background: var(--navy-2); color: var(--navy-ink); }
.btn-lg { padding: 13px 22px; font-size: 15px; }
.btn-sm { padding: 7px 13px; font-size: 13px; }

/* ── The licence register ─────────────────────────────────────────────────
   A modern data grid: sticky header, tabular numbers, an accent rail down the leading
   edge, and a Manage button that lifts on hover. Nothing resizes in place. */
.panel-head.ledger-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.ledger-head .page-title { margin: 0; }
.ledger-head .muted { font-weight: 400; }

.ledger-wrap {
  margin: 14px 0 34px; border: 1px solid var(--rule); border-radius: var(--r-lg);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  background: var(--surface); box-shadow: var(--lift-1);
  animation: sreise .5s var(--ease) both; animation-delay: .34s;
}
table.ledger { width: 100%; border-collapse: collapse; font-size: 14px; min-width: 920px; }
table.ledger th {
  text-align: left; padding: 13px 16px; white-space: nowrap; position: sticky; top: 0;
  font: 600 11px/1.4 var(--sans); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3); background: var(--surface-2);
  border-bottom: 2px solid color-mix(in srgb, var(--navy) 70%, transparent);
}
table.ledger td { padding: 15px 16px; border-bottom: 1px solid var(--rule); vertical-align: middle; }
table.ledger tbody tr { transition: background var(--t), box-shadow var(--t); }
table.ledger tbody tr:nth-child(even) { background: color-mix(in srgb, var(--surface-2) 44%, transparent); }
table.ledger tbody tr:hover { background: var(--surface-2); }
table.ledger tbody tr:last-child td { border-bottom: 0; }
/* A status rail down the leading edge: overdue or blocked, due soon, or fine. */
table.ledger tbody td:first-child { border-left: 4px solid transparent; }
table.ledger tbody tr.st-bad  td:first-child { border-left-color: var(--bad); }
table.ledger tbody tr.st-warn td:first-child { border-left-color: var(--warn); }
table.ledger tbody tr.st-ok   td:first-child { border-left-color: var(--ok); }

.l-key { font: 600 13.5px var(--mono); letter-spacing: .01em; white-space: nowrap; color: var(--ink); }
.l-who .cust { display: block; font-weight: 600; }
.l-who .sub-line { display: block; font-size: 12.5px; color: var(--ink-3); white-space: nowrap; }
.l-who .note-line { font-style: italic; }
.l-expiry { font-variant-numeric: tabular-nums; white-space: nowrap; }
.l-expiry b { display: block; color: var(--ink); font-weight: 600; }
.l-expiry span { font-size: 12.5px; color: var(--ink-3); }
.l-expiry.st-warn b, .l-expiry.st-warn span { color: var(--warn); }
.l-expiry.st-bad  b, .l-expiry.st-bad  span { color: var(--bad); }
.l-seats { font-variant-numeric: tabular-nums; white-space: nowrap; }

.meter {
  display: inline-block; width: 44px; height: 6px; margin-left: 10px; vertical-align: middle;
  background: var(--surface-3); border-radius: 3px; overflow: hidden;
}
.meter i { display: block; height: 100%; width: var(--p); background: var(--navy); border-radius: 3px; transition: width .5s var(--ease); }
.meter.is-full i { background: var(--warn); }
.meter.is-wide { width: 100%; max-width: 180px; height: 7px; margin: 0; display: block; }

.l-manage { text-align: right; white-space: nowrap; }
.manage-btn {
  padding: 8px 16px; border-radius: var(--r);
  font: 600 12px var(--sans); letter-spacing: .04em; text-transform: uppercase;
  color: var(--navy); border: 1px solid var(--navy); background: transparent;
  transition: color var(--t), background var(--t), box-shadow var(--t), transform var(--t);
}
.manage-btn:hover { color: var(--navy-ink); background: var(--navy); box-shadow: var(--lift-1); transform: translateY(-1px); }

/* Stamps (paid / unpaid / blocked / tier / unrestricted). */
.stamp {
  display: inline-block; padding: 4px 10px; border-radius: 999px;
  font: 600 11px/1 var(--sans); letter-spacing: .05em; text-transform: uppercase;
  border: 1px solid currentColor; margin-right: 5px; white-space: nowrap;
}
.stamp-ok   { color: var(--ok); }
.stamp-bad  { color: var(--bad); }
.stamp-mut  { color: var(--ink-3); }
.stamp-tier { color: var(--navy); }

/* ── The action dialog ──────────────────────────────────────────────────────
   A native <dialog>: showModal() gives focus trapping and Esc-to-close for free, and
   site.js closes it on a backdrop click. Rendered as a sheet that springs up, with the
   backdrop frosted and the body a clean two-column split that is divided into named
   sections, so a licence's devices and its actions are separate, legible things. */
dialog.lic-dialog {
  width: min(740px, 94vw); max-height: min(680px, 88vh); padding: 0;
  border: 1px solid var(--rule-2); border-radius: var(--r-lg);
  background: var(--surface); color: var(--ink);
  box-shadow: var(--lift-3);
  animation: sheetin .32s var(--ease) both;
}
@keyframes sheetin { from { opacity: 0; transform: translateY(16px) scale(.98); } to { opacity: 1; transform: none; } }
dialog.lic-dialog::backdrop { background: color-mix(in srgb, var(--ink) 42%, transparent); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
dialog.lic-dialog[open] { display: flex; flex-direction: column; }

.dlg-head {
  flex: none; display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 18px 22px; border-bottom: 2px solid color-mix(in srgb, var(--navy) 70%, transparent);
  background: color-mix(in srgb, var(--surface-2) 55%, transparent);
}
.dlg-head .sub-line { display: block; margin-top: 4px; font-size: 13px; color: var(--ink-3); }
.dlg-close {
  flex: none; width: 34px; height: 34px; display: grid; place-items: center;
  font-size: 22px; line-height: 1; color: var(--ink-3);
  border: 1px solid var(--rule-2); border-radius: var(--r);
  transition: color var(--t), border-color var(--t), background var(--t), transform var(--t);
}
.dlg-close:hover { color: var(--bad); border-color: var(--bad); background: var(--bad-wash); transform: rotate(90deg); }

.dlg-body { flex: 1 1 auto; overflow-y: auto; display: grid; background: color-mix(in srgb, var(--canvas) 40%, var(--surface)); }
@media (min-width: 600px) {
  .dlg-body { grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr); }
  .dlg-body .dlg-devices { border-right: 1px solid var(--rule); }
}
.dlg-sec { padding: 20px 22px; }
.dlg-sec + .dlg-sec { border-top: 1px solid var(--rule); }
@media (min-width: 600px) { .dlg-sec + .dlg-sec { border-top: 0; } }
.dlg-sec > h4 {
  margin: 0 0 15px; font: 600 11px/1.4 var(--sans); letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}

.device-row { font-size: 13px; color: var(--ink-3); padding: 13px 0; border-top: 1px solid var(--rule); }
.device-row:first-of-type { border-top: 0; padding-top: 0; }
.device-row strong { display: block; color: var(--ink); font-size: 14px; margin-bottom: 2px; }
.device-row form { margin-top: 8px; }
.device-row button {
  padding: 7px 13px; border-radius: var(--r); font: 500 13px var(--sans);
  border: 1px solid var(--rule-2); background: var(--surface); color: var(--ink-2);
  transition: color var(--t), border-color var(--t), background var(--t);
}
.device-row button:hover { color: var(--bad); border-color: var(--bad); background: var(--bad-wash); }

/* A labelled cluster of small forms, one per job. */
.act-group { margin-bottom: 20px; }
.act-group:last-child { margin-bottom: 0; }
.act-group > span {
  display: block; margin-bottom: 9px;
  font: 600 11px/1.4 var(--sans); letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-2);
}
.act-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.act-row form { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.act-row button {
  min-height: 40px; padding: 9px 14px; border-radius: var(--r); white-space: nowrap;
  font: 500 13.5px var(--sans);
  border: 1px solid var(--rule-2); background: var(--surface); color: var(--ink);
  transition: color var(--t), border-color var(--t), background var(--t), transform var(--t);
}
.act-row button:hover { color: var(--navy); border-color: var(--navy); background: var(--navy-wash); transform: translateY(-1px); }
.act-row input { padding: 9px 11px; font-size: 14px; width: auto; border-radius: var(--r); border: 1px solid var(--rule-2); background: var(--surface); color: var(--ink); }
.act-row input[type=number] { width: 90px; }
.act-row input[type=date]   { width: 160px; }
.act-row input[type=text]   { width: 160px; }
.act-row .act-primary {
  background: var(--ok); border-color: var(--ok); color: #FFF; font-weight: 600;
}
.act-row .act-primary:hover { background: var(--ok); border-color: var(--ok); color: #FFF; filter: brightness(1.08); transform: translateY(-1px); }
.act-row .act-undo { border-style: dashed; color: var(--ink-3); }
.act-row .act-danger:hover { color: var(--bad); border-color: var(--bad); background: var(--bad-wash); }
.act-group.is-danger { border-top: 1px dashed var(--rule-2); padding-top: 18px; margin-top: 6px; }
.act-group.is-danger > span { color: var(--bad); }

/* ── Centred single-form screens: sign-in, setup ────────────────────────── */
.auth-screen {
  min-height: 100vh; min-height: 100svh;
  display: grid; place-items: center; padding: 24px;
  background: var(--canvas);
  background-image:
    repeating-linear-gradient(to bottom, transparent 0 31px,
      color-mix(in srgb, var(--rule-2) 50%, transparent) 31px 32px),
    repeating-linear-gradient(to right, transparent 0 31px,
      color-mix(in srgb, var(--rule-2) 24%, transparent) 31px 32px);
}
.auth-card {
  width: 100%; max-width: 410px; padding: 34px;
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--r-lg);
  box-shadow: var(--lift-3);
  position: relative; overflow: hidden;
  animation: rise .45s var(--ease) both;
}
.auth-card::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 4px;
  background: linear-gradient(90deg, var(--navy), var(--oxide));
}
.auth-card .logo { width: 34px; height: 34px; color: var(--navy); display: block; margin-bottom: 18px; }
.auth-card h1 {
  font: 700 24px/1.2 var(--serif); font-variation-settings: "opsz" 36;
  letter-spacing: -.02em; margin: 0 0 4px;
}
.auth-card form { margin-top: 22px; }
.auth-card > form > button {
  width: 100%; min-height: 48px; margin-top: 8px; border-radius: var(--r);
  background: var(--navy); color: var(--navy-ink); border: 1px solid var(--navy);
  font: 600 15px var(--sans); box-shadow: var(--lift-1);
  transition: background var(--t), box-shadow var(--t), transform var(--t);
}
.auth-card > form > button:hover { background: var(--navy-2); box-shadow: var(--lift-2); transform: translateY(-1px); }

/* Sign-out reads as a link but posts — no third-party <img> can trigger it. */
.inline-form{display:inline}
.linkbtn{border:0;background:none;padding:0;font:inherit;color:inherit;
         text-decoration:underline;cursor:pointer}

/* ── Empty state ────────────────────────────────────────────────────────── */
.empty { padding: 52px 0; text-align: center; color: var(--ink-3); font-size: 14.5px; }

/* ── Plan & feature pickers (issue-a-key, the licence dialog, tiers.php) ──
   Two selection surfaces: tier cards pick a plan, feature cards fine-tune that plan's
   ticks. Both are <label>-wrapped native inputs, so they work with JS off, and the
   checked state is a card that fills navy via :has() — no class toggling to get wrong. */
.tier-form { display: flex; flex-direction: column; gap: 12px; width: 100%; }
.tier-form .hint { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }

/* ── Tier cards ─────────────────────────────────────────────────────────── */
.tier-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; }
.tier-card {
  position: relative; display: flex; flex-direction: column; gap: 9px;
  padding: 14px 15px; border: 1.5px solid var(--rule-2); border-radius: var(--r-lg);
  background: var(--surface); cursor: pointer;
  transition: border-color var(--t), background var(--t), box-shadow var(--t), transform var(--t);
}
.tier-card input { position: absolute; opacity: 0; pointer-events: none; }
.tier-card:hover { border-color: color-mix(in srgb, var(--navy) 42%, var(--rule-2)); transform: translateY(-1px); }
.tier-card:has(input:checked) {
  border-color: var(--navy); background: color-mix(in srgb, var(--navy) 6%, var(--surface));
  box-shadow: 0 0 0 1px var(--navy) inset, var(--lift-1);
}
.tier-name {
  font: 700 15px/1.2 var(--serif); font-variation-settings: "opsz" 26;
  letter-spacing: -.01em; color: var(--ink); padding-right: 26px;
}
.tier-feats { display: flex; flex-wrap: wrap; gap: 5px; }
.tier-chip {
  font: 500 10.5px/1 var(--sans); letter-spacing: .01em; color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--rule);
  border-radius: 999px; padding: 4px 9px; white-space: nowrap;
}
.tier-card:has(input:checked) .tier-chip { border-color: color-mix(in srgb, var(--navy) 30%, var(--rule)); }
/* the radio indicator: an empty circle off, a filled navy check on */
.tier-card::after {
  content: ""; position: absolute; top: 12px; right: 12px; width: 19px; height: 19px;
  border: 1.5px solid var(--rule-2); border-radius: 50%;
  transition: background var(--t), border-color var(--t);
}
.tier-card:has(input:checked)::after {
  content: "✓"; display: grid; place-items: center; font: 700 12px/1 var(--sans);
  color: var(--navy-ink); border-color: var(--navy); background: var(--navy);
}

/* ── Feature cards ──────────────────────────────────────────────────────── */
.feat-group { margin-top: 16px; }
.feat-group:first-child { margin-top: 4px; }
.feat-cat {
  display: block; margin: 0 0 8px;
  font: 600 11px/1.4 var(--sans); letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3);
}
.feat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 8px; }
@media (min-width: 900px) { .feat-grid { grid-template-columns: repeat(3, 1fr); } }
.feat-card {
  position: relative; display: flex; flex-direction: column; gap: 3px;
  padding: 12px 13px; border: 1.5px solid var(--rule-2); border-radius: var(--r);
  background: var(--surface); cursor: pointer;
  transition: border-color var(--t), background var(--t), box-shadow var(--t), transform var(--t);
}
.feat-card input { position: absolute; opacity: 0; pointer-events: none; }
.feat-card:hover { border-color: color-mix(in srgb, var(--navy) 40%, var(--rule-2)); transform: translateY(-1px); }
.feat-card:has(input:checked) {
  border-color: var(--navy); background: color-mix(in srgb, var(--navy) 7%, var(--surface));
  box-shadow: 0 0 0 1px var(--navy) inset;
}
.feat-name { font: 600 13.5px/1.3 var(--sans); color: var(--ink); padding-right: 24px; }
.feat-desc { font: 400 12px/1.4 var(--sans); color: var(--ink-3); }
.feat-card::after {
  content: ""; position: absolute; top: 12px; right: 12px; width: 18px; height: 18px;
  border: 1.5px solid var(--rule-2); border-radius: 50%;
  transition: background var(--t), border-color var(--t);
}
.feat-card:has(input:checked)::after {
  content: "✓"; display: grid; place-items: center; font: 600 11px/1 var(--sans);
  color: var(--navy-ink); border-color: var(--navy); background: var(--navy);
}

/* ── Motion ────────────────────────────────────────────────────────────────
   The entry animations. Kept soft and brief so the panel feels alive, not slow; all off
   when the system asks for less. */
@keyframes sreise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
