/* Spacing scale — typographic / editorial.
   Tight steps for inner UI rhythm; larger jumps for editorial breaks.
   When picking a value, prefer the nearest token over a magic number.
   Snap convention: 6→8, 10→12, 14/18→16, 20→24, 32→40, 48/72→64, 80/96/160→104. */
:root {
  --bg: #fafafa;
  --panel: #ffffff;
  --text: #1a1a1a;
  --muted: #666666;
  --accent: #2057a8;
  --pill-bg: #f0f0f0;
  --border: #e2e2e2;
  --border-soft: #ededed;
  --error: #b91c1c;
  --link: #2057a8;
  --font-ui: "Work Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-record: "Newsreader", Georgia, serif;
  --space-1: 4px;    /* hairline (within tightly grouped items) */
  --space-2: 8px;    /* snug (icon-label, dense UI internals) */
  --space-3: 12px;   /* small (button padding, list items) */
  --space-4: 16px;   /* base (paragraph rhythm) */
  --space-5: 24px;   /* medium (between content groups) */
  --space-6: 40px;   /* large (between page sections) */
  --space-7: 64px;   /* xlarge (around hero blocks) */
  --space-8: 104px;  /* page (dramatic editorial pause) */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 16px;
  line-height: 1.55;
}

.topnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: clamp(40px, 5vw, 48px);
  padding: 0 clamp(16px, 3vw, 36px);
  position: sticky;
  top: 0;
  background: var(--bg);
  z-index: 10;
  transition: transform 180ms ease-out;
  will-change: transform;
}
.topnav--hidden { transform: translateY(-100%); }
.topnav:focus-within { transform: translateY(0); }
/* Unified small-caps "index" treatment for the topnav: brand and nav
   links share one core type recipe; only color and a 1px size step
   separate them (links are slightly smaller to offset the extra visual
   mass of longer words like LIBRARY against a 4-letter VDNA). Direct-
   child selectors so the rule doesn't reach into the user-menu dropdown
   (which has its own .user-menu-item styling). */
.topnav .brand,
.topnav nav > a,
.topnav nav button.linklike {
  font-weight: 500;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  text-decoration: none;
}
.topnav .brand { font-size: 11px; color: var(--text); }
.topnav nav > a,
.topnav nav button.linklike { font-size: 10px; color: var(--muted); }
.topnav nav > a:hover,
.topnav nav button.linklike:hover,
.topnav nav > a:focus-visible,
.topnav nav button.linklike:focus-visible { color: var(--text); }
.topnav nav {
  display: flex;
  gap: clamp(12px, 2vw, 18px);
  align-items: center;
}

/* Quiet command-palette hint in the topnav. Shown only on devices
   with a mouse-like pointer so touch-only visitors don't see
   keyboard UI they can't use. */
.topnav-shortcut {
  display: none;
  align-items: center;
  gap: 2px;
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.04em;
  pointer-events: none;
}
@media (hover: hover) and (pointer: fine) {
  .topnav-shortcut { display: inline-flex; }
}
.topnav-shortcut kbd {
  font: inherit;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 4px;
  min-width: 14px;
  text-align: center;
  background: transparent;
  color: var(--muted);
}

.inline-form { display: inline; margin: 0; padding: 0; }
.linklike { background: none; border: 0; color: var(--muted); cursor: pointer; padding: 0; font: inherit; }

/* Avatar / user menu dropdown in the topnav. */
.user-menu { position: relative; display: inline-flex; align-items: center; }
.user-menu-trigger {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  background: transparent;
  padding: 0;
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  /* Keep a comfortable click target around the smaller visible avatar. */
  min-width: 32px;
  min-height: 32px;
  border-radius: 50%;
}
.user-menu-trigger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.user-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--text);
  color: var(--bg);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  line-height: 1;
}
.user-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  min-width: 220px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 0;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
  z-index: 50;
}
.user-menu-identity {
  font-size: 12px;
  color: var(--muted);
  padding: 8px 14px 10px;
  margin: 0;
  border-bottom: 1px solid var(--border);
  word-break: break-all;
}
.user-menu-item {
  display: block;
  padding: 8px 14px;
  color: var(--text);
  text-decoration: none;
  font-size: 14px;
}
.user-menu-item:hover {
  background: var(--bg);
}
.user-menu-form { margin: 0; padding: 0; }
.user-menu-logout {
  width: 100%;
  text-align: left;
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  font: inherit;
}

