:root {
  --bg: #111214;
  --bg-card: #1b1c1f;
  --fg: #f2f1ed;
  --fg-muted: #a9a9a9;
  --accent: #d8b26a;
  --error: #e46b6b;
  --border: #2c2d31;
}

* { box-sizing: border-box; }

/* Generic "not currently shown" utility — used throughout the lightbox JS
   (gallery-lightbox.js) to toggle the Select vs. Download button, the
   selfie-search error message, etc. Was missing entirely until now: only
   the unrelated, more specific `.lightbox.hidden` rule below existed, so
   every classList.add('hidden') on the lightbox's Select/Download buttons
   was a silent no-op — the Download link stayed visible next to Select on
   every gallery, sell-mode included, even though it was never functional
   there (stale/placeholder href). This is the actual fix for that. */
.hidden { display: none !important; }

/* Site-wide default button look — every <button> and .button-link falls back
   to this gold accent style unless a more specific rule overrides it. This
   is the single source of truth for "buttons should all be the same color":
   new buttons added anywhere on the site automatically match without
   needing their own color rule. Destructive/danger actions (.danger,
   .upload-cancel-btn, .batch-cancel-btn) are the one deliberate exception —
   those stay red so a delete/cancel action never looks identical to a
   normal one. */
button, .button-link, input[type="submit"] {
  background: var(--accent);
  color: #1b1c1f;
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 0.6rem 1.1rem;
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
button:hover, .button-link:hover, input[type="submit"]:hover { opacity: 0.9; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

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

h1, h2, h3 {
  font-family: Georgia, 'Times New Roman', serif;
  font-weight: 500;
  letter-spacing: 0.02em;
}

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

.container {
  max-width: 1100px;
  margin: 0 auto;
  padding: 2rem 1.5rem 4rem;
}
.container.narrow { max-width: 520px; }

/* Order-status page (views/order-status.ejs) — small colored pill showing
   where an order stands: pending payment, ready to download, prints in
   production, or shipped. */
.order-status-badge {
  display: inline-block;
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 0.85rem;
  margin: 0 0 0.75rem;
}
.order-status-badge.status-pending { background: #f0ece0; color: #6b6b6b; }
.order-status-badge.status-processing { background: #fdf0dc; color: #9a6a1a; }
.order-status-badge.status-ready,
.order-status-badge.status-shipped { background: #e4f3e6; color: #2e7d3f; }
.order-status-details { margin: 0 0 1rem; padding-left: 1.2rem; }

.site-shell {
  display: flex;
  min-height: 100vh;
  align-items: stretch;
}

.sidebar-toggle-checkbox { display: none; }

.sidebar {
  flex: 0 0 260px;
  width: 260px;
  background: var(--bg-card);
  border-right: 1px solid var(--border);
  padding: 0 0 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.sidebar-logo-link {
  display: block;
  width: 100%;
  line-height: 0;
  padding: 1.25rem 1.75rem 0.5rem;
  box-sizing: border-box;
}
.sidebar-logo {
  width: 100%;
  height: auto;
  max-height: 210px;
  object-fit: contain;
  display: block;
  margin: 0 auto;
}

.sidebar-site-name {
  display: block;
  padding: 1.25rem 1rem 1rem 1.25rem;
  font-family: Georgia, serif;
  font-size: 2.2rem;
  letter-spacing: 0.01em;
  line-height: 1.15;
  color: var(--fg);
  overflow-wrap: anywhere;
  word-break: break-word;
}
.sidebar-site-name:hover { color: var(--fg); text-decoration: none; }

.sidebar-close {
  display: none;
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 2;
  width: 34px;
  height: 34px;
  align-items: center;
  justify-content: center;
  background: rgba(0,0,0,0.55);
  border-radius: 6px;
  color: #fff;
  cursor: pointer;
  font-size: 1.1rem;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.25rem 1rem;
}
.sidebar-nav a {
  padding: 0.6rem 0.65rem;
  border-radius: 4px;
  color: var(--fg-muted);
  font-size: 1.3rem;
}
.sidebar-nav a:hover {
  color: var(--fg);
  background: rgba(255,255,255,0.04);
  text-decoration: none;
}

.sidebar-social {
  margin-top: auto;
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}
.sidebar-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  color: var(--fg-muted);
  border: 1px solid var(--border);
}
.sidebar-social a svg { width: 16px; height: 16px; }
.sidebar-social a:hover { color: var(--fg); border-color: var(--fg-muted); text-decoration: none; }

.sidebar-open-btn {
  display: none;
  position: fixed;
  top: 1rem;
  left: 1rem;
  z-index: 50;
  width: 42px;
  height: 42px;
  align-items: center;
  justify-content: center;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--fg);
  font-size: 1.2rem;
  cursor: pointer;
}

.site-content {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--fg);
}

/* Galleries listing, individual gallery pages, and custom pages default to
   a white background — the sidebar stays on the dark theme regardless,
   since .sidebar is a sibling of .site-content and doesn't inherit these
   overridden variables. */
body.light-content .site-content {
  --bg: #ffffff;
  --bg-card: #f7f6f3;
  --fg: #1a1a1a;
  --fg-muted: #6b6b6b;
  --border: #e2e0da;
}

.site-footer {
  margin-top: auto;
  text-align: center;
  color: var(--fg-muted);
  padding: 2rem;
  font-size: 0.85rem;
}
.footer-legal-links { display: flex; gap: 0.5rem; justify-content: center; }
.footer-legal-links span { color: var(--fg-muted); }

@media (max-width: 860px) {
  .sidebar-open-btn { display: flex; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 60;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    box-shadow: 4px 0 24px rgba(0,0,0,0.4);
  }
  .sidebar-close { display: flex; }

  .sidebar-toggle-checkbox:checked ~ .sidebar { transform: translateX(0); }
  .sidebar-toggle-checkbox:checked ~ .sidebar-open-btn { display: none; }
}

.hero { margin: 0 0 2rem; padding: 0 1.5rem; }
.hero p { color: var(--fg-muted); }
.hero.hero-with-photo {
  margin: 0 0 2rem;
  padding: 2rem;
  background-color: #16171a;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  min-height: 100vh;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  box-sizing: border-box;
  position: relative;
  overflow: hidden;
}
.hero.hero-with-photo h1 {
  font-size: 3.4rem;
  color: #fff;
  margin: 0 0 0.5rem;
}
.hero.hero-with-photo p {
  color: rgba(255,255,255,0.9);
  font-size: 1.2rem;
  margin: 0;
}

@media (max-width: 720px) {
  .hero.hero-with-photo { min-height: 70vh; }
  .hero.hero-with-photo h1 { font-size: 2.2rem; }
}

.hero-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 1.5s ease;
}
.hero-slide.active { opacity: 1; }

/* Used on pages that still show a heading/text over the slideshow (e.g.
   the Galleries page) — darkens the photos for legibility. The homepage
   has no overlay content, so its slideshow shows at full brightness. */
.hero-overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem;
  background: linear-gradient(rgba(17,18,20,0.45), rgba(17,18,20,0.85));
}

.hero-cta {
  display: inline-block;
  margin-top: 1.5rem;
  padding: 0.9rem 2.2rem;
  background: var(--accent, #e0393e);
  color: #fff;
  font-weight: 600;
  font-size: 1.05rem;
  text-decoration: none;
  border-radius: 6px;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.hero-cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(0,0,0,0.25);
}

.bib-search-form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin: 1rem 0 0.5rem;
}
.bib-search-form input {
  flex: 1;
  max-width: 320px;
  padding: 0.65rem 0.9rem;
  background: var(--bg-card);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 1rem;
}
.bib-search-form button {
  padding: 0.65rem 1.1rem;
  background: var(--accent);
  color: #1b1c1f;
  border: none;
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
}
.clear-search { color: var(--fg-muted); font-size: 0.9rem; }

/* "Notify me" opt-in form shown under a zero-result bib/name search (see
   gallery.ejs / folder.ejs) — lets a customer leave their email and get
   pinged automatically once a matching photo is uploaded/tagged (see
   data/models.js PhotoAlerts). */
.notify-me-form { margin: 1rem 0; max-width: 420px; }
.notify-me-form label { display: block; margin-bottom: 0.5rem; font-size: 0.9rem; color: var(--fg-muted); }
.notify-me-row { display: flex; gap: 0.5rem; }
.notify-me-row input {
  flex: 1;
  padding: 0.65rem 0.9rem;
  background: var(--bg-card);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 1rem;
}
.notify-me-row button {
  padding: 0.65rem 1.1rem;
  background: var(--accent);
  color: #1b1c1f;
  border: none;
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
}

.back-to-folder-link { display: inline-block; margin-bottom: 1rem; }
.back-to-folder-bottom { margin-top: 1.5rem; margin-bottom: 0; }

/* Folder (category) page hero — a single static banner image, not a
   slideshow, since it's mainly standing in as the link-preview thumbnail
   when a folder's shareable link gets pasted somewhere. */
.folder-hero {
  width: 100%;
  height: 320px;
  overflow: hidden;
  background: #16171a;
}
.folder-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
@media (max-width: 720px) {
  .folder-hero { height: 200px; }
}

.face-search-form { flex-wrap: wrap; }
.face-search-label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
  color: var(--fg-muted);
}
.face-search-label input[type="file"] {
  max-width: 260px;
  font-size: 0.9rem;
  color: var(--fg);
}

