/* ------------------------------------------------------------------
   CRM stylesheet.

   Mobile-first, one file, no framework, no build step. Wide content
   (tables, timelines) scrolls inside its own container so the page body
   never scrolls sideways on a phone.
   ------------------------------------------------------------------ */

:root {
  /* A neutral ramp with one consistent cool cast, rather than greys picked
     one at a time. The background is a shade warmer than the old flat grey so
     white cards read as material sitting on something, not holes in it. */
  --bg: #f5f2ec;
  --surface: #fffefb;
  --surface-alt: #efeade;
  --border: #ddd6c8;
  --border-strong: #b8ac97;
  --text: #1c1710;
  --text-soft: #5d5548;
  --text-faint: #8f8676;

  /* The default accent, deepened. The old steel blue read as a default; this
     one reads as a choice. A company's own colour still replaces it. */
  --accent: #155e94;
  --accent-soft: #e7f0f7;
  --accent-text: #ffffff;

  /* The one dark band in the light theme. The topbar keeps it in every
     company, which is what makes four differently-tinted workspaces still
     feel like one product. */
  --chrome: #191511;
  --chrome-raised: #262019;
  --chrome-text: #f2efe9;
  --chrome-soft: #a89f90;
  --chrome-border: #322b21;

  --ok: #1d6f4f;
  --ok-soft: #e6f3ec;
  --warn: #8a5a11;
  --warn-soft: #fdf2e0;
  --danger: #9a2c2c;
  --danger-soft: #fbeaea;

  --radius: 12px;
  --radius-sm: 7px;
  --radius-lg: 16px;
  --gap: 1rem;
  /* Two elevations, used consistently: resting, and unmistakably above. */
  --shadow-raised: 0 4px 10px rgba(48, 38, 22, .08), 0 12px 32px rgba(48, 38, 22, .10);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);

  /* One type scale, so a page has a shape rather than a uniform grey weight.
     Every size in the interface comes from here. */
  --text-xs:   .75rem;    /* metadata under a title */
  --text-sm:   .85rem;    /* secondary lines, captions */
  --text-base: 1rem;      /* body */
  --text-lg:   1.15rem;   /* card headings */
  --text-xl:   1.45rem;   /* page titles */
  --text-2xl:  2rem;      /* the one sentence that matters */
  --text-fig:  2.6rem;    /* a figure meant to be read across the room */

  /* Numbers want tabular figures and tight tracking; prose does not. */
  --tracking-tight: -.02em;
  --shadow: 0 1px 2px rgba(48, 38, 22, .06), 0 1px 3px rgba(48, 38, 22, .08);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* The display face: the wordmark's serif, promoted from the footer to the
     voice of every page title. One definition, so the mark and the titles
     cannot drift apart. The stack degrades through progressively more
     ordinary serifs and never falls through to a sans. */
  --display: "New York", "Iowan Old Style", "Palatino Linotype", Palatino,
             Cambria, Georgia, "Times New Roman", serif;

  /* The one gradient in the product, used exactly three times: under the
     chrome, over the sign-in card, above the maker's mark. Built from the
     company's own accent blended toward one fixed warm gold, so each
     workspace has its own aurora and none of them had to be designed. */
  --aurora: linear-gradient(90deg,
      var(--accent) 0%,
      color-mix(in srgb, var(--accent) 40%, #c99a3f) 55%,
      transparent 100%);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #141210;
    --surface: #1c1916;
    --surface-alt: #241f1a;
    --border: #39332a;
    --border-strong: #4f473a;
    --text: #ece8e0;
    --text-soft: #b1a898;
    --text-faint: #857c6c;

    --accent: #6aa7d4;
    --accent-soft: #1e2c38;
    --accent-text: #0d1117;

    --ok: #6dc79c;
    --ok-soft: #172a22;
    --warn: #dfa94e;
    --warn-soft: #2c2317;
    --danger: #e08585;
    --danger-soft: #2e1c1c;

    --chrome: #0f0d0a;
    --chrome-raised: #1c1916;
    --chrome-text: #ece8e0;
    --chrome-soft: #b1a898;
    --chrome-border: #292319;

    --shadow: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow-raised: 0 6px 16px rgba(0, 0, 0, .5);
  }
}

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  color: var(--text);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4 { line-height: 1.2; margin: 0 0 .5rem; font-weight: 600; }
h1 {
  /* The serif runs a shade small against the sans at equal size, so the page
     title takes the scale's step up without adding a new stop to it. */
  font-family: var(--display);
  font-size: calc(var(--text-xl) * 1.1);
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: lining-nums;
}
h2 { font-size: var(--text-lg); letter-spacing: var(--tracking-tight); }
h3 { font-size: var(--text-base); }
p { margin: 0 0 .75rem; }

/* Figures read as data, not as prose: same-width digits so a column of
   numbers lines up, and no ligature turning 1/2 into a fraction. */
.figure, .stat-value, .bar-note, .money, td.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- topbar */

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 20;
}

.topbar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem;
  max-width: 1280px;
  margin: 0 auto;
  padding: .6rem .9rem;
}

.brand {
  font-weight: 700;
  letter-spacing: .04em;
  font-size: 1.05rem;
  color: var(--text);
}

.company-switcher { flex: 1 1 12rem; min-width: 0; }
.company-switcher select { width: 100%; }

.topbar-right {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin-left: auto;
  min-width: 0;   /* allow the identity block to shrink instead of overflowing */
}

.whoami {
  display: flex;
  align-items: center;
  gap: .35rem;
  font-size: .85rem;
  color: var(--text-soft);
  min-width: 0;
}

/* The name truncates; the role badge and the sign-out control never do, so on a
   narrow screen you still see what you are and how to leave. */
.whoami-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.whoami .badge { flex: 0 0 auto; }

.inline-form { display: inline; margin: 0; }

.topbar-search { flex: 1 1 10rem; min-width: 0; }
.topbar-search input { width: 100%; padding: .35rem .55rem; font-size: .9rem; }
.topbar-add { flex: 0 0 auto; }

/* Below this width the switcher, the search box and the identity block compete
   for one row and the sign-out control ends up wrapping mid-phrase. Give the
   switcher and search their own full-width rows instead. */
@media (max-width: 719px) {
  .topbar-right { order: 2; margin-left: auto; }
  .company-switcher { order: 3; flex: 1 1 100%; }
  .topbar-search { order: 4; flex: 1 1 100%; }
  .topbar-add { order: 5; }
}

/* --------------------------------------------------------- quick add tiles */

.quick-add-tile {
  display: flex;
  align-items: center;
  gap: .75rem;
  color: var(--text);
  text-decoration: none;
}

.quick-add-tile:hover { background: var(--surface-alt); text-decoration: none; }
.quick-add-tile h2 { margin: 0; font-size: 1.05rem; }
.quick-add-icon { font-size: 1.5rem; line-height: 1; }

/* ------------------------------------------------------------- bulk editing */

.bulk-set { gap: .5rem; margin-bottom: .5rem; align-items: center; }
.bulk-set label { margin: 0; flex: 0 0 8rem; font-size: .85rem; }
.bulk-set select { flex: 1 1 12rem; max-width: 20rem; }

table.data th a { color: inherit; text-decoration: none; }
table.data th a:hover { text-decoration: underline; }

/* subnav: horizontally scrollable tab strip on narrow screens */
.subnav {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 .9rem .5rem;
  display: flex;
  gap: .25rem;
  overflow-x: auto;
  scrollbar-width: thin;
}

.subnav a {
  flex: 0 0 auto;
  padding: .35rem .7rem;
  border-radius: var(--radius-sm);
  font-size: .9rem;
  color: var(--text-soft);
  white-space: nowrap;
}

.subnav a:hover { background: var(--surface-alt); text-decoration: none; }
.subnav a.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

.subnav-shell { position: relative; }
.subnav-overflow-cue { display: none; }

@media (max-width: 700px) {
  .subnav-shell.has-overflow:not(.at-end) .subnav-overflow-cue {
    display: block;
    position: absolute;
    right: 0;
    top: .35rem;
    z-index: 2;
    padding: .45rem .6rem .5rem 1.2rem;
    background: linear-gradient(90deg, transparent, var(--surface) 28%);
    color: var(--text-soft);
    font-size: .75rem;
    font-weight: 650;
    pointer-events: none;
  }
}

/* ------------------------------------------------------------------ page */

.page {
  max-width: 1280px;
  margin: 0 auto;
  padding: 1rem .9rem 2.5rem;
}

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .5rem 1rem;
  margin-bottom: 1rem;
}

.page-head h1 { margin: 0; }
.page-head .page-actions { margin-left: auto; display: flex; gap: .5rem; flex-wrap: wrap; }

.eyebrow {
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-faint);
  font-weight: 600;
}

.footer {
  max-width: 1280px;
  margin: 0 auto;
  padding: 1rem .9rem 2rem;
  font-size: .78rem;
  color: var(--text-faint);
}

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

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
  box-shadow: var(--shadow);
}

