/* Every colour is a token, so the whole interface can be restated for a light
   ground in one block rather than hunted through 300 lines. The names say what
   a value is FOR, not what it looks like: --field is the inset background of
   anything you type into or read a value from, and stays that whichever way up
   the palette is. Nothing below this block may contain a raw colour. */
:root{
  --bg:#0F1211; --panel:#171B18; --panel-2:#1E2320; --line:#313A34;
  --ink:#E9EFEA; --muted:#9BA89F; --dim:#6E7A72;
  /* The brand green, at a value that reads on a dark ground. "Good" is the
     accent: a second green would be indistinguishable from it. */
  --accent:#4FC98A; --accent-ink:#06170F;
  --good:#4FC98A; --warn:#f0b429; --bad:#ef5f5f;

  /* Inset surfaces: inputs, pills, bar troughs. Deliberately cooler and darker
     than --panel, so a field reads as recessed rather than raised. */
  --field:#0f1218; --field-active:#181c24;
  /* Tinted borders that carry a state without a fill. */
  --accent-line:#2f4a3d; --good-line:#1e4a35; --warn-line:#4a3c15;
  /* Tinted grounds for the three things that announce themselves. */
  --note-bg:#141821; --good-bg:#12241a; --bad-bg:#241a16;
  --warn-ink:#2a1f05;
  /* The map is a third-party surface: its own ground, and a ring that separates
     a pin from whatever tile is behind it. */
  --map-bg:#11141a; --pin-ring:#0f1115;
  --attrib-bg:rgba(15,17,21,.8); --attrib-ink:#6b7487; --attrib-link:#8fa3bf;

  --r:14px; --safe-b:env(safe-area-inset-bottom,0px);
  color-scheme: dark light;
}
/* ---------- light ----------
   Two blocks, not one: the media query follows the phone's Appearance setting,
   and the attribute selector lets someone override it in the app. They carry
   identical declarations, and a test asserts that byte for byte -- the failure
   mode otherwise is a value fixed in one and forgotten in the other, visible
   only to whichever users are on the branch nobody checked.
   The :not() guard is what makes "Dark" win over a phone set to light. */
@media (prefers-color-scheme: light){
  :root:not([data-theme="dark"]){
  /* Paper, not screen: an off-white with the faintest green in it, because a
     pure #fff panel on a pure #fff ground has no depth and glares outdoors.
     The accent darkens to #0E7449 -- the mint that glows on near-black washes
     out on white. Every pair here is contrast-checked in test/unit.mjs. */
  --bg:#F7F9F6; --panel:#FFFFFF; --panel-2:#F1F5F0; --line:#C4D2C6;
  --ink:#12201A; --muted:#5A6B60; --dim:#87958B;
  --accent:#0E7449; --accent-ink:#FFFFFF;
  --good:#0E7449; --warn:#8C5A00; --bad:#B3261E;
  /* Inset surfaces go DARKER than the panel here, where in dark mode they go
     darker than the panel too -- recessed either way up. */
  --field:#E6ECE4; --field-active:#DCE4D8;
  --accent-line:#A9D3BD; --good-line:#A9D3BD; --warn-line:#E0CB96;
  --note-bg:#F0F4F8; --good-bg:#E8F5EE; --bad-bg:#FDECEA;
  --warn-ink:#3A2A00;
  --map-bg:#E8EDE8; --pin-ring:#FFFFFF;
  --attrib-bg:rgba(255,255,255,.85); --attrib-ink:#5A6B60; --attrib-link:#0E7449;
  }
}
:root[data-theme="light"]{
  /* Paper, not screen: an off-white with the faintest green in it, because a
     pure #fff panel on a pure #fff ground has no depth and glares outdoors.
     The accent darkens to #0E7449 -- the mint that glows on near-black washes
     out on white. Every pair here is contrast-checked in test/unit.mjs. */
  --bg:#F7F9F6; --panel:#FFFFFF; --panel-2:#F1F5F0; --line:#C4D2C6;
  --ink:#12201A; --muted:#5A6B60; --dim:#87958B;
  --accent:#0E7449; --accent-ink:#FFFFFF;
  --good:#0E7449; --warn:#8C5A00; --bad:#B3261E;
  /* Inset surfaces go DARKER than the panel here, where in dark mode they go
     darker than the panel too -- recessed either way up. */
  --field:#E6ECE4; --field-active:#DCE4D8;
  --accent-line:#A9D3BD; --good-line:#A9D3BD; --warn-line:#E0CB96;
  --note-bg:#F0F4F8; --good-bg:#E8F5EE; --bad-bg:#FDECEA;
  --warn-ink:#3A2A00;
  --map-bg:#E8EDE8; --pin-ring:#FFFFFF;
  --attrib-bg:rgba(255,255,255,.85); --attrib-ink:#5A6B60; --attrib-link:#0E7449;
}

