/* Shared gallery stylesheet.
 *
 * Loaded by BOTH:
 *   - gallery-server/public/gallery.html  (the real client gallery, served at /g/<token>,
 *     links this at /public/gallery.css)
 *   - website/gallery.css                 (a byte-identical copy shipped with prooftide.com's
 *     gallery-preview.html; kept in sync by website/scripts/sync-gallery-css.sh, and the
 *     website deploy re-copies this file and fails on drift)
 *
 * This file is the canonical copy. Edit it here, then run website/scripts/sync-gallery-css.sh.
 */

:root {
  /* Fixed light appearance — this page doesn't follow system dark mode, so browser-
     native controls (the language <select>) shouldn't try to either. Colors sampled
     directly from the "Aurore" mockup (repo root Aurore.png at plan time). This is also
     the "aurore" style/data-style value's own set of colors/fonts -- it needs no
     [data-style="aurore"] block below since these are already the page's defaults. */
  color-scheme: light;
  --bg: #faf4ec;
  --fg: #211c17;
  --muted: #736a63;
  --accent: #af6340;
  --card: #ffffff;
  --border: #e7ddd0;
  --danger: #b3423a;
  --font-heading: "Cormorant Garamond", Georgia, serif;
  --font-body: "Work Sans", Inter, Avenir, Helvetica, Arial, sans-serif;
}
/* Gallery styles below (colors + fonts only, --card/--danger never vary) -- kept in sync
   by hand with gallery-server/src/styles.ts's GALLERY_STYLES, the source of truth for the
   desktop app's picker and validation; this page isn't wired to fetch that list at
   runtime, so a person updates both when a style is added or removed. Values are exactly
   as authored in the source design mockups (a Claude artifact of Aurore color/font
   variants shared 2026-09-09). */
[data-style="ivoire"] {
  --bg: oklch(97% 0.010 90);
  --fg: oklch(20% 0.010 60);
  --muted: oklch(50% 0.014 60);
  --border: oklch(88% 0.010 80);
  --accent: oklch(38% 0.12 20);
  --font-heading: "Playfair Display", Georgia, serif;
  --font-body: "Manrope", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="lin-naturel"] {
  --bg: oklch(96% 0.015 85);
  --fg: oklch(30% 0.020 70);
  --muted: oklch(55% 0.018 70);
  --border: oklch(88% 0.016 80);
  --accent: oklch(52% 0.08 120);
  --font-heading: "EB Garamond", Georgia, serif;
  --font-body: "Karla", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="ardoise"] {
  --bg: oklch(96% 0.006 240);
  --fg: oklch(25% 0.020 240);
  --muted: oklch(53% 0.020 240);
  --border: oklch(88% 0.010 240);
  --accent: oklch(55% 0.09 240);
  --font-heading: "Spectral", Georgia, serif;
  --font-body: "Public Sans", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="poudre"] {
  --bg: oklch(97% 0.012 20);
  --fg: oklch(28% 0.040 340);
  --muted: oklch(55% 0.030 340);
  --border: oklch(89% 0.014 20);
  --accent: oklch(60% 0.09 350);
  --font-heading: "Domine", Georgia, serif;
  --font-body: "Albert Sans", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="contraste"] {
  --bg: oklch(99% 0 0);
  --fg: oklch(12% 0 0);
  --muted: oklch(46% 0 0);
  --border: oklch(88% 0 0);
  --accent: oklch(48% 0.19 25);
  --font-heading: "Bodoni Moda", Georgia, serif;
  --font-body: "Outfit", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="sauge"] {
  --bg: oklch(97% 0.015 145);
  --fg: oklch(28% 0.030 150);
  --muted: oklch(53% 0.024 150);
  --border: oklch(89% 0.016 145);
  --accent: oklch(55% 0.07 150);
  --font-heading: "Prata", Georgia, serif;
  --font-body: "Mulish", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="corail"] {
  --bg: oklch(97% 0.020 50);
  --fg: oklch(30% 0.030 40);
  --muted: oklch(55% 0.026 40);
  --border: oklch(89% 0.022 50);
  --accent: oklch(65% 0.15 35);
  --font-heading: "Instrument Serif", Georgia, serif;
  --font-body: "Figtree", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="bleu-nuit"] {
  --bg: oklch(97% 0.008 250);
  --fg: oklch(22% 0.050 260);
  --muted: oklch(50% 0.030 260);
  --border: oklch(89% 0.012 250);
  --accent: oklch(50% 0.15 260);
  --font-heading: "Gilda Display", Georgia, serif;
  --font-body: "Archivo", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="ocre"] {
  --bg: oklch(96% 0.020 80);
  --fg: oklch(28% 0.030 55);
  --muted: oklch(54% 0.026 60);
  --border: oklch(88% 0.022 80);
  --accent: oklch(62% 0.13 75);
  --font-heading: "Cardo", Georgia, serif;
  --font-body: "Nunito Sans", Inter, Avenir, Helvetica, Arial, sans-serif;
}
[data-style="graphite-acidule"] {
  --bg: oklch(96% 0.004 90);
  --fg: oklch(24% 0.005 90);
  --muted: oklch(52% 0.006 90);
  --border: oklch(87% 0.006 90);
  --accent: oklch(70% 0.17 130);
  --font-heading: "Libre Caslon Display", Georgia, serif;
  --font-body: "Space Grotesk", Inter, Avenir, Helvetica, Arial, sans-serif;
}
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 400;
  background: var(--bg);
  color: var(--fg);
}
.lang-menu {
  grid-area: lang;
  position: relative;
}
#lang-trigger {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.8rem;
  color: var(--muted);
  cursor: pointer;
  padding: 0.3rem 0.2rem;
  border-radius: 4px;
}
#lang-trigger:hover {
  color: var(--fg);
}
#lang-trigger:focus-visible {
  outline: none;
  background: var(--border);
}
#lang-trigger svg {
  flex-shrink: 0;
}
.lang-list {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(33, 28, 23, 0.12);
  padding: 0.35rem;
  min-width: 140px;
  z-index: 6;
}
.lang-list[hidden] {
  display: none;
}
.lang-option {
  display: block;
  width: 100%;
  appearance: none;
  border: none;
  background: none;
  text-align: left;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--fg);
  cursor: pointer;
  padding: 0.5rem 0.7rem;
  border-radius: 5px;
}
.lang-option:hover {
  background: var(--bg);
}
.lang-option:focus-visible {
  outline: none;
  background: var(--border);
}
.lang-option.active {
  color: var(--accent);
  font-weight: 500;
}
header {
  max-width: 1400px;
  margin: 0 auto;
  padding: 2rem 1.5rem 0;
}
/* A grid, not flex: logo/tabs/language need to swap between two genuinely different 2-D
   arrangements (all three side by side vs. the language selector paired with the logo
   while tabs drops to its own full-width row) rather than just reflowing along one axis.
   Named grid areas place each element explicitly per breakpoint, independent of their
   order in the HTML — the thing flex's `order` can't do without also reordering them
   within a single row, which would touch the wide layout too. See the max-width block
   below for the narrow arrangement. */