.card + .card { margin-top: var(--gap); }
.card-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .75rem; }
.card-head h2, .card-head h3 { margin: 0; }
.card-head .card-link { margin-left: auto; font-size: .85rem; }

.grid { display: grid; gap: var(--gap); grid-template-columns: 1fr; }
@media (min-width: 700px)  { .grid-2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 700px)  { .grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1020px) { .grid-3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 700px)  { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1020px) { .grid-4 { grid-template-columns: repeat(4, 1fr); } }

/* stat tiles */
.stat { display: flex; flex-direction: column; gap: .15rem; }
.stat-label { font-size: .78rem; color: var(--text-soft); }
.stat-value { font-size: 1.4rem; font-weight: 650; font-variant-numeric: tabular-nums; }
.stat-note { font-size: .75rem; color: var(--text-faint); }

/* ---------------------------------------------------------------- tables */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: .9rem;
}

table.data th, table.data td {
  text-align: left;
  padding: .5rem .6rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

table.data th {
  font-size: .75rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-soft);
  font-weight: 600;
  white-space: nowrap;
}

table.data tbody tr:hover { background: var(--surface-alt); }
table.data td.num, table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .muted { color: var(--text-faint); }

/* On phones, data tables become stacked cards driven by each cell's label. */
@media (max-width: 640px) {
  table.stacked, table.stacked tbody, table.stacked tr, table.stacked td { display: block; width: 100%; }
  table.stacked thead { display: none; }
  table.stacked tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: .5rem .6rem;
    margin-bottom: .6rem;
    background: var(--surface);
  }
  table.stacked td { border: 0; padding: .2rem 0; display: flex; gap: .6rem; }
  table.stacked td::before {
    content: attr(data-label);
    flex: 0 0 8rem;
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--text-soft);
    font-weight: 600;
  }
  table.stacked td.num { text-align: left; }
}

/* ----------------------------------------------------------------- forms */

label { display: block; font-size: .85rem; font-weight: 600; margin-bottom: .2rem; }

input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="url"], input[type="tel"], input[type="search"],
input[type="month"], input[type="file"], select, textarea {
  width: 100%;
  padding: .5rem .6rem;
  font: inherit;
  font-size: .95rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
}

input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

textarea { min-height: 5rem; resize: vertical; }
.field { margin-bottom: .85rem; }
.field .help { font-size: .78rem; color: var(--text-faint); font-weight: 400; margin-top: .2rem; }
.field .errorlist { margin: .25rem 0 0; padding-left: 1.1rem; color: var(--danger); font-size: .82rem; }

.field-row { display: grid; gap: .85rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .field-row-2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 640px) { .field-row-3 { grid-template-columns: repeat(3, 1fr); } }

fieldset { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: .85rem; margin: 0 0 1rem; }
legend { font-size: .85rem; font-weight: 600; padding: 0 .35rem; }

.form-actions { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: 1rem; }
.filters { display: flex; flex-wrap: wrap; gap: .5rem; align-items: flex-end; margin-bottom: 1rem; }
.filters .field { margin: 0; flex: 1 1 10rem; }

/* --------------------------------------------------------------- buttons */

.btn {
  display: inline-block;
  padding: .45rem .8rem;
  font: inherit;
  font-size: .9rem;
  font-weight: 600;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}

.btn:hover { background: var(--surface-alt); text-decoration: none; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.btn-primary:hover { filter: brightness(1.08); background: var(--accent); }
.btn-danger { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.btn-quiet { border-color: transparent; background: transparent; color: var(--text-soft); }
.btn-quiet:hover { background: var(--surface-alt); }
.btn-sm { padding: .25rem .55rem; font-size: .8rem; }

/* ---------------------------------------------------------------- badges */

.badge {
  display: inline-block;
  padding: .1rem .45rem;
  border-radius: 999px;
  font-size: .72rem;
  font-weight: 600;
  background: var(--surface-alt);
  color: var(--text-soft);
  white-space: nowrap;
}

.badge-ok      { background: var(--ok-soft);     color: var(--ok); }
.badge-warn    { background: var(--warn-soft);   color: var(--warn); }
.badge-danger  { background: var(--danger-soft); color: var(--danger); }
.badge-accent  { background: var(--accent-soft); color: var(--accent); }
.badge-admin   { background: var(--accent-soft); color: var(--accent); }

/* -------------------------------------------------------------- messages */

.messages { list-style: none; margin: 0 0 1rem; padding: 0; }

.message {
  padding: .6rem .8rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  margin-bottom: .5rem;
  font-size: .9rem;
}

.message-success { background: var(--ok-soft);     border-color: var(--ok);     color: var(--ok); }
.message-warning { background: var(--warn-soft);   border-color: var(--warn);   color: var(--warn); }
.message-error   { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }

/* callout: standing notices, e.g. the budget authority statement */
.callout {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  padding: .6rem .8rem;
  font-size: .85rem;
  margin-bottom: 1rem;
}

.callout-warn { border-left-color: var(--warn); background: var(--warn-soft); }
.callout strong { font-weight: 650; }

.empty {
  padding: 1.5rem 1rem;
  text-align: center;
  color: var(--text-faint);
  font-size: .9rem;
}

/* ------------------------------------------------------------ pagination */

.pagination { display: flex; gap: .35rem; align-items: center; margin-top: 1rem; flex-wrap: wrap; font-size: .85rem; }
.pagination .current { padding: .25rem .55rem; color: var(--text-soft); }

/* --------------------------------------------------------------- sign in */

.auth-wrap { min-height: 70vh; display: grid; place-items: center; padding: 1.5rem .9rem; }
.auth-card { width: 100%; max-width: 22rem; }
.auth-card h1 { font-size: 1.25rem; margin-bottom: .25rem; }
.auth-card .lede { font-size: .85rem; color: var(--text-soft); margin-bottom: 1rem; }

/* ------------------------------------------------------------ misc utils */

.stack > * + * { margin-top: .6rem; }
.row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.muted { color: var(--text-faint); }
.small { font-size: .82rem; }
.nowrap { white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--mono); font-size: .85em; }
.negative { color: var(--danger); }
.positive { color: var(--ok); }
.right { text-align: right; }

.definition { display: grid; grid-template-columns: auto 1fr; gap: .3rem .8rem; font-size: .9rem; margin: 0; }
.definition dt { color: var(--text-soft); }
.definition dd { margin: 0; }

.progress { height: .4rem; background: var(--surface-alt); border-radius: 999px; overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--accent); }

/* ------------------------------------------------------------- timeline */

.timeline { list-style: none; margin: 0; padding: 0; }

.timeline-item {
  display: flex;
  gap: .7rem;
  padding: .6rem 0;
  border-bottom: 1px solid var(--border);
}

.timeline-item:last-child { border-bottom: 0; }

.timeline-icon {
  flex: 0 0 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  background: var(--surface-alt);
  color: var(--text-soft);
  display: grid;
  place-items: center;
  font-size: .8rem;
  margin-top: .1rem;
}

.timeline-activity .timeline-icon { background: var(--accent-soft); color: var(--accent); }

.timeline-body { min-width: 0; flex: 1 1 auto; }
.timeline-title { font-weight: 600; font-size: .93rem; }
.timeline-title .badge { margin-left: .35rem; font-weight: 600; }
.timeline-detail { margin: .15rem 0 0; font-size: .87rem; color: var(--text-soft); white-space: pre-wrap; }
.timeline-meta { margin: .2rem 0 0; font-size: .78rem; color: var(--text-faint); }

/* ------------------------------------------- progressive disclosure block */

.more-details {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: .5rem .7rem;
  margin-bottom: .5rem;
  background: var(--surface-alt);
}

.more-details > summary {
  cursor: pointer;
  font-size: .88rem;
  font-weight: 600;
  color: var(--text-soft);
  list-style-position: inside;
}

.more-details > summary:hover { color: var(--text); }
.more-details-body { padding-top: .75rem; }

/* ------------------------------------------------------------------ board */

.board {
  display: grid;
  gap: var(--gap);
  grid-auto-flow: column;
  grid-auto-columns: minmax(15rem, 1fr);
  overflow-x: auto;
  padding-bottom: .5rem;
  -webkit-overflow-scrolling: touch;
}

/* On a phone the columns stack, so the whole pipeline is readable by scrolling
   down rather than sideways. */
@media (max-width: 640px) {
  .board { grid-auto-flow: row; grid-auto-columns: auto; overflow-x: visible; }
}

.board-column {
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: .6rem;
  min-width: 0;
}

.board-column-head { margin-bottom: .5rem; }
.board-column-head h2 { font-size: .95rem; margin: 0; }
.board-column-head p { margin: .15rem 0 0; }

.board-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: .55rem .65rem;
  margin-bottom: .5rem;
  box-shadow: var(--shadow);
}

