/* Page chrome shared by every screen. Tokens live in tokens.css (copied from
   docs/design; keep them in sync, the design doc is the source of truth).
   Layout rules here follow docs/design/SYSTEM.md: hairlines over boxes, mono
   labels, 4px rhythm, one accent. */

/* ---------- topbar ---------- */
.topbar { display: flex; align-items: center; gap: var(--s-4) var(--s-5); padding: 0 var(--gutter); min-height: 52px; border-bottom: 1px solid var(--hairline); background: var(--bg); position: sticky; top: 0; z-index: 5; }
.topbar .wordmark { flex: none; }
/* phone: one scrolling row with the last item reachable; wider: wrap, never clip */
.nav { display: flex; gap: var(--s-5); overflow-x: auto; scrollbar-width: none; font-size: var(--text-sm); font-weight: 500; min-width: 0; flex: 1; padding-right: var(--s-4); }
.nav::-webkit-scrollbar { display: none; }
.nav a { text-decoration: none; color: var(--text-2); white-space: nowrap; padding: 17px 0 15px; flex: none; }
.nav a:hover { color: var(--text); }
.nav a[aria-current] { color: var(--text); box-shadow: inset 0 -2px 0 var(--text); }
.nav a:focus-visible { outline-offset: -4px; }
@media (min-width: 768px) { .nav { flex-wrap: wrap; overflow: visible; padding-right: 0; row-gap: 0; } }
.topbar .right { flex: none; margin-left: auto; display: flex; gap: var(--s-2); align-items: center; }
.topbar .right form { display: contents; }
@media (max-width: 480px) { .topbar { gap: var(--s-3); } .nav { gap: var(--s-4); } }

/* ---------- page and header rhythm ---------- */
.page { padding: var(--s-5) var(--gutter) var(--s-16); max-width: 1400px; margin: 0 auto; }
.page--narrow { max-width: 440px; }
.page-h { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-2) var(--s-4); margin-bottom: var(--s-5); }
.page-h .sub { color: var(--text-2); flex: 1 1 auto; min-width: 0; }
.page-h .sub .ico { vertical-align: -2px; }
.nowrap { white-space: nowrap; }
.page-h .actions { margin-left: auto; display: flex; gap: var(--s-2); align-items: center; }
/* phone: title and actions share the first row, the mono subline runs under both */
@media (max-width: 480px) {
  .page-h { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; row-gap: var(--s-2); margin-bottom: var(--s-4); }
  .page-h h2 { grid-column: 1; grid-row: 1; }
  .page-h .actions { grid-column: 2; grid-row: 1; margin-left: 0; }
  .page-h .sub { grid-column: 1 / -1; }
}
@media (min-width: 1024px) { .page { padding-top: var(--s-6); } .page-h { margin-bottom: var(--s-6); } }

/* flash: one line on a hairline, mono, never a toast */
.flash { padding: var(--s-3) 0; border-bottom: 1px solid var(--hairline); font-size: var(--text-sm); color: var(--text-2); }
.flash--alert { color: var(--danger); }

/* status: an upload or processing line sitting between two hairlines */
.status { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-3) 0; border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); margin-bottom: var(--s-4); }
.status .line { display: flex; align-items: center; gap: var(--s-2); color: var(--text-2); font-size: var(--text-sm); max-width: 70ch; }
.status .line.mono { color: var(--text); }
.status .bar { height: 2px; background: var(--hairline-strong); }
.status .bar i { display: block; height: 100%; background: var(--text); }

/* ---------- forms ---------- */
/* labels are mono labels; inputs are flat fields on a hairline */
.form { display: flex; flex-direction: column; gap: var(--s-5); }
.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field input, .field select, .field textarea {
  height: 40px; padding: 0 var(--s-3); width: 100%;
  background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--r-2);
}
@media (max-width: 480px) { .field input, .field select { height: 44px; } }
.field input::placeholder { color: var(--text-3); }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--text-2); outline: none; }
.field input.code { font-family: var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase; font-size: var(--text-md); }
.field .hint { font-size: var(--text-xs); color: var(--text-3); line-height: var(--lh-ui); }
.field .err { font-size: var(--text-xs); color: var(--danger); }
.field .check { display: flex; gap: var(--s-2); align-items: center; font-size: var(--text-sm); color: var(--text-2); }
.form .row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); }
.form-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); padding-top: var(--s-1); }
.form-foot .alt { margin-left: auto; font-size: var(--text-sm); color: var(--text-2); }
@media (max-width: 480px) { .form-foot .alt { flex-basis: 100%; margin-left: 0; } }
.form .flash { border-top: 1px solid var(--hairline); }
.page--narrow .page-h { margin-bottom: var(--s-6); }
.page--narrow .lead { color: var(--text-2); margin: calc(var(--s-2) * -1) 0 var(--s-5); max-width: 44ch; }
.danger-zone { margin-top: var(--s-10); padding-top: var(--s-4); border-top: 1px solid var(--hairline); }

