/* RWE admin dashboard — components.
   Every rule here answers a specific piece of Chris's feedback on the Paper screens. Where a
   rule looks arbitrary, the comment says which correction it encodes. Do not "tidy" those. */

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--color-canvas);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }

/* ── shell ──────────────────────────────────────────────────────────────── */
.shell { display: grid; grid-template-columns: var(--container-sidebar) 1fr; min-height: 100vh; }

.sidebar {
  background: var(--color-surface);
  border-right: 1px solid var(--color-hairline);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.brand {
  display: flex; align-items: center; gap: var(--spacing-3);
  height: var(--container-topbar); padding: 0 var(--spacing-4);
  border-bottom: 1px solid var(--color-hairline-soft); flex: 0 0 auto;
}
.brand-mark {
  width: 26px; height: 26px; border-radius: var(--radius-sm);
  background: var(--color-accent); color: var(--color-on-accent);
  display: grid; place-items: center;
  font-size: var(--text-label); font-weight: var(--font-weight-bold);
}
.brand-name {
  font-size: var(--text-label); font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-tight);
}

/* The Business | Personal switch. His instruction, 2026-10-11: "There should be a personal &
   then a business section." It is a top-level mode, not a nav item, so it sits above the nav. */
.switch {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--spacing-1);
  margin: var(--spacing-4) var(--spacing-3) var(--spacing-2);
  background: var(--color-tray); border-radius: var(--radius-md); padding: 3px;
}
.switch a {
  text-align: center; padding: 6px 0; border-radius: var(--radius-sm);
  font-size: var(--text-caption); font-weight: var(--font-weight-medium);
  color: var(--color-ink-muted);
}
.switch a.on {
  background: var(--color-surface); color: var(--color-ink);
  font-weight: var(--font-weight-semibold);
  box-shadow: 0 1px 2px rgba(10,12,16,.08);
}

.nav { padding: var(--spacing-2) var(--spacing-3); flex: 1 1 auto; }
.nav-label {
  font-size: var(--text-caps); letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--color-ink-subtle);
  font-weight: var(--font-weight-semibold);
  padding: var(--spacing-4) var(--spacing-2) var(--spacing-2);
}
.nav a {
  display: flex; align-items: center; gap: var(--spacing-3);
  height: var(--container-navitem); padding: 0 var(--spacing-2);
  border-radius: var(--radius-sm); color: var(--color-ink-muted);
  font-size: var(--text-label); font-weight: var(--font-weight-medium);
}
.nav a:hover { background: var(--color-sunk); color: var(--color-ink); }
.nav a.on { background: var(--color-accent-soft); color: var(--color-accent);
            font-weight: var(--font-weight-semibold); }
.nav .dot { width: 6px; height: 6px; border-radius: var(--radius-pill);
            background: var(--color-chart-ghost); flex: 0 0 auto; }
.nav a.on .dot { background: var(--color-accent); }
/* a screen with no live feed is dimmed in the nav, so he can see at a glance which half of
   the product is actually wired up — rather than clicking in and finding an empty page */
.nav a.dim { opacity: .5; }
.nav a.dim .dot { background: var(--color-warn); opacity: .7; }

.me {
  border-top: 1px solid var(--color-hairline-soft);
  padding: var(--spacing-3) var(--spacing-4); display: flex; align-items: center;
  gap: var(--spacing-3); flex: 0 0 auto;
}
.me-avatar {
  width: 28px; height: 28px; border-radius: var(--radius-pill);
  background: var(--color-accent-soft); color: var(--color-accent);
  display: grid; place-items: center;
  font-size: var(--text-caption); font-weight: var(--font-weight-semibold);
}
.me-name { font-size: var(--text-label); font-weight: var(--font-weight-medium); }
.me-role { font-size: var(--text-caps); color: var(--color-ink-subtle); }

/* ── topbar ─────────────────────────────────────────────────────────────── */
.main { min-width: 0; display: flex; flex-direction: column; }
.topbar {
  height: var(--container-topbar); background: var(--color-surface);
  border-bottom: 1px solid var(--color-hairline);
  display: flex; align-items: center; gap: var(--spacing-4);
  padding: 0 var(--spacing-6); position: sticky; top: 0; z-index: 20;
}
.topbar h1 {
  margin: 0; font-size: var(--text-section); font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-tight);
}
.topbar .spacer { flex: 1 1 auto; }
.stamp { font-size: var(--text-caption); color: var(--color-ink-subtle); }
.stamp.stale { color: var(--color-warn); font-weight: var(--font-weight-medium); }

/* Period selector. His correction, 2026-10-11: "you only have this year and 6 months. I would
   want a lot more, with the ability to sort by last 7, last 30 days, last 90, and then custom
   ranges." Custom is a real control, not a label. */
.periods { display: flex; gap: 2px; background: var(--color-tray);
           border-radius: var(--radius-md); padding: 3px; }
.periods a, .periods button {
  border: 0; background: transparent; cursor: pointer; font: inherit;
  font-size: var(--text-caption); color: var(--color-ink-muted);
  padding: 5px var(--spacing-3); border-radius: var(--radius-sm);
}
.periods a.on, .periods button.on {
  background: var(--color-surface); color: var(--color-ink);
  font-weight: var(--font-weight-semibold); box-shadow: 0 1px 2px rgba(10,12,16,.08);
}
.periods input[type=date] {
  font: inherit; font-size: var(--text-caption); border: 1px solid var(--color-hairline);
  border-radius: var(--radius-sm); padding: 4px var(--spacing-2); background: var(--color-surface);
}

.page { padding: var(--spacing-6); max-width: var(--container-page); width: 100%; }
.grid { display: grid; gap: var(--spacing-4); }
.g4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.g2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.g23 { grid-template-columns: 2fr 1fr; }
.section-title {
  font-size: var(--text-caps); letter-spacing: var(--tracking-caps); text-transform: uppercase;
  color: var(--color-ink-subtle); font-weight: var(--font-weight-semibold);
  margin: var(--spacing-8) 0 var(--spacing-3);
}
.section-title:first-child { margin-top: 0; }