main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 32px;
}

h1 { font-size: 28px; margin: 0 0 8px; font-weight: 500; }
h2 { font-size: 13px; margin: 32px 0 12px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); font-weight: 500; }
h3 { font-size: 16px; margin: 0 0 6px; font-weight: 500; }

a { color: var(--link); }

.muted { color: var(--muted); }
.small { font-size: 13px; }
.alert { background: rgba(155, 47, 47, 0.08); border: 1px solid var(--error); color: var(--error); padding: 10px 14px; border-radius: 6px; margin: 16px 0; }
.alert.alert-success { background: rgba(20, 100, 20, 0.08); border-color: #2a8c2a; color: #2a8c2a; }
.flash-messages { max-width: 560px; margin: 16px auto 0; padding: 0 16px; }
.error { color: var(--error); font-size: 14px; }

.page-narrow { max-width: 560px; margin: 0 auto; }

.upload-form { display: flex; flex-direction: column; gap: 16px; margin-top: 24px; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field-label { font-size: 13px; color: var(--muted); }
.field-label em { font-style: normal; color: var(--muted); opacity: 0.7; }
.field-hint { display: block; margin-top: 4px; color: var(--muted); font-size: 12px; }

/* Public-handle availability indicator: ✓/✕ sits inside the input on
   the right edge; the reason text (only shown when unavailable) goes
   below. */
.handle-input-wrap { position: relative; display: block; }
.upload-form .handle-input-wrap input[type="text"] { padding-right: 34px; }
.handle-status-icon {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  pointer-events: none;
}
.handle-status-icon.is-available { color: #2a8c2a; }
.handle-status-icon.is-taken { color: var(--error); }
.handle-reason { display: block; margin-top: 4px; font-size: 12px; color: var(--error); }
.upload-form input[type="text"],
.upload-form input[type="email"],
.upload-form input[type="password"] {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 10px 12px;
  border-radius: 6px;
  font: inherit;
  width: 100%;
  box-sizing: border-box;
}
.upload-form input[type="text"]:focus,
.upload-form input[type="email"]:focus,
.upload-form input[type="password"]:focus {
  outline: none;
  border-color: var(--accent);
}

button.primary, .primary.as-link {
  background: var(--text);
  color: var(--panel);
  border: 0;
  padding: 10px 18px;
  border-radius: 6px;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  font: inherit;
}
button.primary:hover, .primary.as-link:hover { background: #000; }
.primary.is-loading { opacity: 0.7; cursor: progress; }

.kbd-hint { display: inline-flex; gap: 2px; margin-left: 8px; opacity: 0.65; vertical-align: baseline; }
.kbd-hint kbd {
  font: inherit;
  font-size: 0.85em;
  background: rgba(255, 255, 255, 0.18);
  border-radius: 4px;
  padding: 1px 5px;
  min-width: 1.2em;
  text-align: center;
}
.primary.is-loading .kbd-hint { display: none; }

/* Pills (kept global; used by gallery cards) */
.pills { display: flex; flex-wrap: wrap; gap: 6px; }
.pill { background: var(--pill-bg); color: var(--text); padding: 4px 10px; border-radius: 100px; font-size: 13px; }
.pill.small { font-size: 12px; padding: 2px 8px; }

/* Settings page */
.settings-page { max-width: 560px; margin: 0 auto; padding-top: 16px; }
.settings-page h2 { margin-top: 32px; }

/* Usage page */
.usage-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 24px;
  margin-top: 16px;
  background: #fff;
}
.usage-card h2 { margin: 0 0 12px 0; font-size: 16px; color: var(--muted); font-weight: 500; }
.usage-card > p { margin: 0; }
.usage-card > p + p { margin-top: 12px; }
.usage-count { font-size: 22px; font-weight: 500; }
.usage-bar {
  background: var(--pill-bg);
  border-radius: 100px;
  height: 8px;
  overflow: hidden;
  margin: 12px 0 4px 0;
}
.usage-bar-fill {
  background: var(--text);
  height: 100%;
  transition: width 200ms ease;
}
.usage-note { color: var(--muted); font-size: 13px; }

/* Upload page (dropzone + preview) */
.upload-page { padding-top: 16px; max-width: 960px; margin: 0 auto; }
.upload-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 48px;
  align-items: start;
  margin-top: 24px;
}
.upload-col-image, .upload-col-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}
.upload-col-form h1 { margin: 0; }
.upload-col-form p { margin: 0; }
.dropzone {
  display: grid;
  place-items: center;
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 64px 24px;
  background: var(--panel);
  cursor: pointer;
  transition: border-color .15s, background .15s;
  text-align: center;
}
.dropzone:hover, .dropzone.is-dragover, .dropzone:focus-within {
  border-color: var(--accent);
  background: #fff;
}
.dropzone:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.dropzone-prompt { font-size: 16px; color: var(--text); margin: 0; }
.dropzone-hint { font-size: 13px; color: var(--muted); margin: 8px 0 0; }
/* Visually hide the file input but keep it focusable + in the a11y tree.
   display:none would remove it from the tab order, breaking keyboard users. */
.dropzone input[type="file"] {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  border: 0;
}
.upload-preview { margin: 24px 0 0; }
.upload-preview img { display: block; max-width: 100%; max-height: 60vh; object-fit: contain; border-radius: 4px; }
.field-secondary .field-label { font-size: 12px; }

.upload-form--submitting { display: none; }

.upload-loading {
  max-width: 640px;
  margin: 72px auto;
  text-align: center;
}
.upload-loading:focus { outline: none; }
.upload-loading-kicker {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 0 0 16px;
}
.upload-loading-preview {
  margin: 0 auto 32px;
}
.upload-loading-preview img {
  display: block;
  max-width: 100%;
  max-height: 52vh;
  object-fit: contain;
  margin: 0 auto;
  border-radius: 4px;
  background: var(--panel);
}
.upload-loading h2 {
  margin: 0 0 12px;
  font-family: var(--font-record);
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text);
}
.upload-loading p {
  max-width: 48ch;
  margin: 0 auto 8px;
  color: var(--text);
}
.upload-loading p.muted { color: var(--muted); margin-top: 12px; }

