/* ── Landscape shell and component set ─────────────────────────────────────
   The ~12 shared components the redesign runs on, plus the application shell
   (sidebar, top bar, command palette, drawer). Built in-house on the tokens in
   tokens.css rather than on MudBlazor or Radzen, whose Material look would
   fight this direction.

   Rules here own layout and chrome only. Nothing in this file hard-codes a
   colour, radius, font or spacing step — those all come from tokens.css.
   ────────────────────────────────────────────────────────────────────────── */

/* Form controls do not inherit the page font by default — without this, every
   button and input in the app silently falls back to the browser's Arial. */
button, input, select, textarea { font-family: inherit; }

/* ══ Shell ══════════════════════════════════════════════════════════════ */

.app-shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  min-height: 100vh;
}
/* Below the breakpoint the sidebar stacks above the content rather than
   disappearing, so every destination stays reachable on a phone without a
   second navigation being written for small screens. */
@media (max-width: 860px) {
  .app-shell { grid-template-columns: 1fr; }
}

.app-sidebar {
  background: var(--forest);
  color: var(--forest-ink);
  display: flex;
  flex-direction: column;
  padding: 0 0 var(--sp-4);
  border-right: 1px solid var(--forest-line);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
/* Stacked above the content on a phone, so it has to be compact: groups flow
   side by side and items sit inline. Full height here would push the actual page
   most of a screen down. */
@media (max-width: 860px) {
  .app-sidebar { position: static; height: auto; overflow: visible; }
  .nav-groups { display: flex; flex-wrap: wrap; gap: 0 var(--sp-2); }
  .navgroup { padding: var(--sp-1) var(--sp-3); }
  .navgroup-label { padding-bottom: 2px; }
  .navgroup :is(a, .navitem) { display: inline-flex; width: auto; margin-right: var(--sp-1); }
  .navitem .dot { display: none; }
  .navitem .count { margin-left: var(--sp-1); }
}

.brand {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-4) var(--sp-4);
  border-bottom: 1px solid var(--forest-line);
  margin-bottom: var(--sp-2);
  color: var(--forest-ink); text-decoration: none;
}
.brand:hover { color: var(--forest-ink); }
.brand-mark {
  width: 30px; height: 30px; border-radius: var(--r-sm); flex: 0 0 auto;
  background: #fff; overflow: hidden; display: grid; place-items: center;
}
.brand-mark img { width: 100%; height: 100%; object-fit: contain; display: block; }
.brand-name { font-weight: 600; font-size: var(--fs-base); letter-spacing: -.01em; }
.brand-sub  { font-size: var(--fs-xs); color: var(--forest-ink-2); margin-top: -2px; }

.navgroup { padding: var(--sp-2) var(--sp-3) 0; }
.navgroup-label {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .11em;
  color: var(--forest-ink-2); padding: 0 var(--sp-2) var(--sp-1); font-weight: 600;
}
.navitem {
  display: flex; align-items: center; gap: var(--sp-2); width: 100%;
  padding: var(--sp-1) var(--sp-2); border-radius: var(--r-sm);
  color: var(--forest-ink); font-size: var(--fs-base); text-decoration: none;
  transition: background .14s ease;
}
.navitem:hover { background: rgba(255,255,255,.06); color: var(--forest-ink); }
/* NavLink stamps .active on the matching route. */
.navitem.active { background: var(--accent); color: #fff; font-weight: 500; }
.navitem .dot {
  width: 5px; height: 5px; border-radius: 50%; background: currentColor;
  opacity: .45; flex: 0 0 auto;
}
.navitem.active .dot { opacity: 1; }
.navitem .count {
  margin-left: auto; font-size: var(--fs-xs); font-variant-numeric: tabular-nums;
  color: var(--forest-ink-2);
}
.navitem.active .count { color: rgba(255,255,255,.82); }
/* Attention count (e.g. estimates awaiting you) — reads as a badge, not a total. */
.navitem .count.attn {
  background: var(--accent-2); color: #06170F; font-weight: 700;
  border-radius: var(--r-pill); padding: 0 var(--sp-1); min-width: 17px; text-align: center;
}
.navitem.active .count.attn { background: #fff; color: var(--accent); }

.sidebar-foot {
  margin-top: auto; padding: var(--sp-3) var(--sp-4) 0;
  border-top: 1px solid var(--forest-line);
}
.who { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); }
.who .who-name { color: var(--forest-ink); text-decoration: none; }
.who .who-name:hover { text-decoration: underline; }
.who .role {
  font-size: var(--fs-micro); color: var(--forest-ink-2);
  text-transform: uppercase; letter-spacing: .09em;
}
.sidebar-foot .signout {
  display: inline-block; margin-top: var(--sp-2);
  font-size: var(--fs-xs); color: var(--forest-ink-2); text-decoration: none;
}
.sidebar-foot .signout:hover { color: var(--forest-ink); }

.app-main { display: flex; flex-direction: column; min-width: 0; }

.app-topbar {
  display: flex; align-items: center; gap: var(--sp-2) var(--sp-4); flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-5);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  position: sticky; top: 0; z-index: 20;
}
.crumbs {
  display: flex; align-items: center; gap: var(--sp-1);
  font-size: 13px; color: var(--ink-3); min-width: 0;
}
.crumbs b { color: var(--ink); font-weight: 600; }

