/* app.css — the product's shared UI kit, on the Pinnacle Grove design system:
   the tokens, header, cards, forms, buttons, badges, overlays, toast and icon
   masks every page loads before its own <style> block. Values come from the
   design system's tokens/ layer (colors, typography, spacing, radius,
   elevation, motion); a page adds only what is its own.

   Brand rules applied that tokens alone could not reach:
     - sentence case everywhere; uppercase only on the eyebrow (.dayhead)
     - no coloured left-border accents, no 2px+ borders
     - evergreen-tinted shadows, never neutral black
     - 4px controls / 10px cards / 16px surfaces / 2px badges / pill tags
     - focus is 1px evergreen + a 3px sage ring, never browser blue
     - mono carries badges, ids, counts and column headers                      */

/* Self-hosted so the CSP stays default-src 'self'. Manrope ships as a single
   variable face (Google serves one file for every weight); both are OFL. */
@font-face{
  font-family:"Manrope"; font-style:normal; font-weight:400 700; font-display:swap;
  src:url("/vendor/fonts/manrope.woff2") format("woff2");
}
@font-face{
  font-family:"IBM Plex Mono"; font-style:normal; font-weight:400; font-display:swap;
  src:url("/vendor/fonts/plexmono-400.woff2") format("woff2");
}
@font-face{
  font-family:"IBM Plex Mono"; font-style:normal; font-weight:500; font-display:swap;
  src:url("/vendor/fonts/plexmono-500.woff2") format("woff2");
}

:root{
  /* --- base palette (tokens/colors.css) --- */
  --pg-evergreen:#082D27; --pg-forest:#123D32; --pg-sage:#93A78F;
  --pg-stone:#DADBD8; --pg-warm-white:#F4F3EF; --pg-graphite:#202526;
  --pg-evergreen-900:#041a16; --pg-evergreen-700:#123D32; --pg-evergreen-600:#1d5145;
  --pg-evergreen-050:#ecf1ee; --pg-evergreen-100:#d3e0da;
  --pg-sage-200:#dee5dc;
  --pg-neutral-100:#ECEBE7; --pg-neutral-200:#DADBD8; --pg-neutral-300:#C2C3BF;
  /* neutral-500 sits at 5.0:1 on the warm white — AA for the 12–13px hints
     that use it (the design system's #74776F was 4.1:1) */
  --pg-neutral-400:#9A9C98; --pg-neutral-500:#66695F; --pg-neutral-600:#55584F;
  --pg-success:#2f6a5b; --pg-warning:#9A7B3C; --pg-danger:#8C4033; --pg-info:#41616E;

  /* --- the eleven app tokens, remapped --- */
  --brand:var(--pg-evergreen); --brand-dark:var(--pg-evergreen-900);
  --ink:var(--pg-graphite); --muted:var(--pg-neutral-500);
  --line:var(--pg-neutral-200); --bg:var(--pg-warm-white); --card:#ffffff;
  --danger:var(--pg-danger); --ok:var(--pg-success); --warn:var(--pg-warning);
  --accent:var(--pg-evergreen-050);

  /* --- supporting tokens: tints, hairlines, the map line ---
     Every colour a page needs lives here, so a dark theme is a retoken. */
  --placeholder:#6F726C;               /* 4.9:1 on white — often the only visible label */
  --line-soft:var(--pg-neutral-100);   /* hairlines inside a component */
  --warn-bg:#f3ecdd; --warn-ink:#6E5522;   /* 6.0:1 on --warn-bg */
  --ok-bg:#e6efe9; --danger-bg:#f6e9e6;
  --route:var(--pg-evergreen-600);     /* the map polyline */
  --on-brand:var(--pg-warm-white);     /* text on a --brand surface */

  /* --- type, radius, elevation, motion --- */
  --font-core:"Manrope","Avenir Next","Neue Haas Grotesk Display",-apple-system,"Segoe UI",sans-serif;
  --font-mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --radius-control:4px; --radius-chrome:6px; --radius-card:10px;
  --radius-surface:16px; --radius-badge:2px; --radius-pill:999px;
  --shadow-xs:0 1px 2px rgba(8,45,39,.06);
  --shadow-sm:0 1px 3px rgba(8,45,39,.08),0 1px 2px rgba(8,45,39,.04);
  --shadow-md:0 4px 16px -4px rgba(8,45,39,.12),0 1px 3px rgba(8,45,39,.05);
  --shadow-lg:0 18px 48px -18px rgba(8,45,39,.22),0 2px 6px rgba(8,45,39,.05);
  --shadow-focus:0 0 0 3px rgba(147,167,143,.45);
  --ease:cubic-bezier(.2,.6,.2,1); --dur-control:140ms; --dur-surface:220ms;
}

