/* GlockCollector registry -- minimal, legible styling for the public
   browse/search pages. No framework; kept small and hand-written so it's
   easy to restyle later once real branding/UI work happens. */

:root {
  --ink: #1c1f24;
  --ink-soft: #52585f;
  --line: #dcdfe3;
  --bg: #ffffff;
  --bg-soft: #f5f6f8;
  --accent: #2f4858;
  --accent-soft: #eef2f4;
  --tag-confirmed: #1f7a4d;
  --tag-probable: #a3690f;
  --tag-reported: #7a7f85;
  --tag-featured: #a3690f;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--ink);
  background: var(--bg-soft);
  line-height: 1.5;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.site-header {
  background: var(--accent);
  color: #fff;
  padding: 0.9rem 1.25rem;
}

.site-header .header-inner {
  max-width: 1000px;
  margin: 0 auto;
  display: flex;
  align-items: baseline;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.site-header a {
  color: #fff;
}

.site-title {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  row-gap: 0.6rem;
  font-size: 0.92rem;
  opacity: 0.92;
  /* Wraps instead of overflowing once the dropdowns + search box + Log
     in/username don't all fit on one line -- without this, the search box
     (added after this nav was originally sized) pushed Log in/username
     off the right edge of the header on narrow screens. */
  flex-wrap: wrap;
}

/* Header dropdowns (Registry / Research) -- plain <details>/<summary>, no
   JS required to open/close; style.css just gives it a menu look instead
   of the default browser triangle-and-list. */
.nav-dropdown {
  position: relative;
}

.nav-dropdown > summary {
  cursor: pointer;
  list-style: none;
  color: #fff;
}

.nav-dropdown > summary::-webkit-details-marker {
  display: none;
}

.nav-dropdown > summary::after {
  content: " \25BE";
  font-size: 0.7em;
}

.nav-dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 0.6rem;
  background: var(--bg);
  border-radius: 6px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2);
  padding: 0.35rem 0;
  min-width: 150px;
  display: flex;
  flex-direction: column;
  z-index: 20;
}

.nav-dropdown-menu a {
  color: var(--ink);
  padding: 0.5rem 0.9rem;
  font-size: 0.9rem;
  white-space: nowrap;
}

.nav-dropdown-menu a:hover {
  background: var(--accent-soft);
  text-decoration: none;
}

main {
  max-width: 1000px;
  margin: 0 auto;
  padding: 1.75rem 1.25rem 3rem;
}

.page-title {
  margin: 0 0 0.25rem;
  font-size: 1.5rem;
}

.page-subtitle {
  color: var(--ink-soft);
  margin: 0 0 1.5rem;
  font-size: 0.95rem;
}

.card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 1.25rem 1.4rem;
  margin-bottom: 1.25rem;
}

.hero {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 2rem 1.75rem;
  margin-bottom: 1.75rem;
}

.hero h1 {
  margin: 0 0 0.4rem;
  font-size: 1.6rem;
}

.hero p {
  color: var(--ink-soft);
  margin: 0 0 1.25rem;
  max-width: 55ch;
}

.stat-row {
  display: flex;
  gap: 2rem;
  margin-top: 1.25rem;
  flex-wrap: wrap;
}

.stat {
  min-width: 100px;
}

.stat .num {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--accent);
}

.stat .label {
  font-size: 0.82rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.button {
  display: inline-block;
  background: var(--accent);
  color: #fff !important;
  border-radius: 6px;
  padding: 0.55rem 1.1rem;
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none !important;
}

.button.secondary {
  background: var(--accent-soft);
  color: var(--accent) !important;
}

.filter-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: flex-end;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 1rem 1.1rem;
  margin-bottom: 1.25rem;
}

.filter-form .field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
}

.filter-form label {
  color: var(--ink-soft);
  font-weight: 600;
}

.filter-form input[type="text"],
.filter-form select {
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  font-size: 0.92rem;
  min-width: 8rem;
}

.filter-form button {
  padding: 0.45rem 1rem;
  border: none;
  border-radius: 5px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  font-size: 0.9rem;
}

.filter-form .clear-link {
  font-size: 0.85rem;
  align-self: center;
}

table.data-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}

table.data-table th,
table.data-table td {
  text-align: left;
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.92rem;
}

table.data-table th {
  background: var(--bg-soft);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}

table.data-table tr:last-child td {
  border-bottom: none;
}

table.data-table tr:hover td {
  background: var(--accent-soft);
}

.table-scroll {
  overflow-x: auto;
}

table.data-table.centered-table th,
table.data-table.centered-table td {
  text-align: center;
}

/* SN Graphic page */

.sn-legend-table {
  border-collapse: collapse;
  margin-bottom: 1rem;
}