.board-card-stale { border-left-color: var(--danger); }
.board-card-title { font-weight: 650; font-size: .92rem; display: block; }
.board-card-value { margin: .3rem 0; font-weight: 600; font-size: .9rem; }
.board-card p { margin: .2rem 0; }

.board-move { display: flex; gap: .35rem; margin-top: .5rem; }
.board-move select { flex: 1 1 auto; min-width: 0; font-size: .8rem; padding: .25rem .4rem; }

/* --------------------------------------------------------------- calendar */

.calendar {
  display: grid;
  grid-template-columns: repeat(7, minmax(6.5rem, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  min-width: 46rem;   /* scrolls inside .table-scroll on a phone */
}

.calendar-weekday {
  background: var(--surface-alt);
  padding: .35rem .5rem;
  font-size: .75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--text-soft);
}

.calendar-day { background: var(--surface); padding: .35rem .4rem; min-height: 5.5rem; }
.calendar-empty { background: var(--surface-alt); }
.calendar-today { background: var(--accent-soft); }
.calendar-date { font-size: .78rem; font-weight: 650; color: var(--text-soft); }

.calendar-task {
  display: block;
  margin-top: .25rem;
  padding: .15rem .3rem;
  border-radius: 3px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: .74rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.calendar-task-late { background: var(--danger-soft); color: var(--danger); }
.calendar-task-done { background: var(--ok-soft); color: var(--ok); text-decoration: line-through; }

/* --------------------------------------------------------------- comments */

.comment-list { list-style: none; margin: 0; padding: 0; }

.comment {
  padding: .6rem 0;
  border-bottom: 1px solid var(--border);
}

.comment:last-child { border-bottom: 0; }
.comment-head { display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap; }
.comment-body { margin: .25rem 0 0; white-space: pre-wrap; font-size: .92rem; }

.mention-hint {
  display: inline-block;
  font-family: var(--mono);
  font-size: .78rem;
  background: var(--surface-alt);
  border-radius: 3px;
  padding: 0 .25rem;
}

/* ---------------------------------------------------------- notifications */

.notification-list { list-style: none; margin: 0; padding: 0; }

.notification { border-bottom: 1px solid var(--border); }
.notification:last-child { border-bottom: 0; }

.notification-open {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  padding: .6rem .5rem;
  cursor: pointer;
  font: inherit;
  color: inherit;
  border-radius: var(--radius-sm);
}

.notification-open:hover { background: var(--surface-alt); }
.notification-summary { display: block; font-size: .93rem; }
.notification-unread .notification-summary { font-weight: 650; }
.notification-meta { display: block; font-size: .78rem; color: var(--text-faint); margin-top: .15rem; }

.notification-unread {
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
}

.topbar-inbox, .topbar-mywork, .topbar-home { flex: 0 0 auto; }
@media (max-width: 719px) {
  .topbar-inbox, .topbar-mywork, .topbar-home { order: 5; }
}

/* Sits next to the wordmark, which people read as a logo rather than a link. */
.topbar-home { margin-right: .25rem; }

/* ------------------------------------------------------- meeting notes */

.note-body {
  white-space: pre-wrap;
  font-size: .92rem;
  line-height: 1.6;
  margin: 0;
  max-width: 60ch;
}

.suggestion-list { list-style: none; margin: 0 0 .75rem; padding: 0; }

.suggestion {
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: .55rem .7rem;
  margin-bottom: .5rem;
  background: var(--surface);
}

/* Held back from a batch: visibly different, with the reason beside it, so a
   reviewer sees why rather than meeting a disabled control. */
.suggestion-held { border-left-color: var(--warn); background: var(--warn-soft); }

.suggestion-head { display: flex; gap: .5rem; align-items: baseline; }
.suggestion-head .badge { margin-left: .35rem; }

.suggestion-excerpt {
  margin: .3rem 0;
  font-size: .85rem;
  color: var(--text-soft);
  font-style: italic;
  border-left: 2px solid var(--border);
  padding-left: .55rem;
}

/* ------------------------------------------------------- dashboard panels */

/* A section heading that sits between cards rather than inside one. */
.section-heading {
  margin: var(--gap) 0 .6rem;
  font-size: 1.05rem;
}

.text-danger { color: var(--danger); }

/* Exception panels carry a coloured edge so the worst reads first at a glance,
   without relying on colour alone: the count badge repeats the same tone. */
.panel { border-left: 3px solid var(--border); }
.panel-bad   { border-left-color: var(--danger); }
.panel-warn  { border-left-color: var(--warn); }
.panel-plain { border-left-color: var(--border); }
.panel-ok    { border-left-color: var(--ok); }

.panel-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.panel-list > li { padding-bottom: .55rem; border-bottom: 1px solid var(--border); }
.panel-list > li:last-child { padding-bottom: 0; border-bottom: 0; }

.panel-title { font-weight: 550; }
.panel-meta { margin: .15rem 0 0; }

/* The grid puts panels side by side; without this a short panel next to a tall
   one stretches and its content floats in the middle. */
.grid > .panel { align-self: start; }

/* Separators between meta bearings come from CSS, so a record that lacks one
   (no due date, nobody assigned) does not leave a stray bullet behind. */
.panel-meta > span + span::before { content: " · "; color: var(--text-faint); }
.panel-meta .badge + * { margin-left: .2rem; }

/* Four numbers stacked one per row wastes a phone screen and pushes the real
   content below the fold. Two by two keeps them scannable at a glance.
   Scoped to below the grid-4 breakpoint so the desktop layout is untouched. */
@media (max-width: 699px) {
  .grid-stats { grid-template-columns: repeat(2, 1fr); }
}

/* ------------------------------------------------- dragging a board card */

/* Applied by script, so a card only looks draggable where dragging works.
   Without JavaScript, on a touch device, or for somebody with read-only
   access, none of this appears and the stage control is the way to move a
   card. */
.board-card.is-draggable { cursor: grab; }
.board-card.is-draggable:active { cursor: grabbing; }

.board-card.is-dragging {
  opacity: .5;
  /* Kept subtle: the card under the cursor is the feedback, not this one. */
  border-style: dashed;
}

/* The card waits, greyed, until the reload confirms the move. */
.board-card.is-saving { opacity: .6; pointer-events: none; }

.board-column.is-drop-target {
  background: var(--accent-soft);
  outline: 2px dashed var(--accent);
  outline-offset: -2px;
}

/* While a drag is in progress, stop text selection turning the board blue. */
.board.is-dragging-within { user-select: none; }

/* Somebody who prefers less motion still gets the outline and the cursor,
   which carry the whole message; only the fading goes. */
@media (prefers-reduced-motion: reduce) {
  .board-card.is-dragging { opacity: 1; }
}

/* A row's one-click action. Quiet until wanted: the row is for reading, and a
   column of loud buttons would compete with the record it belongs to. */
.row-action { opacity: .75; }
.row-action:hover, .row-action:focus-visible { opacity: 1; }

@media (max-width: 719px) {
  /* Stacked into cards on a phone, where a full-width button reads as the
     row's action rather than a stray control. Given a proper tap target: the
     small button is 29px, which is a miss waiting to happen on the device
     where precision is worst. */
  /* `table.data .row-action` below sets the resting opacity to .45 and is
     more specific than a bare `.row-action`, so this selector has to match
     it: a media query changes when a rule applies, never how much it
     outranks another. Without the qualifier the phone stayed at .45 and
     no hover exists on a phone to lift it. */
  .row-action,
  table.data .row-action {
    width: 100%;
    min-height: 44px;
    opacity: 1;
  }
}

/* ==================================================== dashboard visuals ==
   Proportional bars drawn in CSS. No charting library, so the dependency
   count stays at three, and nothing here needs JavaScript to render.

   Colour is never the only signal. Every bar carries an aria-label, and every
   segment is named and numbered beneath it, so the meaning survives a
   monochrome screen or a reader who cannot separate the hues. */

/* ---- shared swatch, used by every key ---- */
.key-swatch {
  display: inline-block;
  width: .6rem;
  height: .6rem;
  border-radius: 2px;
  margin-right: .3rem;
  vertical-align: baseline;
}
.key-spent      { background: var(--accent); }
.key-committed  { background: var(--warn); }
.key-remaining  { background: var(--border); }
.key-green      { background: var(--ok); }
.key-amber      { background: var(--warn); }
.key-red        { background: var(--danger); }

/* ---- budget bars ---- */
.bar-set { display: grid; gap: 1.1rem; }
.bar-row { display: grid; gap: .4rem; }

.bar-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.bar-title { font-weight: 650; font-variant-numeric: tabular-nums; }
.bar-note { margin-left: auto; }

.bar {
  display: flex;
  height: .85rem;
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface-alt);
}
.bar-part { display: block; height: 100%; }
.bar-spent     { background: var(--accent); }
.bar-committed { background: var(--warn); }
.bar-remaining { background: var(--border); }

.bar-key {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem 1.25rem;
  margin: 0;
  font-size: .82rem;
}
.bar-key > div { display: flex; align-items: baseline; gap: .4rem; }
.bar-key dt { color: var(--text-soft); }
.bar-key dd { margin: 0; font-weight: 600; }

/* ---- pipeline funnel ---- */
.funnel { display: grid; gap: .85rem; }

/* The bar sits under its label at full width. Laying it out in columns looked
   tidy until the card landed in a two-column grid, where the middle column
   collapsed to nothing and every bar disappeared: a media query asks about the
   window, not about the space this card actually got. */
.funnel-row { display: grid; gap: .3rem; }

.funnel-head {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  flex-wrap: wrap;
}
.funnel-stage { font-weight: 550; }
.funnel-value { margin-left: auto; text-align: right; }

.funnel-track {
  height: 1.15rem;
  border-radius: 4px;
  background: var(--surface-alt);
  overflow: hidden;
}
.funnel-fill {
  display: block;
  height: 100%;
  background: var(--accent);
  /* A stage with something in it should never look empty, however small its
     share, so the fill keeps a visible minimum. */
  min-width: 3px;

  /* Each step down the pipeline is drawn a little lighter, so the set reads
     as one funnel narrowing rather than four separate bars. Decoration only —
     the length is the count and the count is written beside it — so it stops
     well short of invisible however many stages a company defines. */
  opacity: max(.4, calc(1 - var(--step, 0) * .13));
}

/* ---- project health strip ---- */
.strip {
  display: flex;
  height: .85rem;
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface-alt);
}
.strip-part { display: block; height: 100%; }
.strip-green { background: var(--ok); }
.strip-amber { background: var(--warn); }
.strip-red   { background: var(--danger); }