/* empty states: a sentence and one action, no illustration */
.empty { padding: var(--s-8) 0; border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); display: flex; flex-direction: column; gap: var(--s-4); align-items: flex-start; }
.empty p { max-width: 48ch; color: var(--text-2); }

/* ---------- property show: map + camera list ---------- */
/* minmax(0, …) everywhere: grid items default to min-width:auto, and a
   nowrap hint or a wide table would otherwise push the page past the phone. */
.map-wrap { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s-6); }
.map-wrap > * { min-width: 0; }
@media (min-width: 1024px) { .map-wrap { grid-template-columns: minmax(0, 1fr) 380px; gap: var(--s-8); align-items: start; } }
.side .table-wrap { overflow-x: auto; }
.side .table td { white-space: nowrap; }
.side .table td.name { font-weight: 500; }
.side .table td.name .ico { vertical-align: -3px; margin-right: 2px; color: var(--text-2); }
.side .table td.coords { font-size: var(--text-2xs); }
@media (max-width: 480px) { .side .table td.brand { display: none; } }
@media (max-width: 480px) { .group-h .count { white-space: normal; text-align: right; } }
/* explicit heights, not aspect-ratio: with a min-height the ratio would
   derive the width from the height and push past a phone's viewport. */
.map { width: 100%; height: min(60vh, 420px); background: var(--ir); border-radius: var(--r-2); border: 1px solid var(--hairline-strong); position: relative; overflow: hidden; }
@media (min-width: 1024px) { .map { height: 560px; } }
.map .hidden-note { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; text-align: center; padding: var(--s-6); color: var(--text-2); }
.maplibregl-ctrl-attrib { font-family: var(--font-mono); font-size: 10px; }
.cam-pin { width: 14px; height: 14px; border-radius: 50%; background: var(--accent); border: 2px solid var(--bg); box-shadow: 0 0 0 1px var(--accent); cursor: pointer; }
.cam-pin--new { background: var(--text); box-shadow: 0 0 0 1px var(--text); }
.side { display: flex; flex-direction: column; gap: var(--s-6); }
.side section .form { margin-top: var(--s-4); }
.coords { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-2); }
.auth-hero { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-10) 0 var(--s-6); }
.auth-hero h1 { font-size: var(--text-3xl); }
.auth-hero p { color: var(--text-2); max-width: 44ch; }

/* find-your-ground panel over an unlocated property's map */
.locate { position: absolute; inset: 0; display: flex; align-items: flex-start; justify-content: center; padding: var(--s-4); pointer-events: none; }
.locate__card { pointer-events: auto; background: var(--bg); border: 1px solid var(--hairline-strong); border-radius: var(--r-2); padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); width: min(100%, 420px); }
.locate__search { display: flex; gap: var(--s-2); }
.locate__search input { flex: 1; min-width: 0; height: 40px; padding: 0 var(--s-3); background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--r-2); }
.locate__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); }
.locate .hint { font-size: var(--text-xs); color: var(--text-3); margin: 0; }

/* ---------- library ---------- */
.filters { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: center; margin-bottom: var(--s-5); }
.filters .sep { width: 1px; height: 20px; background: var(--hairline-strong); flex: none; margin: 0 var(--s-1); }
.filters__label { align-self: center; margin-right: var(--s-1); }
.filters .chip .ico { width: 12px; height: 12px; }
.filters select.chip { appearance: none; -webkit-appearance: none; padding-right: 24px; background-repeat: no-repeat; background-position: right 7px center; background-size: 10px 10px; max-width: 100%; }
:root[data-theme="dark"] .filters select.chip { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23a9aa9f' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M3.5 6L8 10.5 12.5 6'/%3E%3C/svg%3E"); }
:root[data-theme="paper"] .filters select.chip { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2355544c' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M3.5 6L8 10.5 12.5 6'/%3E%3C/svg%3E"); }
/* chips are the primary tap target on phone; 32px keeps them tappable without
   turning into buttons */
@media (max-width: 480px) { .filters .chip { height: 32px; } }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--s-5) var(--s-3); padding: var(--s-4) 0 var(--s-8); }
@media (min-width: 1024px) { .grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--s-6) var(--s-4); } }
.grid--small { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
@media (min-width: 1024px) { .grid--small { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); } }
.group-h + .grid { padding-top: var(--s-4); }

/* sighting tile: photo, who, strip. The camera's own burn-in stays visible
   at the bottom of the real photo, so nothing is overlaid there. Trail cam
   photos are 4:3 (2048x1536 keepers); a 16:9 frame would crop the burn-in off
   the bottom, while a 4:3 frame only side-crops the odd 16:9 camera. */
