/* Avocado, faintly. The page sits on a pale yellow-green — the flesh, not the skin —
   with a deep olive accent. Every foreground/background pair below was checked
   against WCAG AA (4.5:1); the lowest is 5.2:1. Light and dark follow the OS setting.

   Note the dark accent takes DARK text, not white: a green light enough to read on a
   near-black panel is far too light to carry white type. */

*, *::before, *::after { box-sizing: border-box; }

:root {
  --bg:#f1f4e6; --panel:#fff; --ink:#16181d; --muted:#5f6857;
  --line:#e2e7d4; --accent:#456529; --accent-ink:#fff;
  --shadow:0 1px 2px rgba(38,48,22,.07), 0 8px 24px rgba(38,48,22,.06);
  --high-bg:#e7f6ec; --high-ink:#1a6b39; --high-line:#bfe4cd;
  --medium-bg:#fdf3e0; --medium-ink:#8a5a10; --medium-line:#f0dbb4;
  --low-bg:#eaeee0; --low-ink:#585f4b; --low-line:#dde2cf;
  --danger:#b3261e;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg:#11140e; --panel:#191d14; --ink:#e8eaed; --muted:#a0a89a;
    --line:#2a3021; --accent:#8cbb5e; --accent-ink:#11140e;
    --shadow:0 1px 2px rgba(0,0,0,.45);
    --high-bg:#12301f; --high-ink:#7fdca0; --high-line:#1f4a30;
    --medium-bg:#33260f; --medium-ink:#f0c273; --medium-line:#4d3a17;
    --low-bg:#20261a; --low-ink:#a0a89a; --low-line:#2f3626;
    --danger:#f2b8b5;
  }
}

html { -webkit-text-size-adjust: 100%; }
body {
  margin:0; background:var(--bg); color:var(--ink);
  font:15px/1.55 ui-sans-serif, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  /* Posting text is third-party and contains things like
     "Calgary, AB, CA, Kitchener, ON, CA, Vancouver, BC, CA, …" and unbroken URLs.
     Without this the page itself scrolls sideways on a phone, which is the one
     layout failure that makes an app feel broken. */
  overflow-wrap: anywhere;
}
.wrap { max-width:1040px; margin:0 auto; padding:28px 20px 80px; }
a { color:var(--accent); }

/* Flex and grid children default to min-width:auto, so a long unbreakable word
   pushes its container wider than the viewport instead of wrapping. */
.card, .head, .facts, .facts li, .actions, .searchbar { min-width: 0; }

/* ---------------------------------------------------------------- header */

header { display:flex; gap:16px; align-items:flex-start; justify-content:space-between; }
header h1 { margin:0; font-size:23px; letter-spacing:-.01em; }
.logo { font-size:.85em; margin-left:.1em; }
.sub { margin:4px 0 0; color:var(--muted); font-size:13px; }
.whoami { display:flex; gap:10px; align-items:center; color:var(--muted); font-size:13px;
          white-space:nowrap; }
button.link { background:none; border:0; padding:0; color:var(--accent); cursor:pointer;
              font:inherit; text-decoration:underline; }

/* ---------------------------------------------------------------- tabs */

.tabs { display:flex; gap:4px; margin:20px 0 0; border-bottom:1px solid var(--line);
        overflow-x:auto; scrollbar-width:none; -webkit-overflow-scrolling:touch; }
.tabs::-webkit-scrollbar { display:none; }
.tab { padding:9px 14px; border-radius:8px 8px 0 0; text-decoration:none;
       color:var(--muted); font-size:14px; white-space:nowrap;
       border:1px solid transparent; border-bottom:0; margin-bottom:-1px; }
.tab:hover { color:var(--ink); }
.tab.on { background:var(--panel); border-color:var(--line); color:var(--ink);
          font-weight:600; }
.tab .n, .group .n { display:inline-block; min-width:20px; padding:1px 6px; margin-left:4px;
                     border-radius:999px; background:var(--low-bg); color:var(--low-ink);
                     font-size:11.5px; font-weight:600; text-align:center; }
.tab.on .n { background:var(--accent); color:var(--accent-ink); }

/* ---------------------------------------------------------------- controls */