*{ box-sizing:border-box; }
[hidden]{ display:none !important; }
body{
  margin:0; font-family:var(--font-core); font-size:16px; line-height:1.6;
  background:var(--bg); color:var(--ink);
  -webkit-font-smoothing:antialiased;
}
a{ color:var(--brand); text-decoration-color:var(--pg-neutral-300); text-underline-offset:2px; }
a:hover{ color:var(--pg-evergreen-600); text-decoration-color:var(--pg-sage); }

/* focus: 1px evergreen + sage ring. Never the browser blue. */
:focus-visible{ outline:1px solid var(--brand); outline-offset:1px; box-shadow:var(--shadow-focus); }

/* ---------- app header: an evergreen band ---------- */
header.app{
  background:var(--brand); color:var(--pg-warm-white); padding:14px 24px;
  display:flex; align-items:center; gap:16px; flex-wrap:wrap;
}
header.app h1{ font-size:21px; margin:0; letter-spacing:-0.012em; font-weight:600; }
header.app .sub{ font-size:14px; color:rgba(244,243,239,.66); }
header.app .grow{ flex:1; }
header.app a{ color:var(--pg-warm-white); }

/* ---------- buttons: sentence case, 4px, evergreen ---------- */
button{
  font:inherit; font-size:14px; font-weight:500; border:1px solid transparent;
  border-radius:var(--radius-control); cursor:pointer; padding:8px 16px;
  background:var(--brand); color:var(--pg-warm-white);
  transition:background var(--dur-control) var(--ease), box-shadow var(--dur-control) var(--ease), transform var(--dur-control) var(--ease);
}
button:hover{ background:var(--pg-evergreen-700); box-shadow:var(--shadow-md); }
button:active{ background:var(--pg-evergreen-900); transform:translateY(1px); }
button.ghost{ background:transparent; border-color:rgba(255,255,255,.24); color:var(--pg-warm-white); }
button.ghost:hover{ background:rgba(255,255,255,.10); box-shadow:none; }
button.plain{ background:var(--card); color:var(--brand); border-color:var(--pg-neutral-300); }
button.plain:hover{ background:var(--accent); box-shadow:var(--shadow-sm); }
button.danger{ background:var(--danger); }
button.danger:hover{ background:#73342a; }
button.small{ padding:4px 10px; font-size:13px; }
button:disabled{ background:var(--pg-neutral-200); color:var(--pg-neutral-400); cursor:not-allowed; box-shadow:none; }

main.app{ max-width:1240px; margin:0 auto; padding:24px 24px 64px; }

/* ---------- chips ---------- */
.chips{ display:flex; gap:8px; margin:8px 0 20px; flex-wrap:wrap; min-width:0; max-width:100%; }
header.app nav.chips{ min-width:0; }
.chip{
  background:var(--card); border:1px solid var(--pg-neutral-300); border-radius:var(--radius-chrome);
  padding:6px 14px; font-size:14px; font-weight:500; cursor:pointer; color:var(--brand);
  transition:background var(--dur-control) var(--ease);
}
.chip:hover{ background:var(--accent); }
.chip.active{ background:var(--brand); color:var(--pg-warm-white); border-color:var(--brand); }
.chip .n{ font-family:var(--font-mono); font-size:12px; letter-spacing:.06em; opacity:.75; margin-left:6px; }

/* ---------- the eyebrow: the brand's signature gesture ---------- */
.dayhead{
  font-size:11px; font-weight:600; letter-spacing:.28em; text-transform:uppercase;
  color:var(--brand); margin:32px 0 12px; border-bottom:1px solid var(--line); padding-bottom:8px;
}

/* ---------- cards: 10px, hairline, evergreen shadow, no left accent ---------- */
.card{
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius-card);
  box-shadow:var(--shadow-sm); padding:20px 24px; margin-bottom:12px;
}
.empty{ color:var(--muted); padding:40px 0; text-align:center; }
/* a card this seat may read but not change (dispatch Settings for a
   dispatcher seat, dispatch/admin-lock.js): the values stay readable, the
   controls say they are off, and one line under the title says who can */
