/* SWGOH Pals administration dashboard
 * Tokens, shell and shared components follow swgoh-frontend-design-spec.md §3,
 * §4 and §8. Pages add their own styles in static/css/pages/<page>.css; keep
 * shared components here.
 * No inline styles: the Content-Security-Policy only allows this origin's CSS.
 *
 * Decoration (page art, rail art, flavor lines, holograms, star field, glow and
 * corner brackets) is layered over a complete plain interface. Every decorative
 * rule is scoped to :root[data-decor="full"]; Reduce decoration, forced colors
 * and prefers-contrast: more remove it all (see the end of this file).
 */

/* ===== Tokens ===== */
:root {
  color-scheme: dark;
  --sw-page: #030E1A;
  --sw-rail: #04182A;
  --sw-panel: #0A1E30;
  --sw-raised: #14304A;
  --sw-input: #061A2C;
  --sw-current: #1A2A33;
  --sw-text: #EAF2FA;
  --sw-text-secondary: #ACBED0;
  --sw-control-border: #5F8DB5;
  --sw-divider: #294156;
  --sw-edge: #1B4A6C;
  --sw-edge-strong: #2B87BF;
  --sw-glow: rgb(43 135 191 / 0.28);
  --sw-icon: #78B9F4;
  --sw-action: #F2C35B;
  --sw-on-action: #101A25;
  --sw-link-focus: #72D7FF;
  --sw-success: #5FD99A;
  --sw-warning: #F2C35B;
  --sw-danger: #FF8A80;

  /* Derived surfaces. The inset surface sits between panel and raised, for
     cards and tiles inside a panel. Hover states lighten, never recolor. */
  --sw-inset: #0F2940;
  --sw-raised-hover: #1C3D5C;
  --sw-action-hover: #F6D07A;
  --sw-star: rgb(234 242 250 / 0.35);
  --edge-glow: 0 0 1.25rem -0.25rem var(--sw-glow), inset 0 1px 0 rgb(114 215 255 / 0.05);

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --radius-control: 0.5rem;
  --radius-well: 0.625rem;
  --radius-panel: 0.75rem;
  --target: 2.75rem; /* 44px product hit-area target */
  --topbar: 4rem;
  --rail: 14rem;
  --content-max: 100rem;
  /* Side space for the main column's rows: 24px, or wider so their content
     stays --content-max wide and centered. The % is the column's width. */
  --gutter: max(var(--space-6), calc((100% - var(--content-max)) / 2));
  --transition: 150ms ease;
  --font: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ACBED0' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --magnifier: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ACBED0' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4-4'/%3E%3C/svg%3E");
}

:root[data-text="large"] { font-size: 112.5%; }
:root[data-text="larger"] { font-size: 125%; }

/* ===== Base ===== */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-padding-top: var(--space-4);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--sw-page);
  color: var(--sw-text);
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.5;
}

/* Faint static star field on the outer page only; panels stay opaque. */
:root[data-decor="full"] body {
  background-image:
    radial-gradient(1px 1px at 12% 18%, var(--sw-star) 50%, transparent 51%),
    radial-gradient(1px 1px at 68% 12%, var(--sw-star) 50%, transparent 51%),
    radial-gradient(1px 1px at 38% 62%, var(--sw-star) 50%, transparent 51%),
    radial-gradient(1px 1px at 86% 74%, var(--sw-star) 50%, transparent 51%),
    radial-gradient(1px 1px at 22% 88%, var(--sw-star) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 54% 36%, rgb(120 185 244 / 0.4) 50%, transparent 51%);
  background-size: 480px 480px;
  background-attachment: fixed;
}

h1, h2, h3, h4 { line-height: 1.25; margin: 0; }
h1 { font-size: 2.5rem; font-weight: 700; letter-spacing: -0.01em; }
h2 { font-size: 1.1875rem; font-weight: 600; }
h3 { font-size: 1rem; font-weight: 600; }
p { margin: 0; }
p + p { margin-top: var(--space-2); }
ul, ol { margin: 0; padding-left: 1.25rem; }
code, kbd, samp, pre { font-family: var(--mono); font-size: 0.9375em; }
code { overflow-wrap: anywhere; }
img, svg { max-width: 100%; }
hr { border: 0; border-top: 1px solid var(--sw-divider); margin: var(--space-4) 0; }

a { color: var(--sw-link-focus); text-underline-offset: 0.15em; }
a:hover { text-decoration-thickness: 2px; }

:focus-visible {
  outline: 3px solid var(--sw-link-focus);
  outline-offset: 2px;
}

main:focus { outline: none; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -10rem;
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  background: var(--sw-action);
  color: var(--sw-on-action);
  border-radius: var(--radius-control);
  font-weight: 600;
}
.skip-link:focus { top: var(--space-2); }

.icon { width: 1.25em; height: 1.25em; flex: none; vertical-align: -0.25em; }

/* ===== Shell (§4): rail, top bar over the page art, content, footer ===== */
.shell {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  min-height: 100vh;
}
.shell-plain { grid-template-columns: minmax(0, 1fr); }
/* Paint the rail column the full page height; the rail itself is sticky. */
@media (min-width: 60.0625rem) {
  .shell:not(.shell-plain) {
    background: linear-gradient(to right, var(--sw-rail) calc(var(--rail) - 1px), var(--sw-edge) calc(var(--rail) - 1px) var(--rail), transparent var(--rail));
  }
}

.rail {
  position: sticky;
  top: 0;
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  height: 100vh;
  overflow-y: auto;
  padding: var(--space-4) var(--space-3);
  background: var(--sw-rail);
  border-right: 1px solid var(--sw-edge);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  color: var(--sw-text);
  text-decoration: none;
}
.brand-emblem { width: 2.75rem; height: 2.75rem; flex: none; }
.brand-text { display: flex; flex-direction: column; min-width: 0; }
.brand-name { font-size: 1.25rem; font-weight: 700; line-height: 1.2; }
.brand-tagline {
  margin-top: 0.125rem;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  line-height: 1.35;
  text-transform: uppercase;
  color: var(--sw-text-secondary);
}
.rail-brand { padding: 0 var(--space-2) var(--space-2); }
.topbar-brand { display: none; }
.topbar-brand .brand-emblem { width: 2.25rem; height: 2.25rem; }
.topbar-brand .brand-name { font-size: 1.0625rem; }