.strip-key {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem 1.25rem;
  list-style: none;
  margin: .5rem 0 0;
  padding: 0;
  font-size: .82rem;
  color: var(--text-soft);
}
.strip-key strong { color: var(--text); margin-left: .15rem; }

/* ---- headline figures: bigger, and given room ---- */
.grid-stats .stat { padding: .15rem 0; }
.grid-stats .stat-value { font-size: 1.9rem; line-height: 1.15; }
.grid-stats .stat-label {
  font-size: .74rem;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.grid-stats .stat-note { margin-top: .1rem; }

@media (min-width: 700px) {
  .grid-stats { gap: 1.6rem; }
  .grid-stats .stat-value { font-size: 2.2rem; }
}

/* A headline figure is a way in, not decoration, so the whole tile is the
   target — easier to hit than the number alone, and obviously so. */
.stat-link {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  padding: .5rem .6rem;
  margin: -.5rem -.6rem;
  border-radius: var(--radius);
  color: inherit;
  text-decoration: none;
}
.stat-link:hover, .stat-link:focus-visible {
  background: var(--surface-alt);
  text-decoration: none;
}
.stat-link:hover .stat-value { color: var(--accent); }
.stat-link .stat-label { text-decoration: underline; text-decoration-color: transparent; }
.stat-link:hover .stat-label { text-decoration-color: currentColor; }

/* Anchored sections should not land under the sticky bar. */
#pipeline, #project-health, #attention { scroll-margin-top: 5rem; }

/* ------------------------------------------------------- knowledge base */

.ask-panel .filters { align-items: flex-end; }

.ask-results { display: grid; gap: 1.1rem; margin-top: .75rem; }
.ask-group { border-top: 1px solid var(--border); padding-top: .75rem; }
.ask-source { margin: 0 0 .4rem; display: flex; gap: .5rem; align-items: baseline; flex-wrap: wrap; }

.passage-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.passage-list > li { display: grid; gap: .1rem; }

.passage-locator {
  font-size: .72rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.passage-text { font-size: .9rem; }

/* The matched words. Background rather than colour alone, and it survives
   dark mode because it derives from the theme. */
.passage-text mark {
  background: var(--warn-soft);
  color: inherit;
  border-radius: 2px;
  padding: 0 .1rem;
}

/* ------------------------------------------------------------- palette
   The command palette. Hidden until Cmd-K; every route it offers is also
   reachable from the header, so this styles a shortcut, not a dependency. */
.palette[hidden] { display: none; }

.palette {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 4rem 1rem 1rem;
}

.palette-scrim {
  position: absolute;
  inset: 0;
  background: rgba(26, 31, 38, 0.35);
}

.palette-box {
  position: relative;
  width: min(40rem, 100%);
  max-height: min(28rem, 80vh);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: 0 12px 40px rgba(26, 31, 38, 0.28);
  overflow: hidden;
}

.palette-input {
  border: 0;
  border-bottom: 1px solid var(--border);
  padding: 0.9rem 1rem;
  font-size: 1rem;
  color: var(--text);
  background: var(--surface);
}
.palette-input:focus { outline: none; }

.palette-results {
  list-style: none;
  margin: 0;
  padding: 0.25rem;
  overflow-y: auto;
  flex: 1;
}

.palette-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.5rem 0.75rem;
  border-radius: var(--radius-sm);
  color: var(--text);
  cursor: pointer;
}

.palette-item.is-active { background: var(--accent-soft); }

.palette-kind {
  flex: none;
  font-size: 0.75rem;
  color: var(--text-soft);   /* --text-faint is under 4.5:1 at this size */
}

.palette-foot {
  margin: 0;
  padding: 0.5rem 1rem;
  border-top: 1px solid var(--border);
  background: var(--surface-alt);
}

.palette-foot kbd {
  font: inherit;
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  padding: 0 0.3rem;
  margin-right: 0.15rem;
  background: var(--surface);
}

/* ---------------------------------------------------------------- peek
   A record at a glance: a side panel from the list, and a hover card on the
   record's own link. Both are shortcuts — the link to the full page is
   always there underneath. */
.peek[hidden], .peek-card[hidden] { display: none; }

.peek { position: fixed; inset: 0; z-index: 55; }

.peek-scrim {
  position: absolute;
  inset: 0;
  background: rgba(26, 31, 38, 0.28);
}

.peek-body {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(26rem, 100%);
  overflow-y: auto;
  padding: 1.25rem;
  background: var(--surface);
  border-left: 1px solid var(--border-strong);
  box-shadow: -8px 0 32px rgba(26, 31, 38, 0.18);
}

.peek-close { position: absolute; top: 0.75rem; right: 0.75rem; }

.peek-head { margin-bottom: 1rem; padding-right: 4rem; }
.peek-head h2 { margin: 0.15rem 0 0; font-size: 1.15rem; }

.peek-actions { margin: 1rem 0 0; }

.peek-card {
  position: absolute;
  z-index: 56;
  width: min(22rem, calc(100vw - 2rem));
  padding: 0.75rem 0.9rem;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(26, 31, 38, 0.2);
  pointer-events: none;
}
.peek-card .peek-actions { display: none; }
.peek-card h2 { font-size: 1rem; }

.peek-trigger {
  border: 1px solid transparent;
  background: none;
  color: var(--text-faint);
  cursor: pointer;
  padding: 0 0.35rem;
  margin-left: 0.25rem;
  border-radius: var(--radius-sm);
  line-height: 1.2;
}
.peek-trigger:hover, .peek-trigger:focus {
  border-color: var(--border);
  color: var(--text);
  background: var(--surface-alt);
}

/* On a touch screen there is no hover, and the panel is the whole width. */
@media (max-width: 34rem) {
  .peek-body { width: 100%; }
}

/* ------------------------------------------------------- inline editing
   A whitelisted cell can be changed in place. The affordance stays quiet
   until the row is under the pointer, so a dense table does not become a
   field of buttons. */
td.is-editable { cursor: pointer; }

tbody tr:hover td.is-editable {
  box-shadow: inset 0 0 0 1px var(--border);
  border-radius: var(--radius-sm);
}

td.is-editable select {
  width: 100%;
  min-width: 8rem;
}

td.is-saving { opacity: 0.5; }

td.is-saved {
  background: var(--ok-soft);
  transition: background 0.6s ease-out;
}

/* ---------------------------------------------------------- empty states
   A first screen should say what this kind of record is for and offer the
   two ways to get one, rather than only reporting that there are none. */
.empty-state { padding: 1.5rem 0.5rem; text-align: center; }

.empty-lead {
  margin: 0 0 0.35rem;
  font-weight: 600;
  color: var(--text);
}

.empty-hint {
  margin: 0 auto 1rem;
  max-width: 34rem;
  color: var(--text-soft);
  font-size: 0.9rem;
  line-height: 1.5;
}

.empty-actions { margin: 0; display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }

/* ------------------------------------------------------- desktop density
   The rest of this stylesheet is mobile-first, which is right: it starts from
   the hardest constraint and relaxes. But the width this CRM is actually
   worked at all day is a desktop one, and phone spacing carried up to 1280px
   wastes it — fewer rows on screen means more scrolling to see the same work.
   This tightens rows and lifts the page's ceiling above that width only.
   Nothing below 64rem changes. */
@media (min-width: 64rem) {
  .page { padding: 1.25rem 1.5rem 3rem; }

  /* Wider than 1280 on a large screen: the extra goes to the columns, which
     is what a dense table wants, rather than to the margins. */
  .page, .topbar-inner, .subnav { max-width: 1560px; }

  table.data { font-size: .875rem; }
  table.data th, table.data td { padding: .4rem .55rem; }
  table.data th { font-size: .7rem; }

  /* A row of cards reads as one band rather than as separate blocks. */
  .card { padding: .9rem 1rem; }
  .grid { gap: .85rem; }
}

/* Beyond a very wide screen, stop growing: a table whose rows span a metre
   is harder to read across, not easier. */
@media (min-width: 110rem) {
  .page, .topbar-inner, .subnav { max-width: 1760px; }
}

/* The mapping table pairs each field with a column and an optional constant. */
.mapping-table td select, .mapping-table td input[type="text"] { width: 100%; }
.mapping-table th:first-child, .mapping-table td:first-child { width: 32%; }

/* "Apply to all matching" — visually distinct from the row checkboxes, because
   it changes what the buttons beneath it will reach. */
.bulk-scope {
  display: block;
  margin: 0 0 .75rem;
  padding: .5rem .65rem;
  border: 1px solid var(--warn);
  border-radius: var(--radius-sm);
  background: var(--warn-soft);
  font-size: .9rem;
}

/* -------------------------------------------------------- form errors
   A summary at the top of a form. Django's per-field messages stay where
   they are and are still the ones you correct against; this is the one
   that says something went wrong at all, which is what was missing when a
   Create button appeared to do nothing. */
.form-errors {
  margin: 0 0 1rem;
  padding: .75rem .9rem;
  border: 1px solid var(--danger);
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  background: var(--danger-soft);
  color: var(--danger);
}
.form-errors-lead { margin: 0 0 .4rem; font-weight: 600; }
.form-errors ul { margin: 0; padding-left: 1.1rem; font-size: .9rem; }
.form-errors li { margin: .15rem 0; }

/* ------------------------------------------------------ this morning
   The single point of entry. The bar is the widest thing on the page
   because it is the thing most often used; the line beneath it is the
   only sentence, and it is allowed to say the day is clear.

   Nothing here needs JavaScript. The bar is a GET form, the sections are
   ordinary markup, and a section that failed to build renders as a
   section that failed rather than taking the page with it. */
.ask-bar {
  display: flex;
  gap: .5rem;
  margin: 0 0 .35rem;
}
.ask-bar input[type="search"] {
  flex: 1 1 auto;
  min-width: 0;
  padding: .7rem .9rem;
  font-size: 1rem;
}
.ask-note { margin: 0 0 1.25rem; }

.the-line { margin-bottom: 1.25rem; }
.line-sentence {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 600;
  line-height: 1.3;
}
.line-qualifier { margin: .2rem 0 0; }

.dash-section { margin: 0 0 1.75rem; }
.dash-section > h2 { margin: 0 0 .35rem; font-size: 1.05rem; }
.dash-section > p.small { margin: 0 0 .75rem; }

/* The neutral preview of newly filed material. Set apart from the record's
   own title so it reads as a quotation, not as a claim about it. */
.preview {
  margin: .35rem 0 .15rem;
  padding-left: .6rem;
  border-left: 2px solid var(--border);
  color: var(--text);
}
.passage { margin: 0 0 .2rem; font-size: .92rem; }
.passage mark { background: var(--accent-soft); padding: 0 .1rem; }

/* What a create would produce, before it produces it. */
.preview-list { margin: .5rem 0 .9rem; display: grid; gap: .3rem; }
.preview-list > div { display: flex; gap: .5rem; }
.preview-list dt { min-width: 7rem; font-weight: 600; }
.preview-list dd { margin: 0; }

.chip-row {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}

@media (max-width: 640px) {
  .ask-bar { flex-wrap: wrap; }
  .ask-bar input[type="search"] { flex-basis: 100%; }
  .line-sentence { font-size: 1.15rem; }
  .preview-list > div { flex-direction: column; gap: 0; }
}

/* ============================================================ hierarchy
   The interface used to draw every card identically: same white, same
   border, same shadow, whether it held nine overdue tasks or nothing at
   all. On a clear day the morning screen was a grid of boxes each saying
   "nothing", which reads as a form somebody failed to fill in rather than
   as a quiet day.

   So: a panel with something in it comes forward, and an empty one
   recedes to a single line. Nothing is hidden — an empty "overdue" is
   information and stays readable — but it stops competing for the eye
   with the things that actually want attention. */

.panel.is-empty,
.card.is-empty {
  background: transparent;
  border-style: dashed;
  border-color: var(--border);
  box-shadow: none;
  padding: .6rem .8rem;
}
.panel.is-empty .card-head { margin-bottom: 0; }
.panel.is-empty .card-head h3 {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-soft);
}
.panel.is-empty .empty {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-faint);
  text-align: left;
  padding: 0;
}
/* An empty panel puts its heading and its answer on one line where there
   is genuinely room. The breakpoint is on the wide side deliberately: most
   of these sit in a two-column grid, so at 40rem each one is barely 200px
   and the "saving" was two cramped columns of wrapped text. */
