/* ---------- Design tokens ---------- */
:root {
  --ground: #f6f6f9;
  --surface: #ffffff;
  --surface-2: #f0f0f4;
  --surface-hover: #ebebf0;
  --border: #e7e7ee;
  --border-strong: #d6d6e0;
  --text: #17181c;
  --text-muted: #6b6e78;
  --text-faint: #9a9da8;
  --primary: #191a1f;
  --primary-hover: #2c2d34;
  --primary-text: #ffffff;
  --accent: #5a5ed6;
  --accent-soft: rgba(90, 94, 214, 0.14);
  --danger: #c33b30;
  --shadow-sm: 0 1px 2px rgba(20, 20, 40, 0.05);
  --shadow-md: 0 6px 22px rgba(20, 20, 45, 0.1);
  --shadow-lg: 0 18px 50px rgba(20, 20, 45, 0.18);

  /* visibility badge tints */
  --vis-private-bg: #f6ecda;
  --vis-private-fg: #8a6321;
  --vis-team-bg: #e6ecf7;
  --vis-team-fg: #3a5488;
  --vis-public-bg: #e5f1e7;
  --vis-public-fg: #37714b;

  /* tile swatches */
  --tile-0-bg: #e6ecf6;
  --tile-0-fg: #46597c;
  --tile-1-bg: #e8f0e7;
  --tile-1-fg: #4c6a4e;
  --tile-2-bg: #f2e8e1;
  --tile-2-fg: #895944;
  --tile-3-bg: #f3efdd;
  --tile-3-fg: #7a6730;
  --tile-4-bg: #efe8f2;
  --tile-4-fg: #6b5079;
  --tile-5-bg: #e3eff0;
  --tile-5-fg: #3d6a6d;

  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --radius: 14px;
  --radius-sm: 9px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ground: #0d0e11;
    --surface: #16171b;
    --surface-2: #1d1f24;
    --surface-hover: #24262c;
    --border: #26282f;
    --border-strong: #363943;
    --text: #eef0f3;
    --text-muted: #9ea2ac;
    --text-faint: #6f727c;
    --primary: #eef0f3;
    --primary-hover: #dcdee3;
    --primary-text: #17181c;
    --accent: #8285ea;
    --accent-soft: rgba(130, 133, 234, 0.18);
    --danger: #e2685d;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 6px 22px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 18px 50px rgba(0, 0, 0, 0.6);

    --vis-private-bg: #2f2718;
    --vis-private-fg: #d8b473;
    --vis-team-bg: #1c2434;
    --vis-team-fg: #9fb6e0;
    --vis-public-bg: #182a1e;
    --vis-public-fg: #82c295;

    --tile-0-bg: #1b2331;
    --tile-0-fg: #9fb4d6;
    --tile-1-bg: #1d2921;
    --tile-1-fg: #a6c6a8;
    --tile-2-bg: #2c221f;
    --tile-2-fg: #d5a892;
    --tile-3-bg: #2a2617;
    --tile-3-fg: #cbb271;
    --tile-4-bg: #261e2d;
    --tile-4-fg: #bfa6cf;
    --tile-5-bg: #192626;
    --tile-5-fg: #8fc4c6;
  }
}

* {
  box-sizing: border-box;
}
[hidden] {
  /* biome-ignore lint/complexity/noImportantStyles: [hidden] must override any author display rule */
  display: none !important;
}
body {
  margin: 0;
  background: var(--ground);
  color: var(--text);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}
button {
  font-family: inherit;
  cursor: pointer;
}
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ---------- Auth splash ---------- */
.auth-splash {
  min-height: 100vh;
  display: grid;
  /* Two rows: the header mount (auto, sized to its own content) then
     everything else (1fr). Without this, both children are auto-sized grid
     items and `place-items: center` shrinks the mount to its content width
     and centers it on both axes — a floating pill above the card, not a
     header bar (Phase 8 fix wave). */
  grid-template-rows: auto 1fr;
  place-items: center;
  padding: 24px;
}
/* Override place-items' centering for the header mount only: it must span
   the full width and sit at the top of its row, while the signed-out card /
   device card below it stays centered via the inherited place-items rule. */