.sn-legend-table td {
  border: 1px solid var(--line);
  padding: 0.1rem 0.5rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-align: center;
  white-space: nowrap;
}

.sn-legend-table .legend-row-label {
  font-weight: 600;
  text-align: right;
  background: var(--bg);
  border: none;
  padding-right: 0.75rem;
  white-space: nowrap;
}

table.sn-graphic-table th,
table.sn-graphic-table td {
  text-align: center;
  vertical-align: middle;
}

table.sn-graphic-table td {
  padding-top: 0.1rem;
  padding-bottom: 0.1rem;
}

table.sn-graphic-table td.year-cell {
  padding-left: 0.05rem;
  padding-right: 0.05rem;
}

table.sn-graphic-table .proof-header {
  background: #eaf5ea;
}

table.sn-graphic-table .import-header {
  background: #eaf1fa;
}

table.sn-graphic-table td.month-cell {
  white-space: nowrap;
  font-size: 0.72rem;
  font-weight: 600;
  background: var(--bg);
  width: 6.5rem;
}

.year-cell {
  width: 0.7rem;
  overflow: hidden;
  text-align: center;
  vertical-align: middle;
}

.year-cell.year-dark {
  background: #6b6f75;
}

.year-cell.year-dark .year-label {
  color: #ffffff;
}

.year-cell.year-light {
  background: #d9dce0;
}

.year-cell.year-light .year-label {
  color: var(--ink);
}

.year-label {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  transform: rotate(-90deg);
}

.chip-cell {
  min-width: 12rem;
}

.chip-cell.proof-cell {
  background: #f3faf3;
}

.chip-cell.import-cell {
  background: #f2f7fc;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.2rem;
}

.proof-cell .chip-row {
  justify-content: flex-end;
}

.import-cell .chip-row {
  justify-content: flex-start;
}

.sn-chip {
  display: inline-block;
  box-sizing: border-box;
  padding: 0.12rem 0.22rem;
  border-radius: 3px;
  border: 1px solid rgba(11, 11, 11, 0.15);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.4;
  text-decoration: none;
  white-space: nowrap;
  text-align: center;
}

.sn-chip:hover {
  outline: 2px solid var(--accent);
  text-decoration: none;
}

.multiselect-dropdown {
  position: relative;
  display: inline-block;
  min-width: 160px;
}

.multiselect-toggle {
  width: 100%;
  text-align: left;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--bg);
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
}

.multiselect-toggle::after {
  content: "\25BE";
  float: right;
  color: var(--ink-soft);
  margin-left: 0.5rem;
}

.multiselect-panel {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 20;
  margin-top: 0.25rem;
  min-width: 180px;
  max-height: 220px;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 5px;
  box-shadow: 0 4px 10px rgba(11, 11, 11, 0.12);
  padding: 0.35rem;
}

.multiselect-option {
  display: block;
  padding: 0.3rem 0.4rem;
  font-size: 0.9rem;
  white-space: nowrap;
  cursor: pointer;
  border-radius: 3px;
}

.multiselect-option:hover {
  background: var(--accent-soft);
}

.multiselect-option input {
  margin-right: 0.4rem;
}

.model-swatch {
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 2px;
  border: 1px solid rgba(11, 11, 11, 0.15);
  margin-right: 0.4rem;
  vertical-align: middle;
}

table.sortable-table th[data-sort] {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

table.sortable-table th[data-sort]:hover {
  color: var(--accent);
}

table.sortable-table th[data-sort].sorted-asc::after {
  content: " \25B2";
}

table.sortable-table th[data-sort].sorted-desc::after {
  content: " \25BC";
}

.tag {
  display: inline-block;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  color: #fff;
}

.tag.confirmed { background: var(--tag-confirmed); }
.tag.probable { background: var(--tag-probable); }
.tag.reported { background: var(--tag-reported); }
.tag.featured { background: var(--tag-featured); }

.featured-books-section {
  border: 1px solid var(--tag-featured);
  background: var(--accent-soft);
  border-radius: 10px;
  padding: 1.25rem;
  margin-bottom: 1.5rem;
}

.featured-books-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-top: 0.75rem;
}

.featured-book-tile {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  background: var(--bg);
  border-radius: 8px;
  padding: 0.85rem;
  max-width: 360px;
  text-decoration: none;
  color: inherit;
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

.featured-book-tile .book-tile-cover,
.featured-book-tile .book-tile-cover-fallback {
  width: 72px;
  height: 108px;
  flex-shrink: 0;
}

.empty-state {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--ink-soft);
}

.pagination {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  justify-content: center;
  margin-top: 1.25rem;
  font-size: 0.9rem;
  flex-wrap: wrap;
}