/* A `display` rule beats the browser's default [hidden] styling, which
   silently breaks anything hidden by attribute. Assert it once. */
[hidden]{display:none!important}
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{transition:none!important;animation:none!important}
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{height:100%;margin:0}
body{
  background:var(--bg); color:var(--ink);
  font:15px/1.45 -apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,sans-serif;
  overscroll-behavior:none;
}
button{font:inherit;color:inherit;cursor:pointer}

/* ---------- layout ---------- */
#app{display:flex;flex-direction:column;height:100dvh}
#map{flex:0 0 38dvh;min-height:200px;background:var(--map-bg);z-index:0}
#sheet{
  /* min-height:0 is load-bearing. A flex item defaults to min-height:auto,
     which refuses to shrink below its content, so overflow-y:auto never
     engages and everything past the fold becomes unreachable -- no inner
     scroll, and no page scroll either because html/body are locked to 100%.
     Chromium is forgiving about this; WebKit is not. */
  flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;
  background:var(--panel);border-radius:18px 18px 0 0;
  margin-top:-18px;position:relative;z-index:400;
  box-shadow:0 -8px 30px rgba(0,0,0,.45);
  padding:0 16px calc(28px + var(--safe-b));
}
.grabber{width:38px;height:4px;border-radius:99px;background:var(--line);margin:9px auto 4px}

/* The appearance control sits with the wordmark rather than in a settings
   screen there is no room for: it is one tap, and people look for it here. */
.headrow{display:flex;align-items:center;justify-content:space-between;gap:10px}
/* Chrome, not a button: no fill, no border, sized to the wordmark beside it.
   The tap target stays 44px per the HIG even though the glyph is 20. */
.icon-btn{
  flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  width:44px;height:44px;margin:-12px -10px -12px 0;
  background:none;border:0;color:var(--dim);border-radius:99px;
}
.icon-btn svg{width:20px;height:20px;display:block}
.icon-btn:active{color:var(--ink);background:var(--field)}
h1{display:flex;align-items:center;gap:9px;font-size:19px;margin:6px 0 2px;
   letter-spacing:-.2px}
.logo{display:inline-flex;width:19px;flex:0 0 auto;color:var(--accent)}
.logo svg{width:100%;height:auto;display:block}
.tagline{color:var(--muted);font-size:13px;margin:0 0 14px}
h2{font-size:12px;letter-spacing:.09em;text-transform:uppercase;color:var(--dim);
   margin:20px 0 9px;font-weight:600}
.hint{color:var(--dim);font-size:12px;margin:6px 0 0}

/* ---------- people ---------- */
.person{
  background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r);
  padding:10px;margin-bottom:8px;display:flex;gap:9px;align-items:center;
}
.dot{width:10px;height:10px;border-radius:99px;flex:0 0 auto}
.person.me{border-color:var(--accent-line)}
.you-tag{font-size:9.5px;letter-spacing:.09em;text-transform:uppercase;font-weight:700;
  color:var(--accent);flex:0 0 auto}
.flex-toggle{align-self:flex-start;background:none;border:1px dashed var(--line);
  border-radius:99px;padding:5px 10px;font-size:11.5px;color:var(--dim)}
.flex-toggle.on{border-style:solid;border-color:var(--accent);color:var(--accent)}
.person .fields{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
input[type=text]{
  width:100%;background:var(--field);border:1px solid var(--line);color:var(--ink);
  border-radius:9px;padding:9px 10px;font:inherit;outline:none;
}
input[type=text]:focus{border-color:var(--accent)}
/* --dim came out at 2.77:1 on the light field -- a placeholder nobody can see
   makes an empty input look like blank space, which is exactly how Sal lost
   the category search. --muted clears 4.5:1 in both themes. */
input::placeholder{color:var(--muted)}
.loc-row{display:flex;gap:6px}
.loc-row input{flex:1}
.mini{
  background:var(--field);border:1px solid var(--line);border-radius:9px;
  padding:0 11px;color:var(--muted);font-size:13px;white-space:nowrap;
}
.mini:active{background:var(--field-active)}
.mini.on{border-color:var(--accent);color:var(--accent)}
.rm{background:none;border:none;color:var(--dim);font-size:20px;padding:0 4px;line-height:1}
.status{font-size:12px;color:var(--dim);min-height:0}
.status.ok{color:var(--good)} .status.err{color:var(--bad)}

#addPerson{
  width:100%;background:none;border:1px dashed var(--line);color:var(--muted);
  border-radius:var(--r);padding:11px;font-size:14px;
}
#addPerson:disabled{opacity:.35}