/* Visual record (detail page) */
.record { max-width: 880px; margin: 0 auto; }

.record-hero {
  display: grid;
  place-items: center;
  min-height: 70vh;
  margin: 0;
  padding: 48px 0 64px;
}
.record-hero img {
  display: block;
  max-width: 100%;
  max-height: min(80vh, 900px);
  object-fit: contain;
}

.record-label {
  max-width: 50ch;
  margin: 0 auto;
}
.record-label h1 {
  font-family: var(--font-record);
  font-size: clamp(24px, 3.2vw, 34px);
  font-weight: 500;
  letter-spacing: -0.005em;
  margin: 0 0 var(--space-4);
  line-height: 1.2;
}
.record-meta {
  color: var(--muted);
  font-size: 13px;
  margin: 0 0 var(--space-5);
}
.record-identification-meta {
  margin: 0;
}
.record-meta-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-6);
}
.record-meta-row .record-meta { margin: 0; }
/* Form wraps the visibility toggle and inherits body line-height (1.55) by
   default, which inflates its height and floats the icon to the top. Make
   it a thin flex container so it collapses to the icon's height and
   centers cleanly with the meta text. */
.record-meta-row .inline-form {
  display: flex;
  align-items: center;
}
/* When the private-hint sits right below the meta row, pull it up so it
   reads as part of the same metadata block instead of a separate line. */
.record-meta-row + .record-meta {
  margin-top: -20px;
}
/* Shared by the staff-only visibility (eye) toggle and the bookmark
   toggle in .record-meta-row — same size, muted color, hover-to-text,
   and aria-label tooltip. The saved-card badge borrows just the
   ::after/::before tooltip (see .saved-card-bookmark-toggle below). */