.pagination-jump {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: 0.5rem;
  padding-left: 0.75rem;
  border-left: 1px solid var(--line);
}

.pagination-jump-input {
  width: 3.5rem;
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  font-size: 0.9rem;
  text-align: center;
}

.pagination-jump-btn {
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bg-soft);
  font-size: 0.9rem;
  cursor: pointer;
}

.pagination-jump-btn:hover {
  background: var(--accent-soft);
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.9rem 1.5rem;
  margin: 1rem 0;
}

.detail-grid .item .label {
  font-size: 0.78rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.detail-grid .item .value {
  font-size: 1rem;
  margin-top: 0.15rem;
}

.section-title {
  font-size: 1.05rem;
  margin: 1.75rem 0 0.75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.breadcrumb {
  font-size: 0.85rem;
  margin-bottom: 1rem;
  color: var(--ink-soft);
}

.photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.75rem;
  margin: 1rem 0 1.75rem;
}

.photo-grid .photo {
  display: block;
  aspect-ratio: 1 / 1;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg);
}

.photo-grid .photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.photo-grid .photo-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 0.5rem;
  text-align: center;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

/* Lead photo gallery: a large focus image with thumbnails underneath,
   clicking the focus image opens a full-screen lightbox with arrow nav. */

.gallery {
  margin: 1rem 0 1.75rem;
}

.gallery-focus {
  display: block;
  width: 100%;
  max-width: 640px;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-soft);
  padding: 0;
  margin: 0 0 0.75rem;
  cursor: zoom-in;
}

.gallery-credit {
  max-width: 640px;
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin: -0.4rem 0 0.75rem;
}

.gallery-focus img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.gallery-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  max-width: 640px;
}

.gallery-thumb {
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg-soft);
  cursor: pointer;
}

.gallery-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.gallery-thumb:hover {
  border-color: var(--accent);
}

.gallery-thumb.active {
  border-color: var(--accent);
}

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.92);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  z-index: 1000;
  padding: 2rem;
}

.lightbox[hidden] {
  display: none;
}

.lightbox-stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 100%;
  max-height: calc(100% - 2.5rem);
}

.lightbox-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
  cursor: zoom-in;
  -webkit-user-drag: none;
  user-select: none;
}

.lightbox-credit {
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.85rem;
  text-align: center;
  max-width: 90%;
}

.lightbox-credit a {
  color: #fff;
}

.lightbox-img.zoomed {
  cursor: grab;
}

.lightbox-img.zoomed.dragging {
  cursor: grabbing;
}

.lightbox-close {
  position: absolute;
  top: 0.75rem;
  right: 1rem;
  background: none;
  border: none;
  color: #fff;
  font-size: 2.25rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.25rem 0.5rem;
}

.lightbox-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, 0.15);
  border: none;
  color: #fff;
  font-size: 2rem;
  line-height: 1;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  cursor: pointer;
}

.lightbox-arrow:hover {
  background: rgba(255, 255, 255, 0.3);
}

.lightbox-prev {
  left: 0.75rem;
}

.lightbox-next {
  right: 0.75rem;
}

@media (max-width: 640px) {
  .gallery-focus,
  .gallery-thumbs {
    max-width: 100%;
  }

  .lightbox-arrow {
    width: 2.5rem;
    height: 2.5rem;
    font-size: 1.6rem;
  }

  .lightbox {
    padding: 1rem;
  }
}

.auth-card {
  max-width: 420px;
}

.form-field {
  margin-bottom: 1rem;
}

.form-field label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 0.3rem;
}

.form-field input[type="text"],
.form-field input[type="password"],
.form-field input[type="email"],
.form-field input[type="url"],
.form-field input[type="file"],
.form-field select,
.form-field textarea {
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  font-size: 0.95rem;
  font-family: inherit;
  resize: vertical;
}

/* Elements only shown once a staff viewer turns on the page's "Edit" mode
   (see page-edit-toggle in specimen_detail.html) -- the !important guards
   against a class on the same element (e.g. .button, .card) setting an
   explicit display value that would otherwise win over the plain [hidden]
   attribute. */
.page-edit-only[hidden] {
  display: none !important;
}

/* The read-only counterpart to .page-edit-only -- a value's normal display,
   hidden the same way once the page's Edit mode is switched on, so a field
   shows either its static text or its input, never both at once. See
   page-edit-toggle's script in specimen_detail.html. */
.page-view-only[hidden] {
  display: none !important;
}

/* Inline-edit inputs that replace a .detail-grid item's read-only .value in
   place, once Edit mode is on -- sized to sit comfortably in a grid cell
   rather than a full-width form. */
.detail-grid .item .value-edit {
  margin-top: 0.15rem;
}