/* .category-heading is now a <summary> (see the admin Galleries list page,
   views/admin/galleries.ejs) so each category's table can be collapsed —
   cursor and outline-removal make that obviously clickable without
   changing the look much from when this was a plain <h2>. Note this can't
   use :first-of-type on .category-heading itself anymore — each <summary>
   is the only one inside its own <details>, so it'd always match. Scoped
   to the first <details class="category-section"> among its siblings
   instead, same "no extra gap before the very first section" effect. */
.category-heading {
  margin: 2rem 0 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  outline: none;
  font-size: 1.15rem;
}
.category-section:first-of-type .category-heading { margin-top: 0; }
/* A closed folder has no table underneath taking up visual weight, so the
   same 2rem gap that separates two open (table-bearing) sections reads as
   an oversized dead zone between two collapsed ones — tighten it here. */
.category-section:not([open]) .category-heading { margin-top: 0.75rem; }
/* The two "Order ... by" dropdowns on the admin Galleries page (see
   views/admin/galleries.ejs) sit side by side rather than stacked, since
   together they're still narrow enough to fit most screens on one line. */
.gallery-sort-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
}
/* Bumped up from the site default (inherited, ~1rem) specifically for the
   admin Galleries list page — scoped to .category-section rather than
   .admin-table/.container globally, since .admin-table is shared with
   several other admin pages (Download Sizes, Dashboard, Print Options,
   Packages, Pages) that weren't asked for here. */
