/* The 22 Oct redesign from Claude Design: the component layer. Report 251.

   SOURCE: `port/redesign.css` in the Claude Design results, with the
   Components, Profile, CE Dashboard, CE Staff Tables, People and Onboarding
   designs. Loaded LAST in base.html (before the firm's brand <style>), so
   these rules win over app.css, components.css, design-system.css and the
   of-* sheets.

   HOW THE PORT WAS FITTED. The design names its classes `.btn`, `.card`,
   `.pill`, `.chip`, `.input`. This app's are `.ui-btn`, `.ui-card`,
   `.ui-pill`/`.ui-badge`/`.of-pill`, `.of-chip`/`.ui-chip`, `.ui-input`
   (108 templates use `.ui-btn`). So the design's rules are written here on
   the app's names, and nothing in a template was renamed. The design's
   new parts (`.dt`, `.hours-bar`, `.segs`, `.stepper`, `.side-list`,
   `.upload`, `.choice`, `.error-summary`, `.field__error`) keep the
   design's names, because nothing in the app used them.

   LEFT OUT ON PURPOSE:
     * `.rail`, `.tabbar`, and the phone rule that hides `.tabs` and
       `.side-list`: Danny, 22 Oct, "Phone tabs: leave them as they are".
       `.tabbar` is also the app's own phone tab bar (components.css §11).
     * `.card`, `.chip`, `.pill`, `.flash`: app.css already has old rules
       under those names (the assistant's suggestion chips, the flash
       messages), and a second meaning would repaint them.

   Every colour is a token. The firm tokens (--primary, --on-primary,
   --primary-press, --accent) come from brand_colors.py; the text greys
   (--ink-1..4) follow the firm's ink through `neutrals()` there. */

:root {
  --row-tint: #FBFAF7;
  --rd-sunken: #EDEAE3;           /* the darkest light ground (SURFACE_2) */
  --radius-s: 9px; --radius-m: 12px; --radius-l: 16px;
  --focus-ring: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
  --tap: 44px;
  /* The design's info and muted pairs; ok/warn/alert stay components.css's. */
  --rd-info-bg: #E7F0FB;  --rd-info-fg: #1B4E86;  --rd-info-dot: #2F6DF6;
  --rd-muted-bg: #ECE7DF; --rd-muted-fg: #6B6257; --rd-muted-dot: #8A7F70;
}

/* ── Buttons ─────────────────────────────────────────────────────────
   44 high, 10 radius, 15/500 (primary 600). Secondary is a white fill
   with the input edge. Quiet has no edge. Danger is QUIET (red words, no
   edge) and fills only on hover. Disabled loses its edge and its fill. */
.ui-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--tap); min-height: var(--tap); padding: 0 18px;
  border-radius: 10px; border: 1px solid transparent;
  font-family: var(--font-sans); font-size: 15px; font-weight: 500; line-height: 1;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.ui-btn:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.ui-btn .ms { font-size: 18px; }
.ui-btn--primary { background: var(--primary); border-color: var(--primary); color: var(--on-primary); font-weight: 600; }
.ui-btn--primary:hover:not(:disabled) { background: var(--primary-press); border-color: var(--primary-press); color: var(--on-primary); }
.ui-btn--secondary { background: #fff; color: var(--ink-1); border-color: var(--line-input); }
.ui-btn--secondary:hover:not(:disabled) { background: var(--rd-sunken); color: var(--ink-1); border-color: var(--line-input); }
.ui-btn--quiet, .ui-btn--ghost { background: transparent; border-color: transparent; color: var(--ink-1); }
.ui-btn--quiet:hover:not(:disabled), .ui-btn--ghost:hover:not(:disabled) { background: var(--rd-sunken); color: var(--ink-1); }
.ui-btn--danger { background: transparent; border-color: transparent; color: var(--alert-fg); }
.ui-btn--danger:hover:not(:disabled) { background: var(--alert-bg); color: var(--alert-fg); }
.ui-btn--sm { height: 36px; min-height: 36px; padding: 0 12px; font-size: 14px; border-radius: var(--radius-s); }
.ui-btn:disabled, .ui-btn[aria-disabled="true"] {
  opacity: 1; background: var(--rd-sunken); color: var(--ink-3); border-color: var(--line); cursor: not-allowed;
}
.btn-row { display: flex; flex-wrap: wrap; gap: 8px; }
/* Header and row buttons were pinned to 40 and 36 (of-base.css). */
.of-head__actions .ui-btn { height: var(--tap); min-height: var(--tap); }

/* ── Fields ──────────────────────────────────────────────────────────
   44 high, 10 radius, the input edge (3:1), the accent ring on focus. The
   LABEL SITS FLUSH with the input's edge: the 13px indent components.css §3
   gave every label is removed there, not undone here. */
.ui-input,
.ui-page input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="range"]):not([type="color"]),
.ui-page select:not([multiple]):not([size]),
.of-search, .of-select {
  min-height: var(--tap); height: var(--tap);
  border: 1px solid var(--line-input); border-radius: 10px; background-color: #fff;
  font-size: 15px; color: var(--ink-1);
}
.ui-page textarea { border-radius: 10px; border-color: var(--line-input); font-size: 15px; }
.ui-input:focus-visible, .ui-page input:focus-visible, .ui-page select:focus-visible,
.ui-page textarea:focus-visible, .of-search:focus-visible, .of-select:focus-visible {
  outline: none; border-color: var(--accent); box-shadow: var(--focus-ring);
}
.ui-page [aria-invalid="true"] { border-color: var(--alert-dot); box-shadow: 0 0 0 1px var(--alert-dot); }
.ui-label, .ui-field__label { font-size: 14px; font-weight: 500; color: var(--ink-1); }
.ui-field { gap: 6px; }
.ui-field__hint, .ui-hint { font-size: 13px; color: var(--ink-3); }