/* Navigation: groups separated by dividers; their names are hidden headings. */
.nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.125rem; }
.nav-group + .nav-group {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--sw-divider);
}
.nav-link {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  padding: var(--space-2) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-control);
  color: var(--sw-text);
  font-size: 0.9375rem;
  text-decoration: none;
  transition: background-color var(--transition);
}
.nav-link .icon { width: 1.375rem; height: 1.375rem; color: var(--sw-icon); }
.nav-link:hover { background: var(--sw-raised); }
.nav-link.active {
  background: var(--sw-current);
  border-color: var(--sw-action);
  color: var(--sw-action);
  font-weight: 600;
}
.nav-link.active .icon { color: var(--sw-action); }

/* Rail art and credo sit at the foot of the rail (decoration). */
.rail-decor { margin-top: auto; padding: var(--space-2) var(--space-2) 0; }
.rail-art {
  width: 100%;
  max-width: 12rem;
  aspect-ratio: 1;
  margin: 0 auto var(--space-3);
  background: center / contain no-repeat;
}
:root[data-decor="full"] .rail-art { background-image: url("/static/img/decor/rail-deathstar.webp"); }
.rail-credo {
  display: grid;
  grid-template-columns: 2rem 1fr;
  column-gap: var(--space-3);
  align-items: start;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  line-height: 1.6;
  text-transform: uppercase;
  color: var(--sw-text-secondary);
}
.rail-credo::before {
  content: "";
  height: 2px;
  margin-top: 0.55em;
  background: var(--sw-action);
}
@media (max-height: 50rem) { .rail-art { display: none; } }

.main-column {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow-x: clip;
}

/* Page art: a cinematic scene anchored top right, behind the top bar and page
   header. Gradients to --sw-page fade its left and bottom edges and dim it, so
   header text sits on near-solid color and it has faded by the first content
   row. Each page sets --page-art; only [data-decor="full"] downloads it. */
.main-column::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  z-index: -1;
  width: min(100%, 68rem);
  height: 22rem;
  pointer-events: none;
  background-repeat: no-repeat;
}
:root[data-decor="full"] .main-column::before {
  background-image:
    linear-gradient(to right, var(--sw-page) 0%, rgb(3 14 26 / 0.82) 22%, rgb(3 14 26 / 0) 58%),
    linear-gradient(to top, var(--sw-page) 0%, rgb(3 14 26 / 0.7) 30%, rgb(3 14 26 / 0) 70%),
    linear-gradient(to bottom, rgb(3 14 26 / 0.7) 0, rgb(3 14 26 / 0) var(--topbar)),
    linear-gradient(rgb(3 14 26 / 0.15), rgb(3 14 26 / 0.15)),
    var(--page-art);
  background-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, cover;
  background-position: 0 0, 0 0, 0 0, 0 0, right top;
}
.art-overview { --page-art: url("/static/img/art/overview.webp"); }
.art-characters { --page-art: url("/static/img/art/characters.webp"); }
.art-test-chat { --page-art: url("/static/img/art/test-chat.webp"); }
.art-channels { --page-art: url("/static/img/art/channels.webp"); }
.art-plan { --page-art: url("/static/img/art/plan.webp"); }
.art-memories { --page-art: url("/static/img/art/memories.webp"); }
.art-reminders { --page-art: url("/static/img/art/reminders.webp"); }
.art-config { --page-art: url("/static/img/art/config.webp"); }
.art-logs { --page-art: url("/static/img/art/logs.webp"); }
/* Lorebooks' art is a code-drawn star field and nebula, not an image. */
:root[data-decor="full"] .art-lorebooks::before {
  background-image:
    linear-gradient(to right, var(--sw-page) 0%, rgb(3 14 26 / 0.8) 22%, rgb(3 14 26 / 0) 60%),
    linear-gradient(to top, var(--sw-page) 0%, rgb(3 14 26 / 0) 70%),
    radial-gradient(1.5px 1.5px at 18% 22%, rgb(234 242 250 / 0.9) 50%, transparent 51%),
    radial-gradient(1px 1px at 42% 64%, rgb(234 242 250 / 0.7) 50%, transparent 51%),
    radial-gradient(2px 2px at 71% 31%, rgb(114 215 255 / 0.9) 50%, transparent 51%),
    radial-gradient(1px 1px at 88% 12%, rgb(234 242 250 / 0.8) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 60% 84%, rgb(234 242 250 / 0.6) 50%, transparent 51%),
    radial-gradient(1px 1px at 8% 76%, rgb(234 242 250 / 0.7) 50%, transparent 51%),
    radial-gradient(ellipse 34% 52% at 78% 26%, rgb(43 135 191 / 0.5), transparent 72%),
    radial-gradient(ellipse 26% 36% at 62% 12%, rgb(126 96 212 / 0.3), transparent 70%),
    radial-gradient(ellipse 20% 30% at 90% 46%, rgb(114 215 255 / 0.14), transparent 70%);
  background-size: 100% 100%, 100% 100%, 190px 150px, 190px 150px, 230px 170px, 170px 130px, 210px 160px, 150px 120px, 100% 100%, 100% 100%, 100% 100%;
  background-repeat: no-repeat, no-repeat, repeat, repeat, repeat, repeat, repeat, repeat, no-repeat, no-repeat, no-repeat;
  background-position: 0 0;
}

.topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--topbar);
  padding: var(--space-3) var(--gutter);
}
.topbar-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.topbar-actions > .popover > summary .icon:last-child { width: 1rem; height: 1rem; color: var(--sw-text-secondary); }

.nav-update {
  min-height: var(--target);
  padding: var(--space-1) var(--space-3);
  text-decoration: none;
}

main {
  flex: 1 0 auto;
  min-width: 0;
  width: 100%;
  padding: var(--space-2) var(--gutter) var(--space-8);
}
/* Signed out, main is its own centered 30rem box, so it keeps a plain gutter. */
.shell-plain main { max-width: 30rem; margin: 0 auto; padding-top: var(--space-8); --gutter: var(--space-6); }
.shell-plain .topbar-brand { display: inline-flex; }
.shell-plain :is(.page-purpose, .status-region) + form { margin-top: var(--space-4); }