.visibility-toggle,
.bookmark-toggle {
  position: relative;
  background: none;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  padding: 0;
  margin: 0;
  display: inline-flex;
  align-items: center;
}
.visibility-toggle:hover,
.bookmark-toggle:hover { color: var(--text); }
.visibility-toggle svg,
.bookmark-toggle svg { display: block; }
/* When bookmarked, the icon is solid. The inline fill attr covers first
   paint; this keeps it correct if the class is ever toggled in place. */
.bookmark-toggle.is-bookmarked { color: var(--text); }
.bookmark-toggle.is-bookmarked svg { fill: currentColor; }
.visibility-toggle::after,
.bookmark-toggle::after,
.saved-card-bookmark-toggle::after {
  content: attr(aria-label);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  background: var(--text);
  color: var(--bg);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 5px 9px;
  border-radius: 3px;
  pointer-events: none;
  opacity: 0;
  z-index: 20;
}
.visibility-toggle::before,
.bookmark-toggle::before,
.saved-card-bookmark-toggle::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 3px);
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--text);
  pointer-events: none;
  opacity: 0;
  z-index: 20;
}
.visibility-toggle:hover::after,
.visibility-toggle:hover::before,
.visibility-toggle:focus-visible::after,
.visibility-toggle:focus-visible::before,
.bookmark-toggle:hover::after,
.bookmark-toggle:hover::before,
.bookmark-toggle:focus-visible::after,
.bookmark-toggle:focus-visible::before,
.saved-card-bookmark-toggle:hover::after,
.saved-card-bookmark-toggle:hover::before,
.saved-card-bookmark-toggle:focus-visible::after,
.saved-card-bookmark-toggle:focus-visible::before {
  opacity: 1;
}
.record-summary {
  font-family: var(--font-record);
  font-size: 17px;
  line-height: 1.7;
  margin: var(--space-5) 0 0;
}
.record-error-detail code {
  display: block;
  background: rgba(155, 47, 47, 0.08);
  color: var(--error);
  padding: 8px 10px;
  border-radius: 4px;
  word-break: break-word;
  font-size: 13px;
}

/* Loading state — pending/processing detail page */
.loading-grid {
  max-width: 960px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 48px;
  align-items: center;
  padding: 48px 0;
}
.loading-grid .record-hero-loading {
  min-height: 0;
  padding: 0;
  margin: 0;
}
.loading-grid .record-hero-loading img {
  max-height: 60vh;
  width: 100%;
  object-fit: contain;
}
.loading-grid .loading-text {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}
.loading-grid .record-label {
  max-width: none;
  margin: 0;
}
.loading-grid .loading-steps {
  margin: 0;
  max-width: none;
}
.record-hero-loading img {
  animation: subtle-zoom 12s ease-in-out infinite alternate;
}
@keyframes subtle-zoom {
  from { transform: scale(1); }
  to { transform: scale(1.04); }
}
.shimmer {
  background: linear-gradient(90deg, #ddd 0%, #1a1a1a 45%, #1a1a1a 55%, #ddd 100%);
  background-size: 220% 100%;
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: shimmer-flow 2.6s linear infinite;
}
@keyframes shimmer-flow {
  from { background-position: 220% 0; }
  to { background-position: -220% 0; }
}
.loading-steps {
  list-style: none;
  padding: 0;
  margin: 32px auto 0;
  max-width: 50ch;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.loading-step {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--muted);
  opacity: 0.45;
  animation: step-emphasis 12s ease-in-out infinite;
}
.loading-step-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}
@keyframes step-emphasis {
  0%, 80%, 100% { opacity: 0.45; color: var(--muted); }
  40%, 60% { opacity: 1; color: var(--text); }
}
.loading-step:nth-child(1) { animation-delay: 0s; }
.loading-step:nth-child(2) { animation-delay: 2.4s; }
.loading-step:nth-child(3) { animation-delay: 4.8s; }
.loading-step:nth-child(4) { animation-delay: 7.2s; }
.loading-step:nth-child(5) { animation-delay: 9.6s; }