.category-section .admin-table th,
.category-section .admin-table td {
  font-size: 1.1rem;
}

.gallery-folder-section { margin: 0 0 2.5rem; }
.gallery-folder-heading {
  margin: 0 0 1.25rem;
  padding-bottom: 0.6rem;
  border-bottom: 2px solid var(--border);
  font-size: 1.4rem;
}
.gallery-folder-section:first-of-type .gallery-folder-heading { margin-top: 0; }

.gallery-description { color: var(--fg-muted); }
.gallery-content {
  /* Solid, near-black (matches the page's own body text color, --fg on a
     light-content page) rather than the muted gray used for the short
     description above it — this is meant to be read as real page content
     (recap, instructions, results links), not a secondary caption. */
  color: var(--fg);
  white-space: pre-line;
  margin: 0.5rem 0 1.5rem;
  font-size: 1.15rem;
}
.gallery-content-small { font-size: 1rem; }
.gallery-content-medium { font-size: 1.15rem; }
.gallery-content-large { font-size: 1.4rem; }
.gallery-content-link { margin: -0.75rem 0 1.5rem; }

.page-content {
  color: var(--fg-muted);
  white-space: pre-line;
  margin: 1rem 0;
  line-height: 1.7;
}

.page-block-figure {
  margin: 1.5rem 0;
}
.page-block-figure img,
.page-block-figure video {
  display: block;
  max-width: 100%;
  border-radius: 6px;
}
.page-block-figure figcaption {
  color: var(--fg-muted);
  font-size: 0.85rem;
  margin-top: 0.4rem;
}

/* Third-party embed block (e.g. a race registration iframe) — most embed
   snippets hard-code a pixel width, so this forces whatever's pasted in to
   never overflow the page on a narrow screen. Height is left alone (the
   snippet usually sets its own, or the widget itself scrolls internally). */
.page-block-embed {
  margin: 1.5rem 0;
}
.page-block-embed iframe {
  max-width: 100%;
}

.folder-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 1rem 0 1.5rem;
}
.folder-tabs a {
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--fg-muted);
  font-size: 0.9rem;
}
.folder-tabs a:hover { color: var(--fg); text-decoration: none; }
.folder-tabs a.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #1b1c1f;
  font-weight: 600;
}