.detail-grid .item .value-edit input[type="text"],
.detail-grid .item .value-edit input[type="number"],
.detail-grid .item .value-edit select,
.detail-grid .item .value-edit textarea {
  width: 100%;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  font-size: 0.95rem;
  font-family: inherit;
  resize: vertical;
}

/* Inline-edit inputs dropped directly into a data-table cell (Provenance
   rows and the always-present "add a new event" row) -- compact enough to
   fit several to a row, since a table cell is much narrower than a
   detail-grid item. */
table.data-table td input[type="text"],
table.data-table td input[type="number"],
table.data-table td input[type="date"],
table.data-table td select {
  width: 100%;
  min-width: 6.5rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  font-size: 0.85rem;
  font-family: inherit;
}

/* Price/currency and source-text/source-url each pack two inputs into one
   cell -- keep the second (currency, source_url) narrower than the first
   rather than splitting the cell evenly, since those hold much shorter
   values. */
table.data-table td.prov-price-edit input:first-child,
table.data-table td .prov-price-edit input:first-child {
  width: 65%;
}

table.data-table td.prov-price-edit input:last-child,
table.data-table td .prov-price-edit input:last-child {
  width: 30%;
  min-width: 3.5rem;
  margin-left: 0.3rem;
}

table.data-table td.prov-source-edit input,
table.data-table td .prov-source-edit input {
  margin-bottom: 0.25rem;
}

.edit-toggle-btn {
  background: none;
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 0.3rem 0.75rem;
  font-size: 0.85rem;
  cursor: pointer;
  color: var(--ink-soft);
}

.edit-toggle-btn:hover {
  background: var(--bg-soft, #f4f4f4);
}

.form-help {
  font-size: 0.78rem;
  color: var(--ink-soft);
  margin-top: 0.25rem;
}

.comment-list {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
}

.comment {
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--line);
}

.comment:last-child {
  border-bottom: none;
}

.comment-meta {
  font-size: 0.85rem;
  margin-bottom: 0.25rem;
}

.comment-meta strong {
  color: var(--ink);
}

.comment-date {
  color: var(--ink-soft);
  margin-left: 0.5rem;
}

.comment-edited {
  color: var(--ink-soft);
  margin-left: 0.5rem;
  font-style: italic;
}

.comment-body {
  margin: 0 0 0.4rem;
  white-space: pre-wrap;
}