/* Command palette trigger. Deliberately looks like a search field, because
   that is what people reach for before they learn the shortcut. */
.kbtn {
  margin-left: auto; display: flex; align-items: center; gap: var(--sp-2);
  background: var(--surface-2); border: 1px solid var(--line);
  padding: 6px var(--sp-2) 6px var(--sp-3); border-radius: var(--r-sm);
  color: var(--ink-3); cursor: pointer; font-size: var(--fs-sm);
  flex: 1 1 180px; min-width: 0; max-width: 340px;
  transition: border-color .14s ease;
}
.kbtn > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kbtn:hover { border-color: var(--accent-line); }
.kbd {
  font-family: var(--mono); font-size: 10.5px; padding: 2px 5px; border-radius: 4px;
  background: var(--surface); border: 1px solid var(--line); color: var(--ink-3);
  margin-left: auto;
}
.icon-btn {
  width: 31px; height: 31px; border-radius: var(--r-sm); border: 1px solid var(--line);
  background: var(--surface); cursor: pointer; display: grid; place-items: center;
  color: var(--ink-2); flex: 0 0 auto; text-decoration: none;
}
.icon-btn:hover { background: var(--surface-2); color: var(--ink); }

.app-content { padding: var(--sp-5); flex: 1; min-height: 0; }

/* ══ Page header ════════════════════════════════════════════════════════ */

.page-head {
  display: flex; align-items: flex-end; gap: var(--sp-4);
  flex-wrap: wrap; margin-bottom: var(--sp-4);
}
.page-head h1 { font-size: var(--fs-xl); letter-spacing: -.02em; margin: 0; font-weight: 600; text-wrap: balance; }
.page-sub { color: var(--ink-3); font-size: 13px; margin: 2px 0 0; }
.head-actions { margin-left: auto; display: flex; gap: var(--sp-2); flex-wrap: wrap; }

/* ══ Button ═════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px var(--sp-4); border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  font-size: 13px; font-weight: 500; text-decoration: none;
  transition: background .14s ease, border-color .14s ease;
}
.btn:hover { background: var(--surface-2); color: var(--ink); }
.btn:disabled { opacity: .5; cursor: default; }
.btn.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.btn-primary:hover { background: var(--accent-2); border-color: var(--accent-2); color: #fff; }
.btn.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn.btn-danger:hover { filter: brightness(1.08); color: #fff; }
.btn.btn-sm { padding: 5px var(--sp-3); font-size: var(--fs-sm); }
.btn.btn-lg { padding: 10px var(--sp-5); font-size: var(--fs-base); }

/* ══ Chip / segmented filter ════════════════════════════════════════════ */

.chips { display: flex; gap: var(--sp-1); flex-wrap: wrap; margin-bottom: var(--sp-4); }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px var(--sp-3); border-radius: var(--r-pill); border: 1px solid var(--line);
  background: var(--surface); color: var(--ink-2); font-size: var(--fs-sm);
  cursor: pointer; text-decoration: none;
}
/* An unselected chip's dot stays coloured — it is the legend for the filter,
   so greying it out would hide the very thing the chip is naming. */
.chip[aria-pressed="false"] { color: var(--ink-3); }
.chip:hover { border-color: var(--accent-line); color: var(--ink); }
.chip[aria-pressed="true"], .chip.on {
  background: var(--accent-soft); border-color: var(--accent-line);
  color: var(--accent); font-weight: 500;
}

/* ══ Pill / badge ═══════════════════════════════════════════════════════ */