@media (min-width: 62rem) {
  .panel.is-empty {
    display: flex;
    align-items: baseline;
    gap: .6rem;
  }
  .panel.is-empty .card-head { flex: 0 0 auto; }
  .panel.is-empty .empty { flex: 1 1 auto; }
}

/* A panel that does hold something earns its weight, and its tone shows
   in a spine down the left rather than a wash of colour behind text. */
.panel:not(.is-empty) {
  border-left: 3px solid var(--border-strong);
}
.panel-bad:not(.is-empty)   { border-left-color: var(--danger); }
.panel-warn:not(.is-empty)  { border-left-color: var(--warn); }
.panel-ok:not(.is-empty)    { border-left-color: var(--ok); }
.panel-plain:not(.is-empty) { border-left-color: var(--border-strong); }

.card-head h3 { font-size: var(--text-base); }
.panel-list > li { padding-bottom: .6rem; }
.panel-title { font-weight: 550; }
.panel-meta { font-size: var(--text-xs); margin: .15rem 0 0; }

/* ================================================================ icons
   Inline SVG on a 24-unit grid, stroked with currentColor, so an icon
   takes the colour and weight of the text beside it. */
.icon {
  display: inline-block;
  vertical-align: -.14em;
  flex: 0 0 auto;
}
.icon-sm { vertical-align: -.16em; }
.head-icon {
  display: inline-flex;
  margin-right: .4rem;
  color: var(--text-faint);
}
.timeline-icon .icon { vertical-align: middle; }

/* ======================================================== the one line
   The morning sentence is the only thing on that page allowed to be
   large. It is also allowed to say the day is clear, which is why the
   clear state gets the calmer colour rather than the emptier one. */
.the-line {
  border-left: 3px solid var(--accent);
  padding: 1.1rem 1.2rem;
}
.the-line.is-clear { border-left-color: var(--ok); }
.line-sentence {
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  line-height: 1.15;
  margin: 0;
}
.the-line.is-clear .line-sentence { color: var(--ok); }
.line-qualifier { margin: .35rem 0 0; font-size: var(--text-sm); }