.auth-splash > [id$="-topbar-mount"] {
  justify-self: stretch;
  align-self: start;
  width: 100%;
}

.device-card {
  width: min(30rem, 100%);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 28px;
}

.device-card h1 {
  margin: 0 0 14px;
  font-size: 20px;
}

.device-card p {
  color: var(--text-muted);
  line-height: 1.5;
  margin: 0 0 12px;
}

.device-card code {
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--text);
}

.device-hint {
  font-size: 13px;
}

.device-actions {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}

/* These reuse the design tokens defined at the top of this file and match
   .device-card's px-based scale. The deliberate difference is width: 44rem
   keeps the numbered steps on one line each. The curl line doesn't actually
   fit at this width either — measured at ~803px wider than the <pre> at a
   1280px viewport — it scrolls inside the <pre> at any width worth using, so
   width here is chosen for the steps, not for that line. */
.connect-card {
  width: min(44rem, 100%);
  /* .auth-splash (above) is display: grid, and a grid item's automatic
     minimum size is its min-content width, not 0 — so without this override
     the <pre>'s long unbreakable curl line inflates the grid column past the
     declared width, dragging the stretched topbar mount off-screen and
     making the whole page scroll horizontally. */
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 28px;
}

.connect-card h1 {
  margin: 0 0 14px;
  font-size: 20px;
}

.connect-card p {
  color: var(--text-muted);
  line-height: 1.5;
  margin: 0 0 12px;
}

/* Scrolls rather than wraps: a soft-wrapped curl line still copies correctly,
   but reads as broken, and the reader is being asked to trust this text. */
.connect-card pre {
  overflow-x: auto;
  margin: 0;
  padding: 16px;
  background: var(--surface-2);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.6;
  color: var(--text);
}

.connect-actions {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}

.connect-hint {
  font-size: 13px;
  color: var(--text-muted);
  margin: 10px 0 0;
}

/* ---------- Top bar ---------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 18px;
  height: 58px;
  padding: 0 22px;
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--border);
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
  /* header.js renders this as <a class="brand" href="/">; without this the
     wordmark inherits the UA's blue, underlined link styling everywhere the
     header mounts (Phase 8 fix wave). */
  color: inherit;
  text-decoration: none;
}
.brand-mark {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--primary);
  position: relative;
  flex-shrink: 0;
}
.brand-mark::after {
  content: "";
  position: absolute;
  inset: 7px;
  border: 1.5px solid var(--primary-text);
  border-radius: 2px;
  opacity: 0.9;
}
.brand-name {
  font-weight: 640;
  font-size: 16px;
  letter-spacing: -0.02em;
}
.brand-name span {
  color: var(--text-faint);
  font-weight: 500;
}

.search {
  flex: 1;
  max-width: 440px;
  margin: 0 auto;
  position: relative;
  display: flex;
  align-items: center;
}
.search svg {
  position: absolute;
  left: 12px;
  width: 16px;
  height: 16px;
  color: var(--text-faint);
  pointer-events: none;
}
.search input {
  width: 100%;
  height: 38px;
  padding: 0 14px 0 36px;
  background: var(--surface-2);
  border: 1px solid transparent;
  border-radius: 10px;
  color: var(--text);
  font-size: 14px;
  transition:
    background 0.15s,
    border-color 0.15s;
}
.search input::placeholder {
  color: var(--text-faint);
}
.search input:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--border-strong);
}
.search input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  margin-left: auto;
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 38px;
  padding: 0 15px;
  border-radius: 10px;
  font-size: 13.5px;
  font-weight: 560;
  border: 1px solid transparent;
  transition:
    background 0.15s,
    border-color 0.15s,
    transform 0.05s;
  /* .btn is applied to both <button> and <a>; without this reset an anchor
     takes the UA's blue, underlined link styling (the same defect .brand
     fixes above). color: inherit is only a fallback for a bare .btn anchor —
     .btn-primary and .btn-ghost below both set their own color and win on
     source order. */
  color: inherit;
  text-decoration: none;
}
.btn:active {
  transform: translateY(0.5px);
}
.btn-primary {
  background: var(--primary);
  color: var(--primary-text);
}
.btn-primary:hover {
  background: var(--primary-hover);
}
.btn-ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--border-strong);
}
.btn-ghost:hover {
  background: var(--surface-2);
}
.btn svg {
  width: 15px;
  height: 15px;
}