.searchbar { display:flex; gap:8px; margin:18px 0 12px; align-items:center; }
input[type=search] {
  flex:1 1 auto; min-width:0; font:inherit; font-size:14px; color:var(--ink);
  background:var(--panel); border:1px solid var(--line); border-radius:8px;
  padding:9px 12px;
}
input[type=search]:focus, input[type=text]:focus, input[type=password]:focus
  { outline:2px solid var(--accent); outline-offset:-1px; }
.searchbar button {
  font:inherit; font-size:14px; cursor:pointer; padding:9px 15px; border-radius:8px;
  border:1px solid var(--line); background:var(--panel); color:var(--ink);
}
.searchbar .clear { font-size:13px; color:var(--muted); }

/* The location filter is a <details> so twenty chips do not push the first job
   below the fold on a phone. Open by default on a wide screen, where there is room. */
.locations { margin:0 0 16px; }
.locations > summary {
  cursor:pointer; list-style:none; display:flex; gap:8px; align-items:baseline;
  font-size:13px; color:var(--muted); padding:7px 0;
}
.locations > summary::-webkit-details-marker { display:none; }
.locations > summary::after { content:"▾"; font-size:10px; opacity:.6; }
.locations[open] > summary::after { content:"▴"; }
.locations > summary b { color:var(--ink); font-weight:600; }
.filters { display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin-bottom:4px; }
.flabel { font-size:12px; text-transform:uppercase; letter-spacing:.06em;
          color:var(--muted); margin-right:4px; }
.chip {
  display:inline-flex; align-items:center; gap:5px; font-size:13px; text-decoration:none;
  background:var(--panel); color:var(--muted); border:1px solid var(--line);
  border-radius:999px; padding:5px 11px;
}
.chip:hover { color:var(--ink); border-color:var(--muted); }
.chip.on { background:var(--accent); border-color:var(--accent); color:var(--accent-ink);
           font-weight:600; }
.chip .n { font-size:11px; opacity:.75; }
.chip.clearall { border-style:dashed; }
.note { color:var(--muted); font-size:13px; margin:14px 0 18px; }

/* ---------------------------------------------------------------- cards */

.group { margin:26px 0 10px; font-size:13px; text-transform:uppercase;
         letter-spacing:.06em; color:var(--muted); font-weight:600; }
.card {
  background:var(--panel); border:1px solid var(--line); border-radius:12px;
  padding:15px 17px; margin-bottom:10px; box-shadow:var(--shadow);
}
.head { display:flex; gap:9px; align-items:baseline; flex-wrap:wrap; }
.card h2 { margin:0; font-size:16px; line-height:1.35; font-weight:600;
           flex:1 1 240px; min-width:0; }
.card h2 a { color:var(--ink); text-decoration:none; }
.card h2 a:hover { color:var(--accent); text-decoration:underline; }

.band, .tag {
  flex:none; font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  border-radius:5px; padding:3px 7px; border:1px solid;
}
/* Category says which tab it belongs to; confidence says how sure the classifier is.
   Two different questions, so they read as two different pills. */
.band.cat-ip      { background:var(--high-bg);   color:var(--high-ink);   border-color:var(--high-line); }
.band.cat-general { background:var(--medium-bg); color:var(--medium-ink); border-color:var(--medium-line); }
.band.conf-high, .band.conf-medium, .band.conf-low {
  background:transparent; color:var(--muted); border-color:var(--line); font-weight:600;
}
.band.conf-low { border-style:dashed; }
.tag { background:transparent; color:var(--accent); border-color:var(--accent); }
.tag.rescued { border-style:dashed; }
.tag.new { background:var(--accent); border-color:var(--accent); color:var(--accent-ink); }
.tag.status-rejected { color:var(--muted); border-color:var(--line); }

.facts { margin:8px 0 0; padding:0; list-style:none; display:flex; flex-wrap:wrap;
         gap:4px 14px; color:var(--ink); font-size:13px; }
.facts .dim { color:var(--muted); }
.facts .exp { font-variant-numeric:tabular-nums; border-bottom:1px dotted var(--line);
              cursor:help; }
.chips-inline { margin:7px 0 0; padding:0; list-style:none; display:flex;
                flex-wrap:wrap; gap:5px; }
.chips-inline li { font-size:11px; color:var(--muted); border:1px solid var(--line);
                   border-radius:4px; padding:1px 6px; }