.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field__label { font-size: 14px; font-weight: 500; color: var(--ink-1); }
.field__label .opt { font-weight: 400; color: var(--ink-3); }
.field__hint { margin: 0; font-size: 13px; color: var(--ink-3); }
.field__error { display: flex; gap: 6px; align-items: center; margin: 0; font-size: 13.5px; color: var(--alert-fg); }
.field__error .ms { font-size: 18px; }
.select { position: relative; }
.search { position: relative; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 16px; }
.form-grid > .span-2 { grid-column: 1 / -1; }
.error-summary { display: flex; gap: 12px; padding: 14px 16px; border-radius: var(--radius-m); background: var(--alert-bg); color: var(--alert-fg); }
.error-summary > .ms { font-size: 22px; }
.error-summary__title { margin: 0; font-weight: 600; }
.error-summary ul { margin: 4px 0 0; padding-left: 18px; }
.error-summary a { color: var(--alert-fg); font-weight: 500; }

/* Choice card: a real radio inside a label, so it posts without JS. */
.choice { display: flex; gap: 14px; align-items: flex-start; padding: 16px; border: 1px solid var(--line); border-radius: var(--radius-m); background: #fff; cursor: pointer; }
.choice input { width: 20px; height: 20px; margin: 1px 0 0; accent-color: var(--accent); flex: none; }
.choice:has(input:checked) { border: 2px solid var(--accent); padding: 15px; background: color-mix(in srgb, var(--accent) 6%, #fff); }
.choice__title { font-size: 16px; font-weight: 600; }
.choice__sub { font-size: 14px; color: var(--ink-2); }

/* File upload: the input is real and reachable; the label is the target.
   With script, picking a file sends the form (data-upload-on-pick, chrome.js);
   without it, the form's own Save button is there. */
.upload { display: flex; flex-wrap: wrap; gap: 12px 16px; align-items: center; }
.upload__preview { width: 72px; height: 72px; border-radius: 50%; object-fit: cover; background: var(--rd-sunken); flex: none; }
.upload__actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.upload input[type=file] { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.upload input[type=file]:focus-visible + label { box-shadow: var(--focus-ring); }
.upload__help { flex-basis: 100%; margin: 0; font-size: 13px; color: var(--ink-3); }
html[data-nav="on"] .upload__save { display: none; }

/* ── Chips (filters with counts) ─────────────────────────────────── */
.of-chip, .ui-chip {
  height: 36px; padding: 0 14px; gap: 8px;
  border: 1px solid var(--line-input); background: #fff; color: var(--ink-1);
  font-size: 14px; font-weight: 500;
}
.of-chip__n { font-weight: 600; font-variant-numeric: tabular-nums; }
.of-chip[aria-current], .of-chip.is-on, .ui-chip[aria-current], .ui-chip.is-on {
  background: var(--ink-1); border-color: var(--ink-1); color: #fff;
}

/* ── Pills (status) ──────────────────────────────────────────────────
   One size, 24 high, never cut off; a dot for scanning, the word for the
   meaning. `.ui-badge`, `.ui-pill` and `.of-pill` are the same component. */
.ui-pill, .ui-badge, .of-pill {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  height: 24px; padding: 0 10px; box-sizing: border-box;
  border-radius: 999px; font-size: 12.5px; font-weight: 500; line-height: 1; white-space: nowrap;
}
.ui-pill::before, .of-pill::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none;
}
.ui-badge--bare::before { display: none; }
.of-pill--ok { background: var(--ok-bg); color: var(--ok-fg); }
.badge { display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: 6px; background: var(--rd-muted-bg); color: var(--rd-muted-fg); font-size: 12.5px; font-weight: 600; }

.pinned-note { display: flex; gap: 8px; align-items: center; margin: 0; font-size: 13px; color: var(--alert-fg); }
.pinned-note .ms { font-size: 18px; }

/* ── Cards ───────────────────────────────────────────────────────────
   16 radius, 24 padding on a desktop and 16 on a phone. A card's header
   row is the title, then its actions on the right. */
.ui-card { border-radius: var(--radius-l); padding: 24px; }
.ui-card--flush { padding: 0; }
.of-card, .of-list, .ui-table-wrap, .ui-rows, .ui-listcard { border-radius: var(--radius-l); }
.of-section { padding: 24px; }
.of-section--flush { padding: 0; }
.ui-card__head { align-items: center; }
.ui-card__title, .of-section__title { font-size: 18px; font-weight: 600; }
.card-edit { margin-left: auto; }
@media (max-width: 720px) {
  .ui-card, .of-section { padding: 16px; }
  .ui-card--flush, .of-section--flush { padding: 0; }
}

/* ── Tabs and the side list ──────────────────────────────────────────
   Tabs switch views of one page. On a phone they scroll sideways rather
   than wrap (the person record has six). */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); overflow-x: auto; scrollbar-width: none; margin: 0 0 20px; }
.tabs a { flex: none; height: var(--tap); padding: 0 12px; display: inline-flex; align-items: center; gap: 6px; color: var(--ink-3); font-weight: 500; text-decoration: none; }
.tabs a:hover { color: var(--ink-1); }
.tabs a[aria-current="page"] { color: var(--ink-1); font-weight: 600; box-shadow: inset 0 -2px 0 var(--ink-1); }
.tabs .badge { margin-left: 2px; }
.side-list { display: flex; flex-direction: column; gap: 2px; }
.side-list a { display: flex; align-items: center; gap: 12px; min-height: var(--tap); padding: 0 12px; border-radius: 10px; color: var(--ink-2); text-decoration: none; font-weight: 500; }
.side-list a:hover { background: var(--rd-sunken); color: var(--ink-1); }
.side-list a[aria-current="page"], .side-list a[aria-current="true"] { background: #fff; color: var(--ink-1); font-weight: 600; box-shadow: 0 1px 2px rgba(0,0,0,.06); }

/* ── Data table: the course-table pattern (report 250) ─────────────────
   <div class="dt" style="--cols: …" role="table">; rows are .dt__row; the
   header links sort (?sort=key / ?sort=-key); the footer totals the rows
   shown. On a phone a row is two lines: [data-m="1"] cells, then
   [data-m="2"] cells; the others hide. */
.dt { background: #fff; border: 1px solid var(--line); border-radius: var(--radius-l); overflow: hidden; }
.dt__row, .dt__head, .dt__foot { display: grid; grid-template-columns: var(--cols); gap: 0 16px; padding: 0 12px 0 20px; align-items: center; }
.dt__head { min-height: 44px; border-bottom: 1px solid var(--line); font-size: 13px; color: var(--ink-3); font-weight: 500; }
.dt__head a { display: inline-flex; align-items: center; gap: 2px; min-height: 44px; color: var(--ink-3); font-weight: 500; text-decoration: none; }
.dt__head a .ms { font-size: 16px; }
.dt__head a:hover, .dt__head [aria-sort]:not([aria-sort="none"]) a { color: var(--ink-1); font-weight: 600; }
.dt__row { position: relative; min-height: 64px; border-bottom: 1px solid var(--line-2); color: var(--ink-1); text-decoration: none; }
.dt__row:last-child { border-bottom: 0; }
.dt__row:hover { background: var(--row-tint); }
.dt__row.is-pinned { background: #FFFBF9; }
.dt__row > * { min-width: 0; }
.dt__row a.dt__link { color: var(--ink-1); text-decoration: none; }
.dt__row a.dt__link::after { content: ""; position: absolute; inset: 0; }
.dt__row a:not(.dt__link), .dt__row button, .dt__row form { position: relative; z-index: 1; }
.dt__two { display: flex; flex-direction: column; line-height: 1.3; }
.dt__two > :first-child { font-size: 15px; font-weight: 500; }
.dt__two > :last-child:not(:first-child) { font-size: 13px; color: var(--ink-3); }
.dt__two > *, .dt .clip { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dt .num { text-align: right; font-variant-numeric: tabular-nums; justify-content: flex-end; }
.dt__head .num a { justify-content: flex-end; }
.dt__chev { color: var(--ink-3); font-size: 20px; }
.dt__foot { min-height: 52px; background: var(--row-tint); font-size: 14px; color: var(--ink-2); border-top: 1px solid var(--line-2); }
.dt__empty { padding: 40px 20px; text-align: center; color: var(--ink-3); }
.dt-toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 12px; }
.dt-toolbar .of-search { flex: 1 1 260px; }
.dt-count { font-size: 13px; color: var(--ink-3); white-space: nowrap; }
.due-soon { color: var(--warn-fg); font-weight: 600; }
.overdue { color: var(--alert-fg); font-weight: 600; }
@media (max-width: 720px) {
  .dt__head { display: none; }
  .dt__row { display: flex; flex-wrap: wrap; align-items: center; min-height: 64px; padding: 12px 12px 12px 16px; gap: 4px 10px; }
  .dt__row > :not([data-m]) { display: none; }
  .dt__row > [data-m="1"] { flex: 1 1 calc(100% - 60px); font-size: 15px; font-weight: 500; }
  .dt__row > [data-m="end"] { flex: none; order: 1; }
  .dt__row > [data-m="2"] { order: 2; font-size: 13px; color: var(--ink-3); }
  .dt__row > [data-m="2"] + [data-m="2"]::before { content: "· "; }
  .dt__row > [data-m="3"] { order: 3; flex-basis: 100%; }
  .dt__foot { padding: 12px 16px; display: flex; justify-content: space-between; }
  .dt-toolbar .of-search { flex-basis: 100%; }
}

/* ── Bars ────────────────────────────────────────────────────────────
   Every progress bar fills with --accent: the raw brand fill fails 3:1 on
   the track under R1's green. Approved hours are solid, hours waiting for
   Licensing are hatched. */
.ui-progress__bar, .of-meter__fill { background: var(--accent); }
.of-progress--done .of-meter__fill { background: var(--accent); }
.hours-bar { height: 12px; border-radius: 6px; background: var(--chip-bg); display: flex; overflow: hidden; }
.hours-bar > .approved { background: var(--accent); }
.hours-bar > .waiting { background: repeating-linear-gradient(135deg, var(--accent) 0 2px, color-mix(in srgb, var(--accent) 25%, #fff) 2px 5px); }
.mini-bar { width: 64px; height: 4px; border-radius: 2px; background: var(--chip-bg); overflow: hidden; }
.mini-bar > span { display: block; height: 100%; background: var(--accent); }
/* One checkpoint bar for the board, the journey and the phone. */
.segs { list-style: none; margin: 0; padding: 0; display: flex; gap: 3px; min-width: 80px; }
.segs > li { flex: 1; height: 6px; border-radius: 3px; background: var(--chip-bg); }
.segs > [data-s="reached"] { background: var(--accent); }
.segs > [data-s="progress"] { background: var(--warn-dot); }
.segs > [data-s="lost"] { background: repeating-linear-gradient(135deg, var(--alert-dot) 0 2px, var(--alert-bg) 2px 4px); }

/* ── Stepper (intake) ─────────────────────────────────────────────── */
.stepper { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; counter-reset: step; }
.stepper li { counter-increment: step; display: flex; align-items: center; gap: 12px; min-height: var(--tap); padding: 0 10px; border-radius: 10px; color: var(--ink-3); font-weight: 500; }
.stepper li::before { content: counter(step); width: 26px; height: 26px; flex: none; border-radius: 50%; border: 1.5px solid var(--line-3); display: flex; align-items: center; justify-content: center; font-size: 12.5px; font-weight: 600; background: #fff; }
.stepper li.is-done { color: var(--ink-1); }
.stepper li.is-done::before { content: '✓'; background: var(--accent); border-color: var(--accent); color: #fff; }
.stepper li[aria-current="step"] { background: #fff; color: var(--ink-1); font-weight: 600; }
.stepper li[aria-current="step"]::before { border-color: var(--accent); color: var(--accent); }
.stepper li[hidden] { display: none; }

/* ── Phone: 720 px and less ──────────────────────────────────────── */
@media (max-width: 720px) {
  .ui-btn { height: 48px; min-height: 48px; }
  .ui-btn--sm { height: var(--tap); min-height: var(--tap); }
  .ui-input,
  .ui-page input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="hidden"]):not([type="submit"]):not([type="button"]):not([type="range"]):not([type="color"]),
  .ui-page select:not([multiple]):not([size]), .of-search, .of-select { height: 48px; min-height: 48px; font-size: 16px; }
  .of-chip, .ui-chip { height: var(--tap); }
  .form-grid { grid-template-columns: 1fr; }
}

/* Report 231: the onboarding intake's type. Its layout stays in the
   templates' own <style>; sizes live here, where the type lints can see a
   stylesheet (test_the_type_has_a_floor). */
.ix-title { font-size: 1.15rem; }
.ix-help { font-size: .9rem; }
