/* ---------------------------------------------------------------------------
   PhotoGallery — visual system

   Dark by default because that is what photo tools do: a neutral, slightly
   cool near-black recedes and lets the photographs supply all the colour. The
   palette is four greys, one warm accent, and nothing else. Type is the system
   UI stack at tight tracking; metadata is set in a monospace face so numbers
   line up in columns.
--------------------------------------------------------------------------- */

:root {
  --bg:        #0b0b0d;
  --bg-raised: #141418;
  --bg-hover:  #1c1c22;
  --line:      #26262e;
  --line-soft: #1a1a20;

  --text:      #e9e9ee;
  --text-dim:  #9a9aa6;
  --text-faint:#63636f;

  --accent:    #f0b429;
  --accent-dim:#8a6614;
  --danger:    #e5484d;
  --ok:        #46a758;

  --radius: 8px;
  --radius-lg: 14px;
  --sidebar: 272px;
  --topbar: 56px;

  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--bg); color: var(--text);
  font-family: var(--sans);
  font-size: 14px; line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
}

button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #2a2a33; border-radius: 6px; border: 3px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: #3a3a46; }

/* --- layout ------------------------------------------------------------- */

.app { display: grid; grid-template-columns: var(--sidebar) 1fr; height: 100vh; }
.app.filters-hidden { grid-template-columns: 0 1fr; }

/* --- top bar ------------------------------------------------------------ */

.topbar {
  grid-column: 1 / -1;
  height: var(--topbar);
  display: flex; align-items: center; gap: 14px;
  padding: 0 16px;
  background: rgba(11,11,13,.86);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 60;
}

.brand {
  display: flex; align-items: center; gap: 9px;
  font-weight: 600; letter-spacing: -.02em; font-size: 15px;
  white-space: nowrap;
}
.brand .mark {
  width: 22px; height: 22px; border-radius: 5px;
  background: linear-gradient(145deg, var(--accent), #d97706);
  display: grid; place-items: center; color: #1a1206; font-size: 12px;
}

.searchbar { flex: 1; max-width: 620px; position: relative; }
.searchbar input {
  width: 100%; height: 36px;
  padding: 0 34px 0 34px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 18px;
  outline: none;
  transition: border-color .15s, background .15s;
}
.searchbar input:focus { border-color: var(--accent-dim); background: #17171c; }
.searchbar .icon {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  color: var(--text-faint); pointer-events: none;
}
.searchbar .clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  background: none; border: 0; color: var(--text-faint); cursor: pointer;
  padding: 4px; border-radius: 4px; line-height: 0;
}
.searchbar .clear:hover { color: var(--text); background: var(--bg-hover); }

.topbar-right { display: flex; align-items: center; gap: 6px; margin-left: auto; }

/* --- buttons ------------------------------------------------------------ */

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 12px;
  background: var(--bg-raised); border: 1px solid var(--line);
  border-radius: var(--radius); cursor: pointer;
  color: var(--text-dim); white-space: nowrap;
  transition: background .13s, color .13s, border-color .13s;
}
.btn:hover { background: var(--bg-hover); color: var(--text); }
.btn.active { background: var(--accent); border-color: var(--accent); color: #1a1206; font-weight: 500; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #1a1206; font-weight: 500; }
.btn.primary:hover { background: #ffc53d; color: #1a1206; }
.btn.icon { width: 32px; padding: 0; justify-content: center; }
.btn.danger:hover { background: #2a1416; border-color: var(--danger); color: var(--danger); }
.btn:disabled { opacity: .45; cursor: not-allowed; }

/* --- sidebar ------------------------------------------------------------ */

.sidebar {
  background: var(--bg);
  border-right: 1px solid var(--line);
  overflow-y: auto; overflow-x: hidden;
  padding: 14px 0 60px;
}
.app.filters-hidden .sidebar { display: none; }

.nav { padding: 0 10px 12px; border-bottom: 1px solid var(--line-soft); margin-bottom: 6px; }
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border-radius: var(--radius);
  color: var(--text-dim); cursor: pointer;
}
.nav a:hover { background: var(--bg-raised); color: var(--text); }
.nav a.active { background: var(--bg-hover); color: var(--text); font-weight: 500; }
.nav a .count { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--text-faint); }

.facet { border-bottom: 1px solid var(--line-soft); }
.facet > summary {
  padding: 10px 16px; cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--text-faint); user-select: none;
}
.facet > summary::-webkit-details-marker { display: none; }
.facet > summary::before {
  content: '▸'; font-size: 9px; transition: transform .15s; color: var(--text-faint);
}
.facet[open] > summary::before { transform: rotate(90deg); }
.facet > summary:hover { color: var(--text-dim); }
.facet-body { padding: 0 10px 12px; }