.header-top {
  display: grid;
  align-items: center;
  /* minmax(0, ...), not a plain auto, on the logo column: unlike flex's shrink behavior
     flex-wrap already relies on elsewhere in this file, a Grid track sized just `auto`
     never shrinks below its content's own natural size — with a wide custom logo and a
     narrow-enough viewport (a long lang-menu label isn't even needed to trigger it), that
     content overflows header-top's own box instead of the column ever giving ground. */
  grid-template-columns: minmax(0, auto) 1fr auto;
  grid-template-areas: "logo tabs lang";
  column-gap: 1.5rem;
  row-gap: 0.75rem;
  min-height: 2rem;
}
header #gallery-logo {
  grid-area: logo;
  /* min-width: 0 overrides the grid item default (content's own natural width, same
     `auto` floor the column-level minmax above works around) — without it, the image
     still refuses to shrink below 207ish px regardless of what the column would allow.
     max-width uses min() so the logo still caps at the original 220px design size
     whenever the column has room for it, and only gives ground below that when it
     genuinely doesn't; width/height: auto keeps it scaling proportionally either way,
     never distorting its aspect ratio. */
  min-width: 0;
  width: auto;
  height: auto;
  max-height: 56px;
  max-width: min(220px, 100%);
  display: block;
}
header #gallery-logo[hidden] {
  display: none;
}
#tabs {
  grid-area: tabs;
  display: flex;
  gap: 1.5rem;
  /* Right-aligned within its own (flexible) grid column, so the empty space this column
     doesn't need collects on tabs' left — between it and the logo — rather than between
     tabs and the language selector, matching the original flex layout's rhythm (a big gap
     after the logo, a small one before the language selector). */
  justify-self: end;
  /* Last-resort fallback, not the primary fix (the language selector now has a
     guaranteed-safe route to its own row below tabs — see the max-width block): if a
     locale's tab labels are ever too long to both fit on tabs' own full-width row, wrap
     rather than overflow it. */
  flex-wrap: wrap;
}
.tab {
  appearance: none;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--muted);
  cursor: pointer;
  padding: 0.25rem 0 0.4rem;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.tab.active {
  font-weight: 400;
  color: var(--fg);
  border-bottom-color: var(--accent);
}
/* Below this, logo + tabs + language selector no longer reliably fit on one row (a
   near-max-width 220px logo plus the longest tab labels across locales, e.g. Spanish
   "Todas las fotos (1000)" for a Pro-tier gallery, plus the language selector, add up to
   more than this). Pairs the language selector with the logo instead of the tabs, since
   it's the one that's always short regardless of gallery/photo count or locale — tabs
   gets its own full-width row below, where its labels have the most room to stay on one
   line. */
