/* Rampart — winter operations. Built for a cold morning and a bright screen. */
:root {
  --bg: #0d1117;
  --panel: #161b22;
  --panel-2: #1c2129;
  --line: #262d38;
  --line-soft: #1f2630;
  --ink: #e6edf3;
  --ink-2: #9aa7b4;
  --ink-3: #6b7785;
  --accent: #4d9dff;
  --accent-dim: #1f3b5c;
  --good: #3fb950;
  --warn: #d29922;
  --bad: #f85149;
  --purple: #a371f7;

  /* Surfaces and states that are not simply background/ink. */
  --input-bg: #0b0f15;
  --btn-hover-bg: #222833;
  --btn-hover-line: #39424f;
  --accent-hover: #6cb0ff;
  --on-accent: #04101f;        /* text ON an accent-filled button */
  --danger-line: #4a2222;
  --tab-on-ink: #cfe4ff;
  --scrim: rgba(1, 4, 9, .7);
  --shadow-drawer: -20px 0 60px rgba(0, 0, 0, .5);
  --shadow-toast: 0 10px 30px rgba(0, 0, 0, .45);

  /* Status pills. Seven tones, each a background / ink / border trio, so a
     new status picks a tone instead of inventing another three hex codes. */
  --tone-neutral-bg: #21262d;  --tone-neutral-ink: var(--ink-2); --tone-neutral-line: var(--line);
  --tone-blue-bg:    #1c2f45;  --tone-blue-ink:    #79c0ff;      --tone-blue-line:    #1f4a75;
  --tone-amber-bg:   #3a2d12;  --tone-amber-ink:   #e3b341;      --tone-amber-line:   #5c4611;
  --tone-green-bg:   #12351d;  --tone-green-ink:   #56d364;      --tone-green-line:   #1d5c2c;
  --tone-red-bg:     #3d1d1d;  --tone-red-ink:     #ff7b72;      --tone-red-line:     #6b2020;
  --tone-purple-bg:  #2c2447;  --tone-purple-ink:  #c4a2ff;      --tone-purple-line:  #45356e;
  --tone-cyan-bg:    #133041;  --tone-cyan-ink:    #56c8e0;      --tone-cyan-line:    #1c5670;

  --radius: 10px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
}

/**
 * Daylight. Billing works at a desk by a window; dispatch works at 5am with the
 * lights off. Only the palette changes — every rule below is written against
 * these tokens, so nothing else in this file knows which theme is showing.
 *
 * app.js resolves the system preference and always sets data-theme explicitly,
 * so this needs no prefers-color-scheme duplicate.
 */
:root[data-theme="light"] {
  --bg: #f4f6fa;
  --panel: #ffffff;
  --panel-2: #eef1f6;
  --line: #d7dee8;
  --line-soft: #e6ebf2;
  --ink: #16202b;
  --ink-2: #4d5b6b;
  --ink-3: #6f7d8c;
  --accent: #1b6fd4;
  --accent-dim: #cfe0f7;
  --good: #1a8a3f;
  --warn: #9a6b06;
  --bad: #c0392b;
  --purple: #6b46c1;

  --input-bg: #ffffff;
  --btn-hover-bg: #e5eaf2;
  --btn-hover-line: #b9c4d2;
  --accent-hover: #1559ab;
  --on-accent: #ffffff;
  --danger-line: #e5b6b0;
  --tab-on-ink: #10437e;
  --scrim: rgba(22, 32, 43, .38);
  --shadow-drawer: -20px 0 60px rgba(22, 32, 43, .18);
  --shadow-toast: 0 10px 30px rgba(22, 32, 43, .16);

  --tone-neutral-bg: #e9edf3;  --tone-neutral-ink: var(--ink-2); --tone-neutral-line: var(--line);
  --tone-blue-bg:    #dceafc;  --tone-blue-ink:    #10529e;      --tone-blue-line:    #b6d3f5;
  --tone-amber-bg:   #fbeecd;  --tone-amber-ink:   #7a5405;      --tone-amber-line:   #efd9a3;
  --tone-green-bg:   #d8f0de;  --tone-green-ink:   #10662f;      --tone-green-line:   #aeddba;
  --tone-red-bg:     #fbdedb;  --tone-red-ink:     #a32b1e;      --tone-red-line:     #f2bcb5;
  --tone-purple-bg:  #e9e0fb;  --tone-purple-ink:  #5b34a8;      --tone-purple-line:  #d3c2f2;
  --tone-cyan-bg:    #d5eef5;  --tone-cyan-ink:    #0d5b70;      --tone-cyan-line:    #a9d8e5;
}