/* ---------- chips ---------- */
.chips{display:flex;flex-wrap:wrap;gap:7px}
.chip{
  background:var(--panel-2);border:1px solid var(--line);border-radius:99px;
  padding:8px 13px;font-size:14px;color:var(--muted);
}
.chip.on{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);font-weight:600}

.filters{display:flex;flex-wrap:wrap;gap:7px;align-items:center}
select{
  background:var(--field);border:1px solid var(--line);color:var(--ink);
  border-radius:99px;padding:8px 11px;font:inherit;
}

/* ---------- actions ---------- */
#find{
  width:100%;margin-top:18px;background:var(--accent);color:var(--accent-ink);
  border:none;border-radius:var(--r);padding:15px;font-size:16px;font-weight:700;
}
#find:disabled{opacity:.4}
#share{
  width:100%;margin-top:8px;background:var(--panel-2);border:1px solid var(--line);
  color:var(--ink);border-radius:var(--r);padding:13px;font-size:15px;
}

/* ---------- results ---------- */
#log{font-size:12.5px;color:var(--muted);margin-top:12px;min-height:18px}
/* Which build am I looking at? Without this, "I don't see it" is unanswerable:
   a phone can serve a cached page for days, and everything below is invisible
   until someone knows they are three versions behind. */
#build{margin-top:22px;text-align:center;font-size:11px;color:var(--dim);
  letter-spacing:.04em}
.venue{
  background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r);
  padding:12px;margin-bottom:9px;
}
.venue.sel{border-color:var(--accent)}
.vhead{display:flex;gap:9px;align-items:baseline}
.rank{color:var(--dim);font-size:12px;font-variant-numeric:tabular-nums;flex:0 0 auto}
.vname{font-weight:650;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The town rides with the name and truncates with it, so a long name loses its
   own tail rather than pushing the town off the row. Lighter weight: it is
   context, not the thing you are reading. */
.vtown{font-weight:400;color:var(--muted)}
.vkind{font-size:12px;color:var(--dim);flex:0 0 auto}
.vmeta{display:flex;flex-wrap:wrap;gap:8px;margin-top:7px;font-size:12px;color:var(--muted)}
.pill{background:var(--field);border:1px solid var(--line);border-radius:99px;padding:2px 8px}
.pill.good{color:var(--good);border-color:var(--good-line)}
.pill.warn{color:var(--warn);border-color:var(--warn-line)}
.pill.bad{color:var(--bad)}

.fair{margin-top:9px;display:flex;flex-direction:column;gap:4px}
.fairrow{display:flex;align-items:center;gap:7px;font-size:12px}
.fairrow .nm{width:62px;flex:0 0 auto;color:var(--muted);overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.bar{flex:1;height:6px;background:var(--field);border-radius:99px;overflow:hidden}
/* Present in the group, absent from the maths. Dimmed rather than hidden, and
   with an empty trough, so nobody reads a missing person as a short journey. */
.fairrow.waiting{opacity:.55}
.fairrow.waiting .tm{font-style:italic;color:var(--dim)}
.bar > i{display:block;height:100%;border-radius:99px}
.fairrow .tm{width:50px;text-align:right;flex:0 0 auto;
  font-variant-numeric:tabular-nums;color:var(--muted)}

.vactions{display:flex;gap:7px;margin-top:10px;align-items:center}
.vote{
  background:var(--field);border:1px solid var(--line);border-radius:99px;
  padding:6px 12px;font-size:13px;color:var(--muted);
}
.vote.up.on{border-color:var(--good);color:var(--good)}
.vote.down.on{border-color:var(--bad);color:var(--bad)}
.tally{font-size:12px;color:var(--dim);margin-left:auto}
.maplink{font-size:13px;color:var(--accent);text-decoration:none}

.empty{color:var(--dim);font-size:13px;padding:10px 0}
.note{
  background:var(--note-bg);border:1px solid var(--line);border-left:3px solid var(--warn);
  border-radius:9px;padding:9px 11px;font-size:12.5px;color:var(--muted);margin-top:12px;
}
.spin{display:inline-block;width:12px;height:12px;border:2px solid var(--line);
  border-top-color:var(--accent);border-radius:99px;animation:s .7s linear infinite;
  vertical-align:-2px;margin-right:6px}
@keyframes s{to{transform:rotate(360deg)}}

/* leaflet dark-ish */
.leaflet-container{background:var(--map-bg)}
.leaflet-control-attribution{background:var(--attrib-bg)!important;color:var(--attrib-ink)!important}
.leaflet-control-attribution a{color:var(--attrib-link)!important}
.pin{border-radius:99px;border:2px solid var(--pin-ring);box-shadow:0 1px 4px rgba(0,0,0,.6)}

/* ---------- controls added since the first version, in the same idiom ---- */
input[type=search],input[type=time]{
  width:100%;background:var(--field);border:1px solid var(--line);color:var(--ink);
  border-radius:99px;padding:10px 13px;font:inherit;font-size:16px;outline:none;
  -webkit-appearance:none;
}
input[type=search]:focus,input[type=time]:focus{border-color:var(--accent)}
input[type=time]{width:auto;font-size:14px;padding:8px 11px}
#catSearch{margin-top:10px;margin-bottom:9px}

#catResults{
  background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r);
  padding:5px;margin-bottom:9px;max-height:236px;overflow-y:auto;
}
.cat-head{padding:8px 11px 4px;font-size:10.5px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--dim);font-weight:600}
.cat-hit{
  display:flex;align-items:center;justify-content:space-between;width:100%;
  background:none;border:none;border-radius:9px;padding:10px 11px;
  font-size:15px;text-align:left;min-height:44px;
}
.cat-hit:active{background:var(--field)}
.cat-hit.on{color:var(--accent)}
.cat-hit .tick{color:var(--accent);font-weight:700}
.no-cat{padding:10px 11px;font-size:13px;color:var(--dim);line-height:1.5}