.card.locked input:disabled:not([type=checkbox]):not([type=radio]),
.card.locked select:disabled, .card.locked textarea:disabled{
  background:var(--pg-neutral-100); color:var(--ink); -webkit-text-fill-color:var(--ink); opacity:1;
}
.card.locked :disabled{ cursor:not-allowed; }
.card .hint.locknote{ color:var(--ink); font-weight:500; }

/* ---------- overlay + panel: 16px surface, scrim is evergreen ---------- */
.overlay{
  position:fixed; inset:0; background:rgba(8,45,39,.42); backdrop-filter:blur(3px); display:none;
  align-items:flex-start; justify-content:center; padding:5vh 16px; overflow:auto; z-index:40;
}
.overlay.open{ display:flex; }
.panel{
  background:var(--card); width:100%; max-width:640px; padding:24px;
  border:1px solid var(--line); border-radius:var(--radius-surface); box-shadow:var(--shadow-lg);
}
.panel h3{ margin:0 0 4px; font-size:21px; font-weight:600; letter-spacing:-0.012em; }

/* .hint is the explanatory line under a heading, a field or a form — the same
   inside a panel and out */
.hint, .panel .hint{ font-size:14px; color:var(--muted); margin:0 0 16px; line-height:1.6; }

/* ---------- forms ----------
   .field is a <label> wherever it wraps exactly one control, so the caption
   is the control's name and a tap on it lands in the box. It stays a <div>
   around buttons, radio groups and read-outs. */
.field{ display:block; margin-bottom:16px; }
.field .label{ display:block; font-size:13px; font-weight:500; color:var(--pg-neutral-600); margin-bottom:6px; }
.field input, .field select, .field textarea{
  width:100%; font:inherit; font-size:14px; padding:9px 12px;
  border:1px solid var(--pg-neutral-300); border-radius:var(--radius-control);
  background:var(--card); color:var(--ink);
  transition:border-color var(--dur-control) var(--ease), box-shadow var(--dur-control) var(--ease);
}
.field input::placeholder, .field textarea::placeholder{ color:var(--placeholder); }
.field input:focus, .field select:focus, .field textarea:focus{
  outline:none; border-color:var(--brand); box-shadow:var(--shadow-focus);
}
/* A radio or checkbox inside a .field keeps its own size, beside its words.
   The full-width box above is for text; stretched, the tick drew centred on
   a line of its own, above the words it belongs to. */
.field input[type="radio"], .field input[type="checkbox"]{
  width:auto; min-height:0; padding:0; margin:0 6px 0 0; vertical-align:middle;
}
.field [aria-invalid="true"]{ border-color:var(--danger); }
.field .fieldhint{ display:block; font-size:12px; color:var(--danger); margin-top:4px; }
/* A field whose "label" only exists to line a button up with the inputs
   beside it. On a phone the row is one column and the blank line is noise. */
.field.nolabel{ align-self:end; }
.row2{ display:grid; grid-template-columns:1fr 1fr; gap:16px; }
.row3{ display:grid; grid-template-columns:1fr 1fr 1fr; gap:16px; }
.formfoot{ display:flex; gap:12px; justify-content:flex-end; margin-top:20px; }
.formfoot .spacer{ margin-right:auto; }
.basis, .resolved{ font-size:13px; color:var(--muted); margin:-4px 0 12px; }
/* The other-unit line under a trailer dimension. Reserves its line height even
   when empty, so a row does not jump as a value is typed or cleared. */
