/* Amos, Clean-Sheet 2026: the components. Load after tokens.css and
   foundation.css. See docs/cleansheet-2026/system.md. */

/* ---------------------------------------------------------------- button */
.btn {
  appearance: none;
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--s-2);
  min-height: var(--hit);
  padding: 0 var(--s-5);
  border: 1px solid transparent;
  border-radius: var(--r-control);
  font: var(--t-body);
  font-weight: 650;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--m-fast) var(--ease),
              border-color var(--m-fast) var(--ease),
              transform var(--m-fast) var(--ease);
}
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn--primary   { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover   { background: var(--accent-pressed); }
.btn--secondary { background: var(--panel); color: var(--ink-1); border-color: var(--line-strong); }
.btn--secondary:hover { background: var(--hover); }
.btn--danger    { background: var(--danger); color: var(--on-danger); }
.btn--danger:hover    { background: var(--danger-pressed); }
.btn--lg    { min-height: var(--hit-lg); font-size: 1.125rem; padding: 0 var(--s-6); }
.btn--block { display: flex; width: 100%; }
.btn--sm    { min-height: 36px; padding: 0 var(--s-3); font: var(--t-meta); font-weight: 650; }
.btn:disabled {
  background: var(--sunken); color: var(--ink-3); border-color: var(--hairline);
  cursor: not-allowed;
}
.btn[aria-busy="true"] { pointer-events: none; }
.btn[aria-busy="true"]::before {
  content: ""; width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(1turn); } }
@media (prefers-reduced-motion: reduce) {
  .btn[aria-busy="true"]::before { animation-duration: 2.4s; }
}
.btn-row { display: flex; flex-wrap: wrap; gap: var(--s-3); }
/* Equal shares while both labels fit. A button is never narrower than
   its label (min-width: auto is its min-content: the whole label at
   100%, the longest word once labels may wrap), so at a large text size
   one that cannot hold its label takes its own line instead. */
.btn-row > .btn { flex: 1 1 0; min-width: auto; }

/* ---------------------------------------------------------------- topbar */
.topbar {
  position: sticky; top: 0; z-index: 10;
  background: var(--canvas);
  padding: var(--s-3) var(--gutter);
  padding-top: max(var(--s-3), env(safe-area-inset-top));
}
.topbar__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-2);
  min-height: 44px;
}
.topbar__actions { display: flex; gap: var(--s-1); }

.icon-btn {
  appearance: none; border: 0; background: transparent; color: var(--ink-1);
  width: 44px; height: 44px; padding: 0; border-radius: var(--r-pill);
  display: inline-grid; place-items: center; cursor: pointer;
  text-decoration: none;
}
.icon-btn:hover { background: var(--hover); }

/* ----------------------------------------------------------------- panel */
.panel {
  background: var(--panel);
  border: 1px solid var(--hairline);
  border-radius: var(--r-panel);
  overflow: hidden;
}
.panel__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-4) var(--s-2);
}
.panel__body { padding: var(--s-2) var(--s-4) var(--s-4); }
.panel__foot { padding: var(--s-2) var(--s-4) var(--s-4); }
.panel__head .chip { flex: none; }
.section-label {
  font: var(--t-meta); font-weight: 700; color: var(--ink-2);
  margin: var(--s-6) 0 var(--s-2); padding: 0 var(--s-1);
}

/* ------------------------------------------------------------------- row */
.list { list-style: none; margin: 0; padding: 0; }
.row {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: var(--s-3);
  min-height: 64px;
  padding: var(--s-3) var(--s-4);
  color: inherit; text-decoration: none;
  position: relative;
}
a.row:hover { background: var(--hover); }
.list > li + li .row::before {
  content: ""; position: absolute; top: 0; right: 0;
  left: var(--row-inset, var(--s-4));
  border-top: 1px solid var(--hairline);
}
.row__lead { min-width: 52px; font: var(--t-meta); color: var(--ink-2); }