/* Section headings sit above their cards as labels, not as competition. */
.dash-section > h2 {
  font-size: var(--text-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
  margin: 0 0 .5rem;
}

@media (max-width: 640px) {
  .line-sentence { font-size: 1.4rem; }
}

/* =============================================================== topbar
   Seven controls at identical weight, wrapping awkwardly. The fix is
   grouping and contrast, not removal: the brand and the company you are
   in read first, the things you press read second, and your own name and
   sign-out sit apart at the end.

   `.btn-quiet-icon` is for the topbar's own buttons — they carry an icon
   and a label, and they are navigation rather than actions, so they lose
   the border that made them look like six submit buttons in a row. */
.topbar-inner { gap: .45rem; padding: .55rem .9rem; }

.brand {
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: .01em;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  margin-right: .2rem;
}
.brand:hover { text-decoration: none; }

.topbar .btn-sm,
.topbar-home, .topbar-mywork, .topbar-inbox {
  border-color: transparent;
  background: transparent;
  color: var(--text-soft);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .38rem .6rem;
}
.topbar .btn-sm:hover,
.topbar-home:hover, .topbar-mywork:hover, .topbar-inbox:hover {
  background: var(--surface-alt);
  color: var(--text);
  text-decoration: none;
}
/* Add stays a real button, because it is the one thing here that makes
   something rather than going somewhere. */
.topbar .btn-primary.topbar-add {
  border-color: transparent;
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 600;
}
.topbar .btn-primary.topbar-add:hover { background: var(--accent); filter: brightness(1.08); }

.company-switcher select {
  font-weight: 600;
  border-color: var(--border);
  background: var(--surface-alt);
  padding: .35rem 1.6rem .35rem .55rem;
}

.topbar-search input {
  border-radius: 999px;
  padding: .38rem .8rem;
  background: var(--surface-alt);
  border-color: transparent;
}
.topbar-search input:focus-visible { background: var(--surface); }

.topbar-right { gap: .5rem; align-items: center; }
.whoami-name { font-weight: 600; font-size: var(--text-sm); }

/* The section bar reads as tabs on a rail rather than as loose links. */
.subnav {
  border-bottom: 1px solid var(--border);
  padding-bottom: 0;
  gap: .1rem;
}
.subnav a {
  border-bottom: 2px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  padding: .45rem .7rem .5rem;
  margin-bottom: -1px;
}
.subnav a.active {
  background: transparent;
  border-bottom-color: var(--accent);
  color: var(--accent);
}
.subnav a:hover { background: var(--surface-alt); }

/* ======================================================== page heading
   The eyebrow is the company; the title is the screen. They were the
   same weight and nearly the same size, so neither led. */
.eyebrow {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .09em;
  color: var(--text-faint);
  margin: 0 0 .15rem;
}
.page-head { align-items: flex-start; margin-bottom: 1.25rem; }
.page-head h1 { margin: 0; }

/* ================================================================ lists
   The table is where the work actually happens, and it was the least
   considered surface in the interface: every column the same width, every
   value the same weight, dates and names wrapping onto three lines in
   columns 60px wide.

   Three changes, no markup: the first column is the record and gets the
   room, secondary columns stop wrapping and stop growing, and the row
   itself becomes the hit area rather than a thin blue link. */
table.data {
  font-size: var(--text-sm);
  table-layout: auto;
}
table.data th, table.data td {
  padding: .55rem .7rem;
  vertical-align: middle;
}
table.data th {
  font-size: var(--text-xs);
  color: var(--text-faint);
  border-bottom-color: var(--border-strong);
}

/* The name of the thing leads: darker, heavier, allowed to take the space
   the other columns give up. */
table.data td:first-of-type,
table.data td.primary {
  font-weight: 550;
  min-width: 12rem;
}
table.data td:first-of-type a { color: var(--text); }
table.data td:first-of-type a:hover { color: var(--accent); }

/* Everything that is a date, a person or a status is a fact you scan, not
   a sentence you read — so it stays on one line and the table scrolls
   instead of the cell wrapping. */
table.data td.nowrap,
table.data td.date,
table.data td.person,
table.data td.status { white-space: nowrap; color: var(--text-soft); }

table.data tbody tr { transition: background 60ms linear; }
table.data tbody tr:hover { background: var(--accent-soft); }
table.data tbody tr:last-child td { border-bottom: 0; }

/* Row controls stay quiet until the row is under the pointer, so a list of
   forty rows is not forty buttons competing with the content. */
table.data .row-action { opacity: .45; }
table.data tr:hover .row-action,
table.data .row-action:focus-visible { opacity: 1; }

/* Status pills read as states rather than as decoration: a dot carries the
   colour, so meaning survives a monochrome screen. */
.badge {
  padding: .12rem .5rem;
  font-size: var(--text-xs);
  border: 1px solid transparent;
}
.badge-danger { background: var(--danger-soft); color: var(--danger); }
.badge-warn   { background: var(--warn-soft);   color: var(--warn); }
.badge-ok     { background: var(--ok-soft);     color: var(--ok); }
.badge-accent { background: var(--accent-soft); color: var(--accent); }

/* ============================================================== footer */
.footer {
  max-width: 1280px;
  margin: 2.5rem auto 0;
  padding: 1.1rem .9rem 1.6rem;
  border-top: 1px solid var(--border);
  color: var(--text-faint);
  font-size: var(--text-xs);
}

/* =========================================================== the marks
   Two of them, and they mean different things.

   The company's mark sits at the top-left, beside the wordmark, inside
   that company's workspace. It answers "where am I" before a word is
   read — which with four companies is the question asked most often.
   Without an uploaded logo it is the company's initials, drawn as a real
   mark rather than a grey placeholder: a workspace should look like
   somebody's from the first day, not like a form left incomplete.

   The maker's mark sits at the bottom of every page, quiet, and stays the
   same everywhere. */
.company-mark {
  display: inline-flex;
  align-items: center;
  margin-right: .1rem;
}
.company-logo {
  height: 26px;
  width: auto;
  max-width: 120px;
  object-fit: contain;
  display: block;
  border-radius: 3px;
}
.company-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .02em;
}

.company-logo-lg { height: 56px; max-width: 220px; }
.company-initials-lg {
  width: 56px;
  height: 56px;
  border-radius: 12px;
  font-size: 1.25rem;
}
.brand-preview {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: 1rem;
}
.brand-preview-name { font-size: var(--text-lg); font-weight: 600; }

.footer-line { margin: 0 0 .35rem; }
/* The maker's mark, which had no typography in it at all — the body face,
   bolded, with an italic tail. That is a default, not a decision, and it read
   like one.

   No web font. A hosted face would mean a request to somebody else's server on
   every page load of a private CRM, which is a privacy cost and a dependency
   that fails silently, for a line of text in a footer. The craft comes instead
   from faces already on the machine, used deliberately.

   The wordmark is set in a serif because "authoritative" is a promise the
   typography either keeps or breaks. Every name here is a real system face:
   New York on modern macOS, Iowan Old Style and Palatino before it, Cambria
   and Georgia on Windows. The stack degrades through progressively more
   ordinary serifs and never falls through to a sans, so the intent survives
   even on a machine that has none of the first choices.

   The slogan drops to small tracked capitals so the two never compete for the
   same glance: one is a name, the other is a claim about it, and they should
   not look like a single phrase. */
.maker {
  margin: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 .7rem;
}

.maker-name {
  font-family: var(--display);
  font-size: 1.06rem;
  font-weight: 600;
  /* A serif at this size sets a shade loose for a wordmark. */
  letter-spacing: -0.005em;
  color: var(--text);
  /* Lining figures, explicitly, and this is not a stylistic preference.
     Old-style figures were tried first — they sit prettily with lowercase
     letters — and they rendered the mark as "3po.ai", because an old-style
     zero drops to x-height and becomes the letter o. The name has a zero in
     it. A typographic refinement that misspells the company is not one. */
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1;
}

.maker-slogan {
  /* Set as a phrase, not as a label.

     It was small tracked capitals, which is the right treatment for two words
     and the wrong one for six: at 10px with .19em of tracking, "intelligence
     with a paper trail" measured 241px against a 49px wordmark — five times
     the width of the thing it qualifies, and thin enough to whisper. A label
     can be spaced out because the eye takes it in as a shape; a sentence has
     to be read, and tracking fights reading.

     So it takes the wordmark's serif in italic. The two are then one family
     in two voices, which is how a masthead sets a title against its standfirst,
     and the italic keeps the lowercase the slogan was written in. */
  font-family: var(--display);
  font-style: italic;
  font-size: .95rem;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--text-soft);
}

/* The em dash belonged to a phrase — a name joined to its slogan reads as one
   sentence. These are two things: a name, and a claim about it. The space now
   does that work, which is what space is for. */

/* ========================================================== group tabs
   The types inside one workspace entry. Distinct from `.subnav`, which
   moves between entries: these move within one, so they read as a
   segmented control rather than a second navigation bar. */
.group-tabs {
  display: flex;
  gap: .2rem;
  margin: 0 0 1rem;
  padding: .2rem;
  background: var(--surface-alt);
  border-radius: 999px;
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
}
.group-tabs a {
  padding: .3rem .85rem;
  border-radius: 999px;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-soft);
  white-space: nowrap;
}
.group-tabs a:hover { color: var(--text); text-decoration: none; }
.group-tabs a.active {
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  box-shadow: var(--shadow);
}

/* Settings sits at the far end of the workspace bar, away from the work. */
.subnav-end { margin-left: auto; }
.subnav-end .icon { opacity: .7; }

/* ===================================================== reading width
   Content spanned the full window, so on a wide screen a sentence ran
   for 1,900px and the eye lost its place between one line and the next.
   Panels and tables still use the room; prose does not. */
.page-head, .dash-section > p.small, .card > p, .empty-lead {
  max-width: 68ch;
}
.page-head { max-width: none; }
.page-head h1 + p, .page-head .small { max-width: 68ch; }

/* ============================================================= settings
   Cards rather than a list of links, because each one is a place and the
   sentence under it is what tells somebody whether it is the place they
   meant. The whole card is the target. */
.settings-card {
  display: flex;
  align-items: flex-start;
  gap: .85rem;
  color: inherit;
}
.settings-card:hover {
  text-decoration: none;
  border-color: var(--accent);
}
.settings-icon {
  display: inline-flex;
  padding: .5rem;
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  color: var(--accent);
}
.settings-label { display: block; margin-bottom: .1rem; }