/* The toggle itself: one quiet button in the top bar. */
button.btn.theme { padding: 6px 10px; line-height: 1; }

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--sans);
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--accent); text-decoration: none; }
h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
button, input, select, textarea { font-family: inherit; font-size: inherit; }

/* --- shell ------------------------------------------------------------- */
.topbar {
  display: flex; align-items: center; gap: 20px;
  padding: 0 20px; height: 64px;
  background: var(--panel); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 50;
}
.brand { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 16px; }

/**
 * Top-bar lockup: the shield and FORTRESS are cropped from the supplied
 * artwork; the service line is live text set where the FACILITIES SOLUTIONS
 * subline runs on the full logo. Baking it in was not an option — there is no
 * font rendering here — and text is the better answer anyway: crisp at any
 * zoom, and it recolours with the theme.
 *
 * The art is navy for a white page, so the dark theme uses reversed files with
 * lightness inverted and hue kept. Only one of each pair is ever displayed.
 */
.brand .shield { height: 42px; width: auto; display: block; flex: none; }
.brand .fortress { height: 19px; width: auto; display: block; }
.brand .stack { display: flex; flex-direction: column; gap: 3px; }

/* The subline is justified across the width of FORTRESS, as on the real logo:
   each letter is its own cell, so the row stretches instead of centring. */
.brand .subline {
  display: flex; justify-content: space-between;
  font-size: 9px; font-weight: 700; color: #004881;
  text-transform: uppercase; padding: 0 1px;
}
:root[data-theme="dark"] .brand .subline { color: #b8e0ff; }
/* The space cells sit either side of the dash, on top of the flex gap the
   justification already provides — keep them narrow or the dash floats. */
.brand .subline .sp { width: .12em; }

:root[data-theme="dark"] .brand .on-light { display: none; }
.brand .on-dark { display: none; }
:root[data-theme="dark"] .brand .on-dark { display: block; }

/* The same lockup, sized for the sign-in screen. At its desktop size the whole
   lockup is 359px wide, which fills a 375px phone edge to edge — so it scales
   with the viewport and only reaches full size on a wide one. */
.brand.hero { justify-content: center; gap: clamp(9px, 2.4vw, 14px); }
.brand.hero .shield { height: clamp(53px, 15.5vw, 84px); }
.brand.hero .fortress { height: clamp(24px, 7vw, 38px); }
.brand.hero .subline { font-size: clamp(12px, 3.5vw, 17px); padding: 0 2px; }
.brand.hero .stack { gap: clamp(4px, 1.1vw, 6px); }
.brand small { color: var(--ink-3); font-weight: 500; font-size: 11px; letter-spacing: .04em;
               text-transform: uppercase; }
nav.tabs { display: flex; gap: 2px; margin-left: 8px; flex: 1; overflow-x: auto; }
nav.tabs button {
  background: none; border: 0; color: var(--ink-2); padding: 8px 13px;
  border-radius: 7px; cursor: pointer; font-weight: 500; white-space: nowrap;
}
nav.tabs button:hover { background: var(--panel-2); color: var(--ink); }
nav.tabs button.on { background: var(--accent-dim); color: var(--tab-on-ink); }
.whoami { display: flex; align-items: center; gap: 10px; color: var(--ink-2); font-size: 13px; }
.whoami .role {
  font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
  background: var(--panel-2); border: 1px solid var(--line); padding: 2px 7px; border-radius: 20px;
}
main { padding: 20px; max-width: 1500px; margin: 0 auto; }

/* --- primitives -------------------------------------------------------- */
.panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.panel > header {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; border-bottom: 1px solid var(--line); background: var(--panel-2);
}
.panel > header h2 { font-size: 14px; }
.panel > header .sub { color: var(--ink-3); font-size: 12px; font-weight: 400; }
.panel .body { padding: 16px; }
.grid { display: grid; gap: 14px; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.spacer { flex: 1; }
.muted { color: var(--ink-3); }
.mono { font-family: var(--mono); font-size: 12px; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }

button.btn {
  background: var(--panel-2); color: var(--ink); border: 1px solid var(--line);
  padding: 7px 13px; border-radius: 7px; cursor: pointer; font-weight: 500;
}
button.btn:hover:not(:disabled) { border-color: var(--btn-hover-line); background: var(--btn-hover-bg); }
button.btn:disabled { opacity: .45; cursor: not-allowed; }
button.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
button.btn.primary:hover:not(:disabled) { background: var(--accent-hover); }
button.btn.danger { color: var(--bad); border-color: var(--danger-line); }
button.btn.sm { padding: 4px 9px; font-size: 12px; }

input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], select, textarea {
  background: var(--input-bg); border: 1px solid var(--line); color: var(--ink);
  padding: 8px 10px; border-radius: 7px; width: 100%;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent-dim); border-color: var(--accent); }