.comment-actions {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.comment-action-form {
  display: inline;
  margin: 0;
}

.comment-action {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-size: 0.82rem;
  color: var(--ink-soft);
  cursor: pointer;
}

.comment-action:hover {
  color: var(--accent);
  text-decoration: underline;
}

.comment-action.active {
  color: var(--accent);
  font-weight: 600;
}

.comment-action-static {
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.comment-action-danger {
  color: #b3261e;
}

.comment-action-danger:hover {
  color: #b3261e;
  text-decoration: underline;
}

.reply-form,
.edit-form {
  margin: 0.6rem 0 0;
}

.reply-form textarea,
.edit-form textarea {
  width: 100%;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  font-size: 0.9rem;
  font-family: inherit;
  resize: vertical;
}

.reply-form button,
.edit-form button[type="submit"] {
  margin-top: 0.4rem;
  padding: 0.4rem 0.9rem;
  border: none;
  border-radius: 5px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0.4rem 0 0 0.7rem;
  font: inherit;
  font-size: 0.85rem;
  color: var(--ink-soft);
  cursor: pointer;
  text-decoration: underline;
}

.link-button:hover {
  color: var(--accent);
}

.comment-replies {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0 0 0 1.25rem;
  border-left: 2px solid var(--line);
}

.comment-replies .comment {
  padding: 0.6rem 0;
}

.comment-replies .comment:last-child {
  border-bottom: none;
}

.form-errors {
  color: #b3261e;
  font-size: 0.85rem;
  margin-top: 0.25rem;
}

.dropzone {
  border: 2px dashed var(--line);
  border-radius: 8px;
  padding: 1.75rem 1rem;
  text-align: center;
  cursor: pointer;
  background: var(--bg-soft);
  transition: border-color 0.15s ease, background 0.15s ease;
  margin-bottom: 0.75rem;
}

.dropzone:hover {
  border-color: var(--accent);
}

.dropzone.dragover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.dropzone-text {
  margin: 0 0 0.25rem;
  font-weight: 600;
  color: var(--ink);
}

.dropzone-hint {
  margin: 0;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

.file-list {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  font-size: 0.85rem;
}

.file-list:empty {
  margin: 0;
}

.file-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.3rem 0.6rem;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 5px;
  margin-bottom: 0.3rem;
  color: var(--ink-soft);
}

/* Higher-specificity ".file-list .file-list-remove" (rather than the bare
   class) so this small inline "remove" control doesn't get swept up by the
   generic ".auth-card button" rule further down, which styles real
   submit-style buttons (like this page's own "Upload" button) as solid
   accent-colored pills. */
.file-list .file-list-remove {
  flex: none;
  background: none;
  border: none;
  padding: 0 0.2rem;
  margin-right: 0;
  font-size: 1rem;
  line-height: 1;
  color: var(--ink-soft);
  cursor: pointer;
}

.file-list .file-list-remove:hover {
  color: var(--ink);
}

.auth-card button,
.card form button[type="submit"] {
  padding: 0.5rem 1.1rem;
  border: none;
  border-radius: 5px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
  font-size: 0.92rem;
  margin-right: 0.75rem;
}

.messages {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
}

.messages .message {
  padding: 0.65rem 0.9rem;
  border-radius: 6px;
  font-size: 0.9rem;
  margin-bottom: 0.5rem;
  background: var(--accent-soft);
  color: var(--accent);
}

.messages .message.error {
  background: #fbe9e7;
  color: #b3261e;
}

.site-nav span {
  opacity: 0.85;
}

/* Header search box -- see search_results.html/registry.views.search.
   Semi-transparent white against the header's accent-color background,
   matching the "site-header a { color: #fff; }" treatment the rest of the
   header uses rather than a stark white input box. */
.site-search-form {
  margin: 0;
  /* Shrinks instead of forcing the nav wider than the viewport, and grows
     to fill any slack on a wide header -- a fixed width is what caused
     the mobile overflow (see .site-nav above). */
  flex: 1 1 140px;
  min-width: 0;
}
.site-search-input {
  box-sizing: border-box;
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: 999px;
  color: #fff;
  padding: 0.35rem 0.9rem;
  font-size: 0.85rem;
  width: 100%;
}
.site-search-input::placeholder {
  color: rgba(255, 255, 255, 0.75);
}
.site-search-input:focus {
  outline: none;
  background: rgba(255, 255, 255, 0.28);
  border-color: #fff;
}

.search-section-more {
  margin: 0.5rem 0 1.75rem;
  font-size: 0.88rem;
}

.logout-form {
  display: inline;
  margin: 0;
}

.site-nav .link-button {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
}

.site-nav .link-button:hover {
  text-decoration: underline;
}

.site-footer {
  text-align: center;
  color: var(--ink-soft);
  font-size: 0.82rem;
  padding: 1.5rem 1rem 2.5rem;
}

.site-footer p {
  margin: 0.2rem 0;
}

.site-footer .copyright {
  font-size: 0.78rem;
}

@media (max-width: 640px) {
  .stat-row { gap: 1.25rem; }
  .filter-form { flex-direction: column; align-items: stretch; }
  .filter-form .field { width: 100%; }
  .multiselect-dropdown { width: 100%; }

  /* Header nav on mobile, per explicit request: the search box stays
     inline with Registry/Literature/avatar on one row, positioned between
     Literature and the avatar -- its natural position in the HTML source
     order. order:0 (the flex default) keeps it from being pushed after
     them the way an earlier order:10/full-width rule did. The flex-basis
     is cut to 70px here (half of the 140px desktop default) -- at the
     140px basis the box was still wide enough to push Log in/the avatar
     onto their own line on a 375px-wide screen, per explicit follow-up
     request to reduce it by half; confirmed via live visual check before
     shipping. */
  .site-search-form {
    order: 0;
    flex: 1 1 70px;
  }

  /* Just the avatar/initials tile on mobile -- the username text next to
     it is dropped so that link stays compact enough to share a line with
     Registry/Literature. aria-label on the link itself (see base.html)
     keeps it accessible with the visible text gone. Unaffected above this
     breakpoint -- desktop still shows the full username. */
  .site-nav-username {
    display: none;
  }

  /* Language switcher on mobile, per explicit request: lifted out of the
     nav's second row and pinned to the far right of the first row, level
     with "GlockCollector.com". It stays where it is in the markup (so the
     desktop header is untouched); the header-inner box is the positioning
     context. */
  .site-header .header-inner {
    position: relative;
  }

  .nav-dropdown.lang-switcher {
    position: absolute;
    top: 0.2rem;
    right: 0;
    line-height: 1.6;
  }
}

/* Prefix-page "sale price over time" chart */

.sales-chart-subtitle {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0 0 1rem;
}

.sales-chart-caption {
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin: 0.6rem 0 1.25rem;
}

.sales-chart {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 1rem 1.25rem 0.75rem;
}

.sales-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.sales-chart-legend-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.sales-chart-legend-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
  display: inline-block;
}

.sales-chart svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.sales-chart .axis-label {
  font-size: 10px;
  fill: var(--ink-soft);
}

.sales-chart .grid-line {
  stroke: var(--line);
  stroke-width: 1;
}

.sales-chart .baseline {
  stroke: var(--ink-soft);
  stroke-width: 1;
}

.sales-chart .sale-dot-link {
  cursor: pointer;
}

.sales-chart .sale-dot-link:hover,
.sales-chart .sale-dot-link:focus {
  filter: brightness(1.2);
  outline: none;
}

.sales-chart-tooltip {
  position: fixed;
  background: var(--ink);
  color: var(--bg);
  font-size: 0.78rem;
  padding: 0.4rem 0.65rem;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -100%);
  transition: opacity 0.08s ease;
  z-index: 20;
  white-space: nowrap;
}

