/* ==========================================================================
   Client Relations Manager design system. Direction A: Graphite (cool neutral charcoal,
   lilac accent, Schibsted Grotesk + DM Mono).

   Other directions (B Umber, C Slate stone) are written up in
   design/directions.md. To swap direction, replace the colour values in the
   token block below and the Google Fonts link in each page head. Nothing else
   in this file names a colour or a font.

   The accent means one thing: the primary action. Nothing else uses it.
   ========================================================================== */

/* ---------- 1. Tokens ----------
   Every colour is written once as light-dark(light value, dark value). Which
   one applies comes from color-scheme: the system setting by default, or the
   theme switch, which sets data-theme="light" or "dark" on <html>. Needs
   Chrome 123, Safari 17.5 or Firefox 120.

   Contrast (WCAG), measured on bg, white cards and surface-3. Light: text 16.9,
   text-2 7.3, text-3 5.1 (not on surface-3), line-ui 3.05 or better on every
   surface, chip and badge text 4.6 or better on its own tinted fill, white on
   accent 6.6 (hover 7.9, press 9.3). Dark: text 11.6 or better, text-2 5.9 or
   better, text-3 4.8 or better (not on surface-3), line-ui 3.2 or better on
   every surface, chip and badge text 5.0 or better on its own tinted fill,
   on-accent text 8.8. */