/* ── card & KPI tile ────────────────────────────────────────────────────── */
.card {
  background: var(--color-surface); border: 1px solid var(--color-hairline);
  border-radius: var(--radius-lg); padding: var(--spacing-5);
}
.card-head { display: flex; align-items: baseline; gap: var(--spacing-3);
             margin-bottom: var(--spacing-4); }
.card-head h2 { margin: 0; font-size: var(--text-section);
                font-weight: var(--font-weight-semibold);
                letter-spacing: var(--tracking-tight); }
.card-head .sub { font-size: var(--text-caption); color: var(--color-ink-subtle); }

.tile { display: flex; flex-direction: column; gap: var(--spacing-2); }
.tile-label {
  font-size: var(--text-caps); letter-spacing: var(--tracking-caps); text-transform: uppercase;
  color: var(--color-ink-subtle); font-weight: var(--font-weight-semibold);
}
.tile-value {
  font-size: var(--text-stat); line-height: var(--leading-stat);
  letter-spacing: var(--tracking-stat); font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
}
.tile-value.sm { font-size: var(--text-stat-sm); line-height: 34px; }
.tile-row { display: flex; align-items: center; gap: var(--spacing-3); }
.tile-foot { font-size: var(--text-caption); color: var(--color-ink-muted); }

/* ⚠️ The delta pill is NOT a judgement. Blue = moved up, red = moved down, grey = flat. His
   correction, 2026-10-11: "I hate the green and red... I really like the blue." Green appears
   on exactly one thing in this product — profit — because he said profit should be green. */
.delta {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px var(--spacing-2);
  border-radius: var(--radius-pill); font-size: var(--text-caption);
  font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums;
}
.delta.up { background: var(--color-up-bg); color: var(--color-up); }
.delta.down { background: var(--color-down-bg); color: var(--color-down); }
.delta.flat { background: var(--color-neutral-pill); color: var(--color-ink-muted); }
.delta.warn { background: var(--color-warn-bg); color: var(--color-warn); }

/* ── goal bar ───────────────────────────────────────────────────────────── */
/* His instruction: every KPI gets an owner, a settable goal, a progress bar and bottleneck
   colouring. The bar is against HIS goal, never against 100% of some invented ceiling. */
.goal { margin-top: var(--spacing-3); }
.goal-meta {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: var(--text-caption); color: var(--color-ink-subtle); margin-bottom: 6px;
}
.goal-owner {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--color-ink-muted);
}
.goal-owner i {
  width: 16px; height: 16px; border-radius: var(--radius-pill); font-style: normal;
  background: var(--color-accent-soft); color: var(--color-accent);
  display: inline-grid; place-items: center; font-size: 9px;
  font-weight: var(--font-weight-bold);
}
.goal-track {
  height: 6px; border-radius: var(--radius-pill);
  background: var(--color-chart-track); overflow: hidden;
}
.goal-fill { height: 100%; border-radius: var(--radius-pill); background: var(--color-accent); }
.goal-fill.ok { background: var(--color-chart-2); }
.goal-fill.watch { background: var(--color-warn); }
.goal-fill.bad { background: var(--color-down); }
.goal-fill.none { background: var(--color-chart-ghost); }

/* ── the layered stacked bar ────────────────────────────────────────────── */
/* THE chart he approved, rebuilt three times. His words, 2026-10-11:
     "The way the things are rounded seems continuous with layers. Every element stacks behind
      each other."        → segments are rounded on top and overlap the one below by 10px
     "I don't want every single bar be a percentage out of 100... there's no such cap"
                          → bar height scales against the tallest month, NOT against 100%
     "I don't like the stripes"            → flat fills, no pattern, no gridline hatching
     "that right column with all of the numbers is not that good. I would rather hover"
                          → every number lives in the tooltip; the chart shows shape only
   ⚠️ No grey track behind a bar. An empty month is an empty slot, not a 0%-filled container. */
.chart { position: relative; }
.chart-bars {
  display: flex; align-items: flex-end; gap: var(--spacing-3);
  height: 240px; padding-top: var(--spacing-4);
}
/* ⚠️ `column`, NOT `column-reverse`. Paper stacks kept → cost → team TOP TO BOTTOM, and the
   later sibling paints over the earlier one, which is what makes the shingle read as depth.
   Reversed, the layers come out in the wrong order and the overlap lands on the wrong edge —
   measured 2026-10-11, the first build had team (palest) sitting on top of every bar. */
.bar { flex: 1 1 0; display: flex; flex-direction: column;
       justify-content: flex-end; position: relative; cursor: default; }
.seg {
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  min-height: 3px; position: relative;
}
/* the shingle: each layer tucks 10px under the one above, so the stack reads as one object
   with depth rather than as three disjoint blocks sitting on each other */
.seg + .seg { margin-top: -10px; }
.seg:last-child { border-radius: var(--radius-md); }
.seg.kept { background: var(--color-kept); }
.seg.cost { background: var(--color-cost); }
.seg.team { background: var(--color-team); }
.seg.ghost { background: var(--color-chart-ghost); opacity: .35; }
.bar:hover .seg { filter: brightness(1.06); }
.bar-x {
  text-align: center; font-size: var(--text-caps); color: var(--color-ink-subtle);
  padding-top: var(--spacing-3); letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
.bar-x.none { color: var(--color-chart-ghost); }

.tip {
  position: absolute; bottom: 100%; left: 50%; transform: translate(-50%, -8px);
  background: var(--color-ink); color: var(--color-surface);
  border-radius: var(--radius-md); padding: var(--spacing-3);
  font-size: var(--text-caption); line-height: 18px; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity .12s; z-index: 40;
  box-shadow: 0 8px 24px rgba(10,12,16,.24);
}
.bar:hover .tip { opacity: 1; }
.tip b { font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums; }
.tip .k { display: flex; justify-content: space-between; gap: var(--spacing-5); }
.tip .sw { display: inline-block; width: 8px; height: 8px; border-radius: 2px;
           margin-right: 6px; }

.legend { display: flex; gap: var(--spacing-5); font-size: var(--text-caption);
          color: var(--color-ink-muted); margin-top: var(--spacing-4); }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.legend i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }

/* ── table ──────────────────────────────────────────────────────────────── */
.table { width: 100%; border-collapse: collapse; }
.table th {
  text-align: left; font-size: var(--text-caps); letter-spacing: var(--tracking-caps);
  text-transform: uppercase; color: var(--color-ink-subtle);
  font-weight: var(--font-weight-semibold); padding: 0 var(--spacing-3) var(--spacing-3);
  border-bottom: 1px solid var(--color-hairline);
}
.table td {
  height: var(--container-row); padding: 0 var(--spacing-3);
  border-bottom: 1px solid var(--color-hairline-soft); font-size: var(--text-label);
  vertical-align: middle;
}
.table tr:last-child td { border-bottom: 0; }
.table tr:hover td { background: var(--color-sunk); }
.table .num { text-align: right; font-variant-numeric: tabular-nums;
              font-weight: var(--font-weight-medium); }
.table .name { font-weight: var(--font-weight-medium); }
.chip {
  display: inline-grid; place-items: center; width: 26px; height: 26px;
  border-radius: var(--radius-sm); background: var(--color-accent-soft);
  color: var(--color-accent); font-size: var(--text-caps);
  font-weight: var(--font-weight-bold); margin-right: var(--spacing-3);
  vertical-align: middle;
}
.muted { color: var(--color-ink-subtle); }

/* ── the empty state ────────────────────────────────────────────────────── */
/* ⚠️⚠️ THE MOST IMPORTANT COMPONENT IN THIS PRODUCT. The last dashboard died by rendering
   "No data" on tiles that were simply broken, and a 0 wherever a feed had quietly stopped.
   Every unknown renders an em-dash and says SINCE WHEN and WHAT UNBLOCKS IT. A number he
   cannot trust is worse than no number, because he will act on it. */
.na { color: var(--color-chart-ghost); font-variant-numeric: tabular-nums; }
.empty {
  border: 1px dashed var(--color-hairline); border-radius: var(--radius-lg);
  background: var(--color-sunk); padding: var(--spacing-6);
  display: flex; flex-direction: column; gap: var(--spacing-2);
}
.empty-title { font-size: var(--text-label); font-weight: var(--font-weight-semibold);
               color: var(--color-ink-strong); }
.empty-why { font-size: var(--text-caption); color: var(--color-ink-muted); }
.empty-need {
  font-size: var(--text-caption); color: var(--color-warn);
  background: var(--color-warn-bg); border-radius: var(--radius-sm);
  padding: var(--spacing-2) var(--spacing-3); align-self: flex-start;
  font-weight: var(--font-weight-medium);
}
.tile.is-empty .tile-value { color: var(--color-chart-ghost); }

/* ── funnel ─────────────────────────────────────────────────────────────── */
/* His correction, 2026-10-11: "you were acting like every metric is not tied to the previous
   one." So the headline number on a funnel row is the CONVERSION FROM THE STEP ABOVE measured
   against the target for that conversion — never the raw count, and never a share of the top.
   A step can be small because the step above starved it; that is tagged, not flagged red. */