.site-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-6);
  padding: var(--space-4) var(--gutter) var(--space-5);
  border-top: 1px solid var(--sw-divider);
  color: var(--sw-text-secondary);
  font-size: 0.8125rem;
}
.footer-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-right: auto; }
.footer-name { color: var(--sw-text); font-weight: 600; }
.footer-sep { color: var(--sw-divider); }
.footer-line { font-size: 0.6875rem; font-weight: 600; letter-spacing: 0.2em; text-transform: uppercase; }
.footer-emblem {
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
  background: var(--sw-action);
  -webkit-mask: url("/static/img/brand/emblem.webp") center / contain no-repeat;
  mask: url("/static/img/brand/emblem.webp") center / contain no-repeat;
}

.menu-drawer { display: none; }
.menu-drawer > summary { list-style: none; }
.menu-drawer > summary::-webkit-details-marker { display: none; }
.menu-drawer[open] > .nav {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  max-height: calc(100vh - var(--topbar));
  overflow-y: auto;
  padding: var(--space-4);
  background: var(--sw-rail);
  border-bottom: 1px solid var(--sw-control-border);
}

.banner {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  margin: 0 var(--gutter) var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--sw-edge);
  border-left: 3px solid var(--sw-warning);
  border-radius: var(--radius-control);
  background: var(--sw-panel);
}
.banner-warning .icon { color: var(--sw-warning); }

/* Tablet and phone: the rail becomes a Menu drawer and the brand moves into a
   solid, sticky top bar. */
@media (max-width: 60rem) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .rail { display: none; }
  .menu-drawer { display: block; }
  .topbar-brand { display: inline-flex; }
  .topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    padding: var(--space-2) var(--space-4);
    background: var(--sw-rail);
    border-bottom: 1px solid var(--sw-edge);
  }
  .topbar-label {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .topbar-actions > .popover > summary .icon:last-child { display: none; }
  html { scroll-padding-top: calc(var(--topbar) + var(--space-4)); }
  main { padding: var(--space-4); }
  .banner { margin: var(--space-4) var(--space-4) 0; }
  .site-footer { padding: var(--space-4); }
  h1 { font-size: 1.75rem; }
}
@media (max-width: 30rem) {
  .topbar-brand .brand-tagline { display: none; }
}
@media (max-height: 30rem) {
  .topbar, .rail { position: static; }
  .rail { height: auto; }
  html { scroll-padding-top: var(--space-4); }
}

/* ===== Popovers and menus (details-based, no JavaScript required) ===== */
.popover { position: relative; }
.popover > summary { list-style: none; }
.popover > summary::-webkit-details-marker { display: none; }
.popover-panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-2));
  z-index: 30;
  width: min(18rem, calc(100vw - 2rem));
  padding: var(--space-4);
  background: var(--sw-panel);
  border: 1px solid var(--sw-control-border);
  border-radius: var(--radius-panel);
  box-shadow: 0 0.75rem 2rem rgb(0 0 0 / 0.45);
}
/* A popover near the start of a row opens rightwards instead. */
.popover-start > .popover-panel { right: auto; left: 0; }
.menu-list {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  width: max-content;
  min-width: 12rem;
  max-width: calc(100vw - 2rem);
  padding: var(--space-2);
}
.menu-list hr { margin: var(--space-1) 0; }
.menu-heading { padding: var(--space-1) var(--space-3) var(--space-2); border-bottom: 1px solid var(--sw-divider); }
.menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--target);
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-control);
  background: none;
  color: var(--sw-text);
  font: inherit;
  font-size: 0.9375rem;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.menu-item .icon { color: var(--sw-icon); }
.menu-item:hover { background: var(--sw-raised); }
.menu-item-danger, .menu-item-danger .icon { color: var(--sw-danger); }
/* Overflow menu: a "…" icon button; its summary carries a visually hidden name
   that includes its object ("More actions for Firefly"). */
.overflow-menu > summary { padding: 0; width: var(--target); }

/* ===== Settings search (§2, §4) =====
   The top bar's field: the input look with the magnifier as its submit
   button and the Ctrl K hint inside it (app.js shows the hint). With HTMX the
   best matches open in a panel under the field. Under 60rem it collapses to a
   Search link to the search page. */
.topbar-search { flex: 0 1 34rem; min-width: 0; }
.topbar-search-form { position: relative; }
.topbar-search-form input[type="search"] {
  padding-left: var(--target);
  padding-right: 4.5rem;
  background-image: none;
}
/* Typing hides the hint, so the field's clear button can sit at its end. */
.topbar-search-form input[type="search"]:is(:focus, :not(:placeholder-shown)) { padding-right: var(--space-3); }
.topbar-search-submit {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--target);
  height: var(--target);
  padding: 0;
  border: 0;
  border-radius: var(--radius-control);
  background: transparent;
  color: var(--sw-text-secondary);
  cursor: pointer;
}
.topbar-search-submit:hover { color: var(--sw-text); }
.topbar-search-submit .icon { width: 1.125rem; height: 1.125rem; }
.search-shortcut {
  position: absolute;
  top: 50%;
  right: var(--space-3);
  transform: translateY(-50%);
  padding: 0.0625rem 0.4375rem;
  border: 1px solid var(--sw-divider);
  border-radius: 0.375rem;
  background: var(--sw-panel);
  color: var(--sw-text-secondary);
  font: 600 0.75rem/1.5 var(--font);
  letter-spacing: 0.02em;
  white-space: nowrap;
  pointer-events: none;
}
.search-shortcut[hidden],
.topbar-search-form input:focus ~ .search-shortcut,
.topbar-search-form input:not(:placeholder-shown) ~ .search-shortcut { display: none; }
.topbar-search .topbar-search-link { display: none; }

