/* ── MediaKind brand font (museo-sans via Adobe TypeKit) ──── */
@import url("https://use.typekit.net/jwa3aeq.css");

/* ── Reset & Base ─────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --bg: #f4f5f7;
  --surface: #ffffff;
  --border: #dde1e7;
  --border-strong: #b0b8c4;
  --text: #1a1d23;
  --text-muted: #6b7280;
  --accent: #004F89;        /* MediaKind deep blue — matches the logo wordmark */
  --brand-cyan: #009FE3;    /* logo secondary */
  --brand-crimson: #D4103A; /* logo asterisk */
  --accent-hover: #003a6e;
  --danger: #dc2626;
  --actual-bg: #f0f9ff;
  --forecast-bg: #fffbeb;
  --quarter-bg: #f0f9ff;
  --fy-bg: #fffbeb;
  --total-bg: #f1f5f9;
  --prior-bg: #f0f9ff;
  --growth-pos: #16a34a;
  --growth-warn: #ca8a04;
  --growth-neg: #dc2626;
  --highlight: #fef08a;
  --header-h: 56px;
}

body {
  font-family: museo-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  font-size: 13px;
  font-weight: 300;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
}

.hidden { display: none !important; }

/* ── Login Page ───────────────────────────────────────────── */
body.login-page {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  /* Faint wash of the two blues so the page isn't a flat grey field. Large,
     low-opacity and behind everything, so it reads as depth rather than decoration. */
  background:
    radial-gradient(1100px 620px at 12% -8%, rgba(0, 159, 227, .10), transparent 60%),
    radial-gradient(900px 540px at 92% 108%, rgba(0, 79, 137, .10), transparent 60%),
    var(--bg);
}

.login-card {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 40px 44px 36px;
  width: 100%;
  max-width: 400px;
  box-shadow: 0 10px 40px rgba(0, 31, 56, .10), 0 2px 6px rgba(0, 31, 56, .05);
}

/* The three logo colours as a hairline across the top of the card. */
.login-brandbar {
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(
    90deg,
    var(--accent) 0%,
    var(--accent) 34%,
    var(--brand-cyan) 34%,
    var(--brand-cyan) 67%,
    var(--brand-crimson) 67%
  );
}

.login-head { text-align: center; }

.login-logo {
  height: 30px;
  width: auto;
  display: block;
  margin: 0 auto 22px;
}

.login-card h1 {
  font-size: 23px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--accent);
  margin-bottom: 5px;
}

.login-tagline {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-muted);
  letter-spacing: .04em;
  text-transform: uppercase;
  margin-bottom: 30px;
}

.sso-btn {
  display: block;
  padding: 12px 16px;
  background: var(--accent);
  color: #fff;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  transition: background .15s ease, box-shadow .15s ease, transform .15s ease;
}

.sso-btn:hover {
  background: var(--accent-hover);
  box-shadow: 0 6px 16px rgba(0, 79, 137, .22);
}

.sso-btn:active { transform: translateY(1px); }

/* Keyboard users get the same affordance as the hover state, plus a ring. */
.sso-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(0, 159, 227, .45);
}

.login-foot {
  margin-top: 16px;
  text-align: center;
  font-size: 11.5px;
  color: var(--text-muted);
}

.error { color: var(--danger); font-size: 13px; line-height: 1.5; }

#login-error,
#sso-unavailable { margin-bottom: 18px; text-align: center; }

#sso-unavailable { margin-bottom: 0; }

@media (max-width: 420px) {
  .login-card { padding: 32px 24px 28px; }
}

/* ── Header ───────────────────────────────────────────────── */
header {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-h);
  padding: 0 20px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 4px rgba(0,0,0,.06);
}

/* ── View tab switcher ─────────────────────────────────────── */
#view-tabs { display: flex; align-items: center; gap: 4px; }

.tab-btn {
  padding: 6px 14px;
  border-radius: 6px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
}
.tab-btn.active { background: var(--accent); color: #fff; }
.tab-btn:hover:not(.active) { background: var(--bg); color: var(--text); }

/* ── SPA iframes (Claude / Github Analytics) ──────────────── */
#analytics-frame,
#github-frame {
  display: none;
  position: fixed;
  top: var(--header-h);
  left: 0; right: 0; bottom: 0;
  width: 100%;
  height: calc(100vh - var(--header-h));
  border: none;
}

header h1 { font-size: 16px; font-weight: 700; color: var(--accent); white-space: nowrap; }
/* margin-right:auto rather than space-between on <header>: the revenue-only
   action group is display:none on the other tabs, and the user menu has to
   stay pinned right either way. */
.header-left { display: flex; align-items: center; gap: 12px; margin-right: auto; min-width: 0; }
.header-logo { height: 22px; width: auto; display: block; }


.header-right { display: flex; align-items: center; gap: 8px; }
.header-right .btn-primary,
.header-right .btn-secondary,
.header-right .btn-ghost {
  padding: 5px 10px;
  font-size: 11px;
  white-space: nowrap; /* two-line buttons were making the bar look broken */
}
.tab-btn { white-space: nowrap; }

/* ── User menu ────────────────────────────────────────────── */
.user-menu { position: relative; margin-left: 12px; flex: none; }
.user-chip {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 8px 3px 3px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  cursor: pointer;
  font: inherit;
}
.user-chip:hover,
.user-chip[aria-expanded="true"] { background: var(--bg); border-color: var(--border-strong); }
.user-initials {
  display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 700; letter-spacing: .02em;
}
.user-name {
  max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 11px; color: var(--text-muted);
}
.user-menu-panel {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 150;
  min-width: 220px; max-width: calc(100vw - 20px); padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.14);
  display: flex; flex-direction: column;
}
.user-menu-email {
  padding: 6px 10px 8px; margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
  font-size: 11px; color: var(--text-muted); overflow-wrap: anywhere;
}
.user-menu-item {
  padding: 7px 10px; border: none; border-radius: 6px;
  background: none; text-align: left; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--text);
}
.user-menu-item:hover,
.user-menu-item:focus-visible { background: var(--bg); outline: none; }

/* ── System Info (admin-only) ─────────────────────────────── */
.system-info { display: flex; flex-direction: column; gap: 14px; max-height: 65vh; overflow-y: auto; }
.system-section h3 { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--accent); margin: 0 0 4px; }
.system-row { display: flex; justify-content: space-between; gap: 16px; padding: 4px 0; border-bottom: 1px solid var(--border); font-size: 12px; }
.system-label { color: var(--text-muted); flex: none; }
.system-value { text-align: right; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.system-value--ok  { color: var(--growth-pos); font-weight: 600; }
.system-value--off { color: var(--text-muted); }
.system-value--bad { color: var(--danger); font-weight: 600; }

/* ── Buttons ──────────────────────────────────────────────── */
.btn-primary {
  padding: 7px 14px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.btn-primary:hover { background: var(--accent-hover); }

.btn-secondary {
  padding: 7px 14px;
  background: var(--surface);
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.btn-secondary:hover { background: #e8f4fb; }

.btn-ghost {
  padding: 7px 14px;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
}
.btn-ghost:hover { background: var(--bg); }

.btn-danger {
  padding: 7px 14px;
  background: #fee2e2;
  color: var(--danger);
  border: 1px solid #fca5a5;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.btn-danger:hover { background: #fecaca; }

/* ── Charts ───────────────────────────────────────────────── */
#charts {
  padding: 16px 20px 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.chart-card--wide { grid-column: 1 / -1; }

.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 20px 14px;
  box-shadow: 0 1px 3px rgba(0,0,0,.04);
  min-width: 0;
}

.chart-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  gap: 12px;
  flex-wrap: wrap;
}

.chart-header h2 {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  text-transform: uppercase;
  letter-spacing: .06em;
}

.chart-subtitle {
  font-weight: 500;
  color: var(--text-muted);
  text-transform: none;
  letter-spacing: 0;
  font-size: 11px;
}

.chart-legend {
  display: flex;
  gap: 14px;
  font-size: 11px;
  color: var(--text-muted);
}

.legend-item { display: flex; align-items: center; gap: 6px; }

.legend-line {
  display: inline-block;
  width: 22px;
  height: 2px;
  background: var(--accent);
  border-radius: 1px;
}

.legend-line.dashed {
  background: #009FE3;
}

.legend-line.trend {
  background: transparent;
  border-top: 2px dashed #f59e0b;
  height: 0;
}

.legend-line.margin-pct {
  background: transparent;
  border-top: 2px solid #16a34a;
  height: 0;
}

.chart-canvas-wrap {
  position: relative;
  height: 220px;
}

.chart-canvas-wrap--tall {
  height: 320px;
}

.chart-canvas-wrap--dev-subs {
  height: 300px;
}

.chart-canvas-wrap canvas {
  position: absolute;
  inset: 0;
}

/* ── Table Container ──────────────────────────────────────── */
#table-container {
  overflow-x: auto;
  padding: 20px;
}

#table-toolbar {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-bottom: 10px;
}
#table-toolbar .btn-ghost {
  padding: 4px 10px;
  font-size: 11px;
}