.dimhint{
  display:block; min-height:1.4em; margin-top:4px;
  font-size:12px; color:var(--muted); font-family:var(--font-mono);
}
.resolved b{ color:var(--ink); font-family:var(--font-mono); font-size:12px; letter-spacing:.06em; }

/* ---------- tables: hairlines, mono column headers ---------- */
table.list{ width:100%; border-collapse:collapse; font-size:14px; }
table.list th{
  text-align:left; font-family:var(--font-mono); font-size:12px; font-weight:500;
  letter-spacing:.06em; color:var(--muted);
  border-bottom:1px solid var(--pg-neutral-300); padding:8px;
}
table.list td{ border-bottom:1px solid var(--pg-neutral-100); padding:10px 8px; vertical-align:top; }
table.list td.r, table.list th.r{ text-align:right; }

/* ---------- toast: fixed bottom-right at 24px ---------- */
.toast{
  position:fixed; bottom:24px; right:24px; left:auto; transform:none;
  background:var(--pg-graphite); color:var(--pg-warm-white); padding:12px 20px;
  border-radius:var(--radius-chrome); box-shadow:var(--shadow-lg);
  font-size:14px; display:none; z-index:60;
}
.toast.show{ display:block; }
/* an error reads as one; success stays the quiet graphite */
.toast.error{ background:var(--danger); }
.toast.ok{ background:var(--pg-success); }

/* ---------- the assistant: talk button, preview card, chips, log ----------
   Shared by the dispatch dock (dispatch/assistant.js) and the driver page's
   hands-free bar. Positioning is each page's own; these are the pieces. */
.ai-talk{ position:relative; }
[data-state="listening"] .ai-talk, .ai-talk[aria-pressed="true"]{
  background:var(--pg-evergreen-700); animation:ai-pulse 1.6s var(--ease) infinite;
}
.ai-talk.hearing{ animation-duration:.8s; }
@keyframes ai-pulse{
  0%{ box-shadow:0 0 0 0 rgba(147,167,143,.65); }
  100%{ box-shadow:0 0 0 14px rgba(147,167,143,0); }
}
.ai-card{
  margin-top:10px; padding:12px 14px; background:var(--card); border:1px solid var(--line);
  border-radius:var(--radius-card); box-shadow:var(--shadow-sm);
}
.ai-card .kicker{ font-family:var(--font-mono); font-size:11px; font-weight:500; letter-spacing:.12em; text-transform:uppercase; color:var(--brand); margin-bottom:4px; }
.ai-card .kicker .mut{ text-transform:none; letter-spacing:0; color:var(--muted); }
.ai-card .title{ font-weight:600; font-size:15px; line-height:1.4; letter-spacing:-0.005em; }
.ai-card .detail{ font-size:13px; color:var(--muted); margin-top:4px; line-height:1.5; white-space:pre-line; }
.ai-card .detail b{ color:var(--ink); font-weight:600; }
.ai-card .warn{ font-size:13px; color:var(--warn-ink); background:var(--warn-bg); border-radius:var(--radius-control); padding:6px 8px; margin-top:8px; line-height:1.45; }
.ai-card .note{ font-size:12.5px; color:var(--pg-info); margin-top:6px; }
.ai-card .acts{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-top:10px; }
.ai-card .acts .mut{ font-size:12px; color:var(--muted); }
.ai-card.danger{ border-color:var(--danger); }
.ai-card.danger .kicker{ color:var(--danger); }
.ai-card.answer .title{ font-weight:500; }
.ai-card .chips, .ai-chips{ display:flex; gap:6px; flex-wrap:wrap; margin-top:8px; }
.ai-chip{
  background:var(--card); color:var(--brand); border:1px solid var(--pg-neutral-300); border-radius:var(--radius-chrome);
  padding:5px 10px; font-size:12.5px; font-weight:500; min-height:0; text-align:left;
}
.ai-chip:hover, .ai-chip[aria-selected="true"]{ background:var(--accent); box-shadow:none; }
.ai-log-item{ display:flex; gap:8px; align-items:baseline; font-size:12.5px; padding:6px 0; border-bottom:1px solid var(--line-soft); line-height:1.45; }
.ai-log-item .t{ font-family:var(--font-mono); font-size:11px; color:var(--muted); flex:none; }
.ai-log-item .what{ flex:1; min-width:0; }
.ai-log-item .mut{ font-size:11.5px; color:var(--muted); }
.ai-log-item.undone .what{ text-decoration:line-through; color:var(--muted); }
.ai-log-item .small{ flex:none; min-height:28px; padding:2px 8px; }
.ai-status.error{ color:var(--danger); }
.ai-status.ok{ color:var(--ok); }