.sales-chart-tooltip.visible {
  opacity: 1;
}

.sales-chart-tooltip .tt-serial {
  font-weight: 600;
}

.sales-chart-tooltip .tt-price {
  font-weight: 700;
}

.sales-chart-tooltip .tt-line {
  margin-top: 0.1rem;
  opacity: 0.85;
}

/* Books page: a grid of cover-photo tiles, a detail page with a larger
   cover beside the book's own fields, and a shared star-rating look used
   for both a book's average and one member's own review. */

.book-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 1.25rem;
  margin: 1rem 0 1.75rem;
}

.book-tile {
  display: block;
  color: inherit;
}

.book-tile:hover {
  text-decoration: none;
}

.book-tile:hover .book-tile-title {
  text-decoration: underline;
  color: var(--accent);
}

.book-tile-cover {
  aspect-ratio: 2 / 3;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg);
  margin-bottom: 0.5rem;
}

.book-tile-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.book-tile-cover-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 0.5rem;
  text-align: center;
  font-size: 0.82rem;
  color: var(--ink-soft);
  background: var(--bg-soft);
}

.book-tile-title {
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.3;
}

.book-tile-author {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0.1rem 0 0.35rem;
}

.book-detail-layout {
  display: flex;
  gap: 1.75rem;
  flex-wrap: wrap;
  /* Without this, flexbox's default cross-axis behavior (stretch) pulls
     .book-detail-cover down to match .book-detail-info's height whenever
     the info column runs longer (a description, buy/download links, a
     wide detail-grid) -- flex-start lets the cover frame size to its own
     2:3 shape instead of trailing empty background space to the bottom of
     the section. */
  align-items: flex-start;
}

.book-detail-cover {
  flex: 0 0 auto;
  width: 200px;
  aspect-ratio: 2 / 3;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-soft);
}

.book-detail-cover img {
  width: 100%;
  height: 100%;
  /* contain, not cover -- the frame box above is a fixed 2:3 shape for
     layout consistency, but the cover photo itself is scaled to fit
     entirely inside it at its own true aspect ratio (letterboxed if it
     isn't already 2:3) rather than being cropped/stretched to fill the
     frame, which is what made off-ratio covers look distorted. Top-
     aligned (object-position) rather than centered, so a cover shorter
     than the frame sits flush with the title/spine art at the top instead
     of floating in the middle with an even gap above and below. */
  object-fit: contain;
  object-position: top;
  display: block;
}

.book-detail-info {
  flex: 1 1 320px;
  min-width: 260px;
}

.star-rating {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.4rem 0 0.9rem;
}

.star-row {
  letter-spacing: 0.1em;
  font-size: 1.05rem;
}

.star-row .star {
  color: var(--line);
}

.star-row .star.filled {
  color: var(--tag-probable);
}

.star-rating-text {
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.star-picker {
  display: flex;
  align-items: center;
  gap: 0.2rem;
}

.star-picker-btn {
  background: none;
  border: none;
  padding: 0;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--line);
  cursor: pointer;
}

.star-picker-btn.filled {
  color: var(--tag-probable);
}

.star-picker-label {
  margin-left: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.book-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1rem;
}

/* Accessory reference pop-up: the small "?" icon next to an Example's
   Accessories/Components field values, and the shared modal it opens
   showing that variant's reference photo + caption. */
.accessory-ref-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  margin-left: 0.4rem;
  border-radius: 50%;
  border: 1px solid var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.7rem;
  line-height: 1;
  font-weight: 700;
  cursor: pointer;
  padding: 0;
  vertical-align: middle;
}

.accessory-ref-btn:hover {
  background: var(--accent);
  color: var(--bg);
}

.accessory-ref-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

.accessory-ref-modal[hidden] {
  display: none;
}

.accessory-ref-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
}

.accessory-ref-modal-content {
  position: relative;
  background: var(--bg);
  border-radius: 10px;
  padding: 1.25rem;
  max-width: 640px;
  width: 100%;
  max-height: 92vh;
  overflow-y: auto;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
}