.facet-item {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: 5px; cursor: pointer;
  color: var(--text-dim); font-size: 13px;
}
.facet-item:hover { background: var(--bg-raised); color: var(--text); }
.facet-item.on { background: var(--bg-hover); color: var(--accent); }
.facet-item .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.facet-item .count { margin-left: auto; font-family: var(--mono); font-size: 10px; color: var(--text-faint); }

.range { display: flex; align-items: center; gap: 6px; padding: 4px 8px; }
.range input {
  width: 100%; min-width: 0; height: 28px; padding: 0 8px;
  background: var(--bg-raised); border: 1px solid var(--line);
  border-radius: 6px; outline: none; font-family: var(--mono); font-size: 12px;
}
.range input:focus { border-color: var(--accent-dim); }
.range span { color: var(--text-faint); font-size: 11px; }

.chips { display: flex; flex-wrap: wrap; gap: 5px; padding: 4px 8px; }
.chip {
  padding: 3px 9px; border-radius: 11px; font-size: 12px; cursor: pointer;
  background: var(--bg-raised); border: 1px solid var(--line); color: var(--text-dim);
}
.chip:hover { border-color: #3a3a46; color: var(--text); }
.chip.on { background: var(--accent); border-color: var(--accent); color: #1a1206; }

/* --- main --------------------------------------------------------------- */

.main { overflow-y: auto; position: relative; }

.toolbar {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--line-soft);
  position: sticky; top: 0; z-index: 40;
  background: rgba(11,11,13,.9); backdrop-filter: blur(10px);
}
.result-count { color: var(--text-dim); font-size: 13px; }
.result-count b { color: var(--text); font-family: var(--mono); font-weight: 500; }
.toolbar .spacer { flex: 1; }

select.select {
  height: 32px; padding: 0 26px 0 10px;
  background: var(--bg-raised) url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none' stroke='%239a9aa6' stroke-width='1.6'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E") no-repeat right 9px center;
  border: 1px solid var(--line); border-radius: var(--radius);
  appearance: none; cursor: pointer; color: var(--text-dim); outline: none;
}
select.select:hover { color: var(--text); }

/* active filter pills */
.active-filters { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 20px 12px; }
.active-filters:empty { display: none; }
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 6px 3px 10px; border-radius: 13px; font-size: 12px;
  background: var(--bg-hover); border: 1px solid var(--line); color: var(--text-dim);
}
.pill b { color: var(--text); font-weight: 500; }
.pill button {
  background: none; border: 0; cursor: pointer; color: var(--text-faint);
  padding: 2px 4px; border-radius: 50%; line-height: 0;
}
.pill button:hover { color: var(--danger); background: rgba(229,72,77,.12); }

/* --- justified photo grid ----------------------------------------------- */
/*
   Rows are laid out by app.js: it fills a row with photos until their combined
   aspect ratio reaches the target, then scales the row to the exact container
   width. That is why every row's right edge lines up perfectly while every
   photo keeps its true proportions — no cropping, no letterboxing.
*/

.grid { padding: 4px 20px 80px; }
.grid-row { display: flex; gap: 4px; margin-bottom: 4px; }

.tile {
  position: relative; overflow: hidden; border-radius: 3px;
  background: var(--bg-raised); cursor: pointer; flex-shrink: 0;
}
.tile img.full {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0; transition: opacity .35s ease;
}
.tile img.full.loaded { opacity: 1; }
/* The blurred placeholder sits underneath and is simply covered up. */
.tile .lqip {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; filter: blur(6px); transform: scale(1.08);
}
.tile::after {
  content: ''; position: absolute; inset: 0;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.06);
  border-radius: 3px; pointer-events: none;
  transition: box-shadow .15s;
}
.tile:hover::after { box-shadow: inset 0 0 0 2px var(--accent); }
.tile.selected::after { box-shadow: inset 0 0 0 3px var(--accent); }

