/* CostAnchor — interface.
 *
 * NO WEB FONTS, EVER (§2). The system stack only. This is inherited from
 * SiteAnchor, where the reason was that a fetched typeface would undo
 * offline-first for the whole interface. It holds here for the same
 * reason and one more: a commercial figure rendered in a fallback font
 * because a font request failed is a figure somebody misreads.
 *
 * Colours are all tokens, defined once on :root and redefined for dark.
 * Money gets its own tokens because over and under budget must be
 * distinguishable at a glance and must not rely on colour alone — the
 * sign and the word are always present too.
 */

:root {
  color-scheme: light;

  --bg: #f6f6f4;
  --surface: #ffffff;
  --surface-2: #f0f0ed;
  --border: #d8d8d2;
  --border-strong: #b4b4ac;

  --text: #1a1a18;
  --text-dim: #5d5d56;
  --text-faint: #8a8a82;

  --accent: #1f5f4f;
  --accent-text: #ffffff;
  --accent-dim: #e3efeb;

  /* Commercial state. Over budget is not "bad red" — it is a fact, and
   * it sits beside a figure that may be entirely expected. */
  --over: #a3352b;
  --over-bg: #fbeceb;
  --under: #1f6b45;
  --under-bg: #e8f4ed;
  --warn: #8a6116;
  --warn-bg: #fbf2df;
  /* Not recorded. Deliberately grey and never zero-coloured: a blank is
   * never a zero (§12), and it must not read as one. */
  --unknown: #6f6f68;
  --unknown-bg: #eeeeea;

  --radius: 6px;
  --gap: 12px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* Figures line up in a column or they cannot be compared. */
  --mono: ui-monospace, "Cascadia Mono", "Segoe UI Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #16171a;
    --surface: #1e2024;
    --surface-2: #26282d;
    --border: #34373d;
    --border-strong: #4a4e56;

    --text: #e9e9e6;
    --text-dim: #a6a8a4;
    --text-faint: #7a7d79;

    --accent: #4fb597;
    --accent-text: #10221d;
    --accent-dim: #1d332d;

    --over: #e88478;
    --over-bg: #33201e;
    --under: #6fc79c;
    --under-bg: #17291f;
    --warn: #d9ac5c;
    --warn-bg: #2e2718;
    --unknown: #9a9c98;
    --unknown-bg: #26282d;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #16171a;
  --surface: #1e2024;
  --surface-2: #26282d;
  --border: #34373d;
  --border-strong: #4a4e56;
  --text: #e9e9e6;
  --text-dim: #a6a8a4;
  --text-faint: #7a7d79;
  --accent: #4fb597;
  --accent-text: #10221d;
  --accent-dim: #1d332d;
  --over: #e88478;
  --over-bg: #33201e;
  --under: #6fc79c;
  --under-bg: #17291f;
  --warn: #d9ac5c;
  --warn-bg: #2e2718;
  --unknown: #9a9c98;
  --unknown-bg: #26282d;
}

* { box-sizing: border-box; }

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

/* ---- shell ---- */

#app { min-height: 100vh; display: flex; flex-direction: column; }

header.app-bar {
  display: flex; align-items: center; gap: var(--gap);
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 10;
}

.app-bar h1 { font-size: 16px; margin: 0; font-weight: 650; letter-spacing: -0.01em; }
.app-bar .spacer { flex: 1; }

nav.tabs {
  display: flex; gap: 4px; padding: 0 12px;
  background: var(--surface); border-bottom: 1px solid var(--border);
  overflow-x: auto;
}

nav.tabs button {
  background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--text-dim); font: inherit; font-size: 14px;
  /* Sized for a hand, not a mouse pointer. Enforced by test. */
  padding: 10px 14px; min-height: 44px; cursor: pointer; white-space: nowrap;
}
nav.tabs button[aria-current="page"] { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }

main { flex: 1; padding: 16px; max-width: 1100px; width: 100%; margin: 0 auto; }

/* ---- blocks ---- */