.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: none;
  background: linear-gradient(140deg, #6d6fdc, #4a4cc0);
  color: #fff;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  display: grid;
  place-items: center;
}

/* ---------- Layout ---------- */
.wrap {
  max-width: 1160px;
  margin: 0 auto;
  padding: 26px 22px 80px;
}
.page-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.page-title {
  font-size: 23px;
  font-weight: 660;
  letter-spacing: -0.02em;
  margin: 0;
}
.page-sub {
  color: var(--text-muted);
  font-size: 13px;
  margin: 4px 0 0;
}

.subbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--border);
}
.tabs {
  display: flex;
  gap: 2px;
}
.tab {
  background: none;
  border: none;
  padding: 10px 13px 12px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--text-muted);
  position: relative;
  border-radius: 6px 6px 0 0;
}
.tab:hover {
  color: var(--text);
}
.tab[aria-selected="true"] {
  color: var(--text);
}
.tab[aria-selected="true"]::after {
  content: "";
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
}
.tab .count {
  color: var(--text-faint);
  margin-left: 6px;
  font-size: 11px;
}

.filter {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 8px;
}
.filter label {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
}
.select {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.select select {
  appearance: none;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 13px;
  font-family: var(--font-sans);
  padding: 6px 28px 6px 11px;
  border-radius: 8px;
  cursor: pointer;
}
.select svg {
  position: absolute;
  right: 9px;
  width: 13px;
  height: 13px;
  color: var(--text-faint);
  pointer-events: none;
}

/* ---------- Grid + cards ---------- */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: 18px;
}
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-sm);
  transition:
    border-color 0.15s,
    box-shadow 0.15s,
    transform 0.15s;
  position: relative;
}
.card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.tile {
  position: relative;
  aspect-ratio: 16 / 10;
  display: grid;
  place-items: center;
  cursor: pointer;
  overflow: hidden;
}
.tile.t0 {
  background: var(--tile-0-bg);
  color: var(--tile-0-fg);
}
.tile.t1 {
  background: var(--tile-1-bg);
  color: var(--tile-1-fg);
}
.tile.t2 {
  background: var(--tile-2-bg);
  color: var(--tile-2-fg);
}
.tile.t3 {
  background: var(--tile-3-bg);
  color: var(--tile-3-fg);
}
.tile.t4 {
  background: var(--tile-4-bg);
  color: var(--tile-4-fg);
}
.tile.t5 {
  background: var(--tile-5-bg);
  color: var(--tile-5-fg);
}
.tile::before {
  /* faint frame, like a mounted piece */
  content: "";
  position: absolute;
  inset: 14px;
  border: 1px solid currentColor;
  opacity: 0.16;
  border-radius: 4px;
}
.tile-glyph {
  width: 40px;
  height: 40px;
  opacity: 0.85;
}

/* ---------- Skeleton (loading) ---------- */
.card.skeleton {
  pointer-events: none;
}
.card.skeleton .tile {
  background: var(--surface-2);
  color: transparent;
  cursor: default;
}
.card.skeleton .tile::before {
  display: none;
}
.card.skeleton .tile::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    color-mix(in srgb, var(--surface) 55%, transparent) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  animation: skeleton-shimmer 1.3s ease-in-out infinite;
}
@keyframes skeleton-shimmer {
  100% {
    transform: translateX(100%);
  }
}

.badge {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  font-weight: 500;
}
.badge svg {
  width: 11px;
  height: 11px;
}
.badge.private {
  background: var(--vis-private-bg);
  color: var(--vis-private-fg);
}
.badge.team {
  background: var(--vis-team-bg);
  color: var(--vis-team-fg);
}
.badge.public {
  background: var(--vis-public-bg);
  color: var(--vis-public-fg);
}