/* Collapsed monthly view: hide every per-month cell in the current year
   (header + data + totals + YoY). Q1A/Q2A rollups, the Actuals summary
   cell, and Q2/Q3/Q4 forecast-quarter cells remain so the table still
   adds up across the year. */
body.months-hidden #revenue-table th.col-month,
body.months-hidden #revenue-table td.cell-month:not(.cell-forecast-quarter) { display: none; }

/* prior-hidden: hides the entire prior-year group (Q1–Q4 + FY header cols and all cell-prior cells) */
body.prior-hidden #revenue-table th.prior,
body.prior-hidden #revenue-table td.cell-prior { display: none; }

#loading { color: var(--text-muted); padding: 40px; text-align: center; }

/* ── Revenue Table ────────────────────────────────────────── */
#revenue-table {
  border-collapse: collapse;
  white-space: nowrap;
  font-size: 12px;
  min-width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

#revenue-table th,
#revenue-table td {
  padding: 5px 8px;
  border: 1px solid var(--border);
  text-align: right;
}

/* Left label columns */
th.col-bu, td.col-bu {
  text-align: left;
  font-weight: 700;
  font-size: 11px;
  background: #f8fafc;
  min-width: 110px;
  max-width: 130px;
  white-space: normal;
  vertical-align: middle;
}


th.col-customer, td.col-customer {
  text-align: left;
  min-width: 160px;
  max-width: 200px;
  font-weight: 500;
  cursor: pointer;
  position: sticky;
  left: 0;
  z-index: 5;
  background: var(--surface);
}
/* Region / Product — reference attributes, not figures. Kept deliberately
   small and muted so they don't compete with the revenue columns. */