label.field { display: block; margin-bottom: 12px; }
label.field > span { display: block; font-size: 12px; color: var(--ink-2); margin-bottom: 5px; }
label.field > span em { color: var(--ink-3); font-style: normal; }

/* --- stats ------------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); gap: 12px; }
.stat {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 15px;
}
.stat .k { color: var(--ink-3); font-size: 11px; text-transform: uppercase;
           letter-spacing: .05em; margin-bottom: 6px; }
.stat .v { font-size: 25px; font-weight: 650; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.stat .n { color: var(--ink-3); font-size: 12px; margin-top: 3px; }
.stat.good .v { color: var(--good); }
.stat.warn .v { color: var(--warn); }
.stat.bad  .v { color: var(--bad); }
.stat.accent .v { color: var(--accent); }

/* --- tables ------------------------------------------------------------ */
table { width: 100%; border-collapse: collapse; }
th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-3); font-weight: 600; padding: 9px 12px;
  border-bottom: 1px solid var(--line); position: sticky; top: 0; background: var(--panel-2);
}
td { padding: 10px 12px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr.clickable { cursor: pointer; }
tbody tr.clickable:hover { background: var(--panel-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.table-wrap { overflow-x: auto; max-height: 70vh; overflow-y: auto; }

/* --- pills ------------------------------------------------------------- */
.pill {
  display: inline-block; padding: 2px 9px; border-radius: 20px; font-size: 11px;
  font-weight: 600; letter-spacing: .02em; border: 1px solid transparent; white-space: nowrap;
}
.pill.Draft,      .pill.pending   { background: var(--tone-neutral-bg); color: var(--tone-neutral-ink); border-color: var(--tone-neutral-line); }
.pill.Sent,       .pill.started   { background: var(--tone-blue-bg); color: var(--tone-blue-ink); border-color: var(--tone-blue-line); }
.pill.Negotiating { background: var(--tone-amber-bg); color: var(--tone-amber-ink); border-color: var(--tone-amber-line); }
.pill.Signed,     .pill.completed,
.pill.active,     .pill.paid      { background: var(--tone-green-bg); color: var(--tone-green-ink); border-color: var(--tone-green-line); }
.pill.Declined,   .pill.Cancelled,
.pill.skipped,    .pill.failed    { background: var(--tone-red-bg); color: var(--tone-red-ink); border-color: var(--tone-red-line); }
.pill.prospect,   .pill.queued    { background: var(--tone-purple-bg); color: var(--tone-purple-ink); border-color: var(--tone-purple-line); }
.pill.ready       { background: var(--tone-cyan-bg); color: var(--tone-cyan-ink); border-color: var(--tone-cyan-line); }
.pill.invoiced    { background: var(--tone-purple-bg); color: var(--tone-purple-ink); border-color: var(--tone-purple-line); }
.pill.seasonal    { background: var(--tone-green-bg); color: var(--tone-green-ink); border-color: var(--tone-green-line); }
.pill.per_plow    { background: var(--tone-blue-bg); color: var(--tone-blue-ink); border-color: var(--tone-blue-line); }
.pill.per_time    { background: var(--tone-amber-bg); color: var(--tone-amber-ink); border-color: var(--tone-amber-line); }
.pill.plow        { background: var(--tone-blue-bg); color: var(--tone-blue-ink); }
.pill.shovel      { background: var(--tone-amber-bg); color: var(--tone-amber-ink); }
.pill.both        { background: var(--tone-purple-bg); color: var(--tone-purple-ink); }
.pill.p1 { background: var(--tone-red-bg); color: var(--tone-red-ink); }
.pill.p2 { background: var(--tone-amber-bg); color: var(--tone-amber-ink); }

/* --- drawer / modal ---------------------------------------------------- */
.scrim {
  position: fixed; inset: 0; background: var(--scrim); z-index: 100;
  display: flex; justify-content: flex-end;
}
.drawer {
  width: min(760px, 100%); background: var(--bg); border-left: 1px solid var(--line);
  overflow-y: auto; box-shadow: var(--shadow-drawer);
}
.drawer > header {
  position: sticky; top: 0; background: var(--panel); border-bottom: 1px solid var(--line);
  padding: 15px 20px; display: flex; align-items: flex-start; gap: 14px; z-index: 2;
}
.drawer > header h2 { font-size: 17px; }
.drawer .content { padding: 20px; }
.modal-center { align-items: center; justify-content: center; }
.modal {
  background: var(--bg); border: 1px solid var(--line); border-radius: 12px;
  width: min(620px, 94vw); max-height: 88vh; overflow-y: auto;
}

.kv { display: grid; grid-template-columns: 170px 1fr; gap: 8px 16px; }
.kv dt { color: var(--ink-3); font-size: 12px; }
.kv dd { margin: 0; }

.section-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); margin: 22px 0 10px; padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.section-title:first-child { margin-top: 0; }

.note {
  border-left: 3px solid var(--accent); background: var(--panel-2);
  padding: 10px 14px; border-radius: 0 7px 7px 0; color: var(--ink-2); font-size: 13px;
}
.note.warn { border-color: var(--warn); }
.note.bad  { border-color: var(--bad); }
.note.good { border-color: var(--good); }

.toast-host { position: fixed; bottom: 20px; right: 20px; z-index: 200;
              display: flex; flex-direction: column; gap: 9px; }
.toast {
  background: var(--panel); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  padding: 11px 16px; border-radius: 8px; max-width: 420px;
  box-shadow: var(--shadow-toast); animation: rise .18s ease-out;
}
.toast.bad  { border-left-color: var(--bad); }
.toast.good { border-left-color: var(--good); }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } }

.empty { text-align: center; padding: 44px 20px; color: var(--ink-3); }
.empty .big { font-size: 30px; margin-bottom: 10px; opacity: .5; }

.bar { height: 6px; background: var(--line); border-radius: 3px; overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--good); }

/* --- login ------------------------------------------------------------- */
.login-wrap { min-height: 100vh; display: grid; place-items: center; padding: 20px; }
.login { width: 100%; max-width: 380px; }
.login .brand { font-size: 26px; justify-content: center; margin-bottom: 6px; }
.login .brand.hero { margin-bottom: 26px; }
.hint { font-size: 12px; color: var(--ink-3); text-align: center; margin-top: 16px; line-height: 1.7; }

@media (max-width: 720px) {
  .topbar { height: auto; flex-wrap: wrap; padding: 10px 14px; gap: 10px; }
  main { padding: 14px; }
  .kv { grid-template-columns: 1fr; gap: 2px 0; }
  .kv dd { margin-bottom: 10px; }
}

/* --- timesheets --------------------------------------------------------- */
input[type=datetime-local] {
  background: var(--input-bg); border: 1px solid var(--line); color: var(--ink);
  padding: 8px 10px; border-radius: 7px; width: 100%;
}
/* A day past twelve hours is the one cell in the week that must not be
   scanned past: Colorado starts owing overtime at that line. */