/* The suggestion panel. Its container stays empty until HTMX fills it. */
.search-suggest-panel {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 0;
  z-index: 40;
  width: max(100%, min(26rem, calc(100vw - 2rem)));
  padding: var(--space-2);
  background: var(--sw-panel);
  border: 1px solid var(--sw-control-border);
  border-radius: var(--radius-panel);
  box-shadow: 0 0.75rem 2rem rgb(0 0 0 / 0.45);
}
.search-suggest-list { display: flex; flex-direction: column; gap: 0.125rem; margin: 0; padding: 0; list-style: none; }
.search-suggest-hit {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-height: var(--target);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-control);
  color: var(--sw-text);
  text-decoration: none;
}
.search-suggest-hit:hover { background: var(--sw-raised); }
.search-suggest-label { font-weight: 600; }
.search-suggest-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  color: var(--sw-text-secondary);
  font-size: 0.8125rem;
}
.search-suggest-all {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: var(--target);
  margin-top: var(--space-1);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--sw-divider);
  font-size: 0.9375rem;
  font-weight: 600;
}
.search-suggest-empty { padding: var(--space-3); color: var(--sw-text-secondary); }
.search-suggest-note { padding: var(--space-1) var(--space-3) var(--space-2); color: var(--sw-text-secondary); font-size: 0.8125rem; }
/* The scope pill beside a result: who the setting affects. */
.search-scope { font-weight: 500; }

/* Tablet and phone: settings search opens from a Search link to its page
   (§4), and the top bar's icon buttons are exactly 44px. On phones the brand
   keeps its emblem while its name becomes visually hidden (it still names the
   link), so Menu, Search, Appearance and the operator menu fit at 320px. If
   the bar still does not fit, for example at a larger text size, it wraps to
   a second row rather than hiding a control. */
@media (max-width: 60rem) {
  .topbar { flex-wrap: wrap; row-gap: var(--space-2); }
  .topbar-search { flex: none; margin-left: auto; }
  .topbar-search + .topbar-actions { margin-left: 0; }
  .topbar-search-form { display: none; }
  .topbar-search .topbar-search-link { display: inline-flex; }
  .topbar-search .topbar-search-link, .topbar-actions > .popover > summary { padding: 0; width: var(--target); }
  /* The update indicator's placeholder takes no gap until it has something to say. */
  .topbar-actions > span:empty { display: none; }
}
@media (max-width: 30rem) {
  .topbar-brand .brand-text {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
}
@media (max-width: 22.5rem) {
  .topbar { gap: var(--space-2) var(--space-1); padding-inline: var(--space-3); }
  .topbar-actions { gap: var(--space-1); }
}

/* A link to a control (#fragment) keeps the control's label in view. */
:is(input, select, textarea):target { scroll-margin-top: 2.5rem; }

/* ===== Page structure ===== */
.page-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4) var(--space-8);
  margin: var(--space-2) 0 var(--space-6);
}
.page-header > :first-child { min-width: 0; flex: 1 1 28rem; }
.page-title-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-5); }
.page-purpose { margin-top: var(--space-2); color: var(--sw-text-secondary); max-width: 52rem; }
.page-header-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.page-purpose + .page-header-actions { margin-top: var(--space-4); }
.page-eyebrow {
  margin-bottom: var(--space-1);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sw-text-secondary);
}

/* Flavor lines: motto beside the title, a quote or tagline at the right. */
.page-motto {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 2rem;
  padding-left: var(--space-5);
  border-left: 1px solid var(--sw-divider);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sw-text-secondary);
}
.page-motto::before { content: ""; width: 2rem; height: 2px; flex: none; background: var(--sw-action); }
.page-quote {
  margin: 0;
  max-width: 20rem;
  text-align: right;
  color: var(--sw-text-secondary);
}
.page-quote blockquote { margin: 0; font-size: 0.9375rem; font-style: italic; line-height: 1.45; }
.page-quote figcaption { margin-top: var(--space-1); font-size: 0.8125rem; }
.page-tagline {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  line-height: 1.9;
  text-transform: uppercase;
  color: var(--sw-text-secondary);
}
.page-tagline::after { content: ""; display: block; width: 2rem; height: 2px; margin-top: var(--space-2); background: var(--sw-action); }
/* A soft gradient backdrop behind whatever sits on the art's right side (the
   quote or tagline, and the top bar's actions) keeps it at 4.5:1 wherever it
   lands on the art. A gradient, not text glow or shadow (§3). */
.page-quote, .page-tagline, .topbar-actions { position: relative; }
:root[data-decor="full"] .page-quote::before,
:root[data-decor="full"] .page-tagline::before {
  content: "";
  position: absolute;
  inset: -1rem -1.5rem -1rem -2.5rem;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to right, rgb(3 14 26 / 0), rgb(3 14 26 / 0.86) 2.5rem);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 1rem, #000 calc(100% - 1rem), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 1rem, #000 calc(100% - 1rem), transparent);
}
@media (min-width: 60.0625rem) {
  :root[data-decor="full"] .topbar-actions::before {
    content: "";
    position: absolute;
    inset: -0.75rem -1.5rem -0.75rem -2.5rem;
    z-index: -1;
    pointer-events: none;
    background: linear-gradient(to right, rgb(3 14 26 / 0), rgb(3 14 26 / 0.8) 2.5rem);
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 0.75rem), transparent);
    mask-image: linear-gradient(to bottom, #000 calc(100% - 0.75rem), transparent);
  }
}

.stack { display: flex; flex-direction: column; gap: var(--space-4); }
.stack-sm { display: flex; flex-direction: column; gap: var(--space-2); }
.stack-lg { display: flex; flex-direction: column; gap: var(--space-6); }
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.cluster-between { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
.grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); }
.grid-wide { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr)); }
.span-full { grid-column: 1 / -1; }

/* Panel: an opaque surface with edge light. Header: an optional line icon in
   the h2, the title, a one-line description and at most one action. */