@media (max-width: 640px) {
  .header-top {
    grid-template-areas:
      "logo . lang"
      "tabs tabs tabs";
  }
  #tabs {
    justify-self: start;
  }
}
header h1 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 2.6rem;
  margin: 1.75rem 0 0.4rem;
}
#gallery-subtitle {
  margin: 0 0 1.5rem;
  color: var(--muted);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
#gallery-subtitle[hidden] {
  display: none;
}
#status-bar {
  max-width: 1400px;
  margin: 0 auto;
  padding: 1rem 1.5rem;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  row-gap: 0.6rem;
  /* Same reasoning as .header-top: without this, #status-actions' two buttons have
     nowhere to go on a narrow viewport and overflow past status-bar's own right edge
     instead of dropping to their own row. */
  flex-wrap: wrap;
}
#status-bar[hidden] {
  display: none;
}
#gallery-count {
  margin: 0;
  font-weight: 400;
  font-size: 0.85rem;
}
#gallery-count.count-exceeded {
  color: var(--danger);
}
#gallery-count .warning-icon {
  display: inline-block;
  margin-left: 0.35rem;
  cursor: help;
}
#status-actions {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.text-btn {
  appearance: none;
  border: none;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.85rem;
  background: var(--fg);
  color: #ffffff;
  cursor: pointer;
  padding: 0.55rem 1.15rem;
  border-radius: 999px;
}
.text-btn:hover {
  background: var(--accent);
}
.text-btn:disabled {
  background: var(--border);
  color: var(--muted);
  cursor: default;
}
#locked-banner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0.85rem 1.5rem;
  color: var(--danger);
  font-size: 0.85rem;
  text-align: center;
}
#locked-banner[hidden] {
  display: none;
}
#status {
  text-align: center;
  color: var(--muted);
  padding: 3rem 1rem;
}
#grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  padding: 1.5rem 1.5rem 3rem;
  max-width: 1400px;
  margin: 0 auto;
}
.thumb {
  position: relative;
  height: 280px;
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  padding: 0;
  border: none;
  background: var(--card);
}
.thumb img {
  height: 100%;
  width: auto;
  max-width: 420px;
  object-fit: cover;
  display: block;
}

.select-btn {
  border: none;
  border-radius: 50%;
  width: 2.1rem;
  height: 2.1rem;
  font-size: 1.15rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Always the same light circle (matching the mockup) — only the heart glyph's color
     switches, so contrast against unpredictable photo brightness comes from the
     consistently-light background, not from swapping the button's own fill. */
  background: rgba(255, 255, 255, 0.85);
  color: var(--muted);
  transition: color 0.15s, transform 0.1s;
}
.select-btn:hover {
  color: var(--accent);
}
.select-btn.selected {
  color: var(--accent);
}
.thumb .select-btn {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 1;
}

/* Opposite corner from .select-btn, same circle -- purely informational (no click handler), so
   pointer-events is off and clicks pass straight through to the cell underneath it. */
.annotation-badge {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  z-index: 1;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.85);
  color: var(--accent);
  pointer-events: none;
}

/* A row, not the old "photo centered, controls floating over it" layout: #lightbox-media and
   #lightbox-sidebar sit side by side, both vertically centered as a unit. flex-wrap lets the
   sidebar drop below the photo on a viewport too narrow to hold both side by side, rather than
   either overlapping or overflowing the screen. */
#lightbox {
  position: fixed;
  inset: 0;
  background: rgba(10, 11, 13, 0.92);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 1.25rem;
  padding: 3.5rem 4rem;
  overflow-y: auto;
  z-index: 10;
}
#lightbox[hidden] {
  display: none;
}
/* Wraps #lightbox-img so #annotation-canvas can be absolutely positioned exactly on top of it,
   at whatever size the image itself renders at (inline-flex sizes the wrapper to its content,
   same max-width/max-height ceiling as the image so it never grows past it) -- capped narrower
   than before (was 90vw) and no longer purely viewport-relative, so there's reliably enough
   room left over for #lightbox-sidebar (min(300px, 100%) wide) beside it down to a ~1050px
   viewport; narrower than that and flex-wrap drops the sidebar to its own line below instead. */