.subchips{display:flex;flex-wrap:wrap;gap:6px;width:100%;margin-top:2px;
  padding-top:9px;border-top:1px solid var(--line)}
.chip.sub{font-size:13px;padding:6px 11px}
.chip.lucky{border-style:dashed}
.chip.lucky.on{background:var(--warn);border-color:var(--warn);
  border-style:solid;color:var(--warn-ink);font-weight:700}

/* ---------- live session ---------- */
#liveBar{margin-top:14px;padding:10px;background:var(--panel-2);
  border:1px solid var(--line);border-radius:var(--r)}
.live-row{display:flex;gap:7px;align-items:center;flex-wrap:wrap}
.live-row .mini{padding:7px 12px}
.mini.accent{border-color:var(--accent);color:var(--accent)}
#liveOn{display:flex;gap:7px;align-items:center;flex-wrap:wrap}
#liveCode{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;
  letter-spacing:.06em;color:var(--ink);background:var(--field);border:1px solid var(--line);
  border-radius:7px;padding:6px 9px;user-select:all;cursor:pointer}
#liveCode:active{border-color:var(--accent)}
#liveCode[data-copied]{color:var(--good);border-color:var(--good);
  font-family:inherit;letter-spacing:0}
#liveBar .hint{margin-top:8px}
#liveBar .hint.err{color:var(--bad)}
#shareLoc{width:100%;margin-top:10px;background:var(--accent);color:var(--accent-ink);
  border:none;border-radius:var(--r);padding:13px;font-size:15px;font-weight:700}

/* ---------- notices ---------- */
#geoHelp,#outlier{
  background:var(--note-bg);border:1px solid var(--line);border-left:3px solid var(--warn);
  border-radius:9px;padding:11px 12px;font-size:12.5px;color:var(--muted);line-height:1.5;
}
#geoHelp{margin-bottom:10px} #outlier{margin-top:16px}
#geoHelp b,#outlier b{color:var(--ink)}
#geoHelp p,#outlier p{margin:6px 0 0}
#geoHelp ol{margin:6px 0 0;padding-left:20px}
#geoHelp li{margin:3px 0}
#geoHelp .or{margin-top:9px;padding-top:9px;border-top:1px solid var(--line)}
.outlier-actions{display:flex;gap:7px;flex-wrap:wrap;margin-top:10px}