.panel {
  background: var(--sw-panel);
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-panel);
  padding: var(--space-5) var(--space-6);
  min-width: 0;
}
.panel + .panel { margin-top: var(--space-4); }
/* Grids and stacks space their panels with gap, not margin. */
:is(.grid, .grid-wide, .stack, .stack-sm, .stack-lg) > .panel + .panel { margin-top: 0; }
.panel-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.panel-header p { color: var(--sw-text-secondary); margin-top: var(--space-1); }
.panel-header h2:has(> .icon) { display: flex; align-items: center; gap: var(--space-3); }
.panel-header h2 > .icon { width: 1.5rem; height: 1.5rem; color: var(--sw-icon); }
.panel-header > div:has(> h2 > .icon) > p { padding-left: calc(1.5rem + var(--space-3)); }
.panel-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--sw-divider);
}
@media (max-width: 40rem) {
  .panel { padding: var(--space-4); }
  .panel-header > div:has(> h2 > .icon) > p { padding-left: 0; }
  .tabs { gap: 0; }
  .tabs a { padding-inline: var(--space-2); }
  /* Long pill labels wrap instead of pushing the page sideways. */
  .badge { max-width: 100%; white-space: normal; overflow-wrap: anywhere; }
}

.muted { color: var(--sw-text-secondary); }
.small { font-size: 0.875rem; }
.mono { font-family: var(--mono); }
.nowrap { white-space: nowrap; }
.tabular { font-variant-numeric: tabular-nums; }
.text-success { color: var(--sw-success); }
.text-warning { color: var(--sw-warning); }
.text-danger { color: var(--sw-danger); }

/* ===== Buttons =====
   Primary: gold fill, one per task area. Accent: gold outline for the main
   action repeated on every card of a grid. Secondary (the default): raised
   fill; "View all" links use it with a trailing arrow. Quiet: text only.
   Danger: red outline, kept apart from Save/Publish. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--target);
  min-width: var(--target);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--sw-control-border);
  border-radius: var(--radius-control);
  background: var(--sw-raised);
  color: var(--sw-text);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition);
}
.btn:hover { background: var(--sw-raised-hover); }
.btn-primary {
  background: var(--sw-action);
  border-color: var(--sw-action);
  color: var(--sw-on-action);
}
.btn-primary:hover { background: var(--sw-action-hover); border-color: var(--sw-action-hover); }
.btn-accent { background: transparent; border-color: var(--sw-action); color: var(--sw-action); }
.btn-accent:hover { background: rgb(242 195 91 / 0.12); }
.btn-secondary { background: var(--sw-raised); }
.btn-quiet { background: transparent; border-color: transparent; }
.btn-quiet:hover { background: var(--sw-raised); border-color: transparent; }
.btn-danger { background: transparent; color: var(--sw-danger); border-color: var(--sw-danger); }
.btn-danger:hover { background: rgb(255 138 128 / 0.12); }
.btn-small { position: relative; min-height: 2.25rem; padding: var(--space-1) var(--space-3); font-size: 0.875rem; }
/* A small button still keeps a 44px-tall hit area (§9). */
.btn-small::after { content: ""; position: absolute; inset: -0.25rem 0; }
.btn-icon { padding: 0; width: var(--target); }
.btn-icon.btn-small { width: 2.25rem; }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.btn.htmx-request { cursor: progress; }

/* Destructive actions live in a disclosure so one click never destroys data. */
.confirm { display: inline-block; }
.confirm > summary { list-style: none; }
.confirm > summary::-webkit-details-marker { display: none; }
.confirm[open] > summary { margin-bottom: var(--space-2); }
.confirm-panel {
  padding: var(--space-3);
  border: 1px solid var(--sw-danger);
  border-radius: var(--radius-control);
  background: var(--sw-raised);
  max-width: 28rem;
}
.confirm-panel p { margin-bottom: var(--space-2); }

/* ===== Forms ===== */
.field { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.field + .field { margin-top: var(--space-4); }
.field label, .field-label, legend { font-weight: 600; font-size: 0.9375rem; }
.field-help { color: var(--sw-text-secondary); font-size: 0.875rem; }
.field-error { color: var(--sw-danger); font-size: 0.9375rem; font-weight: 600; }
.field-effective { color: var(--sw-text-secondary); font-size: 0.875rem; font-variant-numeric: tabular-nums; }
fieldset { border: 0; margin: 0; padding: 0; min-width: 0; }
legend { padding: 0; margin-bottom: var(--space-2); }

input[type="text"], input[type="search"], input[type="password"], input[type="number"],
input[type="url"], input[type="time"], input[type="email"], input[type="date"],
input[type="datetime-local"], input:not([type]), select, textarea {
  width: 100%;
  min-height: var(--target);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--sw-control-border);
  border-radius: var(--radius-control);
  background-color: var(--sw-input);
  color: var(--sw-text);
  font: inherit;
  font-size: 1rem;
}
::placeholder { color: var(--sw-text-secondary); opacity: 0.85; }
input[type="number"] { font-variant-numeric: tabular-nums; }
input[type="search"] {
  padding-left: 2.5rem;
  background-image: var(--magnifier);
  background-repeat: no-repeat;
  background-position: 0.75rem center;
  background-size: 1.125rem;
}
textarea { min-height: 8rem; resize: vertical; line-height: 1.5; }
textarea.code, .code-editor { font-family: var(--mono); font-size: 0.875rem; tab-size: 2; }
/* Element-level specificity, so a page's own class can set another height. */
textarea:where(.code, .code-editor) { min-height: 16rem; }
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.5rem;
  background-image: var(--chevron);
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 1rem;
  cursor: pointer;
}
select[multiple], select[size] { padding-right: var(--space-3); background-image: none; }
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--sw-danger);
  border-width: 2px;
}
input[readonly], textarea[readonly] { background-color: var(--sw-raised); }
input[type="file"] { font: inherit; max-width: 100%; }
input[type="file"]::file-selector-button {
  min-height: var(--target);
  margin-right: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--sw-control-border);
  border-radius: var(--radius-control);
  background: var(--sw-raised);
  color: var(--sw-text);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--sw-raised-hover); }

.choice {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--target);
  font-weight: 400;
  cursor: pointer;
}
/* A checkbox field's help and error line up with its label text. */
.field-check .field-help,
.field-check .field-error { padding-left: calc(1.25rem + var(--space-2)); }
/* A file picker's button takes the secondary button look and a 44px target. */
input[type="file"] { max-width: 100%; }
input[type="file"]::file-selector-button {
  min-height: var(--target);
  margin-right: var(--space-3);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--sw-control-border);
  border-radius: var(--radius-control);
  background: var(--sw-raised);
  color: var(--sw-text);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--sw-raised-hover); }