.pill {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .03em;
  padding: 2px 7px; border-radius: var(--r-pill); border: 1px solid; white-space: nowrap;
}
.pill-accent { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.pill-warn   { background: var(--warn-soft);   border-color: var(--warn-line);   color: var(--warn); }
.pill-info   { background: var(--info-soft);   border-color: var(--info-line);   color: var(--info); }
.pill-danger { background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger); }
.pill-plain  { background: var(--surface-2);   border-color: var(--line);        color: var(--ink-3); }

/* ══ Panel / table ══════════════════════════════════════════════════════ */

.panel {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden;
}
.panel + .panel { margin-top: var(--sp-3); }
.panel-head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line-soft); flex-wrap: wrap;
}
.panel-title { font-size: var(--fs-base); font-weight: 600; }
.panel-note  { font-size: var(--fs-sm); color: var(--ink-3); }
.panel-body  { padding: var(--sp-4); }

.tablewrap { overflow-x: auto; }
.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th {
  text-align: left; font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-3); font-weight: 700; padding: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--line-soft); white-space: nowrap; background: var(--surface-2);
}
.tbl td { padding: var(--sp-2) var(--sp-4); border-bottom: 1px solid var(--line-soft); vertical-align: middle; }
.tbl tbody tr:last-child td { border-bottom: 0; }
.tbl tbody tr:hover { background: var(--surface-2); }
.tbl td.num, .tbl th.num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl .sub { display: block; font-size: var(--fs-xs); color: var(--ink-3); margin-top: 1px; font-weight: 400; }

/* ══ Stat tile ══════════════════════════════════════════════════════════ */

.stat-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(155px, 1fr));
  gap: var(--sp-3); margin-bottom: var(--sp-4);
}
.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: var(--sp-3) var(--sp-4); }
.stat-label { font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-3); font-weight: 700; }
/* The one place the serif earns its keep: a figure you are meant to read, not scan past. */
.stat-val {
  font-family: var(--serif); font-size: var(--fs-figure); line-height: 1.1;
  margin-top: 4px; letter-spacing: -.01em; font-variant-numeric: tabular-nums;
}
.stat-val.sm { font-size: 27px; }
.stat-foot { font-size: var(--fs-xs); color: var(--ink-3); margin-top: 2px; }
.stat-accent .stat-val { color: var(--accent); }

/* ══ Board column ═══════════════════════════════════════════════════════ */

.board { display: flex; gap: var(--sp-3); overflow-x: auto; padding-bottom: var(--sp-2); align-items: flex-start; }
.col {
  flex: 0 0 270px; background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: var(--r); padding: var(--sp-2);
}
.col-head { display: flex; align-items: center; gap: var(--sp-2); padding: 2px 3px var(--sp-2); }
.col-title { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.col-n {
  font-size: var(--fs-xs); color: var(--ink-3); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-pill); padding: 0 6px;
  font-variant-numeric: tabular-nums;
}
.col-sum { margin-left: auto; font-size: var(--fs-sm); color: var(--ink-2); font-variant-numeric: tabular-nums; font-weight: 600; }
.col-body { display: flex; flex-direction: column; gap: var(--sp-2); min-height: 48px; }
/* The work board shows seven lanes by default and nine with the estimation lanes
   expanded — far more than the pipeline's five, which is what .col's fixed width
   is sized for. So these stretch to fill instead.

   The 150px floor is deliberate and is the value the board used before the
   restyle: on a 1280px window the content area is roughly 1004px, which leaves
   about 133px per lane across seven. Anything higher starts a horizontal scroll
   that was not there before. The basis is a little larger so lanes take the extra
   room on a wide monitor rather than leaving it at the end of the row. */
.board-lanes .col { flex: 1 1 160px; min-width: 150px; }

.tile {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: var(--sp-2) var(--sp-3); cursor: pointer; text-align: left; width: 100%;
  display: block; text-decoration: none; color: var(--ink);
  transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}