th.col-attr-hdr {
  font-weight: 600;
  font-size: 9px;
  color: var(--text-muted);
  letter-spacing: .04em;
  text-align: left;
  padding-left: 8px;
}
td.col-attr {
  font-size: 9.5px;
  line-height: 1.25;
  color: var(--text-muted);
  vertical-align: middle;
  padding: 2px 6px;
  text-align: left;
  white-space: normal;
}
td.col-attr-region {
  width: 46px;
  min-width: 46px;
  max-width: 46px;
  text-transform: uppercase;
  letter-spacing: .03em;
}
td.col-attr-product {
  width: 74px;
  min-width: 74px;
  max-width: 74px;
}
.product-chip {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.product-chip + .product-chip { margin-top: 1px; }

/* Sticky on totals / yoy rows: pick up row-level background colors. */
tr.totals-row td.col-customer { background: var(--total-bg); }
tr.grand-totals-row td.col-customer { background: #192639; }
tr.yoy-row td.col-customer { background: #f0fdf4; }
tr.at-risk td.col-customer { background-color: #fff5f5; }
tr.declining td.col-customer { background-color: #fef9c3; }
td.col-customer:hover { text-decoration: underline; color: var(--accent); }

/* Column groups */
th.group-header {
  text-align: center;
  font-weight: 700;
  font-size: 11px;
  letter-spacing: .05em;
  text-transform: uppercase;
  background: #d5eaf6;
  color: #004F89;
  border-bottom: 2px solid #009FE3;
}

#revenue-table th.group-header-year {
  font-size: 14px;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  padding: 8px 12px;
}

th.group-header.prior {
  background: #edf2f7;
  color: #4a5568;
  border-bottom: 2px solid var(--border-strong);
}

th.col-month { min-width: 52px; font-weight: 500; font-size: 11px; }
th.col-quarter { min-width: 60px; font-weight: 700; background: var(--quarter-bg); }
th.col-fy { min-width: 68px; font-weight: 700; background: var(--fy-bg); }
th.col-yoy { min-width: 64px; font-weight: 700; background: #f0fdf4; color: var(--growth-pos); }
th.col-cloud-hdr { min-width: 44px; font-weight: 600; color: var(--text-muted); font-size: 10px; letter-spacing: .04em; }
td.col-cloud { padding: 2px 6px; vertical-align: middle; text-align: center; }
.cloud-badge { display: inline-block; padding: 2px 6px; border-radius: 4px; font-size: 10px; font-weight: 700; letter-spacing: .03em; white-space: nowrap; }
.cloud-badge--mk { background: #cffafe; color: #0e7490; }
.cloud-badge--cc { background: #ede9fe; color: #6d28d9; }
.cloud-badge--aws { background: #fef3c7; color: #92400e; }
th.col-sparkline-hdr { min-width: 88px; font-weight: 600; color: var(--text-muted); font-size: 10px; letter-spacing: .04em; }
td.col-sparkline { padding: 2px 6px; vertical-align: middle; }

/* Data cells */
td.cell-month,
td.cell-prior.cell-quarter,
td.cell-prior.cell-fy,
td.cell-actuals-summary,
td.cell-actuals-quarter { position: relative; }

.cell-val { display: block; text-align: right; }

.cell-margin-hint {
  position: absolute;
  bottom: 1px;
  right: 3px;
  font-size: 8px;
  line-height: 1;
  pointer-events: none;
  opacity: 0.75;
  font-weight: 600;
  letter-spacing: .01em;
}
.cell-margin-hint.positive { color: var(--growth-pos); }
.cell-margin-hint.warning  { color: var(--growth-warn); }
.cell-margin-hint.negative { color: var(--growth-neg); }

td.cell-month { cursor: pointer; }
td.cell-month:hover { background: #cce8f7; }
td.cell-month.is-actual { background: var(--actual-bg); font-weight: 500; }
td.cell-month.is-forecast { background: var(--forecast-bg); font-style: italic; color: var(--text-muted); }
td.cell-month.editing {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  background: #cce8f7 !important;
}

td.cell-quarter { background: var(--actual-bg); font-weight: 600; }
td.cell-fy { background: var(--forecast-bg); font-weight: 700; }
td.cell-prior { background: var(--actual-bg); color: var(--text-muted); }
td.cell-prior.cell-quarter { background: var(--actual-bg); }
td.cell-prior.cell-fy { background: var(--actual-bg); font-weight: 700; }
td.cell-yoy { font-weight: 600; }
td.cell-yoy.positive { color: var(--growth-pos); }
td.cell-yoy.negative { color: var(--growth-neg); }

td.cell-predict { background: var(--forecast-bg); font-weight: 700; cursor: help; }
td.cell-predict.positive { color: var(--growth-pos); }
td.cell-predict.negative { color: var(--growth-neg); }
td.cell-predict .conf-dot { font-size: 9px; margin-right: 3px; vertical-align: middle; }

/* At-risk customers (YoY ≤ -15% with prior baseline > 0) */
tr.at-risk td.col-customer { box-shadow: inset 3px 0 0 #dc2626; }
tr.at-risk td { background-color: #fff5f5; }
tr.at-risk td.cell-prior { background-color: #faeae6; }
tr.at-risk td.cell-prior.cell-quarter { background-color: #f5e0dc; }
tr.at-risk td.cell-prior.cell-fy { background-color: #f0d4ce; }
tr.at-risk td.cell-quarter { background-color: #fde8e8; }
tr.at-risk td.cell-fy { background-color: #fbdada; }

tr.declining td.col-customer { box-shadow: inset 3px 0 0 #d97706; }
tr.declining td:nth-child(-n+4) { background-color: #fef9c3; }
.at-risk-badge {
  display: inline-block;
  margin-left: 6px;
  color: #dc2626;
  font-size: 12px;
  cursor: help;
}

/* History modal */
.history-list { max-height: 60vh; overflow-y: auto; font-size: 12px; }
.history-row {
  display: grid;
  grid-template-columns: 130px 110px 1fr 110px;
  gap: 10px;
  padding: 6px 4px;
  border-bottom: 1px solid #f1f5f9;
  align-items: baseline;
}
.history-row:last-child { border-bottom: none; }
.history-when { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.history-who { font-weight: 600; }
.history-what { color: #334155; }
.history-cust { font-weight: 600; }
.history-delta { text-align: right; font-variant-numeric: tabular-nums; }
.history-delta .from { color: var(--text-muted); text-decoration: line-through; }
.history-delta .arrow { color: var(--text-muted); margin: 0 4px; }
.history-delta .to.up { color: var(--growth-pos); font-weight: 600; }
.history-delta .to.down { color: var(--growth-neg); font-weight: 600; }
.history-delta .toggle { color: #009FE3; font-style: italic; }
.history-empty { padding: 24px; text-align: center; color: var(--text-muted); }

/* Actuals / Forecast summary columns */
th.cell-actuals-hdr { background: var(--actual-bg); font-weight: 700; }
th.cell-forecast-hdr { background: var(--forecast-bg); font-weight: 700; }
td.cell-actuals-summary { background: var(--actual-bg); font-weight: 600; }
td.cell-forecast-summary { background: var(--forecast-bg); font-weight: 600; }

/* Actual-quarter rollup cells — revenue + inline YoY % */
td.cell-actuals-quarter { border-left: 2px solid #818cf8; }
.q1a-rev  { display: block; text-align: center; }

/* Margin column */
th.col-margin-hdr { min-width: 64px; font-weight: 700; background: #fef3c7; color: #b45309; }
td.cell-margin { font-weight: 600; font-variant-numeric: tabular-nums; }
td.cell-margin.positive { color: var(--growth-pos); }
td.cell-margin.warning  { color: var(--growth-warn); }
td.cell-margin.negative { color: var(--growth-neg); }
td.cell-margin.muted { color: var(--text-muted); font-weight: 400; }
tr.at-risk td.cell-margin { background-color: #fbdada; }

/* Company logo in customer name cell */
img.cust-logo {
  width: 16px;
  height: 16px;
  object-fit: contain;
  vertical-align: middle;
  margin-right: 5px;
  border-radius: 2px;
  flex-shrink: 0;
}

/* Expand chevron in customer name cell */
.expand-chevron {
  display: inline-block;
  width: 13px;
  font-size: 8px;
  color: var(--text-muted);
  cursor: pointer;
  margin-right: 5px;
  user-select: none;
  vertical-align: middle;
  line-height: 1;
}
.expand-chevron:hover { color: var(--accent); }
td.col-customer:hover .expand-chevron { color: var(--accent); }

/* Per-customer margin detail row */
.margin-detail-row > td {
  padding: 6px 12px 8px 28px;
  background: #f8faff;
  border-bottom: 1px solid var(--border);
}
.detail-table {
  border-collapse: collapse;
  font-size: 11px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.detail-table td { padding: 2px 8px; text-align: right; }
.detail-table td.detail-row-label {
  text-align: left;
  padding-right: 12px;
  color: var(--text-muted);
  font-weight: 500;
}
.detail-month-hdr {
  font-weight: 600;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  font-size: 10px;
  letter-spacing: .03em;
}
.detail-month-hdr.forecast { font-style: italic; color: #94a3b8; }
.detail-val.forecast { color: var(--text-muted); font-style: italic; }
.detail-val.actual { color: var(--text); }
.detail-month-hdr.detail-fy-hdr { border-left: 2px solid var(--border); font-weight: 700; color: var(--text); }
.detail-val.detail-fy { border-left: 2px solid var(--border); font-weight: 600; }
tr.detail-year-sep { border-top: 1px solid var(--border); }
td.detail-year-label {
  text-align: left;
  font-weight: 700;
  font-size: 10px;
  letter-spacing: .05em;
  color: var(--text-muted);
  padding: 4px 0 1px;
  text-transform: uppercase;
}
.detail-val.detail-cost { color: #b45309; }
.detail-val.detail-margin.positive { color: var(--growth-pos); font-weight: 600; }
.detail-val.detail-margin.warning  { color: var(--growth-warn); font-weight: 600; }
.detail-val.detail-margin.negative { color: var(--growth-neg); font-weight: 600; }
.detail-val.detail-margin.muted { color: var(--text-muted); }
tr.at-risk + .margin-detail-row > td { background: #fff8f8; }

/* Subscriptions modal */
.subs-filter {
  width: 100%;
  padding: 6px 10px;
  margin-bottom: 8px;
  font-size: 13px;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
}
.subs-list { max-height: 60vh; overflow-y: auto; font-size: 12px; }
.subs-row {
  display: grid;
  grid-template-columns: 1fr 80px 170px 200px;
  gap: 8px;
  align-items: start;
  padding: 6px 4px;
  border-bottom: 1px solid #f1f5f9;
}
.subs-tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  min-height: 24px;
}
.subs-pill {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px 4px 2px 8px;
  background: #d5eaf6;
  color: #004F89;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  line-height: 1.4;
}
.subs-pill-x {
  background: none;
  border: none;
  color: #004F89;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0 4px;
  border-radius: 50%;
}
.subs-pill-x:hover { background: rgba(0, 79, 137, 0.15); }
.subs-add-btn {
  padding: 2px 8px;
  background: white;
  border: 1px dashed #94a3b8;
  border-radius: 12px;
  color: var(--text-muted);
  font-size: 11px;
  cursor: pointer;
  line-height: 1.4;
}
.subs-add-btn:hover { border-color: #009FE3; color: #009FE3; }

.subs-add-popover {
  z-index: 1000;
  width: 240px;
  max-height: 320px;
  background: white;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.subs-add-search {
  padding: 7px 10px;
  border: none;
  border-bottom: 1px solid #e2e8f0;
  font-size: 12px;
  outline: none;
}
.subs-add-list { overflow-y: auto; max-height: 280px; }
.subs-add-item {
  padding: 6px 10px;
  font-size: 12px;
  cursor: pointer;
}
.subs-add-item:hover { background: #e8f4fb; }
.subs-add-empty {
  padding: 12px;
  color: var(--text-muted);
  font-size: 11px;
  text-align: center;
}
.subs-row:last-child { border-bottom: none; }
.subs-row.unmapped       { background: #fffbea; }
.subs-row.mktv           { background: #f3e8ff; }
.subs-row.harmonic       { background: #eef2ff; }
.subs-row.opex-dev       { background: #ecfeff; }
.subs-row.opex-presales  { background: #fdf2f8; }
.subs-name { font-family: ui-monospace, Menlo, monospace; font-size: 11px; word-break: break-all; }
.subs-cost { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-muted); }
.subs-select, .subs-cat-select {
  padding: 4px 6px;
  font-size: 12px;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
  background: white;
  width: 100%;
}

/* BU separator rows */
#revenue-table tr.bu-header-row td {
  background: #192639;
  color: #fff;
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  padding: 6px 8px;
  text-align: left;
}

/* Totals rows */
tr.totals-row td {
  background: var(--total-bg);
  font-weight: 700;
  border-top: 2px solid var(--border-strong);
}

tr.grand-totals-row td {
  background: #192639;
  color: #fff;
  font-weight: 700;
  border-top: 2px solid #009FE3;
}

tr.yoy-row td {
  background: #f0fdf4;
  color: var(--growth-pos);
  font-weight: 600;
  font-size: 11px;
}
tr.yoy-row td.negative { color: var(--growth-neg); }

/* Floating cell editor popover */
.cell-editor {
  position: absolute;
  z-index: 150;
  background: var(--surface);
  border: 2px solid var(--accent);
  border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0,0,0,.18);
  padding: 10px 12px;
  min-width: 220px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 13px;
}

.cell-editor .ce-context {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}

.cell-editor .ce-context .ce-customer { color: var(--text); }

.cell-editor .ce-input-wrap {
  display: flex;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: #fff;
  padding: 0 10px;
}

.cell-editor .ce-input-wrap:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(0,79,137,.15);
}

.cell-editor input.ce-input {
  border: none;
  outline: none;
  flex: 1;
  font-size: 22px;
  font-weight: 600;
  text-align: right;
  padding: 8px 0;
  width: 100%;
  background: transparent;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* Hide number input spinners — cleaner look */
.cell-editor input.ce-input::-webkit-outer-spin-button,
.cell-editor input.ce-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.cell-editor input.ce-input { -moz-appearance: textfield; }

.cell-editor .ce-suffix {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-muted);
  margin-left: 6px;
}

.cell-editor .ce-toggle {
  display: flex;
  background: var(--bg);
  border-radius: 6px;
  padding: 2px;
  gap: 2px;
}

.cell-editor .ce-toggle button {
  flex: 1;
  padding: 5px 10px;
  border: none;
  background: transparent;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.cell-editor .ce-toggle button.active {
  background: var(--surface);
  color: var(--accent);
  box-shadow: 0 1px 2px rgba(0,0,0,.08);
}

.cell-editor .ce-hint {
  font-size: 10px;
  color: var(--text-muted);
  text-align: center;
  letter-spacing: .03em;
}

.cell-editor .ce-hint kbd {
  display: inline-block;
  padding: 1px 5px;
  background: #f3f4f6;
  border: 1px solid var(--border);
  border-radius: 3px;
  font-family: -apple-system, monospace;
  font-size: 10px;
  margin: 0 2px;
}

/* ── Modals ───────────────────────────────────────────────── */
.modal { position: fixed; inset: 0; z-index: 200; display: flex; align-items: center; justify-content: center; }

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,.35);
}

.modal-box {
  position: relative;
  background: var(--surface);
  border-radius: 12px;
  padding: 32px;
  width: 420px;
  max-width: 95vw;
  box-shadow: 0 8px 40px rgba(0,0,0,.18);
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.modal-box h2 { font-size: 18px; font-weight: 700; }
.modal-box h3 { font-size: 14px; font-weight: 700; margin-top: 4px; }

.modal-box form { display: flex; flex-direction: column; gap: 12px; }

.modal-box label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .05em;
}

.modal-box input[type=text],
.modal-box input[type=password],
.modal-box select {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
  outline: none;
}

.modal-box input:focus,
.modal-box select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(0,79,137,.15);
}

.modal-actions { display: flex; gap: 8px; margin-top: 4px; flex-wrap: wrap; }

.checkbox-label { flex-direction: row !important; align-items: center; gap: 8px !important; }
.checkbox-label input { width: auto; }

/* Multi-select attribute group (e.g. Product Line) in the customer modal. */
.checkbox-group {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 10px 10px;
}
.checkbox-group legend {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: 0 4px;
}
.checkbox-group > div { display: flex; flex-direction: column; gap: 6px; }
/* Product names keep their own casing — don't uppercase them like field labels. */
.checkbox-group .checkbox-label {
  text-transform: none;
  letter-spacing: normal;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}

.modal-box--users { width: min(680px, calc(100vw - 32px)); }
#users-list { display: flex; flex-direction: column; gap: 6px; max-height: 60vh; overflow-y: auto; }

.user-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px;
  background: var(--bg);
  border-radius: 6px;
  font-size: 13px;
}
.user-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.user-row .user-name { font-weight: 600; max-width: none; font-size: 13px; color: var(--text); }
.user-pages { display: flex; flex-wrap: wrap; gap: 4px 14px; }
/* .modal-box label stacks and upper-cases a form label; these are inline
   checkboxes, so undo that. */
.modal-box .user-page {
  display: inline-flex; flex-direction: row; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 400; color: var(--text);
  text-transform: none; letter-spacing: normal; cursor: pointer;
}
.user-page input:disabled { cursor: default; }
.no-access {
  max-width: 520px; margin: 80px auto; padding: 0 16px; text-align: center;
  color: var(--text-muted);
}
.no-access h2 { color: var(--text); margin-bottom: 8px; }
.user-row .user-badge {
  font-size: 10px;
  background: var(--accent);
  color: #fff;
  padding: 1px 6px;
  border-radius: 10px;
  margin-left: 6px;
}

/* ── Tooltip for actual/forecast ─────────────────────────── */
.toggle-hint {
  position: fixed;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  background: #192639;
  color: #fff;
  font-size: 11px;
  padding: 6px 14px;
  border-radius: 20px;
  pointer-events: none;
  opacity: 0;
  transition: opacity .2s;
  z-index: 300;
}
.toggle-hint.visible { opacity: 1; }

/* ── Upload provider picker modal ────────────────────────── */
.modal-box--narrow { max-width: 340px; }
.upload-modal-hint {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 8px;
}

/* ── Cloud provider badges (Subscriptions modal) ─────────── */
.provider-badge {
  display: inline-block;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 8px;
  margin-left: 6px;
  vertical-align: middle;
  line-height: 1.6;
}
.provider-badge--azure {
  background: #e0f0ff;
  color: #0063b2;
}
.provider-badge--aws {
  background: #fff0d6;
  color: #c45f00;
}
.provider-badge--gcp {
  background: #efe7fd;
  color: #6a2ec7;
}
.provider-badge--fastly {
  background: #ffe1e1;
  color: #b00020;
}
.provider-badge--akamai {
  background: #e6f4ea;
  color: #137333;
}

/* ── Provider filter tab strip (Subscriptions modal) ─────── */
.subs-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.subs-toolbar .subs-filter { flex: 1; margin-bottom: 0; }

.subs-provider-filter {
  display: flex;
  gap: 2px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 2px;
  flex-shrink: 0;
}
.subs-provider-tab {
  background: none;
  border: none;
  border-radius: 6px;
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  transition: background .15s, color .15s;
}
.subs-provider-tab.active {
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 1px 3px rgba(0,0,0,.08);
}

/* ── Mobile / narrow viewports ────────────────────────────── */
/* Tablet & small laptop: stack charts, allow header to wrap. */
@media (max-width: 900px) {
  header {
    height: auto;
    min-height: var(--header-h);
    flex-wrap: wrap;
    padding: 8px 14px;
    gap: 8px;
  }
  .header-left,
  .header-center,
  .header-right { flex-wrap: wrap; gap: 8px; }
  .header-center { order: 3; flex-basis: 100%; justify-content: center; }

  /* Once the header wraps, the three children stack: logo+title and the user
     chip share the first row, then the tabs, then the action buttons. The
     chip has to stay on that first row — wrapped onto a row of its own it sat
     at the LEFT edge, and its menu (anchored right: 0) then opened off the
     left side of the screen. */
  /* flex-basis 0, not auto: with auto the tabs' intrinsic width makes
     .header-left claim the whole row during line-breaking, so the chip is
     pushed onto a row of its own before it can ever sit beside it. */
  .header-left { flex: 1 1 0; }
  #view-tabs {
    order: 3;
    flex-basis: 100%;
    min-width: 0;
    /* More tabs than fit a phone, so scroll them rather than wrap or clip. */
    overflow-x: auto;
    scrollbar-width: none;
  }
  #view-tabs .tab-btn { flex: none; }
  #view-tabs::-webkit-scrollbar { display: none; }
  .user-menu { order: 2; align-self: flex-start; margin-left: 8px; }
  #header-actions { order: 3; flex-basis: 100%; }

  #charts {
    grid-template-columns: 1fr;
    padding: 12px;
    gap: 12px;
  }

  #table-container { padding: 12px; }

  /* History modal: stack the fixed grid columns. */
  .history-row {
    grid-template-columns: 1fr;
    gap: 2px;
    padding: 8px 4px;
  }
  .history-delta { text-align: left; }

  /* Subscriptions modal: drop the 800px min so it fits the viewport. */
  #subs-modal .modal-box { min-width: 0 !important; width: 95vw; }
}

/* Phone: hide cosmetic labels, tighten chart cards, allow iframe height to follow wrapped header. */
/* ── Summary Metrics Section ──────────────────────────────── */
.summary-metrics {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 10px;
  padding: 12px 16px 0;
  background: var(--bg);
  margin-bottom: 8px;
}

.metric-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.metric-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.metric-header {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.2;
}

.metric-value {
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.1;
  white-space: nowrap;
}

.metric-value.positive { color: var(--growth-pos); }
.metric-value.negative { color: var(--growth-neg); }
.metric-value.warning { color: var(--growth-warn); }

.metric-label {
  font-size: 10px;
  color: var(--text-muted);
}

.metric-sparkline {
  flex-shrink: 0;
  width: 64px;
  height: 28px;
}

.sparkline-svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

.sp-prior {
  stroke: var(--border-strong);
}

.sp-current {
  stroke: var(--accent);
}

.sp-dot-prior {
  fill: var(--border-strong);
}

.sp-dot-current {
  fill: var(--accent);
}

.sp-dot-prior, .sp-dot-current {
  cursor: pointer;
}

.sp-divider {
  stroke: var(--border);
  stroke-width: 1;
  stroke-dasharray: 2 2;
}

.metric-quarters {
  font-size: 10px;
  color: var(--text-muted);
  text-align: center;
  letter-spacing: 0.05em;
}

@media (max-width: 600px) {
  :root { --header-h: 96px; }

  header { padding: 6px 10px; }

  header h1 { font-size: 14px; }
  .header-logo { height: 18px; }

  /* Phone: the initials alone identify the account; the name is in the menu. */
  #user-label { display: none; }
  .user-chip { padding: 3px; }

  .tab-btn { padding: 5px 10px; font-size: 13px; }

  .btn-primary,
  .btn-secondary,
  .btn-ghost,
  .btn-danger {
    padding: 6px 10px;
    font-size: 12px;
  }

  .chart-card { padding: 12px 12px 10px; }
  .chart-header h2 { font-size: 11px; }

  .modal-box { padding: 20px; gap: 12px; }
}

/* ── Cloud Cost by Subscription Table ─────────────────────────────────────── */
#cloud-cost-section {
  padding: 0 1rem 2rem;
}
#cloud-cost-header {
  display: flex;
  align-items: baseline;
  gap: .75rem;
  padding: .5rem 0 .25rem;
}
#cloud-cost-header h2 {
  font-size: 1rem;
  font-weight: 600;
  margin: 0;
}
table.cloud-cost-table {
  border-collapse: collapse;
  width: 100%;
  font-size: 12px;
}
table.cloud-cost-table th {
  padding: 5px 8px;
  text-align: right;
  background: var(--header-bg, #f0f4f8);
  border-bottom: 2px solid var(--border, #d1d5db);
  white-space: nowrap;
  color: var(--text-muted, #6b7280);
  font-weight: 600;
  font-size: 11px;
}
th.cc-hdr-provider { width: 40px; text-align: center; }
th.cc-hdr-name { text-align: left; min-width: 200px; max-width: 300px; }
th.cc-hdr-month { width: 72px; }
th.cc-hdr-total { width: 80px; background: var(--actual-bg, #e8f4fb); }

tr.cc-sep-row td.cc-sep-cell {
  padding: 8px 8px 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted, #6b7280);
  background: transparent;
  border-top: 1px solid var(--border, #d1d5db);
}
tr.cc-row:hover td { background: #f0f9ff; }
tr.cc-row td {
  border-bottom: 1px solid var(--border-light, #e5e7eb);
}
td.cc-provider-cell {
  padding: 4px 6px;
  text-align: center;
  width: 40px;
}
table.cloud-cost-table td.cc-provider-cell .cloud-badge--azure {
  background: #e0f0ff;
  color: #0063b2;
}
table.cloud-cost-table td.cc-provider-cell .cloud-badge--fastly {
  background: #ffe1e1;
  color: #b00020;
}
td.cc-name-cell {
  padding: 4px 8px;
  max-width: 300px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text, #111827);
}
td.cc-cell {
  padding: 4px 6px;
  text-align: right;
  position: relative;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  min-width: 64px;
}
td.cc-cell.cc-zero {
  color: var(--text-muted, #9ca3af);
}
td.cc-cell .cc-val {
  display: block;
  line-height: 1.3;
}
td.cc-cell .cc-mom {
  display: block;
  font-size: 9px;
  font-weight: 600;
  line-height: 1.1;
  text-align: right;
}
.cc-increase { color: #dc2626; }   /* red  = cost went up   = bad  */
.cc-decrease { color: #16a34a; }   /* green = cost went down = good */
td.cc-fy-cell {
  background: var(--actual-bg, #e8f4fb);
  font-weight: 600;
}
tr.cc-cat-totals-row td,
tr.cc-grand-row td {
  font-weight: 600;
  background: var(--actual-bg, #e8f4fb);
  border-top: 2px solid var(--border, #d1d5db);
  border-bottom: 2px solid var(--border, #d1d5db);
}
tr.cc-grand-row td {
  background: var(--header-bg, #f0f4f8);
  border-top: 2px solid #9ca3af;
  border-bottom: 2px solid #9ca3af;
}
td.cc-totals-label {
  text-align: right;
  padding: 4px 8px;
  color: var(--text-muted);
  font-size: 11px;
}
td.cc-subtotal { }

/* ── Modals ───────────────────────────────────────────────── */
.modal-note {
  margin: 14px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-muted);
}

.modal-note code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
}

/* ── Vendor Contracts (admin-only) ────────────────────────── */
#contracts-view,
#customer-contracts-view { padding: 1rem 1rem 2rem; }

.contracts-toolbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: .75rem;
}
.contracts-heading h2 { font-size: 16px; font-weight: 700; color: var(--accent); }
.contracts-summary { display: flex; align-items: center; gap: .5rem .75rem; flex-wrap: wrap; margin-top: 4px; font-size: 12px; color: var(--text-muted); }
.contracts-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.contracts-filter {
  padding: 7px 10px;
  font-size: 13px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
}
input.contracts-filter { width: 260px; max-width: 100%; }

.contracts-banner {
  margin-bottom: .75rem;
  padding: 8px 12px;
  border: 1px solid #fcd34d;
  border-radius: 6px;
  background: var(--forecast-bg);
  font-size: 12px;
}

#contracts-table-container,
#customer-contracts-table-container {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow-x: auto;
}
/* table-layout: fixed so the caps below are obeyed. Without it the browser
   sizes columns to content and one long contract title or vendor name pushes
   the money columns off the right-hand side. */
/* min-width, not just width: with table-layout: fixed the column widths below
   only hold if the table is allowed to be as wide as their sum. Squeezed
   narrower, the browser satisfies the pixel columns first and gives the
   others nothing — see the comment on the width list. */
.contracts-table {
  width: 100%;
  /* The sum of the column widths below. Lower than that and the browser
     starts starving columns again; keep the two in step. */
  min-width: 1358px;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 12px;
}
.contracts-table th,
.contracts-table td {
  padding: 8px 10px; text-align: left;
  border-bottom: 1px solid var(--border); vertical-align: top;
  /* Long values are truncated rather than allowed to widen the column; the
     full text stays available through the cell's title attribute. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Widths are capped per column, keyed to the column's name rather than its
   position — nth-child rules shifted the moment a column was added. The
   identity column gets the room because it carries the vendor and the title;
   everything else is sized to its content, so a long signatory name can no
   longer squeeze the renewal date out of view.

   Every width is in pixels on purpose. Mixing percentages with pixels under
   table-layout: fixed collapsed the percentage columns to ZERO on a phone —
   the pixel columns already exceeded the container, so Vendor / Contract,
   Signed By and Business Owner disappeared entirely, and min-width does not
   rescue a table cell the way it would a block. Pixels everywhere plus a
   min-width on the table keeps the sum deterministic at any viewport. */
.contracts-table .col-vendor_name          { width: 220px; }
.contracts-table .col-document_kind        { width: 74px; }
.contracts-table .col-mediakind_signee     { width: 120px; }
.contracts-table .col-business_owner       { width: 110px; }
.contracts-table .col-status               { width: 74px; }
.contracts-table .col-term_months          { width: 62px; }
.contracts-table .col-renewal_date         { width: 92px; }
.contracts-table .col-notice_period_days   { width: 62px; }
.contracts-table .col-notice_deadline      { width: 116px; }
.contracts-table .col-auto_renews          { width: 76px; }
.contracts-table .col-one_time_cost        { width: 96px; }
.contracts-table .col-recurring_cost       { width: 112px; }
.contracts-table .col-total_contract_value { width: 96px; }
.contracts-table .col-file_count           { width: 48px; }

/* The identity cell is the one place wrapping is wanted: vendor on one line,
   title beneath it. */
.contracts-table td:first-child { white-space: normal; }

/* ...and it stays put while the rest scrolls sideways. On a phone the table is
   far wider than the screen, so scrolling to reach Renewal or Recurring used
   to carry the vendor and title off the left edge, leaving rows you could read
   but not identify. */
.contracts-table th:first-child,
.contracts-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--surface);
}
.contracts-table th:first-child { z-index: 4; }
.contracts-group > td:first-child { background: var(--total-bg); }
/* The sticky column needs its own right edge, since the cell it used to sit
   against may have scrolled away underneath it. */
.contracts-table th:first-child::after,
.contracts-table td:first-child::after {
  content: '';
  position: absolute;
  top: 0; bottom: -1px; right: 0;
  border-right: 1px solid var(--border);
}
.contracts-table tbody tr:hover td:first-child { background: #e8f4fb; }
/* Two lines at most. The cell wraps so vendor and title stack, but a
   90-character title would otherwise make one row four lines tall and push
   everything else down the page. */
.contracts-vendor, .contracts-title {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; text-overflow: ellipsis;
}
.contracts-vendor { -webkit-line-clamp: 1; }

/* The converted figure sits under the contract's own amount. */
.contracts-usd { font-size: 10px; color: var(--text-muted); font-weight: 300; }
.contracts-table th {
  position: sticky; top: 0;
  background: var(--total-bg);
  font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
  color: var(--text-muted);
  user-select: none;
}
.contracts-table th.sorted { color: var(--accent); }
/* The sort control is a real button so it is keyboard-reachable; it inherits
   the header's type so it still reads as a column heading. */
.contracts-sort {
  padding: 0; border: none; background: none; cursor: pointer;
  font: inherit; color: inherit; text-transform: inherit; letter-spacing: inherit;
}
.contracts-sort:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
.contracts-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.contracts-table tbody tr { cursor: pointer; }
.contracts-table tbody tr:hover,
.contracts-table tbody tr:focus-visible { background: #e8f4fb; outline: none; }
.contracts-table tbody tr:last-child td { border-bottom: none; }
.contracts-vendor { font-weight: 600; }
.contracts-sub { font-size: 11px; color: var(--text-muted); font-weight: 300; }
.contracts-muted { color: var(--text-muted); }
.contracts-empty { padding: 3rem 1rem; text-align: center; display: flex; flex-direction: column; gap: 6px; }

.contracts-pill { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.contracts-pill small { font-weight: 300; }
.contracts-pill--overdue  { background: #fee2e2; color: var(--danger); }
.contracts-pill--soon     { background: #ffedd5; color: #c2410c; }
.contracts-pill--upcoming { background: #fef9c3; color: #854d0e; }
.contracts-pill--ok       { background: transparent; color: var(--text); padding-left: 0; font-weight: 300; }
.contracts-pill--muted    { background: transparent; color: var(--text-muted); padding-left: 0; font-weight: 300; }

.contracts-status { font-size: 11px; font-weight: 600; }
.contracts-status--active     { color: var(--growth-pos); }
.contracts-status--pending    { color: var(--growth-warn); }
.contracts-status--expired,
.contracts-status--terminated { color: var(--text-muted); }

/* Vendor grouping: a vendor row with its contracts nested beneath it. */
.contracts-group > td { background: var(--total-bg); border-bottom: 1px solid var(--border-strong); }
.contracts-group-toggle {
  display: flex; align-items: center; gap: 8px;
  padding: 0; border: none; background: none; cursor: pointer;
  font: inherit; text-align: left; width: 100%;
}
.contracts-group-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.contracts-caret { color: var(--text-muted); font-size: 10px; width: 10px; flex: none; }
.contracts-count { font-size: 11px; color: var(--text-muted); font-weight: 300; }
.contracts-badge {
  padding: 1px 7px; border-radius: 999px;
  background: var(--forecast-bg); border: 1px solid #fcd34d; color: #854d0e;
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
}
.contracts-badge--button { cursor: pointer; font-family: inherit; }
.contracts-badge--button:hover { background: #fde68a; }

/* The indent is what carries the parent/child relationship visually. */
.contracts-child { padding-left: 30px !important; }
/* Smaller than the vendor row above it: the vendor is the heading, the
   contract title is detail under it, and matching sizes made the hierarchy
   hard to read at a glance. */
.contracts-title { font-weight: 600; font-size: 11px; }
.contracts-row.is-unreviewed > td:first-child { box-shadow: inset 3px 0 0 #fcd34d; }

/* Batch upload progress */
.contracts-batch {
  margin-bottom: .75rem; padding: 10px 12px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  display: flex; flex-direction: column; gap: 8px; font-size: 12px;
}
.contracts-batch-head { display: flex; align-items: center; gap: 8px; }
.contracts-batch-close { margin-left: auto; padding: 3px 8px; font-size: 11px; }
.contracts-batch-counts { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }
.contracts-progress { height: 4px; background: var(--bg); border-radius: 999px; overflow: hidden; }
.contracts-progress-bar { height: 100%; background: var(--accent); transition: width .3s ease; }
.contracts-batch-list summary { cursor: pointer; color: var(--text-muted); }
.contracts-batch-list ul { margin: 6px 0 0 18px; display: flex; flex-direction: column; gap: 3px; }
.contracts-batch-list li { overflow-wrap: anywhere; }

/* Contract modal */
.modal-box--wide { width: 980px; max-height: 92vh; overflow-y: auto; }

.contract-section { border: none; padding: 0; margin: 0; }
.contract-section legend {
  font-size: 12px; font-weight: 700; color: var(--accent);
  padding: 0; margin-bottom: 6px;
}
.contract-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 14px; }
.contract-grid--wide { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.contract-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

/* .modal-box only styles text/password inputs and selects; the contract form
   also uses date, number and textarea. */
#contract-modal input,
#contract-modal select,
#contract-modal textarea,
#customer-contract-modal input,
#customer-contract-modal select,
#customer-contract-modal textarea {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font: inherit;
  font-size: 13px;
  outline: none;
  width: 100%;
  background: var(--surface);
}
#contract-modal textarea,
#customer-contract-modal textarea { resize: vertical; }
#contract-modal textarea:focus,
#customer-contract-modal textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(0,79,137,.15); }
#contract-modal .contract-input--code,
#customer-contract-modal .contract-input--code { text-transform: uppercase; }
#contract-modal .ai-filled,
#customer-contract-modal .ai-filled { background: var(--actual-bg); border-color: var(--brand-cyan); }

.contract-hint { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; font-size: 11px; color: var(--text-muted); }
.contract-hint-tag { font-weight: 700; text-transform: uppercase; letter-spacing: .04em; font-size: 10px; color: var(--brand-cyan); }
.contract-hint--medium .contract-hint-tag { color: var(--growth-warn); }
.contract-hint--low .contract-hint-tag { color: var(--danger); }
.contract-hint-value { font-weight: 600; color: var(--text); }
.contract-hint-apply {
  padding: 1px 8px; font-size: 11px; font-weight: 600;
  color: var(--accent); background: var(--surface);
  border: 1px solid var(--accent); border-radius: 999px; cursor: pointer;
}
.contract-hint-apply:hover { background: #e8f4fb; }
.contract-hint-quote { flex-basis: 100%; font-style: italic; overflow-wrap: anywhere; }

.contract-analysis { padding: 10px 12px; border-radius: 8px; font-size: 12px; display: flex; flex-direction: column; gap: 6px; border: 1px solid var(--border); }
.contract-analysis--working { flex-direction: row; align-items: center; gap: 10px; background: var(--actual-bg); border-color: #bae6fd; }
.contract-analysis--done    { background: var(--actual-bg); border-color: #bae6fd; }
.contract-analysis--failed  { background: #fee2e2; border-color: #fca5a5; align-items: flex-start; }
.contract-analysis--skipped { background: var(--forecast-bg); border-color: #fcd34d; }
.contract-analysis-summary { color: var(--text-muted); }
.contract-analysis-warnings ul { margin: 2px 0 0 18px; }
.contract-spinner {
  flex: none; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid #bae6fd; border-top-color: var(--accent);
  animation: contract-spin .8s linear infinite;
}
@keyframes contract-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .contract-spinner { animation: none; } }

.contract-error { padding: 8px 12px; border-radius: 6px; background: #fee2e2; color: var(--danger); font-size: 12px; font-weight: 600; }

.contract-documents { border-top: 1px solid var(--border); padding-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.contract-doc {
  display: grid; grid-template-columns: minmax(0, 1fr) 160px auto auto; align-items: center; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 12px;
}
.contract-doc-main { min-width: 0; }
.contract-doc-name {
  padding: 0; border: none; background: none; cursor: pointer;
  font: inherit; font-weight: 600; color: var(--accent); text-align: left;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.contract-doc-name:hover { text-decoration: underline; }
.contract-doc-error { color: var(--danger); font-size: 11px; white-space: normal; }
.contract-doc-status { font-size: 11px; font-weight: 600; color: var(--text-muted); }
.contract-doc-status--done { color: var(--growth-pos); }
.contract-doc-status--failed { color: var(--danger); }
.contract-doc-actions { display: flex; gap: 4px; }
.contract-doc-actions .btn-ghost { padding: 4px 8px; font-size: 11px; }
.contract-doc-remove:hover { color: var(--danger); border-color: #fca5a5; }
.contract-attach { display: flex; gap: 8px; align-items: center; }
#contract-modal .contract-attach select,
#customer-contract-modal .contract-attach select { width: 200px; }

.contract-history-list { max-height: 60vh; overflow-y: auto; display: flex; flex-direction: column; font-size: 12px; }
.contract-history-row { padding: 8px 0; border-bottom: 1px solid var(--border); overflow-wrap: anywhere; }
.contract-history-old { color: var(--text-muted); text-decoration: line-through; }

@media (max-width: 760px) {
  .contract-grid, .contract-grid--wide { grid-template-columns: 1fr; }
  .contract-doc { grid-template-columns: 1fr; }
  input.contracts-filter { width: 100%; }
}
#contract-form-body,
#customer-contract-form-body { display: flex; flex-direction: column; gap: 14px; }
.contract-doc.is-hidden { opacity: .6; }
.contract-doc-hidden > summary { cursor: pointer; color: var(--text-muted); font-size: 11px; padding: 6px 0; }
.contracts-kind { font-size: 11px; font-weight: 600; }
.contracts-kind--signed_order { color: var(--growth-pos); }
.contracts-kind--quote {
  color: #854d0e; background: var(--forecast-bg);
  border: 1px solid #fcd34d; border-radius: 999px; padding: 1px 7px;
}
.contracts-kind--unsigned { color: var(--danger); }
.contracts-kind--unknown { color: var(--text-muted); font-weight: 300; }

/* Committed-cost projection under the contracts table */
.contracts-forecast {
  margin-top: 1rem; padding: 12px 14px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.contracts-forecast-head { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; margin-bottom: 8px; }
.contracts-forecast-head h3 { font-size: 13px; font-weight: 700; color: var(--accent); }
.contracts-forecast-canvas { height: 220px; }
@media (max-width: 600px) { .contracts-forecast-canvas { height: 260px; } }

/* ── Customer Contracts (admin-only) ──────────────────────
   The table reuses .contracts-table wholesale; only the column widths differ,
   because the columns do. Same rule as the vendor table: every width is in
   pixels, keyed to the column's NAME, and .customer-contracts-table's
   min-width is their sum — keep the two in step or the browser starts
   starving columns on a narrow screen. */
.customer-contracts-table { min-width: 1378px; }
.customer-contracts-table .col-customer_name        { width: 220px; }
.customer-contracts-table .col-document_kind        { width: 74px; }
.customer-contracts-table .col-doc_types            { width: 140px; }
.customer-contracts-table .col-account_owner        { width: 110px; }
.customer-contracts-table .col-status               { width: 74px; }
.customer-contracts-table .col-term_months          { width: 62px; }
.customer-contracts-table .col-renewal_date         { width: 92px; }
.customer-contracts-table .col-notice_period_days   { width: 62px; }
.customer-contracts-table .col-notice_deadline      { width: 116px; }
.customer-contracts-table .col-auto_renews          { width: 76px; }
.customer-contracts-table .col-one_time_fee         { width: 96px; }
.customer-contracts-table .col-recurring_fee        { width: 112px; }
.customer-contracts-table .col-total_contract_value { width: 96px; }
.customer-contracts-table .col-file_count           { width: 48px; }
/* Chips wrap, so this one cell is allowed to be as tall as it needs. */
.customer-contracts-table .col-doc_types { white-space: normal; }

/* Which paperwork is on file. The three that matter — MSA, NDA, order form —
   are solid; anything else is outlined, so a glance down the column reads as
   "what is missing" rather than "what exists". */
.doc-chips { display: flex; flex-wrap: wrap; gap: 3px; }
.doc-chip {
  font-size: 10px; font-weight: 600; letter-spacing: .02em;
  padding: 1px 6px; border-radius: 999px;
  border: 1px solid var(--border-strong); color: var(--text-muted);
}
.doc-chip--key { border-color: transparent; color: #fff; background: var(--brand-cyan); }
.doc-chip--msa { background: var(--accent); }
.doc-chip--nda { background: #0f766e; }
.doc-chip--order_form { background: var(--brand-cyan); }

.contract-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
}
.contract-ask-btn:disabled { opacity: .5; cursor: not-allowed; }

/* ── Ask Claude about a contract ──────────────────────────
   A chat panel, not a form: the log grows, the composer stays put, and the
   answer is plain text laid out by renderAnswer() — never HTML. */
/* .modal-box--wide scrolls its own content; here only the log should,
   or the composer slides off the bottom as the conversation grows. The log
   is the one flexible child, so it is what shrinks on a short screen. */
/* A fixed height rather than max-height: sized to the content, the panel sat
   half-empty in the middle of a tall window while the transcript — the part
   you actually read — was the smallest thing in it. Now it takes the room
   that is there and the log, as the one flexible child, gets all of it. */
.chat-box {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: min(88vh, 880px);
  max-height: 88vh;
  overflow: hidden;
}
.chat-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.chat-head-text { min-width: 0; }
.chat-head h2 { margin: 0; }
.chat-head-actions { display: flex; gap: 6px; flex: none; }
.chat-head-actions .btn-ghost { padding: 5px 10px; font-size: 12px; }
.chat-sources {
  margin-top: 3px; font-size: 11px; color: var(--text-muted);
  overflow-wrap: anywhere;
  /* Contract filenames run long, and on a phone an eight-line one pushed the
     conversation itself off the screen. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.chat-source { font-weight: 600; color: var(--text); }
.chat-warn { color: var(--growth-warn); }

.chat-log {
  /* No max-height: the box above has a height, so this fills whatever is
     left once the header, the composer and the note have taken theirs. */
  flex: 1 1 auto; min-height: 160px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  padding: 12px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg);
}
.chat-msg { display: flex; flex-direction: column; gap: 3px; max-width: 86%; }
.chat-msg--user { align-self: flex-end; align-items: flex-end; }
.chat-role {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--text-muted);
}
.chat-body {
  padding: 9px 12px; border-radius: 10px; font-size: 13px; line-height: 1.5;
  background: var(--surface); border: 1px solid var(--border);
  overflow-wrap: anywhere;
}
.chat-msg--user .chat-body { background: var(--accent); border-color: var(--accent); color: #fff; }
.chat-body p + p, .chat-body p + .chat-list, .chat-body .chat-list + p { margin-top: 7px; }
.chat-list { margin: 0 0 0 18px; display: flex; flex-direction: column; gap: 3px; }
.chat-error { color: var(--danger); font-weight: 600; }

.chat-suggestions { display: flex; flex-wrap: wrap; gap: 6px; }
.chat-suggestions.hidden { display: none; }
.chat-chip {
  font: inherit; font-size: 12px; cursor: pointer;
  padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
}
.chat-chip:hover { background: #e8f4fb; border-color: var(--accent); color: var(--accent); }

.chat-status { font-size: 11px; color: var(--text-muted); min-height: 14px; }
/* `.modal-box form` further up sets flex-direction: column, and at (0,2,0) it
   outranks a bare `.chat-form` — which left the composer stacked and, because
   of the align-items below, shrunk into the bottom-right corner. Matched
   specificity, and the direction stated rather than inherited. */
.modal-box .chat-form {
  display: flex;
  flex-direction: row;
  gap: 8px;
  align-items: flex-end;
}
.modal-box .chat-form textarea {
  flex: 1 1 auto;
  width: 100%;
  /* Three lines to start. A contract question is usually a sentence, and a
     two-line box made it feel like a search field. */
  min-height: 92px;
  max-height: 40vh;
  resize: vertical;
  font: inherit;
  font-size: 13px;
  line-height: 1.45;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
}
.modal-box .chat-form textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(0,79,137,.15); }
.modal-box .chat-form button { flex: none; min-height: 40px; padding-left: 22px; padding-right: 22px; }
.chat-note { font-size: 11px; color: var(--text-muted); }

/* The empty transcript, before anyone has asked anything. Without it the
   panel opens on a large blank panel that reads as something failing to
   load. */
.chat-empty {
  margin: auto; text-align: center; max-width: 42ch;
  color: var(--text-muted); font-size: 12px; line-height: 1.6;
}
.chat-empty strong { display: block; color: var(--text); font-size: 13px; margin-bottom: 2px; }

@media (max-width: 760px) {
  .chat-msg { max-width: 100%; }
  .chat-box { height: min(92vh, 720px); }
}

/* ── Contract modal: fixed head, scrolling body, pinned actions ──────────
   The form was one long scroll with Save at the far end, so saving meant
   scrolling past every field to reach the button — and there was no way to
   dismiss the modal from the top at all. Three bands now: the title and the
   close control stay put, the middle scrolls, and the actions sit on the
   bottom edge where they can always be reached.

   Padding moves off .modal-box and onto the bands, so the divider above the
   actions runs the full width of the panel rather than stopping short. */
.contract-box {
  padding: 0;
  gap: 0;
  overflow: hidden;           /* .modal-box--wide scrolls; here the body does */
  max-height: 92vh;
}
.contract-box .contract-modal-head {
  flex: none;
  align-items: flex-start;
  padding: 26px 32px 14px;
}
.contract-modal-head-actions { display: flex; align-items: center; gap: 10px; }
.contract-modal-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0 32px 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.contract-box .contract-modal-actions {
  flex: none;
  margin: 0;
  padding: 14px 32px;
  border-top: 1px solid var(--border);
  background: var(--surface);
}

/* The close control. A real button, not a glyph in a span: it takes focus,
   answers Enter and Space, and tells a screen reader what it does. */
.modal-x {
  flex: none;
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1;
  color: var(--text-muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
}
.modal-x:hover { background: var(--bg); color: var(--text); border-color: var(--border); }
.modal-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* A document that arrived as Word and was converted on the way in. */
.contract-doc-original { font-size: 11px; }
.contract-doc-original button {
  font: inherit; color: var(--accent); background: none; border: none;
  padding: 0; cursor: pointer; text-decoration: underline;
}

@media (max-width: 760px) {
  .contract-box .contract-modal-head { padding: 18px 18px 10px; }
  .contract-modal-body { padding: 0 18px 14px; }
  .contract-box .contract-modal-actions { padding: 12px 18px; }
}

/* The Merge control on a customer group row. Kept quiet until the row is
   hovered or it takes focus: it is an occasional cleanup action, and one that
   rewrites every contract under the group, so it should not read as an
   invitation on every row at rest. Always rendered, never display:none, so it
   stays reachable by keyboard. */
.contracts-merge-btn {
  margin-left: 8px;
  padding: 1px 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: transparent;
  color: var(--text-muted);
  font-size: 11px;
  cursor: pointer;
  opacity: 0;
  /* Invisible AND inert. At opacity 0 alone it still takes a click, so a
     stray tap near the customer name opened a dialog that renames every
     contract in the group. Keyboard focus is unaffected by pointer-events,
     so :focus-visible below still reaches it. */
  pointer-events: none;
  transition: opacity .12s ease;
}
/* :focus as well as :focus-visible. focus-visible depends on the browser's
   heuristic for "was this keyboard?", and where it does not match, the button
   would be focused, invisible and inert at once -- the worst of the three. */
.contracts-group:hover .contracts-merge-btn,
.contracts-merge-btn:focus,
.contracts-merge-btn:focus-visible { opacity: 1; pointer-events: auto; }
.contracts-merge-btn:hover { color: var(--accent); border-color: var(--accent); }

/* A touch screen has no hover to reveal it with, so there it is simply
   always shown rather than permanently unreachable. */
@media (hover: none) {
  .contracts-merge-btn { opacity: 1; pointer-events: auto; }
}