input[type="checkbox"], input[type="radio"] {
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  accent-color: var(--sw-action);
  flex: none;
}

/* Switch: a native checkbox with role="switch" and a visible state word.
   On: gold track, dark knob, the word in gold. Off: input track, control
   border and a pale knob. */
.field-switch {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-content: start;
  align-items: center;
  column-gap: var(--space-4);
}
.field-switch > label, .field-switch > .field-help { grid-column: 2; }
.field-switch > label { cursor: pointer; min-height: var(--target); display: flex; align-items: center; }
.switch-control { display: inline-flex; align-items: center; gap: var(--space-2); min-height: var(--target); }
input.switch {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  width: 2.75rem;
  height: 1.5rem;
  margin: 0;
  flex: none;
  border: 1px solid var(--sw-control-border);
  border-radius: 999px;
  background: var(--sw-input);
  cursor: pointer;
  transition: background-color var(--transition), border-color var(--transition);
}
input.switch::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0.1875rem;
  width: 1.0625rem;
  height: 1.0625rem;
  border-radius: 50%;
  background: var(--sw-text);
  transform: translateY(-50%);
  transition: transform var(--transition);
}
input.switch:checked { background: var(--sw-action); border-color: var(--sw-action); }
input.switch:checked::after { background: var(--sw-on-action); transform: translate(1.1875rem, -50%); }
input.switch:disabled { opacity: 0.55; cursor: not-allowed; }
.switch-state { min-width: 1.75rem; font-size: 0.875rem; font-weight: 600; color: var(--sw-text-secondary); }
.switch-state::after { content: attr(data-word-off); }
.switch:checked + .switch-state { color: var(--sw-action); }
.switch:checked + .switch-state::after { content: attr(data-word-on); }

.form-grid { display: grid; gap: var(--space-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); }
.form-grid .field + .field { margin-top: 0; }
.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.form-state { color: var(--sw-text-secondary); font-size: 0.9375rem; }

/* Filter bar: full-width search, labelled selects in a row, Apply filters
   (secondary, search icon) and Reset (quiet). A plain GET form. */
.filter-bar { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-4); }
.filter-bar-fields { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr)); }
.filter-bar-fields .field + .field { margin-top: 0; }
.filter-bar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.panel > .filter-bar:last-child { margin-bottom: 0; }

/* ===== Status pills ===== */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.1875rem 0.625rem;
  border: 1px solid var(--sw-edge);
  border-radius: 999px;
  background: var(--sw-raised);
  color: var(--sw-text);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.35;
  white-space: nowrap;
}
.badge .icon { width: 1em; height: 1em; }
.badge-dot { width: 0.5rem; height: 0.5rem; flex: none; border-radius: 50%; background: currentColor; }
.badge-success { color: var(--sw-success); background: rgb(95 217 154 / 0.12); border-color: rgb(95 217 154 / 0.35); }
.badge-warning { color: var(--sw-warning); background: rgb(242 195 91 / 0.12); border-color: rgb(242 195 91 / 0.35); }
.badge-danger { color: var(--sw-danger); background: rgb(255 138 128 / 0.12); border-color: rgb(255 138 128 / 0.35); }
.badge-info { color: var(--sw-link-focus); background: rgb(114 215 255 / 0.1); border-color: rgb(114 215 255 / 0.3); }
.badge-neutral { color: var(--sw-text-secondary); }
/* A pill whose words may be long (a draft state with a timestamp) wraps. */
.badge-wrap { white-space: normal; overflow-wrap: anywhere; align-items: flex-start; border-radius: 0.875rem; }
.badge-wrap .badge-dot { margin-top: 0.3125rem; }

/* ===== Alerts ===== */
.status-region:empty { display: none; }
.status-region { margin-bottom: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.alert {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--sw-edge);
  border-left-width: 3px;
  border-radius: var(--radius-control);
  background: var(--sw-panel);
}
.alert .icon { margin-top: 0.1rem; }
.alert-success { border-left-color: var(--sw-success); }
.alert-success .icon { color: var(--sw-success); }
.alert-warning { border-left-color: var(--sw-warning); }
.alert-warning .icon { color: var(--sw-warning); }
.alert-error { border-left-color: var(--sw-danger); }
.alert-error .icon { color: var(--sw-danger); }
.alert-info { border-left-color: var(--sw-link-focus); }
.alert-info .icon { color: var(--sw-link-focus); }

/* ===== Tabs (links; each tab is an addressable URL) ===== */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-2);
  margin-bottom: var(--space-6);
  border-bottom: 1px solid var(--sw-divider);
}
.tabs a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding: var(--space-2) var(--space-3);
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--sw-text-secondary);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9375rem;
}
.tabs a:hover { color: var(--sw-text); }
.tabs a[aria-current="page"] { color: var(--sw-text); border-bottom-color: var(--sw-action); }

/* ===== Tables ===== */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-well);
}
.table { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.table th, .table td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--sw-divider);
}
.table thead th { background: var(--sw-raised); font-weight: 600; font-size: 0.875rem; white-space: nowrap; }
.table tbody th { font-weight: 600; }
.table tbody tr:last-child > * { border-bottom: 0; }
.table .num { text-align: right; font-variant-numeric: tabular-nums; }
.table td:has(> .overflow-menu), .table td.actions { width: 1%; padding-block: var(--space-1); vertical-align: middle; }
/* A short table whose rows hold overflow menus lets the menus overhang it. */
.table-wrap.table-wrap-menus { overflow: visible; }

/* Stacked cards on narrow screens: add data-label to each cell. */
@media (max-width: 40rem) {
  .table-stack thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .table-stack, .table-stack tbody, .table-stack tr, .table-stack td, .table-stack tbody th { display: block; width: 100%; }
  .table-stack tr { border-bottom: 1px solid var(--sw-divider); padding: var(--space-2) 0; }
  .table-stack td, .table-stack tbody th { border: 0; padding: var(--space-1) var(--space-3); }
  .table-stack td[data-label]::before, .table-stack tbody th[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--sw-text-secondary);
  }
  .table-stack .num { text-align: left; }
  .table-stack td:has(> .overflow-menu) { width: 100%; }
  .table-stack .popover-panel { left: 0; right: auto; }
}