/* ---------- badges: mono, 2px, uppercase permitted ---------- */
.badge{
  font-family:var(--font-mono); font-size:11px; font-weight:500; letter-spacing:.06em;
  text-transform:uppercase; padding:2px 7px; border-radius:var(--radius-badge); display:inline-block;
}
.badge .tm{ text-transform:none; }   /* "7:05 AM", never "7:05 A.M." */
.badge.pending, .badge.quoted, .badge.enroute{ background:var(--warn-bg); color:var(--warn-ink); }
.badge.accepted{ background:var(--accent); color:var(--brand); }
.badge.completed, .badge.invoiced{ background:var(--pg-evergreen-100); color:var(--ok); }
.badge.declined, .badge.expired, .badge.cancelled{ background:var(--pg-neutral-100); color:var(--muted); }
.badge.arrived{ background:var(--pg-evergreen-100); color:var(--ok); }

/* ---------- map ---------- */
.maptools{ display:flex; gap:8px; align-items:center; margin:0 0 8px; }
.maptools .hintline{ font-size:13px; color:var(--muted); }
.maptools button.armed{ background:var(--brand); color:var(--pg-warm-white); border-color:var(--brand); }
.map{
  height:300px; min-height:140px; max-height:900px;
  border:1px solid var(--line); border-radius:var(--radius-card); margin-bottom:12px;
  position:relative; z-index:0; overflow:hidden;
}
.map-grip{
  position:absolute; right:0; bottom:0; width:18px; height:18px; z-index:1000;
  cursor:ns-resize; touch-action:none; opacity:.75;
  background:repeating-linear-gradient(135deg, transparent 0 3px, var(--muted) 3px 4px);
  clip-path:polygon(100% 0, 100% 100%, 0 100%);
}
.map-grip:hover{ opacity:1; }
.pin{
  display:flex; align-items:center; justify-content:center;
  width:24px; height:24px; border-radius:var(--radius-pill); color:#fff;
  font-weight:600; font-size:12px; border:2px solid #fff;
  box-shadow:0 1px 4px rgba(8,45,39,.45);
}
.pin.from{ background:var(--brand); }
.pin.to{ background:var(--ok); }
/* the second drop-off: a drop like B, told apart by colour as well as letter */
.pin.to2{ background:var(--warn); }
.pin.stop{ background:var(--pg-neutral-600); width:20px; height:20px; font-size:11px; }
/* the "Advanced — second drop-off" section on both booking forms */
details.drop2{ border:1px solid var(--line); border-radius:8px; padding:6px 10px; margin:6px 0; }
details.drop2 summary{ cursor:pointer; font-size:12.5px; color:var(--muted); }
details.drop2 summary b{ color:var(--ink); font-weight:600; }
details.drop2 .drop2body{ padding-top:8px; }
details.drop2 .maptools{ flex-wrap:wrap; }
/* a preload's overnight park spot: its own colour and letter, never mistaken
   for a drop — the machine sleeps there, it is not delivered there */
.pin.park{ background:var(--pg-info); }
details.preload .smsopt{ margin:0 0 8px; font-size:13px; }
details.preload .pl-note{ margin:0 0 8px; }
details.preload .pl-note.bad{ color:var(--danger); }
.badge.preload, .badge.parked{ background:var(--pg-neutral-100); color:var(--pg-info); }
/* site contacts and access notes (shared/site-details.js): one group per end
   of the move on a form, and the read-out on a card — who meets the truck,
   then how to get in. Notes keep the line breaks they were typed with. */