.tile:hover { border-color: var(--accent-line); transform: translateY(-1px); box-shadow: var(--shadow); color: var(--ink); }
.tile-top { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; flex-wrap: wrap; }
.tile-eyebrow { font-size: 10.5px; color: var(--ink-3); text-transform: uppercase; letter-spacing: .07em; font-weight: 700; }
.tile-eyebrow.app { color: var(--accent); }
.tile-title { font-size: var(--fs-base); font-weight: 500; line-height: 1.35; margin-bottom: var(--sp-2); text-wrap: balance; }
.tile-meta { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.money { font-variant-numeric: tabular-nums; font-weight: 600; font-size: 13px; }
.dim { color: var(--ink-3); font-size: var(--fs-xs); }

/* Work-type dot. Carries the category at a glance without spending a pill's
   worth of width on every card; the pill below it spells the category out.
   The .cat-* classes it shares with badges also carry a tinted fill and border,
   so the dot resets the border and takes the solid hue instead. */
.cat-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  border: 0; background: var(--cat-internal);
}
.cat-dot.cat-project  { background: var(--cat-project); }
.cat-dot.cat-billable { background: var(--cat-billable); }
.cat-dot.cat-warranty { background: var(--cat-warranty); }
.cat-dot.cat-internal { background: var(--cat-internal); }

/* Card reference code — mono, quiet, and never wraps. */
.refcode {
  font-family: var(--mono); font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .04em; color: var(--ink-3); white-space: nowrap;
}

/* A card being dragged between lanes. SortableJS adds this to the ghost. */
.tile.dragging { opacity: .5; }

/* ── Work card ──────────────────────────────────────────────────────────
   The board tile. Grabbable, and the "move" affordance only appears on
   hover so it does not add permanent clutter to every card. */

.card-tile { position: relative; cursor: grab; }
.card-tile:active { cursor: grabbing; }
.card-tile .tile-title {
  display: block; color: inherit; text-decoration: none; margin: 2px 0 0;
  font-weight: 600;
}
.card-tile .tile-title:hover { color: var(--accent); }
.card-tile .tile-meta { margin-top: var(--sp-2); }
.card-tile .tile-who { margin-left: auto; display: inline-flex; align-items: center; }

.tile-move {
  position: absolute; top: 4px; right: 4px;
  padding: 0 6px; line-height: 1.5; font-size: var(--fs-sm);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-3); cursor: pointer;
  opacity: 0; transition: opacity .13s ease;
}
.card-tile:hover .tile-move, .tile-move:focus-visible { opacity: 1; }
.tile-move:hover { background: var(--surface-2); color: var(--ink); }
/* List rows have no hover-reveal: the control sits in the row's own flow. */
.tile-move.static { position: static; opacity: 1; flex: 0 0 auto; }

/* ── Work row (list mode) ───────────────────────────────────────────── */

.card-row {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 7px var(--sp-3); border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--surface);
}
.card-row:hover { border-color: var(--accent-line); }
.card-row + .card-row { margin-top: var(--sp-1); }
.card-row.terminal { opacity: .78; }
.card-row-title {
  flex: 1; min-width: 0; font-weight: 600; font-size: 13px;
  color: inherit; text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.card-row-title:hover { color: var(--accent); }

/* ══ Segmented control ══════════════════════════════════════════════════
   Two or three mutually exclusive views (Lanes vs By client). A row of chips
   would imply multi-select; this reads as one choice. */

.seg {
  display: inline-flex; border: 1px solid var(--line);
  border-radius: var(--r-sm); overflow: hidden; flex: 0 0 auto;
}
.seg button {
  padding: 6px var(--sp-3); border: 0; cursor: pointer;
  background: var(--surface); color: var(--ink-2); font-size: var(--fs-sm);
}
.seg button + button { border-left: 1px solid var(--line); }
.seg button:hover { background: var(--surface-2); }
.seg button[aria-pressed="true"] { background: var(--accent); color: #fff; font-weight: 500; }

/* ══ Filter bar ═════════════════════════════════════════════════════════ */

.filterbar {
  display: flex; align-items: center; gap: var(--sp-2) var(--sp-3);
  flex-wrap: wrap; margin-bottom: var(--sp-4);
}
.filterbar .flabel {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-3); font-weight: 700;
}
.filterbar select {
  padding: 5px var(--sp-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); font-size: var(--fs-sm);
}
.filterbar select:hover { border-color: var(--accent-line); }
.filterbar .spacer { margin-left: auto; }

/* ══ Summary strip ══════════════════════════════════════════════════════
   One line of counts above a filtered board. Quiet by design: it answers
   "how much is here" without competing with the cards. */

.summary-strip {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-2) var(--sp-3); margin-bottom: var(--sp-3);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm); font-size: var(--fs-sm); color: var(--ink-3);
}
.summary-strip b { color: var(--ink); font-weight: 600; }
.summary-strip .n,
.panel-note .n { font-variant-numeric: tabular-nums; color: var(--ink-2); font-weight: 600; }