.gallery-social {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.5rem 0 1rem;
}
.gallery-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--border);
  border-radius: 50%;
  color: var(--fg-muted);
}
.gallery-social a svg { width: 17px; height: 17px; }
.gallery-social a:hover { color: var(--fg); border-color: var(--fg-muted); text-decoration: none; }

.gallery-grid, .photo-grid, .cart-photo-grid, .admin-photo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1.25rem;
}
/* The public browsing grid (proofing photos to buy) gets noticeably bigger
   tiles than the gallery-card, cart, and admin grids above — those benefit
   from staying compact so more fits on screen at once, but customers
   deciding whether to buy a photo want to actually see detail in it. */
.photo-grid {
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}
/* Gallery/subfolder cards on a folder's own page — wider tiles than the
   top-level Races and Events page's denser wall of cards, since a folder
   typically holds a handful of galleries (races, sub-events) rather than
   the whole site's worth. Lands at 2-3 columns on a typical desktop width
   inside the 1100px .container, fewer as the screen narrows. */
.folder-page-grid {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.admin-photo-grid.small { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); }
.admin-photo-grid.small img { border-radius: 4px; }

.gallery-card {
  display: block;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.gallery-card-thumb { aspect-ratio: 4/3; background: #000; }
.gallery-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-card-title { padding: 0.75rem 1rem; color: var(--fg); }

.photo-tile, .cart-photo-tile, .admin-photo-tile {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  position: relative;
}
.photo-tile img, .cart-photo-tile img, .admin-photo-tile img {
  width: 100%;
  aspect-ratio: 4/3;
  object-fit: cover;
  display: block;
}
.cart-photo-filename {
  margin: 0;
  padding: 0.4rem 0.5rem 0;
  font-size: 0.8rem;
  color: var(--fg-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Wraps just the admin thumbnail image (see views/admin/_photo-tile.ejs) so
   the filename overlay below can anchor to the bottom of the IMAGE itself,
   not the bottom of the whole tile — the tile also has folder-move/tag/
   delete controls stacked underneath the image. */
.admin-photo-thumb { position: relative; }
.photo-filename-overlay {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 0.25rem 0.4rem;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-size: 0.7rem;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}
/* "Cover photo" checkbox overlaid on an admin thumbnail (see
   views/admin/_photo-tile.ejs) — sits opposite the filename overlay, in the
   top-right corner. .is-cover-photo highlights the whole tile once it's the
   gallery's chosen cover, so it's obvious at a glance while scanning the
   grid. */
.admin-photo-tile.is-cover-photo { outline: 2px solid var(--accent); outline-offset: -2px; }
.cover-photo-form { position: absolute; top: 0; right: 0; margin: 0; z-index: 1; }
.cover-photo-overlay {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0.35rem;
  padding: 0.2rem 0.45rem;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  font-size: 0.7rem;
  line-height: 1.2;
  border-radius: 4px;
  cursor: pointer;
  white-space: nowrap;
}
.cover-photo-overlay input { margin: 0; }

.select-form { padding: 0.5rem; }
.select-form button, .remove {
  width: 100%;
  padding: 0.5rem;
}
/* "+ Select" (add to cart, for a sell-mode gallery) shares the same button
   element as "Download" (an actual free-download gallery) would use, so
   without this override every public gallery — sell or free — showed the
   same solid gold, "lit up" button regardless of whether anything was
   actually free to download. Now a not-yet-selected photo gets a quieter
   outlined look, and only turns solid gold once the customer has actually
   picked it — so gold specifically means "free download" or "you selected
   this," never just "here's a button." Applies everywhere a photo can be
   selected for purchase: the gallery grid, the lightbox overlay, and the
   single-photo detail page. */
.select-form button:not(.selected),
.photo-detail-side button:not(.selected),
.lightbox-actions button:not(.selected) {
  background: none;
  color: var(--accent);
  border: 1px solid var(--accent);
}
.select-form button.selected,
.photo-detail-side button.selected,
.lightbox-actions button.selected {
  background: var(--accent);
  color: #1b1c1f;
  border: 1px solid var(--accent);
}
.logo-choice-form {
  padding: 0 0.5rem;
  margin: 0.2rem 0;
}
.logo-bulk-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0 1rem;
}
.logo-bulk-actions form { display: inline; }
.logo-bulk-btn {
  background: var(--accent);
  color: #1b1c1f;
  border: 1px solid var(--accent);
  border-radius: 999px;
  padding: 0.45rem 1rem;
  font-size: 0.85rem;
  font-weight: 600;
}
.logo-bulk-btn:hover { opacity: 0.85; }
/* "Remove from all" is the undo of "Include on all" — same size/weight so
   neither looks like an afterthought, but outlined instead of filled so the
   two are still visually distinct from each other at a glance. */
.logo-bulk-btn-outline {
  background: none;
  color: var(--accent);
}
.checkbox-label.small {
  font-size: 0.78rem;
  gap: 0.35rem !important;
}

.package-toggle-form { padding: 0 0.5rem; margin-top: 0.35rem; }
.select-form-button {
  width: 100%;
  padding: 0.4rem;
  font-size: 0.8rem;
}

.floating-cart {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 50;
  background: var(--accent);
  color: #1b1c1f;
  padding: 0.9rem 1.4rem;
  border-radius: 999px;
  font-weight: 600;
  box-shadow: 0 4px 16px rgba(0,0,0,0.4);
}
.floating-cart:hover { text-decoration: none; opacity: 0.9; }
/* Empty-cart state — still visible on every page (so the cart is never
   "hidden" just because nothing's in it yet), but deliberately quieter than
   the filled state so it doesn't compete for attention with an actual call
   to action. */
.floating-cart-empty {
  background: var(--bg-alt, #2a2b2f);
  color: var(--fg-muted, #b7b7bd);
  border: 1px solid var(--fg-muted, #4a4a50);
  font-weight: 500;
  box-shadow: none;
  padding: 0.6rem 1.1rem;
}

/* Floating "back to top" button — bottom-LEFT so it never overlaps the
   floating cart badge above (that one's bottom-right). Hidden by default;
   public/js/back-to-top.js toggles .visible once the page is scrolled down. */
.back-to-top {
  position: fixed;
  bottom: 1.5rem;
  left: 1.5rem;
  z-index: 50;
  padding: 0.7rem 1.1rem;
  background: var(--accent);
  color: #1b1c1f;
  border: none;
  border-radius: 999px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(0,0,0,0.4);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
}
.back-to-top.visible { opacity: 1; visibility: visible; transform: translateY(0); }

.photo-detail { display: grid; grid-template-columns: 2fr 1fr; gap: 2rem; margin-top: 1.5rem; }
.photo-detail img { width: 100%; border-radius: 6px; }
.photo-detail-side button, .photo-detail-side .button-link {
  display: block;
  width: 100%;
  padding: 0.8rem;
  margin: 0.5rem 0;
  text-align: center;
}
.photo-detail-position { margin: 0 0 1rem; }

/* Prev/Next arrows overlaid on the single-photo page's image (see
   views/photo.ejs) — same round, semi-transparent look as .lightbox-nav in
   the gallery grid's overlay, just positioned relative to the image itself
   instead of a full-viewport overlay, since this page has no dark backdrop
   to sit on. */
.photo-detail-image-wrap { position: relative; }
.photo-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 2.5rem;
  height: 2.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 1.2rem;
  border-radius: 50%;
  text-decoration: none;
  transition: background 0.15s ease;
}
.photo-nav:hover { background: rgba(0, 0, 0, 0.65); }
.photo-nav-prev { left: 0.75rem; }
.photo-nav-next { right: 0.75rem; }

@media (max-width: 720px) {
  .photo-detail { grid-template-columns: 1fr; }
}

/* Click-to-enlarge lightbox for the public gallery grid (bib search
   results included) — see gallery-lightbox.js. Scoped to .photo-tile so
   this doesn't touch the admin panel's own (separate) lightbox or the
   cart page's photo tiles. */
.photo-tile img { cursor: zoom-in; }

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
.lightbox.hidden { display: none; }
.lightbox-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  max-width: 90vw;
  max-height: 90vh;
}
.lightbox-content img {
  max-width: 90vw;
  max-height: 75vh;
  object-fit: contain;
  border-radius: 4px;
}
/* Filename caption under the enlarged image (see #lightbox-title in
   gallery.ejs, populated in gallery-lightbox.js) — .lightbox-content's own
   flex gap already spaces it from the image above and the buttons below,
   so this only needs to handle its own text look. */
.lightbox-title {
  margin: 0;
  max-width: 90vw;
  color: #fff;
  font-size: 0.9rem;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lightbox-actions { display: flex; gap: 0.75rem; }
.lightbox-actions button, .lightbox-actions .button-link {
  padding: 0.7rem 1.4rem;
  font-size: 0.95rem;
}
.lightbox-close {
  position: absolute;
  top: 1rem;
  right: 1.5rem;
  background: none;
  border: none;
  color: #fff;
  font-size: 2.4rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}
.lightbox-close:hover { opacity: 0.8; }
.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, 0.12);
  border: none;
  color: #fff;
  font-size: 1.3rem;
  padding: 0.75rem 1rem;
  cursor: pointer;
  border-radius: 6px;
}
.lightbox-nav:hover { background: rgba(255, 255, 255, 0.28); }
.lightbox-prev { left: 1rem; }
.lightbox-next { right: 1rem; }
body.lightbox-open { overflow: hidden; }

.back-link { display: inline-block; margin-bottom: 1rem; color: var(--fg-muted); }

.cart-section, .admin-section {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}

.package-option {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
}
.package-option:last-of-type { border-bottom: none; }
.package-option input { margin-top: 0.3rem; }
.package-option p { margin: 0.25rem 0 0; color: var(--fg-muted); font-size: 0.9rem; }

.qty-label { display: block; margin: 1rem 0; }
.qty-label input { width: 5rem; margin-left: 0.5rem; }

.package-fill-box {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 1rem;
  margin-bottom: 1.25rem;
}
.package-fill-box-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.75rem;
}
.package-fill-box-header form { flex-shrink: 0; }
.package-fill-box-header button.remove { width: auto; padding: 0.4rem 0.8rem; }

/* Stays pinned to the top of the viewport while the customer scrolls through
   the "fill each package" section (sticky within its containing section, so
   it scrolls away naturally once that section ends) — a constant reminder of
   which direction to scroll for the two things they'll want next. */
/* Containing block for .scroll-hint's sticky positioning — spans from the
   package section through the digital-downloads section, ending right
   before the order summary. That's what makes the hint stay pinned in view
   the whole time the customer is filling packages / adding extra prints or
   downloads, then scroll away naturally once they actually reach the order
   summary at the bottom. */
.scroll-hint-wrapper { position: relative; }

/* Anchor-jump targets (#choose-packages, #fill-packages, #package-fill-<id>,
   #order-summary) all get a little breathing room above them so the sticky
   .scroll-hint bar never lands directly on top of — and hides — the heading
   the browser just jumped to. */
#choose-packages, #fill-packages, .package-fill-box, #order-summary {
  scroll-margin-top: 4.5rem;
}

.scroll-hint {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0 0 1.25rem;
  padding: 0.6rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.scroll-hint .button-link { font-size: 0.85rem; padding: 0.5rem 1rem; }

/* Backdoor-gallery banner pointing at the real public gallery to share (see
   routes/public.js linkedTargetGallery) — same card treatment as
   .scroll-hint, just not sticky, since it only needs to be seen once at the
   top of the page rather than while scrolling through photos. */
.linked-gallery-note {
  margin: 0 0 1.25rem;
  padding: 0.7rem 0.9rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.linked-gallery-note .copy-link-btn {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

/* Same look as .scroll-hint but not sticky — this one lives inside the
   order summary itself, next to the "these photos aren't covered yet"
   notice, so it's just a plain inline action rather than something that
   needs to follow the customer while they scroll. */
.uncovered-hint {
  display: flex;
  margin: 0 0 1rem;
}
.uncovered-hint .button-link { font-size: 0.85rem; padding: 0.5rem 1rem; }
.package-fill-box h3 { margin: 0; font-size: 1rem; }
.cart-photo-grid.small { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.75rem; margin-bottom: 1rem; }
.photo-check-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.5rem;
  cursor: pointer;
  text-align: center;
}
.photo-check-tile img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: 4px; }
.photo-check-tile.disabled { opacity: 0.45; cursor: not-allowed; }
.photo-check-tile .cart-photo-filename { padding: 0; }

.package-fill-box h4 { margin: 1rem 0 0.25rem; font-size: 0.95rem; }
.package-print-slot {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.5rem 0;
  border-top: 1px solid var(--border);
}
.package-print-slot:first-of-type { border-top: none; }
.package-print-slot strong { min-width: 90px; }

.cart-table { width: 100%; border-collapse: collapse; margin-bottom: 1rem; }
.cart-table td { padding: 0.5rem 0.25rem; border-bottom: 1px solid var(--border); }

.add-print-form { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.add-print-form select, .add-print-form input { padding: 0.5rem; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; }

/* Print crop-preview box (see public/js/print-crop-preview.js) — shows a
   dashed crop boundary over the chosen photo once both a photo and a print
   size are selected on the "Add print" form above. */
.print-crop-preview { max-width: 360px; margin: 0.75rem 0 1rem; }
.print-crop-preview-frame { position: relative; display: inline-block; max-width: 100%; }
.print-crop-preview-frame img { display: block; max-width: 100%; height: auto; border-radius: 4px; }
.print-crop-preview-box {
  position: absolute;
  border: 2px dashed var(--accent);
  box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.35);
  pointer-events: none;
  display: none;
}

/* "Update package", "Add print", "Add download" — matches the same gold
   accent used by the Checkout button and every other primary action button
   site-wide, rather than falling back to a plain unstyled button. */
.package-form button,
.add-print-form button {
  padding: 0.65rem 1.1rem;
  background: var(--accent);
  color: #1b1c1f;
  border: none;
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
}
.package-form button:hover,
.add-print-form button:hover {
  opacity: 0.9;
}

.order-summary-list {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.order-summary-list li {
  padding: 0.5rem 0;
  color: var(--fg);
  font-size: 0.92rem;
}
.order-summary-list li + li { border-top: 1px solid var(--border); }
.totals p { margin: 0.25rem 0; color: var(--fg-muted); }
.grand-total { color: var(--fg) !important; font-size: 1.3rem; font-weight: 600; margin-top: 0.5rem !important; }
.checkout-button {
  width: 100%;
  padding: 1rem;
  margin-top: 1rem;
  background: var(--accent);
  color: #1b1c1f;
  border: none;
  border-radius: 4px;
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
}
.checkout-button[disabled] { opacity: 0.5; cursor: not-allowed; }

.link-button {
  background: none;
  border: none;
  color: var(--fg-muted);
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
  margin-top: 0.75rem;
}

.stacked-form { display: flex; flex-direction: column; gap: 1rem; max-width: 480px; }
.stacked-form label { display: flex; flex-direction: column; gap: 0.35rem; color: var(--fg-muted); }
.stacked-form input, .stacked-form textarea, .stacked-form select {
  padding: 0.6rem;
  background: var(--bg);
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-size: 1rem;
}
.stacked-form button {
  padding: 0.8rem;
  background: var(--accent);
  color: #1b1c1f;
  border: none;
  border-radius: 4px;
  font-weight: 600;
  cursor: pointer;
}
.checkbox-label { flex-direction: row !important; align-items: center; gap: 0.5rem !important; }

.shipping-options-form { margin: 0.75rem 0; }
.shipping-option-choice {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0;
  cursor: pointer;
}
.shipping-options-form button { margin-top: 0.5rem; }

.button-link {
  display: inline-block;
  padding: 0.6rem 1.2rem;
  background: var(--accent);
  color: #1b1c1f !important;
  border-radius: 4px;
  font-weight: 600;
}
.button-link:hover { text-decoration: none; opacity: 0.9; }
.download-all-top { margin: 0.5rem 0 1rem; }
.download-all-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0.5rem 0 1rem;
}
.download-all-form select {
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-card);
  color: var(--fg);
}

.error { color: var(--error); }
.success { color: #5cb87a; }
.empty { color: var(--fg-muted); }
.fine-print { color: var(--fg-muted); font-size: 0.85rem; }
.hint { color: var(--fg-muted); font-size: 0.9rem; }
.private-note { color: var(--fg-muted); font-size: 0.9rem; margin-top: 2rem; }
/* Cart-page callout letting a customer know they can drop the race/event
   logo from any photo — only shown when at least one selected photo
   actually has one available (see views/cart.ejs). */
.cart-logo-note {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.7rem 1rem;
  margin: 1rem 0;
  font-size: 0.9rem;
}
.folder-breadcrumbs { margin-bottom: 0.75rem; }
.folder-breadcrumbs a { color: var(--fg-muted); }
.download-list { list-style: none; padding: 0; }
.download-list li { margin-bottom: 0.5rem; }
.download-list a { display: inline-block; padding: 0.6rem 1rem; background: var(--accent); color: #1b1c1f; border-radius: 4px; }