.tile-meta {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 20px 8px 6px;
  background: linear-gradient(transparent, rgba(0,0,0,.82));
  font-size: 11px; font-family: var(--mono); color: rgba(255,255,255,.9);
  opacity: 0; transition: opacity .15s;
  display: flex; gap: 8px; align-items: center;
  pointer-events: none;
}
.tile:hover .tile-meta { opacity: 1; }
.tile-meta .gps { color: var(--accent); }

.tile-check {
  position: absolute; top: 6px; left: 6px; width: 19px; height: 19px;
  border-radius: 50%; border: 1.5px solid rgba(255,255,255,.75);
  background: rgba(0,0,0,.35); opacity: 0; transition: opacity .12s;
  display: grid; place-items: center; z-index: 2;
}
.tile:hover .tile-check, .tile.selected .tile-check { opacity: 1; }
.tile.selected .tile-check { background: var(--accent); border-color: var(--accent); color: #1a1206; }

.tile-star {
  position: absolute; top: 6px; right: 6px;
  color: var(--accent); font-size: 12px; opacity: .95;
  text-shadow: 0 1px 3px rgba(0,0,0,.7); z-index: 2;
}

/* --- empty / loading states --------------------------------------------- */

.empty {
  padding: 90px 20px; text-align: center; color: var(--text-faint);
}
.empty h3 { color: var(--text-dim); font-weight: 500; margin: 0 0 6px; font-size: 16px; }
.empty p { margin: 0 0 18px; font-size: 13px; }

.spinner {
  width: 15px; height: 15px; border: 2px solid var(--line);
  border-top-color: var(--accent); border-radius: 50%;
  animation: spin .7s linear infinite; display: inline-block;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* --- lightbox ----------------------------------------------------------- */

.lightbox {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(6,6,8,.97);
  display: grid; grid-template-columns: 1fr 340px;
  opacity: 0; pointer-events: none; transition: opacity .18s;
}
.lightbox.open { opacity: 1; pointer-events: auto; }
.lightbox.no-info { grid-template-columns: 1fr 0; }

.lb-stage {
  position: relative; display: grid; place-items: center;
  overflow: hidden; padding: 20px;
}
.lb-stage img {
  max-width: 100%; max-height: calc(100vh - 40px);
  object-fit: contain; border-radius: 2px;
  box-shadow: 0 20px 70px rgba(0,0,0,.65);
}
.lb-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 42px; height: 68px; border: 0; border-radius: var(--radius);
  background: rgba(20,20,24,.7); color: var(--text-dim); cursor: pointer;
  display: grid; place-items: center; backdrop-filter: blur(6px);
  transition: background .13s, color .13s;
}
.lb-nav:hover { background: rgba(40,40,48,.9); color: var(--text); }
.lb-nav.prev { left: 14px; } .lb-nav.next { right: 14px; }
.lb-nav:disabled { opacity: .2; cursor: default; }

.lb-close {
  position: absolute; top: 14px; right: 14px; z-index: 3;
}

.lb-info {
  background: var(--bg-raised); border-left: 1px solid var(--line);
  overflow-y: auto; padding: 18px 18px 60px;
}
.lightbox.no-info .lb-info { display: none; }

.lb-title { font-size: 15px; font-weight: 600; margin: 0 0 2px; letter-spacing: -.01em; word-break: break-word; }
.lb-sub { color: var(--text-faint); font-size: 12px; font-family: var(--mono); margin-bottom: 16px; }

.stars { display: flex; gap: 3px; margin-bottom: 16px; }
.stars button {
  background: none; border: 0; cursor: pointer; padding: 2px;
  color: var(--line); font-size: 17px; line-height: 1; transition: color .1s;
}
.stars button.on { color: var(--accent); }
.stars button:hover { color: var(--accent); }

.meta-section { margin-bottom: 18px; }
.meta-section h4 {
  font-size: 10px; text-transform: uppercase; letter-spacing: .09em;
  color: var(--text-faint); margin: 0 0 8px; font-weight: 600;
}
.meta-grid { display: grid; grid-template-columns: auto 1fr; gap: 5px 14px; font-size: 12.5px; }
.meta-grid dt { color: var(--text-faint); white-space: nowrap; }
.meta-grid dd {
  margin: 0; font-family: var(--mono); font-size: 12px;
  color: var(--text); word-break: break-word;
}
.meta-grid dd.clickable { cursor: pointer; }
.meta-grid dd.clickable:hover { color: var(--accent); text-decoration: underline; }

/* The exposure triangle, given the prominence it has on a camera. */
.exposure {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
  background: var(--line); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; margin-bottom: 16px;
}
.exposure div { background: var(--bg); padding: 9px 6px; text-align: center; }
.exposure .v { font-family: var(--mono); font-size: 15px; color: var(--text); }
.exposure .k { font-size: 9.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); margin-top: 2px; }