.record-dna {
  max-width: 50ch;
  margin: 96px auto 0;
}
.record-dna h2 { margin-bottom: var(--space-2); }
.record-dna .reference-traits { margin-bottom: 32px; }

.record-refs { margin-top: 96px; }
.record-refs-rail {
  max-width: 50ch;
  margin: 0 auto;
}
.reference {
  max-width: 50ch;
  margin: 0 auto;
  padding: 96px 0;
  border-top: 1px solid var(--border-soft);
}
.reference:first-of-type {
  border-top: 0;
  padding-top: 32px;
}
.reference-image { margin: 0 0 32px; }
.reference-image img {
  display: block;
  width: 100%;
  max-height: 60vh;
  object-fit: contain;
  background: var(--panel);
}
.reference-image-caption {
  font-size: 10px;
  color: var(--muted);
  margin: 4px 0 0;
}
.reference-image-caption code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: inherit;
  color: inherit;
}
.reference-image-caption a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--border);
}
.reference-image-caption a:hover {
  color: var(--text);
  border-bottom-color: var(--accent);
}
.reference-eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 11px;
  color: var(--muted);
  margin: 0 0 var(--space-2);
}
.reference-label {
  font-family: var(--font-record);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.005em;
  margin: 0 0 var(--space-2);
  line-height: 1.25;
}
.reference-grounded {
  color: var(--muted);
  font-size: 13px;
  margin: 0 0 var(--space-5);
}
.reference-notice {
  font-family: var(--font-record);
  font-size: 17px;
  line-height: 1.7;
  margin: 0 0 var(--space-5);
  max-width: 50ch;
}
.reference-traits {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 12px;
  font-size: 13px;
  line-height: 1.55;
  margin: 0 0 var(--space-5);
  align-items: baseline;
}
.reference-traits-label {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 11px;
  color: var(--muted);
}
.reference-traits-values { color: var(--text); }
.reference-traits-values--stacked {
  display: flex;
  flex-direction: column;
}
.reference-traits-values--query { font-size: 12px; }
.reference-traits-values--query a {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
}
.reference-traits-values--query a:hover { border-bottom-color: var(--accent); }
.reference-traits-values--query code {
  color: inherit;
  font-size: inherit;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.reference--with-image {
  max-width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 48px;
  align-items: start;
}
.reference--with-image .reference-image { margin: 0; }
.reference--with-image .reference-image img { max-height: 70vh; }
.reference--with-image .reference-body { max-width: 50ch; }

/* Library (gallery) */
.gallery-header { display: flex; align-items: center; justify-content: space-between; }
.gallery-subtitle { color: var(--muted); margin: 0 0 24px; font-size: 14px; }
/* Two sections stack on /app/: "Your records" then "Saved". */
.gallery-section + .gallery-section { margin-top: var(--space-7); }
.gallery-section-heading { margin: 0 0 4px; }
.gallery-grid { list-style: none; padding: 0; margin: 24px 0 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }
.gallery-card { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; overflow: visible; position: relative; }
.gallery-card a { display: block; color: inherit; text-decoration: none; }

/* Per-record options menu (anonymity toggle today; room for future
   per-record actions). Sits absolutely over the top-right corner of the
   card, fading in on hover/focus/open so it doesn't compete with the
   thumbnail. Markup pattern mirrors the topnav user-menu. */
.card-menu { position: absolute; top: 8px; right: 8px; z-index: 2; }
.card-menu-trigger {
  appearance: none;
  border: 0;
  background: rgba(255, 255, 255, 0.85);
  color: var(--text);
  padding: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  opacity: 0;
  transition: opacity 120ms ease;
}
.gallery-card:hover .card-menu-trigger,
.card-menu-trigger:focus-visible,
.card-menu-trigger[aria-expanded="true"] { opacity: 1; }
.card-menu-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 220px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 0;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
}
.card-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 8px 14px;
  font: inherit;
  color: var(--text);
}
.card-menu-item:hover { background: var(--bg); }