/* ===== Icon wells, stat tiles, control cards, quick access, ranked lists ===== */
.icon-well {
  display: inline-grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  flex: none;
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-well);
  background: var(--sw-raised);
  color: var(--sw-icon);
}
.icon-well .icon { width: 1.5rem; height: 1.5rem; }

/* Stat tile: icon well, label, large tabular number and a caption naming what
   is counted. Place tiles in <dl class="stat-row">. A linked tile's label is
   the link and its hit area covers the tile. */
.stat-row {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  margin: 0 0 var(--space-4);
}
.stat-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 6.5rem;
  min-width: 0;
  padding: var(--space-4) var(--space-4) var(--space-4) calc(var(--space-4) + 3rem + var(--space-4));
  background: var(--sw-panel);
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-panel);
}
.stat-tile dt { font-size: 0.9375rem; font-weight: 500; }
.stat-tile .icon-well { position: absolute; left: var(--space-4); top: 50%; transform: translateY(-50%); }
.stat-value { margin: 0; font-size: 1.875rem; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.stat-caption { margin: 0; font-size: 0.8125rem; color: var(--sw-text-secondary); }
.panel .stat-tile, .panel .stat { background: var(--sw-inset); }
.stat-link { color: inherit; text-decoration: none; }
.stat-link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.stat-link:hover { text-decoration: underline; }
.stat-tile:has(.stat-link:hover) { border-color: var(--sw-control-border); }
@supports selector(:has(*)) {
  .stat-link:focus-visible { outline: none; }
  .stat-tile:has(.stat-link:focus-visible) { outline: 3px solid var(--sw-link-focus); outline-offset: 2px; }
}

/* The older compact stat list keeps its markup and takes the tile look. */
.stat-list { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr)); margin: 0; }
.stat { padding: var(--space-3) var(--space-4); border: 1px solid var(--sw-edge); border-radius: var(--radius-panel); background: var(--sw-panel); }
.stat dt { color: var(--sw-text-secondary); font-size: 0.875rem; font-weight: 600; }
.stat dd { margin: 0; font-size: 1.625rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* Control card: icon well, setting name, one-line effect and one control. */
.control-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.control-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-content: start;
  gap: var(--space-1) var(--space-3);
  min-width: 0;
  padding: var(--space-4);
  background: var(--sw-inset);
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-panel);
}
.control-card > .icon-well { grid-row: span 2; }
.control-card h3 { font-size: 1rem; align-self: end; }
.control-card-effect { color: var(--sw-text-secondary); font-size: 0.875rem; }
.control-card-control { grid-column: 1 / -1; margin-top: var(--space-2); }

/* Quick access tile: a link with icon, destination, short caption and chevron. */
.quick-grid { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr)); }
.quick-tile {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  min-height: 4rem;
  padding: var(--space-3);
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-well);
  background: var(--sw-inset);
  color: var(--sw-text);
  text-decoration: none;
  transition: border-color var(--transition);
}
.quick-tile:hover { border-color: var(--sw-control-border); }
.quick-tile > .icon:first-child { width: 1.75rem; height: 1.75rem; color: var(--sw-icon); }
.quick-tile > .icon:last-child { color: var(--sw-text-secondary); }
.quick-tile-name { display: block; font-weight: 600; font-size: 0.9375rem; }
.quick-tile-caption { display: block; font-size: 0.8125rem; color: var(--sw-text-secondary); }

/* Ranked list: ordinal numeral in a gold ring, name and a tabular value. */
.ranked-list { list-style: none; margin: 0; padding: 0; }
.ranked-list > li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--target);
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--sw-divider);
}
.ranked-list > li:last-child { border-bottom: 0; }
.ranked-ordinal {
  display: inline-grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  border: 1.5px solid var(--sw-action);
  border-radius: 50%;
  color: var(--sw-action);
  font-size: 0.875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.ranked-value { color: var(--sw-text-secondary); font-variant-numeric: tabular-nums; text-align: right; }

/* Image slot for Persona cards and Lorebook rows; without an image it shows
   the brand emblem. */
.image-slot {
  display: block;
  flex: none;
  width: 4rem;
  height: 4rem;
  overflow: hidden;
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-well);
  background: var(--sw-raised);
}
.image-slot img { display: block; width: 100%; height: 100%; object-fit: cover; }
.image-slot-emblem { background: var(--sw-raised) url("/static/img/brand/emblem.webp") center / 64% no-repeat; }

/* ===== Lists, key/values, cards ===== */
.kv { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-4); margin: 0; }
.kv dt { color: var(--sw-text-secondary); font-weight: 600; }
.kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 30rem) { .kv { grid-template-columns: 1fr; } .kv dd { margin-bottom: var(--space-2); } }

.item-list { list-style: none; padding: 0; margin: 0; }
.item-list > li { padding: var(--space-3) 0; border-bottom: 1px solid var(--sw-divider); }
.item-list > li:last-child { border-bottom: 0; }

.card {
  padding: var(--space-4);
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-well);
  background: var(--sw-inset);
  min-width: 0;
}
.card-header { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-2); }

pre, .pre {
  margin: 0;
  padding: var(--space-3);
  background: var(--sw-input);
  border: 1px solid var(--sw-divider);
  border-radius: var(--radius-control);
  overflow: auto;
  max-height: 32rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 0.875rem;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.toolbar .field { flex: 1 1 12rem; }
.toolbar .field + .field { margin-top: 0; }

/* Empty state: optional hologram, a title, one line and one action. */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-8) var(--space-4);
  text-align: center;
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-panel);
  background: var(--sw-inset);
  color: var(--sw-text-secondary);
}
.empty-title { font-weight: 600; font-size: 1.0625rem; color: var(--sw-text); }
.empty .btn { margin-top: var(--space-3); }
.holo {
  display: block;
  width: 6rem;
  height: 6rem;
  margin-bottom: var(--space-2);
  background: center / contain no-repeat;
}
:root[data-decor="full"] .holo-core { background-image: url("/static/img/holo/core.webp"); }
:root[data-decor="full"] .holo-archive { background-image: url("/static/img/holo/archive.webp"); }
:root[data-decor="full"] .holo-droid { background-image: url("/static/img/holo/droid.webp"); }