/* A variant with a single photo keeps the narrow pop-up. */
.accessory-ref-modal-content.single {
  max-width: 420px;
}

/* Up to 8 photos: 2 across x 4 down (the pop-up scrolls if the screen is short). */
.accessory-ref-modal-images {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem;
  align-items: start;
  margin-top: 0.4rem;
}

.accessory-ref-modal-content.single .accessory-ref-modal-images {
  grid-template-columns: minmax(0, 1fr);
}

/* 3+ photos: shrink each so all four rows fit on screen without scrolling
   (click a photo to see it large). */
.accessory-ref-modal-content.many .accessory-ref-modal-images img {
  max-height: calc((92vh - 8rem) / 4);
}

.accessory-ref-modal-images img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 45vh;
  object-fit: contain;
  border-radius: 6px;
  cursor: zoom-in;
}

/* Stacks above .accessory-ref-modal (same z-index as .lightbox) so clicking
   a photo in the small pop-up opens full-screen on top of it, not behind
   it -- see the lightbox markup/script in specimen_detail.html. */
#accessory-ref-lightbox {
  z-index: 1100;
}

.accessory-ref-modal-caption {
  margin: 0.75rem 0 0;
  font-size: 0.9rem;
  color: var(--ink-soft);
  text-align: center;
}

.accessory-ref-modal-close {
  position: sticky;
  top: 0;
  float: right;
  z-index: 2;
  margin: -0.4rem -0.3rem 0 0;
  background: none;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  color: var(--ink-soft);
}

/* Analytics consent banner -- see base.html's {% if umami_website_id %}
   block. Fixed to the bottom of the viewport, above everything else, until
   dismissed via Accept/Decline (then it's simply hidden and never shown
   again, per the localStorage choice). */
.consent-banner[hidden] {
  display: none;
}
.consent-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.25rem;
  padding: 0.9rem 1.25rem;
  background: var(--ink);
  color: #fff;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.15);
}
.consent-banner p {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.4;
  max-width: 62ch;
}
.consent-banner a {
  color: #fff;
  text-decoration: underline;
}
.consent-banner-actions {
  display: flex;
  gap: 0.6rem;
  flex-shrink: 0;
}
.consent-btn {
  padding: 0.45rem 1rem;
  border-radius: 5px;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
}
.consent-btn-primary {
  background: #fff;
  color: var(--ink);
  border-color: #fff;
}
.consent-btn-secondary {
  background: transparent;
  color: #fff;
  border-color: rgba(255, 255, 255, 0.5);
}

/* Examples list: table/card view toggle -- see specimen_list.html and the
   "view" GET param read in specimen_list (views.py). */
.view-toggle {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
  margin-bottom: 1rem;
}
.view-toggle-link {
  padding: 0.4rem 1rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
}
.view-toggle-link:hover {
  text-decoration: none;
  color: var(--ink);
}
.view-toggle-link.active {
  background: var(--ink);
  color: #fff;
}

/* Examples list, card view -- a "baseball card" per Example, standing in
   for a row of the data-table above when "Cards" is selected. */