.activity-line { display: flex; gap: .55rem; align-items: flex-start; }
.activity-line .timeline-icon { color: var(--text-faint); padding-top: .15rem; }

/* ============================================================= figures
   The four numbers the retired Overview led with. Large and calm, each
   one a link into what it counts — a figure somebody cannot act on is
   decoration, and this page has no room for decoration. */
.figure-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: .75rem;
  margin-bottom: 1.5rem;
}
.figure-tile {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  padding: .9rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: inherit;
}
.figure-tile:hover { text-decoration: none; border-color: var(--accent); }
.figure-value {
  font-size: var(--text-fig);
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--tracking-tight);
  font-variant-numeric: tabular-nums;
}
.figure-label {
  font-size: var(--text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--text-faint);
}
.figure-note { font-size: var(--text-sm); font-weight: 600; }
.figure-bad { color: var(--danger); }
.figure-money {
  font-size: var(--text-sm);
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 640px) {
  .figure-value { font-size: 1.9rem; }
}

/* ============================================================ first run
   A workspace with nothing in it. One card that says so and offers the
   two or three ways people actually start, instead of six sections each
   reporting an absence. */
.first-run { padding: 1.75rem; }
.first-run h2 { font-size: var(--text-xl); margin-bottom: .4rem; }
.first-run > p { max-width: 60ch; }
.first-run .chip-row { margin: 1rem 0; }

/* ====================================================================
   THE FINISH.

   Everything below is the visual finishing pass, in one place and applied
   last so the cascade is unambiguous. Four commitments, each answering
   something Hassan's screenshots showed:

   1. One dark band. The topbar is the same dark chrome in every company
      and both themes — it is what makes four differently-tinted
      workspaces still feel like one product, and it is the difference
      between "web page" and "application" at first glance.
   2. A type scale used with intent: display sizes tight and heavy, micro
      labels small and spaced, nothing in between pretending to be both.
   3. Two elevations. Resting things sit; floating things float. No third
      state.
   4. Room. The old rhythm packed sections against each other; a screen
      somebody reads every morning earns its margins.
   ==================================================================== */

/* ------------------------------------------------------------- chrome */
.topbar {
  background: var(--chrome);
  border-bottom: 1px solid var(--chrome-border);
}
.topbar-inner { padding: .55rem 1.1rem; gap: .55rem; }

.topbar .brand {
  color: var(--chrome-text);
  font-size: 1.02rem;
  letter-spacing: .02em;
}
.topbar .brand .icon { color: var(--chrome-soft); }
.topbar .brand:hover .icon { color: var(--chrome-text); }

/* Navigation on the chrome: quiet light text, never bordered boxes. */
.topbar .btn-sm,
.topbar .topbar-mywork,
.topbar .topbar-inbox {
  color: var(--chrome-soft);
  background: transparent;
  border-color: transparent;
}
.topbar .btn-sm:hover,
.topbar .topbar-mywork:hover,
.topbar .topbar-inbox:hover {
  color: var(--chrome-text);
  background: var(--chrome-raised);
}

/* Add is the one control up here that makes something rather than going
   somewhere, so it is the one solid object on the chrome. White, not
   accent: a company may choose a dark colour, and the button must not
   sink into the band behind it. */
.topbar .btn-primary.topbar-add {
  background: #ffffff;
  color: #14181e;
  font-weight: 650;
}
.topbar .btn-primary.topbar-add:hover { background: #e9edf2; filter: none; }

.topbar .company-switcher select {
  background: var(--chrome-raised);
  border: 1px solid var(--chrome-border);
  color: var(--chrome-text);
  font-weight: 600;
  border-radius: var(--radius-sm);
}
.topbar .topbar-search input {
  background: var(--chrome-raised);
  border-color: transparent;
  color: var(--chrome-text);
}
.topbar .topbar-search input::placeholder { color: var(--chrome-soft); }
.topbar .topbar-search input:focus-visible {
  background: var(--chrome-raised);
  outline-color: var(--chrome-soft);
}

.topbar .whoami-name { color: var(--chrome-text); }
.topbar .badge-admin {
  background: var(--chrome-raised);
  color: var(--chrome-soft);
  border: 1px solid var(--chrome-border);
}
.topbar .btn-quiet {
  color: var(--chrome-soft);
  background: transparent;
  border-color: transparent;
}
.topbar .btn-quiet:hover { color: var(--chrome-text); background: var(--chrome-raised); }

/* The company's mark holds its own colour on the dark band — it is the
   one thing up there allowed to be the company rather than the product. */
.topbar .company-initials { box-shadow: inset 0 0 0 1px rgba(255,255,255,.14); }
.topbar .company-logo { background: #ffffff; padding: 2px; }

/* The section bar stays light, directly under the chrome: one dark band,
   one light rail, then the page. */
.subnav {
  background: var(--surface);
  padding-top: .35rem;
}

/* --------------------------------------------------------------- type */
h1 { font-size: 1.6rem; font-weight: 650; letter-spacing: -.025em; }
.page-head { margin: 1.6rem 0 1.5rem; }
.page-head .eyebrow { margin-bottom: .3rem; }

/* Every micro-label in the interface is the same voice: the eyebrow, the
   section headings, the figure captions, the table headers. One size, one
   tracking, one colour — so they read as structure, not as content. */
.eyebrow,
.dash-section > h2,
.figure-label,
table.data th {
  font-size: .72rem;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-faint);
}
.dash-section { margin-bottom: 2.25rem; }
.dash-section > h2 { margin-bottom: .6rem; }

.line-sentence { font-size: 1.9rem; font-weight: 650; letter-spacing: -.03em; }
.the-line { padding: 1.3rem 1.4rem; }

.figure-value { font-size: 2.3rem; font-weight: 650; }

/* ---------------------------------------------------------- elevation */
.card { padding: 1.1rem 1.2rem; }
.figure-tile,
.settings-card { transition: box-shadow .12s ease, transform .12s ease, border-color .12s ease; }
.figure-tile:hover,
.settings-card:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-raised);
}
.palette-box, .peek-body, .peek-card { box-shadow: var(--shadow-raised); }

/* Focus carries the accent, so keyboard travel is visible in the
   company's own colour. The outline stays for forced-colours modes. */
input:focus-visible, select:focus-visible, textarea:focus-visible,
button:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  box-shadow: var(--ring);
}

/* ---------------------------------------------------------- the slots
   Empty panels: a slot, not a wireframe. Softer dash, no fill, and the
   text does the explaining. */
.panel.is-empty, .card.is-empty {
  border-style: dashed;
  border-color: color-mix(in srgb, var(--border) 75%, transparent);
  border-radius: var(--radius-sm);
}

/* ------------------------------------------------------------ sign in
   The first screen anybody sees. One card, centred, the product's name
   above it and the maker beneath — a front door rather than a form that
   happens to be alone on a page. */
.auth-wrap {
  min-height: 62vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1rem;
}
.auth-card {
  width: 100%;
  max-width: 24rem;
  padding: 2rem 2rem 1.6rem;
  box-shadow: var(--shadow-raised);
  border-radius: var(--radius-lg);
}
.auth-card h1 { margin-bottom: .35rem; }
.auth-card .lede { color: var(--text-soft); font-size: var(--text-sm); margin-bottom: 1.25rem; }
.auth-card .btn-primary { width: 100%; padding: .6rem; font-size: 1rem; }

/* --------------------------------------------------------------- misc */
.footer { border-top: 0; padding-top: 2rem; }
.group-tabs { margin-top: -.25rem; }
.first-run { box-shadow: var(--shadow-raised); border-radius: var(--radius-lg); }

@media (max-width: 640px) {
  .line-sentence { font-size: 1.45rem; }
  h1 { font-size: 1.35rem; }
  .figure-value { font-size: 1.9rem; }
  .page-head { margin: 1rem 0 1.1rem; }
}

/* ============================================================== GRAPHICS
   Sparklines and comparison bars.

   Everything here is drawn by the server: inline SVG and a div with a width.
   No charting library, which would have been a fifth dependency for the sake
   of pictures the browser can already draw, and a second rendering path that
   breaks differently from the first.

   Two rules the shapes obey:

   * A shape never carries meaning alone. Every line has its direction in
     words beside it and every bar has its figure above it, so the page reads
     the same to somebody who cannot separate the hues or is looking at it
     printed.
   * A shape with nothing in it is not drawn. Empty tracks and flat lines
     read as something that failed to load, and they teach a person to stop
     looking at that part of the screen.
*/

.spark {
  display: flex;
  flex-direction: column;
  gap: .12rem;
  margin-top: .45rem;
  color: var(--text-faint);
}

.spark-line {
  width: 100%;
  height: 22px;
  display: block;
  overflow: visible;
}

.spark-change {
  font-size: .7rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}

/* The line takes the mood, the words stay readable. Rising is not good news
   and falling is not bad news — that depends entirely on the figure — so
   these are the accent and a neutral, never green and red. */