.kebab {
  position: absolute;
  top: 9px;
  right: 9px;
  z-index: 3;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border: none;
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  color: var(--text);
  backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
  opacity: 0;
  transition:
    opacity 0.12s,
    background 0.12s;
}
.kebab svg {
  width: 17px;
  height: 17px;
}
.card:hover .kebab,
.kebab:focus-visible {
  opacity: 1;
}
.kebab:hover {
  background: var(--surface);
}

.card-body {
  padding: 13px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.card-title {
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.35;
  margin: 0;
  letter-spacing: -0.01em;
  cursor: pointer;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-title:hover {
  color: var(--accent);
}
.card-meta {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text-muted);
}
.card-meta .dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--text-faint);
}
.card-meta .owner-you {
  color: var(--text);
}

/* ---------- Popover menu ---------- */
.menu {
  position: absolute;
  z-index: 60;
  min-width: 194px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 11px;
  box-shadow: var(--shadow-lg);
  padding: 5px;
  overflow: hidden;
}
.menu button,
.menu .menu-static {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  background: none;
  color: var(--text);
  font-size: 13px;
  text-align: left;
  border-radius: 7px;
}
.menu button:hover {
  background: var(--surface-2);
}
.menu button svg {
  width: 15px;
  height: 15px;
  color: var(--text-muted);
}
.menu .sep {
  height: 1px;
  background: var(--border);
  margin: 4px 2px;
}
.menu button.danger {
  color: var(--danger);
}
.menu button.danger svg {
  color: var(--danger);
}
.menu-label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  padding: 6px 10px 3px;
}

/* ---------- Empty state ---------- */
.empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 70px 20px;
  color: var(--text-muted);
}
.empty svg {
  width: 42px;
  height: 42px;
  color: var(--text-faint);
  margin-bottom: 14px;
}
.empty h3 {
  margin: 0 0 6px;
  font-size: 16px;
  color: var(--text);
  font-weight: 600;
}
.empty p {
  margin: 0 0 18px;
  font-size: 13.5px;
}

/* ---------- Modal ---------- */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(15, 15, 30, 0.45);
  backdrop-filter: blur(3px);
  display: grid;
  place-items: center;
  padding: 20px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s;
}
.scrim.open {
  opacity: 1;
  pointer-events: auto;
}
.modal {
  width: 100%;
  max-width: 460px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow-lg);
  transform: translateY(8px) scale(0.99);
  transition: transform 0.16s;
  overflow: hidden;
}
.scrim.open .modal {
  transform: none;
}
.modal-head {
  padding: 20px 22px 6px;
}
.modal-head h2 {
  margin: 0;
  font-size: 17px;
  font-weight: 640;
  letter-spacing: -0.01em;
}
.modal-head p {
  margin: 5px 0 0;
  font-size: 13px;
  color: var(--text-muted);
}
.modal-body {
  padding: 18px 22px;
  display: flex;
  flex-direction: column;
  gap: 15px;
}
.modal-foot {
  padding: 14px 22px 20px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.field label {
  font-size: 12.5px;
  font-weight: 560;
  color: var(--text-muted);
}
.field input[type="text"],
.field select {
  height: 38px;
  padding: 0 11px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 9px;
  color: var(--text);
  font-size: 14px;
  font-family: var(--font-sans);
}
.field select {
  appearance: none;
}
.dropzone {
  border: 1.5px dashed var(--border-strong);
  border-radius: 12px;
  padding: 26px 16px;
  text-align: center;
  color: var(--text-muted);
  background: var(--surface-2);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition:
    border-color 0.15s,
    background 0.15s;
}
.dropzone svg {
  width: 26px;
  height: 26px;
  color: var(--text-faint);
}
.dropzone strong {
  color: var(--text);
  font-weight: 580;
  font-size: 13.5px;
}
.dropzone small {
  font-size: 12px;
}
.dropzone.filled {
  border-style: solid;
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* ---------- Settings slide-over ---------- */
.sheet-scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(15, 15, 30, 0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s;
}
.sheet-scrim.open {
  opacity: 1;
  pointer-events: auto;
}
.sheet {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 91;
  width: 452px;
  max-width: 92vw;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  transform: translateX(100%);
  transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  display: flex;
  flex-direction: column;
}
.sheet.open {
  transform: none;
}
.sheet-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid var(--border);
}
.sheet-head h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 620;
}
.icon-btn {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: none;
  background: none;
  color: var(--text-muted);
  display: grid;
  place-items: center;
}
.icon-btn:hover {
  background: var(--surface-2);
  color: var(--text);
}
.icon-btn svg {
  width: 18px;
  height: 18px;
}
.sheet-body {
  padding: 20px;
  overflow-y: auto;
}
.sheet-body > p {
  margin: 0 0 16px;
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.5;
}