table.week td.hot { color: var(--warn); font-weight: 650; }
table.week tbody tr.clickable { cursor: pointer; }
table.week tbody tr.clickable:hover { background: var(--panel-2); }
.tiny { font-size: 11px; line-height: 1.35; }
.card {
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 13px 15px;
}
.content h3 { font-size: 14px; margin: 0 0 8px; font-weight: 650; }

/* --- enrollment QR ------------------------------------------------------ */
/* Always on white, whatever the app theme: a scanner needs the contrast the
   spec assumes, and an inverted code is a code that does not read. */
.qr-frame {
  background: #fff; padding: 14px; border-radius: 12px;
  width: 232px; margin: 22px auto 0;
}
.qr-frame svg { display: block; }
.or-line { display: flex; align-items: center; gap: 12px; margin: 22px 0 0; color: var(--ink-3); font-size: 12px; }
.or-line::before, .or-line::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* --- sortable table headings ------------------------------------------
   A heading that can be clicked should look like it can be clicked, and the
   one currently in use should be obvious without hunting for a small arrow. */
th.sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

th.sortable:hover {
  color: var(--ink);
  background: rgba(0, 0, 0, 0.03);
}

th.sortable:focus-visible {
  outline: 2px solid var(--accent, #1b2a4a);
  outline-offset: -2px;
}

.sort-arrow {
  display: inline-block;
  margin-left: 5px;
  font-size: 9px;
  vertical-align: 1px;
}

/* The column being sorted on, so the table says what it is doing. */
th.sortable[aria-sort="ascending"],
th.sortable[aria-sort="descending"] {
  color: var(--ink);
}

/* --- the customer table on a narrow screen -----------------------------
   Nine columns do not fit a laptop. Rather than leave people scrolling
   sideways to find out whether somebody has an email address, the columns
   that can be carried elsewhere are folded into the customer cell, and the
   ones that cannot are truncated with the full value on hover. */

/* Long values stop stretching the table and get an ellipsis instead. Every
   one of these carries a title, so nothing is lost — production route zones
   read "EAGLE VAIL, BEAVER CK, BACH GULCH" and would otherwise set the width
   of the whole column. */
.trunc {
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

td.col-zone, th.col-zone { max-width: 150px; }
td.col-customer { max-width: 260px; }

/* Shown only when the Account column itself is hidden. */
.account-inline {
  display: none;
  font-size: 11px;
  color: var(--ink-3);
  margin-right: 6px;
}

@media (max-width: 1200px) {
  th, td { padding-left: 9px; padding-right: 9px; }
}

/* Shown only when the Service column itself is hidden. */
.service-inline { display: none; margin-top: 4px; }

@media (max-width: 1100px) {
  /* The account number is six characters and needs a whole column; it reads
     just as well in front of the customer's name. */
  .col-account { display: none; }
  .account-inline { display: inline; }
}

@media (max-width: 1000px) {
  /* Service is one badge in a column of its own. Under the address it says the
     same thing and costs no width — and what a property buys is the sort of
     thing you read with the property, not in a column three across. */
  .col-service { display: none; }
  .service-inline { display: block; }
  th, td { padding-left: 7px; padding-right: 7px; }
  .trunc { max-width: 160px; }
  td.col-customer { max-width: 220px; }
}