/* Board grouped by client: one panel per client, cards tiled inside it. */
.client-group + .client-group { margin-top: var(--sp-3); }
.card-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--sp-2);
}

/* ══ Form controls ══════════════════════════════════════════════════════ */

.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--sp-3) var(--sp-4); }
.fld { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.fld.full { grid-column: 1 / -1; }
.fld > label { font-size: var(--fs-sm); font-weight: 600; color: var(--ink-2); }
.fld .req { color: var(--accent); margin-left: 2px; }
.fld input, .fld select, .fld textarea,
.inp {
  padding: 9px var(--sp-3); border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink); font-family: var(--sans);
  font-size: var(--fs-base); width: 100%; transition: border-color .14s ease;
}
.fld input:hover, .fld select:hover, .fld textarea:hover, .inp:hover { border-color: var(--accent-line); }
.fld input::placeholder, .fld textarea::placeholder, .inp::placeholder { color: var(--ink-3); }
.fld textarea, textarea.inp { resize: vertical; min-height: 76px; line-height: 1.5; }
.fld .hint { font-size: var(--fs-xs); color: var(--ink-3); }

.switch { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); color: var(--ink-2); cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 32px; height: 18px; border-radius: var(--r-pill); background: var(--surface-3);
  border: 1px solid var(--line); position: relative; flex: 0 0 auto;
  transition: background .15s ease, border-color .15s ease;
}
.switch .track::after {
  content: ""; position: absolute; top: 1px; left: 1px; width: 14px; height: 14px;
  border-radius: 50%; background: var(--surface); box-shadow: 0 1px 2px rgba(0,0,0,.2);
  transition: transform .15s ease;
}
.switch input:checked + .track { background: var(--accent); border-color: var(--accent); }
.switch input:checked + .track::after { transform: translateX(14px); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent-2); outline-offset: 2px; }

/* ══ Avatar ═════════════════════════════════════════════════════════════
   On a card an avatar carries no name — the name appears on hover. That is
   what keeps a dense board legible. */

.av {
  position: relative; width: 28px; height: 28px; border-radius: 50%;
  display: inline-grid; place-items: center; flex: 0 0 auto;
  font-size: 10.5px; font-weight: 700; color: #fff; letter-spacing: .01em;
  background-size: cover; background-position: center;
  box-shadow: 0 0 0 1.5px var(--surface), 0 0 0 2.5px var(--line-soft);
}
.av[data-name]::after {
  content: attr(data-name);
  position: absolute; right: calc(100% + 8px); top: 50%; transform: translateY(-50%);
  background: var(--ink); color: var(--ground);
  padding: 3px 8px; border-radius: 5px;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity .13s ease;
}
.av:hover { z-index: 5; }
.av[data-name]:hover::after { opacity: 1; }
/* The Avatar component's own class sets overflow:hidden to clip a photo to the
   circle. That would also clip the hover label, so the two together opt back out
   — the border-radius still rounds the image. */
.avatar.av { overflow: visible; }

.av-sm { width: 20px; height: 20px; font-size: 8.5px; }
.av-stack { display: inline-flex; align-items: center; }
.av-stack .av + .av { margin-left: -8px; }

/* ══ Drawer ═════════════════════════════════════════════════════════════ */

.drawer-scrim {
  position: fixed; inset: 0; background: rgba(8,26,20,.42);
  opacity: 0; pointer-events: none; transition: opacity .18s ease; z-index: 60;
}
.drawer-scrim.on { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; right: 0; height: 100vh; width: min(var(--drawer-w), 95vw);
  background: var(--surface); border-left: 1px solid var(--line); box-shadow: var(--shadow-lg);
  z-index: 70; transform: translateX(101%);
  transition: transform .2s cubic-bezier(.4,0,.2,1), width .2s cubic-bezier(.4,0,.2,1);
  display: flex; flex-direction: column;
}
.drawer.on { transform: none; }
.drawer.wide { width: min(var(--drawer-w-wide), 97vw); }
.drawer-head {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5) var(--sp-3); border-bottom: 1px solid var(--line-soft);
}
.drawer-eyebrow { font-size: 10.5px; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-3); font-weight: 700; }
.drawer-title { font-size: var(--fs-lg); font-weight: 600; letter-spacing: -.015em; margin: 2px 0 0; text-wrap: balance; }
.drawer-body { overflow-y: auto; padding: var(--sp-4) var(--sp-5) var(--sp-8); flex: 1; }
.drawer-foot {
  display: flex; gap: var(--sp-2); align-items: center;
  padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--line);
  background: var(--surface-2); flex-wrap: wrap;
}