.token-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 0;
  border-top: 1px solid var(--border);
}
.token-row:last-child {
  border-bottom: 1px solid var(--border);
}
.token-prefix {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
}
.token-times {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 3px;
}
.token-row .grow {
  flex: 1;
  min-width: 0;
}
.link-btn {
  background: none;
  border: none;
  color: var(--danger);
  font-size: 12.5px;
  font-weight: 560;
  padding: 4px 6px;
  border-radius: 6px;
}
.link-btn:hover {
  background: var(--surface-2);
}
.revoked {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-faint);
  border: 1px solid var(--border);
  padding: 2px 6px;
  border-radius: 5px;
}

.secret {
  margin-top: 14px;
  padding: 14px;
  border: 1px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 11px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.secret .warn {
  font-size: 12px;
  color: var(--text);
  font-weight: 560;
  display: flex;
  gap: 7px;
  align-items: center;
}
.secret .warn svg {
  width: 15px;
  height: 15px;
  color: var(--accent);
  flex-shrink: 0;
}
.secret code {
  font-family: var(--font-mono);
  font-size: 12.5px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 11px;
  word-break: break-all;
  color: var(--text);
}
.secret-actions {
  display: flex;
  gap: 8px;
}
.btn-sm {
  height: 32px;
  padding: 0 12px;
  font-size: 12.5px;
  border-radius: 8px;
}

/* ---------- Toast ---------- */
.toasts {
  position: fixed;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 120;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
}
.toast {
  background: var(--primary);
  color: var(--primary-text);
  font-size: 13px;
  font-weight: 520;
  padding: 10px 16px;
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  display: flex;
  align-items: center;
  gap: 9px;
  animation: toast-in 0.2s ease;
}
.toast svg {
  width: 15px;
  height: 15px;
}
.toast.error {
  border-left: 3px solid var(--danger);
}
.toast.error svg {
  color: var(--danger);
}
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.note {
  max-width: 1160px;
  margin: 0 auto;
  padding: 12px 22px 0;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-faint);
  letter-spacing: 0.02em;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    /* biome-ignore lint/complexity/noImportantStyles: the reduced-motion override must beat every higher-specificity transition/animation to actually stop motion */
    transition: none !important;
    /* biome-ignore lint/complexity/noImportantStyles: the reduced-motion override must beat every higher-specificity transition/animation to actually stop motion */
    animation: none !important;
  }
}
@media (max-width: 640px) {
  .search {
    max-width: none;
  }
  .brand-name span {
    display: none;
  }
  .btn-primary .label {
    display: none;
  }
  .btn-primary {
    padding: 0 11px;
  }
}