.row__body { min-width: 0; }
.row__title, .row__meta { display: block; }
.row__meta--wrap { white-space: normal; }
.row--compact { min-height: 56px; padding-top: var(--s-2); padding-bottom: var(--s-2); }
.row:not(:has(> .row__lead)) { grid-template-columns: 1fr auto; }
.row__title {
  font: var(--t-body); font-weight: 650;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row__meta {
  font: var(--t-meta); color: var(--ink-2); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row__trail { display: flex; align-items: center; gap: var(--s-2); color: var(--ink-3); font: var(--t-body); font-weight: 600; }
.row__trail .amount { color: var(--ink-1); }

/* THE LIST ROW'S THREE THINGS (round 2, item 6): the name at title
   weight, one status chip, the figure at the right edge - one line when
   it fits. When it does not, the chip and then the figure wrap to the
   next line; the name wraps too, and is never cut. The one meta line
   under it (.row__meta) is what yields: one line, then an ellipsis. */
.row3 {
  display: flex; flex-wrap: wrap; align-items: center;
  column-gap: var(--s-2); row-gap: 4px; min-width: 0;
}
.row3__name { flex: 0 1 auto; min-width: 0; font: var(--t-body); font-weight: 650; overflow-wrap: anywhere; }
.row3 > .status .chip { min-height: 24px; font-size: 0.8125rem; }
.row3__fig {
  flex: none; margin-left: auto;
  font: var(--t-body); font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.row3__fig:empty { display: none; }
.row:has(.row3) { grid-template-columns: minmax(0, 1fr); }

/* ------------------------------------------------------------------ chip */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 28px; padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  font: var(--t-meta); font-weight: 650; white-space: nowrap;
  background: var(--sunken); color: var(--ink-2);
}
.chip::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; flex: none;
}
.chip--plain::before { display: none; }
.chip[data-role="money-in"]  { background: var(--money-in-fill);  color: var(--money-in-ink); }
.chip[data-role="owed"]      { background: var(--owed-fill);      color: var(--owed-ink); }
.chip[data-role="attention"] { background: var(--attention-fill); color: var(--attention-ink); }
.chip[data-role="live"]      { background: var(--live-fill);      color: var(--live-ink); }
.chip[data-role="planned"]   { background: var(--planned-fill);   color: var(--planned-ink); }
.chip[data-role="live"]::before { animation: pulse 1.8s var(--ease) infinite; }
@keyframes pulse { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
  .chip[data-role="live"]::before { animation: none; }
}
/* A filter chip is a toggle, not a status. */
button.chip { border: 1px solid var(--hairline); background: var(--panel); color: var(--ink-1); cursor: pointer; height: 36px; }
button.chip::before { display: none; }
button.chip[aria-pressed="true"] { background: var(--ink-1); color: var(--canvas); border-color: var(--ink-1); }
.chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
/* A record's state (round 2, item 1): the chip from the one vocabulary
   (web/status_vocab.py, drawn by cs.status()), and its degree - "3 days
   late", "due Oct 1" - beside it as meta text, never inside it. */
.status { display: inline-flex; align-items: center; flex-wrap: wrap; gap: var(--s-1) var(--s-2); min-width: 0; vertical-align: middle; }
.chip-degree { font: var(--t-meta); color: var(--ink-2); }
/* A slot that has gone by today: quiet meta, never a chip (round 3, item 1). */
.is-was { font: var(--t-meta); font-weight: 600; color: var(--ink-3); }
.chip--count { text-decoration: none; }

/* ----------------------------------------------------------------- field */
.field { display: grid; gap: 6px; }

.input {
  appearance: none; width: 100%;
  min-height: 52px; padding: 0 var(--s-4);
  background: var(--panel); color: var(--ink-1);
  border: 1px solid var(--line-strong); border-radius: var(--r-control);
  font: var(--t-body);
  transition: border-color var(--m-fast) var(--ease);
}
textarea.input { padding: var(--s-3) var(--s-4); min-height: 104px; resize: vertical; }
select.input {
  padding-right: var(--s-10);
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%),
                    linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: right 22px center, right 16px center;
  background-size: 6px 6px; background-repeat: no-repeat;
}
.input::placeholder { color: var(--ink-3); }
.input:focus { outline: none; border-color: var(--focus); box-shadow: 0 0 0 1px var(--focus); }
.input[aria-invalid="true"] { border-color: var(--attention-mark); box-shadow: 0 0 0 1px var(--attention-mark); }
.input:disabled { background: var(--sunken); color: var(--ink-3); border-color: var(--hairline); }

/* ------------------------------------------------ sheet and modal motion */
/* The shell's action sheet and modals (shell.css) run these. */
@keyframes sheet-in { from { transform: translateY(24px); opacity: 0; } }
@keyframes modal-in { from { transform: scale(0.97); opacity: 0; } }

/* ------------------------------------------------------------ empty state */
.empty {
  display: grid; justify-items: center; text-align: center;
  gap: var(--s-2);
  padding: var(--s-12) var(--s-6);
}
.empty .mark { width: 56px; height: 56px; color: var(--ink-3); margin-bottom: var(--s-2); }
.empty .t-body { color: var(--ink-2); max-width: 30ch; margin-bottom: var(--s-4); }

/* ------------------------------------------------------------------ stat */
.stat {
  background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--r-panel);
  padding: var(--s-4);
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: var(--s-1) var(--s-3);
}

/* -------------------------------------------------------------- next-up */
.next {
  background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--r-panel);
  padding: var(--s-5) var(--s-4) var(--s-4);
}
.next__when { display: flex; align-items: baseline; gap: var(--s-2); }
.next__client { font: var(--t-title); letter-spacing: var(--track-title); margin: var(--s-3) 0 2px; }
.next .btn-row { margin-top: var(--s-5); }
.next .btn-row > .btn--primary { flex: 1.6; }