#lb-map { height: 150px; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line); margin-bottom: 8px; }

.tag-input { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.tag-input input {
  flex: 1; min-width: 90px; height: 26px; padding: 0 8px;
  background: var(--bg); border: 1px solid var(--line); border-radius: 5px; outline: none; font-size: 12px;
}
.tag-input input:focus { border-color: var(--accent-dim); }
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 5px 2px 9px; border-radius: 11px; font-size: 11.5px;
  background: var(--bg-hover); border: 1px solid var(--line); color: var(--text-dim);
}
.tag button { background: none; border: 0; color: var(--text-faint); cursor: pointer; padding: 0 2px; line-height: 1; }
.tag button:hover { color: var(--danger); }

textarea.field, input.field {
  width: 100%; background: var(--bg); border: 1px solid var(--line);
  border-radius: 6px; padding: 7px 9px; outline: none; resize: vertical; font-size: 12.5px;
}
textarea.field:focus, input.field:focus { border-color: var(--accent-dim); }

details.raw-exif summary {
  cursor: pointer; font-size: 10px; text-transform: uppercase;
  letter-spacing: .09em; color: var(--text-faint); padding: 6px 0;
}
details.raw-exif pre {
  font-family: var(--mono); font-size: 10.5px; color: var(--text-dim);
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px;
  padding: 9px; overflow-x: auto; max-height: 280px; margin: 4px 0 0;
}

/* --- map view ----------------------------------------------------------- */

#map { width: 100%; height: calc(100vh - var(--topbar)); background: var(--bg-raised); }
.leaflet-container { background: #0f0f13 !important; font-family: var(--sans) !important; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
  background: var(--bg-raised) !important; color: var(--text) !important;
  border: 1px solid var(--line);
}
.leaflet-popup-content { margin: 8px 10px !important; font-size: 12px; }
.leaflet-control-attribution { background: rgba(11,11,13,.8) !important; color: var(--text-faint) !important; }
.leaflet-control-attribution a { color: var(--text-dim) !important; }
.leaflet-bar a { background: var(--bg-raised) !important; color: var(--text) !important; border-color: var(--line) !important; }
.leaflet-bar a:hover { background: var(--bg-hover) !important; }
/* The basemap is a genuinely dark raster (CARTO's dark_all, free and keyless).
   Inverting a light map instead was tempting, but a CSS filter on the tile pane
   leaves visible hairline seams wherever two tiles meet. */

.map-pin {
  background: var(--accent); border: 2px solid #1a1206;
  border-radius: 50%; width: 11px; height: 11px;
  box-shadow: 0 0 0 1px rgba(240,180,41,.35);
}
.cluster {
  background: rgba(240,180,41,.9); color: #1a1206;
  border-radius: 50%; display: grid; place-items: center;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  border: 2px solid #1a1206;
}

/* --- modal -------------------------------------------------------------- */

.modal-backdrop {
  position: fixed; inset: 0; z-index: 300;
  background: rgba(4,4,6,.72); backdrop-filter: blur(3px);
  display: grid; place-items: center; padding: 20px;
}
.modal {
  background: var(--bg-raised); border: 1px solid var(--line);
  border-radius: var(--radius-lg); width: 100%; max-width: 520px;
  max-height: 86vh; overflow-y: auto;
  box-shadow: 0 24px 80px rgba(0,0,0,.6);
}
.modal header {
  padding: 16px 20px; border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 10px;
}
.modal header h3 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
.modal .body { padding: 18px 20px; }
.modal footer {
  padding: 14px 20px; border-top: 1px solid var(--line);
  display: flex; gap: 8px; justify-content: flex-end;
}
.modal label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--text-faint); margin: 12px 0 5px; }
.modal label:first-child { margin-top: 0; }