#lightbox-media {
  position: relative;
  display: inline-flex;
  max-width: min(60vw, 820px);
  max-height: 78vh;
}
#lightbox-media img {
  max-width: min(60vw, 820px);
  max-height: 78vh;
  object-fit: contain;
  border-radius: 4px;
  display: block;
}
#annotation-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* Hidden (not just non-interactive) when the gallery hasn't enabled drawing at all -- see
     [hidden] below; pointer-events stays off otherwise so it doesn't swallow lightbox clicks
     except while the draw tool is actively toggled on. */
  touch-action: none;
}
#annotation-canvas[hidden] {
  display: none;
}
#annotation-canvas.drawing-active {
  pointer-events: auto;
  cursor: crosshair;
}
/* To the photo's right, never over it -- holds the nav arrows, the title/select row, and the
   (optional) annotation panel, stacked. Independently scrollable so a gallery with every
   annotation type enabled plus a long comment doesn't force the whole lightbox to scroll. */
#lightbox-sidebar {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  width: min(300px, 100%);
  max-height: 78vh;
  overflow-y: auto;
  color: #ffffff;
}
#lightbox-nav {
  display: flex;
  gap: 0.6rem;
}
#lightbox-header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
#lightbox-header .select-btn {
  background: rgba(255, 255, 255, 0.1);
  color: #ffffff;
  flex-shrink: 0;
}
#lightbox-header .select-btn.selected {
  color: var(--accent);
}
#lightbox-caption {
  color: #e7e9ee;
  font-size: 0.85rem;
  margin: 0;
}
#annotation-panel {
  background: rgba(255, 255, 255, 0.06);
  border-radius: 10px;
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  width: 100%;
  color: #ffffff;
}
#annotation-panel[hidden] {
  display: none;
}
/* Each annotation type is its own labeled block, not just a run of controls -- a divider
   between blocks is what keeps three genuinely different kinds of annotation from reading as
   one undifferentiated run of buttons. The general-sibling form (~, not the adjacent +) matters
   because a gallery can enable any subset of the three types: it puts the border on every
   visible section that has *some* earlier visible sibling, not just an immediately-adjacent one
   -- so if, say, the text section is disabled, the audio section (now visually first) still
   correctly gets no top border instead of one left dangling with nothing above it to divide. */
.annotation-section {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem 0;
}
.annotation-section[hidden] {
  display: none;
}
.annotation-section:not([hidden]) ~ .annotation-section:not([hidden]) {
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.annotation-section-label {
  margin: 0;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(255, 255, 255, 0.55);
}
.annotation-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
#annotation-text-input {
  flex: 1 1 160px;
  min-width: 0;
  resize: vertical;
  font-family: var(--font-body);
  font-size: 0.85rem;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
  padding: 0.5rem 0.6rem;
}
#annotation-text-input::placeholder {
  color: rgba(255, 255, 255, 0.55);
}
.annotation-btn {
  appearance: none;
  border: none;
  border-radius: 999px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.78rem;
  padding: 0.45rem 0.9rem;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.14);
  color: #ffffff;
  white-space: nowrap;
}
.annotation-btn:hover {
  background: rgba(255, 255, 255, 0.26);
}
.annotation-btn:disabled {
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.4);
  cursor: default;
}
#annotation-text-input:disabled,
.annotation-color-input:disabled {
  opacity: 0.5;
  cursor: default;
}
.annotation-btn.recording {
  background: var(--danger);
}
.annotation-btn.active {
  background: var(--accent);
}
.annotation-status {
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.7);
}
.annotation-status:empty {
  display: none;
}
#annotation-audio-playback {
  height: 2.1rem;
  max-width: 220px;
}
/* A native color swatch, not a text-styled .annotation-btn -- kept small and square so it reads
   as a color picker among the round pill buttons rather than trying to imitate them. */
.annotation-color-input {
  appearance: none;
  -webkit-appearance: none;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-radius: 50%;
  background: none;
  cursor: pointer;
  flex-shrink: 0;
}
.annotation-color-input::-webkit-color-swatch-wrapper {
  padding: 0;
}
.annotation-color-input::-webkit-color-swatch {
  border: none;
  border-radius: 50%;
}
.annotation-color-input::-moz-color-swatch {
  border: none;
  border-radius: 50%;
}

.lightbox-btn {
  background: rgba(255, 255, 255, 0.1);
  color: #ffffff;
  border: none;
  border-radius: 50%;
  width: 2.75rem;
  height: 2.75rem;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.lightbox-btn:hover {
  background: rgba(255, 255, 255, 0.22);
}
/* The only lightbox-btn still floating over the photo rather than living in the sidebar --
   closing the whole overlay reads naturally as a top-corner action regardless of layout. */
#lightbox-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
}