.spark-up   { color: var(--accent); }
.spark-down { color: var(--text-faint); }
.spark-level { color: var(--text-faint); }

/* A bar under a figure in the by-company table. Thin on purpose: the number
   is the answer and this only has to make four rows rankable at a glance. */
.cbar {
  display: block;
  height: 4px;
  margin-top: .3rem;
  border-radius: 2px;
  background: var(--surface-sunk, rgba(0, 0, 0, .06));
  overflow: hidden;
}

.cbar-fill {
  display: block;
  height: 100%;
  border-radius: 2px;
  min-width: 2px;
}

/* Stacked cards on a narrow screen put the figure and its bar side by side,
   where a full-width bar would push the number off its own row. */
@media (max-width: 700px) {
  .cbar { max-width: 120px; margin-left: auto; }
}

/* ============================================================== THE PAPER
   Tranche E: the 3p0 design language, translated for a working tool.

   The source is the company website: warm paper against near-black, serif
   display type, a drafting grid with numbered mono markers, one aurora
   gradient used sparingly. A site is read once, top to bottom; a CRM is
   scanned for hours. So the translation keeps the materials and refuses the
   drama — no alternating dark bands (every table would become a lighting
   change), no display type inside data, and the aurora appears exactly three
   times, always as a hairline, never as a surface.

   The ramps themselves changed at the top of this file: paper instead of
   cool grey, warm near-black chrome, warmed shadows. Everything below is
   what could not be done by changing a variable. */

/* -- the aurora, placement one: the edge where the chrome meets the page.
      This is the signature line of the whole product, and it is in the
      company's own colour because the chrome deliberately is not. */
.topbar::after {
  content: "";
  display: block;
  height: 2px;
  background: var(--aurora);
}

/* -- placement two: the sign-in card, which is the first thing anyone sees
      and the only page with no chrome to carry the line. */
.auth-card {
  border-top: 2px solid transparent;
  border-image: var(--aurora) 1;
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  background: var(--surface);
  border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: var(--shadow-raised);
  padding: 1.5rem 1.4rem;
}

/* -- placement three: a short rule above the maker's mark. The signature
      above the signature, and the only one at fixed width. */
.maker::before {
  content: "";
  display: block;
  width: 3rem;
  height: 2px;
  margin-bottom: .6rem;
  background: var(--aurora);
}
.footer .maker { display: block; }
.footer .maker .maker-name { margin-right: .7rem; }

/* -- the eyebrow becomes a drafting label: mono, tracked, small. It holds
      the company name over every page title, and a mono company name over a
      serif title is the two-tone pairing the site's display type does with
      size — voice against voice rather than weight against weight. */
.eyebrow {
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .14em;
}

/* -- numbered section markers on the morning page, straight from the site's
      drafting grid. Pure CSS counters: the templates do not know their own
      numbers, so a section added or removed renumbers the rest for free. */
.page { counter-reset: dash-section; }

.dash-section > h2 {
  display: flex;
  align-items: baseline;
  gap: .6rem;
}

.dash-section > h2::before {
  counter-increment: dash-section;
  content: counter(dash-section, decimal-leading-zero);
  font-family: var(--mono);
  font-size: .68rem;
  font-weight: 500;
  color: var(--text-faint);
  letter-spacing: .08em;
}

/* The hairline that carries the heading across the page, which is what makes
   a list of sections read as a drawing rather than a document. */
.dash-section > h2::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--border);
  transform: translateY(-.28em);
}

/* -- the morning verdict is the one sentence that matters, and it gets the
      display face at display size. Its colour keeps meaning elsewhere. */
.line-sentence {
  font-family: var(--display);
  font-size: var(--text-2xl);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* -- empty states in the serif's italic: a margin note, not an error. Most
      of a young workspace is empty state, so this is most of what a new
      company actually looks at. */
.empty,
.empty-lead {
  font-family: var(--display);
  font-style: italic;
  font-weight: 400;
}
.empty-lead { font-size: 1.05rem; }

/* Focused usability corrections: preserve the existing visual language. */
.skip-link { position: fixed; left: 1rem; top: -5rem; z-index: 100; padding: .75rem;
  background: var(--surface); color: var(--text); border: 2px solid var(--accent); }
.skip-link:focus { top: .5rem; }
.quick-add-tile { align-items: flex-start; }
.quick-add-tile h2 { margin: 0 0 .3rem; }
.quick-add-tile p { margin: 0; }
.palette-close { display: block; margin: .5rem .75rem .25rem auto; }
.palette-status { margin: .5rem 1rem; }
.palette-status:empty { display: none; }
.table-scroll { overflow-x: auto; }
.mobile-table-hint { display: none; }
@media (max-width: 719px) {
  .mobile-table-hint { display: block; margin: .5rem 0; }
  .btn, .topbar .btn-sm, .topbar .btn-quiet, .subnav a, .group-tabs a,
  .board-move select, .company-switcher select, .peek-trigger {
    min-height: 44px;
  }
  .peek-trigger { min-width: 44px; }
  .topbar-search input, .ask-bar input, .palette-input,
  .field input:not([type="checkbox"]):not([type="radio"]),
  .field select, .field textarea { font-size: 16px; }
  .topbar-search { flex: 1 1 calc(100% - 5rem); }
  .topbar-add { order: 4; }
  .topbar .company-mark { display: none; }
  .company-switcher { order: 0; flex: 1 1 calc(100% - 6rem); }
  .topbar-integration { order: 5; }
  .topbar-right { order: 6; flex: 1 1 100%; justify-content: space-between; }
  .board-move { gap: .5rem; }
  .ask-note { line-height: 1.45; }
  .ask-bar { flex-wrap: nowrap; }
  .ask-bar input[type="search"] { flex-basis: 0; }
}

/* ------------------------------------------------------ form accessibility */

/* A group of radios or checkboxes is a fieldset (partials/field.html) so its
   question is announced with every option. It keeps the look of an ordinary
   field rather than the boxed fieldset used for sections of a form. */
fieldset.field-group { border: 0; padding: 0; margin: 0 0 .85rem; min-width: 0; }
fieldset.field-group > legend { padding: 0; margin-bottom: .2rem; }

/* Help sits under an input at a small size, which needs the stronger of the
   two secondary inks: --text-faint measures 3.6:1 on a card, under the
   4.5:1 small text needs. */
.field .help { color: var(--text-soft); }

/* The error summary's lines are links to their fields; they keep the danger
   colour of the message rather than turning into ordinary accent links. */
.form-errors a { color: inherit; text-decoration: underline; }

/* --------------------------------------------------- activity composer
   At the top of a record's History card (contacts/_activity_composer.html).
   The kinds are real radio buttons, drawn as chips: the input stays in the
   accessibility tree and in the tab order, only its circle is hidden. */
.composer { border-bottom: 1px solid var(--border); padding-bottom: 1rem; margin-bottom: 1rem; }
.composer-kinds { border: 0; padding: 0; margin: 0 0 .75rem; display: flex; flex-wrap: wrap; gap: .4rem; min-width: 0; }
.chip-choice { position: relative; margin: 0; font-weight: 500; }
.chip-choice input {
  position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0;
}
.chip-choice span {
  display: inline-block;
  min-height: 44px;             /* a thumb-sized target on a phone */
  line-height: 1.2;
  padding: .75rem .9rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
}
.chip-choice input:checked + span {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
.chip-choice input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (min-width: 720px) {
  .chip-choice span { min-height: 0; padding: .35rem .8rem; }
}
.composer .more-details { margin-top: .25rem; }

/* The activity form's "When" is a datetime-local input, which the shared
   input rule above did not list, so it was the one unstyled box on the page. */
input[type="datetime-local"] {
  width: 100%;
  padding: .5rem .6rem;
  font: inherit;
  font-size: .95rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
}

/* An inline edit the server refused, or that never reached it: the old value
   is back and the cell says so, until the next attempt (static/js/crm.js). */
td.is-failed { background: var(--danger-soft); }
.inline-failed {
  display: block;
  margin-top: .2rem;
  color: var(--danger);
  font-size: var(--text-xs);
  font-weight: 600;
}

/* ------------------------------------------------------------------ links
   Colour alone does not mark a link for everyone (WCAG 1.4.1). A plain link
   — one without a class of its own, so not a button, tab, tile or card —
   underlines on keyboard focus as it already did on hover, and is always
   underlined where it sits inside running text. Styled links (.btn,
   .card-link, tiles) keep their own affordances. */
a:not([class]):focus-visible { text-decoration: underline; }
p a:not([class]),
dd a:not([class]),
li.message a:not([class]),
.callout a:not([class]),
.timeline-detail a:not([class]) {
  text-decoration: underline;
  text-underline-offset: .15em;
}

/* ------------------------------------------------------------ motion
   Somebody who has asked their system for less motion gets none: no
   transitions, no animations, no smooth scrolling. State changes still
   happen, instantly. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