.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px; margin-bottom: var(--gap);
}
.card h2 { margin: 0 0 10px; font-size: 15px; font-weight: 650; }
.card h3 { margin: 14px 0 6px; font-size: 13px; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.04em; }

.row { display: flex; gap: var(--gap); align-items: center; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.grid { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.muted { color: var(--text-dim); }
.faint { color: var(--text-faint); font-size: 13px; }
.small { font-size: 13px; }

/* ---- figures ---- */

/* A money value never wraps. Broken across two lines the currency symbol
 * separates from its number, and a column of figures stops lining up —
 * which is the only reason the column exists. */
.figure { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.figure.over { color: var(--over); }
.figure.under { color: var(--under); }
/* Never a zero. Reads "not recorded" and looks like nothing else. */
.figure.unknown { color: var(--unknown); font-family: var(--font); font-style: italic; }

.basis { color: var(--text-faint); font-size: 12px; margin-left: 4px; }

/* ---- controls ---- */

button, .button {
  font: inherit; font-size: 14px;
  padding: 9px 14px; min-height: 44px;
  border-radius: var(--radius); border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text); cursor: pointer;
}
button:hover { background: var(--surface-2); }
button.primary { background: var(--accent); color: var(--accent-text); border-color: var(--accent); font-weight: 600; }
button.primary:hover { filter: brightness(1.08); }
button:disabled { opacity: 0.5; cursor: not-allowed; }

label { display: block; font-size: 13px; color: var(--text-dim); margin-bottom: 4px; }
.field { margin-bottom: var(--gap); }

input, select, textarea {
  font: inherit; font-size: 15px; width: 100%;
  padding: 9px 10px; min-height: 44px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text);
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
input.money { font-family: var(--mono); text-align: right; }

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

.table-wrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 14px; }
th, td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); }
th { font-weight: 600; color: var(--text-dim); font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; }
td.num, th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
tbody tr:hover { background: var(--surface-2); }

/* ---- notices ---- */

.notice { padding: 10px 12px; border-radius: var(--radius); font-size: 14px; margin-bottom: var(--gap); border: 1px solid transparent; }
.notice.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn); }
.notice.over { background: var(--over-bg); color: var(--over); border-color: var(--over); }
.notice.ok { background: var(--under-bg); color: var(--under); border-color: var(--under); }
.notice.info { background: var(--accent-dim); color: var(--text); border-color: var(--accent); }
.notice.unknown { background: var(--unknown-bg); color: var(--unknown); border-color: var(--border-strong); }

.pill { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px; background: var(--surface-2); color: var(--text-dim); border: 1px solid var(--border); }

.empty { padding: 32px 16px; text-align: center; color: var(--text-dim); }

/* ---- project list ---- */

.project { display: block; width: 100%; text-align: left; margin-bottom: 8px; padding: 14px; }
.project .code { font-family: var(--mono); font-size: 12px; color: var(--text-faint); }
.project .name { font-size: 15px; font-weight: 600; display: block; margin-top: 2px; }

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

.test-pass { color: var(--under); }
.test-fail { color: var(--over); font-weight: 600; }
#results { font-family: var(--mono); font-size: 13px; white-space: pre-wrap; }

/* ---- dashboard (§10) ----
 *
 * "Leads with the commercial position, not with counts."
 *
 * The headline is three figures and nothing else competes with them. The
 * variance concentration sits immediately beneath, because §10 rules that
 * a variance which does not show where it is concentrated invites the
 * wrong conversation.
 *
 * Direction is never carried by colour alone. Every figure that can be
 * over or under also states the word, so the screen survives being read
 * by somebody who cannot separate the two hues, printed in grey, or
 * glanced at in sunlight.
 */

.headline { display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }

.headline .tile { padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.headline .tile .label { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-dim); }
.headline .tile .value { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 24px; margin-top: 4px; line-height: 1.15; }
.headline .tile .value.unknown { font-family: var(--font); font-style: italic; font-size: 17px; color: var(--unknown); }
.headline .tile .sub { font-size: 13px; margin-top: 4px; color: var(--text-dim); }