.funnel td.step { font-weight: var(--font-weight-medium); }
.funnel .conv { font-variant-numeric: tabular-nums; font-weight: var(--font-weight-semibold); }
.funnel tr.bottleneck { background: var(--color-warn-bg); }
.funnel tr.bottleneck td { border-bottom-color: #F0DFC6; }
.tag {
  display: inline-block; font-size: var(--text-caps); padding: 2px var(--spacing-2);
  border-radius: var(--radius-xs); font-weight: var(--font-weight-semibold);
  letter-spacing: .02em;
}
.tag.bottleneck { background: var(--color-warn); color: #fff; }
.tag.starved { background: var(--color-neutral-pill); color: var(--color-ink-muted); }
.tag.ok { background: var(--color-accent-soft); color: var(--color-accent); }

/* ── cohort grid ────────────────────────────────────────────────────────── */
.cohort { border-collapse: separate; border-spacing: 2px; font-variant-numeric: tabular-nums; }
.cohort th { font-size: var(--text-caps); color: var(--color-ink-subtle);
             font-weight: var(--font-weight-semibold); padding: 0 var(--spacing-2) 6px; }
.cohort td { width: 42px; height: 30px; text-align: center; font-size: var(--text-caption);
             border-radius: var(--radius-xs); color: var(--color-ink-strong); }
.cohort td.m { background: var(--color-accent-soft); }
.cohort td.none { background: transparent; color: var(--color-chart-ghost); }
.cohort td.lbl { text-align: left; width: auto; white-space: nowrap;
                 font-weight: var(--font-weight-medium); padding-right: var(--spacing-3); }

/* ── habit heatmap ──────────────────────────────────────────────────────── */
/* ⚠️ Three states, not two: hit, logged-and-missed, and NOT LOGGED. His own Obsidian heatmap
   collapses the last two and so reads as a wall of failure for days he simply did not fill in.
   Not-logged is a hairline outline with no fill, and it is the commonest state. */
.heat { display: flex; flex-wrap: wrap; gap: 3px; }
.heat i {
  width: 11px; height: 11px; border-radius: 2px; display: block;
  background: var(--color-sunk); box-shadow: inset 0 0 0 1px var(--color-hairline);
}
.heat i.hit { background: var(--color-accent); box-shadow: none; }
.heat i.part { background: var(--color-accent-border); box-shadow: none; }
.heat i.miss { background: var(--color-tray); box-shadow: none; }
.heat-row { display: flex; align-items: center; gap: var(--spacing-4);
            padding: var(--spacing-3) 0; border-bottom: 1px solid var(--color-hairline-soft); }
.heat-row:last-child { border-bottom: 0; }
.heat-name { width: 190px; flex: 0 0 auto; font-size: var(--text-label);
             font-weight: var(--font-weight-medium); }
.heat-stat { width: 128px; flex: 0 0 auto; font-size: var(--text-caption);
             color: var(--color-ink-muted); font-variant-numeric: tabular-nums; }

/* ── responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 1024px) {
  .g4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .g3, .g23 { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { position: static; height: auto; flex-direction: row; flex-wrap: wrap;
             border-right: 0; border-bottom: 1px solid var(--color-hairline); }
  .nav { display: flex; gap: var(--spacing-1); overflow-x: auto; padding: var(--spacing-2); }
  .nav-label, .me { display: none; }
  .nav a { white-space: nowrap; }
  .switch { flex: 1 1 100%; margin: var(--spacing-2) var(--spacing-3); }
  .g4, .g2 { grid-template-columns: 1fr; }
  .page { padding: var(--spacing-4); }   /* the 16px phone gutter */
  .topbar { flex-wrap: wrap; height: auto; padding: var(--spacing-3) var(--spacing-4); }
  .heat-name { width: 140px; }
  .heat-stat { display: none; }
}

/* ════════════════════════════════════════════════════════════════════════════
   PARITY PASS — 2026-10-11
   Chris: "it looks like a way cheaper build than what you did in Paper. Feels like a
   huge regression." He was right. The first build shipped the LAYOUT of the Paper file
   and none of its content: no sparkline, no segmented ageing bar, no constraint card,
   no caveats panel, no owed-table, no icons, no badges, and the chart card had lost its
   headline number. Everything below is measured off the Paper artboard "03 · Today"
   (file 01M4MZ2B12G3YQD8KGGWC3XEDQ) via get_jsx, not eyeballed from a screenshot.
   ⚠️ Paper remains the authority. Diff against it before changing any number here.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── sidebar, the real one ───────────────────────────────────────────────── */
.sidebar { padding: 18px 12px; gap: 3px; }
.brand { height: auto; padding: 0 10px 18px; border-bottom: 0; gap: 9px; }
.brand-mark { width: 26px; height: 26px; border-radius: 7px; background: var(--color-ink);
              font-family: var(--font-mono); font-size: var(--text-caps); }
.brand-name { font-size: var(--text-body); letter-spacing: -0.01em; }

.switch { margin: 0 2px 16px; padding: 3px; background: var(--color-sunk);
          border: 1px solid var(--color-hairline); border-radius: var(--radius-md); }
.switch a { padding: 6px 0; font-size: var(--text-label); border-radius: var(--radius-sm); }
.switch a.on { background: var(--color-surface); border: 1px solid var(--color-hairline);
               box-shadow: none; }

.nav { padding: 0; }
.nav-label { padding: 14px 10px 6px; font-weight: var(--font-weight-medium); }
.nav a { height: 36px; padding: 0 10px; gap: 10px; font-size: var(--text-body);
         color: var(--color-ink-strong); }
.nav a svg { flex: 0 0 auto; }
.nav a.on { background: var(--color-accent-soft); color: var(--color-accent); }
.nav-count { font-family: var(--font-mono); font-size: var(--text-caps);
             font-weight: var(--font-weight-medium); color: var(--color-ink-subtle); }
/* ⚠️ The attention dot is the whole point of the sidebar: it says WHICH screen needs him
   before he opens anything. Amber = a feed is missing, red = something is broken. */
.nav-dot { width: 6px; height: 6px; border-radius: var(--radius-pill); flex: 0 0 auto; }
.nav-dot.warn { background: var(--color-warn); }
.nav-dot.down { background: var(--color-down); }

/* ⚠️ `.nav a` beats a bare `.nav-cta` on specificity, so the white text lost to the inherited
   ink colour and the button rendered as a black rectangle with invisible text. */
.nav a.nav-cta, .nav-cta {
  height: 36px; margin-top: 10px; padding: 0 12px; border-radius: var(--radius-md);
  background: var(--color-ink); color: #fff; display: flex; align-items: center;
  font-size: var(--text-label); font-weight: var(--font-weight-semibold);
}
.nav a.nav-cta span, .nav-cta span { margin-left: auto; font-size: var(--text-caps);
                color: var(--color-ink-subtle); font-weight: var(--font-weight-regular); }

.me { margin-top: auto; padding: 16px 8px 2px; gap: 10px; }
.me-avatar { width: 28px; height: 28px; background: var(--color-tray); color: var(--color-ink-muted); }

/* ── topbar, the real one ────────────────────────────────────────────────── */
.topbar { justify-content: space-between; }
.topbar .live { display: flex; align-items: center; gap: var(--spacing-2);
                font-size: var(--text-label); color: var(--color-ink-muted); }
.topbar .live i { width: 6px; height: 6px; border-radius: var(--radius-pill);
                  background: var(--color-up); display: block; }
.topbar .live.stale i { background: var(--color-warn); }
.topbar .right { display: flex; align-items: center; gap: var(--spacing-3);
                 font-size: var(--text-label); color: var(--color-ink-muted); }
.topbar .right .av { width: 28px; height: 28px; border-radius: var(--radius-pill);
                     background: var(--color-tray); }

/* ── page header ─────────────────────────────────────────────────────────── */
.page { padding: 28px var(--spacing-6) var(--spacing-10); display: flex;
        flex-direction: column; gap: var(--spacing-6); }
.pagehead { display: flex; align-items: flex-end; justify-content: space-between; width: 100%; }
.pagehead h1 { margin: 0; font-size: var(--text-h1); line-height: var(--leading-h1);
               letter-spacing: -0.022em; font-weight: var(--font-weight-semibold); }
/* ⚠️ The subtitle is a SENTENCE about the current state, not a description of the page.
   "Nothing is on fire. One thing needs deciding and two need chasing." It is the single
   line that makes this feel like a dashboard someone built for him rather than a report. */
.pagehead .sub { font-size: var(--text-body); line-height: 18px;
                 color: var(--color-ink-muted); margin-top: 6px; }
.btn {
  font: inherit; font-size: var(--text-label); font-weight: var(--font-weight-medium);
  padding: 8px 14px; border-radius: var(--radius-md); cursor: pointer;
  background: var(--color-surface); border: 1px solid var(--color-hairline);
  color: var(--color-ink-strong); text-decoration: none; display: inline-block;
}
.btn.dark { background: var(--color-ink); border-color: var(--color-ink); color: #fff; }

/* ── KPI tile, the real one ──────────────────────────────────────────────── */
.kpis { display: flex; gap: var(--spacing-4); width: 100%; }
.kpi {
  flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: var(--spacing-3);
  padding: var(--spacing-5); border-radius: var(--radius-xl);
  background: var(--color-surface); border: 1px solid var(--color-hairline);
}
.kpi-top { height: 16px; display: flex; align-items: center; justify-content: space-between; }
.kpi-label { font-size: var(--text-caps); letter-spacing: var(--tracking-caps);
             text-transform: uppercase; font-weight: var(--font-weight-medium);
             color: var(--color-ink-muted); }
.kpi-value { display: flex; align-items: center; gap: 10px; }
.kpi-value b { font-size: var(--text-stat); line-height: var(--leading-stat);
               letter-spacing: var(--tracking-stat); font-weight: var(--font-weight-semibold);
               font-variant-numeric: tabular-nums; }
.kpi-note { font-size: var(--text-caption); line-height: var(--leading-caption);
            color: var(--color-ink-muted); }
/* the footer is divided off and pushed to the bottom, so four tiles of different
   content still line their last row up */
.kpi-foot { margin-top: auto; padding-top: var(--spacing-3); display: flex;
            flex-direction: column; gap: 6px;
            border-top: 1px solid var(--color-hairline-soft); }
.pill { padding: 3px var(--spacing-2); border-radius: var(--radius-pill);
        font-size: var(--text-caption); font-weight: var(--font-weight-semibold); }
.pill.up { background: var(--color-up-bg); color: var(--color-up); }
.pill.down { background: var(--color-down-bg); color: var(--color-down); }
.pill.flat { background: var(--color-neutral-pill); color: var(--color-ink-muted); }
.pill.warn { background: var(--color-warn-bg); color: var(--color-warn);
             font-size: var(--text-caps); padding: 2px var(--spacing-2); }

.meter { height: 6px; width: 100%; display: flex; border-radius: var(--radius-pill);
         overflow: hidden; background: var(--color-chart-track); }
.meter > i { display: block; height: 100%; }
.meter > i.fill { background: var(--color-accent); border-radius: var(--radius-pill); }
.meter > i.warn { background: var(--color-warn); }
.meter > i.warn2 { background: #D9A05B; }
.spark { display: block; width: 100%; height: 38px; }

/* ── chart card ──────────────────────────────────────────────────────────── */
.chart-card { flex: 2 1 0; min-width: 0; padding: 22px; border-radius: var(--radius-xl);
              background: var(--color-surface); border: 1px solid var(--color-hairline);
              display: flex; flex-direction: column; gap: 18px; }
.chart-head { display: flex; align-items: flex-start; justify-content: space-between; }
.chart-head .big { font-size: 34px; line-height: 38px; letter-spacing: var(--tracking-stat);
                   font-weight: var(--font-weight-semibold); font-variant-numeric: tabular-nums; }
.seg-row { display: flex; align-items: center; gap: 9px; }
.periods { background: var(--color-sunk); border: 1px solid var(--color-hairline); }
.periods a.on, .periods button.on { border: 1px solid var(--color-hairline); box-shadow: none; }
/* ⚠️ The GAP has to shrink as the bars multiply, or a 30-bar range renders as hairlines with
   more air than data. Klaviyo does the same: fewer bars, fatter bars. Set per chart from the
   bar count — see `gap_for()` in app.py. */
.chart-bars { gap: 14px; }
.chart-bars.dense { gap: 5px; }
.chart-bars.verydense { gap: 2px; }
.inout.dense { gap: 5px; }
.inout.verydense { gap: 2px; }
.inout-x.dense { gap: 5px; }
.inout-x.verydense { gap: 2px; }
.bar-x.now { color: var(--color-ink); font-weight: var(--font-weight-semibold); }
.legend { padding-top: 14px; border-top: 1px solid var(--color-hairline-soft);
          align-items: center; gap: var(--spacing-5); margin-top: 0; }
.legend .hint { margin-left: auto; color: var(--color-ink-subtle); }

/* ── the constraint card ─────────────────────────────────────────────────── */
/* ⚠️ The loudest object on the page, deliberately. The whole dashboard exists so he can
   see the ONE thing to fix this week; everything else is evidence for it. */
.constraint { padding: 22px; border-radius: var(--radius-xl); background: var(--color-ink);
              display: flex; flex-direction: column; gap: 14px; }
.constraint .eyebrow { font-size: var(--text-caps); letter-spacing: var(--tracking-caps);
                       text-transform: uppercase; font-weight: var(--font-weight-medium);
                       color: var(--color-ink-subtle); }
.constraint h2 { margin: 0; font-size: 22px; line-height: 29px; letter-spacing: -0.02em;
                 font-weight: var(--font-weight-semibold); color: #fff; }
.constraint p { margin: 0; font-size: var(--text-label); line-height: 19px; color: #B6BBC4; }
.constraint .owner { display: flex; align-items: center; gap: 9px; padding-top: 14px;
                     border-top: 1px solid #2A2E36; font-size: var(--text-label); }
.constraint .owner i { width: 22px; height: 22px; border-radius: var(--radius-pill);
                       background: #35383F; display: block; }
.constraint .owner b { font-weight: var(--font-weight-medium); color: #E6E8EC; }
.constraint .owner span { margin-left: auto; font-size: var(--text-caption);
                          color: var(--color-ink-subtle); }

/* ── worth knowing ───────────────────────────────────────────────────────── */
.knowing { flex: 1 1 auto; padding: 22px; border-radius: var(--radius-xl);
           background: var(--color-surface); border: 1px solid var(--color-hairline);
           display: flex; flex-direction: column; gap: 14px; }
.knowing .row { display: flex; align-items: flex-start; gap: 10px; }
.knowing .row + .row { padding-top: var(--spacing-3);
                       border-top: 1px solid var(--color-hairline-soft); }
.knowing .row i { width: 7px; height: 7px; margin-top: 5px; border-radius: var(--radius-pill);
                  background: var(--color-warn); flex: 0 0 auto; }
.knowing .row b { display: block; font-size: var(--text-label);
                  font-weight: var(--font-weight-medium); }
.knowing .row span { display: block; font-size: var(--text-caption); line-height: 17px;
                     color: var(--color-ink-muted); margin-top: 2px; }

.cols { display: flex; gap: var(--spacing-4); width: 100%; align-items: stretch; }
.cols .side { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
              gap: var(--spacing-4); }

/* ── panel table ─────────────────────────────────────────────────────────── */
.panel { width: 100%; border-radius: var(--radius-xl); overflow: hidden;
         background: var(--color-surface); border: 1px solid var(--color-hairline); }
.panel-head { display: flex; align-items: center; justify-content: space-between;
              padding: 17px 22px; border-bottom: 1px solid var(--color-hairline); }
.panel-head h2 { margin: 0; font-size: 15px; line-height: 18px;
                 font-weight: var(--font-weight-semibold); }
.panel-head .muted { font-size: var(--text-label); }
.panel-head a { font-size: var(--text-label); font-weight: var(--font-weight-semibold);
                color: var(--color-accent); }
.panel table { width: 100%; border-collapse: collapse; }
.panel thead th { height: 38px; padding: 0 0 0 var(--spacing-4); background: var(--color-sunk);
                  border-bottom: 1px solid var(--color-hairline); text-align: left;
                  font-size: var(--text-caps); letter-spacing: 0.06em; text-transform: uppercase;
                  font-weight: var(--font-weight-medium); color: var(--color-ink-muted); }
.panel thead th:first-child, .panel tbody td:first-child { padding-left: 22px; }
.panel thead th:last-child, .panel tbody td:last-child { padding-right: 22px; }
.panel tbody td { height: 52px; padding: 0 0 0 var(--spacing-4); font-size: var(--text-label);
                  border-bottom: 1px solid var(--color-hairline-soft); }
.panel tbody tr:last-child td { border-bottom: 0; }
.panel .num { text-align: right; font-family: var(--font-mono);
              font-weight: var(--font-weight-medium); }
.panel .nm { font-size: var(--text-body); font-weight: var(--font-weight-medium); }
.panel-foot { display: flex; align-items: center; justify-content: space-between;
              padding: 13px 22px; font-size: var(--text-label); color: var(--color-ink-muted); }
.panel-foot span { color: var(--color-ink-subtle); }
.tagchip { display: inline-block; white-space: nowrap; padding: 3px 6px; border-radius: var(--radius-xs);
           background: var(--color-sunk); border: 1px solid var(--color-hairline);
           font-family: var(--font-mono); font-size: var(--text-caps);
           font-weight: var(--font-weight-semibold); color: var(--color-ink-muted); }
.status { display: inline-block; padding: 3px 9px; border-radius: var(--radius-pill);
          font-size: var(--text-caps); font-weight: var(--font-weight-semibold);
          white-space: nowrap; }
.status.warn { background: var(--color-warn-bg); color: var(--color-warn); }
.status.flat { background: var(--color-neutral-pill); color: var(--color-ink-muted); }
.t-down { color: var(--color-down); }
.t-warn { color: var(--color-warn); }

@media (max-width: 1100px) {
  .kpis, .cols { flex-direction: column; }
}

/* ── margin-by-month column chart (Paper "04 · Revenue & profit") ─────────── */
/* ⚠️ Not the stacked bar. One column per month, the % printed ABOVE it, and the colour is
   the VERDICT against his goal: full accent cleared it, mid-blue fell short, amber failed
   outright. The number is the label, so there is no axis and nothing to decode. */
.mbm { display: flex; align-items: flex-end; gap: var(--spacing-3); width: 100%; }
.mbm .col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
            align-items: center; gap: var(--spacing-2); }
.mbm .v { font-size: var(--text-caption); font-weight: var(--font-weight-semibold);
          font-variant-numeric: tabular-nums; }
.mbm .b { width: 100%; border-radius: var(--radius-md) var(--radius-md) 0 0; }
.mbm .x { font-size: var(--text-caps); letter-spacing: var(--tracking-caps);
          text-transform: uppercase; color: var(--color-ink-muted); }
.mbm .hit  .v { color: var(--color-ink); }        .mbm .hit  .b { background: var(--color-kept); }
.mbm .near .v { color: var(--color-ink-muted); }  .mbm .near .b { background: #8FA3F2; }
.mbm .miss .v, .mbm .miss .x { color: var(--color-warn);
                               font-weight: var(--font-weight-semibold); }
.mbm .miss .b { background: var(--color-warn); }
.mbm .now .x { color: var(--color-ink); font-weight: var(--font-weight-semibold); }
.mbm .none .v { color: var(--color-chart-ghost); }
.mbm .none .b { background: var(--color-chart-track); }

/* ── split bar + legend rows ──────────────────────────────────────────────── */
.splitbar { display: flex; height: 10px; width: 100%; border-radius: var(--radius-pill);
            overflow: hidden; gap: 2px; }
.splitbar > i { display: block; height: 100%; }
.breakdown { display: flex; flex-direction: column; width: 100%; }
.breakdown .r { display: flex; align-items: center; gap: 10px; padding: 10px 0;
                border-bottom: 1px solid var(--color-hairline-soft); }
.breakdown .r:last-child { border-bottom: 0; }
.breakdown .r i { width: 8px; height: 8px; border-radius: var(--radius-pill); flex: 0 0 auto; }
.breakdown .r b { flex: 1 1 auto; font-size: var(--text-label);
                  font-weight: var(--font-weight-medium); }
.breakdown .r span { font-family: var(--font-mono); font-size: var(--text-label);
                     font-weight: var(--font-weight-medium); }
/* the card's own conclusion — the thing a column of numbers does not say out loud */
.takeaway { margin-top: auto; padding-top: 13px; display: flex; flex-direction: column;
            gap: 3px; border-top: 1px solid var(--color-hairline-soft); }
.takeaway b { font-size: var(--text-label); font-weight: var(--font-weight-semibold); }
.takeaway span { font-size: var(--text-caption); line-height: 17px;
                 color: var(--color-ink-muted); }
.kpi-foot .warn-text { color: var(--color-warn); }
.card-xl { padding: 22px; border-radius: var(--radius-xl); background: var(--color-surface);
           border: 1px solid var(--color-hairline); display: flex; flex-direction: column;
           gap: var(--spacing-4); }

/* ── money in vs money out (Paper "05 · Cash & collections") ──────────────── */
/* ⚠️ Mirrored, not stacked. In grows up from the centre line, out grows down, so a month
   where more left than arrived is visible as a shape rather than as a number to compare. */
.inout { display: flex; align-items: center; width: 100%; height: 190px; gap: var(--spacing-3); }
.inout .col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
              justify-content: center; height: 190px; gap: var(--spacing-1); position: relative;
              cursor: default; }
.inout .in  { background: var(--color-kept); border-radius: var(--radius-md) var(--radius-md) 0 0; }
.inout .out { background: var(--color-cost); border-radius: 0 0 var(--radius-md) var(--radius-md); }
.inout .col:hover .in, .inout .col:hover .out { filter: brightness(1.06); }
.inout .tip { bottom: auto; top: 0; }
.inout-x { display: flex; gap: var(--spacing-3); width: 100%; }
.inout-x div { flex: 1 1 0; text-align: center; font-size: var(--text-caps);
               letter-spacing: var(--tracking-caps); text-transform: uppercase;
               color: var(--color-ink-subtle); }
.inout-x div.now { color: var(--color-ink); font-weight: var(--font-weight-semibold); }

/* ── ageing rows ─────────────────────────────────────────────────────────── */
.ageing { display: flex; flex-direction: column; gap: var(--spacing-3); }
.ageing .a { display: flex; flex-direction: column; gap: 5px; }
.ageing .a .t { display: flex; justify-content: space-between; font-size: var(--text-label); }
.ageing .a .t span { font-family: var(--font-mono); font-weight: var(--font-weight-medium); }
.ageing .a.cold .t, .ageing .a.cold .t span { color: var(--color-ink-muted); }
.ageing .bar { height: 6px; border-radius: var(--radius-pill);
               background: var(--color-chart-track); }
.ageing .bar > i { display: block; height: 6px; border-radius: var(--radius-pill); }
.legend-note { margin-left: auto; color: var(--color-ink-subtle); }

/* ── cohort grid (Paper "06 · Clients & retention") ───────────────────────── */
.cohort-g { display: flex; flex-direction: column; width: 100%; gap: var(--spacing-1); }
.cohort-g .r { display: flex; align-items: center; gap: var(--spacing-1); }
.cohort-g .lbl { width: 96px; flex: 0 0 auto; font-size: var(--text-caption);
                 color: var(--color-ink-strong); }
.cohort-g .hd .lbl { font-size: var(--text-caps); letter-spacing: 0.06em;
                     text-transform: uppercase; font-weight: var(--font-weight-medium);
                     color: var(--color-ink-muted); }
.cohort-g .h { flex: 1 1 0; text-align: center; font-size: var(--text-caps);
               color: var(--color-ink-muted); }
.cohort-g .h.drop { color: var(--color-down); font-weight: var(--font-weight-semibold); }
.cohort-g .c { flex: 1 1 0; height: 30px; border-radius: var(--radius-xs);
               background: var(--color-sunk); }
/* four steps of "still here", darkest = most retained. ⚠️ An EMPTY cell is the sunk colour and
   means "that month has not happened yet" — not 0% retention. */
.cohort-g .c.s4 { background: var(--color-kept); }
.cohort-g .c.s3 { background: #5B74EC; }
.cohort-g .c.s2 { background: #A3B4F5; }
.cohort-g .c.s1 { background: #D7DEFC; }
.cohort-g .avg { margin-top: var(--spacing-2); padding-top: 10px;
                 border-top: 1px solid var(--color-hairline); }
.cohort-g .avg .lbl { font-weight: var(--font-weight-semibold); color: var(--color-ink); }
.cohort-g .avg .v { flex: 1 1 0; text-align: center; font-family: var(--font-mono);
                    font-size: var(--text-caption); }
.cohort-g .avg .v.drop { color: var(--color-down); font-weight: var(--font-weight-semibold); }
.scale { display: flex; align-items: center; gap: 9px; font-size: var(--text-caption);
         color: var(--color-ink-muted); }
.scale .sw { display: flex; gap: 3px; }
.scale .sw i { width: 18px; height: 10px; border-radius: 2px; display: block; }
/* ⚠️ The illustrative banner. Paper itself carries it — a worked example that is not labelled
   as one is indistinguishable from data, and this grid is the most believable thing on the
   page precisely because it looks like every cohort grid he has ever seen. */
.illustrative { padding-top: 13px; border-top: 1px solid var(--color-hairline-soft);
                display: flex; flex-direction: column; gap: 3px; }
.illustrative b { font-size: var(--text-label); font-weight: var(--font-weight-semibold); }
.illustrative span { font-size: var(--text-caption); line-height: 17px;
                     color: var(--color-ink-muted); }

/* ── inline share bar inside a table row (Paper "07 · Client results") ────── */
.rowbar { height: 8px; border-radius: var(--radius-pill); background: var(--color-chart-track); }
.rowbar > i { display: block; height: 8px; border-radius: var(--radius-pill);
              background: var(--color-kept); }
/* ⚠️ A client we cannot measure gets a FLAT, EMPTY track — not a zero-width fill on a live
   track. The two look different on purpose: one is "we measured nothing", the other is
   "we cannot measure". */
.rowbar.blind { background: var(--color-sunk); }
.ret { font-family: var(--font-mono); font-weight: var(--font-weight-medium);
       color: var(--color-kept); }

/* ⚠️ At 36px the ghost grey all but disappears, and an unknown that cannot be seen
   reads as an empty tile rather than as a missing number. Paper uses ink-subtle at
   stat size; match it. */
.kpi-value b.na, .tile-value.na { color: var(--color-ink-subtle); }

/* ── per-screen source banner (Paper puts this in the top bar of every personal artboard;
      base.html owns the real top bar, so it lands as the first row of the page) ───────── */
.notice { display: flex; align-items: center; gap: var(--spacing-2); width: 100%;
          padding: var(--spacing-3) var(--spacing-4); background: var(--color-surface);
          border: 1px solid var(--color-hairline); border-radius: var(--radius-lg);
          font-size: var(--text-label); color: var(--color-ink-muted); }
.notice > i { width: 6px; height: 6px; flex: 0 0 auto;
              border-radius: var(--radius-pill); background: var(--color-warn); }

/* Paper's progress tracks on the personal screens are 8px, not the 6px .ageing ships with */
.ageing .bar, .ageing .bar > i { height: 8px; }

/* ── bucket-vs-target rows (Paper "12 · Personal · Time") ──────────────────────────── */
.buckets { display: flex; flex-direction: column; }
.buckets .hd, .buckets .r { display: flex; align-items: center; gap: 14px; padding: 0 14px; }
.buckets .hd { height: 34px; background: var(--color-sunk); border-radius: var(--radius-md);
               font-size: var(--text-caps); letter-spacing: .06em; text-transform: uppercase;
               font-weight: var(--font-weight-medium); color: var(--color-ink-muted); }
.buckets .r { height: 46px; border-bottom: 1px solid var(--color-hairline-soft); }
.buckets .r:last-child { border-bottom: 0; }
.buckets .r.bottleneck { background: var(--color-warn-bg); }
.buckets .nm { flex: 1 1 auto; display: flex; align-items: center; gap: 9px;
               font-size: var(--text-body); }
.buckets .nm i { width: 9px; height: 9px; flex: 0 0 auto; border-radius: 3px;
                 background: var(--color-chart-track); }
.buckets .a, .buckets .t { flex: 0 0 auto; text-align: right;
                           font-family: var(--font-mono); font-size: var(--text-label); }
.buckets .a { width: 86px; }
.buckets .t { width: 76px; color: var(--color-ink-muted); }
.buckets .vs { width: 200px; flex: 0 0 auto; display: flex; align-items: center; gap: 10px; }
.buckets .vs .pct { width: 40px; flex: 0 0 auto; text-align: right;
                    font-family: var(--font-mono); font-size: var(--text-caption); }

/* ── the week, hour by hour. ⚠️ A hollow slot is NOT LOGGED, never "did nothing". ───── */
.weekgrid { flex: 1 1 auto; display: flex; flex-direction: column;
            justify-content: space-around; gap: 5px; }
.weekgrid .r { display: flex; align-items: center; gap: 5px; }
.weekgrid .d { width: 30px; flex: 0 0 auto; font-size: var(--text-caps);
               color: var(--color-ink-muted); }
.weekgrid .s { flex: 1 1 0; height: 22px; border-radius: var(--radius-xs);
               background: var(--color-sunk);
               box-shadow: inset 0 0 0 1px var(--color-hairline); }

/* ── legend swatch beside a heat strip — the same four states as .heat i ────────────── */
.heat-key { display: inline-block; width: 11px; height: 11px; border-radius: 2px;
            background: var(--color-sunk); box-shadow: inset 0 0 0 1px var(--color-hairline); }
.heat-key.hit  { background: var(--color-accent); box-shadow: none; }
.heat-key.part { background: var(--color-accent-border); box-shadow: none; }
.heat-key.miss { background: var(--color-tray); box-shadow: none; }

/* a card whose single figure centres in whatever height the row gives it (the donut) */
.ring { flex: 1 1 auto; display: flex; flex-direction: column;
        align-items: center; justify-content: center; gap: 18px; }

/* ── weight line (Personal · Weight) ──────────────────────────────────────── */
/* ⚠️ A weight chart MUST NOT start its y-axis at zero — a 1kg move inside a 58kg body is
   invisible against a zero baseline, and a chart that hides the only thing it measures is
   worse than no chart. The band is the real range, padded, and the axis labels say so. */
.linechart { position: relative; width: 100%; }
.linechart svg { display: block; width: 100%; height: 220px; overflow: visible; }
.linechart .grid { stroke: var(--color-hairline-soft); stroke-width: 1; }
.linechart .goal { stroke: var(--color-warn); stroke-width: 1.5; stroke-dasharray: 4 4; }
.linechart .line { fill: none; stroke: var(--color-kept); stroke-width: 2;
                   stroke-linecap: round; stroke-linejoin: round; }
.linechart .area { fill: var(--color-kept-soft); }
.linechart .dot { fill: var(--color-kept); }
.linechart .ax { font-size: var(--text-caps); fill: var(--color-ink-subtle);
                 font-family: var(--font-sans); }
.linechart-x { display: flex; justify-content: space-between; width: 100%;
               padding-top: var(--spacing-3); font-size: var(--text-caps);
               letter-spacing: var(--tracking-caps); text-transform: uppercase;
               color: var(--color-ink-subtle); }
/* a target that has not been set renders as a dashed empty row, never as a line at zero */
.goal-row { display: flex; align-items: center; gap: var(--spacing-3); padding: 12px 0;
            border-bottom: 1px solid var(--color-hairline-soft); }
.goal-row:last-child { border-bottom: 0; }
.goal-row .nm { flex: 1 1 auto; font-size: var(--text-label);
                font-weight: var(--font-weight-medium); }
.goal-row .now { width: 92px; text-align: right; font-family: var(--font-mono);
                 font-size: var(--text-label); font-weight: var(--font-weight-medium); }
.goal-row .tgt { width: 92px; text-align: right; font-family: var(--font-mono);
                 font-size: var(--text-label); color: var(--color-ink-muted); }
.goal-row .mark { width: 110px; text-align: right; }

/* ── the goal form (Personal · Weight) ────────────────────────────────────── */
/* ⚠️ He asked "show me where to do it" — so the targets are set on the screen that grades
   them, not by messaging me. An empty box clears a target; it never means zero. */
.goalform { margin-top: var(--spacing-5); padding-top: var(--spacing-4);
            border-top: 1px solid var(--color-hairline-soft);
            display: flex; flex-direction: column; gap: var(--spacing-3); }
.goalform label { display: flex; align-items: center; gap: var(--spacing-3);
                  font-size: var(--text-label); color: var(--color-ink-strong); }
.goalform label > input, .goalform label > select {
  margin-left: auto; width: 128px; font: inherit; font-size: var(--text-label);
  padding: 7px var(--spacing-3); border: 1px solid var(--color-hairline);
  border-radius: var(--radius-md); background: var(--color-sunk); color: var(--color-ink);
}
.goalform label > input:focus, .goalform label > select:focus {
  outline: 2px solid var(--color-accent-border); border-color: var(--color-accent);
  background: var(--color-surface);
}
.goalform-foot { display: flex; flex-direction: column; gap: var(--spacing-2);
                 margin-top: var(--spacing-2); }
.goalform-foot .muted { font-size: var(--text-caption); line-height: 16px; }