.hint.sitehint{ margin:0 0 8px; font-size:13px; }
.sitegrp + .sitegrp{ border-top:1px solid var(--line-soft); padding-top:8px; margin-top:2px; }
.sitegrp .sitehead{ font-size:13px; font-weight:600; color:var(--ink); margin:0 0 6px; }
.sitegrp .field{ margin-bottom:10px; }
.sitegrp textarea{ resize:vertical; }
.site{ font-size:13px; line-height:1.45; margin-top:4px; }
.site .sk{ color:var(--muted); font-weight:500; }
.site .sn{ white-space:pre-line; }
.site a[href^="tel:"]{ white-space:nowrap; }
.site.cab{ font-size:14px; margin-top:6px; }
.site.cab .sitecall{ margin:2px 0 4px; font-weight:600; }

.smsopt{ display:flex; gap:10px; align-items:flex-start; font-size:14px; color:var(--muted); margin:4px 0 16px; }
.smsopt input{ width:auto; margin-top:4px; min-height:0 !important; }

/* ---------- star rating: brand gold; owner.js writes the ★/☆ glyphs as text ---------- */
.stars{ display:inline-flex; gap:3px; align-items:center; }
.stars .lbl{ font-size:13px; color:var(--muted); margin-right:8px; }
.stars button{
  background:none; border:0; padding:0 1px; min-height:0; cursor:pointer;
  font-size:18px; line-height:1.2; color:var(--warn); box-shadow:none;
}
.stars button:hover{ background:none; box-shadow:none; color:var(--warn); }
.stars button.off{ color:var(--pg-neutral-300); }

.legalfoot{ margin:64px 0 32px; text-align:center; font-size:13px; color:var(--muted); }
.legalfoot a{ color:var(--muted); }

/* ---------- filter and sort, above a list (shared/list-tools.js) ----------
   One row: the search box takes the room, the count sits beside it, the
   sort and its direction on the right. On a phone the sort drops under the
   box. The count only appears while a filter is hiding rows. */
.listtools{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin:0 0 12px; }
.listtools input.q{
  flex:1 1 200px; min-width:160px; font:inherit; font-size:14px; padding:8px 12px;
  border:1px solid var(--pg-neutral-300); border-radius:var(--radius-control);
  background:var(--card); color:var(--ink);
}
.listtools input.q::placeholder{ color:var(--placeholder); }
.listtools input.q:focus{ outline:none; border-color:var(--brand); box-shadow:var(--shadow-focus); }
.listtools .count{ font-family:var(--font-mono); font-size:12px; letter-spacing:.04em; color:var(--muted); white-space:nowrap; }
.listtools .count:empty{ display:none; }
.listtools .sortlbl{ display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--muted); margin-left:auto; }
.listtools select.sort{
  font:inherit; font-size:14px; padding:7px 10px; border:1px solid var(--pg-neutral-300);
  border-radius:var(--radius-control); background:var(--card); color:var(--ink);
}
.listtools select.sort:focus{ outline:none; border-color:var(--brand); box-shadow:var(--shadow-focus); }
.listtools button.dir{ min-width:34px; padding:6px 8px; font-size:15px; line-height:1; }
.card > .listtools{ margin-top:4px; }
@media (max-width: 640px){
  .listtools .sortlbl{ margin-left:0; }
}

/* ---------- the operator's preview (shared/preview.js) ----------
   A band above the header saying this is the demo, in the warning tint so it
   cannot be mistaken for the product's own chrome. Sticky: a long board or a
   long list of requests must not scroll the fact away. */
.preview-bar{
  position:sticky; top:0; z-index:30;
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  padding:8px 24px; font-size:13.5px; line-height:1.45;
  background:var(--warn-bg); color:var(--warn-ink); border-bottom:1px solid var(--warn);
}
.preview-bar > b{ font-size:11px; font-weight:600; letter-spacing:.28em; text-transform:uppercase; }
.preview-bar .who{ min-width:0; }
.preview-bar .grow{ flex:1; }
.preview-bar button.plain{ color:var(--warn-ink); border-color:var(--warn); background:transparent; }
.preview-bar button.plain:hover{ background:rgba(154,123,60,.12); box-shadow:none; }
.preview-bar a.back{ color:var(--warn-ink); font-weight:500; white-space:nowrap; }
@media (max-width: 640px){
  .preview-bar{ padding:8px 16px; font-size:13px; }
  .preview-bar .who{ flex-basis:100%; }
}