.tile { display: flex; flex-direction: column; gap: var(--s-2); min-width: 0; color: inherit; text-decoration: none; border-radius: var(--r-2); }
.tile .photo { aspect-ratio: 4 / 3; transition: box-shadow 80ms linear; }
.tile:hover .photo { box-shadow: 0 0 0 1px var(--text-3); }
.tile:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; }
.tile:focus-visible .photo { box-shadow: 0 0 0 1px var(--text); }
.tile .who { display: flex; align-items: baseline; gap: var(--s-2); font-size: var(--text-sm); font-weight: 500; min-width: 0; line-height: var(--lh-data); margin-top: 2px; }
.tile .who .name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tile .who .guess { flex: 0 0 auto; color: var(--text-3); font-family: var(--font-mono); font-size: var(--text-2xs); letter-spacing: var(--track-mono); text-transform: uppercase; white-space: nowrap; }
.tile .who .ico { color: var(--accent); }
.tile.is-person .photo { opacity: .6; }
.tile.is-person .who .name { color: var(--text-2); }
.tile .strip { margin-top: -2px; }
.tile .strip > span { line-height: 1.5; }
.tile .label { margin-top: 2px; }
.tile form { margin-top: 2px; }

.foot { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); padding: var(--s-4) 0; border-top: 1px solid var(--hairline); color: var(--text-2); font-size: var(--text-sm); }

/* ---------- sighting viewer ---------- */
.frames { display: grid; gap: var(--s-8); }
.frame { margin: 0; display: flex; flex-direction: column; gap: var(--s-3); }
/* the frame shrink-wraps the real photo, so detection boxes map 1:1 onto it;
   the photo itself is capped at 80vh so one frame never fills the screen */
/* width is explicit: .photo is an inline-size container, so a shrink-to-fit
   width (auto margins alone, fit-content) would collapse to the border */
.photo--full { aspect-ratio: auto; width: 100%; max-width: calc(80vh * var(--frame-ratio)); margin: 0 auto; border: 1px solid var(--hairline); --frame-ratio: 4 / 3; }
/* .photo.photo--full outranks tokens.css's .photo > img, which is absolute */
.photo.photo--full > img { position: static; display: block; width: 100%; height: auto; background: #000; }
.photo--full .box .tag { text-transform: capitalize; }
.frame .strip { font-size: var(--text-xs); }
.frame .strip .faint { color: var(--text-3); }

form.inline { display: inline; }
/* profile crops and review crops are square; .tile .photo above is 16:9 */
.photo--square, .tile .photo.photo--square { aspect-ratio: 1 / 1; }
.photo--square img { object-fit: cover; }

/* review queue */
.review-list { display: grid; gap: var(--s-4); }
.review-row { display: grid; gap: var(--s-4); padding: var(--s-4) 0; border-top: 1px solid var(--hairline); }
.review-row[data-current] { border-top-color: var(--text); }
@media (min-width: 768px) { .review-row { grid-template-columns: 1fr 1fr; align-items: center; } }
.review-pair { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--s-3); align-items: center; }
.review-arrow { color: var(--text-3); text-align: center; }
.review-body { display: flex; flex-direction: column; gap: var(--s-3); }
.review-body h3 { font-size: var(--text-lg); }

/* ---------- upload page ---------- */
.upload-form { gap: var(--s-4); margin-bottom: var(--s-5); }
.dropzone {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-2); text-align: center;
  padding: var(--s-8) var(--s-4); cursor: pointer;
  border: 1px dashed var(--hairline-strong); border-radius: var(--r-2); background: var(--surface);
}
.dropzone:hover, .dropzone.is-over { border-color: var(--text); border-style: solid; }
.dropzone p { margin: 0; }
.ico--big { width: 28px; height: 28px; }
.is-missing { outline: 2px solid var(--accent); outline-offset: 2px; }
.upload-run { display: flex; flex-direction: column; gap: var(--s-3); margin-bottom: var(--s-5); }
.upload-bar { height: 3px; background: var(--hairline-strong); }
.upload-bar > div { height: 100%; width: 0; background: var(--text); transition: width .15s linear; }
.upload-counts { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); font-size: var(--text-sm); color: var(--text-2); }
.upload-counts b { color: var(--text); font-weight: 600; }
.upload-counts .hit b { color: var(--accent); }
.upload-counts .warn b { color: var(--text-2); }
.upload-log { list-style: none; margin: 0; padding: 0; font-size: var(--text-sm); color: var(--text-2); display: flex; flex-direction: column; gap: 2px; }
.upload-log li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.upload-log li.warn { color: var(--accent); }
.upload-done .actions { display: flex; gap: var(--s-2); margin-top: var(--s-2); }