.specimen-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1.25rem;
  margin: 0 0 1.75rem;
}
.specimen-card {
  position: relative;
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
}
.specimen-card:hover {
  text-decoration: none;
  box-shadow: 0 2px 8px rgba(28, 31, 36, 0.12);
}
.specimen-card-banner {
  padding: 0.85rem 1rem;
}
.specimen-card-banner-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
}
.specimen-card-serial {
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.specimen-card-banner-sub {
  font-size: 0.78rem;
  font-weight: 700;
  margin-top: 0.25rem;
  opacity: 0.85;
}
.specimen-card-photo {
  position: relative;
  width: 100%;
  height: 160px;
  flex-shrink: 0;
  background: var(--bg-soft);
  display: flex;
  align-items: center;
  justify-content: center;
}
.specimen-card-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.specimen-card-photo-fallback {
  font-size: 0.72rem;
  color: var(--ink-soft);
  text-align: center;
  max-width: 80%;
}
.specimen-card-body {
  padding: 0.9rem 1rem 1rem;
  display: flex;
  flex-direction: column;
  flex: 1;
}
/* My Collection, card view only -- the body sits outside the card's <a>
   now (see my_collection.html) so the Prefix stat can be its own link;
   cursor:pointer signals the rest of the body still navigates to the
   specimen via its click handler there. The shared card grid partial
   (_specimen_card_grid.html) keeps its body inside its <a>, where this
   rule has no visible effect since the whole thing is already a link. */
.specimen-card-body[data-specimen-href] {
  cursor: pointer;
}
.specimen-card-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.65rem 1rem;
}
.specimen-card-stat-wide {
  grid-column: span 2;
}
.specimen-card-stat-label {
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.specimen-card-stat-value {
  font-size: 0.85rem;
  font-weight: 600;
  margin-top: 0.1rem;
}
.specimen-card-notes {
  margin-top: 0.65rem;
}
.specimen-card-notes-text {
  font-size: 0.78rem;
  margin-top: 0.15rem;
  max-height: 3.4rem;
  overflow-y: auto;
  line-height: 1.4;
  padding-right: 0.25rem;
}
.specimen-card-footer {
  margin-top: auto;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.specimen-card-status {
  font-size: 0.78rem;
  color: var(--ink-soft);
}

/* My Collection, card view -- a small circular remove button overlaid on
   the card banner. Lives outside the card's own <a> (see my_collection.html)
   since a <form>/<button> can't validly nest inside an anchor; its click
   handler posts the matching hidden per-card remove form instead. */
.specimen-card-remove {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 2;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.specimen-card-remove:hover {
  background: rgba(0, 0, 0, 0.7);
}

/* Manage-photos drag-and-drop (see _photo_gallery.html and media_reorder).
   The first image in the table is the cover. */
.media-handle-cell {
  width: 2.2rem;
  padding-right: 0;
}
.media-drag-handle {
  cursor: grab;
  touch-action: none; /* dragging the handle must not scroll the page on touch screens */
  user-select: none;
  background: none;
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.35rem 0.4rem;
  line-height: 1;
  letter-spacing: -0.15em;
  color: inherit;
}
.media-drag-handle:active {
  cursor: grabbing;
}
.media-item.media-dragging > tr > td {
  background: var(--accent-soft);
}
.media-item.media-dragging {
  outline: 2px solid var(--accent);
}
.media-cover-badge {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--tag-probable);
  margin-top: 0.2rem;
  white-space: nowrap;
}


/* "?" icon with a mouse-over (or keyboard-focus / tap) text bubble -- see
   specimen_detail.html's Slide finish. The text comes from the data-tip
   attribute. */
.help-tip {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  margin-left: 0.4rem;
  border-radius: 50%;
  border: 1px solid var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.7rem;
  line-height: 1;
  font-weight: 700;
  cursor: help;
  vertical-align: middle;
}

.help-tip:hover,
.help-tip:focus {
  background: var(--accent);
  color: var(--bg);
  outline: none;
}

/* The mouse-over text bubble is one shared element placed by script (see
   base.html) so it always stays inside the screen, on computer and phone. */
.help-tip-bubble {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 2000;
  box-sizing: border-box;
  width: max-content;
  max-width: min(18rem, calc(100vw - 1.5rem));
  padding: 0.5rem 0.65rem;
  border-radius: 6px;
  background: var(--ink);
  color: var(--bg);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.35;
  text-align: left;
  white-space: normal;
  overflow-wrap: anywhere;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  pointer-events: none;
  visibility: hidden;
}

.help-tip-bubble.show {
  visibility: visible;
}

/* "Show 25 / 50 / 100 per page" picker above a list -- see _per_page.html. */
.per-page-control {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.6rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.per-page-control select {
  width: auto;
  padding: 0.2rem 0.4rem;
}

/* Language switcher (header) -- reuses the .nav-dropdown disclosure pattern;
   the menu is a <form> of buttons so choosing a language POSTs to set_language. */
.nav-dropdown-menu.align-right {
  left: auto;
  right: 0;
}

.nav-dropdown-menu button {
  background: none;
  border: 0;
  border-radius: 0;
  color: var(--ink);
  cursor: pointer;
  font: inherit;
  font-size: 0.9rem;
  padding: 0.5rem 0.9rem;
  text-align: left;
  white-space: nowrap;
}

.nav-dropdown-menu button:hover {
  background: var(--accent-soft);
}

.nav-dropdown-menu button.current {
  font-weight: bold;
}

/* "Written in <language>" tag on member comments/reviews (see lang_detect.py) */
.lang-tag {
  font-size: 0.75rem;
  color: var(--ink-soft);
  border: 1px solid var(--line, #dcdfe3);
  border-radius: 999px;
  padding: 0 0.45rem;
  margin-left: 0.4rem;
  white-space: nowrap;
}

/* Search results: heading links sort the table server-side (see _apply_search_sort);
   the arrow comes from aria-sort. */
table.sortable-table th a.sort-link {
  color: inherit;
  text-decoration: none;
}

table.sortable-table th[aria-sort="ascending"] a.sort-link::after {
  content: " \25B2";
}

table.sortable-table th[aria-sort="descending"] a.sort-link::after {
  content: " \25BC";
}