/* --- drop zone / upload ------------------------------------------------- */

.dropzone {
  border: 1.5px dashed var(--line); border-radius: var(--radius-lg);
  padding: 34px 20px; text-align: center; color: var(--text-faint);
  transition: border-color .15s, background .15s, color .15s; cursor: pointer;
}
.dropzone:hover, .dropzone.over { border-color: var(--accent); background: rgba(240,180,41,.05); color: var(--text-dim); }

.progress { height: 3px; background: var(--line); border-radius: 2px; overflow: hidden; margin-top: 10px; }
.progress i { display: block; height: 100%; background: var(--accent); transition: width .2s; }

.upload-row {
  display: flex; align-items: center; gap: 8px; padding: 5px 0;
  font-size: 12px; border-bottom: 1px solid var(--line-soft);
}
.upload-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-dim); }
.upload-row .status { font-family: var(--mono); font-size: 11px; }
.status.added, .status.ok { color: var(--ok); }
.status.skipped, .status.updated { color: var(--text-faint); }
.status.duplicate { color: var(--accent); }
.status.failed, .status.rejected { color: var(--danger); }

/* --- toast -------------------------------------------------------------- */

.toasts { position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 400; display: flex; flex-direction: column; gap: 7px; align-items: center; }
.toast {
  background: var(--bg-hover); border: 1px solid var(--line);
  padding: 9px 15px; border-radius: 20px; font-size: 13px;
  box-shadow: 0 8px 28px rgba(0,0,0,.5);
  animation: rise .22s ease;
}
.toast.err { border-color: var(--danger); color: #ff9ea1; }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }

/* --- selection bar ------------------------------------------------------ */

.selbar {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%);
  z-index: 120; display: flex; align-items: center; gap: 8px;
  background: var(--bg-hover); border: 1px solid var(--line);
  padding: 8px 10px 8px 16px; border-radius: 24px;
  box-shadow: 0 10px 34px rgba(0,0,0,.55);
}
.selbar .n { font-family: var(--mono); font-size: 13px; color: var(--accent); }

/* --- login -------------------------------------------------------------- */

.auth-page { display: grid; place-items: center; min-height: 100vh; padding: 20px; }
.auth-card {
  width: 100%; max-width: 360px;
  background: var(--bg-raised); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: 30px;
  box-shadow: 0 20px 60px rgba(0,0,0,.45);
}
.auth-card .brand { justify-content: center; font-size: 17px; margin-bottom: 4px; }
.auth-card .tagline { text-align: center; color: var(--text-faint); font-size: 12.5px; margin-bottom: 24px; }
.auth-card input {
  width: 100%; height: 38px; padding: 0 12px; margin-bottom: 10px;
  background: var(--bg); border: 1px solid var(--line);
  border-radius: var(--radius); outline: none;
}
.auth-card input:focus { border-color: var(--accent-dim); }
.auth-card .btn { width: 100%; justify-content: center; height: 38px; margin-top: 6px; }
.auth-error { color: var(--danger); font-size: 12.5px; text-align: center; margin-top: 12px; min-height: 17px; }

/* --- share page --------------------------------------------------------- */

.share-header { padding: 26px 24px 16px; border-bottom: 1px solid var(--line); }
.share-header h1 { margin: 0 0 4px; font-size: 21px; font-weight: 600; letter-spacing: -.02em; }
.share-header p { margin: 0; color: var(--text-faint); font-size: 13px; }

/* --- responsive --------------------------------------------------------- */

@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; top: var(--topbar); bottom: 0; left: 0; width: 280px;
    z-index: 55; transform: translateX(-100%); transition: transform .2s;
    background: var(--bg);
  }
  .app.filters-open .sidebar { transform: none; box-shadow: 12px 0 40px rgba(0,0,0,.5); }
  .app.filters-hidden .sidebar { display: block; }
  .lightbox { grid-template-columns: 1fr; grid-template-rows: 1fr auto; }
  .lb-info { max-height: 44vh; border-left: 0; border-top: 1px solid var(--line); }
  .lightbox.no-info { grid-template-rows: 1fr 0; }
  .brand span { display: none; }
}