/* Disclosure: the summary is a row ending in a chevron that turns when open. */
details.disclosure > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--target);
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}
details.disclosure > summary::-webkit-details-marker { display: none; }
details.disclosure > summary > .icon:first-child { color: var(--sw-icon); }
details.disclosure > summary::after {
  content: "";
  width: 1rem;
  height: 1rem;
  flex: none;
  margin-left: auto;
  background: var(--chevron) center / contain no-repeat;
  transform: rotate(-90deg);
  transition: transform var(--transition);
}
details.disclosure[open] > summary::after { transform: none; }
details.disclosure[open] > summary { margin-bottom: var(--space-3); }

/* Create flow: a disclosure whose summary is the page's gold button. While it
   is open the form's own Create button is the gold one, so the toggle takes
   the secondary look. */
.create-popover { margin-left: auto; }
.create-popover[open] > summary.btn-primary {
  background: var(--sw-raised);
  border-color: var(--sw-control-border);
  color: var(--sw-text);
}
.create-popover[open] > summary.btn-primary:hover { background: var(--sw-raised-hover); }
.create-panel { width: min(26rem, calc(100vw - 3rem)); }
.create-panel h3, .create-inline h3 { font-size: 1.0625rem; }
.create-purpose { margin: var(--space-1) 0 var(--space-4); }
/* With nothing to list, the form shows in place below the empty state. */
.create-inline {
  max-width: 36rem;
  margin-top: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--sw-edge);
  border-radius: var(--radius-panel);
  background: var(--sw-inset);
}

/* Page-level alerts above a form, and a panel holding destructive actions. */
.page-alerts { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-4); }
.page-alerts:focus { outline: 3px solid var(--sw-link-focus); outline-offset: 2px; }
.danger-panel { border-color: var(--sw-danger); }
.danger-panel h2, .danger-panel h2 > .icon { color: var(--sw-danger); }

/* A delete confirmation inside an overflow menu. */
.menu-list .confirm { display: block; }
.menu-list .confirm[open] > summary { margin-bottom: var(--space-1); }
.menu-list .confirm-panel { max-width: none; background: var(--sw-inset); }
.menu-list .confirm-panel .btn { width: 100%; }

/* ===== Edge light (decoration): glow on edged surfaces, corner brackets on
   the ends of a bracketed stat row. Static; never marks state or focus. ===== */
:root[data-decor="full"] .panel,
:root[data-decor="full"] .stat-tile,
:root[data-decor="full"] .stat,
:root[data-decor="full"] .icon-well {
  box-shadow: var(--edge-glow);
}
:root[data-decor="full"] .stat-row-bracketed > .stat-tile:first-child::before,
:root[data-decor="full"] .stat-row-bracketed > .stat-tile:last-child::after {
  content: "";
  position: absolute;
  inset: -5px;
  pointer-events: none;
  background-repeat: no-repeat;
}
:root[data-decor="full"] .stat-row-bracketed > .stat-tile:first-child::before {
  background-image:
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong)),
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong)),
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong)),
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong));
  background-size: 1rem 2px, 2px 1rem, 1rem 2px, 2px 1rem;
  background-position: left top, left top, left bottom, left bottom;
}
:root[data-decor="full"] .stat-row-bracketed > .stat-tile:last-child::after {
  background-image:
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong)),
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong)),
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong)),
    linear-gradient(var(--sw-edge-strong), var(--sw-edge-strong));
  background-size: 1rem 2px, 2px 1rem, 1rem 2px, 2px 1rem;
  background-position: right top, right top, right bottom, right bottom;
}

/* ===== HTMX request states (indicator styles are ours; htmx's are disabled) ===== */
.htmx-indicator { opacity: 0; transition: opacity var(--transition); }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }
.spinner {
  display: inline-block;
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--sw-control-border);
  border-top-color: var(--sw-action);
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
[aria-busy="true"] { cursor: progress; }

/* ===== Responsive decoration: below 720px the page header is plain ===== */
@media (max-width: 45rem) {
  .main-column::before, .flavor { display: none; }
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat-tile { padding-left: var(--space-4); padding-top: calc(var(--space-4) + 3rem + var(--space-2)); }
  .stat-tile .icon-well { top: var(--space-4); transform: none; }
}
@media (max-width: 22.5rem) {
  .stat-row { grid-template-columns: minmax(0, 1fr); }
}

/* ===== Reduce decoration, higher contrast and forced colors ===== */
:root[data-decor="reduced"] .flavor,
:root[data-decor="reduced"] .rail-decor,
:root[data-decor="reduced"] .holo { display: none; }

@media (prefers-contrast: more) {
  :root[data-decor] body { background-image: none; }
  .main-column::before, .flavor, .rail-decor, .holo,
  .stat-row-bracketed > .stat-tile::before, .stat-row-bracketed > .stat-tile::after { display: none; }
  :root[data-decor] .panel, :root[data-decor] .stat-tile, :root[data-decor] .stat, :root[data-decor] .icon-well { box-shadow: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

@media (forced-colors: active) {
  .main-column::before, .flavor, .rail-decor, .holo, .footer-emblem,
  .stat-row-bracketed > .stat-tile::before, .stat-row-bracketed > .stat-tile::after { display: none; }
  .btn, .badge, .alert, .panel, .card, .stat-tile, .control-card, .quick-tile, .empty,
  input.switch, .tabs a[aria-current="page"], .nav-link.active {
    border: 1px solid CanvasText;
  }
  input.switch { forced-color-adjust: none; background: Canvas; border-color: CanvasText; }
  input.switch::after { background: CanvasText; }
  input.switch:checked { background: Highlight; border-color: Highlight; }
  input.switch:checked::after { background: HighlightText; }
  select { appearance: auto; background-image: none; }
  input[type="search"] { background-image: none; padding-left: var(--space-3); }
  .nav-link.active, .tabs a[aria-current="page"] { outline: 2px solid Highlight; }
  .badge-dot { forced-color-adjust: none; background: CanvasText; }
}