/* ══ Toast ══════════════════════════════════════════════════════════════ */

.toast-stack {
  position: fixed; right: var(--sp-5); bottom: var(--sp-5); z-index: 80;
  display: flex; flex-direction: column; gap: var(--sp-2); max-width: 380px;
}
.toast {
  background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--r-sm); box-shadow: var(--shadow); padding: var(--sp-3);
  font-size: 13px; color: var(--ink);
}
.toast.err  { border-left-color: var(--danger); }
.toast.warn { border-left-color: var(--warn); }

/* ══ Command palette ════════════════════════════════════════════════════
   Cmd/Ctrl-K. Results are grouped by record type, because "Heartland" means
   a different thing depending on whether it is a client, an app or a deal. */

.cmdk-scrim {
  position: fixed; inset: 0; background: rgba(8,26,20,.42);
  opacity: 0; pointer-events: none; transition: opacity .18s ease; z-index: 60;
}
.cmdk-scrim.on { opacity: 1; pointer-events: auto; }
.cmdk {
  position: fixed; left: 50%; top: 12vh; transform: translateX(-50%) scale(.98);
  width: min(620px, 92vw); background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow-lg); z-index: 70; overflow: hidden;
  opacity: 0; pointer-events: none; transition: opacity .18s ease, transform .18s ease;
}
.cmdk.on { opacity: 1; pointer-events: auto; transform: translateX(-50%) scale(1); }
.cmdk-in {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line-soft);
}
.cmdk-in input {
  flex: 1; border: 0; background: none; font-family: var(--sans);
  font-size: var(--fs-md); color: var(--ink); outline: none; min-width: 0;
}
.cmdk-in input::placeholder { color: var(--ink-3); }
.cmdk-body { max-height: 52vh; overflow-y: auto; padding: var(--sp-1) 0 var(--sp-2); }
.cmdk-group-label {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .11em;
  color: var(--ink-3); font-weight: 700; padding: var(--sp-2) var(--sp-4) 4px;
}
.cmdk-result {
  display: flex; align-items: center; gap: var(--sp-2); width: 100%;
  padding: 7px var(--sp-4); background: none; border: 0; cursor: pointer;
  text-align: left; text-decoration: none; color: var(--ink);
}
.cmdk-result:hover, .cmdk-result.sel { background: var(--accent-soft); color: var(--ink); }
.cmdk-result .ic {
  width: 24px; height: 24px; border-radius: 6px; display: grid; place-items: center; flex: 0 0 auto;
  background: var(--surface-2); border: 1px solid var(--line); font-size: 9.5px;
  color: var(--ink-2); font-family: var(--mono); font-weight: 500;
}
.cmdk-result .nm { font-size: var(--fs-base); }
.cmdk-result .hint { margin-left: auto; font-size: var(--fs-xs); color: var(--ink-3); padding-left: var(--sp-2); text-align: right; }
.cmdk-foot {
  display: flex; gap: var(--sp-4); padding: 7px var(--sp-4);
  border-top: 1px solid var(--line-soft); background: var(--surface-2);
  font-size: var(--fs-xs); color: var(--ink-3); flex-wrap: wrap;
}
.cmdk-empty { padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--ink-3); font-size: 13px; }

/* ══ Small utilities ════════════════════════════════════════════════════
   Named classes rather than inline style attributes. Beyond consistency this
   shrinks the surface that keeps 'unsafe-inline' in the CSP's style-src: the
   policy can only tighten once the inline styles are gone app-wide. */

/* Nothing matched, said quietly. Not an error. */
.empty-note { padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--ink-3); font-size: 13px; }
/* A chip row sitting inside another flex row, which owns the spacing. */
.chips-inline { margin: 0; }
/* Explanatory line under a board or table. */
.board-hint { margin-top: var(--sp-3); }
/* Buttons at the foot of a form or modal. */
.form-actions { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); flex-wrap: wrap; }

/* ══ Shared niceties ════════════════════════════════════════════════════ */

.mono { font-family: var(--mono); font-size: .92em; }
:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