.reason { margin:10px 0 0; font-size:13.5px; color:var(--muted);
          border-left:2px solid var(--line); padding-left:10px; }
.desc { margin:10px 0 0; font-size:13.5px; }
.desc summary { cursor:pointer; color:var(--accent); font-size:13px; }
.desc p { color:var(--muted); margin:8px 0 0; white-space:pre-wrap; }

/* ---------------------------------------------------------------- card actions */

.actions { display:flex; flex-wrap:wrap; gap:6px; align-items:center;
           margin:13px 0 0; padding-top:12px; border-top:1px solid var(--line); }
.actions form { display:flex; gap:6px; margin:0; }
.actions .spacer { flex:1 1 auto; }
.act {
  font:inherit; font-size:12.5px; cursor:pointer; padding:5px 11px;
  border-radius:7px; border:1px solid var(--line);
  background:transparent; color:var(--muted);
}
/* Only the status buttons take their label from the stored value, so only they
   need capitalising — otherwise "Return to low pile" comes out title-cased. */
.statuses .act { text-transform:capitalize; }
.act:hover { color:var(--ink); border-color:var(--muted); }
.act.on { background:var(--accent); border-color:var(--accent);
          color:var(--accent-ink); font-weight:600; }
.statuses { flex-wrap:wrap; }

/* htmx sets this while a request is in flight */
.card.htmx-request { opacity:.5; transition:opacity .1s; }

.empty { text-align:center; color:var(--muted); padding:56px 20px; }

footer { margin-top:36px; padding-top:14px; border-top:1px solid var(--line);
         color:var(--muted); font-size:12.5px; }

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

.login { max-width:340px; margin:12vh auto 0; }
.login h1 { margin:0; font-size:24px; }
.login form { margin-top:22px; display:flex; flex-direction:column; gap:6px; }
.login label { font-size:12.5px; color:var(--muted); margin-top:8px; }
.login input {
  font:inherit; font-size:15px; color:var(--ink); background:var(--panel);
  border:1px solid var(--line); border-radius:8px; padding:10px 12px;
}
.login button {
  margin-top:18px; font:inherit; font-size:15px; font-weight:600; cursor:pointer;
  padding:11px; border-radius:8px; border:0;
  background:var(--accent); color:var(--accent-ink);
}
.error { margin-top:16px; padding:10px 12px; border-radius:8px; font-size:13.5px;
         color:var(--danger); border:1px solid var(--danger); background:transparent; }

/* ---------------------------------------------------------------- small screens */

/* ---------------------------------------------------------------- phone

   The primary device. Five tabs, twenty location chips and a six-button action bar
   all have to fit 390px without the page scrolling sideways. */

@media (max-width:640px) {
  .wrap { padding:16px 12px 48px; }

  header { flex-direction:row; align-items:flex-start; gap:10px; }
  header h1 { font-size:19px; }
  .sub { display:none; }             /* she knows what the app is */
  .whoami { font-size:12px; }

  /* Tabs scroll horizontally rather than wrapping to two rows: keeping them on one
     line preserves the sense of a single row of sections. Tighter padding fits four
     of the five at once, so the fifth is a short nudge away rather than hidden. */
  .tabs { margin:14px -12px 0; padding:0 12px; gap:2px; }
  .tab { padding:8px 10px; font-size:13.5px; }
  .tab .n { min-width:18px; padding:1px 5px; font-size:11px; }

  .searchbar { margin:12px 0 10px; }
  .searchbar button { padding:9px 12px; }

  .locations { margin-bottom:12px; }
  .card { padding:13px 14px; border-radius:10px; }
  .card h2 { font-size:15.5px; flex-basis:100%; }
  .facts { gap:2px 10px; font-size:12.5px; }
  .reason { font-size:13px; }

  /* Actions go full width and split: statuses on one line, hide/rescue on the next,
     so the destructive-ish controls are never a mis-tap away from a status. */
  .actions { gap:8px; }
  .actions form { flex-wrap:wrap; }
  .statuses { flex:1 1 100%; }
  /* min-width:0 lets a button shrink below its label rather than widening the
     card; without it a 320px phone scrolls sideways. */
  .statuses .act { flex:1 1 0; min-width:0; text-align:center; padding:7px 4px; }
  .act { min-width:0; }
  .actions .spacer { display:none; }
  .act { padding:7px 10px; }
}