/* ---------- auth gate: a card, not a 4px-ruled slab ---------- */
.gate{
  max-width:440px; margin:12vh auto; background:var(--card);
  border:1px solid var(--line); border-radius:var(--radius-surface);
  box-shadow:var(--shadow-lg); padding:32px;
}
.gate h1{ font-size:27px; font-weight:600; letter-spacing:-0.012em; margin:0 0 4px; }
.gate .wt{ font-size:11px; font-weight:600; color:var(--brand); letter-spacing:.28em; text-transform:uppercase; }
/* "Sign in with a password" under the emailed link on every door
   (shared/signin.js): folded away, so the link stays the first way in. An
   empty status line takes no room but stays in place to be announced. */
.pwsignin{ margin-top:16px; }
.pwsignin > summary{ cursor:pointer; font-size:14px; font-weight:500; color:var(--brand); }
.pwsignin > summary:hover{ color:var(--pg-evergreen-600); }
.pwsignin > form{ margin-top:12px; }
.pwsignin .pwmsg:empty{ margin:0; }

/* ---------- Lucide icons as masks, inheriting currentColor ---------- */
.ic{
  display:inline-block; width:16px; height:16px; vertical-align:-3px;
  background-color:currentColor; flex:none;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  -webkit-mask-size:contain; mask-size:contain;
}
.ic-camera{ -webkit-mask-image:url("/vendor/icons/camera.svg"); mask-image:url("/vendor/icons/camera.svg"); }
.ic-image{ -webkit-mask-image:url("/vendor/icons/image.svg"); mask-image:url("/vendor/icons/image.svg"); }
.ic-map-pin{ -webkit-mask-image:url("/vendor/icons/map-pin.svg"); mask-image:url("/vendor/icons/map-pin.svg"); }
.ic-pin{ -webkit-mask-image:url("/vendor/icons/pin.svg"); mask-image:url("/vendor/icons/pin.svg"); }
.ic-clock{ -webkit-mask-image:url("/vendor/icons/clock.svg"); mask-image:url("/vendor/icons/clock.svg"); }
.ic-arrow-up-right{ -webkit-mask-image:url("/vendor/icons/arrow-up-right.svg"); mask-image:url("/vendor/icons/arrow-up-right.svg"); }
.ic-undo-2{ -webkit-mask-image:url("/vendor/icons/undo-2.svg"); mask-image:url("/vendor/icons/undo-2.svg"); }
.ic-chevron-left{ -webkit-mask-image:url("/vendor/icons/chevron-left.svg"); mask-image:url("/vendor/icons/chevron-left.svg"); }
.ic-chevron-right{ -webkit-mask-image:url("/vendor/icons/chevron-right.svg"); mask-image:url("/vendor/icons/chevron-right.svg"); }
.ic-x{ -webkit-mask-image:url("/vendor/icons/x.svg"); mask-image:url("/vendor/icons/x.svg"); }
.ic-plus{ -webkit-mask-image:url("/vendor/icons/plus.svg"); mask-image:url("/vendor/icons/plus.svg"); }
.ic-mic{ -webkit-mask-image:url("/vendor/icons/mic.svg"); mask-image:url("/vendor/icons/mic.svg"); }
.ic-mic-off{ -webkit-mask-image:url("/vendor/icons/mic-off.svg"); mask-image:url("/vendor/icons/mic-off.svg"); }