.tile.over { border-color: var(--over); background: var(--over-bg); }
.tile.over .value, .tile.over .sub { color: var(--over); }
.tile.under { border-color: var(--under); background: var(--under-bg); }
.tile.under .value, .tile.under .sub { color: var(--under); }

/* Secondary position figures. Smaller, but still money, so still mono. */
.position { display: grid; gap: 2px 18px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.position .line { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; border-bottom: 1px solid var(--border); }
.position .line .k { color: var(--text-dim); font-size: 14px; }
.position .line .v { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 14px; white-space: nowrap; }

/* Variance concentration. The bar is a proportion, never a value — it
 * shows share of the overrun and is labelled as such. */
.concentration .row { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: baseline; margin-bottom: 10px; }
.concentration .name { font-size: 14px; }
.concentration .amount { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 14px; color: var(--over); }
.concentration .track { grid-column: 1 / -1; height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.concentration .fill { height: 100%; background: var(--over); border-radius: 3px; }
.concentration .lead { font-size: 14px; margin-bottom: 12px; }

/* Alerts. Each names what it counts and links to the packages behind it —
 * a count with nothing to open is a number somebody has to chase by hand. */
.alert { display: flex; gap: 10px; align-items: baseline; padding: 9px 12px; border-radius: var(--radius); margin-bottom: 6px; border: 1px solid transparent; font-size: 14px; }
.alert .count { font-family: var(--mono); font-weight: 650; }
.alert.over { background: var(--over-bg); color: var(--over); border-color: var(--over); }
.alert.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn); }
.alert.unknown { background: var(--unknown-bg); color: var(--unknown); border-color: var(--border-strong); }

/* The package table's variance column. */
td.over { color: var(--over); }
td.under { color: var(--under); }
td.unknown { color: var(--unknown); font-family: var(--font); font-style: italic; }

/* ---- typed inputs ---- */

/* The currency sits beside the box, never inside it. Every monetary value
 * carries its currency (§12), and one parsed out of free text is one that
 * can be wrong. */
.money-field { display: flex; align-items: stretch; gap: 0; }
.money-field .ccy {
  display: flex; align-items: center; padding: 0 10px;
  border: 1px solid var(--border-strong); border-right: none;
  border-radius: var(--radius) 0 0 var(--radius);
  background: var(--surface-2); color: var(--text-dim);
  font-family: var(--mono); font-size: 13px; white-space: nowrap;
}
.money-field input { border-radius: 0 var(--radius) var(--radius) 0; }
.money-field .ccy + input { border-left: 1px solid var(--border-strong); }
.money-field .basis {
  display: flex; align-items: center; padding-left: 8px;
  font-size: 12px; color: var(--text-faint); white-space: nowrap;
}
.money-field input:only-child,
.money-field input:first-child { border-radius: var(--radius) 0 0 var(--radius); }

button.link {
  background: none; border: none; padding: 0; min-height: 0;
  color: var(--accent); font: inherit; font-size: 14px; cursor: pointer;
}
button.link:hover { background: none; text-decoration: underline; }

.form-grid { display: grid; gap: 0 18px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

.record-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 4px; }
.record-head .code { font-family: var(--mono); font-size: 12px; color: var(--text-faint); }

/* A row that opens something. */
tr.openable { cursor: pointer; }
tr.openable:hover { background: var(--surface-2); }

/* The audit trail on a record. */
.trail { font-size: 13px; }
.trail .entry { padding: 7px 0; border-bottom: 1px solid var(--border); }
.trail .when { color: var(--text-faint); font-size: 12px; }

/* ---- import review and reconciliation (§11) ---- */

/* A match confidence, and a row the report disagrees on. Coloured with
 * the same three tones the rest of the application uses, so "this is a
 * problem" looks the same here as it does on the dashboard. */
.pill.ok { background: var(--under-bg); color: var(--under); border-color: var(--under); }
.pill.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn); }
.pill.over { background: var(--over-bg); color: var(--over); border-color: var(--over); }

tr.flagged { background: var(--over-bg); }
tr.flagged td { color: var(--over); }