/* ---------- decisions ---------- */
.winner{
  background:var(--good-bg);border:1px solid var(--good-line);border-left:3px solid var(--good);
  border-radius:var(--r);padding:13px;margin-bottom:10px;font-size:14px;color:var(--muted);
}
.winner b{display:block;color:var(--ink);font-size:17px;margin-bottom:4px}
.winner p{margin:5px 0 8px}
.venue.won{border-color:var(--good)}
.venue.vetoed{opacity:.45}
.venue.vetoed .vname{text-decoration:line-through}
.vetoed-toggle{
  width:100%;background:none;border:1px dashed var(--line);color:var(--dim);
  border-radius:var(--r);padding:10px;font-size:13px;margin-top:2px;
}

/* The midpoint is a place, not a person: a ring, never a filled dot. */
.pin.mid{background:transparent!important;border:3px solid var(--ink)}


/* ---------- which maps app, asked at the moment of tapping ---------- */
.maplink{background:none;border:none;padding:10px 0;font:inherit;font-size:13px;
  color:var(--accent);font-weight:500}
#mapsSheet{position:fixed;inset:0;z-index:900;display:flex;align-items:flex-end}
.ms-backdrop{position:absolute;inset:0;background:rgba(0,0,0,.55)}
.ms-panel{
  position:relative;width:100%;background:var(--panel);border-radius:18px 18px 0 0;
  padding:18px 16px calc(18px + var(--safe-b));display:flex;flex-direction:column;gap:8px;
}
.ms-panel p{margin:0 0 6px;font-size:13px;color:var(--dim);text-align:center}
.ms-opt{
  display:block;text-align:center;padding:15px;border-radius:var(--r);
  background:var(--panel-2);border:1px solid var(--line);color:var(--ink);
  text-decoration:none;font-size:16px;
}
.ms-opt.last{border-color:var(--accent);color:var(--accent)}
.ms-cancel{
  margin-top:4px;padding:14px;border-radius:var(--r);background:none;
  border:1px solid var(--line);color:var(--muted);font-size:15px;
}

/* ---------- saved groups ---------- */
#groups{margin-top:10px}
.group-chip{display:inline-flex;align-items:stretch;border:1px solid var(--line);
  border-radius:99px;overflow:hidden;background:var(--panel-2)}
.group-chip .g-load{background:none;border:none;padding:9px 6px 9px 14px;
  font-size:13px;color:var(--ink);display:inline-flex;align-items:center;gap:7px;
  min-height:40px}
.group-chip .g-n{font-size:11px;color:var(--dim);
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.group-chip .g-del{background:none;border:none;padding:0 12px 0 6px;color:var(--dim);
  font-size:17px;line-height:1}
.group-chip .g-del:active{color:var(--bad)}
.chip.g-save{border-style:dashed;background:none}
.g-form{display:flex;gap:7px;width:100%;flex-wrap:wrap}
.g-form .g-name{flex:1;min-width:150px;background:var(--field);border:1px solid var(--accent);
  color:var(--ink);border-radius:99px;padding:10px 14px;font:inherit;font-size:16px;
  outline:none}

/* ---------- something is wrong, said out loud ---------- */
#trouble{margin:10px 0 0;display:flex;flex-direction:column;gap:7px}
#trouble .tr{background:var(--bad-bg);border:1px solid var(--warn-line);border-left:3px solid var(--warn);
  border-radius:9px;padding:10px 12px;font-size:12.5px;line-height:1.5;
  display:flex;flex-direction:column;gap:3px}
#trouble .tr b{color:var(--ink);font-weight:600}
#trouble .tr span{color:var(--muted)}

/* When everyone is in the same place, eight identical bars say nothing. */
.fair.one .nm{width:auto;color:var(--muted)}

/* ---------- shortlist ---------- */
.shortlist-head{display:flex;align-items:baseline;gap:9px;margin:4px 0 9px;flex-wrap:wrap}
.shortlist-head b{font-size:11px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--accent);font-weight:700}
.shortlist-head.rest b{color:var(--dim)}
.shortlist-head span{font-size:12px;color:var(--dim)}
.venue.liked{border-color:var(--accent-line)}
/* Someone wants it and someone doesn't. Shown plainly rather than hidden or
   struck through, so the group can settle it themselves. */
.venue.contested{border-color:var(--warn)}