:root {
  color-scheme: light dark;

  /* Ground */
  --bg: light-dark(#F6F6F8, #141416);            /* page */
  --bg-sunken: light-dark(#EBEBF0, #0F0F11);     /* board columns, wells */
  --surface-1: light-dark(#FFFFFF, #1B1B1E);     /* cards, nav */
  --surface-2: light-dark(#F0F0F4, #232327);     /* inputs, raised */
  --surface-3: light-dark(#E3E3EA, #2D2D32);     /* selected, pressed, toast */
  --surface-pop: light-dark(#FFFFFF, #232327);   /* dialogs */

  /* Lines */
  --line: light-dark(#DEDEE5, #303036);          /* decorative hairlines only */
  --line-ui: light-dark(#80808D, #7A7A85);       /* borders of anything clickable, 3:1 or better */

  /* Text */
  --text: light-dark(#15151A, #ECECF0);
  --text-2: light-dark(#51515C, #A9A9B3);
  --text-3: light-dark(#686874, #8E8E99);        /* placeholders, faint meta. Not on surface-3 */

  /* Accent: primary action only */
  --accent: light-dark(#6B40C9, #B7A6FF);
  --accent-hover: light-dark(#6032BB, #C8BCFF);
  --accent-press: light-dark(#5623AE, #A592F5);
  --on-accent: light-dark(#FFFFFF, #14111F);

  /* Focus ring: neutral so the accent keeps one meaning */
  --focus: light-dark(#15151A, #F2F2F6);

  /* Status */
  --success: light-dark(#006D3A, #55C98F);
  --warning: light-dark(#845600, #E6B450);
  --danger: light-dark(#A43B35, #F58479);
  --danger-hover: light-dark(#8B322D, #F6958C);
  --on-danger: light-dark(#FFFFFF, #1A0B0A);      /* text on a solid danger fill, 6.4 or better */

  /* Role chip text colours. Backgrounds are derived from these. */
  --role-lead: light-dark(#5B606E, #A9AFBE);
  --role-prospect: light-dark(#5A5F1E, #B5BC78);
  --role-mockup_done: light-dark(#4B6B2F, #A6C47F);
  --role-contacted: light-dark(#715D37, #C9B38A);
  --role-talking: light-dark(#2F677C, #86BFD6);
  --role-interested: light-dark(#884E69, #E3A1BE);
  --role-deal: light-dark(#8F4F1F, #E09A6B);
  --role-completed: light-dark(#41684A, #9CC6A4);
  --role-managed: light-dark(#0E6A65, #78C7C0);
  --role-maybe_later: light-dark(#695C52, #B3A59A);
  --role-not_interested: light-dark(#5F5F68, #A9A9B2);

  /* Strengths of derived fills. Same in both themes. */
  --tint: 12%;              /* chip background tint */
  --badge-tint: 14%;        /* badge background tint */
  --danger-edge: 80%;       /* danger colour in the danger button border */

  --scrim: light-dark(rgba(20, 20, 32, 0.45), rgba(6, 6, 8, 0.66));
  --shadow-toast: 0 8px 24px light-dark(rgba(20, 20, 40, 0.16), rgba(0, 0, 0, 0.4));
  --shadow-dialog: 0 16px 48px light-dark(rgba(20, 20, 40, 0.22), rgba(0, 0, 0, 0.5));

  /* Type */
  --font-sans: "Schibsted Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "DM Mono", ui-monospace, "SF Mono", Consolas, monospace;
  --fs-xs: 0.75rem;         /* 12 */
  --fs-sm: 0.8125rem;       /* 13 */
  --fs-base: 0.9375rem;     /* 15 */
  --fs-md: 1.0625rem;       /* 17 */
  --fs-lg: 1.25rem;         /* 20 */
  --fs-xl: 1.625rem;        /* 26 */
  --fs-2xl: 2rem;           /* 32 */
  --fs-input: 1rem;         /* 16: form controls on touch screens, stops iOS zooming on focus */
  --lh-tight: 1.2;
  --lh-base: 1.5;

  /* Spacing, 4px base */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 20px;
  --s-6: 24px;
  --s-7: 32px;
  --s-8: 48px;

  /* Radii */
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 12px;
  --r-xl: 16px;

  /* Motion */
  --dur-fast: 120ms;
  --dur: 200ms;
  --dur-slow: 300ms;
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);

  /* Stacking. Dialogs use the top layer and need no number. */
  --z-sticky: 20;           /* filter bar */
  --z-nav: 50;              /* bottom nav, sidebar */
  --z-toast: 120;
  --z-skip: 200;            /* skip link, above everything */

  /* Layout and control heights */
  --tap: 44px;              /* minimum touch target */
  --control-sm: 36px;       /* small controls where a pointer is fine */
  --control-xs: 32px;
  --btn-sm: 34px;           /* painted height of a small button, tap area stays 44 */
  --chip-h: 24px;
  --topbar-h: 56px;
  --row-h: 56px;            /* list row */
  --nav-h: 64px;
  --sidebar-w: 220px;
  --content-max: 1120px;
  --gutter: 16px;
}

/* The theme switch. No data-theme means follow the system. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* ---------- 2. Base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body:has(dialog[open]) { overflow: hidden; }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 600;
  line-height: var(--lh-tight);
  letter-spacing: -0.01em;
  text-wrap: balance;
}
h1 { font-size: var(--fs-xl); }
h2 { font-size: var(--fs-lg); }
h3 { font-size: var(--fs-md); }
h4 { font-size: var(--fs-base); }

p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }
dl, dd { margin: 0; }
img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
hr { border: 0; border-top: 1px solid var(--line); margin: var(--s-5) 0; }

a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--line-ui);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
@media (hover: hover) {
  a:hover { text-decoration-color: var(--text); }
}

::selection { background: var(--surface-3); color: var(--text); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
:focus:not(:focus-visible) { outline: none; }

code, pre, kbd { font-family: var(--font-mono); font-size: 0.92em; }

[hidden] { display: none !important; }

/* Utilities */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.muted { color: var(--text-2); }
.mono { font-family: var(--font-mono); }
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.small { font-size: var(--fs-sm); }
.stack { display: flex; flex-direction: column; gap: var(--s-4); }
.stack--sm { gap: var(--s-2); }
.row { display: flex; align-items: center; gap: var(--s-3); }
.row--wrap { flex-wrap: wrap; }
.row--between { justify-content: space-between; }
.row--sm { gap: var(--s-2); }
@media (min-width: 900px) {
  .only-phone { display: none !important; }
}

/* Icons */
.icon {
  width: 20px; height: 20px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round;
}
.icon--sm { width: 16px; height: 16px; }

/* ---------- 3. App shell ---------- */
.skip-link {
  position: fixed; top: var(--s-2); left: var(--s-2); z-index: var(--z-skip);
  transform: translateY(-200%);
  background: var(--surface-3); color: var(--text);
  padding: var(--s-3) var(--s-4); border-radius: var(--r-md);
  border: 1px solid var(--line-ui);
}
.skip-link:focus { transform: none; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-3);
  min-height: var(--topbar-h);
  padding: 0 var(--gutter);
  padding-top: env(safe-area-inset-top);
  border-bottom: 1px solid var(--line);
}
.brand {
  display: inline-flex; align-items: center; gap: var(--s-2);
  color: var(--text); text-decoration: none;
  font-weight: 600; letter-spacing: -0.01em;
}
.brand__mark { width: 24px; height: 24px; flex: none; }
/* The name is 24 characters. It stays on one line when there is room, and breaks to two balanced
   lines ("Client Relations" / "Manager") when there is not. Never truncated. */
.brand { min-width: 0; }
.brand > span, .nav__brand > span { min-width: 0; line-height: 1.15; text-wrap: balance; }
.topbar > .row { flex: none; }
/* At 359px and under the Log out label is visually hidden (still read aloud), so the button is an icon
   like its neighbours and the name gets about 125px at 320: two lines, never three. */
@media (max-width: 359.98px) {
  .topbar [data-logout] { width: var(--btn-sm); padding: 0; }
  .topbar [data-logout] > span {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
}

/* Bottom nav on phone */
.nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-nav);
  display: flex; flex-direction: column;
  background: var(--surface-1);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom);
}
.nav__brand, .nav__foot { display: none; }
.nav__list { display: grid; grid-template-columns: repeat(5, 1fr); }
.nav__link {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px;
  min-height: var(--nav-h);
  padding: var(--s-2) 2px;
  color: var(--text-2);
  text-decoration: none;
  font-size: var(--fs-xs);
  font-weight: 500;
}
.nav__link .icon { width: 22px; height: 22px; }
.nav__link[aria-current="page"] { color: var(--text); font-weight: 600; }
/* A link shown only in the desktop sidebar, so the phone bottom bar stays at five items. */
@media (max-width: 899.98px) {
  .nav__link--desktop-only { display: none; }
}
/* Count on a nav item. Bottom bar: on the icon corner. Sidebar: at the right end of the link. */
.nav__badge { position: absolute; top: 6px; left: calc(50% + 6px); }
.nav__link[aria-current="page"]::before {
  content: ""; position: absolute; top: 0; left: 24%; right: 24%;
  height: 2px; background: var(--text); border-radius: 0 0 2px 2px;
}
@media (hover: hover) {
  .nav__link:hover { color: var(--text); }
}

.app-main {
  padding: var(--s-4) var(--gutter);
  padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--s-7));
}
.app-main > * { max-width: var(--content-max); margin-inline: auto; }
.app-main--wide > * { max-width: none; }

/* Desktop sidebar */
@media (min-width: 900px) {
  :root { --gutter: 32px; }
  .topbar { display: none; }
  .nav {
    top: 0; right: auto; bottom: 0;
    width: var(--sidebar-w);
    border-top: 0; border-right: 1px solid var(--line);
    padding: var(--s-5) var(--s-3) var(--s-4);
  }
  .nav__brand {
    display: flex; align-items: center; gap: var(--s-2);
    padding: var(--s-1) var(--s-3) var(--s-5);
    font-weight: 600; letter-spacing: -0.01em;
  }
  .nav__list { display: flex; flex-direction: column; gap: 2px; }
  .nav__link {
    flex-direction: row; justify-content: flex-start; gap: var(--s-3);
    min-height: 40px; padding: 0 var(--s-3);
    border-radius: var(--r-md);
    font-size: var(--fs-base);
  }
  .nav__link .icon { width: 20px; height: 20px; }
  .nav__badge { position: static; margin-left: auto; }
  .nav__link[aria-current="page"] { background: var(--surface-3); }
  .nav__link[aria-current="page"]::before { display: none; }
  @media (hover: hover) {
    .nav__link:hover { background: var(--surface-2); }
    .nav__link[aria-current="page"]:hover { background: var(--surface-3); }
  }
  .nav__foot { display: block; margin-top: auto; }
  .app-main {
    margin-left: var(--sidebar-w);
    padding: var(--s-7) var(--gutter) var(--s-8);
  }
}

/* Page header */
.page-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: var(--s-3) var(--s-4);
  margin-bottom: var(--s-5);
}
.page-head__text { min-width: 0; flex: 1 1 220px; }
.page-head__title { overflow-wrap: anywhere; }
.page-head__sub { margin-top: var(--s-1); color: var(--text-2); font-size: var(--fs-base); }
.page-head__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); align-items: center; }

.back-link {
  display: inline-flex; align-items: center; gap: var(--s-1);
  min-height: var(--tap); margin-bottom: var(--s-1);
  color: var(--text-2); text-decoration: none; font-size: var(--fs-sm);
}
@media (hover: hover) { .back-link:hover { color: var(--text); } }

.section { margin-top: var(--s-7); }
.section:first-child { margin-top: 0; }
.section__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  margin-bottom: var(--s-3);
}
.section__title { font-size: var(--fs-md); }
.section__meta { color: var(--text-2); font-size: var(--fs-sm); font-weight: 500; font-variant-numeric: tabular-nums; }

/* ---------- 4. Buttons ---------- */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text);
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn--secondary { background: var(--surface-2); border-color: var(--line-ui); }
.btn--ghost { color: var(--text-2); font-weight: 500; }
.btn--danger {
  background: color-mix(in srgb, var(--danger) 12%, var(--surface-1));
  border-color: color-mix(in srgb, var(--danger) var(--danger-edge), var(--bg));
  color: var(--danger);
}
@media (hover: hover) {
  .btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
  .btn--secondary:hover { background: var(--surface-3); }
  .btn--ghost:hover { background: var(--surface-2); color: var(--text); }
  .btn--danger:hover { background: color-mix(in srgb, var(--danger) 20%, var(--surface-1)); }
}
.btn--primary:active { background: var(--accent-press); border-color: var(--accent-press); }
.btn--secondary:active { background: var(--surface-3); }
.btn--ghost:active { background: var(--surface-3); color: var(--text); }
/* Solid danger: only for the last step of a delete (typed confirm). */
.btn--danger-solid { background: var(--danger); border-color: var(--danger); color: var(--on-danger); }
/* Quiet danger: a ghost icon or text button for delete inside a row. */
.btn--ghost.btn--danger-quiet { color: var(--danger); }
@media (hover: hover) {
  .btn--danger-solid:hover { background: var(--danger-hover); border-color: var(--danger-hover); }
  .btn--ghost.btn--danger-quiet:hover { background: color-mix(in srgb, var(--danger) 12%, var(--surface-1)); color: var(--danger); }
}
.btn--danger-solid:active { background: var(--danger-hover); border-color: var(--danger-hover); }
.btn--sm { min-height: var(--btn-sm); padding: 0 var(--s-3); font-size: var(--fs-sm); }
.btn--sm::after { content: ""; position: absolute; inset: -5px -2px; } /* keeps a 44px tap area high */
.btn--block { display: flex; width: 100%; }
.btn--icon { width: var(--tap); padding: 0; }
.btn--icon.btn--sm { width: var(--btn-sm); }
/* Painted 34px square, tap area a full 44px square. */
.btn--icon.btn--sm::after { inset: calc((var(--btn-sm) - var(--tap)) / 2); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; pointer-events: none; }
.btn[aria-busy="true"] { opacity: 0.7; cursor: progress; pointer-events: none; }

/* ---------- 5. Form fields ---------- */
.form-grid { display: grid; gap: var(--s-4); }
@media (min-width: 700px) {
  .form-grid--2 { grid-template-columns: 1fr 1fr; }
  .form-grid--2 > .field--full { grid-column: 1 / -1; }
}
.form-actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }

.field { display: flex; flex-direction: column; min-width: 0; }
.field > * + * { margin-top: 6px; }
/* The kit always renders the error line, empty until there is an error. Empty it takes no space. */
.field > .field__error:empty { margin-top: 0; }
.field__label { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.field__help { font-size: var(--fs-sm); color: var(--text-2); }
.field__error { font-size: var(--fs-sm); color: var(--danger); font-weight: 500; }

.input, .textarea, .select {
  display: block; width: 100%; min-width: 0;
  min-height: var(--tap);
  padding: 0 var(--s-3);
  background: var(--surface-2);
  border: 1px solid var(--line-ui);
  border-radius: var(--r-md);
  color: var(--text);
  font-size: var(--fs-input);
  line-height: 1.4;
  transition: border-color var(--dur-fast) var(--ease);
}
.textarea { padding: 10px var(--s-3); min-height: 96px; resize: vertical; }
.input::placeholder, .textarea::placeholder { color: var(--text-3); opacity: 1; }
.input:focus-visible, .textarea:focus-visible, .select:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 1px; border-color: var(--text);
}
.input[disabled], .textarea[disabled], .select[disabled] { opacity: 0.5; cursor: not-allowed; }
.input[readonly] { color: var(--text-2); }
.input[type="date"] { min-width: 0; -webkit-appearance: none; appearance: none; }
.select {
  appearance: none; -webkit-appearance: none;
  padding-right: 40px;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-2) 50%),
    linear-gradient(135deg, var(--text-2) 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
/* Small controls for inside cards and rows. Full 44px and 16px type on touch
   screens, 36px with smaller type only where a mouse is the main input. */
.input--sm, .select--sm { min-height: var(--tap); font-size: var(--fs-input); }
.input--sm { padding: 0 var(--s-2); }
.select--sm { padding-left: var(--s-2); }
@media (min-width: 900px) and (pointer: fine) {
  .input--sm, .select--sm { min-height: var(--control-sm); font-size: var(--fs-base); }
}

.field--error .input, .field--error .textarea, .field--error .select,
.input[aria-invalid="true"], .textarea[aria-invalid="true"], .select[aria-invalid="true"] {
  border-color: var(--danger);
}

/* Checkbox and radio */
.check {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: var(--tap);
  cursor: pointer;
  font-size: var(--fs-base);
}
.check input[type="checkbox"], .check input[type="radio"] {
  appearance: none; -webkit-appearance: none;
  flex: none; width: 22px; height: 22px; margin: 0;
  background: var(--surface-2);
  border: 1.5px solid var(--line-ui);
  border-radius: var(--r-sm);
  display: grid; place-content: center;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.check input[type="radio"] { border-radius: 50%; }
.check input[type="checkbox"]::after {
  content: ""; width: 11px; height: 6px;
  border-left: 2.5px solid var(--bg); border-bottom: 2.5px solid var(--bg);
  transform: translateY(-1px) rotate(-45deg) scale(0);
  transition: transform var(--dur-fast) var(--ease);
}
.check input[type="radio"]::after {
  content: ""; width: 10px; height: 10px; border-radius: 50%; background: var(--bg);
  transform: scale(0); transition: transform var(--dur-fast) var(--ease);
}
.check input:checked { background: var(--text); border-color: var(--text); }
.check input[type="checkbox"]:checked::after { transform: translateY(-1px) rotate(-45deg) scale(1); }
.check input[type="radio"]:checked::after { transform: scale(1); }
.check input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.check input[disabled] { opacity: 0.45; cursor: not-allowed; }
.check__text { min-width: 0; }

/* ---------- 6. Chips and badges ---------- */
.chip {
  --chip-fg: var(--text-2);
  display: inline-flex; align-items: center; gap: 6px;
  min-height: var(--chip-h); padding: 0 var(--s-2);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--chip-fg) var(--tint), var(--surface-2));
  color: var(--chip-fg);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}
.chip--success { --chip-fg: var(--success); }
.chip--warning { --chip-fg: var(--warning); }
.chip--problem { --chip-fg: var(--danger); }
.chip--neutral { --chip-fg: var(--text-2); }
/* Marks a client an agent added. Mono type tells it apart from role chips. */
.chip--agent { --chip-fg: var(--text-2); font-family: var(--font-mono); font-weight: 500; }

.chip--role[data-role="lead"] { --chip-fg: var(--role-lead); }
.chip--role[data-role="prospect"] { --chip-fg: var(--role-prospect); }
.chip--role[data-role="mockup_done"] { --chip-fg: var(--role-mockup_done); }
.chip--role[data-role="contacted"] { --chip-fg: var(--role-contacted); }
.chip--role[data-role="talking"] { --chip-fg: var(--role-talking); }
.chip--role[data-role="interested"] { --chip-fg: var(--role-interested); }
.chip--role[data-role="deal"] { --chip-fg: var(--role-deal); }
.chip--role[data-role="completed"] { --chip-fg: var(--role-completed); }
.chip--role[data-role="managed"] { --chip-fg: var(--role-managed); }
.chip--role[data-role="maybe_later"] { --chip-fg: var(--role-maybe_later); }
.chip--role[data-role="not_interested"] { --chip-fg: var(--role-not_interested); }
/* Archived roles are hollow so they read as set aside */
.chip--role[data-role="maybe_later"], .chip--role[data-role="not_interested"] {
  background: transparent;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--chip-fg) 45%, transparent);
}

.badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: var(--r-sm);
  background: var(--surface-3); color: var(--text);
  font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.badge--warning {
  background: color-mix(in srgb, var(--warning) var(--badge-tint), var(--surface-2)); color: var(--warning);
}

/* Filter chip bar */
.filter-bar {
  position: sticky; top: 0; z-index: var(--z-sticky);
  margin-inline: calc(var(--gutter) * -1);
  padding: var(--s-2) var(--gutter);
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--s-4);
}
.filter-bar__scroll {
  display: flex; gap: var(--s-2); align-items: center;
  overflow-x: auto; overscroll-behavior-x: contain;
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
  -webkit-overflow-scrolling: touch;
}
/* Edge cue: a row that scrolls sideways fades out where more is hidden. The
   pipeline board and each of its columns use the same fade (sideways and down).
   Browsers with scroll-driven animations fade only the side that has more
   (the left fade grows in as you scroll, the right fade goes away at the end),
   and nothing fades when the row fits. Others keep a fixed fade the width of
   the right gutter, which sits on empty padding when the row is at its end. The board and columns have no fixed fade. */
@property --fade-start { syntax: "<length>"; inherits: false; initial-value: 0px; }
@property --fade-end { syntax: "<length>"; inherits: false; initial-value: 0px; }
.filter-bar__scroll {
  --fade-end: var(--gutter);
  mask-image: linear-gradient(to right, transparent, #000 var(--fade-start), #000 calc(100% - var(--fade-end)), transparent);
}
@keyframes edge-fade-start { from { --fade-start: 0px; } to { --fade-start: 28px; } }
@keyframes edge-fade-end { from { --fade-end: 28px; } to { --fade-end: 0px; } }
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .filter-bar__scroll, .board {
      --fade-end: 0px;
      mask-image: linear-gradient(to right, transparent, #000 var(--fade-start), #000 calc(100% - var(--fade-end)), transparent);
      animation: edge-fade-start linear both, edge-fade-end linear both;
      animation-timeline: scroll(self inline), scroll(self inline);
      animation-range: 0px 28px, calc(100% - 28px) 100%;
    }
    .board__body {
      --fade-end: 0px;
      mask-image: linear-gradient(to bottom, transparent, #000 var(--fade-start), #000 calc(100% - var(--fade-end)), transparent);
      animation: edge-fade-start linear both, edge-fade-end linear both;
      animation-timeline: scroll(self block), scroll(self block);
      animation-range: 0px 28px, calc(100% - 28px) 100%;
    }
  }
}

/* A row that wraps instead of scrolling, so nothing is ever off screen.
   Add filter-bar__scroll--wrap for a short row on a phone (Money date range).
   Every filter row wraps on a wide screen with a mouse. */
.filter-bar__scroll--wrap {
  flex-wrap: wrap; overflow: visible;
  margin-inline: 0; padding-inline: 0;
  row-gap: 0;
  mask-image: none; animation: none;
}
@media (min-width: 900px) and (pointer: fine) {
  .filter-bar__scroll {
    flex-wrap: wrap; overflow: visible;
    margin-inline: 0; padding-inline: 0;
    row-gap: 0;
    mask-image: none; animation: none;
  }
}
.filter-bar__search { margin-bottom: var(--s-2); }
.filter-chip {
  flex: none;
  display: inline-flex; align-items: center; gap: var(--s-2);
  /* 44px tap height, 34px painted: transparent border + inset ring */
  min-height: var(--tap);
  padding: 0 var(--s-3);
  border: 0; border-block: 5px solid transparent;
  background: var(--surface-1);
  background-clip: padding-box;
  box-shadow: inset 0 0 0 1px var(--line-ui);
  border-radius: var(--r-lg);
  color: var(--text-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.filter-chip:focus-visible { outline-offset: -4px; }
.filter-chip__count { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-2); }
.filter-chip[aria-pressed="true"], .filter-chip.is-active {
  background-color: var(--surface-3);
  box-shadow: inset 0 0 0 1.5px var(--text);
  color: var(--text); font-weight: 600;
}
.filter-chip[aria-pressed="true"] .filter-chip__count, .filter-chip.is-active .filter-chip__count { color: var(--text); }
@media (hover: hover) {
  .filter-chip:hover { color: var(--text); background-color: var(--surface-2); }
  .filter-chip[aria-pressed="true"]:hover { background-color: var(--surface-3); }
}

/* ---------- 7. Cards ---------- */
.card {
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-4);
}
.card__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  margin-bottom: var(--s-3);
}
.card__title { font-size: var(--fs-md); }
.card__foot { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line); }
a.card {
  display: block; color: inherit; text-decoration: none;
}
@media (hover: hover) {
  a.card:hover { background: var(--surface-2); border-color: var(--line-ui); }
}

/* Client card (list and pipeline) */
.client-card {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-3) var(--s-4);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  color: var(--text);
  text-decoration: none;
  min-width: 0;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
@media (hover: hover) {
  a.client-card:hover { background: var(--surface-2); border-color: var(--line-ui); }
}
a.client-card:active { background: var(--surface-2); }
.client-card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-3); }
.client-card__name {
  font-size: var(--fs-md); font-weight: 600; line-height: 1.25; min-width: 0;
  overflow-wrap: anywhere;
}
.client-card__name a { color: inherit; text-decoration: none; }
@media (hover: hover) { .client-card__name a:hover { text-decoration: underline; text-underline-offset: 3px; } }
.client-card__sub { color: var(--text-2); font-size: var(--fs-sm); }
.client-card__chips { display: flex; flex-wrap: wrap; gap: 6px; }
.client-card__foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  font-size: var(--fs-sm); color: var(--text-2);
}
.client-card__move { margin-top: var(--s-1); }
.client-card--compact { padding: var(--s-3); gap: 6px; border-radius: var(--r-md); }
.client-card--compact .client-card__name { font-size: var(--fs-base); }
.client-card--compact .client-card__sub {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1; overflow: hidden;
}

/* Move control (pipeline card, phone first). A 32px painted square with an
   arrow icon and a 44px tap area. The native select sits invisibly on top, so
   tapping opens the system picker: no extra row on the card. The first option
   is an empty "Move to" that the picker shows as its title. */
.move {
  position: relative; flex: none;
  width: var(--tap); height: var(--tap);
  margin: calc((var(--tap) - var(--control-xs)) / -2);
}
.move::before, .move::after { content: ""; position: absolute; pointer-events: none; }
.move::before {
  inset: calc((var(--tap) - var(--control-xs)) / 2);
  border-radius: var(--r-md);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--line-ui);
  transition: background-color var(--dur-fast) var(--ease);
}
.move::after {
  inset: 0; margin: auto; width: 18px; height: 18px;
  background: var(--text-2);
  -webkit-mask: var(--move-icon) center / contain no-repeat;
  mask: var(--move-icon) center / contain no-repeat;
  --move-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h11M11 7l5 5-5 5M20 5v14'/%3E%3C/svg%3E");
}
.move__select {
  position: absolute; inset: 0;
  width: 100%; height: 100%; margin: 0; padding: 0;
  border: 0; border-radius: var(--r-md);
  appearance: none; -webkit-appearance: none;
  background: transparent; color: transparent;
  font-size: var(--fs-input);
  cursor: pointer;
}
.move__select option { color: var(--text); background: var(--surface-2); }
.move__select:focus-visible { outline: 2px solid var(--focus); outline-offset: -4px; }
.move__select[disabled] { cursor: not-allowed; }
.move:has(.move__select[disabled]) { opacity: 0.45; }
@media (hover: hover) {
  .move:hover::before { background: var(--surface-3); }
}
.client-card[draggable="true"] { cursor: grab; }
.client-card.is-dragging { opacity: 0.45; border-style: dashed; border-color: var(--line-ui); }

/* ---------- 8. Data table (card list under 700px) ---------- */
.table-wrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.table th {
  padding: var(--s-2) var(--s-3);
  text-align: left; white-space: nowrap;
  font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--text-2);
  border-bottom: 1px solid var(--line-ui);
}
.table td {
  padding: var(--s-3);
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
  color: var(--text);
}
.table .num { text-align: right; }
.table__title { font-weight: 600; font-size: var(--fs-base); }
.table__title a { color: var(--text); text-decoration: none; }
@media (hover: hover) {
  .table tbody tr:hover { background: var(--surface-1); }
}

@media (max-width: 699.98px) {
  .table-wrap { overflow: visible; }
  .table thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  }
  .table, .table tbody, .table tr, .table td { display: block; }
  .table tr {
    margin-bottom: var(--s-3);
    padding: var(--s-3) var(--s-4);
    background: var(--surface-1);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
  }
  .table td {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px var(--s-2);
    padding: 5px 0;
    border: 0;
    text-align: left;
  }
  .table td::before {
    content: attr(data-label);
    flex: 0 0 7.5rem;
    font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-2);
  }
  .table td.table__title { display: block; padding: 0 0 var(--s-2); font-size: var(--fs-md); }
  .table td.table__title::before, .table td[data-label=""]::before { content: none; }
  .table .num { text-align: left; }
}

/* ---------- 9. Pipeline board ---------- */
.board {
  display: flex; align-items: flex-start; gap: var(--s-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--gutter);
  margin-inline: calc(var(--gutter) * -1);
  padding: 0 var(--gutter) var(--s-3);
  overscroll-behavior-x: contain;
}
.board__col {
  flex: 0 0 84%; max-width: 340px;
  scroll-snap-align: start;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.board__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
  padding: var(--s-3) var(--s-3) var(--s-1);
}
.board__title { font-size: var(--fs-base); font-weight: 600; }
.board__hint { padding: 0 var(--s-3); color: var(--text-2); font-size: var(--fs-xs); }
.board__body {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-2);
  min-height: 96px;
  /* A long column scrolls inside itself, so the page stays one screen tall. */
  max-height: max(320px, calc(100dvh - 15rem));
  overflow-y: auto; overscroll-behavior-y: contain;
}
.board__empty {
  padding: var(--s-4) var(--s-2); text-align: center;
  color: var(--text-3); font-size: var(--fs-sm);
}
.board__col.is-over { border-color: var(--text-2); background: var(--surface-1); }
.board__col.is-over .board__body { outline: 1.5px dashed var(--line-ui); outline-offset: -4px; border-radius: var(--r-md); }
@media (min-width: 900px) {
  .board { scroll-snap-type: none; margin-inline: 0; padding-inline: 0; }
  .board__col { flex: 1 1 0; min-width: 216px; max-width: none; }
}

.disclosure { border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface-1); }
.disclosure > summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  min-height: var(--tap); padding: 0 var(--s-4);
  cursor: pointer; font-weight: 600; list-style: none;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::after {
  content: ""; width: 8px; height: 8px; flex: none;
  border-right: 2px solid var(--text-2); border-bottom: 2px solid var(--text-2);
  transform: rotate(45deg) translateY(-2px);
  transition: transform var(--dur) var(--ease);
}
.disclosure[open] > summary::after { transform: rotate(-135deg) translateY(-2px); }
.disclosure__body { padding: 0 var(--s-4) var(--s-4); }

/* ---------- 10. Checklist rows ---------- */
.checklist { display: flex; flex-direction: column; gap: var(--s-2); }
.check-row {
  display: grid; grid-template-columns: auto 1fr; column-gap: var(--s-3);
  align-items: start;
  padding: var(--s-3) var(--s-4);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.check-row .check { min-height: var(--tap); min-width: var(--tap); justify-content: center; margin: -8px 0 -8px -12px; }
.check-row__main { min-width: 0; padding-top: 2px; }
.check-row__title { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px var(--s-2); font-weight: 600; }
.check-row__num { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 500; color: var(--text-2); }
.check-row__gate { margin-top: 2px; color: var(--text-2); font-size: var(--fs-sm); }
.check-row__form { grid-column: 2; margin-top: var(--s-3); display: grid; gap: var(--s-2); }
.check-row.is-done { background: var(--surface-1); }
.check-row.is-done .check-row__title { color: var(--text); }
.check-progress { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }

/* ---------- 11. Stat tiles ---------- */
.stats { display: grid; gap: var(--s-3); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 700px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat {
  padding: var(--s-4);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  min-width: 0;
}
.stat__label { font-size: var(--fs-sm); color: var(--text-2); }
.stat__value {
  margin-top: var(--s-1);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-xl); font-weight: 500; line-height: 1.15; letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}
.stat__note { margin-top: var(--s-1); font-size: var(--fs-xs); color: var(--text-2); }
.stat--success .stat__value { color: var(--success); }
.stat--warning .stat__value { color: var(--warning); }

/* ---------- 12. Empty state, notices, skeletons ---------- */
.empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-2);
  padding: var(--s-8) var(--s-4);
  text-align: center;
  border: 1px dashed var(--line-ui);
  border-radius: var(--r-lg);
}
.empty__title { font-size: var(--fs-md); font-weight: 600; }
.empty__body { max-width: 36ch; color: var(--text-2); }
.empty .btn { margin-top: var(--s-2); }

.notice {
  --notice: var(--text-2);
  padding: var(--s-3) var(--s-4);
  background: color-mix(in srgb, var(--notice) 9%, var(--surface-1));
  border: 1px solid color-mix(in srgb, var(--notice) 55%, var(--bg));
  border-radius: var(--r-lg);
  font-size: var(--fs-base);
}
.notice--warning { --notice: var(--warning); }
.notice--danger { --notice: var(--danger); }
.notice__title { font-weight: 600; color: var(--notice); margin-bottom: 2px; }

.skeleton {
  display: block;
  height: 14px; border-radius: var(--r-sm);
  background: var(--surface-3);
  animation: skeleton-pulse 1.4s ease-in-out infinite;
}
.skeleton--title { height: 18px; width: 55%; }
.skeleton--short { width: 35%; }
.skeleton--chip { height: var(--chip-h); width: 72px; }
.skeleton-row {
  display: flex; flex-direction: column; gap: var(--s-3);
  padding: var(--s-4);
  background: var(--surface-1); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.skeleton-list { display: flex; flex-direction: column; gap: var(--s-3); }
@keyframes skeleton-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }

/* ---------- 13. Needs attention list ---------- */
.attention { margin-top: var(--s-6); }
.attention:first-child { margin-top: 0; }
.attention__head {
  display: flex; align-items: center; gap: var(--s-2);
  margin-bottom: var(--s-2);
}
.attention__title { font-size: var(--fs-md); }
.attention__list {
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.attention-item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  min-height: var(--row-h); padding: var(--s-2) var(--s-4);
  color: var(--text); text-decoration: none;
  border-bottom: 1px solid var(--line);
}
.attention-item:last-child { border-bottom: 0; }
@media (hover: hover) { .attention-item:hover { background: var(--surface-2); } }
.attention-item:active { background: var(--surface-2); }
.attention-item__main { min-width: 0; }
.attention-item__name { font-weight: 600; overflow-wrap: anywhere; }
.attention-item__why { color: var(--text-2); font-size: var(--fs-sm); }
.attention-item .icon { color: var(--text-2); }

/* ---------- 14. Key-value detail list ---------- */
.kv { display: grid; gap: 0; }
.kv__row {
  display: grid; gap: 2px;
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line);
}
.kv__row:last-child { border-bottom: 0; }
.kv dt {
  font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-2);
}
.kv dd { overflow-wrap: anywhere; min-width: 0; }
.kv__empty { color: var(--text-3); }
@media (min-width: 700px) {
  .kv--wide .kv__row { grid-template-columns: 8.5rem 1fr; gap: var(--s-4); align-items: baseline; }
}

/* ---------- 15. Timeline and log ---------- */
.timeline { display: flex; flex-direction: column; }
.timeline__item {
  position: relative;
  padding: 0 0 var(--s-5) 22px;
}
.timeline__item::before {
  content: ""; position: absolute; left: 3px; top: 7px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-2);
}
.timeline__item::after {
  content: ""; position: absolute; left: 6px; top: 18px; bottom: 0;
  width: 1px; background: var(--line);
}
.timeline__item:last-child { padding-bottom: 0; }
.timeline__item:last-child::after { display: none; }
.timeline__meta {
  display: flex; flex-wrap: wrap; gap: 2px var(--s-3);
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-2);
}
.timeline__text { margin-top: 2px; overflow-wrap: anywhere; }
.timeline__next { margin-top: 2px; color: var(--text-2); font-size: var(--fs-sm); }

/* ---------- 16. Toast ---------- */
/* A popover toast region (popover="manual") sits in the top layer, so toasts show above an open dialog. */
.toast-region:where([popover]) { margin: 0; padding: 0; border: 0; background: transparent; overflow: visible; top: auto; width: auto; height: auto; }
.toast-region {
  position: fixed; z-index: var(--z-toast);
  left: var(--s-3); right: var(--s-3);
  bottom: calc(var(--nav-h) + env(safe-area-inset-bottom) + var(--s-3));
  display: flex; flex-direction: column; gap: var(--s-2);
  pointer-events: none;
}
.toast {
  --toast: var(--text-2);
  display: flex; align-items: flex-start; gap: var(--s-3);
  max-width: 440px; width: 100%; margin-inline: auto;
  padding: var(--s-3) var(--s-4);
  background: var(--surface-3);
  border: 1px solid var(--line-ui);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-toast);
  color: var(--text);
  font-size: var(--fs-base);
  pointer-events: auto;
  animation: toast-in var(--dur) var(--ease);
}
.toast--success { --toast: var(--success); }
.toast--error { --toast: var(--danger); }
.toast--warning { --toast: var(--warning); }
.toast__icon { color: var(--toast); margin-top: 1px; }
.toast__msg { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.toast.is-leaving { opacity: 0; transform: translateY(6px); transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (min-width: 900px) {
  .toast-region { left: auto; right: var(--s-5); bottom: var(--s-5); width: 380px; }
  .toast { max-width: none; }
}

/* ---------- 17. Dialog (modal on desktop, bottom sheet on phone) ---------- */
.dialog {
  padding: 0;
  color: var(--text);
  background: var(--surface-pop);
  border: 1px solid var(--line-ui);
  /* phone: bottom sheet */
  width: 100%; max-width: none;
  margin: auto 0 0 0;
  max-height: calc(100dvh - var(--s-7));
  overflow: auto;
  border-radius: var(--r-xl) var(--r-xl) 0 0;
  border-bottom: 0;
}
.dialog::backdrop { background: var(--scrim); }
.dialog[open] { animation: sheet-in var(--dur-slow) var(--ease); }
.dialog[open]::backdrop { animation: fade-in var(--dur) var(--ease); }
.dialog__form { display: block; margin: 0; }
.dialog__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
  padding: var(--s-4) var(--s-4) 0;
}
.dialog__title { font-size: var(--fs-lg); }
.dialog__body { padding: var(--s-3) var(--s-4) var(--s-4); color: var(--text); }
.dialog__body > * + * { margin-top: var(--s-3); }
.dialog__foot {
  display: flex; gap: var(--s-2);
  padding: 0 var(--s-4) calc(var(--s-4) + env(safe-area-inset-bottom));
}
.dialog__foot .btn { flex: 1 1 0; }
@media (min-width: 700px) {
  .dialog {
    width: min(480px, calc(100vw - 32px));
    margin: auto;
    border-radius: var(--r-lg);
    border-bottom: 1px solid var(--line-ui);
    box-shadow: var(--shadow-dialog);
  }
  .dialog[open] { animation: dialog-in var(--dur) var(--ease); }
  .dialog__foot { justify-content: flex-end; padding-bottom: var(--s-4); }
  .dialog__foot .btn { flex: 0 0 auto; }
}
@keyframes sheet-in { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes dialog-in { from { transform: translateY(8px) scale(0.98); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ---------- 18. Auth (login page, no shell) ---------- */
.auth {
  min-height: 100dvh;
  display: flex; align-items: center; justify-content: center;
  padding: var(--s-4);
}
.auth__card { width: 100%; max-width: 380px; display: flex; flex-direction: column; gap: var(--s-5); }
.auth__brand { display: flex; align-items: center; gap: var(--s-3); }

/* ---------- 19. Bar chart (ui/bar-chart.js) ---------- */
.chart-card { margin-top: var(--s-5); }
.chart-card__readout { min-height: 1.5em; margin-bottom: var(--s-2); color: var(--text-2); font-size: var(--fs-sm); }
.chart-card__readout strong { color: var(--text); font-weight: 600; }
.chart-card__table { margin-top: var(--s-4); }
.chart { display: block; width: 100%; height: auto; overflow: visible; }
.chart__grid { stroke: var(--line); stroke-width: 1; }
.chart__base { stroke: var(--line-ui); stroke-width: 1; }
.chart__tick { fill: var(--text-2); font-size: 11px; font-family: var(--font-mono); }
.chart__bar { fill: var(--text-2); }
.chart__col { outline: none; cursor: default; }
.chart__col:hover .chart__bar, .chart__col:focus .chart__bar, .chart__col.is-active .chart__bar { fill: var(--text); }
.chart__col:focus-visible .chart__hit { stroke: var(--focus); stroke-width: 2; }
.chart__hit { fill: transparent; }
/* Second kind of money, stacked on the first. Blue is the talking role colour, not the accent. */
.chart__bar--alt { fill: var(--role-talking); stroke: var(--surface-1); stroke-width: 1; }
.chart__col:hover .chart__bar--alt, .chart__col:focus .chart__bar--alt, .chart__col.is-active .chart__bar--alt { fill: var(--role-talking); stroke: var(--text); stroke-width: 1.5; }
.chart__legend { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin-top: var(--s-3); font-size: var(--fs-sm); color: var(--text-2); }
.chart__legend-item { display: inline-flex; align-items: center; gap: var(--s-2); }
.chart__swatch { flex: none; width: 12px; height: 12px; border-radius: 3px; background: var(--text-2); }
.chart__swatch--alt { background: var(--role-talking); }
.chart__value { fill: var(--text); font-size: 11px; font-family: var(--font-mono); text-anchor: middle; }

/* ---------- 20. Value with an action beside it ---------- */
.value-row { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
.value-row__text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.value-row .btn { flex: none; }

/* ---------- 21. Links, danger zone, typed confirm ---------- */
/* Middle ellipsis: the start shrinks with an ellipsis, the end stays whole.
   Split the text yourself, for example the last 14 characters in __end, and
   put the full text in title. */
.mid-trunc { display: flex; min-width: 0; }
.mid-trunc__start { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mid-trunc__end { flex: none; white-space: nowrap; }

/* Link list on the client page */
.link-list { display: flex; flex-direction: column; gap: var(--s-2); container-type: inline-size; }
.link-row {
  display: grid; gap: 0 var(--s-3);
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "kind actions" "url url";
  align-items: center;
  padding: var(--s-2) var(--s-3) var(--s-3) var(--s-4);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
}
.link-row__kind { grid-area: kind; min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--s-2); }
.link-row__type {
  font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-2);
}
.link-row__label { font-weight: 600; overflow-wrap: anywhere; }
.link-row__url { grid-area: url; min-width: 0; font-size: var(--fs-sm); }
.link-row__url a { color: var(--text); }
.link-row__actions { grid-area: actions; display: flex; margin-right: calc(var(--s-2) * -1); }
/* One line only when the list itself is wide enough (the client page has two
   columns at 1280, so the screen width says nothing). Otherwise the address
   keeps its own full-width line. */
@container (min-width: 44rem) {
  .link-row {
    grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr) auto;
    grid-template-areas: "kind url actions";
    padding: var(--s-1) var(--s-2) var(--s-1) var(--s-4);
  }
}

/* Live site and Repo shortcuts on a card or table row. The ring is 28px, the
   tap area 44px wide and 44px tall (the extra height overlaps the line above
   and below, so the card does not grow). */
.icon-links { display: inline-flex; align-items: center; margin-inline: -8px; }
.icon-link {
  position: relative; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); margin-block: -8px;
  color: var(--text-2);
  -webkit-tap-highlight-color: transparent;
}
.icon-link::before {
  content: ""; position: absolute; inset: 8px; border-radius: var(--r-sm);
  box-shadow: inset 0 0 0 1px var(--line-ui);
  transition: background-color var(--dur-fast) var(--ease);
}
.icon-link .icon { position: relative; width: 16px; height: 16px; }
.icon-link:active::before { background: var(--surface-3); }
@media (hover: hover) {
  .icon-link:hover { color: var(--text); }
  .icon-link:hover::before { background: var(--surface-3); }
}

/* Danger zone at the bottom of a page */
.danger-zone {
  margin-top: var(--s-8);
  padding: var(--s-4);
  background: color-mix(in srgb, var(--danger) 6%, var(--surface-1));
  border: 1px solid color-mix(in srgb, var(--danger) 75%, var(--bg));
  border-radius: var(--r-lg);
  display: grid; gap: var(--s-3);
}
.danger-zone__title { font-size: var(--fs-md); color: var(--danger); }
.danger-zone__text { color: var(--text); }
@media (min-width: 700px) {
  .danger-zone { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s-2) var(--s-6); }
  .danger-zone__title, .danger-zone__text { grid-column: 1; }
  .danger-zone .btn { grid-column: 2; grid-row: 1 / span 2; }
}

/* Typed confirm inside a dialog: the name to type, then the field */
.confirm-type { display: grid; gap: var(--s-3); }
.confirm-type__name {
  display: block; padding: var(--s-2) var(--s-3);
  background: var(--surface-3); border-radius: var(--r-md);
  font-family: var(--font-mono); font-size: var(--fs-base); font-weight: 500;
  overflow-wrap: anywhere; user-select: all;
}
.confirm-type .input.is-match { border-color: var(--success); }

/* ---------- 22. Money: switch, payment history, key line, date button ---------- */
/* Yes or no switch. A real checkbox with role="switch", so keyboard and screen
   readers work. The whole row is the 44px target. Yes or no is also written out,
   so state never depends on colour. */
.switch {
  display: flex; align-items: center; gap: var(--s-3);
  min-height: var(--tap);
  cursor: pointer;
}
.switch__label { flex: 1 1 auto; min-width: 0; font-weight: 600; }
.switch__text { color: var(--text-2); font-size: var(--fs-sm); font-weight: 500; min-width: 2ch; text-align: right; }
.switch__on { display: none; color: var(--text); }
.switch:has(.switch__input:checked) .switch__on { display: inline; }
.switch:has(.switch__input:checked) .switch__off { display: none; }
.switch__input {
  appearance: none; -webkit-appearance: none;
  position: relative; flex: none;
  width: 46px; height: 28px; margin: 0;
  background: var(--surface-2);
  border: 1.5px solid var(--line-ui);
  border-radius: 14px;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.switch__input::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 19px; height: 19px; border-radius: 50%;
  background: var(--text-2);
  transition: transform var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.switch__input:checked { background: var(--text); border-color: var(--text); }
.switch__input:checked::after { background: var(--bg); transform: translateX(18px); }
.switch__input:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.switch__input[disabled] { opacity: 0.45; cursor: not-allowed; }

/* Payment history. Phone: date, amount and the buttons on the first line, the
   period and note below. One line when the list itself is wide. */
.payment-list { display: flex; flex-direction: column; container-type: inline-size; }
.payment-row {
  display: grid; gap: 0 var(--s-3);
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "date amount actions" "period period period" "note note note";
  align-items: center;
  padding: var(--s-1) 0 var(--s-3);
  border-bottom: 1px solid var(--line);
}
.payment-row:last-child { border-bottom: 0; }
.payment-row__date { grid-area: date; font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--text-2); }
.payment-row__amount {
  grid-area: amount; text-align: right;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 500;
}
.payment-row__period { grid-area: period; font-size: var(--fs-sm); color: var(--text-2); }
.payment-row__note { grid-area: note; margin-top: 2px; font-size: var(--fs-sm); overflow-wrap: anywhere; }
.payment-row__actions { grid-area: actions; display: flex; margin-right: calc(var(--s-2) * -1); }
@container (min-width: 36rem) {
  .payment-row {
    grid-template-columns: 5.5rem 8rem minmax(0, 1fr) auto;
    grid-template-areas: "date amount period actions" ". . note actions";
    padding: var(--s-1) 0;
  }
  .payment-row__amount { text-align: left; }
  .payment-row__note { margin-top: 0; }
}

/* Paid through and next due, at the top of the Subscription card */
.key-line {
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-6);
  padding: var(--s-3) var(--s-4);
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.key-line__item { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1) var(--s-2); min-width: 0; }
.key-line__label {
  flex: 1 1 100%;
  font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-2);
}
.key-line__value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-md); font-weight: 500; }
.key-line__item--overdue .key-line__value { color: var(--danger); }
.key-line--overdue { border-color: color-mix(in srgb, var(--danger) 75%, var(--bg)); }

/* A date you can edit by clicking it. Plain text at rest. Underline on hover and
   keyboard focus, and the focus ring from :focus-visible. */
.date-button {
  position: relative;
  display: inline; margin: 0; padding: 0;
  background: none; border: 0; border-radius: var(--r-sm);
  font: inherit; color: inherit; text-align: inherit;
  text-decoration: none;
  text-decoration-thickness: 1px; text-underline-offset: 3px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.date-button::after { content: ""; position: absolute; inset: -12px -8px; } /* 44px tap area */
.date-button:focus-visible { text-decoration: underline; outline: 2px solid var(--focus); outline-offset: 2px; }
@media (hover: hover) {
  .date-button:hover { text-decoration: underline; }
}

/* ---------- 23. Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