/* ---------- Artifact viewer (Phase 8) ---------- */
.viewer-body {
  /* The header, plus the older-version strip when it is showing. The frame is
     sized against this, so the strip cannot push the page into outer scroll. */
  --chrome-h: 58px;
  margin: 0;
  overflow: hidden;
}
.viewer-body .topbar {
  position: static;
}
.viewer-titles {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}
.viewer-title {
  font-weight: 600;
  font-size: 14px;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.viewer-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
}
.viewer-version {
  font-family: var(--font-mono);
}
.viewer-meta .badge {
  /* .badge (above, in the card-tile section) is written for the card tile,
     whose ancestor .card is position: relative — absolute + top/left pins it
     to that corner. .viewer-meta has no positioned ancestor, so without this
     override the badge escapes flow entirely and pins to the viewport's
     top-left, overlapping the brand mark instead of sitting inline on the
     meta line (Phase 8 fix wave). top/left/z-index have no effect once
     position is static, so overriding position alone is enough. */
  position: static;
}
#viewer-frame {
  display: block;
  width: 100%;
  height: calc(100dvh - var(--chrome-h));
  border: 0;
  background: var(--surface);
}
.viewer-noscript {
  display: block;
  padding: 40px;
  text-align: center;
  color: var(--text-muted);
}
@media (max-width: 640px) {
  .viewer-meta {
    display: none;
  }
}
.viewer-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 34px;
  padding: 0 22px;
  font-size: 12px;
  color: var(--vis-private-fg);
  background: var(--vis-private-bg);
  border-bottom: 1px solid var(--border);
}
.viewer-strip a {
  color: inherit;
  font-weight: 600;
}
/* Descendant selector is deliberate, not incidental: shareButton() gives this
   div both "menu-static" and "share-body", and the pre-existing
   ".menu .menu-static" rule (align-items: center; gap: 10px) is specificity
   0,2,0, higher than a bare ".share-body" (0,1,0) — so a bare selector here
   would lose on the conflicting properties regardless of source order.
   account.js solves the same shadowing problem for its menu header with
   inline style.cssText; this matches ".menu .menu-static"'s specificity
   instead and wins on source order (it comes later in the file). Do not
   simplify this back to ".share-body" — it would silently stop overriding
   align-items/gap. */
.menu .share-body {
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}
.share-label {
  font-size: 12px;
  color: var(--text-muted);
}

/* ---------- Not found (404) ---------- */
/* Padding for the pre-JS state: notfound.js swaps this id's class to
   .auth-splash (padding: 24px) once it runs, but a JS-disabled browser, curl,
   and the sandboxed frame (see below) never get that far, and body { margin:
   0 } would otherwise render the raw mount flush against the viewport edge.
   Safe to set unconditionally: 24px is the identical value .auth-splash's own
   padding resolves to, so once JS does run the higher-specificity id selector
   here just restates it. */
#notfound-mount {
  padding: 24px;
}
/* Layout comes from .auth-splash, which notfound.js puts on #notfound-mount:
   full-width header row above a centered card. Only the card is new here. */
/* This styles markup that normally never survives to be seen: the served 404's
   static fallback (functions/src/routes/serve.ts's OPAQUE_404_BODY and
   portal/404.html) is replaced by notfound.js on a normal load. It only
   renders when /styles.css loads but the JS module does not (spec §2.2 case
   1: the sandboxed frame, whose opaque origin turns the module script into a
   blocked cross-origin request). Left unstyled, its unclassed <a> keeps the
   UA default #0000EE, which against dark mode's --ground is ~2.05:1 — below
   WCAG AA. var(--accent) already resolves separately per theme (see the
   dark-mode block above), and meets AA against --ground in both. Scoped to an
   unclassed anchor so it can never touch .btn or any other styled link.

   A second, unfixable defect lives in this exact case: inside the viewer's
   sandboxed frame, this same fallback "Go to Exhibit" link navigates the
   IFRAME rather than the top window, because it is a plain <a> with no
   target. `target="_top"` would fix it, but SANDBOX in
   functions/src/viewerShell.ts deliberately omits `allow-top-navigation`, and
   Phase 8 §1.3 forbids adding it — that omission is exactly what closes the
   escalation the sandbox exists to prevent. Real, but out of reach here.
   Reachable only when the frame route serves 200 while the stored bytes are
   missing (this fallback body renders, but a same-tab "Go to Exhibit" click
   lands inside the frame instead of leaving it). Ruled cosmetic and left as
   written. */
#notfound-mount a:not([class]) {
  color: var(--accent);
}
.notfound-card {
  width: min(30rem, 100%);
  margin-top: 16px;
  padding: 32px 28px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}
.notfound-title {
  font-size: 19px;
  font-weight: 640;
  letter-spacing: -0.02em;
}
.notfound-body {
  color: var(--text-faint);
  font-size: 14px;
  line-height: 1.55;
  max-width: 24rem;
}
.notfound-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 6px;
}