/* Saved-card "Unsave" badge — a small filled-bookmark control over the
   image's top-right corner. Quiet catalog action, not a dropdown.
   Anchored to the .gallery-card <li> (already position: relative); the
   image sits flush at the card's top edge. On hover-capable devices
   it's revealed on card hover/focus (mirrors .card-menu-trigger); on
   touch, where there's no hover, it stays visible. */
.saved-card-bookmark-form { position: absolute; top: 12px; right: 12px; z-index: 2; margin: 0; }
@media (hover: hover) {
  .saved-card-bookmark-form { opacity: 0; transition: opacity 120ms ease; }
  .gallery-card:hover .saved-card-bookmark-form,
  .gallery-card:focus-within .saved-card-bookmark-form { opacity: 1; }
}
.saved-card-bookmark-toggle {
  position: relative;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.72);
  color: var(--text);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.saved-card-bookmark-toggle svg { display: block; }
.saved-card-bookmark-toggle:hover,
.saved-card-bookmark-toggle:focus-visible { background: rgba(255, 255, 255, 0.9); }
.saved-card-bookmark-toggle:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 2px;
}

.gallery-card img { width: 100%; aspect-ratio: 4/3; object-fit: cover; display: block; background: var(--bg); border-radius: 8px 8px 0 0; }
.thumb-placeholder { aspect-ratio: 4/3; display: grid; place-items: center; font-size: 32px; color: var(--muted); background: var(--bg); }
.gallery-meta { padding: 12px 14px; }
.gallery-meta h2 { font-size: 14px; text-transform: none; letter-spacing: 0; margin: 0 0 4px; color: var(--text); font-weight: 500; }
.gallery-keywords { margin-top: 8px; }
.gallery-card.gallery-card-create {
  background: var(--panel);
  border-style: dashed;
  border-color: var(--text);
  transition: background 150ms ease, color 150ms ease;
}
.gallery-card.gallery-card-create:hover {
  background: var(--text);
}
.gallery-card.gallery-card-create:hover .gallery-card-create-plus,
.gallery-card.gallery-card-create:hover h2,
.gallery-card.gallery-card-create:hover p {
  color: var(--bg);
}
.gallery-card-create-button {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
  display: flex;
  width: 100%;
  height: 100%;
  min-height: 200px;
  align-items: center;
  justify-content: center;
  padding: 0;
  text-decoration: none;
}
.gallery-card-create-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.gallery-card-create-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 24px;
  text-align: center;
}
.gallery-card.gallery-card-create.is-drag-over {
  background: var(--text);
}
.gallery-card.gallery-card-create.is-drag-over .gallery-card-create-plus,
.gallery-card.gallery-card-create.is-drag-over h2,
.gallery-card.gallery-card-create.is-drag-over p {
  color: var(--bg);
}
.gallery-card-create-error {
  color: var(--error);
  font-size: 12px;
  margin: 8px 0 0;
}
.gallery-card-create-plus {
  font-size: 32px;
  line-height: 1;
  color: var(--muted);
}
.gallery-card-create h2 {
  font-size: 14px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  margin: 0;
  color: var(--text);
}
.gallery-card-create p {
  margin: 0;
}
.status-badge { font-size: 11px; padding: 2px 8px; border-radius: 100px; text-transform: uppercase; letter-spacing: 0.04em; }
.status-pending { background: #f0f0f0; color: var(--muted); }
.status-processing { background: #f0f0f0; color: var(--muted); }
.status-succeeded { background: #f0f0f0; color: var(--text); }
.status-failed { background: #fbe6e6; color: var(--error); }
.gallery-meta h2.analyzing { color: var(--muted); font-style: italic; font-weight: 400; }

.empty-state { background: var(--panel); border: 1px dashed var(--border); padding: 48px 24px; border-radius: 8px; text-align: center; margin-top: 24px; }

@media (max-width: 760px) {
  .upload-grid, .loading-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 24px;
  }
  .loading-grid { padding: 24px 0; }
  .reference--with-image { grid-template-columns: 1fr; gap: 24px; }
}

@media (max-width: 600px) {
  main { padding: 16px; }
  .record-hero { min-height: 50vh; padding: 32px 0; }
  .record-summary { font-size: 17px; }
  .record-dna { margin-top: 64px; }
  .reference { padding: 64px 0; }
  .reference-label { font-size: 19px; }
  .reference-traits { grid-template-columns: 1fr; gap: 4px; }
  .reference--with-image .reference-image img { max-height: 50vh; }
  .dropzone { padding: 40px 16px; }
  .upload-loading { margin: 32px auto; }
  .upload-loading-preview img { max-height: 40vh; }
}

/* Command palette */
.command-palette {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 80px 16px 0;
}
.command-palette[hidden] { display: none; }
.command-palette-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
}
.command-palette-panel {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  width: 100%;
  max-width: 560px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.2);
  overflow: hidden;
}
.command-palette-input {
  width: 100%;
  border: 0;
  outline: none;
  padding: 16px 20px;
  font: inherit;
  font-size: 16px;
  border-bottom: 1px solid var(--border);
  background: transparent;
  box-sizing: border-box;
}
.command-palette-list {
  list-style: none;
  margin: 0;
  padding: 8px 0;
  max-height: 60vh;
  overflow-y: auto;
}
.command-palette-item {
  padding: 12px 20px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.command-palette-item.is-active {
  background: var(--bg);
}
.command-palette-item-title { font-size: 14px; color: var(--text); }
.command-palette-item-subtitle { color: var(--muted); font-size: 12px; }
.command-palette-empty { padding: 16px 20px; color: var(--muted); font-size: 14px; }

/* ============ Reusable visual browser ============ */
/* When a page's <main> is hosting the visual browser (or the empty
   state stub), kill main's standard 1100px/32px container so the
   gallery sections can use full viewport width and end exactly at
   the viewport bottom. Without this, main's 32px bottom padding
   pushes the section below the viewport and the centered image gets
   cut off. */
main:has(> .visual-browser),
main:has(> .home-empty) {
  max-width: none;
  margin: 0;
  padding: 0;
}

/* Generic gallery-wall pattern. One record per ~viewport section,
   image preserves aspect ratio, never cropped, always visible whole
   within the viewport. Reused by the homepage; ready for future tag
   pages and related-records views. */
.visual-browser { display: block; }
.visual-browser__item {
  /* Subtract sticky-topnav height so each section fills exactly the
     visible area below the topnav. Topnav is min-height clamp(40,5vw,48)
     — using 48 (the desktop max) keeps the math clean and means the
     section is at most 8px shorter than necessary on mobile. */
  min-height: calc(100svh - 48px);
  display: grid;
  place-items: center;
  padding: 0 clamp(20px, 6vw, 96px);
}
.visual-browser__link {
  display: block;
  line-height: 0;
}
.visual-browser__link:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 6px;
  border-radius: 4px;
}
.visual-browser__image {
  display: block;
  width: auto;
  height: auto;
  max-width: min(88vw, 1440px);
  /* Visible area = viewport - topnav (48). Reserve 64px total breathing
     room (32 above + 32 below the image) so the image never touches
     the topnav or the bottom edge, on any viewport size. */
  max-height: calc(100svh - 48px - 64px);
  object-fit: contain;
}

/* Load-more affordance: small-caps catalog text, sister to the topnav. */
.visual-browser-more {
  display: flex;
  justify-content: center;
  padding: clamp(40px, 8vh, 96px) 20px clamp(80px, 12vh, 160px);
}
.visual-browser-more__link {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--muted);
  padding: 4px 0;
  transition: color 120ms ease;
}
.visual-browser-more__link:hover,
.visual-browser-more__link:focus-visible {
  color: var(--text);
}
.visual-browser-more__link[aria-busy="true"] {
  opacity: 0.5;
  cursor: progress;
}

/* ============ Home empty state ============ */
.home-empty {
  min-height: 50svh;
  display: grid;
  place-items: center;
  color: var(--muted);
  padding: clamp(40px, 8vh, 96px) 20px;
}