/* ---------- mobile ---------- */
@media (max-width: 640px){
  main.app{ padding:16px 16px 90px; }
  header.app{ padding:12px 16px; gap:12px; }
  header.app h1{ font-size:18px; }
  header.app .sub{ display:none; }
  .row2, .row3{ grid-template-columns:1fr; gap:0; }
  .overlay{ padding:0; align-items:stretch; }
  .panel{ max-width:none; min-height:100%; padding:20px 16px 32px; border-radius:0; border:0; }
  .panel .formfoot{ position:sticky; bottom:0; background:var(--card); padding:12px 0 4px; }
  .map{ height:min(52vh, 340px); }
  table.list{ display:block; overflow-x:auto; }
  .gate{ margin:8vh auto; border-radius:var(--radius-card); }
  /* chips scroll INSIDE their strip; the page never scrolls sideways */
  .chips{ overflow-x:auto; flex-wrap:nowrap; padding-bottom:4px; -webkit-overflow-scrolling:touch; }
  header.app nav.chips{ flex:1 1 100%; order:9; margin:0; }
  .chip{ white-space:nowrap; flex:none; }
  .toast{ right:16px; left:16px; }
  .field.nolabel > .label{ display:none; }
}
@media (pointer: coarse){
  .map-grip{ width:26px; height:26px; }
  button{ min-height:44px; }
  button.small{ min-height:36px; }
  .field input, .field select, .field textarea{ min-height:44px; font-size:16px; }
  .chip{ padding:10px 16px; }
  .pin{ width:30px; height:30px; font-size:14px; }
  .stars button{ min-height:0; font-size:26px; padding:2px 4px; }
}
@media (prefers-reduced-motion: reduce){
  *{ transition-duration:0.01ms !important; animation-duration:0.01ms !important; }
}

/* ---------- place search dropdown (shared/geo-search.js) ----------
   Floats over whatever is below the input instead of pushing the form down,
   so a map or the next row does not jump while someone is still typing. */
.has-geopick{ position:relative; }
.geopick{
  list-style:none; margin:4px 0 0; padding:0; border:1px solid var(--line);
  border-radius:var(--radius-control); background:var(--card); box-shadow:var(--shadow-lg);
  max-height:260px; overflow-y:auto;
  position:absolute; left:0; right:0; z-index:30; min-width:260px;
}
.geopick[hidden]{ display:none; }
.geopick li + li{ border-top:1px solid var(--line); }
.geopick button{
  display:block; width:100%; text-align:left; background:none; border:0;
  padding:9px 12px; font:inherit; cursor:pointer; color:var(--ink); box-shadow:none;
  min-height:0; border-radius:0;
}
.geopick button:hover, .geopick li.active button{ background:var(--accent); box-shadow:none; }
.geopick .nm{ display:block; font-size:14px; line-height:1.3; }
.geopick .kd{ display:flex; gap:8px; align-items:baseline; font-size:12.5px; color:var(--muted); line-height:1.3; }
.geopick .kd em{ font-style:normal; font-family:var(--font-mono); font-size:11px; letter-spacing:.04em; text-transform:uppercase; }
.geopick .dist{ margin-left:auto; white-space:nowrap; font-family:var(--font-mono); font-size:11.5px; }

/* ---------- "More" on a card's actions row (shared/more-menu.js) ----------
   Wide screens: not there at all, the items sit in the row as before. At
   phone width the row keeps its primary actions and the rest fold behind
   one button, in a panel like the place-search dropdown. Anchored to the
   button's right edge, or its left when it is the row's only control, so
   the panel never runs off a phone screen. */
.more{ display:contents; }
.more > .more-toggle{ display:none; }
.more > .more-items{ display:contents; }
@media (max-width: 640px){
  .more{ display:inline-block; position:relative; }
  .more > .more-toggle{ display:inline-block; }
  .more > .more-items{
    display:none; position:absolute; top:calc(100% + 4px); right:0; z-index:30;
    min-width:190px; padding:6px; background:var(--card); border:1px solid var(--line);
    border-radius:var(--radius-control); box-shadow:var(--shadow-lg);
  }
  .more:first-child > .more-items{ right:auto; left:0; }
  .more.open > .more-items{ display:flex; flex-direction:column; gap:6px; }
  .more-items > button, .more-items > a{ width:100%; justify-content:flex-start; text-align:left; }
}

@media print{
  @page{ margin:16mm; }
  body > *{ display:none !important; }
  #printArea{ display:block !important; }
  #printArea tr{ page-break-inside:avoid; break-inside:avoid; }
  #printArea thead{ display:table-header-group; }
  #printArea .totals, #printArea .foot{ page-break-inside:avoid; break-inside:avoid; }
}
#printArea{ display:none; }