/* ------------------------------------------------- the phone's text size */
/* Round 4, A. An em in a media query is the phone's text size, so this
   width is in characters: at 390 it holds from about 130% text up (and
   on a small phone at any size). Rows then wrap to a second line rather
   than cut, and a button's label may take two lines rather than run off
   the edge. At 100% the rows keep round 2's one meta line. */
@media (max-width: 22em) {
  .row__title, .row__meta {
    white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere;
  }
  .btn { white-space: normal; text-align: center; padding-top: var(--s-2); padding-bottom: var(--s-2); }
}

/* A control drawn smaller than a thumb still takes a 44px tap (round 4,
   A): an invisible box centred on it, as wide and tall as it is or 44px,
   whichever is more. The chip that is a link, the quiet text actions,
   the small secondary button, the phone number and the name in a fact. */
/* The polish pass added the filter pills and report ranges (36px), the
   phone number under a name (and in the quick view), a name that links
   inside a row, and the colophon's Terms / Privacy. */
a.chip, .text-btn, .btn--sm, .field-v a,
.filter-pill, .range-chip, .identity__meta a, .more-colophon a, .qv-line a, .row-item .name a, .money-connect-note a, .range-hint a { position: relative; }
a.chip::after, .text-btn::after, .btn--sm::after, .field-v a::after,
.filter-pill::after, .range-chip::after, .identity__meta a::after, .more-colophon a::after,
.qv-line a::after, .row-item .name a::after, .money-connect-note a::after, .range-hint a::after {
  content: ""; position: absolute;
  top: min(0px, calc((100% - 44px) / 2)); bottom: min(0px, calc((100% - 44px) / 2));
  left: min(0px, calc((100% - 44px) / 2)); right: min(0px, calc((100% - 44px) / 2));
}
/* A checkbox: its label is the 44px box, pulled back by its own margin
   so the row lays out as it did around the 22px box. */
.check-hit { display: inline-grid; place-items: center; flex: none; width: 44px; height: 44px; margin: -11px; cursor: pointer; }

/* ------------------------------------------------------- the outbox */
/* docs/archive/round4-spec.md Part C. Work saved on the phone and waiting for
   signal is PLANNED - it will happen - so it wears planned blue; work
   the server refused and a person must look at wears attention red.
   Nothing here is money, so nothing here is green or amber. */
.outbox-chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 24px; padding: 0 var(--s-2);
  border-radius: var(--r-pill);
  background: var(--planned-fill); color: var(--planned-ink);
  font: var(--t-meta); font-weight: 650; white-space: normal;
}
.outbox-chip.is-attention { background: var(--attention-fill); color: var(--attention-ink); }
.job-row-sub .outbox-chip, .row__meta .outbox-chip { margin-right: var(--s-2); }
.outbox-record-line { margin: var(--s-2) 0 var(--s-3); }

.outbox-pill {
  display: inline-flex; align-items: center;
  min-height: var(--hit); padding: 0 var(--s-3);
  border: 0; border-radius: var(--r-pill);
  background: var(--planned-fill); color: var(--planned-ink);
  font: var(--t-meta); font-weight: 700; white-space: nowrap; cursor: pointer;
}
.outbox-pill.is-attention { background: var(--attention-fill); color: var(--attention-ink); }

.outbox-as-of {
  margin: 0 0 var(--s-3); padding: var(--s-2) var(--s-3);
  border-radius: var(--r-control);
  background: var(--sunken); color: var(--ink-2);
  font: var(--t-meta); font-weight: 650;
}

.outbox-saved-line { color: var(--planned-text); font-weight: 600; }
.outbox-refused-line { color: var(--attention-text); font-weight: 600; }

.outbox-sheet__title { font: var(--t-title); margin: 0 0 var(--s-3); }
.outbox-sheet__group { font: var(--t-meta); font-weight: 700; color: var(--ink-2); margin: var(--s-4) 0 var(--s-2); }
.outbox-sheet__note { color: var(--ink-2); margin: var(--s-3) 0; }
.outbox-item { padding: var(--s-3) 0; border-top: 1px solid var(--hairline); }
.outbox-item p { margin: 0; }
.outbox-item__what { font-weight: 650; overflow-wrap: anywhere; }
.outbox-item__meta { font: var(--t-meta); color: var(--ink-2); }
.outbox-item__why { margin: var(--s-1) 0 var(--s-3) !important; }
.outbox-item.is-attention .outbox-item__why, .outbox-item.is-notice .outbox-item__why { color: var(--attention-text); }
.outbox-sheet .stack > .btn { width: 100%; }

/* ------------------------------------------------- a customer's link */
/* Polish pass, 2: a link handed to a customer is two quiet buttons,
   Copy link and Preview (_cs.html link_actions), never the address. */
.link-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.link-actions > .btn { flex: 1 1 0; color: var(--ink-1); }   /* not the link purple a .field-v gives an <a> */
