/* ---------------------------------------------------------------------------
   Colour, in two themes.

   Stefan's note after seeing Andrew's FBOM: the black background is hard on
   the eyes for a full working day. So light is now a real theme rather than an
   inversion, and dark has been lifted off pure black -- #0b0f15 became #131820,
   which reads as a dark room rather than a switched-off screen.

   The rule that makes both work: NOTHING declares a colour outside :root. Every
   surface, hairline and hover used to be a literal var(--lift-2), which
   is a "lift" in dark and invisible-on-white in light. Those are now --lift-N
   tokens that go the other way round under light. Same for shadows, which have
   to be far softer on paper than on black or every card looks stamped on.
--------------------------------------------------------------------------- */
:root {
  color-scheme: dark;
  --bg: #131820;
  --panel: #1a212b;
  --panel-2: #212a36;
  --sidebar: #161d26;
  --line: var(--lift-3);
  --line-strong: var(--lift-1);
  --text: #f1f5f9;
  --muted: #9aa8bc;
  --subtle: #6b7a90;
  /* The accent. "Blue" by name because the app was built blue; the value
     comes from the colour a person picked in Appearance (data-accent on
     <html>), and every tint in the sheet is mixed from it. */
  --blue: var(--accent-ink-dark, #4387f5);
  /* Blue as a SOLID behind white text, which is a different job from blue as
     ink. --blue is tuned to read on a dark ground; white on it measures
     3.49:1, under the 4.5:1 that button-sized text needs, so every filled
     button in the app was failing in dark mode. This one passes in both
     themes (4.88:1) and still reads as a blue button against the panel. Use
     --blue for text and borders, this for fills. */
  --blue-solid: var(--accent-solid, #2f6fd0);
  /* The lighter end of a filled gradient (your own bubbles, the brand tiles):
     mostly the solid, a little of the ink, so white text stays readable on
     every accent. */
  --accent-fill-2: color-mix(in srgb, var(--blue-solid) 72%, var(--blue));
  --select-arrow: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%228%22%20viewBox%3D%220%200%2012%208%22%3E%3Cpath%20d%3D%22M1%201.5%206%206.5%2011%201.5%22%20fill%3D%22none%22%20stroke%3D%22%239a958e%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E");
  --violet: #8b5cf6;
  --green: #35c98f;
  --amber: #f5ae4e;
  --red: #fb6472;
  --on-accent: #fff;
  /* Lifts: a wash over whatever is behind. In dark they lighten, in light they
     darken, which is why each theme sets its own.

     These were written as `--lift-1: var(--lift-1)` -- a property defined as
     itself, which is invalid and resolves to nothing. So in dark mode, the
     default and the one Stefan uses, every hover built on a lift did nothing at
     all: the nav, secondary buttons, table rows, all of it. The app had no
     hover feedback in its own default theme and the CSS looked correct. */
  --lift-1: rgba(255,255,255,.025);
  --lift-2: rgba(255,255,255,.055);
  --lift-3: rgba(255,255,255,.09);
  --lift-4: rgba(255,255,255,.13);
  --sink-1: rgba(0,0,0,.18);
  --field: #0f151d;
  --radius: 14px;
  --shadow: 0 18px 60px rgba(0,0,0,.28);
  --shadow-sm: 0 2px 10px rgba(0,0,0,.22);
  --shadow-lg: 0 30px 80px rgba(0,0,0,.45);
  --tint-blue: color-mix(in srgb, var(--blue) 16%, transparent);
  --blue-line: color-mix(in srgb, var(--blue) 45%, transparent);
  --tint-green: rgba(53,201,143,.16);
  --tint-amber: rgba(245,174,78,.18);
  --tint-red: rgba(251,100,114,.16);
  --tint-violet: rgba(139,92,246,.16);
  /* Client status has to be readable at a glance and TELLABLE APART. Freeze and
     Final 30 Days were both var(--ink-warn) -- the same colour for "paused" and "ending
     soon", which are opposite problems. And every one of these was a pale tint
     picked for a dark ground, so in light mode they sat on white and vanished.
     Each status now has its own token with a value chosen for each theme.
     The reds are a ramp on purpose, worst last: freeze is a pause, inactive is
     drift, declined is money failing to arrive. */
  --st-active:   var(--ink-good);
  --st-final30:  var(--ink-warn);
  --st-overdue:  #ffb457;
  /* An overdue renewal should be zero. When it is not, it is a failure state
     and it gets alarm treatment rather than a tint -- a solid fill that cannot
     be scrolled past. Dark mode inverts: white on red fails there (3.9:1), so
     the fill goes bright and the text goes dark instead. */
  --alarm-bg:  #ff5c5c;
  --alarm-ink: #1a0d0d;
  --st-freeze:   #ff9d9d;
  --st-inactive: #f2606f;
  --st-declined: #fa7a90;
  --st-inperson: #a9c9fb;
  --st-finished: #9a9a92;

  /* Semantic ink. Seventy-three hard-coded pale hexes were scattered through the
     JS -- var(--ink-good) for good, var(--ink-warn) for warning, var(--ink-bad) for bad -- every one of
     them chosen to sit on a dark ground. In light mode they are pale text on
     white and effectively invisible, which is why "Paid up" and "renews in 67
     days" could not be read. Same names, a value per theme, one place to change. */
  --ink-good: #35c98f;
  --ink-warn: #f5ae4e;
  /* The step between good and warn on the re-sign runway: a client 45-60
     days out is neither. Defined per theme like the rest of the inks. */
  --ink-yellow: #f2d05a;
  --tint-yellow: rgba(242,208,90,.18);
  --ink-bad:  #f2807c;
  --ink-info: #a9c9fb;
  --ink-violet: #c4b5fd;

  /* Older names, still used in a dozen rules. They were only ever reached
     through a hardcoded fallback -- var(--warn, #d9a441) -- which meant those
     rules used a dark-mode amber in light mode and never changed with the
     theme. Aliased once here, so they follow whatever the theme sets and there
     is no second set of values to keep in step. */
  --good: var(--ink-good);
  --warn: var(--ink-warn);
  --bad: var(--ink-bad);
  --accent-soft: var(--tint-blue);

}

/* The accent colours, the way ClickUp offers them. Three values each: ink
   on a dark ground, ink on a light ground, and the solid that sits behind
   white text (checked at 4.5:1 or better). Blue is the house default and
   needs no stamp. */
:root[data-accent="black"]  { --accent-ink-dark: #e6e8ee; --accent-ink-light: #1b1b18; --accent-solid: #2a2d34; }
:root[data-accent="purple"] { --accent-ink-dark: #a78bfa; --accent-ink-light: #6d28d9; --accent-solid: #6d28d9; }
:root[data-accent="violet"] { --accent-ink-dark: #c084fc; --accent-ink-light: #7e22ce; --accent-solid: #7e22ce; }
:root[data-accent="indigo"] { --accent-ink-dark: #818cf8; --accent-ink-light: #4338ca; --accent-solid: #4f46e5; }
:root[data-accent="pink"]   { --accent-ink-dark: #f472b6; --accent-ink-light: #be185d; --accent-solid: #db2777; }
:root[data-accent="orange"] { --accent-ink-dark: #fb923c; --accent-ink-light: #c2410c; --accent-solid: #c2410c; }
:root[data-accent="teal"]   { --accent-ink-dark: #2dd4bf; --accent-ink-light: #0f766e; --accent-solid: #0f766e; }
:root[data-accent="bronze"] { --accent-ink-dark: #d4a373; --accent-ink-light: #8a5a2b; --accent-solid: #8a5a2b; }
:root[data-accent="mint"]   { --accent-ink-dark: #34d399; --accent-ink-light: #047857; --accent-solid: #047857; }
/* Black's active tiles and hovers are mixed from near-white ink in the dark
   theme, which reads as grey -- right for a monochrome look. */

/* Light: warm paper, not grey. Taken off Andrew's screenshots -- an off-white
   page, white cards, and hairlines dark enough to actually separate them. */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f7f6f3;
  --panel: #ffffff;
  --panel-2: #faf9f7;
  --sidebar: #fbfaf8;
  --line: rgba(24,24,20,.10);
  --line-strong: rgba(24,24,20,.20);
  --text: #1b1b18;
  --muted: #5f5f58;
  --subtle: #8b8b82;
  --blue: var(--accent-ink-light, #2f6fd0);
  --select-arrow: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%228%22%20viewBox%3D%220%200%2012%208%22%3E%3Cpath%20d%3D%22M1%201.5%206%206.5%2011%201.5%22%20fill%3D%22none%22%20stroke%3D%22%236f6b64%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E");
  --violet: #6d45c9;
  --green: #12805a;
  --amber: #9a6410;
  --red: #c2382f;
  --on-accent: #fff;
  --lift-1: rgba(24,24,20,.022);
  --lift-2: rgba(24,24,20,.045);
  --lift-3: rgba(24,24,20,.07);
  --lift-4: rgba(24,24,20,.10);
  --sink-1: rgba(24,24,20,.05);
  --field: #ffffff;
  --shadow: 0 10px 30px rgba(24,24,20,.08);
  --shadow-sm: 0 1px 3px rgba(24,24,20,.07);
  --shadow-lg: 0 20px 50px rgba(24,24,20,.13);
  --tint-blue: color-mix(in srgb, var(--blue) 16%, transparent);
  --blue-line: color-mix(in srgb, var(--blue) 40%, transparent);
  --tint-green: rgba(18,128,90,.17);
  --tint-amber: rgba(154,100,16,.18);
  --tint-red: rgba(194,56,47,.18);
  --tint-violet: rgba(109,69,201,.16);

    --st-active:   #0f7a52; --st-final30:  #8a5a0c; --st-freeze:   #c2503f;
  --st-overdue:  #a34a00;
  --alarm-bg: #b3241f; --alarm-ink: #ffffff;
    --st-inactive: #b02020; --st-declined: #7a0d0d; --st-inperson: #2a62bd;
    --st-finished: #6a6a62;
  --ink-good: #0f7a52; --ink-warn: #8a5a0c; --ink-bad: #b3241f;
  --ink-info: #2a62bd; --ink-violet: #5b3bb8;
  --ink-yellow: #7a5f00; --tint-yellow: rgba(214,178,40,.22);
}

/* Nobody has chosen yet: follow the system rather than forcing dark. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;
    --bg: #f7f6f3; --panel: #ffffff; --panel-2: #faf9f7; --sidebar: #fbfaf8;
    --line: rgba(24,24,20,.10); --line-strong: rgba(24,24,20,.20);
    --text: #1b1b18; --muted: #5f5f58; --subtle: #8b8b82;
    --blue: var(--accent-ink-light, #2f6fd0); --violet: #6d45c9; --green: #12805a;
  --select-arrow: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%228%22%20viewBox%3D%220%200%2012%208%22%3E%3Cpath%20d%3D%22M1%201.5%206%206.5%2011%201.5%22%20fill%3D%22none%22%20stroke%3D%22%236f6b64%22%20stroke-width%3D%221.8%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E");
    --amber: #9a6410; --red: #c2382f;
    --lift-1: rgba(24,24,20,.022); --lift-2: rgba(24,24,20,.045);
    --lift-3: rgba(24,24,20,.07); --lift-4: rgba(24,24,20,.10);
    --sink-1: rgba(24,24,20,.05); --field: #ffffff;
    --shadow: 0 10px 30px rgba(24,24,20,.08);
    --shadow-sm: 0 1px 3px rgba(24,24,20,.07);
    --shadow-lg: 0 20px 50px rgba(24,24,20,.13);
    --tint-blue: color-mix(in srgb, var(--blue) 16%, transparent); --tint-green: rgba(18,128,90,.17);
    --blue-line: color-mix(in srgb, var(--blue) 40%, transparent);
    --tint-amber: rgba(154,100,16,.18); --tint-red: rgba(194,56,47,.18);
    --tint-violet: rgba(109,69,201,.16);

    --st-active:   #0f7a52; --st-final30:  #8a5a0c; --st-freeze:   #c2503f;
  --st-overdue:  #a34a00;
  --alarm-bg: #b3241f; --alarm-ink: #ffffff;
    --st-inactive: #b02020; --st-declined: #7a0d0d; --st-inperson: #2a62bd;
    --st-finished: #6a6a62;

    --ink-good: #0f7a52; --ink-warn: #8a5a0c; --ink-bad: #b3241f;
    --ink-info: #2a62bd; --ink-violet: #5b3bb8;
    --ink-yellow: #7a5f00; --tint-yellow: rgba(214,178,40,.22);
  }
}

/* Every element carrying the hidden attribute is hidden, whatever else
   it is styled as. Without this any rule that sets `display` silently
   overrides the attribute -- which has now caused three separate bugs:
   a conversation drawn on top of its own empty state, a thread panel
   that would not close, and a notification badge permanently lit with
   nothing in it. */
[hidden] { display: none !important; }
* { box-sizing: border-box; }
html { background: var(--bg); -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
/* ^ Without this, Safari on a phone "helpfully" inflates the text of any block
   it decides is wide -- the prospect list's preview lines came out at twice
   the size of the names beside them. Sizes here are set on purpose. */
body {
  margin: 0; min-width: 320px; color: var(--text); background: var(--bg);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 14px;
}
button, input, select, textarea { font: inherit; }
button { cursor: pointer; }
button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
a { text-decoration: none; }

.app-shell { display: grid; grid-template-columns: var(--sbw, 248px) minmax(0,1fr); min-height: 100vh; }
.sidebar {
  position: sticky; top: 0; height: 100vh; z-index: 4; padding: 18px 14px; overflow: hidden;
  /* the nav scrolls inside; the sidebar itself must not, or the footer scrolls away */
  border-right: 1px solid var(--line); background: var(--sidebar);
  display: flex; flex-direction: column; gap: 22px; transition: width .2s ease, padding .2s ease;
}
.brand { display: flex; align-items: center; gap: 10px; min-height: 38px; }
.brand-mark { width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; background: linear-gradient(135deg, var(--blue-solid), color-mix(in srgb, var(--blue-solid) 45%, var(--violet))); box-shadow: 0 8px 24px color-mix(in srgb, var(--blue-solid) 30%, transparent); font-weight: 800; color:#fff; }
.brand-copy { min-width: 0; line-height: 1.05; }
.brand-copy strong { display:block; font-size: 15px; letter-spacing: -.02em; color: var(--text); }
.brand-copy span { display:block; color: var(--subtle); margin-top: 4px; font-size: 9px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; }
.collapse { margin-left: auto; width: 28px; height: 28px; color: var(--muted); border: 1px solid var(--line); border-radius: 8px; background: transparent; }
.nav-section { display: grid; gap: 6px; }
.nav-label { padding: 0 10px; color: var(--subtle); font-size: 10px; font-weight: 800; letter-spacing: .13em; text-transform: uppercase; }
.nav-item { width:100%; min-height: 40px; padding: 0 10px; border: 0; border-radius: 9px; background: transparent; color: var(--muted); display: flex; align-items: center; gap: 11px; text-align: left; transition: background .16s ease, color .16s ease; }
/* The label takes only the room its words need, so the star and the count
   sit right after it rather than at the far edge of a wide sidebar (Stefan:
   "bring stars closer to labels"). A long label shortens with an ellipsis
   before anything is pushed under the drag handle at the right. */
.nav-item { padding-right: 24px; }
.nav-item-label { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nav-item:hover { background: var(--lift-2); color: var(--text); }
.nav-item.active { color: white; background: linear-gradient(90deg, color-mix(in srgb, var(--blue) 18%, transparent), color-mix(in srgb, var(--blue) 4%, transparent)); box-shadow: inset 2px 0 0 var(--blue); }
.nav-icon { width: 18px; flex: 0 0 18px; color: inherit; text-align:center; font-size: 15px; }
.sidebar-note { margin-top: auto; padding: 12px; border: 1px solid var(--line); border-radius: 12px; background: var(--lift-1); color: var(--subtle); font-size: 11px; line-height: 1.55; }
/* The sidebar's right edge is a handle. Six pixels wide, invisible until
   hovered, when a thin blue line says "this moves". While dragging, the
   shell's transitions are off so the page follows the pointer exactly. */
.sb-resizer { position: absolute; top: 0; right: -1px; width: 7px; height: 100%; cursor: col-resize; z-index: 6; }
.sb-resizer::after { content: ""; position: absolute; top: 0; bottom: 0; right: 1px; width: 2px;
  background: var(--blue); opacity: 0; transition: opacity .15s ease; }
.sb-resizer:hover::after, body.sb-resizing .sb-resizer::after { opacity: .85; }
body.sb-resizing { cursor: col-resize; user-select: none; -webkit-user-select: none; }
body.sb-resizing .sidebar, body.sb-resizing .app-shell, body.sb-resizing main { transition: none !important; }
body.sb-resizing iframe { pointer-events: none; }   /* an iframe would swallow the drag */
@media (max-width: 940px) { .sb-resizer { display: none; } }

/* The collapsed rail ---------------------------------------------------------
   Hiding the labels is not enough: the favourite star, the drag handle and the
   section gaps all stayed, so starred items had a star wedged against their
   icon and the whole rail read as half-cut-off. Collapsed is its own layout,
   not the open sidebar with the text switched off. */
.sidebar.collapsed { width: 64px; padding: 18px 8px; gap: 14px; }
.app-shell.collapsed { grid-template-columns: 64px minmax(0,1fr); }
.sidebar.collapsed .brand-copy,
.sidebar.collapsed .nav-label,
.sidebar.collapsed .nav-item-label,
.sidebar.collapsed .nav-star,
.sidebar.collapsed .nav-grip,
.sidebar.collapsed .sidebar-note,
.sidebar.collapsed .sidebar-foot,
.sidebar.collapsed .nav-caret { display: none !important; }
.sidebar.collapsed .brand { justify-content: center; }

/* A square, evenly spaced hit target. The icon is the whole control, so it
   gets the whole button. */
.sidebar.collapsed .nav-item { justify-content: center; padding: 0;
  min-height: 40px; width: 40px; margin: 0 auto; border-radius: 10px; gap: 0; }
.sidebar.collapsed .nav-icon { width: 20px; flex: 0 0 20px; font-size: 15px; }
/* The open state marks the active row with a left bar; at this width a bar on
   a 40px square just looks clipped, so it becomes a filled tile. */
.sidebar.collapsed .nav-item.active { background: color-mix(in srgb, var(--blue) 20%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 40%, transparent); }

/* Sections keep their separation without their headings. */
.sidebar.collapsed .nav-group + .nav-group { margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--line); }
.sidebar.collapsed .nav-items { gap: 4px; }
/* A collapsed SECTION still hides its items when the rail is collapsed --
   otherwise closing a section and then the sidebar shows it reopened. */
.sidebar.collapsed .nav-section.collapsed .nav-items { display: none; }

/* The toggle sat outside the rail on a negative offset, which put it under the
   page's own scrollbar and made it look cut off. It belongs inside. */
.sidebar.collapsed .collapse { position: static; margin: 0 auto; width: 32px;
  height: 32px; background: transparent; }
.sidebar.collapsed .collapse svg { transform: rotate(180deg); }

/* The rail scrolls when there are more modules than height. Give it a thin
   scrollbar rather than the browser's default slab, which at 64px wide takes a
   quarter of the rail. */
.sidebar.collapsed #sidebarNav { scrollbar-width: thin; }
.sidebar.collapsed #sidebarNav::-webkit-scrollbar { width: 3px; }
.sidebar.collapsed #sidebarNav::-webkit-scrollbar-thumb { background: var(--line); }

main { min-width: 0; padding: 0 26px 36px; }
/* Pinned. The title, the search, the Brain and the icons stay put while the
   page scrolls under them -- on the desk, on the phone, and in the installed
   app. It spans main's gutters (the negative margin) so nothing scrolls past
   at the sides, and sits below the "acting as" bar when that is up. */
.topbar { min-height: 72px; border-bottom: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; gap: 16px;
  position: sticky; top: 0; z-index: 5; background: var(--bg); margin: 0 -26px; padding: 0 26px; }
body[data-asbar] .topbar { top: var(--asbar, 40px); }
.crumb { color: var(--muted); font-size: 13px; }
.crumb b { color: var(--text); font-weight: 700; }
.page { max-width: 1520px; margin: 0 auto; padding-top: 30px; }
.page-heading { display:flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }
h1 { margin:0; font-size: clamp(23px, 3vw, 30px); letter-spacing: -.045em; }
.eyebrow { margin: 0 0 7px; color: var(--blue); font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .12em; }
.lede { margin: 8px 0 0; color: var(--muted); max-width: 680px; line-height: 1.55; }
.action-row { display:flex; gap: 8px; align-items:center; flex-wrap: wrap; }
.button { border: 1px solid transparent; border-radius: 9px; padding: 9px 12px; color: white; background: var(--blue-solid); font-size: 12px; font-weight: 750; box-shadow: 0 1px 2px rgba(0,0,0,.14); transition: transform .14s ease, background .14s ease, box-shadow .14s ease; }
.button:hover { background: color-mix(in srgb, var(--blue-solid) 86%, white); box-shadow: 0 3px 12px color-mix(in srgb, var(--blue-solid) 45%, transparent); }
.button:active { transform: scale(.97); }
/* One quiet button. `secondary` and `ghost` were the same idea written twice
   -- one defined, one asked for in thirty places and never defined -- and
   `small` and `sm` were two sizes of small. Each pair is one rule now, so the
   two names cannot drift apart again. Both stay valid at the call sites.

   They sit on the panel with a little lift: fully transparent, a row of them
   read as text with boxes drawn round it rather than as controls. The hover
   colour follows the theme -- it was literally "white", 1.16:1 on paper. */
.button.secondary, .button.ghost { border-color: var(--line-strong); background: var(--panel);
  color: var(--muted); font-weight: 700; box-shadow: var(--shadow-sm); }
.button.secondary:hover, .button.ghost:hover { background: var(--lift-2); color: var(--text);
  border-color: var(--blue); transform: translateY(-1px); box-shadow: var(--shadow); }
.button.danger { background: transparent; border-color: rgba(251,100,114,.35); color:var(--ink-bad); }
.button.danger:hover { background: var(--tint-red); color: var(--red); border-color: var(--red); }
.button.small, .button.sm { padding: 5px 11px; font-size: 11px; border-radius: 8px; }
.button:disabled { opacity:.5; cursor:not-allowed; }

.section { margin-top: 28px; }
.section-head { display:flex; justify-content:space-between; align-items: center; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.section-head h2 { margin:0; font-size: 15px; letter-spacing: -.015em; }
.section-head p { margin: 4px 0 0; color: var(--subtle); font-size: 12px; }
.chips { display:flex; gap:6px; flex-wrap:wrap; }
.chip { border: 1px solid var(--line); border-radius: 999px; background: transparent; padding: 6px 9px; color: var(--muted); font-size: 11px; font-weight: 650; }
.chip.active { background: color-mix(in srgb, var(--blue) 16%, transparent); border-color: color-mix(in srgb, var(--blue) 50%, transparent); color: var(--ink-info); }
/* A row of chips is the same control as the tab strip -- pick one of these --
   and it had the same problem: flat, transparent, with the selected one only
   slightly bluer than the rest. Scoped to .chips so the dozens of chips used
   as small inline labels elsewhere stay quiet. */
.chips .chip { background:var(--panel); box-shadow:var(--shadow-sm); cursor:pointer;
  transition:background .14s ease, color .14s ease, border-color .14s ease,
             transform .14s ease, box-shadow .14s ease; }
.chips .chip:hover { background:var(--lift-2); color:var(--text);
  border-color:var(--line-strong); transform:translateY(-1px); box-shadow:var(--shadow); }
.chips .chip:active { transform:translateY(0); }
.chips .chip.active { background:var(--blue-solid); border-color:var(--blue-solid);
  color:#fff; box-shadow:0 2px 10px color-mix(in srgb, var(--blue-solid) 40%, transparent); }
.chips .chip.active:hover { background:var(--blue-solid); color:#fff;
  border-color:var(--blue-solid); }
.metric-grid { display:grid; grid-template-columns: repeat(5, minmax(0,1fr)); gap: 12px; }
/* Where the number of cards is decided by the data rather than fixed in the
   markup, let them fill the row. A hard five columns leaves the eleventh card
   sitting alone on a row of its own, which reads as a mistake. */
.metric-grid.flow { grid-template-columns: repeat(auto-fit, minmax(186px, 1fr)); }
.metric { position:relative; overflow:hidden; min-height: 108px;
  border: 1px solid var(--line); border-radius: var(--radius); padding: 17px;
  background: linear-gradient(150deg, var(--panel-2), var(--panel));
  box-shadow:var(--shadow);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease; }
.metric:hover { transform: translateY(-2px); border-color: var(--line-strong);
  box-shadow:var(--shadow); }
@media (prefers-reduced-motion: reduce) { .metric:hover { transform:none; } }
.metric::after { content:""; position:absolute; inset: auto -20px -46px auto; width:100px; height:100px; border-radius:50%; background: radial-gradient(circle, var(--metric-color, color-mix(in srgb, var(--blue) 13%, transparent)), transparent 68%); }
.metric-label { position:relative; z-index:1; color: var(--muted); font-size: 10px; font-weight: 800; letter-spacing:.08em; text-transform:uppercase; }
.metric-value { position:relative; z-index:1; margin-top: 11px; font-size: 23px; font-weight: 800; letter-spacing:-.035em; font-variant-numeric: tabular-nums; }
.metric-sub { position:relative; z-index:1; margin-top: 7px; color: var(--subtle); font-size: 11px; }
.positive { color: var(--green); } .warning { color: var(--amber); } .negative { color: var(--red); } .blue { color:var(--ink-info); }

/* Every card in the hub, lifted. Stefan's complaint was that the app reads as
   text pasted flat onto a background, and that the AI tool cards -- gradient,
   shadowed, floating slightly -- were the part that felt finished. This is
   that treatment, applied to the primitive rather than page by page, so it
   reaches everything at once. */
.card { border:1px solid var(--line); border-radius: var(--radius); padding:18px;
  background: linear-gradient(160deg, var(--panel-2), var(--panel));
  box-shadow:var(--shadow);
  transition: box-shadow .18s ease, border-color .18s ease; }
.card h3 { margin:0; font-size: 14px; letter-spacing:-.015em; }
.card-sub { margin:5px 0 0; color:var(--subtle); font-size:11px; }
.main-grid { display:grid; grid-template-columns: minmax(0,1.5fr) minmax(300px,.9fr); gap: 12px; }
.two-col { display:grid; grid-template-columns: minmax(0,1fr) minmax(330px,.95fr); gap:12px; }

.chart { height: 260px; display:flex; align-items:flex-end; gap:8px; padding: 28px 4px 4px; border-bottom:1px solid var(--line); background: repeating-linear-gradient(to bottom, transparent 0, transparent 51px, var(--lift-1) 52px); overflow-x:auto; }
.bar-group { flex:1; min-width: 22px; height:100%; display:flex; align-items:flex-end; justify-content:center; gap:3px; position:relative; }
.bar { width: 42%; max-width:26px; min-height:3px; border-radius:6px 6px 0 0; transition:height .25s ease; }
.bar.ad { background:linear-gradient(color-mix(in srgb, var(--blue) 70%, white), var(--blue)); } .bar.cash { background:linear-gradient(#59e5ad, var(--green)); }
.bar-label { position:absolute; bottom:-22px; color:var(--subtle); font-size:10px; white-space:nowrap; }
.legend { display:flex; gap:12px; color:var(--subtle); font-size:10px; margin-top:28px; flex-wrap:wrap; }
.legend i { display:inline-block; width:8px; height:8px; border-radius:2px; margin-right:4px; }

.table-wrap { overflow:auto; border:1px solid var(--line); border-radius: 12px; }
table { width:100%; min-width:650px; border-collapse:collapse; }
th { padding:11px 12px; color:var(--subtle); background:var(--lift-1); border-bottom:1px solid var(--line); text-align:left; font-size:10px; text-transform:uppercase; letter-spacing:.06em; white-space:nowrap; }
td { padding:12px; color:var(--muted); border-bottom:1px solid var(--line); font-size:12px; white-space:nowrap; }
td:first-child { color:var(--text); font-weight:650; }
tbody tr:last-child td { border-bottom:0; }
tbody tr:hover { background:var(--lift-1); }
.status { display:inline-flex; align-items:center; gap:5px; padding:4px 7px; border-radius:999px; font-size:10px; font-weight:800; }
.status.scale { color:var(--ink-good); background:rgba(53,201,143,.12); } .status.monitor { color:var(--ink-warn); background:rgba(245,174,78,.12); } .status.pause { color:var(--ink-bad); background:rgba(251,100,114,.12); }
.status.manual { color:var(--ink-info); background:color-mix(in srgb, var(--blue) 12%, transparent); } .status.meta_sync { color:var(--ink-violet); background:rgba(139,92,246,.12); } .status.import { color:var(--subtle); background:var(--lift-2); }

label { display:block; margin-bottom:5px; color:var(--muted); font-size:10px; font-weight:700; letter-spacing:.045em; }
label small { display:block; margin-top:3px; color:var(--subtle); font-size:9px; line-height:1.3; font-weight:500; letter-spacing:0; }
input, select, textarea { width:100%; border:1px solid var(--line); border-radius:8px; padding:9px 10px; color:var(--text); background:var(--field); font-size:12px; }
/* Every dropdown in the app was drawing the operating system's own control --
   appearance:auto -- so it carried macOS chrome and a grey native arrow while
   everything around it was ours. Same box as the other fields now, with a
   chevron that follows the theme. */
select { appearance:none; -webkit-appearance:none; -moz-appearance:none;
  padding-right:30px; background-image:var(--select-arrow);
  background-repeat:no-repeat; background-position:right 11px center;
  background-color:var(--panel); border-color:var(--line-strong);
  box-shadow:var(--shadow-sm); font-weight:600; cursor:pointer;
  transition:border-color .14s ease, box-shadow .14s ease, transform .14s ease; }
select:hover { border-color:var(--blue); transform:translateY(-1px);
  box-shadow:var(--shadow); }
select:focus-visible { outline:2px solid var(--blue); outline-offset:-1px; }
select::-ms-expand { display:none; }
textarea { min-height:64px; resize:vertical; line-height:1.4; }
/* The rule above stretches every input to 100%, which for a checkbox means a
   full-width box with its label shoved to the far edge. Pages have been
   working around it one at a time with inline width:auto; this fixes it for
   all of them. */
input[type=checkbox], input[type=radio] { width:auto; flex:none; margin:0; }
.field-grid { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap: 10px; }
.field.full { grid-column: 1 / -1; }
.helper { color:var(--subtle); font-size:11px; line-height:1.45; }
/* Used in seventy-odd places -- table cells, secondary lines under a name --
   and never actually defined, so every one of them rendered in full ink.
   Quieter, as each of those call sites meant. */
.muted { color: var(--muted); }
.empty { padding:32px; text-align:center; color:var(--subtle); }
/* The toast lives in the top bar, in the gap between the search pill and
   the icons -- a stretch of screen that never holds anything, so a "Saved"
   or a "Could not send" is never text over text. Out of the flow until it
   shows, so the icons do not shift. */
.topbar-actions { position:relative; }
.toast { position:absolute; right:0; top:50%; transform:translateY(-50%) translateX(6px); z-index:10; order:-1; margin-right:8px;
  border:1px solid rgba(53,201,143,.5); border-left-width:4px; background:var(--panel); color:var(--green); border-radius:9px; padding:8px 12px;
  box-shadow:var(--shadow); font-size:12px; font-weight:600; line-height:1.35; opacity:0; pointer-events:none; transition:opacity .18s ease, transform .18s ease;
  white-space:normal; }
.toast.show { position:relative; top:auto; transform:none; opacity:1; }
/* Opaque, always: a see-through toast over a page is text on text. */
.toast.error { border-color: rgba(251,100,114,.55); background:var(--panel); color:var(--red); }
.toast { pointer-events:auto; display:flex; align-items:center; gap:10px; max-width:min(520px, 44vw); }
/* A phone has no empty stretch in its bar: the toast sits just under it,
   full width, over the top of the page rather than over the composer. */
@media (max-width:700px) {
  .toast, .toast.show { position:fixed; left:12px; right:12px; top:calc(var(--asbar, 0px) + var(--topbar-h, 64px) + 8px); max-width:none; margin:0; order:0; }
  .toast { transform:translateY(-6px); }
  .toast.show { transform:none; }
}
.toast:not(.show) { pointer-events:none; }
.toast-act { font:inherit; font-weight:700; padding:4px 9px; border-radius:7px; cursor:pointer;
  border:1px solid currentColor; background:transparent; color:inherit; white-space:nowrap; }
.toast-act:hover { background:rgba(255,255,255,.12); }
.toast-x { font:inherit; font-size:15px; line-height:1; padding:0 2px; border:0; background:none;
  color:inherit; opacity:.7; cursor:pointer; }
.toast-x:hover { opacity:1; }
.badge { border: 1px solid rgba(139,92,246,.35); color:var(--ink-violet); background: rgba(139,92,246,.10); padding: 4px 8px; border-radius: 999px; font-size: 10px; font-weight: 700; }

@media (max-width:1200px) { .metric-grid { grid-template-columns:repeat(3,1fr); } .field-grid{grid-template-columns:repeat(2,1fr);} }
@media (max-width:940px) { .app-shell { grid-template-columns:68px minmax(0,1fr); } .sidebar { width:68px; padding-inline:10px; } .sidebar .brand-copy,.sidebar .nav-label,.sidebar .nav-item span:not(.nav-badge),.sidebar .sidebar-note { display:none; } .sidebar .brand { justify-content:center; } .sidebar .collapse { margin-left:0; position:absolute; right:-14px; background:var(--panel); } .sidebar .nav-item { justify-content:center; padding-inline:0; } .main-grid,.two-col { grid-template-columns:1fr; }
  /* The count rides the icon's corner on the narrow rail, as in the collapsed one. */
  .sidebar .nav-badge { position:absolute; top:2px; right:4px; min-width:16px; height:16px; line-height:16px; font-size:9px; padding:0 4px; margin:0; box-shadow:0 0 0 2px var(--sidebar); } }
@media (max-width:680px) { main { padding:0 14px 26px; } .topbar { min-height:64px; margin:0 -14px; padding:0 14px; } .page { padding-top:22px; } .page-heading { align-items:flex-start; flex-direction:column; } .metric-grid { grid-template-columns:repeat(2,1fr); } .field-grid{grid-template-columns:1fr;} }

/* ============================================================
   Data visualization
   Categorical slots are the dataviz reference palette's *dark*
   steps, assigned to entities in a fixed order (never by rank).
   Our surfaces (#0b0f15 / #121822) are darker than the palette's
   reference dark surface (#1a1a19), so every slot's contrast
   against the surface is >= what was validated; CVD separation
   between slots is surface-independent.
   ============================================================ */
.viz-root {
  --series-1: #3987e5;  /* blue    */
  --series-2: #d95926;  /* orange  */
  --series-3: #199e70;  /* aqua    */
  --series-4: #c98500;  /* yellow  */
  --series-5: #d55181;  /* magenta */
  --series-6: #008300;  /* green   */
  --series-7: #9085e9;  /* violet  */
  --series-8: #e66767;  /* red     */
  /* Was #898781. Its chroma was 0.009 -- a grey wearing a series slot --
     and against Lead Magnet's magenta it measured OKLab dE 1.1 under
     deuteranopia: the same line, twice, to a red-green colourblind
     reader. This passes all six checks in both modes. */
  --series-other: #8a7cc4;
  --viz-grid: var(--lift-3);
  --viz-axis: var(--lift-1);
  --viz-ink-muted: #93a1b5;
}

.filter-bar { display:flex; flex-wrap:wrap; gap:14px; align-items:flex-end; justify-content:space-between; }
.filter-group { display:flex; flex-direction:column; gap:6px; }
.filter-group > .filter-label { color:var(--subtle); font-size:10px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; }
.filter-row-inner { display:flex; gap:6px; align-items:center; flex-wrap:wrap; }
.filter-bar select { min-width:150px; }

.segmented { display:inline-flex; border:1px solid var(--line); border-radius:9px; overflow:hidden; }
.segmented button { padding:6px 12px; border:0; background:transparent; color:var(--muted); font-size:11px; font-weight:700; }
.segmented button + button { border-left:1px solid var(--line); }
.segmented button.active { background:color-mix(in srgb, var(--blue) 16%, transparent); color:var(--ink-info); }

.chart-head { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap; margin-bottom:6px; }
.chart-box { width:100%; overflow:hidden; }
.chart-box svg { display:block; width:100%; }
.viz-legend { display:flex; flex-wrap:wrap; gap:14px; margin-top:12px; }
.viz-legend-item { display:inline-flex; align-items:center; gap:7px; color:var(--muted); font-size:11px; }
.viz-legend-item i { width:10px; height:10px; border-radius:3px; flex:0 0 10px; }
.viz-legend-item.dim { opacity:.4; }
.viz-legend-item button { background:none; border:0; color:inherit; font:inherit; padding:0; }

.viz-tooltip {
  position:fixed; z-index:60; pointer-events:none; opacity:0; transform:translateY(4px);
  transition:opacity .12s ease, transform .12s ease;
  background:var(--field); border:1px solid var(--line-strong); border-radius:10px;
  padding:9px 11px; box-shadow:var(--shadow); font-size:11px; color:var(--text); min-width:150px;
}
.viz-tooltip.show { opacity:1; transform:translateY(0); }
.viz-tooltip .tt-title { color:var(--subtle); font-size:10px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; margin-bottom:6px; }
.viz-tooltip .tt-row { display:flex; align-items:center; gap:8px; justify-content:space-between; margin-top:3px; }
.viz-tooltip .tt-key { display:inline-flex; align-items:center; gap:6px; color:var(--muted); }
.viz-tooltip .tt-key i { width:8px; height:8px; border-radius:2px; flex:0 0 8px; }
.viz-tooltip .tt-val { color:var(--text); font-weight:700; font-variant-numeric:tabular-nums; }
.viz-tooltip .tt-total { margin-top:7px; padding-top:6px; border-top:1px solid var(--line); }
/* The columns either side of the one you are on step back rather than
   vanish. Transitioned, because an instant swap between two whole chart
   states reads as a flicker rather than as a response. */
.viz-seg { transition: opacity .12s ease; }
.viz-rail { transition: opacity .12s ease; }
@media (prefers-reduced-motion:reduce) {
  .viz-seg, .viz-rail { transition: none; } }

.bar-list { display:grid; gap:14px; margin-top:16px; }
.bar-item-head { display:flex; justify-content:space-between; align-items:baseline; gap:10px; margin-bottom:6px; }
.bar-item-name { display:inline-flex; align-items:center; gap:8px; color:var(--text); font-size:12px; font-weight:650; }
.bar-item-name i { width:10px; height:10px; border-radius:3px; flex:0 0 10px; }
.bar-item-val { color:var(--text); font-size:12px; font-weight:700; font-variant-numeric:tabular-nums; }
.bar-item-sub { color:var(--subtle); font-size:11px; font-variant-numeric:tabular-nums; }
.bar-track { height:8px; border-radius:999px; background:var(--lift-2); overflow:hidden; }
.bar-fill { height:100%; border-radius:999px; }

.split-list { display:grid; gap:10px; margin-top:14px; }
.split-row { display:grid; grid-template-columns:1fr auto; gap:8px; align-items:baseline; padding:10px 12px; border:1px solid var(--line); border-radius:10px; background:var(--lift-1); }
.split-row b { color:var(--text); font-size:12px; }
.split-row span { color:var(--subtle); font-size:11px; }
.split-row .split-val { color:var(--text); font-size:13px; font-weight:750; font-variant-numeric:tabular-nums; text-align:right; }

.table-toggle { display:flex; justify-content:flex-end; margin-top:10px; }
.loading { opacity:.45; transition:opacity .15s ease; }
/* Proportional figures on large standalone numbers; tabular-nums is reserved
   for columns that align vertically (table rows, axis ticks). */
.viz-root .metric-value { font-variant-numeric: proportional-nums; }
/* Six stat tiles read as one row on wide screens, no orphan. */
.viz-root .metric-grid { grid-template-columns: repeat(6, minmax(0,1fr)); }
@media (max-width:1400px) { .viz-root .metric-grid { grid-template-columns: repeat(3,1fr); } }
@media (max-width:760px)  { .viz-root .metric-grid { grid-template-columns: repeat(2,1fr); } }
/* Command Center funnel */
.funnel-list { display:grid; gap:16px; margin-top:16px; }
.funnel-step-head { display:flex; justify-content:space-between; align-items:baseline; gap:10px; margin-bottom:6px; }
.funnel-step-name { color:var(--text); font-size:12px; font-weight:650; }
.funnel-step-val { color:var(--text); font-size:12px; font-weight:700; font-variant-numeric:tabular-nums; }

/* Weekly scorecard */
.ad-card { margin-bottom: 12px; }
.ad-card-head { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap; }
.decision { margin-top:14px; padding:12px 14px; border-radius:11px; border:1px solid var(--line); background:var(--lift-1); }
.decision b { display:block; font-size:12.5px; color:var(--text); }
.decision p { margin:5px 0 0; color:var(--muted); font-size:11.5px; line-height:1.5; }
.decision.kill { border-color:rgba(251,100,114,.35); background:rgba(251,100,114,.07); }
.decision.kill b { color:var(--ink-bad); }
.decision.fix_first { border-color:rgba(245,174,78,.32); background:rgba(245,174,78,.06); }
.decision.fix_first b { color:var(--ink-warn); }
.decision.scale { border-color:rgba(53,201,143,.32); background:rgba(53,201,143,.06); }
.decision.scale b { color:var(--ink-good); }
.decision.watch { border-color:color-mix(in srgb, var(--blue) 30%, transparent); background:color-mix(in srgb, var(--blue) 6%, transparent); }
.decision.watch b { color:var(--ink-info); }

.kpi-strip { display:flex; flex-wrap:wrap; gap:8px; margin-top:14px; padding-top:14px; border-top:1px solid var(--line); }
.kpi-chip { padding:7px 10px; border:1px solid var(--line); border-radius:9px; background:var(--lift-1); min-width:104px; }
.kpi-chip-label { display:block; color:var(--subtle); font-size:9px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; }
.kpi-chip-val { display:block; margin-top:4px; color:var(--text); font-size:13px; font-weight:750; font-variant-numeric:tabular-nums; }

.modal-backdrop { position:fixed; inset:0; z-index:50; background:rgba(3,6,11,.72); display:grid; place-items:center; padding:20px; }
.modal-backdrop[hidden] { display:none; }
.modal { width:min(640px,100%); max-height:88vh; overflow:auto; border:1px solid var(--line-strong); border-radius:16px; background:var(--panel); padding:20px; box-shadow:var(--shadow); }

/* Call log entry row */
.entry-row { display:grid; grid-template-columns:repeat(7,minmax(0,1fr)); gap:10px; margin-top:14px; align-items:end; }
.entry-row .span-2 { grid-column:span 2; }
.entry-actions { display:flex; flex-direction:column; justify-content:flex-end; }
@media (max-width:1400px){ .entry-row { grid-template-columns:repeat(4,minmax(0,1fr)); } }
@media (max-width:900px){ .entry-row { grid-template-columns:repeat(2,minmax(0,1fr)); } }

/* Monthly KPI matrix */
.kpi-matrix { min-width: 1080px; }
.kpi-matrix th, .kpi-matrix td { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
.kpi-matrix th:first-child, .kpi-matrix td:first-child { text-align:left; }
.kpi-label-col { position:sticky; left:0; z-index:2; background:var(--panel); min-width:250px; }
.kpi-matrix thead .kpi-label-col { background:var(--panel-2); }
.kpi-year-col { background:var(--lift-2); font-weight:750; color:var(--text); }
.kpi-empty { color:var(--subtle); opacity:.45; }
.kpi-matrix tbody tr { border-left:3px solid transparent; }
.kpi-group-value  td:first-child { box-shadow: inset 3px 0 0 var(--series-5); }
.kpi-group-rates  td:first-child { box-shadow: inset 3px 0 0 var(--series-1); }
.kpi-group-fu     td:first-child { box-shadow: inset 3px 0 0 var(--series-7); }
.kpi-group-front  td:first-child { box-shadow: inset 3px 0 0 var(--series-3); }
.kpi-group-resign td:first-child { box-shadow: inset 3px 0 0 var(--series-2); }

/* OfferOps wordmark: "Offer" in primary ink, "Ops" carrying the brand gradient */
.brand-copy strong { font-size: 16px; letter-spacing: -.03em; }
.brand-copy strong em {
  font-style: normal;
  background: linear-gradient(100deg, var(--blue), var(--violet));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* Fallback for engines that ignore background-clip on text */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .brand-copy strong em { color: var(--violet); background: none; }
}
.brand-mark { border-radius: 11px; font-size: 17px; }

/* Dashboard hub */
.metric-link { cursor: pointer; transition: border-color .15s ease, transform .15s ease; }
.metric-link:hover { border-color: var(--line-strong); transform: translateY(-1px); }
.metric-link-cue { position:relative; z-index:1; margin-top:10px; color:var(--blue); font-size:11px; font-weight:700; }
.dot { display:inline-block; width:7px; height:7px; border-radius:50%; margin-left:6px; vertical-align:middle; }
.dot.good { background:var(--green); } .dot.warn { background:var(--amber); } .dot.bad { background:var(--red); }

.module-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; }
/* One row of six on a wide screen, so the Dashboard is one screen: metrics,
   modules, and the re-sign list under them without scrolling. */
@media (min-width:1360px) {
  .module-grid { grid-template-columns:repeat(6,minmax(0,1fr)); gap:10px; }
  .module-card { padding:14px 14px 12px; gap:10px; }
  .module-card h3 { font-size:13px; }
  .module-head { flex-direction:column; gap:6px; }
  .module-head .badge { align-self:flex-start; }
  /* Stats as three short lines -- value then label -- instead of three
     columns that no longer fit side by side at this width. */
  .module-stats { display:grid; gap:3px; padding-top:8px; }
  .module-stats > div { display:flex; align-items:baseline; gap:6px; min-width:0; }
  .module-stat-val { display:inline; font-size:14px; }
  .module-stat-label { display:inline; margin:0; font-size:9.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .module-stats > div { line-height:1.25; }
  .module-open { font-size:11.5px; margin-top:6px; }
  .module-card .card-sub { display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; font-size:11px; }
  /* The Dashboard as one screen: tighter sections and shorter metric cards
     when there is the width for the six-across modules row. */
  .viz-root .section { margin-top:18px; }
  .viz-root .page-heading { margin-bottom:14px; }
  .viz-root .page-heading .lede { display:none; }
  #keyMetrics .metric { min-height:0; padding:14px 16px; }
  #keyMetrics .metric-value { margin-top:6px; font-size:21px; }
  #keyMetrics .metric-sub { margin-top:4px; }
  #keyMetrics .metric-link-cue { margin-top:6px; }
  #keyMetrics .bar-track { margin-top:6px !important; }
}
.module-card { display:flex; flex-direction:column; gap:14px; }
.module-card.is-idle { opacity:.6; }
.module-head { display:flex; justify-content:space-between; align-items:flex-start; gap:12px; }
.badge-good { border-color:rgba(53,201,143,.35); color:var(--ink-good); background:rgba(53,201,143,.10); }
.badge-warn { border-color:rgba(245,174,78,.35); color:var(--ink-warn); background:rgba(245,174,78,.10); }
.badge-idle { border-color:var(--line); color:var(--subtle); background:var(--lift-1); }
.module-stats { display:flex; gap:20px; flex-wrap:wrap; padding-top:12px; border-top:1px solid var(--line); }
.module-stat-val { display:block; color:var(--text); font-size:19px; font-weight:800; letter-spacing:-.03em; }
.module-stat-label { display:block; margin-top:3px; color:var(--subtle); font-size:10px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; }
.module-open { margin-top:auto; color:var(--blue); font-size:12px; font-weight:750; }
.module-open.is-muted { color:var(--subtle); }
@media (max-width:1200px){ .module-grid { grid-template-columns:repeat(2,1fr); } }
@media (max-width:760px){ .module-grid { grid-template-columns:1fr; } }
.nav-group + .nav-group { margin-top:16px; }


/* ---- customisable sidebar ---------------------------------------------- */
.nav-label { display:flex; align-items:center; gap:6px; cursor:default; user-select:none; }
.nav-caret { font-size:9px; color:var(--subtle); width:10px; }
.nav-label-text { flex:1; }
.nav-grip { display:none; color:var(--subtle); cursor:grab; fill:currentColor;
  flex:0 0 10px; opacity:.55; }
.nav-grip:active { cursor:grabbing; }
.nav-section.collapsed .nav-items { display:none; }
.nav-label[data-toggle] { cursor:pointer; }
.nav-edit { width:100%; background:transparent; border:1px dashed var(--line);
  color:var(--subtle); border-radius:8px; padding:7px; font-size:10px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; cursor:pointer; }
.nav-edit:hover { border-color:var(--line-strong); color:var(--muted); }
body.nav-editing .nav-grip { display:inline; }
body.nav-editing .nav-item { cursor:grab; }
body.nav-editing .nav-section { outline:1px dashed var(--line); border-radius:8px;
  padding:4px; margin-bottom:6px; }
.nav-drag-over { outline:1.5px solid var(--blue,#4387f5) !important; }
.nav-dragging { opacity:.4; }


/* ---- sidebar: scrolling nav, pinned footer ----------------------------- */
/* The menu is longer than a laptop viewport. Without this the Admin section
   is simply unreachable -- which is how Settings became invisible. */
#sidebarNav {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 22px; padding-right: 2px;
}
#sidebarNav::-webkit-scrollbar { width: 6px; }
#sidebarNav::-webkit-scrollbar-thumb { background: var(--line-strong,var(--line-strong)); border-radius: 3px; }
#sidebarNav::-webkit-scrollbar-track { background: transparent; }

.sidebar-foot {
  flex: 0 0 auto; display: grid; gap: 6px; padding-top: 12px;
  border-top: 1px solid var(--line);
}
.account-chip {
  display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 9px;
  text-decoration: none; color: var(--muted);
}
.account-chip:hover { background: var(--lift-2); }
.account-avatar {
  width: 26px; height: 26px; flex: 0 0 26px; border-radius: 8px; display: grid;
  place-items: center; font-size: 12px; font-weight: 800; color: #fff;
  background: linear-gradient(135deg, var(--blue), var(--violet));
}
.account-copy { min-width: 0; line-height: 1.15; }
.account-copy strong { display: block; font-size: 11px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-copy em { display: block; font-style: normal; font-size: 9px; color: var(--subtle);
  margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sign-out { font-size: 10px; color: var(--subtle); text-decoration: none; padding: 0 10px 4px; }
.sign-out:hover { color: var(--muted); }

/* Chevron points down when open, right when collapsed. */
.nav-caret { display: inline-flex; align-items: center; transition: transform .16s ease;
  color: var(--subtle); }
.nav-section.collapsed .nav-caret { transform: rotate(-90deg); }
.nav-label:hover .nav-caret { color: var(--muted); }
.sidebar.collapsed .sidebar-foot, .sidebar.collapsed .nav-caret { display: none; }


/* ---- rearranging the menu --------------------------------------------- */
/* Edit mode has to look different from normal, or a drag handle just reads as
   decoration and nobody discovers it. */
/* Handles stay hidden until you hover the row they belong to -- present when
   wanted, invisible the rest of the time, the way ClickUp does it. */
.nav-item, .nav-label { position: relative; }
.nav-grip { position:absolute; right:6px; top:50%; transform:translateY(-50%);
  opacity:0; transition:opacity .12s ease; }
.nav-item:hover .nav-grip, .nav-label:hover .nav-grip { display:inline-flex;
  align-items:center; opacity:.6; }
.nav-grip:hover { opacity:1 !important; color:var(--blue,#4387f5); }
.nav-label { cursor:pointer; user-select:none; border-radius:7px; padding-block:4px; }
.nav-label:hover { background:var(--lift-2); }

/* While a drag is in flight, show every drop target. */
body.nav-rearranging .nav-grip { display:inline-flex; align-items:center; opacity:.45; }
body.nav-rearranging .nav-item { transition:transform .12s ease; }
.nav-dragging { opacity:.35; }
.nav-drag-over { background:color-mix(in srgb, var(--blue) 8%, transparent); border-radius:9px; }

/* ---- top bar actions --------------------------------------------------- */
.topbar-actions { display:flex; align-items:center; gap:6px; }

.campaign-chip { display:inline-flex; align-items:center; gap:8px; margin-right:12px;
  padding:5px 6px 5px 11px; border-radius:999px; font-size:11.5px; color:var(--muted);
  background:color-mix(in srgb, var(--blue) 10%, transparent); border:1px solid color-mix(in srgb, var(--blue) 32%, transparent); }
.campaign-chip b { color:var(--ink-info); font-weight:700; }
.campaign-chip button { width:20px; height:20px; border-radius:50%; border:0; padding:0;
  background:color-mix(in srgb, var(--blue) 16%, transparent); color:var(--ink-info); font-size:14px; line-height:1;
  cursor:pointer; }
.campaign-chip button:hover { background:var(--blue-solid); color:#fff; }

/* ---- the search box at the top of every page ------------------------- */
/* The pill is the .gsearch box itself; the input inside it has no border of
   its own. The magnifying glass sits in the pill's left padding, the Brain
   segment closes the right end, and the whole thing lights up as one when
   the box has focus. */
.gsearch { position:relative; flex:1 1 auto; max-width:520px; min-width:200px;
  display:flex; align-items:center; gap:4px; height:38px; padding:0 4px 0 12px;
  border:1px solid var(--line); border-radius:999px; background:var(--lift-1);
  transition:border-color .14s ease, background .14s ease, box-shadow .14s ease; }
.gsearch:focus-within, .gsearch.open { border-color:var(--blue); background:var(--panel);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.gsearch .gs-icon { flex:0 0 auto; color:var(--subtle); pointer-events:none;
  transition:color .14s ease; }
.gsearch.open .gs-icon, .gsearch:focus-within .gs-icon { color:var(--blue); }
#gsInput { flex:1 1 auto; min-width:0; width:auto; height:100%; padding:0 6px 0 8px;
  border:0; border-radius:0; background:transparent; color:var(--text);
  font-size:13px; box-shadow:none; }
#gsInput::placeholder { color:var(--subtle); }
#gsInput:focus { outline:none; box-shadow:none; }
#gsInput::-webkit-search-cancel-button { -webkit-appearance:none; }
.gs-kbd { flex:0 0 auto; padding:2px 6px; border-radius:5px;
  font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:10px;
  color:var(--subtle); border:1px solid var(--line); background:var(--panel);
  pointer-events:none; transition:opacity .14s ease; }
.gsearch:focus-within .gs-kbd { opacity:0; }
/* The segment at the right end of the pill. A hairline divides it from the
   box, it keeps the pill's curve on its outer side only, and it fills solid
   while the panel is open, so the bar says whether the Brain is up. */
.gs-brain { display:inline-flex; align-items:center; gap:6px; flex:0 0 auto;
  height:28px; margin-left:4px; padding:0 12px 0 11px; border:0;
  border-left:1px solid var(--line); border-radius:0 999px 999px 0;
  font:inherit; font-size:12px; font-weight:700; letter-spacing:.01em;
  color:var(--blue); cursor:pointer; white-space:nowrap;
  background:linear-gradient(100deg, color-mix(in srgb, var(--blue) 13%, transparent), color-mix(in srgb, var(--violet) 15%, transparent));
  transition:background .14s ease, color .14s ease; }
.gs-brain-ico { width:15px; height:15px; }
/* The wordmark's own gradient, on the Brain: the icon holds the blue end and
   the word runs into the violet, so the pill reads as the "Ops" in the logo
   rather than as one more blue chip. */
.gs-brain-label {
  background:linear-gradient(100deg, var(--blue), var(--violet));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .gs-brain-label { color:var(--violet); background:none; }
}
.gs-brain:hover, .gs-brain[aria-expanded="true"] { color:#fff;
  background:linear-gradient(100deg, var(--blue-solid), var(--violet)); }
.gs-brain:hover .gs-brain-label, .gs-brain[aria-expanded="true"] .gs-brain-label {
  background:none; color:#fff; -webkit-text-fill-color:#fff; }
.gs-brain:focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
@media (max-width:900px) { .gs-brain-label { display:none; } .gs-brain { padding:0 9px; } }

.gs-panel { position:absolute; top:calc(100% + 6px); left:0; right:0; z-index:40;
  max-height:min(60vh, 520px); overflow:auto; padding:6px; border-radius:13px;
  background:var(--panel); border:1px solid var(--line-strong);
  box-shadow:0 18px 44px -14px rgba(0,0,0,.55), 0 2px 8px rgba(0,0,0,.18); }
.gs-panel[hidden] { display:none !important; }
.gs-group + .gs-group { margin-top:4px; padding-top:4px; border-top:1px solid var(--line); }
.gs-group-label { padding:7px 10px 4px; font-size:9.5px; font-weight:800;
  letter-spacing:.11em; text-transform:uppercase; color:var(--subtle); }
.gs-item { display:flex; align-items:center; gap:10px; width:100%; text-align:left;
  padding:8px 10px; border-radius:9px; border:0; background:transparent;
  color:var(--text); cursor:pointer; }
.gs-item.on { background:var(--lift-2); }
.gs-item.on .gs-label { color:var(--ink-info); }
.gs-kind { flex:0 0 auto; width:24px; height:24px; border-radius:7px; display:grid;
  place-items:center; font-size:10px; font-weight:800; letter-spacing:.02em;
  background:var(--lift-2); color:var(--muted); }
.gs-kind-client { background:rgba(53,201,143,.14); color:var(--ink-good); }
.gs-kind-campaign { background:color-mix(in srgb, var(--blue) 14%, transparent); color:var(--ink-info); }
.gs-kind-page { background:var(--lift-2); color:var(--muted); }
.gs-kind-resource { background:rgba(139,92,246,.14); color:var(--ink-violet); }
.gs-kind-brain { background:var(--tint-blue); color:var(--blue); }
.gs-kind-brain svg { width:14px; height:14px; }
.gs-item.gs-ask { border-top:1px solid var(--line); margin-top:4px; padding-top:9px; border-radius:0 0 8px 8px; }
.gs-item.gs-ask .gs-label { color:var(--blue); }
.gs-body { display:flex; flex-direction:column; gap:1px; min-width:0; flex:1 1 auto; }
.gs-label { font-size:13px; font-weight:600; white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; }
.gs-label mark { background:transparent; color:var(--ink-info); font-weight:800; }
.gs-past { font-size:9.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--subtle); margin-left:4px; }
.gs-sub { font-size:11px; color:var(--subtle); white-space:nowrap; overflow:hidden;
  text-overflow:ellipsis; }
.gs-ext { color:var(--subtle); font-size:12px; flex:0 0 auto; }
.gs-empty { padding:16px 12px; font-size:12.5px; color:var(--subtle); text-align:center; }

@media (max-width:940px) {
  .gsearch { max-width:none; }
  .gs-kbd { display:none; }
}
@media (max-width:680px) {
  .topbar { flex-wrap:wrap; }
  .gsearch { order:3; flex-basis:100%; }
}
/* A pill you can see. These were transparent with a hairline border, so a row
   of them read as text with boxes drawn round it rather than as controls --
   and the selected one differed only by a pale wash. They now sit on the panel
   surface with a little lift, and the selected one is properly blue. */
.tb-btn { height:38px; min-width:38px; padding:0 12px; border:1px solid var(--line);
  border-radius:9px; background:var(--panel); color:var(--muted); display:inline-flex;
  align-items:center; justify-content:center; gap:7px; text-decoration:none;
  font-size:12px; font-weight:600; box-shadow:var(--shadow-sm);
  transition:background .14s ease, color .14s ease, border-color .14s ease,
             transform .14s ease, box-shadow .14s ease; }
.tb-btn:hover { background:var(--lift-2); color:var(--text);
  border-color:var(--line-strong); transform:translateY(-1px);
  box-shadow:var(--shadow); }
.tb-btn:active { transform:translateY(0); }
.tb-icon { font-size:17px; line-height:1; }
.tb-account { position:relative; margin-left:4px; }
.tb-account .account-avatar { width:38px; height:38px; flex:0 0 38px; border:0;
  cursor:pointer; font-size:14px; }
.tb-menu { position:absolute; right:0; top:42px; width:230px; z-index:30; padding:6px;
  background:var(--panel,#141b26); border:1px solid var(--line); border-radius:12px;
  box-shadow:var(--shadow-lg); display:grid; gap:2px; }
.tb-menu[hidden] { display:none; }
.tb-menu-head { padding:10px; border-bottom:1px solid var(--line); margin-bottom:4px;
  display:grid; gap:2px; }
.tb-menu-head strong { font-size:12px; color:var(--text); }
.tb-menu-head span { font-size:10px; color:var(--subtle); overflow:hidden;
  text-overflow:ellipsis; }
.tb-menu-head em { font-style:normal; font-size:10px; color:var(--blue,#4387f5); }
.tb-menu a, .tb-menu-btn { padding:8px 10px; border-radius:8px; font-size:12px; color:var(--muted);
  text-decoration:none; }
.tb-menu-btn { display:block; width:100%; text-align:left; border:0; background:transparent; font:inherit; font-size:12px; cursor:pointer; }
.tb-menu a:hover, .tb-menu-btn:hover { background:var(--lift-2); color:var(--text); }
.tb-menu a.danger:hover { color:var(--ink-bad); }

/* ---- the modal dialog ----------------------------------------------------
   Named for the Brain, which was the first thing to use it; now the frame
   behind every centred dialog in the app (client profile, save-a-document,
   end-of-day report). The Brain itself moved to a side panel below. */
.brain-overlay { position:fixed; inset:0; z-index:60; background:rgba(4,7,12,.62);
  backdrop-filter:blur(3px); display:flex; align-items:flex-start;
  justify-content:center; padding:78px 20px 24px; }
.brain-overlay[hidden] { display:none; }
.brain-panel { width:min(760px,100%); max-height:calc(100vh - 110px); display:flex;
  flex-direction:column; background:var(--panel,#141b26); border:1px solid var(--line);
  border-radius:15px; box-shadow:var(--shadow-lg); overflow:hidden; }
.brain-head { display:flex; align-items:center; gap:10px; padding:14px 16px;
  border-bottom:1px solid var(--line); }
.brain-head input { flex:1; background:transparent; border:0; color:var(--text);
  font-size:15px; padding:4px 0; }
.brain-head input:focus { outline:none; }
.brain-body { padding:0 16px 18px; overflow-y:auto; }

/* ---- the Brain ---------------------------------------------------------
   A panel on the right, over the page rather than instead of it. Styled as a
   conversation: your messages on the right in the accent, the Brain's on the
   left in the panel colour, the way every messaging app has taught everybody
   to read a thread. */
.bside { position:fixed; top:0; right:0; bottom:0; width:min(440px,100vw);
  z-index:65; display:flex; flex-direction:column; background:var(--panel);
  border-left:1px solid var(--line); box-shadow:-12px 0 40px -18px rgba(0,0,0,.35); }
.bside[hidden] { display:none; }
.bside-head { display:flex; align-items:center; gap:8px; padding:12px 14px;
  border-bottom:1px solid var(--line); flex:0 0 auto; }
.bside-head > .bside-ico { width:18px; height:18px; color:var(--blue); }
.bside-head b { font-size:14px; }
.bside-scope { font-size:11px; color:var(--subtle); }
.bside-spacer { flex:1 1 auto; }
.bside-close { border:0; background:none; font-size:22px; line-height:1; color:var(--subtle);
  cursor:pointer; padding:2px 6px; border-radius:7px; }
.bside-close:hover { color:var(--text); background:var(--lift-2); }
.bside-thread { flex:1 1 auto; min-height:0; overflow-y:auto; padding:16px 14px;
  display:flex; flex-direction:column; gap:10px; }
.bside-empty { margin:auto 0; text-align:center; color:var(--muted); display:flex;
  flex-direction:column; align-items:center; gap:12px; }
.bside-empty[hidden] { display:none; }
.bside-empty .bside-ico.big { width:34px; height:34px; color:var(--blue); }
.bside-empty p { margin:0; font-size:13px; max-width:34ch; line-height:1.5; }
.bside-hints { display:flex; flex-direction:column; gap:6px; width:100%; margin-top:4px; }
.bside-hint { font:inherit; font-size:12.5px; text-align:left; padding:9px 12px;
  border:1px solid var(--line); border-radius:10px; background:var(--lift-1);
  color:var(--muted); cursor:pointer; transition:border-color .14s ease, color .14s ease; }
.bside-hint:hover { border-color:var(--blue-line); color:var(--blue); }
.bside-msg { max-width:88%; padding:10px 13px; font-size:13.5px; line-height:1.5;
  border-radius:16px; overflow-wrap:anywhere; }
.bside-msg.user { align-self:flex-end; background:var(--blue-solid); color:var(--on-accent);
  border-bottom-right-radius:5px; }
.bside-msg.assistant { align-self:flex-start; background:var(--lift-1); color:var(--text);
  border:1px solid var(--line); border-bottom-left-radius:5px; }
.bside-msg p { margin:0 0 7px; } .bside-msg p:last-child { margin-bottom:0; }
.bside-msg ul { margin:4px 0 6px; padding-left:18px; } .bside-msg li { margin:2px 0; }
.bside-msg.error { color:var(--ink-bad); }
.bside-looked { margin-top:8px; padding-top:6px; border-top:1px dashed var(--line);
  font-size:10.5px; color:var(--subtle); }
/* Three dots while it reads. */
.bside-msg.thinking { display:flex; gap:4px; padding:13px 15px; }
.bside-msg.thinking span { width:6px; height:6px; border-radius:50%; background:var(--subtle);
  animation:brainpulse 1.1s infinite ease-in-out; }
.bside-msg.thinking span:nth-child(2) { animation-delay:.15s; }
.bside-msg.thinking span:nth-child(3) { animation-delay:.3s; }
@keyframes brainpulse { 0%,80%,100% { opacity:.3; transform:translateY(0); }
  40% { opacity:1; transform:translateY(-3px); } }
@media (prefers-reduced-motion: reduce) { .bside-msg.thinking span { animation:none; opacity:.6; } }
.bside-compose { flex:0 0 auto; display:flex; align-items:flex-end; gap:8px;
  padding:10px 12px 12px; border-top:1px solid var(--line); background:var(--panel); }
.bside-compose textarea { flex:1 1 auto; margin:0; resize:none; min-height:40px; max-height:160px;
  padding:10px 14px; border-radius:20px; font:inherit; font-size:13.5px; line-height:1.4;
  border:1px solid var(--line); background:var(--field); color:var(--text); }
.bside-compose textarea:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.bside-send { flex:0 0 auto; width:40px; height:40px; border-radius:50%; border:0;
  background:var(--blue-solid); color:var(--on-accent); cursor:pointer;
  display:inline-flex; align-items:center; justify-content:center; }
.bside-send:disabled { opacity:.5; cursor:default; }
.bside-send:hover:not(:disabled) { filter:brightness(1.08); }
/* With the panel open, the page keeps a right margin so nothing important
   sits under it on a wide screen. On a narrow one the panel is the screen. */
@media (min-width:1100px) { body.brain-open main { padding-right:466px; } }
.avatar.avatar-brain { color:var(--blue); display:inline-grid; place-items:center; }
.avatar.avatar-brain svg { width:60%; height:60%; }


/* Tooltips. The browser's own title= tooltip takes a second to appear and cannot
   be styled, which makes an icon-only toolbar feel like a guessing game. */
[data-tip] { position:relative; }
[data-tip]::after {
  content: attr(data-tip); position:absolute; top:calc(100% + 8px); left:50%;
  transform:translateX(-50%) translateY(-3px); white-space:nowrap;
  background:var(--field); color:var(--text); border:1px solid var(--line-strong,var(--line-strong));
  border-radius:7px; padding:5px 9px; font-size:11px; font-weight:600; line-height:1;
  opacity:0; pointer-events:none; transition:opacity .13s ease, transform .13s ease;
  box-shadow:var(--shadow); z-index:40;
}
[data-tip]::before {
  content:""; position:absolute; top:calc(100% + 3px); left:50%;
  transform:translateX(-50%); border:5px solid transparent;
  border-bottom-color:var(--line-strong,var(--line-strong)); opacity:0;
  transition:opacity .13s ease; pointer-events:none; z-index:41;
}
[data-tip]:hover::after, [data-tip]:focus-visible::after {
  opacity:1; transform:translateX(-50%) translateY(0);
}
[data-tip]:hover::before, [data-tip]:focus-visible::before { opacity:1; }
/* The rightmost buttons would otherwise push their tooltip off-screen. */
.topbar-actions > *:last-child [data-tip]::after,
.tb-account [data-tip]::after { left:auto; right:0; transform:translateY(-3px); }
.tb-account [data-tip]:hover::after { transform:translateY(0); }
.tb-account [data-tip]::before { left:auto; right:14px; transform:none; }
/* The Brain's tip is a sentence. Centred under a 76px button it hung 160px
   past the pill on each side, and the right-hand overhang gave a 1024px
   window a horizontal scrollbar even with the tip invisible. Hung from the
   pill's right end it runs back under the search box instead. */
.gs-brain[data-tip]::after { left:auto; right:0; transform:translateY(-3px); }
.gs-brain[data-tip]:hover::after, .gs-brain[data-tip]:focus-visible::after { transform:translateY(0); }
.gs-brain[data-tip]::before { left:auto; right:30px; transform:none; }


/* ---- reveal toggles on secret fields ----------------------------------- */
.secret-wrap { position:relative; display:block; }
.secret-wrap input { width:100%; padding-right:38px; }
.secret-eye {
  position:absolute; right:6px; top:50%; transform:translateY(-50%);
  width:28px; height:28px; display:grid; place-items:center; cursor:pointer;
  border:0; background:transparent; color:var(--subtle); border-radius:7px;
}
.secret-eye:hover { color:var(--text); background:var(--lift-2); }
.secret-eye svg { width:16px; height:16px; fill:none; stroke:currentColor;
  stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round; }

/* ---- client money panel + finance page ---- */
.money-grid { display:grid; grid-template-columns:repeat(2,1fr); gap:10px; margin-top:10px; }
.money-grid label { display:flex; flex-direction:column; gap:4px; font-size:11px;
  color:var(--muted); text-transform:uppercase; letter-spacing:.04em; }
.money-grid input, .money-grid select { width:100%; }
.tab-row { display:flex; gap:7px; border-bottom:1px solid var(--line);
  padding-bottom:10px; flex-wrap:wrap; }
/* The one you are on is filled, not tinted — at a glance the row should have an
   obvious current tab rather than one slightly bluer rectangle. */
.tab-row .tb-btn.active { background:var(--blue-solid); color:#fff;
  border-color:var(--blue-solid);
  box-shadow:0 2px 10px color-mix(in srgb, var(--blue-solid) 40%, transparent); }
.tab-row .tb-btn.active:hover { background:var(--blue-solid); color:#fff;
  border-color:var(--blue-solid); transform:translateY(-1px); }
.tab-pane { margin-top:12px; }
/* The two inputs and the button sit on one baseline. They did not: the button
   carried a class this app does not define, so it rendered at the browser's
   own height and looked out of line with fields it is meant to sit beside. */
.fin-top { display:flex; gap:10px; align-items:flex-end; margin-bottom:14px;
  flex-wrap:wrap; }
.fin-top .button { height:38px; padding-inline:16px; }
/* align-items:flex-end lines up MARGIN boxes, and the generic label rule puts
   5px under every label — so the fields sat five pixels above the button they
   are meant to share a baseline with. */
.fin-top .cash-input { margin-bottom:0; }
.cash-input { display:flex; flex-direction:column; gap:4px; font-size:11px;
  color:var(--muted); text-transform:uppercase; letter-spacing:.04em;
  font-weight:700; }
.cash-input input { height:38px; }
.caveat { border-left:3px solid var(--warn, #d9a441); background:rgba(217,164,65,.08);
  padding:10px 14px; border-radius:4px; font-size:12.5px; margin-bottom:16px; }
.grid { width:100%; border-collapse:collapse; font-size:12.5px; }
.grid th, .grid td { padding:7px 10px; border-bottom:1px solid var(--line); text-align:left; }
.grid th { font-size:10.5px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted); }
.grid .num, .grid th.num { text-align:right; font-variant-numeric:tabular-nums; }
.grid tr.neg td { background:rgba(220,80,80,.07); }
.grid td.pos { color:var(--good, #4caf7d); }
.grid td.neg { color:var(--bad, #e2635f); }
.missing-note { font-size:11.5px; color:var(--muted); line-height:1.5; padding:10px; }
.two-col { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
@media (max-width:900px){ .two-col, .money-grid { grid-template-columns:1fr; } }
.cost-add { display:flex; gap:8px; margin-top:10px; flex-wrap:wrap; }
.cost-add input { flex:1; min-width:110px; }
.stat-row { display:flex; gap:14px; flex-wrap:wrap; margin-bottom:16px; }
.stat { border:1px solid var(--line); border-radius:11px;
  padding:12px 15px; min-width:150px;
  background: linear-gradient(160deg, var(--panel-2), var(--panel));
  box-shadow:var(--shadow); }
.stat .k { display:block; font-size:10.5px; text-transform:uppercase;
  letter-spacing:.05em; color:var(--muted); }
.stat .v { display:block; font-size:19px; font-weight:700; margin-top:3px; }
.pill { font-size:10px; padding:1px 6px; border-radius:9px; background:var(--tint-blue);
  color:var(--blue); vertical-align:middle; }
.link-btn { background:none; border:none; color:var(--muted); cursor:pointer;
  font-size:11px; text-decoration:underline; padding:0; }
.link-btn.danger:hover { color:var(--bad, #e2635f); }

.app-footer { display:flex; gap:14px; align-items:center; justify-content:center;
  padding:22px 16px 30px; font-size:11.5px; color:var(--muted);
  border-top:1px solid var(--line); margin-top:34px; }
.app-footer a { color:var(--muted); text-decoration:underline; }
.app-footer a:hover { color:var(--blue); }

/* Settings cards are short; stacking them one per row left most of the page
   empty and pushed the useful controls below the fold. */
.settings-grid { display:grid; grid-template-columns:repeat(2, minmax(0,1fr));
  gap:14px; align-items:start; }
.settings-grid > .card { margin-top:0 !important; }
@media (max-width:1100px){ .settings-grid { grid-template-columns:1fr; } }

#build-notice { position:fixed; left:50%; transform:translateX(-50%); bottom:22px;
  z-index:9999; display:flex; align-items:center; gap:14px; padding:12px 14px 12px 18px;
  border-radius:12px; background:var(--panel,var(--panel-2)); color:var(--text,#eef1f6);
  border:1px solid var(--line,var(--line)); box-shadow:var(--shadow-lg);
  font-size:13px; max-width:min(560px, calc(100vw - 32px)); }
#build-notice .bn-body { display:flex; flex-direction:column; gap:2px; min-width:0; }
#build-notice .bn-meta { font-size:11px; color:var(--muted,#8a93a6); }
#build-notice .bn-go { border:0; border-radius:8px; padding:8px 14px; cursor:pointer;
  background:var(--blue-solid); color:#fff; font-weight:700; font-size:12px;
  white-space:nowrap; }
#build-notice .bn-later { border:0; background:transparent; color:var(--muted,#8a93a6);
  font-size:18px; line-height:1; cursor:pointer; padding:0 4px; }
#build-notice .bn-later:hover { color:var(--text,#eef1f6); }

/* build marker */

/* Favourite stars: invisible until the row is hovered, so the sidebar stays
   quiet, but always visible once something IS a favourite. */
.nav-star { margin-left:auto; width:20px; height:20px; padding:0; border:0;
  background:transparent; color:var(--subtle,#6b7280); opacity:0; cursor:pointer;
  display:grid; place-items:center; border-radius:5px; flex:0 0 auto;
  transition:opacity .13s ease, color .13s ease; }
.nav-item:hover .nav-star { opacity:.55; }
.nav-star:hover { opacity:1 !important; color:var(--warn,#f5ae4e); }
.nav-star.on { opacity:1; color:var(--warn,#f5ae4e); }
/* The star follows the label (the row's right padding keeps it clear of the
   drag handle), a touch inside the row's own gap so it reads as part of the
   word rather than a separate control. */
.nav-star { margin-left:-4px; margin-right:0; }

/* A red count on a menu entry: Tasks carries the tasks handed to you that
   you have not looked at. Sits before the star; the star only shows on
   hover, and the count must not jump when it does. */
.nav-badge { flex:0 0 auto; min-width:18px; height:18px; padding:0 5px; border-radius:9px;
  background:var(--red,#fb6472); color:#fff; font-size:10px; font-weight:800; line-height:18px;
  text-align:center; font-variant-numeric:tabular-nums; margin-left:-3px; }
/* In the 64px rail there is no row to sit in, so it rides the icon's corner. */
.sidebar.collapsed .nav-badge { position:absolute; top:2px; right:2px; min-width:16px; height:16px;
  line-height:16px; font-size:9px; padding:0 4px; margin:0; box-shadow:0 0 0 2px var(--sidebar); }

/* Icon picker */
.nav-icon-btn { border:0; background:transparent; padding:0; cursor:pointer;
  font-size:15px; line-height:1; color:inherit; border-radius:5px; }
.nav-icon-btn:hover { background:var(--lift-1); }
#icon-picker { position:fixed; z-index:10000; width:330px; padding:10px;
  border-radius:12px; background:var(--panel,var(--panel-2)); color:var(--text,#eef1f6);
  border:1px solid var(--line,var(--line)); box-shadow:var(--shadow-lg);
  display:flex; flex-direction:column; gap:8px; }
.ip-search { width:100%; font-size:13px; padding:7px 10px; }
.ip-tabs { display:flex; gap:4px; overflow-x:auto; padding-bottom:2px;
  scrollbar-width:none; }
.ip-tabs::-webkit-scrollbar { display:none; }
.ip-tab { flex:0 0 auto; border:0; background:transparent; cursor:pointer;
  font-size:10.5px; font-weight:700; letter-spacing:.02em; padding:4px 8px;
  border-radius:6px; color:var(--muted,#8a93a6); white-space:nowrap; }
.ip-tab:hover { background:var(--lift-3); color:var(--text,#eef1f6); }
.ip-tab.on { background:var(--accent-soft,color-mix(in srgb, var(--blue) 18%, transparent)); color:var(--blue,#4387f5); }
.ip-scroll { height:250px; overflow-y:auto; overscroll-behavior:contain;
  padding-right:2px; }
.ip-scroll h5 { position:sticky; top:0; margin:6px 0 4px; padding:4px 2px;
  font-size:10px; font-weight:800; letter-spacing:.09em; text-transform:uppercase;
  color:var(--subtle,#6b7280); background:var(--panel,var(--panel-2)); }
.ip-grid { display:grid; grid-template-columns:repeat(8,1fr); gap:2px; }
.ip-one { border:0; background:transparent; font-size:19px; padding:4px 0;
  border-radius:7px; cursor:pointer; line-height:1.15; }
.ip-one:hover { background:var(--lift-1); transform:scale(1.15); }
.ip-none { font-size:12px; color:var(--muted,#8a93a6); padding:14px 4px; }
.ip-reset { width:100%; border:0; background:transparent; cursor:pointer;
  color:var(--muted,#8a93a6); font-size:11px; padding:5px;
  text-decoration:underline; }
.ip-reset:hover { color:var(--text,#eef1f6); }

/* ---- AI tools ---- */
.tool-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
  gap:14px; }
.tool-card { display:flex; gap:14px; align-items:flex-start; padding:16px;
  border-radius:12px; background:var(--panel); border:1px solid var(--line);
  text-decoration:none; color:inherit; transition:border-color .15s, transform .15s; }
.tool-card:hover { border-color:var(--blue,#4387f5); transform:translateY(-2px); }
.tool-avatar { width:42px; height:42px; flex:0 0 42px; border-radius:12px;
  display:grid; place-items:center; font-size:20px;
  background:linear-gradient(135deg, var(--blue,#4387f5), var(--violet,#8b5cf6));
  box-shadow:0 8px 20px rgba(79,70,229,.28); }
.tool-body { display:flex; flex-direction:column; gap:3px; min-width:0; }
.tool-body strong { font-size:14.5px; }
.tool-blurb { font-size:12px; color:var(--muted); }
.tool-meta { font-size:10.5px; color:var(--subtle); margin-top:4px; }
.dropzone { border:1.5px dashed var(--line); border-radius:12px; padding:26px;
  text-align:center; display:flex; flex-direction:column; gap:5px;
  transition:border-color .15s, background .15s; margin-top:12px; }
.dropzone.over { border-color:var(--blue,#4387f5); background:color-mix(in srgb, var(--blue) 6%, transparent); }

/* AI tools ------------------------------------------------------------------
   Built to feel like sitting in front of Claude rather than filling in a form:
   a rail of past chats grouped by when you had them, a thread that scrolls on
   its own, and a composer pinned to the bottom that grows with what you type.
   It borrows the Messages bubbles deliberately -- a conversation with an
   assistant should read like every other conversation in here. */
.ai-shell { display:grid; grid-template-columns:262px minmax(0,1fr); gap:16px;
  align-items:stretch; height:calc(100vh - 196px); min-height:480px; }
@media (max-width:900px){
  .ai-shell { grid-template-columns:1fr; height:auto; }
  .ai-rail { max-height:220px; }
  .ai-log { min-height:50vh; }
}

.ai-rail { background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); display:flex; flex-direction:column;
  min-height:0; overflow:hidden; }
.ai-rail-top { padding:10px 10px 6px; }
.ai-rail-list { flex:1; overflow-y:auto; padding:4px 8px 8px;
  scrollbar-width:thin; }
.ai-rail-foot { border-top:1px solid var(--line); padding:8px; }
.ai-rail-empty { padding:10px 10px 0; }

.ai-new { width:100%; display:flex; align-items:center; gap:8px;
  padding:9px 12px; border-radius:11px; cursor:pointer; font-size:12.5px;
  font-weight:600; color:#fff; border:1px solid transparent;
  background:linear-gradient(135deg, var(--accent-fill-2), var(--blue-solid));
  box-shadow:0 4px 14px color-mix(in srgb, var(--blue) 28%, transparent);
  transition:transform .12s ease, box-shadow .15s ease; }
.ai-new:hover { box-shadow:0 6px 18px color-mix(in srgb, var(--blue) 40%, transparent); }
.ai-new:active { transform:scale(.985); }

.ai-rail-group { font-size:9.5px; font-weight:800; letter-spacing:.1em;
  text-transform:uppercase; color:var(--subtle); padding:12px 10px 5px; }
.ai-rail-group:first-child { padding-top:4px; }
.ai-proj { width:100%; display:flex; flex-direction:column; gap:2px;
  padding:8px 10px; border:0; background:transparent; color:inherit;
  cursor:pointer; border-radius:10px; text-align:left; position:relative;
  transition:background .15s ease, transform .12s ease; }
.ai-proj:hover { background:var(--lift-2); }
.ai-proj:active { transform:scale(.985); }
.ai-proj.on { background:linear-gradient(90deg,
  color-mix(in srgb, var(--blue) 20%, transparent), color-mix(in srgb, var(--blue) 5%, transparent)); }
.ai-proj.on::before { content:""; position:absolute; left:0; top:8px; bottom:8px;
  width:2.5px; border-radius:0 3px 3px 0; background:var(--blue); }
.ai-proj-title { font-size:12.5px; font-weight:600; letter-spacing:-.01em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ai-proj-meta { font-size:10px; color:var(--subtle); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.ai-rail-link { width:100%; display:flex; align-items:center; gap:8px;
  padding:8px 10px; border:0; background:transparent; color:var(--muted);
  cursor:pointer; border-radius:10px; text-align:left; font-size:12px;
  transition:background .15s ease, color .15s ease; }
.ai-rail-link:hover { background:var(--lift-2); color:var(--text); }
.ai-shell.training .ai-rail-link { background:color-mix(in srgb, var(--blue) 16%, transparent);
  color:var(--text); }

.ai-main { background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); display:flex; flex-direction:column;
  overflow:hidden; min-height:0; }
.ai-main[hidden] { display:none !important; }

.ai-head { display:flex; align-items:center; gap:12px; padding:12px 16px;
  border-bottom:1px solid var(--line); background:var(--panel-2); }
.ai-head-title { display:flex; align-items:center; gap:11px; flex:1; min-width:0; }
.ai-head-title > div { min-width:0; flex:1; }
.ai-head-actions { display:flex; align-items:center; gap:8px; flex:0 0 auto; }
.ai-mark { width:30px; height:30px; flex:0 0 30px; border-radius:10px;
  display:grid; place-items:center; font-size:15px;
  background:linear-gradient(135deg, var(--blue,#4387f5), var(--violet,#8b5cf6));
  box-shadow:0 6px 16px rgba(79,70,229,.3); }
/* The title is the field. No border until you are in it, so it reads as a
   heading you happen to be able to rename rather than as a form. */
.ai-title, .ai-title-static { width:100%; font-size:14px; font-weight:600;
  letter-spacing:-.01em; color:var(--text); }
.ai-title-wrap { display:flex; align-items:center; gap:2px; margin-left:-6px; }
.ai-title { flex:1; min-width:0; border:1px solid transparent;
  background:transparent; padding:2px 6px; border-radius:7px;
  transition:background .14s, border-color .14s; }
.ai-title:hover { background:var(--lift-2); }
.ai-title:focus { background:var(--panel); border-color:var(--line);
  outline:none; }
/* The pencil only shows on hover, and gets out of the way once you are
   actually typing -- the field itself is the affordance by then. */
.ai-title-pen { flex:0 0 auto; color:var(--subtle); opacity:0;
  transition:opacity .14s ease; }
.ai-title-wrap:hover .ai-title-pen { opacity:1; }
.ai-title-wrap:focus-within .ai-title-pen { opacity:0; }
.ai-title:disabled { color:var(--text); }
.ai-title:disabled:hover { background:transparent; }
.ai-title-wrap:has(.ai-title:disabled):hover .ai-title-pen { opacity:0; }
.ai-sub { font-size:11px; color:var(--subtle); margin-top:1px; padding-left:1px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

.ai-log { flex:1; overflow-y:auto; padding:24px 20px 6px; display:flex;
  flex-direction:column; gap:16px; scrollbar-width:thin; }
.ai-turn { max-width:74%; }
.ai-turn.theirs { max-width:88%; }
.ai-who { display:flex; align-items:center; gap:6px; font-size:10px;
  font-weight:800; letter-spacing:.07em; text-transform:uppercase;
  color:var(--subtle); margin-bottom:5px; }
.ai-who-mark { font-size:11px; }
/* The Brain's mark is a drawing, not a character: sized to the box it sits in. */
.ai-mark-svg { width:58%; height:58%; color:#fff; }
.ai-who-mark .ai-mark-svg { width:13px; height:13px; color:var(--blue); vertical-align:-2px; }
/* The assistant's side is plain text, not a bubble -- your question is the
   thing in a bubble, its answer is the page. A two-thousand-word meal plan
   inside a chat bubble reads like a wall; the same words plain read like a
   document. Written against .msg-bubble.ai-answer because the Messages bubble
   rules are defined further down the file and would otherwise win. */
.msg-bubble.ai-answer { background:transparent; border-color:transparent;
  padding:0 2px; border-radius:0; box-shadow:none; }
.ai-answer p { margin:0 0 9px; }
.ai-answer p:last-child, .ai-answer ul:last-child, .ai-answer ol:last-child { margin-bottom:0; }
.ai-answer h4 { font-size:12.5px; font-weight:700; letter-spacing:.01em;
  margin:14px 0 6px; }
.ai-answer h4:first-child { margin-top:0; }
.ai-answer ul, .ai-answer ol { margin:0 0 9px; padding-left:19px; }
.ai-answer li { margin-bottom:4px; }
.ai-answer code { font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:12px; padding:1px 5px; border-radius:5px;
  background:var(--lift-3); }
.ai-failed { color:var(--bad,#e2635f); }
/* A caret on the last line while the answer is still being written. */
.ai-answer.streaming > :last-child::after { content:""; display:inline-block;
  width:2px; height:1em; margin-left:2px; vertical-align:-2px;
  background:var(--blue); animation:aiCaret .9s step-end infinite; }
@keyframes aiCaret { 50% { opacity:0; } }
@media (prefers-reduced-motion:reduce){
  .ai-answer.streaming > :last-child::after { animation:none; } }
/* Said when an answer stopped short of what was asked for. */
.ai-cut { margin-top:10px; padding-top:8px; border-top:1px solid var(--line);
  font-size:11.5px; color:var(--subtle); }

/* A model takes seconds to answer. Without this the send button just went
   quiet, which is indistinguishable from a broken button. */
.ai-thinking { display:inline-flex; align-items:center; gap:4px; }
.ai-thinking i { width:5px; height:5px; border-radius:50%;
  background:var(--blue); animation:aiPulse 1.15s ease-in-out infinite; }
.ai-thinking i:nth-child(2) { animation-delay:.16s; }
.ai-thinking i:nth-child(3) { animation-delay:.32s; }
.ai-thinking em { font-style:normal; font-size:12.5px; color:var(--subtle);
  margin-left:5px; }
@keyframes aiPulse { 0%, 70%, 100% { opacity:.25; transform:scale(.8); }
                     35% { opacity:1; transform:scale(1); } }
@media (prefers-reduced-motion:reduce){ .ai-thinking i { animation:none; opacity:.6; } }

.ai-empty { margin:auto; text-align:center; max-width:420px; padding:20px; }
.ai-empty-mark { width:46px; height:46px; margin:0 auto 14px; border-radius:15px;
  display:grid; place-items:center; font-size:22px;
  background:linear-gradient(135deg, var(--blue,#4387f5), var(--violet,#8b5cf6));
  box-shadow:0 10px 26px rgba(79,70,229,.32); }
.ai-empty h2 { font-size:19px; letter-spacing:-.02em; margin-bottom:6px; }

/* Pinned to the bottom, grows with the text, and is the whole target -- the
   click lands on the box even when it misses the textarea. */
.ai-composer { display:flex; align-items:flex-end; gap:8px; margin:10px 16px 0;
  padding:8px 8px 8px 14px; border:1px solid var(--line); border-radius:16px;
  background:var(--panel-2); transition:border-color .15s ease,
  box-shadow .15s ease; }
.ai-composer:focus-within { border-color:color-mix(in srgb, var(--blue) 60%, transparent);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.ai-composer textarea { flex:1; border:0; background:transparent; resize:none;
  padding:7px 0; font-size:13.5px; line-height:1.5; color:var(--text);
  /* Overriding the app-wide textarea min-height on purpose: this one starts at
     a single line and grows, so a 64px floor makes an empty box look like a
     form field. */
  min-height:0; height:34px; max-height:180px; overflow-y:auto; }
.ai-composer textarea:focus { outline:none; box-shadow:none; }
.ai-send { width:32px; height:32px; flex:0 0 32px; border-radius:50%;
  display:grid; place-items:center; cursor:pointer; color:#fff; border:0;
  background:linear-gradient(135deg, var(--accent-fill-2), var(--blue-solid));
  box-shadow:0 4px 12px color-mix(in srgb, var(--blue) 32%, transparent);
  transition:transform .12s ease, opacity .15s ease; }
.ai-send:hover:not(:disabled) { transform:scale(1.06); }
.ai-send:disabled { opacity:.45; cursor:default; }
.ai-note { margin:7px 16px 12px; font-size:10.5px; }

.ai-train { flex:1; overflow-y:auto; padding:16px; display:flex;
  flex-direction:column; gap:16px; scrollbar-width:thin; }

/* Inbox */
.tb-btn { position:relative; }
.tb-badge { position:absolute; top:1px; right:1px; min-width:16px; height:16px;
  padding:0 4px; border-radius:9px; background:var(--red,#fb6472); color:#fff;
  font-size:9.5px; font-weight:800; display:grid; place-items:center;
  line-height:1; font-variant-numeric:tabular-nums;
  box-shadow:0 0 0 2px var(--panel,#121822); }
.inbox-row { display:flex; gap:12px; align-items:flex-start; padding:12px 11px;
  border-bottom:1px solid var(--line); cursor:pointer; border-radius:10px;
  transition:background .15s ease, transform .12s ease; position:relative; }
.inbox-row:hover { background:var(--lift-2); }
.inbox-row:active { transform:scale(.99); }
.inbox-row.unread { background:linear-gradient(90deg,
  color-mix(in srgb, var(--blue) 14%, transparent), color-mix(in srgb, var(--blue) 3%, transparent)); }
.inbox-row.unread::before { content:""; position:absolute; left:2px; top:16px;
  width:5px; height:5px; border-radius:50%; background:var(--blue); }
.inbox-row.unread .inbox-main { padding-left:8px; }
.inbox-main { flex:1; min-width:0; font-size:12.5px; }
.inbox-body { color:var(--muted); font-size:11.5px; margin-top:3px;
  overflow:hidden; text-overflow:ellipsis; }
.inbox-meta { color:var(--subtle); font-size:10px; margin-top:4px; }

/* Sharing: avatars you click, no dropdowns */
.share-wrap { position:relative; display:flex; align-items:center; gap:6px; }
.avatars { display:flex; }
.avatars .avatar:not(:first-child) { margin-left:-7px; }
.avatar { width:25px; height:25px; border-radius:50%; display:grid;
  place-items:center; font-size:9.5px; font-weight:800; color:#fff;
  border:2px solid var(--panel,var(--panel-2)); letter-spacing:.02em; flex:0 0 auto; }
.share-add { width:25px; height:25px; border-radius:50%; display:grid;
  place-items:center; cursor:pointer; color:var(--muted);
  border:1.5px dashed var(--line); background:transparent; padding:0;
  transition:color .14s, border-color .14s; }
.share-add:hover { color:var(--blue,#4387f5); border-color:var(--blue,#4387f5); }
.share-pop { position:absolute; top:32px; left:0; z-index:60; width:236px;
  padding:6px; border-radius:11px; background:var(--panel,var(--panel-2));
  border:1px solid var(--line); box-shadow:var(--shadow-lg);
  animation:sharePop .12s ease-out; }
@keyframes sharePop { from { opacity:0; transform:translateY(-4px); }
                      to { opacity:1; transform:none; } }
.share-head, .share-foot { font-size:10px; font-weight:800; letter-spacing:.07em;
  text-transform:uppercase; color:var(--subtle); padding:7px 9px 5px; }
.share-foot { text-transform:none; letter-spacing:0; font-weight:600;
  border-top:1px solid var(--line); margin-top:4px; }
.share-row { width:100%; display:flex; align-items:center; gap:9px; padding:6px 9px;
  border:0; background:transparent; color:inherit; cursor:pointer;
  border-radius:8px; text-align:left; }
.share-row:hover { background:var(--lift-3); }
.share-name { flex:1; font-size:12.5px; }
.share-tick { opacity:0; color:var(--blue,#4387f5); transition:opacity .12s; }
.share-row.on .share-tick { opacity:1; }

/* Messages -----------------------------------------------------------------
   Held to the same standard as the AI tool cards, because this is the page
   that gets opened most: real motion on anything that reacts, a type scale
   with three clear levels, and colour used to separate speakers rather than
   to decorate. Every transition is short enough to feel like response rather
   than animation. */
/* minmax(0,1fr) rather than 1fr: a plain 1fr refuses to shrink below its
   content, so opening the thread panel squeezed the conversation to a column
   too narrow to read instead of taking the space it needed. */
.msg-shell { display:grid; grid-template-columns:264px minmax(0,1fr); gap:16px;
  align-items:stretch; height:calc(100vh - 196px); min-height:460px; }
.msg-shell.with-panel { grid-template-columns:264px minmax(300px,1fr) 340px; }
/* Not enough width for three columns: the people list goes, not the
   conversation. You already know who you are talking to. */
@media (max-width:1300px){
  .msg-shell.with-panel { grid-template-columns:minmax(280px,1fr) 330px; }
  .msg-shell.with-panel .msg-rail { display:none; }
}
@media (max-width:900px){
  .msg-shell, .msg-shell.with-panel { grid-template-columns:1fr; height:auto; }
  .msg-shell.with-panel .msg-rail { display:none; }
  .msg-panel { max-height:70vh; }
}

.msg-rail { background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); padding:10px 8px; overflow-y:auto;
  scrollbar-width:thin; }
.msg-rail-head { font-size:10px; font-weight:800; letter-spacing:.1em;
  text-transform:uppercase; color:var(--subtle); padding:6px 10px 10px; }

.ibx-rail .msg-person { border-radius:10px; }
.msg-person { width:100%; display:flex; align-items:center; gap:11px;
  padding:9px 10px; border:0; background:transparent; color:inherit;
  cursor:pointer; border-radius:11px; text-align:left; position:relative;
  transition:background .15s ease, transform .12s ease; }
.msg-person:hover { background:var(--lift-2); }
.msg-person:active { transform:scale(.985); }
.msg-person.on { background:linear-gradient(90deg,
  color-mix(in srgb, var(--blue) 20%, transparent), color-mix(in srgb, var(--blue) 5%, transparent)); }
.msg-person.on::before { content:""; position:absolute; left:0; top:9px;
  bottom:9px; width:2.5px; border-radius:0 3px 3px 0; background:var(--blue); }
.msg-person-body { flex:1; min-width:0; display:flex; flex-direction:column;
  gap:2px; }
.msg-person-top { display:flex; align-items:baseline; justify-content:space-between;
  gap:8px; }
.msg-person-name { font-size:13px; font-weight:600; letter-spacing:-.01em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.msg-person-when { font-size:10px; color:var(--subtle); flex:0 0 auto; }
/* Mark read / unread, on hover, where the dot sits. */
.msg-person-act { position:absolute; right:8px; top:50%; transform:translateY(-50%); width:26px; height:26px; border-radius:7px;
  border:1px solid transparent; background:var(--panel); color:var(--muted); display:grid; place-items:center; padding:0; cursor:pointer;
  opacity:0; transition:opacity .12s ease; }
.msg-person-act i { position:absolute; top:5px; right:5px; width:6px; height:6px; border-radius:50%; background:var(--blue); }
.msg-person:hover .msg-person-act, .msg-person-act:focus-visible { opacity:1; }
.msg-person:hover .msg-dot { opacity:0; }
.msg-person-act:hover { border-color:var(--line); color:var(--text); }
/* No hover on a phone, so the control is simply always there -- with a lane
   of its own, because it used to sit on top of the last line said. */
@media (hover: none) {
  .msg-person { padding-right:42px; }
  .msg-person-act { opacity:.55; right:6px; width:30px; height:30px; }
  .msg-person:hover .msg-dot { opacity:1; }
}
.hpop-unread { border:0; background:transparent; color:var(--subtle); width:26px; height:26px; border-radius:7px; display:grid; place-items:center; cursor:pointer; padding:0; }
.hpop-unread:hover { background:var(--lift-2); color:var(--text); }
.msg-person-last { display:block; font-size:11.5px; color:var(--subtle); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }   /* block, or the ellipsis never applies and a pasted link runs off the rail */
.msg-person.on .msg-person-last { color:var(--muted); }
.msg-dot { min-width:18px; height:18px; padding:0 5px; border-radius:9px;
  background:var(--blue-solid); color:#fff; font-size:9.5px; font-weight:800;
  display:grid; place-items:center; box-shadow:0 2px 8px color-mix(in srgb, var(--blue) 45%, transparent); }

.msg-main { background:var(--panel); border:1px solid var(--line);
  border-radius:var(--radius); display:flex; flex-direction:column;
  overflow:hidden; min-height:0; }
.msg-empty { padding:40px 34px; max-width:440px; }

#msgThread { display:flex; flex-direction:column; height:100%; min-height:0; }
/* A display rule beats the hidden attribute, so anything given `display` here
   has to say so explicitly -- without this the empty state and the open
   conversation render on top of each other, which is exactly what they did. */
#msgThread[hidden], .msg-panel[hidden], .msg-empty[hidden] { display:none !important; }
.msg-head { display:flex; align-items:center; gap:11px; padding:14px 18px;
  border-bottom:1px solid var(--line); background:var(--panel-2); }
.msg-head strong { font-size:14px; letter-spacing:-.01em; }

.msg-log { flex:1; overflow-y:auto; padding:22px 18px; display:flex;
  flex-direction:column; gap:14px; scrollbar-width:thin; }
.msg-turn { display:flex; flex-direction:column; max-width:64%;
  animation:msgIn .18s ease-out; }
@keyframes msgIn { from { opacity:0; transform:translateY(4px); }
                   to { opacity:1; transform:none; } }
.msg-turn.mine { align-self:flex-end; align-items:flex-end; }
.msg-turn.theirs { align-self:flex-start; }
.msg-bubble { padding:10px 14px; border-radius:16px; font-size:13.5px;
  line-height:1.55; background:var(--panel-2); border:1px solid var(--line);
  overflow-wrap:anywhere; }
.msg-turn.mine .msg-bubble { background:linear-gradient(135deg,
  var(--accent-fill-2), var(--blue-solid)); border-color:transparent; color:#fff;
  border-bottom-right-radius:6px; box-shadow:0 4px 14px color-mix(in srgb, var(--blue) 28%, transparent); }
.msg-turn.theirs .msg-bubble { border-bottom-left-radius:6px; }
.msg-subject { display:inline-block; margin-top:7px; padding:2px 8px;
  border-radius:20px; font-size:10.5px; font-weight:600; text-decoration:none;
  background:var(--lift-1); color:inherit; opacity:.9;
  transition:opacity .14s ease; }
.msg-subject:hover { opacity:1; }
.msg-turn.theirs .msg-subject { background:color-mix(in srgb, var(--blue) 16%, transparent);
  color:var(--blue); }
.msg-time { font-size:9.5px; color:var(--subtle); margin-top:5px; padding:0 5px;
  letter-spacing:.02em; }
.msg-edited { font-style:italic; opacity:.85; }

/* Day dividers and grouping.

   Consecutive messages from one person inside a few minutes are one utterance,
   so they are drawn as one: tight spacing, a single timestamp, softened inner
   corners. This is most of the difference between a chat that looks designed
   and one that looks like a table of rows. */
.msg-day { align-self:center; display:flex; align-items:center; gap:10px;
  width:100%; margin:6px 0 2px; }
.msg-day::before, .msg-day::after { content:""; flex:1; height:1px;
  background:var(--line); }
.msg-day span { font-size:10px; font-weight:700; letter-spacing:.06em;
  text-transform:uppercase; color:var(--subtle); white-space:nowrap; }
.msg-day.thin { margin:12px 0 4px; }
.msg-turn.grouped { margin-top:-10px; }
.msg-turn.grouped.mine .msg-bubble { border-top-right-radius:7px; }
.msg-turn.grouped.theirs .msg-bubble { border-top-left-radius:7px; }
.msg-bubble.pending { opacity:.62; }
/* A link in a bubble reads as one on either colour of ground. */
.msg-bubble a, .hpop-bubble a { color:var(--blue); text-decoration:underline; overflow-wrap:anywhere; }
.msg-turn.mine .msg-bubble a, .hpop-turn.mine .hpop-bubble a { color:#fff; }
/* A voice memo: caption, then the player. The player is the browser's, so
   it sits on a quiet ground inside either colour of bubble. */
.msg-bubble.memo, .hpop-bubble.memo { display:flex; flex-direction:column; gap:5px; }
.msg-cap { font-size:11.5px; font-weight:650; opacity:.85; }
.msg-audio { display:block; height:34px; width:260px; max-width:100%; border-radius:17px; }
.hpop-bubble .msg-audio { width:220px; }
.msg-memo { padding:10px 18px 0; }
.msg-memo .ws-memo { margin-bottom:0; }
.msg-mic { align-self:flex-end; width:40px; padding:0; display:grid; place-items:center; }
.msg-bubble.gone { font-style:italic; color:var(--subtle); background:transparent;
  border:1px dashed var(--line); box-shadow:none; }
.msg-turn.mine .msg-bubble.gone { background:transparent; color:var(--subtle); }

/* The ⋯ menu.

   One affordance instead of a row of icons: a message has four things you can
   do to it and a bubble is not a toolbar. Hidden until the pointer is on the
   message, because these are used a few times a week and read every day. */
.msg-row { display:flex; align-items:center; gap:4px; max-width:100%; }
.msg-more { display:grid; place-items:center; width:26px; height:26px; padding:0;
  flex:0 0 auto; border-radius:8px; border:1px solid transparent;
  background:transparent; color:var(--subtle); cursor:pointer; opacity:0;
  pointer-events:none; fill:currentColor;
  transition:opacity .14s ease, background .14s ease, color .14s ease; }
.msg-turn:hover .msg-more, .msg-more:focus-visible { opacity:1; pointer-events:auto; }
.msg-more:hover { background:var(--panel-2); color:var(--text); }
.msg-more:focus-visible { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
@media (hover: none) { .msg-more { opacity:.45; pointer-events:auto; } }

/* Reactions. Chips under the bubble, the way ClickUp and Slack draw them:
   the emoji and a count, lit when one of them is yours, the names on hover.
   The smiley-plus that adds one behaves like the ⋯ -- there when the
   pointer is on the message, out of the way when it is not. */
.msg-reacts { display:flex; flex-wrap:wrap; align-items:center; gap:4px; margin-top:4px; padding:0 4px; }
.msg-turn.mine .msg-reacts { justify-content:flex-end; }
.msg-react { display:inline-flex; align-items:center; gap:4px; height:24px; padding:0 8px 0 6px;
  border-radius:12px; border:1px solid var(--line); background:var(--panel); color:var(--muted);
  font-size:13px; line-height:1; cursor:pointer; transition:border-color .12s ease, background .12s ease; }
.msg-react b { font-size:10.5px; font-weight:750; font-variant-numeric:tabular-nums; }
.msg-react:hover { border-color:var(--line-strong); background:var(--lift-2); }
.msg-react.on { border-color:var(--blue); background:var(--tint-blue); color:var(--blue); }
.msg-react-add { display:grid; place-items:center; width:26px; height:24px; padding:0; border-radius:12px;
  border:1px solid transparent; background:transparent; color:var(--subtle); cursor:pointer; opacity:0;
  transition:opacity .14s ease, background .14s ease, color .14s ease; }
.msg-turn:hover .msg-react-add, .hpop-turn:hover .msg-react-add, .msg-react-add:focus-visible { opacity:1; }
.msg-react-add:hover { background:var(--lift-2); color:var(--text); border-color:var(--line); }
@media (hover: none) { .msg-react-add { opacity:.55; } }
.hpop-turn.mine .msg-reacts { justify-content:flex-end; }
.hpop-turn .msg-react { height:22px; font-size:12px; }

/* The reaction picker: the icon picker's grid on the ⋯ menu's footing. */
.epick { position:fixed; z-index:10000; width:300px; padding:8px; border-radius:12px;
  background:var(--panel); color:var(--text); border:1px solid var(--line); box-shadow:var(--shadow-lg);
  display:flex; flex-direction:column; gap:6px; animation:menuIn .12s cubic-bezier(.2,.8,.3,1); }
.epick-quick { display:grid; grid-template-columns:repeat(8,1fr); gap:2px; padding-bottom:6px; border-bottom:1px solid var(--line); }
.epick-quick .ip-one { font-size:21px; padding:5px 0; }
.epick .epick-scroll { height:190px; }
.epick .ip-scroll h5 { background:var(--panel); }
@media (max-width:700px) { .epick { width:min(300px, calc(100vw - 16px)); } }

.msg-menu { position:fixed; z-index:80; min-width:186px; padding:5px;
  border-radius:12px; background:var(--panel); border:1px solid var(--line);
  box-shadow:var(--shadow);
  transform-origin:top center;
  /* An animation rather than a class toggled on the next frame: the toggle
     leaves the menu invisible if anything delays that frame, which is a menu
     that silently does not open. */
  animation:menuIn .12s cubic-bezier(.2,.8,.3,1); }
@keyframes menuIn { from { opacity:0; transform:scale(.97) translateY(-3px); }
                    to { opacity:1; transform:none; } }
.msg-menu-item { display:block; width:100%; text-align:left; padding:7px 10px;
  border:0; border-radius:8px; background:transparent; color:var(--text);
  font-size:12.5px; font-weight:500; cursor:pointer; letter-spacing:-.01em;
  transition:background .1s ease, color .1s ease; }
.msg-menu-item:hover { background:color-mix(in srgb, var(--blue) 14%, transparent); color:var(--blue); }
.msg-menu-item.danger:hover { background:rgba(226,86,75,.14); color:var(--ink-bad); }

/* The reply count under a message: the whole of the thread affordance. */
.msg-replies { display:inline-flex; align-items:center; gap:6px; margin-top:6px;
  /* The turn is a stretching flex column, so without this the chip spans the
     whole width and stops reading as a small control. */
  align-self:flex-start; width:fit-content;
  padding:3px 9px 3px 7px; border-radius:20px; cursor:pointer;
  border:1px solid transparent; background:color-mix(in srgb, var(--blue) 12%, transparent);
  color:var(--blue); font-size:11px; font-weight:650; letter-spacing:-.005em;
  transition:background .14s ease, border-color .14s ease, transform .1s ease; }
.msg-replies:hover { background:color-mix(in srgb, var(--blue) 20%, transparent);
  border-color:color-mix(in srgb, var(--blue) 36%, transparent); }
.msg-replies:active { transform:scale(.97); }
.msg-turn.mine .msg-replies { align-self:flex-end; }
.msg-replies-when { color:var(--subtle); font-weight:500; }
.msg-replies.fresh { background:color-mix(in srgb, var(--blue) 20%, transparent); }
.msg-replies.fresh::after { content:""; width:6px; height:6px; border-radius:50%;
  background:var(--blue); box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 20%, transparent); }

/* An open editor drops the gradient: you are working on the text, not reading
   it, and white-on-blue in a textarea is unreadable. */
.msg-turn.mine .msg-bubble.editing,
.msg-turn.mine .msg-bubble.confirming { background:var(--panel-2);
  border:1px solid var(--line); color:var(--text); box-shadow:none; }
.msg-bubble.editing, .msg-bubble.confirming { padding:9px 10px; min-width:236px; }
.msg-edit-input { width:100%; resize:none; font:inherit; font-size:13.5px;
  line-height:1.55; padding:7px 9px; border-radius:9px; background:var(--panel);
  border:1px solid var(--line); color:var(--text);
  transition:border-color .15s ease, box-shadow .15s ease; }
.msg-edit-input:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.msg-confirm-q { display:block; font-size:12.5px; padding:2px 2px 0;
  color:var(--text); }
.msg-inline-actions { display:flex; justify-content:flex-end; gap:6px;
  margin-top:8px; }
/* The same size and shape as .button.sm, so a small button is one thing. */
.msg-mini { padding:5px 11px; border-radius:8px; font-size:11px;
  font-weight:700; cursor:pointer; border:1px solid var(--line-strong);
  background:var(--panel); color:var(--muted); box-shadow:var(--shadow-sm);
  transition:background .14s ease, border-color .14s ease, color .14s ease; }
.msg-mini:hover { border-color:var(--blue); color:var(--text); background:var(--lift-2); }
.msg-mini.primary { background:var(--blue-solid); border-color:transparent; color:#fff; }
.msg-mini.primary:hover { filter:brightness(1.07); }
.msg-mini.danger { background:#e2564b; border-color:transparent; color:#fff; }
.msg-mini.danger:hover { filter:brightness(1.07); }

/* The thread panel. Beside the log, not over it -- you never lose your place
   in the conversation to read one reply. */
.msg-panel { background:var(--panel); border:1px solid var(--line);
  border-radius:16px; display:flex; flex-direction:column; overflow:hidden;
  animation:panelIn .18s cubic-bezier(.2,.8,.3,1); }
@keyframes panelIn { from { opacity:0; transform:translateX(10px); }
                     to { opacity:1; transform:none; } }
.msg-panel-head { display:flex; align-items:flex-start; justify-content:space-between;
  gap:10px; padding:13px 14px; border-bottom:1px solid var(--line);
  background:var(--panel-2); }
.msg-panel-head strong { display:block; font-size:13px; letter-spacing:-.01em; }
.msg-panel-sub { font-size:10.5px; }
.msg-x { display:grid; place-items:center; width:26px; height:26px; padding:0;
  border-radius:8px; border:1px solid transparent; background:transparent;
  color:var(--subtle); cursor:pointer;
  transition:background .14s ease, color .14s ease; }
.msg-x:hover { background:var(--panel); color:var(--text); }
.msg-panel-body { flex:1; overflow-y:auto; padding:16px 14px; display:flex;
  flex-direction:column; gap:14px; scrollbar-width:thin; }
.msg-panel-body .msg-turn { max-width:88%; }
.msg-panel .msg-box { padding:12px 14px 8px; }

.msg-toast { position:fixed; left:50%; bottom:26px; transform:translate(-50%,10px);
  z-index:90; padding:8px 16px; border-radius:22px; font-size:12px;
  font-weight:600; color:var(--text); background:var(--panel);
  border:1px solid var(--line); box-shadow:var(--shadow);
  opacity:0; pointer-events:none;
  transition:opacity .16s ease, transform .16s cubic-bezier(.2,.8,.3,1); }
.msg-toast.on { opacity:1; transform:translate(-50%,0); }

/* The prospect composer's shape: the box across the full width, the tools in
   a row under it, Send on the right. A message box that shares its line with
   three buttons is a message box nobody wants to write in. */
.msg-box { display:flex; flex-direction:column; gap:8px; padding:12px 16px 12px;
  border-top:1px solid var(--line); background:var(--panel-2); }
.msg-box textarea { width:100%; resize:none; font-size:13.5px; line-height:1.5;
  min-height:44px; padding:11px 13px; border-radius:12px; background:var(--panel);
  border:1px solid var(--line); color:var(--text);
  transition:border-color .15s ease, box-shadow .15s ease; }
.msg-box textarea:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.msg-box-row { display:flex; align-items:center; gap:8px; }
.msg-box-row .msg-note { padding:0; margin:0 0 0 auto; background:none; }
.msg-box-row .button { flex:0 0 auto; }
.msg-tool { flex:0 0 auto; }
.msg-note { padding:0 18px 13px; margin:0; font-size:10.5px;
  color:var(--subtle); background:var(--panel-2); }

/* An SVG icon in the top bar needs the same optical size as its glyph
   siblings, which are text and sit on a baseline. */
.tb-icon.tb-svg { display:grid; place-items:center; line-height:0; }
.msg-empty { display:flex; flex-direction:column; align-items:flex-start; }
.msg-empty-mark { width:52px; height:52px; border-radius:15px; display:grid;
  place-items:center; color:var(--blue);
  background:linear-gradient(135deg, color-mix(in srgb, var(--blue) 18%, transparent), rgba(139,92,246,.14));
  border:1px solid color-mix(in srgb, var(--blue) 22%, transparent); }

/* Starting a message from the header panel */
.quick-msg { margin-bottom:14px; padding-bottom:12px;
  border-bottom:1px solid var(--line); }
.quick-msg-head { font-size:10px; font-weight:800; letter-spacing:.1em;
  text-transform:uppercase; color:var(--subtle); margin-bottom:8px; }
.quick-people { display:flex; flex-wrap:wrap; gap:7px; }
.quick-person { display:flex; align-items:center; gap:8px; padding:6px 11px 6px 6px;
  border-radius:22px; background:var(--panel-2); border:1px solid var(--line);
  text-decoration:none; color:inherit; font-size:12.5px;
  transition:border-color .15s ease, transform .12s ease; }
.quick-person:hover { border-color:var(--blue); transform:translateY(-1px); }
.quick-person .avatar { width:22px; height:22px; font-size:9px; border-width:0; }

/* Inbox ---------------------------------------------------------------------
   A place, not a popover. Two sections down the side, read state across the
   top, and every row carrying the one control that matters on it -- keeping
   something unread. Rows are quiet by default and only the unread ones carry
   weight, so a full inbox still reads as a short list of things to do. */
/* Same three-column frame as the conversation view, because they are the same
   page now: rail, main, and the thread panel when one is open. */
.ibx-shell { display:grid; grid-template-columns:244px minmax(0,1fr); gap:16px;
  align-items:stretch; height:calc(100vh - 196px); min-height:460px; }
.ibx-shell.with-panel { grid-template-columns:244px minmax(300px,1fr) 340px; }
/* Not enough width for three: the rail goes, not the conversation. You already
   know who you are talking to. */
@media (max-width:1300px){
  .ibx-shell.with-panel { grid-template-columns:minmax(280px,1fr) 330px; }
  .ibx-shell.with-panel .ibx-rail { display:none; }
}
@media (max-width:900px){
  .ibx-shell, .ibx-shell.with-panel { grid-template-columns:1fr; height:auto; }
  .ibx-shell.with-panel .ibx-rail { display:none; }
  .msg-panel { max-height:70vh; }
}
#notifPane[hidden], #msgMain[hidden] { display:none !important; }

.ibx-rail { background:var(--panel); border:1px solid var(--line);
  border-radius:16px; padding:8px; display:flex; flex-direction:column; gap:2px;
  overflow-y:auto; scrollbar-width:thin; }
.ibx-rail > * { flex:0 0 auto; }
.ibx-nav-row { display:flex; flex-direction:column; gap:2px; }
/* The heading that separates the queue above from the people below. */
.ibx-rail-head { font-size:10px; font-weight:800; letter-spacing:.1em;
  text-transform:uppercase; color:var(--subtle); padding:14px 11px 7px;
  margin-top:6px; border-top:1px solid var(--line); }
.ibx-nav { display:flex; align-items:center; gap:10px; width:100%;
  padding:9px 11px; border:0; border-radius:10px; background:transparent;
  color:var(--muted); font-size:13px; font-weight:600; letter-spacing:-.01em;
  cursor:pointer; text-align:left; text-decoration:none;
  transition:background .14s ease, color .14s ease; }
.ibx-nav span:first-of-type { flex:1; }
.ibx-nav:hover { background:var(--lift-2); color:var(--text); }
.ibx-nav.on { background:color-mix(in srgb, var(--blue) 14%, transparent); color:var(--blue); }
.ibx-count { min-width:19px; height:19px; padding:0 6px; border-radius:10px;
  display:grid; place-items:center; font-size:10.5px; font-weight:800;
  background:var(--blue-solid); color:#fff; }
/* display:grid outranks the hidden attribute, so an empty count would sit
   there reading "0" -- which is worse than no badge at all. */
.ibx-count[hidden], .hpop-n[hidden] { display:none !important; }

.ibx-main { background:var(--panel); border:1px solid var(--line);
  border-radius:16px; overflow:hidden; display:flex; flex-direction:column;
  min-height:0; }
.ibx-head { display:flex; align-items:center; gap:14px; padding:14px 18px;
  border-bottom:1px solid var(--line); background:var(--panel-2); }
.ibx-head h1 { font-size:15px; margin:0; letter-spacing:-.015em; }
.ibx-tabs { display:flex; gap:2px; padding:3px; border-radius:10px;
  background:var(--panel); border:1px solid var(--line); margin-left:auto; }
.ibx-tab { padding:5px 13px; border:0; border-radius:8px; background:transparent;
  color:var(--subtle); font-size:11.5px; font-weight:650; cursor:pointer;
  transition:background .14s ease, color .14s ease; }
.ibx-tab:hover { color:var(--text); }
.ibx-tab.on { background:color-mix(in srgb, var(--blue) 16%, transparent); color:var(--blue); }

.ibx-list { flex:1; min-height:0; overflow-y:auto; display:flex;
  flex-direction:column; scrollbar-width:thin; }
.ibx-card { display:flex; flex-wrap:wrap; align-items:flex-start; gap:12px; padding:14px 18px;
  border-bottom:1px solid var(--line); cursor:pointer; position:relative;
  transition:background .14s ease; }
.ibx-card:last-child { border-bottom:0; }
.ibx-card:hover { background:var(--lift-1); }
/* Unread carries an accent bar and full-weight text; read is the same row with
   the volume turned down, which is what makes a mixed list scannable. */
.ibx-card.unread::before { content:""; position:absolute; left:0; top:12px;
  bottom:12px; width:3px; border-radius:0 3px 3px 0; background:var(--blue); }
.ibx-card:not(.unread) .avatar,
.ibx-card:not(.unread) .ibx-text { opacity:.72; }
.ibx-card:not(.unread) .ibx-line strong { font-weight:600; color:var(--muted); }
.ibx-card-body { flex:1; min-width:0; }
.ibx-line { display:flex; align-items:baseline; gap:5px; flex-wrap:wrap;
  font-size:12.5px; color:var(--muted); }
.ibx-line strong { font-size:13px; font-weight:700; color:var(--text);
  letter-spacing:-.01em; }
.ibx-subject { font-weight:650; color:var(--blue); }
.ibx-when { color:var(--subtle); font-size:10.5px; margin-left:2px; }
.ibx-text { margin:5px 0 0; font-size:12.5px; line-height:1.5; color:var(--muted);
  overflow-wrap:anywhere; }
.ibx-actions { display:flex; align-items:center; gap:7px; flex:0 0 auto;
  opacity:0; transition:opacity .14s ease; }
.ibx-card:hover .ibx-actions, .ibx-actions:focus-within { opacity:1; }
@media (hover: none){ .ibx-actions { opacity:1; } }
.ibx-keep { padding:5px 11px; border-radius:8px; font-size:11.5px;
  font-weight:650; cursor:pointer; border:1px solid var(--line);
  background:var(--panel); color:var(--muted);
  transition:border-color .14s ease, color .14s ease, background .14s ease; }
.ibx-keep:hover { color:var(--text); border-color:var(--subtle); }
.ibx-keep.held { background:color-mix(in srgb, var(--blue) 14%, transparent); border-color:transparent;
  color:var(--blue); }
.ibx-empty { padding:52px 24px; text-align:center; }
.ibx-empty strong { display:block; font-size:14px; margin-bottom:5px; }
.ibx-empty .helper { max-width:380px; margin:0 auto; }

/* Header messages popover ----------------------------------------------------
   Anchored under the icon rather than centred over the page: this is a glance,
   not a context switch, and a full-screen modal for "reply yes" is the thing
   that makes people go back to Slack. */
/* A quarter larger than it was (380 × 560), on Stefan's ask: a chat with a
   screenshot in it needs the room. The phone rule below still takes the width. */
.hpop { position:fixed; z-index:70; width:475px; max-height:min(700px, 82vh);
  display:flex; flex-direction:column; overflow:hidden;
  background:var(--panel); border:1px solid var(--line); border-radius:14px;
  box-shadow:var(--shadow-lg);
  animation:hpopIn .14s cubic-bezier(.2,.8,.3,1); }
.hpop[hidden] { display:none !important; }
@keyframes hpopIn { from { opacity:0; transform:translateY(-6px) scale(.985); }
                    to { opacity:1; transform:none; } }
@media (max-width:520px){ .hpop { width:calc(100vw - 16px); } }

.hpop-tabs { display:flex; align-items:center; gap:4px; padding:8px 8px 0;
  border-bottom:1px solid var(--line); background:var(--panel-2); }
.hpop-tab { position:relative; display:flex; align-items:center; gap:6px;
  padding:8px 11px 9px; border:0; background:transparent; cursor:pointer;
  color:var(--subtle); font-size:12px; font-weight:650; letter-spacing:-.01em;
  transition:color .14s ease; }
.hpop-tab:hover { color:var(--text); }
.hpop-tab.on { color:var(--text); }
.hpop-tab.on::after { content:""; position:absolute; left:11px; right:11px;
  bottom:-1px; height:2px; border-radius:2px 2px 0 0; background:var(--blue); }
.hpop-n { min-width:16px; height:16px; padding:0 5px; border-radius:8px;
  display:grid; place-items:center; font-size:9.5px; font-weight:800;
  background:var(--blue-solid); color:#fff; }
.hpop-open { margin-left:auto; margin-right:4px; padding:5px 10px;
  border-radius:8px; font-size:11px; font-weight:650; text-decoration:none;
  color:var(--subtle); transition:background .14s ease, color .14s ease; }
.hpop-open:hover { background:var(--panel); color:var(--blue); }
.hpop-body { flex:1; min-height:0; display:flex; flex-direction:column;
  overflow-y:auto; scrollbar-width:thin; }
.hpop-empty { padding:26px 18px; margin:0; text-align:center; }

.hpop-person { display:flex; align-items:center; gap:10px; width:100%;
  padding:10px 12px; border:0; border-bottom:1px solid var(--line);
  background:transparent; cursor:pointer; text-align:left;
  transition:background .12s ease; }
.hpop-person:hover { background:var(--lift-2); }
.hpop-person-body { flex:1; min-width:0; }
.hpop-person-top { display:flex; align-items:baseline; justify-content:space-between;
  gap:8px; }
.hpop-person-name { font-size:12.5px; font-weight:650; letter-spacing:-.01em; }
.hpop-person-last { display:block; font-size:11px; color:var(--subtle);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }
.hpop-when { font-size:10px; color:var(--subtle); font-weight:500; flex:0 0 auto; }
.avatar.sm { width:26px; height:26px; font-size:10px; flex:0 0 auto; }

.hpop-chat-head { display:flex; align-items:center; gap:8px; padding:9px 10px;
  border-bottom:1px solid var(--line); background:var(--panel-2);
  position:sticky; top:0; z-index:2; }
.hpop-chat-head strong { flex:1; font-size:12.5px; letter-spacing:-.01em; }
.hpop-back, .hpop-expand { display:grid; place-items:center; width:24px;
  height:24px; border-radius:7px; border:0; background:transparent;
  color:var(--subtle); cursor:pointer; text-decoration:none;
  transition:background .12s ease, color .12s ease; }
.hpop-back:hover, .hpop-expand:hover { background:var(--panel); color:var(--text); }

.hpop-log { flex:1; min-height:120px; overflow-y:auto; padding:12px;
  display:flex; flex-direction:column; gap:9px; scrollbar-width:thin; }
/* Sits the conversation on the bottom of the panel when there is not enough of
   it to fill the space. `margin-top:auto` on the first child rather than
   justify-content:flex-end, which makes overflowing content unreachable. */
.hpop-log > :first-child { margin-top:auto; }
.hpop-row { display:flex; align-items:center; gap:3px; max-width:100%; }
.hpop-more { display:grid; place-items:center; width:22px; height:22px; padding:0;
  flex:0 0 auto; border:0; border-radius:6px; background:transparent;
  color:var(--subtle); cursor:pointer; fill:currentColor; opacity:0;
  pointer-events:none; transition:opacity .13s ease, background .13s ease,
  color .13s ease; }
.hpop-turn:hover .hpop-more, .hpop-more:focus-visible { opacity:1;
  pointer-events:auto; }
.hpop-more:hover { background:var(--panel-2); color:var(--text); }
@media (hover: none) { .hpop-more { opacity:.45; pointer-events:auto; } }
.hpop-bubble.gone { font-style:italic; color:var(--subtle);
  background:transparent; border:1px dashed var(--line); }
.hpop-turn.mine .hpop-bubble.gone { background:transparent; color:var(--subtle); }
.hpop-turn.mine .hpop-bubble.editing,
.hpop-turn.mine .hpop-bubble.confirming { background:var(--panel-2);
  border:1px solid var(--line); color:var(--text); }
.hpop-bubble.editing, .hpop-bubble.confirming { padding:7px 8px; min-width:200px;
  font-size:12px; }
.hpop-edit { width:100%; resize:none; font:inherit; font-size:12.5px;
  line-height:1.45; padding:6px 8px; border-radius:8px; background:var(--panel);
  border:1px solid var(--line); color:var(--text); }
.hpop-edit:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.hpop-mini-row { display:flex; justify-content:flex-end; gap:5px; margin-top:6px; }
.hpop-turn { display:flex; flex-direction:column; max-width:82%; }
.hpop-turn.mine { align-self:flex-end; align-items:flex-end; }
.hpop-bubble { padding:7px 11px; border-radius:13px; font-size:12.5px;
  line-height:1.5; background:var(--panel-2); border:1px solid var(--line);
  overflow-wrap:anywhere; }
.hpop-turn.mine .hpop-bubble { background:var(--blue-solid); border-color:transparent;
  color:#fff; border-bottom-right-radius:5px; }
.hpop-turn.theirs .hpop-bubble { border-bottom-left-radius:5px; }
.hpop-bubble.pending { opacity:.6; }
.hpop-stamp { font-size:9px; color:var(--subtle); margin-top:3px; padding:0 4px; }
.hpop-stamp a { color:var(--blue); text-decoration:none; font-weight:650; }
.hpop-stamp a:hover { text-decoration:underline; }

.hpop-compose-wrap { position:sticky; bottom:0; border-top:1px solid var(--line);
  background:var(--panel-2); }
.hpop-compose { display:flex; align-items:flex-end; gap:7px; padding:9px 10px; }
.hpop-memo { padding:8px 10px 0; }
.hpop-memo .ws-memo { margin-bottom:0; }
.hpop-memo audio { width:190px; }
.hpop-mic { display:grid; place-items:center; width:32px; height:32px;
  border-radius:9px; border:1px solid var(--line); background:var(--panel);
  color:var(--muted); cursor:pointer; flex:0 0 auto;
  transition:color .14s ease, border-color .14s ease; }
.hpop-mic:hover { color:var(--blue); border-color:color-mix(in srgb, var(--blue) 40%, transparent); }
.hpop-compose textarea { flex:1; resize:none; font:inherit; font-size:12.5px;
  line-height:1.5; padding:8px 11px; border-radius:10px; max-height:96px;
  background:var(--panel); border:1px solid var(--line); color:var(--text);
  transition:border-color .14s ease, box-shadow .14s ease; }
.hpop-compose textarea:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.hpop-send { display:grid; place-items:center; width:32px; height:32px;
  border-radius:9px; border:0; background:var(--blue-solid); color:#fff;
  cursor:pointer; flex:0 0 auto; transition:filter .14s ease, transform .1s ease; }
.hpop-send:hover { filter:brightness(1.08); }
.hpop-send:active { transform:scale(.94); }

.hpop-bar { display:flex; align-items:center; justify-content:space-between;
  gap:8px; padding:7px 12px; border-bottom:1px solid var(--line);
  font-size:10px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:var(--subtle); }
.hpop-bar.push { text-transform:none; letter-spacing:0; font-size:11.5px; font-weight:500;
  color:var(--muted); background:color-mix(in srgb, var(--blue) 6%, transparent); }
.hpop-bar-acts { display:flex; align-items:center; gap:8px; flex:0 0 auto; }
.hpop-x { border:0; background:transparent; color:var(--subtle); font-size:15px; line-height:1;
  padding:0 2px; cursor:pointer; }
.hpop-x:hover { color:var(--text); }
.hpop-link { border:0; background:transparent; padding:2px 0; font:inherit;
  font-size:11px; font-weight:650; letter-spacing:0; text-transform:none;
  color:var(--blue); cursor:pointer; }
.hpop-link:hover { text-decoration:underline; }
.hpop-link:disabled { color:var(--subtle); cursor:default; text-decoration:none; }
/* A mention is a row you open, like a person in Messages: the whole row is
   the button, the chevron says it stays in the panel. */
.hpop-note { display:flex; align-items:flex-start; gap:9px; width:100%;
  padding:11px 12px; border:0; border-bottom:1px solid var(--line);
  background:transparent; text-align:left; cursor:pointer; font:inherit;
  color:inherit; transition:background .12s ease; }
.hpop-note:hover { background:var(--lift-2); }
.hpop-note-body { flex:1; min-width:0; display:block; }
.hpop-note-line { display:block; font-size:11.5px; color:var(--muted); line-height:1.45; }
.hpop-note-line strong { font-size:12px; color:var(--text); font-weight:700; }
.hpop-subject { color:var(--blue); font-weight:650; }
.hpop-note-text { display:block; margin:3px 0 0; font-size:11.5px; line-height:1.45;
  color:var(--subtle); overflow-wrap:anywhere; }
.hpop-chev { flex:0 0 auto; align-self:center; color:var(--subtle); }
.hpop-note-full { padding:12px 14px 14px; }
.hpop-note-when { margin-top:2px; font-size:10.5px; color:var(--subtle); }
.hpop-note-read { margin:10px 0 0; font-size:12.5px; line-height:1.5;
  color:var(--text); white-space:pre-wrap; overflow-wrap:anywhere; }
.hpop-note-acts { display:flex; flex-wrap:wrap; gap:8px; margin-top:14px; }
.hpop-go { flex:0 0 auto; padding:5px 11px; border-radius:7px; font:inherit;
  font-size:11px; font-weight:650; text-decoration:none; color:var(--muted);
  background:transparent; border:1px solid var(--line); cursor:pointer;
  transition:color .14s ease, border-color .14s ease; }
.hpop-go:hover { color:var(--blue); border-color:color-mix(in srgb, var(--blue) 40%, transparent); }
.hpop-go:disabled { color:var(--subtle); border-color:var(--line); cursor:default; }
.hpop-go.go { color:#fff; background:var(--blue-solid); border-color:transparent; }
.hpop-go.go:hover { color:#fff; filter:brightness(1.07); }

/* Shared conversation ---------------------------------------------------------
   The same frame wherever people talk: direct messages, thread panels, and the
   running conversation under a client. A note on a client is a message that
   happens to be about that client, and it should not have to be recognised as
   a different kind of object. */
.convo { display:flex; flex-direction:column; border:1px solid var(--line);
  border-radius:14px; overflow:hidden; background:var(--panel-2);
  min-height:320px; }
.convo .msg-log { background:var(--panel); max-height:min(560px, 60vh); }
/* Inside the client overlay there is a header, tabs and a composer to fit
   around, so the log takes less. Without this the composer is pushed past the
   bottom of the dialog and the conversation is readable but not writable --
   which is most of the way to useless. */
.brain-panel .convo .msg-log { max-height:min(360px, 40vh); }
.convo .msg-box { border-top:1px solid var(--line); }
.convo-head { display:flex; align-items:center; gap:12px; margin:10px 0 12px; }

/* Who said it, once per run rather than on every bubble. With two people it is
   noise; with a whole team on a client record it is the first thing you need. */
.msg-who { display:flex; align-items:center; gap:6px; margin:0 0 5px 2px;
  font-size:11px; font-weight:700; color:var(--muted); letter-spacing:-.01em; }
.avatar.xs { width:18px; height:18px; font-size:8px; flex:0 0 auto; }
/* Where a line came from, when that is not obvious. Deliberately quiet: it is
   provenance, not a label anybody is looking for. */
.msg-badge { padding:1px 6px; border-radius:20px; font-size:9px; font-weight:700;
  letter-spacing:.03em; text-transform:uppercase; color:var(--subtle);
  border:1px solid var(--line); }
.msg-blank { padding:34px 20px; text-align:center; margin:0; }

/* A client conversation is many voices, so the bubbles get more room than the
   two-person case needs. */
.convo .msg-turn { max-width:82%; }

/* What you are replying to, named above the composer. Quiet, dismissible, and
   impossible to miss -- a reply that silently lands on the wrong message is
   worse than no threading at all. */
.reply-to { display:flex; align-items:center; gap:8px; padding:7px 14px;
  background:color-mix(in srgb, var(--blue) 10%, transparent); border-top:1px solid var(--line);
  font-size:11.5px; color:var(--blue); font-weight:600; }
.reply-to[hidden] { display:none !important; }
.reply-to span { flex:1; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; }
.reply-to button { display:grid; place-items:center; width:20px; height:20px;
  border:0; border-radius:6px; background:transparent; color:inherit;
  cursor:pointer; flex:0 0 auto; transition:background .13s ease; }
.reply-to button:hover { background:color-mix(in srgb, var(--blue) 20%, transparent); }

/* Threads open beside the conversation, never inside it -------------------
   Slack and ClickUp both push the conversation left and put the thread in its
   own column, and they are right: the point of a thread is that you have gone
   somewhere. A few indented bubbles do not read as somewhere, and an overlay
   that covers the conversation loses the message you are replying to. */
.convo-split { display:grid; grid-template-columns:minmax(0,1fr); gap:14px;
  align-items:stretch; }
.convo-split.open { grid-template-columns:minmax(0,1fr) 320px; }
@media (max-width:820px){
  .convo-split.open { grid-template-columns:minmax(0,1fr); }
}
.convo-panel { display:flex; flex-direction:column; overflow:hidden;
  background:var(--panel-2); border:1px solid var(--line); border-radius:14px;
  animation:panelIn .18s cubic-bezier(.2,.8,.3,1); }
.convo-panel[hidden] { display:none !important; }
.convo-panel .msg-panel-body { background:var(--panel);
  max-height:min(360px, 40vh); }
.brain-panel .convo-panel .msg-panel-body { max-height:min(320px, 36vh); }

/* The dialog grows to make room rather than squeezing the conversation into a
   column too narrow to read. */
/* .brain-panel sets `width`, and max-width cannot grow a box past its own
   width -- so opening a thread has to raise both or the dialog silently stays
   narrow and the two columns fight over 760px. */
.note-dialog { width:min(600px, 100%); max-width:none;
  transition:width .22s cubic-bezier(.2,.8,.3,1); }
.note-dialog.wide { width:min(1040px, calc(100vw - 48px)); }

/* Which message the open thread belongs to. Without this the panel is a box of
   text floating next to a log, and you cannot tell what it is attached to. */
.msg-turn.threaded .msg-bubble { box-shadow:0 0 0 2px color-mix(in srgb, var(--blue) 45%, transparent); }
.msg-turn.threaded.mine .msg-bubble { box-shadow:0 0 0 2px rgba(255,255,255,.5),
  0 4px 14px color-mix(in srgb, var(--blue) 28%, transparent); }
.msg-replies.open { background:color-mix(in srgb, var(--blue) 22%, transparent);
  border-color:color-mix(in srgb, var(--blue) 45%, transparent); }

/* Contract dates -------------------------------------------------------------
   Changed through what happened -- froze, re-signed -- rather than by typing
   two dates, because the typing is what people forgot. */
.term-now { margin-bottom:16px; }
.term-dates { display:flex; align-items:center; gap:16px; flex-wrap:wrap;
  padding:14px 16px; border:1px solid var(--line); border-radius:12px;
  background:var(--panel-2); }
.term-dates label { display:block; font-size:9.5px; font-weight:800;
  letter-spacing:.08em; text-transform:uppercase; color:var(--subtle);
  margin-bottom:3px; }
.term-dates strong { font-size:15px; letter-spacing:-.01em;
  font-variant-numeric:tabular-nums; }
.term-arrow { color:var(--subtle); font-size:16px; }
.term-meta { margin-left:auto; font-size:11.5px; color:var(--muted); }
.term-over { color:var(--ink-bad); font-weight:650; }

/* A contract agreed but not yet started. Given real weight on purpose: this is
   the thing that used to be invisible until it was too late. */
.term-queued { display:flex; align-items:center; gap:12px; margin-top:10px;
  padding:11px 14px; border-radius:12px; font-size:12.5px;
  background:color-mix(in srgb, var(--blue) 12%, transparent); border:1px solid color-mix(in srgb, var(--blue) 30%, transparent); }
.term-queued > div { flex:1; }
.term-queued .helper { display:block; font-size:10.5px; margin-top:2px; }

.term-actions { display:grid; gap:12px; }
.term-card { padding:14px 16px; border:1px solid var(--line); border-radius:12px;
  background:var(--panel-2); }
.term-card h4 { margin:0 0 4px; font-size:13px; letter-spacing:-.01em; }
.term-card .helper { margin:0 0 10px; }
.term-chips { display:flex; gap:6px; margin-bottom:9px; flex-wrap:wrap; }
.term-chip { padding:6px 13px; border-radius:9px; font-size:12px; font-weight:650;
  cursor:pointer; color:var(--muted); background:var(--panel);
  border:1px solid var(--line);
  transition:border-color .14s ease, color .14s ease, background .14s ease; }
.term-chip:hover { border-color:var(--blue); color:var(--blue);
  background:color-mix(in srgb, var(--blue) 10%, transparent); }
.term-row { display:flex; align-items:flex-end; gap:8px; flex-wrap:wrap; }
.term-row label { display:block; font-size:9.5px; font-weight:800;
  letter-spacing:.08em; text-transform:uppercase; color:var(--subtle); }
.term-row input, .term-row select { display:block; margin-top:4px;
  padding:8px 10px; border-radius:9px; background:var(--panel);
  border:1px solid var(--line); color:var(--text); font-size:12.5px; }
.term-row > input { flex:1; min-width:120px; }
.term-row input:focus, .term-row select:focus { outline:none;
  border-color:var(--blue); box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }

.term-history { margin-top:18px; }
.term-history h4 { font-size:11px; font-weight:800; letter-spacing:.08em;
  text-transform:uppercase; color:var(--subtle); margin:0 0 8px; }
.term-log { display:flex; align-items:flex-start; gap:12px; padding:9px 0;
  border-top:1px solid var(--line); font-size:11.5px; color:var(--muted); }
.term-log-kind { flex:0 0 74px; font-weight:750; font-size:10px;
  letter-spacing:.04em; text-transform:uppercase; padding:2px 0; }
.term-log-kind.resign { color:var(--ink-good); }
.term-log-kind.freeze { color:var(--ink-info); }
.term-log-kind.correction { color:var(--ink-warn); }
.term-log-kind.status { color:var(--muted); }
.term-log-kind.unfreeze { color:var(--ink-info); }
/* A month-to-month roll is routine bookkeeping, not a decision somebody made
   — it should read quietly next to a freeze or a re-sign. */
.term-log-kind.rolled { color:var(--muted); }
.term-log-what { flex:1; line-height:1.5; overflow-wrap:anywhere; }
.term-log-who { flex:0 0 auto; text-align:right; font-size:10.5px;
  color:var(--muted); white-space:nowrap; }
.term-log-who .helper { font-size:10px; }

/* The queued term, on the roster row. Small, but it is the whole point: the
   end date on screen is no longer the last word. */
.next-term { font-size:10px; color:var(--blue); font-weight:650;
  margin-top:2px; white-space:nowrap; }
.next-term span { color:var(--subtle); font-weight:500; }

/* The queued term on a roster row. Green when it is a re-sign: it is the one
   piece of good news in a column of churn signals and should not be read as
   another warning. */
.next-term.good { color:var(--ink-good); }
.next-term.good span { color:rgba(138,240,189,.6); }

/* Sortable columns. The glyph used to appear only on hover, so a wide table
   was not covered in arrows -- and Stefan, who the table is for, concluded
   that only the column already sorted could be sorted, because nothing told
   him otherwise. Faint at rest now: quiet enough not to be noise, present
   enough to be found. */
th.sortable { cursor:pointer; user-select:none; position:relative;
  transition:color .14s ease; }
th.sortable:hover { color:var(--text); }
th.sortable::after { content:"↕"; margin-left:5px; opacity:.32; font-size:9px;
  transition:opacity .14s ease; }
th.sortable:hover::after { opacity:.7; }
th.sortable.sorted { color:var(--blue); }
th.sortable.sorted::after { opacity:1; content:"↑"; }
th.sortable.sorted[data-dir="down"]::after { content:"↓"; }

/* The client's status, as a control rather than a label. Reads as text until
   you go near it, because it sits in a line of plain metadata and should not
   shout over the client's name. */
.status-pick { display:inline-flex; align-items:center; gap:5px; padding:2px 8px;
  margin:-2px 0; border-radius:7px; cursor:pointer; font:inherit;
  font-weight:700; color:var(--muted); background:transparent;
  border:1px solid transparent;
  transition:background .14s ease, border-color .14s ease, color .14s ease; }
.status-pick:hover { background:var(--panel); border-color:var(--line);
  color:var(--text); }
.status-pick svg { opacity:.5; }
.status-pick:hover svg { opacity:1; }

/* Renewal runway ------------------------------------------------------------
   Ninety days is "put it on the list", sixty is "book the call", thirty is
   "nobody has spoken to them and it is happening". One colour flattened all
   three into the same shrug, so each stage gets its own temperature. */
.badge.renew-ahead { border-color:rgba(234,203,94,.32); color:var(--ink-warn);
  background:rgba(234,203,94,.10); }
.badge.renew-soon { border-color:rgba(245,174,78,.42); color:var(--ink-warn);
  background:rgba(245,174,78,.16); }
.badge.renew-urgent { border-color:rgba(251,100,114,.5); color:var(--ink-bad);
  background:rgba(251,100,114,.18); font-weight:750; }

/* Photo permission, beside the name. Three states and never two: "not asked"
   has to stay visibly different from "no", because silence is not a refusal
   and it is certainly not consent. */
.photo-chip { display:inline-flex; align-items:center; gap:4px; margin-left:7px;
  padding:1px 7px; border-radius:20px; font-size:9.5px; font-weight:700;
  letter-spacing:-.005em; white-space:nowrap; vertical-align:middle;
  border:1px solid transparent; }
.photo-chip.ok { color:var(--ink-good); background:rgba(53,201,143,.12);
  border-color:rgba(53,201,143,.3); }
.photo-chip.no { color:var(--ink-bad); background:rgba(251,100,114,.14);
  border-color:rgba(251,100,114,.36); }
.photo-chip.unknown { color:var(--subtle); border-color:var(--line); }
.photo-chip svg { opacity:.85; }

/* Onboarding, beside the name. Complete is deliberately the quieter of the
   two: after the backfill it is true of the whole roster, and a loud chip on
   every row is wallpaper that buries the one row still owing a step. */
.onboard-chip { display:inline-flex; align-items:center; gap:4px; margin-left:7px;
  padding:1px 7px; border-radius:999px; font-size:9.5px; font-weight:700;
  letter-spacing:.01em; vertical-align:middle; border:1px solid transparent;
  white-space:nowrap; }
.onboard-chip.ok { color:var(--ink-good); background:rgba(53,201,143,.10);
  border-color:rgba(53,201,143,.26); }
.onboard-chip.open { color:var(--ink-warn); background:rgba(245,174,78,.16);
  border-color:rgba(245,174,78,.4); font-size:10px; padding:2px 8px; }
.onboard-chip svg { opacity:.9; }
.onboard-chip.open svg { display:none; }

.photo-card .helper { margin-bottom:10px; }
.photo-pick { display:flex; gap:6px; flex-wrap:wrap; }
.photo-pick button { padding:7px 13px; border-radius:9px; font-size:12px;
  font-weight:650; cursor:pointer; color:var(--muted); background:var(--panel);
  border:1px solid var(--line);
  transition:border-color .14s ease, color .14s ease, background .14s ease; }
.photo-pick button:hover { color:var(--text); border-color:var(--subtle); }
.photo-pick button.on[data-photo="yes"] { color:var(--ink-good);
  border-color:rgba(53,201,143,.5); background:rgba(53,201,143,.14); }
.photo-pick button.on[data-photo="no"] { color:var(--ink-bad);
  border-color:rgba(251,100,114,.5); background:rgba(251,100,114,.14); }
.photo-pick button.on[data-photo=""] { color:var(--text);
  border-color:var(--subtle); background:var(--panel-2); }

/* The five onboarding steps. Numbered while open, ticked when done -- the
   number is the order to do them in, which is most of what an SOP is. */
.steps { display:flex; flex-direction:column; gap:6px; }
.step { display:flex; align-items:flex-start; gap:11px; width:100%;
  padding:10px 12px; border-radius:11px; text-align:left; cursor:pointer;
  background:var(--panel); border:1px solid var(--line);
  transition:border-color .14s ease, background .14s ease; }
.step:hover { border-color:var(--subtle); }
.step-tick { display:grid; place-items:center; width:22px; height:22px;
  flex:0 0 auto; border-radius:50%; font-size:10.5px; font-weight:800;
  color:var(--subtle); border:1px solid var(--line);
  transition:background .14s ease, color .14s ease, border-color .14s ease; }
.step.done .step-tick { background:rgba(53,201,143,.16); color:var(--ink-good);
  border-color:rgba(53,201,143,.42); }
.step-body { display:flex; flex-direction:column; gap:2px; min-width:0; }
.step-label { font-size:12.5px; font-weight:650; letter-spacing:-.01em; }
/* currentColor, not a fixed white: a white strike at 25% is invisible on the
   white card in light mode, so a finished step read as an unfinished one. */
.step.done .step-label { color:var(--muted); text-decoration:line-through;
  text-decoration-color:currentColor; text-decoration-thickness:1px; }
.step-hint { font-size:11px; color:var(--subtle); line-height:1.45; }

.tab-count { margin-left:5px; padding:1px 6px; border-radius:9px; font-size:9.5px;
  font-weight:800; background:rgba(245,174,78,.2); color:var(--ink-warn); }
.tab-count[hidden] { display:none !important; }
/* Finished reads as an answer, not an absence. The badge used to disappear at
   zero-left, which made "all five done" look exactly like "no checklist here". */
.tab-count.ok { display:inline-grid; place-items:center; padding:2px 6px;
  background:rgba(53,201,143,.2); color:var(--ink-good); }

/* Said out loud on the Onboarding tab, and it takes the place of the "tick them
   as they are done" instruction rather than sitting above it -- once they are
   all ticked the instruction is noise. */
.onboard-complete { display:flex; align-items:center; gap:10px;
  margin:0 0 10px; padding:10px 12px; border-radius:11px;
  background:rgba(53,201,143,.10); border:1px solid rgba(53,201,143,.34); }
.onboard-complete[hidden] { display:none !important; }
.onboard-complete-tick { display:grid; place-items:center; width:22px; height:22px;
  flex:0 0 auto; border-radius:50%; color:var(--ink-good);
  background:rgba(53,201,143,.18); border:1px solid rgba(53,201,143,.42); }
.onboard-complete-body { display:flex; flex-direction:column; gap:1px; min-width:0; }
.onboard-complete-body strong { font-size:12.5px; font-weight:700;
  letter-spacing:-.01em; color:var(--ink-good); }
/* --subtle is the app's faintest ink and it does not survive the green tint
   this line sits on: 3.0:1 in light, 2.8:1 in dark, against 4.5:1 for text
   this size. --muted clears it in both. */
.onboard-complete-body span { font-size:11px; color:var(--muted); }

/* An empty status group still shows its heading, so the set of buckets is
   always visible. Dimmed, because there is nothing to do in it. */
.group-head.empty { opacity:.5; }
.group-empty { margin-left:8px; font-size:10.5px; color:var(--subtle);
  font-style:italic; }

/* Tile panel -----------------------------------------------------------------
   A number on a card is a question -- "who are the eight?" -- and it used to
   be a dead end. Clicking one opens the list beside the page rather than
   navigating away, so you can look at them, act on one, and still be where you
   started. Same instinct as the thread panel. */
.metric-open { display:block; width:100%; text-align:left; cursor:pointer;
  font:inherit; position:relative;
  transition:border-color .16s ease, transform .12s ease; }
.metric-open:hover { border-color:var(--line-strong); transform:translateY(-1px); }
.metric-open:active { transform:translateY(0); }
/* A quiet arrow rather than a button: the whole card is the target. */
.metric-open::after { content:"›"; position:absolute; top:12px; right:14px;
  font-size:15px; line-height:1; color:var(--subtle); opacity:0;
  transition:opacity .16s ease, transform .16s ease; }
.metric-open:hover::after { opacity:.8; transform:translateX(2px); }
.metric-open:focus-visible { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); }

.tile-panel { position:fixed; top:0; right:0; bottom:0; width:min(420px, 92vw);
  z-index:55; display:flex; flex-direction:column; background:var(--panel);
  border-left:1px solid var(--line);
  box-shadow:var(--shadow-lg);
  animation:tileIn .2s cubic-bezier(.2,.8,.3,1); }
.tile-panel[hidden] { display:none !important; }
@keyframes tileIn { from { transform:translateX(24px); opacity:0; }
                    to { transform:none; opacity:1; } }
/* The page slides over rather than being covered, so the roster underneath
   stays readable and keeps its place. */
body.tile-open .app-shell { padding-right:min(420px, 92vw);
  transition:padding-right .2s cubic-bezier(.2,.8,.3,1); }
@media (max-width:900px){ body.tile-open .app-shell { padding-right:0; } }

.tile-panel-head { display:flex; align-items:flex-start; justify-content:space-between;
  gap:10px; padding:16px 16px 13px; border-bottom:1px solid var(--line);
  background:var(--panel-2); }
.tile-panel-head strong { display:block; font-size:15px; letter-spacing:-.015em; }
.tile-panel-head .helper { display:block; margin-top:3px; font-size:11px;
  line-height:1.45; }
.tile-panel-tools { display:flex; align-items:center; gap:7px; flex-wrap:wrap;
  padding:11px 16px; border-bottom:1px solid var(--line); }
.tile-panel-tools input, .tile-panel-tools select { flex:1; min-width:110px;
  padding:7px 10px; border-radius:9px; font-size:12px; background:var(--panel-2);
  border:1px solid var(--line); color:var(--text); }
.tile-panel-tools input:focus, .tile-panel-tools select:focus { outline:none;
  border-color:var(--blue); box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.tile-sort { display:flex; gap:2px; padding:2px; border-radius:9px;
  background:var(--panel-2); border:1px solid var(--line); flex:0 0 auto; }
.tile-sort button { padding:5px 10px; border:0; border-radius:7px;
  background:transparent; color:var(--subtle); font-size:11px; font-weight:650;
  cursor:pointer; transition:background .14s ease, color .14s ease; }
.tile-sort button:hover { color:var(--text); }
.tile-sort button.on { background:color-mix(in srgb, var(--blue) 16%, transparent); color:var(--blue); }

.tile-panel-body { flex:1; overflow-y:auto; scrollbar-width:thin; }
.tile-row { display:block; width:100%; text-align:left; padding:12px 16px;
  border:0; border-bottom:1px solid var(--line); background:transparent;
  cursor:pointer; transition:background .13s ease; }
.tile-row:hover { background:var(--lift-2); }
.tile-row-top { display:flex; align-items:center; justify-content:space-between;
  gap:10px; }
.tile-row-name { font-size:13px; font-weight:650; letter-spacing:-.01em; }
.tile-row-sub { display:block; margin-top:3px; font-size:11px;
  color:var(--subtle); }
.tile-row .photo-chip { margin:6px 0 0; }

/* Clients the live roster does not list, surfaced by name search. A finished
   client who has just re-signed is exactly who you go looking for, and until
   now they could not be found at all. Marked clearly so nobody mistakes one
   for an active client. */
.off-roster { margin:10px 0 4px; border:1px solid rgba(245,174,78,.3);
  border-radius:12px; overflow:hidden; background:rgba(245,174,78,.06); }
.off-roster[hidden] { display:none !important; }
.off-roster-head { padding:8px 14px; font-size:10px; font-weight:800;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink-warn);
  border-bottom:1px solid rgba(245,174,78,.2); }
.off-roster-row { display:flex; align-items:center; justify-content:space-between;
  gap:12px; width:100%; padding:10px 14px; border:0; background:transparent;
  cursor:pointer; text-align:left; transition:background .13s ease; }
.off-roster-row:hover { background:rgba(245,174,78,.1); }
.off-roster-row strong { font-size:13px; }
.off-roster-row .helper { display:block; font-size:11px; margin-top:2px; }
.off-roster-open { flex:0 0 auto; font-size:11px; font-weight:700; color:var(--ink-warn); }

/* P&L -----------------------------------------------------------------------
   A month whose costs were never entered is marked, not hidden. The gross
   profit on those months is higher than the truth, and a runway model built on
   them would say the business is in the best shape it has ever been in. */
.pnl-row { cursor:pointer; transition:background .13s ease; }
.pnl-row:hover { background:var(--lift-2); }
.pnl-row.partial td { opacity:.72; }
.pnl-row.partial td:first-child b::after { content:"*"; color:var(--ink-warn);
  margin-left:3px; }
.pnl-gap { font-size:10.5px; font-weight:650; color:var(--ink-warn);
  background:rgba(245,174,78,.13); border:1px solid rgba(245,174,78,.28);
  border-radius:20px; padding:1px 8px; white-space:nowrap; }
.pnl-detail td { background:var(--panel-2); padding:12px 14px; }
.pnl-chip { display:inline-flex; gap:6px; margin:0 6px 6px 0; padding:3px 10px;
  border-radius:20px; font-size:11.5px; color:var(--muted);
  background:var(--panel); border:1px solid var(--line); }
.pnl-chip b { color:var(--text); font-variant-numeric:tabular-nums; }
.pnl-total td { border-top:1px solid var(--line-strong); }
td.num, th.num { text-align:right; font-variant-numeric:tabular-nums; }
td.num.neg { color:var(--ink-bad); }
.term-hint { margin:9px 0 0; font-size:11.5px; }

/* Payment standing. Deliberately amount-free so it can be shown to coaches:
   knowing a client's card is failing is what lets them flag it, and it is a
   different thing from knowing what the contract is worth. */
.pay-chip { display:inline-flex; align-items:center; gap:4px; margin-left:7px;
  padding:1px 7px; border-radius:20px; font-size:9.5px; font-weight:750;
  letter-spacing:-.005em; white-space:nowrap; vertical-align:middle;
  border:1px solid transparent; }
.pay-chip.bad { color:var(--ink-bad); background:var(--tint-red);
  border-color:var(--ink-bad); }
/* Quieter than past due, but still legible -- which it was not. It used a pale
   green at 72% alpha over nothing, chosen against a dark panel; on a white page
   that is a rumour of a chip. It carries its own tint and a real border now,
   and both come from the theme so light gets the dark green and dark gets the
   bright one. */
.pay-chip.ok { color:var(--ink-good); background:var(--tint-green);
  border-color:color-mix(in srgb, var(--ink-good) 45%, transparent); }
.pay-chip.unknown { color:var(--subtle); border-color:var(--line); }
.past-pane[hidden] { display:none !important; }
.wb-state { padding:5px 9px; border-radius:8px; font-size:11.5px;
  background:var(--panel-2); border:1px solid var(--line); color:var(--text); }
.wb-state:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.wb-who { font-size:9.5px; color:var(--subtle); margin-top:3px; }
.pay-card { margin-bottom:14px; }
.photo-pick button.on[data-pay="good"] { color:var(--ink-good);
  border-color:rgba(53,201,143,.5); background:rgba(53,201,143,.14); }
.photo-pick button.on[data-pay="past_due"] { color:var(--ink-bad);
  border-color:rgba(251,100,114,.5); background:rgba(251,100,114,.14); }

/* The MM-DD-YYYY echo under a native date input. The browser renders those in
   the operating system's locale and gives no way to override it, so the value
   is repeated in our format rather than left ambiguous. */
.date-echo { display:inline-block; margin-left:8px; font-size:10.5px;
  color:var(--subtle); font-variant-numeric:tabular-nums; }
.date-echo:empty { display:none; }

/* Payroll ------------------------------------------------------------------- */
.pr-field { display:flex; align-items:center; gap:8px; font-size:11px;
  font-weight:800; letter-spacing:.08em; text-transform:uppercase;
  color:var(--subtle); }
.pr-field select { padding:8px 10px; border-radius:9px; background:var(--panel-2);
  border:1px solid var(--line); color:var(--text); font-size:13px;
  letter-spacing:normal; text-transform:none; font-weight:600; }
.pr-check { display:flex; align-items:center; gap:7px; font-size:12px;
  color:var(--muted); }
.pr-period { margin:6px 0 16px; font-size:13px; color:var(--muted); }
.pr-period b { color:var(--text); }

.pr-coach { padding:0; margin-bottom:10px; overflow:hidden; }
.pr-coach-head { display:flex; align-items:center; gap:14px; width:100%;
  padding:14px 18px; border:0; background:transparent; cursor:pointer;
  text-align:left; transition:background .14s ease; }
.pr-coach-head:hover { background:var(--lift-2); }
.pr-coach-name { font-size:14px; font-weight:700; letter-spacing:-.01em;
  flex:0 0 auto; }
.pr-coach-split { flex:1; }
.pr-coach-total { font-size:17px; font-weight:800; font-variant-numeric:tabular-nums; }
.pr-detail { border-top:1px solid var(--line); padding:4px 8px 8px; }

/* Filtering nineteen clients down to the one being queried. Sits inside the
   coach's card so it is obvious which list it is narrowing. */
.pr-filters { display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  padding:10px 6px 8px; }
.pr-filters .pr-search { flex:0 1 220px; min-width:150px; }
.pr-filters select { flex:0 1 170px; min-width:130px; }
.pr-filters input, .pr-filters select { font-size:12px; padding:6px 9px;
  min-height:0; height:auto; }
.pr-count { margin-left:auto; }
/* Inside a coach's card, and inside each paid run in the history: the
   paycheck in its two parts, client pay and commission, each with its own
   subtotal. The commission part is always drawn -- an empty one says so. */
.pr-part { padding:6px 0 4px; }
.pr-part + .pr-part { border-top:1px solid var(--line); margin-top:6px; }
.pr-part-head, .pr-hist-block-head { display:flex; justify-content:space-between; align-items:baseline;
  padding:8px 6px 4px; font-size:12px; font-weight:700; letter-spacing:.02em;
  text-transform:uppercase; color:var(--muted); }
.pr-part-head span:last-child, .pr-hist-block-head span:last-child {
  font-variant-numeric:tabular-nums; text-transform:none; letter-spacing:0; color:var(--text); }
.pr-hist-block { padding:0 10px 6px; }
.pr-hist-empty { margin:0 6px 8px; font-size:12px; }
.pr-hist-coach-head .helper { flex:1; margin:0 12px; }
/* A commission that has already gone out on a paid run: kept for the record,
   read-only, shown on request. */
.pr-paid-row td { color:var(--muted); }
/* The tracker's editable cells: a coach name needs room to read, an amount
   does not. */
#prPending select.pr-mini { min-width:130px; }
#prPending input[data-pamount] { width:76px; }
/* A commission somebody has decided not to pay. Struck rather than deleted --
   it can be put back, and "where did that go" is a worse question than a line
   with a line through it. */
.pr-dropped td { opacity:.5; }
.pr-dropped td:first-child b { text-decoration:line-through; }
.pr-mini { font-size:11px; padding:5px 11px; min-height:0; height:auto;
  width:100%; max-width:170px; }
.pr-pend-actions { display:flex; gap:6px; align-items:center;
  white-space:nowrap; }

/* A coach whose total was agreed rather than worked out. Flagged on the card,
   because a number somebody typed should never look like a number the software
   derived. */
.pr-agreed { border-color:rgba(53,201,143,.35); }
.pr-coach-total .pr-tag { margin-left:8px; vertical-align:middle; }
.pr-coach-note { padding:0 16px 12px; font-size:12px; color:var(--muted);
  border-left:2px solid rgba(53,201,143,.5); margin:0 16px 12px; }
.pr-adjust { display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap;
  padding:12px 6px 6px; margin-top:6px; border-top:1px solid var(--line); }
.pr-adjust label { display:flex; flex-direction:column; gap:4px; font-size:11px;
  color:var(--subtle); }
.pr-adjust .pr-adjust-note { flex:1; min-width:220px; }
.pr-adjust .pr-adjust-note input { max-width:none; }
.pr-adjust .helper { flex-basis:100%; }

/* Rates, folded away and read-only until asked for twice. */
.pr-disclose { display:flex; align-items:flex-start; gap:10px; width:100%;
  text-align:left; padding:12px 14px; border:1px solid var(--line);
  border-radius:var(--radius); background:var(--panel); color:inherit;
  cursor:pointer; transition:background .15s ease, border-color .15s ease; }
.pr-disclose:hover { background:var(--lift-2); }
.pr-disclose .pr-chev { flex:0 0 auto; margin-top:3px; color:var(--subtle);
  transition:transform .16s ease; }
.pr-disclose[aria-expanded="true"] .pr-chev { transform:rotate(90deg); }
.pr-disclose-title { display:block; font-size:15px; font-weight:700;
  letter-spacing:-.01em; }
.pr-disclose-sub { display:block; font-size:11.5px; color:var(--subtle);
  margin-top:2px; }
.pr-lock { display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  margin:10px 0; padding:9px 13px; border-radius:11px;
  border:1px solid var(--line); background:var(--panel-2); }
.pr-lock.on { border-color:rgba(245,174,78,.45);
  background:rgba(245,174,78,.09); }
.pr-lock .helper { flex:1; }
.pr-rate-cols { align-items:start; }
.pr-rate-cols input:disabled, .pr-rate-cols button:disabled { opacity:.5;
  cursor:default; }
.pr-comm-row td { background:rgba(53,201,143,.06); }
.pr-tag { display:inline-block; padding:1px 7px; border-radius:20px; font-size:9.5px;
  font-weight:700; color:var(--subtle); border:1px solid var(--line); }
.pr-tag.warn { color:var(--ink-warn); border-color:rgba(245,174,78,.4); }
.pr-tag.good { color:var(--ink-good); border-color:rgba(53,201,143,.35); }
.pr-rate, .pr-comm { width:90px; padding:5px 8px; border-radius:7px; text-align:right;
  background:var(--panel-2); border:1px solid var(--line); color:var(--text);
  font-variant-numeric:tabular-nums; }

/* The date field ------------------------------------------------------------
   Ours rather than the browser's, because the browser's renders in the
   operating system's locale and cannot be told otherwise -- which is how the
   same contract read 08-01 in Arizona and 01-08 in Manila. */
.dp { display:inline-flex; align-items:center; position:relative; }
.dp-text { padding:8px 10px; border-radius:9px; background:var(--panel);
  border:1px solid var(--line); color:var(--text); font-size:12.5px;
  font-variant-numeric:tabular-nums; width:132px; }
.dp-text:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
/* Something unparseable stays on screen and is marked, rather than being
   silently discarded or silently guessed at. */
.dp-text.bad { border-color:var(--ink-bad); box-shadow:0 0 0 3px rgba(226,86,75,.16); }
.dp-btn { display:grid; place-items:center; width:28px; height:28px; margin-left:-32px;
  border:0; background:transparent; color:var(--subtle); cursor:pointer;
  border-radius:7px; transition:color .14s ease; }
.dp-btn:hover { color:var(--blue); }

.dp-cal { position:fixed; z-index:95; width:252px; padding:10px;
  border-radius:14px; background:var(--panel); border:1px solid var(--line);
  box-shadow:var(--shadow-lg);
  animation:menuIn .12s cubic-bezier(.2,.8,.3,1); }
.dp-head { display:flex; align-items:center; justify-content:space-between;
  margin-bottom:8px; }
.dp-title { font-size:12.5px; font-weight:700; letter-spacing:-.01em; }
.dp-nav { width:26px; height:26px; border:0; border-radius:7px; cursor:pointer;
  background:transparent; color:var(--muted); font-size:16px; line-height:1;
  transition:background .13s ease, color .13s ease; }
.dp-nav:hover { background:var(--panel-2); color:var(--text); }
.dp-dow, .dp-grid { display:grid; grid-template-columns:repeat(7, 1fr); gap:2px; }
.dp-dow span { text-align:center; font-size:9.5px; font-weight:800;
  letter-spacing:.06em; color:var(--subtle); padding:4px 0; }
.dp-day { height:30px; border:0; border-radius:8px; background:transparent;
  color:var(--muted); font-size:12px; cursor:pointer;
  font-variant-numeric:tabular-nums;
  transition:background .12s ease, color .12s ease; }
.dp-day:hover { background:var(--lift-3); color:var(--text); }
.dp-day.today { color:var(--blue); font-weight:750; }
.dp-day.on { background:var(--blue-solid); color:#fff; font-weight:750; }
.dp-pad { height:30px; }
.dp-foot { display:flex; gap:6px; margin-top:8px; padding-top:8px;
  border-top:1px solid var(--line); }
.dp-quick { flex:1; padding:6px; border-radius:8px; font-size:11px;
  font-weight:650; cursor:pointer; background:var(--panel-2);
  border:1px solid var(--line); color:var(--muted);
  transition:color .13s ease, border-color .13s ease; }
.dp-quick:hover { color:var(--text); border-color:var(--subtle); }

/* Payroll: the run bar, exclusions and history */
.pr-runbar { display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap;
  margin:0 0 16px; padding:12px 14px; border:1px solid var(--line);
  border-radius:12px; background:var(--panel-2); }
.pr-notewrap { flex:1; min-width:240px; display:flex; flex-direction:column;
  gap:5px; font-size:10px; font-weight:800; letter-spacing:.08em;
  text-transform:uppercase; color:var(--subtle); }
.pr-notewrap input { padding:8px 11px; border-radius:9px; background:var(--panel);
  border:1px solid var(--line); color:var(--text); font-size:12.5px;
  letter-spacing:normal; text-transform:none; font-weight:400; }
.pr-notewrap input:focus { outline:none; border-color:var(--blue);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 14%, transparent); }
.pr-status { margin-left:auto; font-size:11.5px; }
.pr-paid { color:var(--ink-good); font-weight:700; }
/* A removed line stays on the page struck through rather than vanishing: a
   client who is simply gone from a payslip is what starts an argument. */
.pr-struck { text-decoration:line-through; opacity:.5; }
.pr-x { padding:1px 8px; border-radius:20px; font-size:9.5px; font-weight:700;
  cursor:pointer; background:transparent; color:var(--subtle);
  border:1px solid var(--line); transition:color .13s ease, border-color .13s ease; }
.pr-x:hover { color:var(--ink-bad); border-color:rgba(226,86,75,.45); }

.pr-hist { padding:0; margin-bottom:10px; overflow:hidden; }
.pr-hist-head { display:flex; align-items:flex-start; justify-content:space-between;
  gap:14px; padding:14px 18px; border-bottom:1px solid var(--line);
  background:var(--panel-2); }
.pr-hist-head .helper { display:block; margin-top:2px; }
.pr-hist-note { margin-top:6px; font-size:12px; color:var(--muted);
  padding:6px 10px; border-radius:8px; background:color-mix(in srgb, var(--blue) 10%, transparent); }
.pr-hist-coach { border-bottom:1px solid var(--line); }
.pr-hist-coach:last-child { border-bottom:0; }
.pr-hist-coach-head { display:flex; justify-content:space-between;
  padding:10px 18px 4px; font-size:12.5px; }
.pr-hist-coach-head span { font-variant-numeric:tabular-nums; }
.pr-decide { display:flex; gap:6px; white-space:nowrap; }

/* Documents ----------------------------------------------------------------
   A document is a thing you will probably end up handing to someone, so it is
   laid out like a sheet of paper rather than like a record in a table. */
.doc-row, .doc-line { display:flex; align-items:center; gap:12px; padding:11px 12px;
  border-bottom:1px solid var(--line); text-decoration:none; color:inherit;
  border-radius:10px; transition:background .15s ease, transform .12s ease; }
.doc-row:hover, .doc-line:hover { background:var(--lift-2); }
.doc-row:active { transform:scale(.995); }
.doc-icon { width:28px; height:28px; flex:0 0 28px; border-radius:8px;
  display:grid; place-items:center; font-size:13px; color:var(--blue);
  background:color-mix(in srgb, var(--blue) 14%, transparent); }
.doc-icon.file { color:var(--ink-violet); background:rgba(139,92,246,.16); }
.doc-row-main, .doc-line-main { flex:1; min-width:0; display:flex;
  flex-direction:column; gap:2px; text-decoration:none; color:inherit; }
.doc-row-title, .doc-line-title { font-size:13px; font-weight:600;
  letter-spacing:-.01em; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; }
.doc-row-sub { font-size:11.5px; color:var(--subtle); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.doc-row-who { flex:0 0 auto; }
.doc-row-meta { flex:0 0 auto; font-size:11px; color:var(--muted);
  text-align:right; }
.doc-line { border-radius:9px; }

/* The sheet */
.doc-sheet { max-width:820px; margin:0 auto; background:var(--panel);
  border:1px solid var(--line); border-radius:var(--radius); padding:30px 34px; }
.doc-head { display:flex; align-items:flex-start; gap:16px; flex-wrap:wrap;
  padding-bottom:16px; margin-bottom:22px; border-bottom:1px solid var(--line); }
.doc-head-main { flex:1; min-width:220px; }
.doc-head h1 { font-size:23px; letter-spacing:-.02em; }
.doc-meta { font-size:11.5px; color:var(--subtle); margin-top:5px; }
.doc-meta a { color:var(--blue); text-decoration:none; }
.doc-unfiled { color:var(--ink-warn); }
.doc-body { font-size:14px; line-height:1.65; }
.doc-body h4 { font-size:14.5px; font-weight:700; margin:20px 0 8px; }
.doc-body h4:first-child { margin-top:0; }
.doc-body p { margin:0 0 11px; }
.doc-body ul, .doc-body ol { margin:0 0 12px; padding-left:22px; }
.doc-body li { margin-bottom:5px; }
.doc-body code { font-family:ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size:12.5px; padding:1px 5px; border-radius:5px;
  background:var(--lift-3); }
.doc-file { text-align:center; padding:34px 20px; border:1.5px dashed var(--line);
  border-radius:12px; display:flex; flex-direction:column; gap:14px;
  align-items:center; }
.doc-editor textarea { width:100%; font-family:ui-monospace, SFMono-Regular,
  Menlo, monospace; font-size:12.5px; line-height:1.6; }

/* Printing is the PDF. Everything that is not the document itself goes. */
@media print {
  body { background:#fff !important; color:#111 !important; }
  .sidebar, .topbar, .crumb, .crumbs, .doc-tools, .toast, .brain-overlay, .bside,
  #sdOverlay { display:none !important; }
  .app-shell { display:block !important; }
  main { padding:0 !important; margin:0 !important; background:#fff !important; }
  .doc-sheet { max-width:none; margin:0; padding:0; border:0; background:#fff !important; }
  .doc-head { border-bottom:1px solid #ddd; }
  .doc-head h1, .doc-body, .doc-body h4 { color:#111 !important; }
  .doc-meta, .doc-meta a { color:#555 !important; }
  .doc-body code { background:#f1f1f1 !important; color:#111 !important; }
  a { text-decoration:none; }
}

/* Saving something into a client's file */
.sd-panel { max-width:560px; }
.sd-body { padding:18px; }
.sd-label { display:block; font-size:10.5px; font-weight:800; letter-spacing:.07em;
  text-transform:uppercase; color:var(--subtle); margin:14px 0 5px; }
.sd-label:first-child { margin-top:0; }
.sd-label .helper { text-transform:none; letter-spacing:0; font-weight:500; }
.sd-body input { width:100%; }
.sd-pick { position:relative; }
.sd-results { position:absolute; left:0; right:0; top:calc(100% + 4px); z-index:40;
  max-height:236px; overflow-y:auto; padding:5px; border-radius:11px;
  background:var(--panel-2); border:1px solid var(--line);
  box-shadow:var(--shadow-lg); }
.sd-row { width:100%; display:flex; flex-direction:column; gap:1px; padding:7px 9px;
  border:0; background:transparent; color:inherit; cursor:pointer;
  border-radius:8px; text-align:left; }
.sd-row:hover { background:var(--lift-3); }
.sd-row-name { font-size:12.5px; font-weight:600; }
.sd-chosen { display:flex; align-items:center; gap:9px; padding:8px 10px;
  border-radius:10px; font-size:13px; background:color-mix(in srgb, var(--blue) 16%, transparent);
  border:1px solid color-mix(in srgb, var(--blue) 34%, transparent); }
.sd-chosen span { flex:1; }
.sd-preview { max-height:210px; overflow-y:auto; padding:12px 14px;
  border:1px solid var(--line); border-radius:11px; background:var(--panel-2);
  font-size:12.5px; line-height:1.55; color:var(--muted); }
.sd-preview h4 { font-size:12.5px; font-weight:700; margin:10px 0 5px;
  color:var(--text); }
.sd-preview h4:first-child { margin-top:0; }
.sd-preview p { margin:0 0 7px; }
.sd-preview ul, .sd-preview ol { margin:0 0 7px; padding-left:18px; }

/* What you can do with an answer once it exists */
/* Always visible, just quiet. Hiding these until hover meant nobody knew an
   answer could be copied rather than filed. */
.ai-actions { display:flex; gap:6px; margin-top:9px; opacity:.72;
  transition:opacity .15s ease; }
.ai-turn:hover .ai-actions, .ai-actions:focus-within { opacity:1; }
.ai-act { display:inline-flex; align-items:center; gap:5px; padding:4px 9px;
  font-size:11px; color:var(--muted); background:transparent; cursor:pointer;
  border:1px solid var(--line); border-radius:8px;
  transition:color .14s ease, border-color .14s ease, background .14s ease; }
.ai-act:hover { color:var(--text); border-color:color-mix(in srgb, var(--blue) 50%, transparent);
  background:color-mix(in srgb, var(--blue) 10%, transparent); }


/* Dropping a file onto a client. The target is the whole panel rather than a
   button, because dragging a contract out of Finder and letting go is the
   entire interaction -- there is nothing to click. */
.filedrop { display:flex; flex-direction:column; align-items:center; gap:6px;
  padding:22px 18px; text-align:center; color:var(--muted);
  border:1.5px dashed var(--line); border-radius:12px;
  transition:border-color .15s ease, background .15s ease, color .15s ease; }
.filedrop svg { color:var(--subtle); transition:color .15s ease; }
.filedrop p { font-size:12.5px; margin:0; }
.filedrop:hover { border-color:color-mix(in srgb, var(--blue) 45%, transparent); }
.filedrop.over { border-color:var(--blue); background:color-mix(in srgb, var(--blue) 10%, transparent);
  color:var(--text); }
.filedrop.over svg { color:var(--blue); }

/* Contract check: one card per person, because each is a small decision. */
.cc-card { border-left:3px solid var(--metric-color, var(--line));
  margin-bottom:10px; }
.cc-head { display:flex; align-items:flex-start; justify-content:space-between;
  gap:12px; }
.cc-who { display:flex; flex-direction:column; gap:2px; min-width:0; }
.cc-name { font-size:14.5px; font-weight:700; letter-spacing:-.01em;
  color:var(--text); text-decoration:none; }
.cc-name:hover { color:var(--blue); }
.cc-why { font-size:12.5px; color:var(--muted); margin-top:9px; }
.cc-known { font-size:12px; color:var(--muted); margin-top:6px;
  display:flex; gap:8px; align-items:baseline; }
.cc-docs { margin-top:10px; border-top:1px solid var(--line); padding-top:8px; }
.cc-doc { display:flex; justify-content:space-between; gap:12px; padding:4px 0;
  font-size:12px; flex-wrap:wrap; }
.cc-actions { margin-top:12px; }

/* Owner pay: typed per month, because it is a decision rather than a figure
   anything else in the system could know. */
.pnl-own { display:flex; align-items:center; gap:9px; flex-wrap:wrap;
  margin-top:12px; padding-top:11px; border-top:1px solid var(--line); }
.pnl-own label { font-size:10.5px; font-weight:800; letter-spacing:.07em;
  text-transform:uppercase; color:var(--subtle); }
.pnl-own input { width:130px; font-size:12.5px; padding:6px 9px; min-height:0;
  height:auto; font-variant-numeric:tabular-nums; }
.pnl-own .helper { flex:1 1 15rem; }

/* The expense grid, laid out like the tracker: months down, categories across.
   Every figure is an input because this is the screen a bank statement gets
   categorised on, and a dialog per cell would make that unbearable. */
.pnl-grid { font-size:12px; }
.pnl-grid th { white-space:nowrap; font-size:9.5px; vertical-align:bottom; }
.pnl-grid th:first-child, .pnl-grid td:first-child { position:sticky; left:0;
  background:var(--panel); z-index:2; }
.pnl-grid tfoot td { border-top:1px solid var(--line-strong); }
.pnl-cell { width:88px; text-align:right; font-size:12px; padding:4px 6px;
  min-height:0; height:auto; border-color:transparent; background:transparent;
  font-variant-numeric:tabular-nums;
  transition:border-color .12s ease, background .12s ease; }
.pnl-cell:hover { border-color:var(--line); background:var(--lift-2); }
.pnl-cell:focus { border-color:var(--blue); background:var(--panel-2);
  outline:none; }
.pnl-cell.saving { opacity:.5; }
.pnl-cell::placeholder { color:var(--subtle); }

/* The categoriser's memory, tucked behind a disclosure: needed occasionally,
   in the way the rest of the time. */
.bank-memory { margin-top:18px; border-top:1px solid var(--line); padding-top:12px; }
.bank-memory summary { cursor:pointer; font-family:inherit; font-size:12.5px;
  font-weight:600; color:var(--muted); list-style:none; display:flex;
  align-items:center; gap:7px; }
.bank-memory summary::-webkit-details-marker { display:none; }
.bank-memory summary::before { content:"▸"; color:var(--subtle);
  transition:transform .15s ease; display:inline-block; }
.bank-memory[open] summary::before { transform:rotate(90deg); }
.bank-memory summary:hover { color:var(--text); }
.bank-memory summary span { font-weight:400; color:var(--subtle); }

/* The P&L, restructured: the year, the months, the categories -- and the
   machinery of importing statements folded out of the way beneath them. */
.pnl-head { display:flex; align-items:flex-end; justify-content:space-between;
  gap:16px; flex-wrap:wrap; margin-bottom:18px; }
.pnl-year-title { font-size:19px; letter-spacing:-.02em; }
.pnl-head select { width:130px; }
.fin-machinery { margin-top:26px; border:1px solid var(--line);
  border-radius:var(--radius); background:var(--panel); }
.fin-machinery summary { cursor:pointer; padding:14px 18px; font-size:13.5px;
  font-weight:600; list-style:none; display:flex; align-items:center; gap:8px; }
.fin-machinery summary::-webkit-details-marker { display:none; }
.fin-machinery summary::before { content:"▸"; color:var(--subtle);
  transition:transform .15s ease; display:inline-block; }
.fin-machinery[open] summary::before { transform:rotate(90deg); }
.fin-machinery summary span { font-weight:400; color:var(--subtle);
  font-size:12px; }
.fin-machinery-body { padding:0 18px 18px; }

/* ===========================================================================
   Raised surfaces and semantic colour.
   Stefan's note: the hub reads flat and grey, and the parts he likes -- the AI
   answer bubbles, the conversation cards -- are the ones that sit up off the
   page. So: a real shadow, a lighter ground than the page behind it, and a
   lift on hover for anything you can click. Money is coloured by what it MEANS
   -- green good, red bad, amber unsure -- and never for decoration, so colour
   still carries information when it appears.
   =========================================================================== */
.raised {
  background: linear-gradient(160deg, var(--panel-2), var(--panel));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow:var(--shadow);
}
.raised-hover { transition: transform .16s ease, box-shadow .16s ease,
                            border-color .16s ease; }
.raised-hover:hover { transform: translateY(-2px);
  box-shadow:var(--shadow);
  border-color: var(--line-strong); }
@media (prefers-reduced-motion: reduce) {
  .raised-hover:hover { transform: none; }
}

/* Money, coloured by meaning */
.money-good { color: var(--green); }
.money-bad  { color: var(--red); }
.money-warn { color: var(--amber); }
.money-flat { color: var(--muted); }

/* The P&L's headline figures, as raised objects rather than boxes on a grid */
#pnlStats { display:grid; grid-template-columns:repeat(auto-fit,minmax(158px,1fr));
  gap:10px; margin-bottom:18px; }
#pnlStats .stat { border-radius:var(--radius); padding:14px 16px; min-width:0;
  background: linear-gradient(160deg, var(--panel-2), var(--panel));
  border:1px solid var(--line);
  box-shadow:var(--shadow);
  border-top:2px solid var(--tone, transparent);
  display:flex; flex-direction:column; gap:5px; }
#pnlStats .stat span { font-size:10px; font-weight:800; letter-spacing:.08em;
  text-transform:uppercase; color:var(--muted); }
#pnlStats .stat b { font-size:21px; font-weight:800; letter-spacing:-.03em;
  font-variant-numeric:tabular-nums; color:var(--tone, var(--text)); }
#pnlStats .stat.is-good { --tone: var(--green); }
#pnlStats .stat.is-bad  { --tone: var(--red); }
#pnlStats .stat.is-warn { --tone: var(--amber); }
#pnlStats .stat.is-plain { --tone: transparent; }
#pnlStats .stat.is-plain b { color: var(--text); }

/* Tables lifted off the page the same way */
/* A table is an object too, not a grid ruled onto the page. */
.table-wrap { border-radius:var(--radius); overflow-x:auto;
  background: linear-gradient(160deg, var(--panel-2), var(--panel));
  border:1px solid var(--line);
  box-shadow:var(--shadow); }
.table-wrap > table { margin:0; }
.table-wrap th { background:var(--lift-1); }
.card .table-wrap { box-shadow:none; border-color:var(--line);
  background:transparent; }
.pnl-row { cursor:pointer; transition:background .13s ease; }
.pnl-row:hover td { background:var(--lift-2); }
.pnl-row.partial td:first-child { box-shadow:inset 3px 0 0 var(--amber); }
tr.pnl-total td { background:var(--lift-2); border-top:1px solid var(--line-strong); }
.section-head h2 { letter-spacing:-.02em; }
.section-head { padding-bottom:2px; }

.pnl-chip { display:inline-block; margin:3px 6px 3px 0; padding:4px 10px;
  border-radius:20px; font-size:11px; background:var(--panel);
  border:1px solid var(--line); }

/* The categoriser asking for help. Sits with the headline figures, because a
   question buried in the statement it came from is a question nobody answers. */
.ask-card { padding:16px 18px; margin-bottom:18px;
  border-left:3px solid var(--amber); display:flex; flex-direction:column; gap:12px; }
.ask-head b { font-size:13.5px; }
.ask-head .helper { display:block; margin-top:3px; }
.ask-list { display:flex; flex-direction:column; gap:2px; }
/* One question. The description used to be a single truncated line, which is
   exactly wrong here -- a Chase ACH descriptor carries the only identifying
   detail at its END, so an ellipsis hides the part that answers the question.
   The tidy name is the heading, the raw text sits under it in full, and both
   wrap. */
.ask-row { display:flex; align-items:flex-start; gap:14px; padding:11px 0;
  border-top:1px solid var(--line); flex-wrap:wrap; }
.ask-row:first-child { border-top:0; }
.ask-text { flex:1 1 20rem; min-width:0; }
.ask-what { font-size:13px; font-weight:600; line-height:1.4; word-break:break-word; }
.ask-raw { margin:3px 0 0; font-size:10.5px; line-height:1.5; color:var(--subtle);
  font-family:ui-monospace, monospace; word-break:break-all; }
.ask-meta { font-size:11px; color:var(--muted); margin-top:5px; line-height:1.5; }
.ask-row select { flex:0 0 auto; max-width:210px; margin-top:2px; }
.ask-row .ask-yes { margin-top:2px; }

/* ---------- check-ins ----------
   The panel reuses the conversation drawer's shape deliberately: reading a
   client's check-in and reading their thread are the same motion, and a second
   drawer that behaved differently would be a second thing to learn. */
.ci-panel { position: fixed; top: 0; right: 0; width: min(460px, 100%); height: 100vh;
  z-index: 30; display: flex; flex-direction: column;
  background: linear-gradient(160deg, var(--panel), var(--panel-2));
  border-left: 1px solid var(--line); box-shadow:var(--shadow-lg); }
/* .convo-panel caps its body at 360px because inline threads sit inside a
   card. This one is a full-height drawer, so the cap has to go or a nine
   question check-in is cut off at question four. */
.ci-panel .msg-panel-body { max-height: none; flex: 1 1 auto; min-height: 0;
  display: block; background: transparent; }
.ci-panel .msg-box { flex: none; border-top: 1px solid var(--line); }
/* The run table. A row is a thing you open, so it has to look like one --
   the whole row lifts on hover, not just the link in it. */
/* The outbox, one block per coach. Sending is done by a coach with their own
   clients open, so the queue is grouped the way the work is done. */
.ci-outg { margin-bottom:18px; }
.ci-outg-head { display:flex; align-items:center; justify-content:space-between;
  gap:12px; margin-bottom:8px; flex-wrap:wrap; }
.ci-outg-head h3 { margin:0; font-size:13px; font-weight:800; }
.ci-outg-head h3 .helper { font-weight:600; margin-left:6px; }
/* A flag a person raised, not one the system worked out. Deliberately quieter
   than badge-warn: it is a note to somebody, not an alarm. */
.badge-note { background:var(--tint-violet, rgba(139,92,246,.16)); color:var(--ink-violet); }

/* The @ picker. Sits above the composer because the composer is usually at the
   bottom of a panel, where a list hanging below would fall off the screen. */
/* Month to month: a standing arrangement, not an alarm. Quieter than the
   overdue chip on purpose -- it is information, and it sits next to one that
   genuinely is a warning. */
.chip-monthly { display:inline-block; margin-left:6px; font-size:9.5px;
  font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  padding:2px 7px; border-radius:20px; vertical-align:middle;
  background:var(--tint-violet); color:var(--ink-violet); }

/* A name in a note is a person, so it looks like one you can click. */
.mention { color:var(--blue); font-weight:600; cursor:default;
  border-radius:4px; padding:0 2px; }
.mention:hover { background:var(--tint-blue); }
/* Inside your own bubble the ground is already blue, so a blue mention
   disappears entirely — the name read as a gap in the sentence. */
.msg-turn.mine .msg-bubble .mention,
.hpop-turn.mine .hpop-bubble .mention { color:#fff; text-decoration:underline;
  text-decoration-color:rgba(255,255,255,.5); text-underline-offset:2px; }
.msg-turn.mine .msg-bubble .mention:hover,
.hpop-turn.mine .hpop-bubble .mention:hover { background:rgba(255,255,255,.18); }
.mention-mirror { z-index:-1; }
.inbox-back { display:inline-block; margin-bottom:12px; font-size:12.5px;
  font-weight:600; color:var(--blue); text-decoration:none; }
.inbox-back:hover { text-decoration:underline; }

.mention-card { position:absolute; z-index:90; width:250px; background:var(--panel);
  border:1px solid var(--line); border-radius:12px; padding:13px 15px;
  box-shadow:var(--shadow-lg); }
.mention-card .mc-top { display:flex; align-items:center; gap:9px; margin-bottom:9px; }
.mention-card .mc-av { width:28px; height:28px; border-radius:50%; flex:0 0 auto;
  background:var(--blue-solid); color:#fff; font-weight:700; font-size:13px;
  display:flex; align-items:center; justify-content:center; }
.mention-card .mc-name { font-size:14px; font-weight:700; }
.mention-card .mc-row { font-size:12px; color:var(--muted); margin-bottom:3px; }
.mention-card .mc-acts { display:flex; gap:7px; margin-top:11px; }
.mention-card .mc-btn { flex:1; text-align:center; font-size:12px; font-weight:600;
  padding:6px 8px; border-radius:8px; border:1px solid var(--line);
  color:var(--text); text-decoration:none; }
.mention-card .mc-btn:hover { background:var(--lift-2); border-color:var(--blue); }
.mention-card button.mc-btn { font-family:inherit; cursor:pointer;
  background:var(--panel); color:var(--text); }
.mention-card .mc-send { margin-top:10px; }
.mention-card .mc-send textarea { width:100%; resize:vertical; font:inherit;
  font-size:12.5px; color:var(--text); background:var(--field);
  border:1px solid var(--line); border-radius:8px; padding:7px 9px; }
.mention-card .mc-send textarea:focus { border-color:var(--blue); outline:none; }
.mention-card .mc-send-foot { display:flex; align-items:center;
  justify-content:space-between; gap:8px; margin-top:7px; }
.mention-card .mc-said { font-size:11px; color:var(--muted); }
/* button.mc-go, not .mc-go: the rule above is (0,2,1) because of the element
   selector, so a plain two-class rule loses to it and the Send button drew
   white text on a white box — readable only on hover, where the extra
   pseudo-class finally won. Matched specificity, and later in the file. */
.mention-card button.mc-go { flex:0 0 auto; background:var(--blue-solid); color:#fff;
  border-color:var(--blue-solid); }
.mention-card button.mc-go:hover { filter:brightness(1.08);
  background:var(--blue-solid); color:#fff; }
.mention-card button.mc-go:disabled { opacity:.6; cursor:default; }

.mention-pop { position:absolute; z-index:80; background:var(--panel);
  border:1px solid var(--line); border-radius:10px; padding:4px;
  box-shadow:var(--shadow-lg); max-height:232px; overflow-y:auto; }
.mention-pop button { display:flex; flex-direction:column; align-items:flex-start;
  gap:1px; width:100%; text-align:left; background:none; border:0; cursor:pointer;
  padding:7px 10px; border-radius:7px; color:var(--text); font:inherit; }
.mention-pop button:hover, .mention-pop button.on { background:var(--lift-2); }
.mention-pop button.on { outline:1px solid var(--blue); outline-offset:-1px; }
.mention-pop .mn-head { font-size:9.5px; font-weight:800; letter-spacing:.08em;
  text-transform:uppercase; color:var(--subtle); padding:7px 10px 3px; }
.mention-pop .mn-name { font-size:13px; font-weight:600; }
.mention-pop .mn-mail { font-size:11px; color:var(--muted); }

.ci-tier { display:inline-block; font-size:10px; font-weight:800; letter-spacing:.05em;
  text-transform:uppercase; padding:2px 8px; border-radius:20px;
  background:var(--tint-blue); color:var(--ink-info); }
.ci-drift { color:var(--ink-warn); font-weight:700; }
.ci-filters { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.ci-filters input[type="search"] { width:min(260px, 46vw); }
.ci-filters select { width:auto; min-width:130px; }
.ci-row { cursor:pointer; }
.ci-row td { vertical-align:top; }
.ci-row .helper { font-size:11px; line-height:1.4; margin-top:2px; }
.ci-status { display:inline-block; font-size:10px; font-weight:800; letter-spacing:.06em;
  text-transform:uppercase; color:var(--st); }
.ci-late { color:var(--ink-bad); font-weight:700; }

.ci-answer { padding: 14px 0; border-bottom: 1px solid var(--line); }
.ci-answer:last-child { border-bottom: 0; }
.ci-q { color: var(--muted); font-size: 12px; letter-spacing: .04em;
  text-transform: uppercase; margin-bottom: 5px; }
.ci-a { line-height: 1.6; white-space: pre-wrap; }
.ci-reply { background: rgba(53,201,143,.07); border-radius: 10px; padding: 12px 13px;
  border: 1px solid rgba(53,201,143,.22); margin-top: 12px; }
.ci-link { display: block; margin-top: 8px; padding: 10px 12px; border-radius: 9px;
  background: var(--field); border: 1px solid var(--line); color: var(--muted);
  font-size: 12px; word-break: break-all; }

/* The question rows in the form builder. Arrows rather than drag: reordering
   nine questions on a phone with drag-and-drop is a fight, and the arrows are
   also the only version a keyboard can use. */
.ci-qrow { display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--line); }
.ci-qrow:last-child { border-bottom: 0; }
.ci-qmove { display: flex; flex-direction: column; gap: 2px; }
.ci-qlabel { flex: 1; min-width: 140px; }
.ci-arrow { width: 26px; height: 20px; border-radius: 6px; border: 1px solid var(--line);
  background: transparent; color: var(--muted); font-size: 11px; line-height: 1;
  display: grid; place-items: center; transition: color .12s ease, background .12s ease; }
.ci-arrow:hover:not([disabled]) { color: var(--text); background: var(--lift-2); }
.ci-arrow[disabled] { opacity: .3; cursor: default; }

/* On the client record: the check-in history, densest form that still reads. */
.ci-hist { display: flex; flex-direction: column; gap: 8px; }
.ci-item { border: 1px solid var(--line); border-radius: 11px; overflow: hidden;
  background: var(--lift-1); }
.ci-head { display: flex; align-items: center; gap: 10px; padding: 11px 13px;
  cursor: pointer; transition: background .12s ease; }
.ci-head:hover { background: var(--lift-2); }
.ci-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.ci-when { font-weight: 600; }
.ci-tag { margin-left: auto; font-size: 11.5px; color: var(--muted); }
.ci-body { padding: 4px 13px 14px; border-top: 1px solid var(--line); }
@media (max-width: 640px) {
  .ci-qrow { flex-wrap: wrap; }
  .ci-panel { width: 100%; }
}

/* The outbox message column. Wraps rather than truncating: the whole point is
   that somebody reads what is about to go to a client before it goes. */
/* pre-wrap, not normal: these messages have real line breaks in them and
   the person pasting one into Trainerize needs to see where they fall. */
.ci-msg { max-width: 520px; line-height: 1.5; color: var(--muted);
  font-size: 12.5px; white-space: pre-wrap; }
.ci-vh { margin: 0 0 10px; font-size: 12px; letter-spacing: .05em;
  text-transform: uppercase; color: var(--subtle); }
.ci-checks { display: flex; flex-direction: column; gap: 8px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--lift-1); }
.ci-checks .pr-check { font-size: 12.5px; }

/* ---------- theme switch and drawn icons ---------- */

/* Three states, one button: light, dark, follow the system. Only the glyph for
   the current state is shown, so the button says what you are on rather than
   what you would get. */
.theme-toggle .th-sun, .theme-toggle .th-moon, .theme-toggle .th-auto { display: none; }
:root .theme-toggle .th-moon { display: block; }
:root[data-theme="light"] .theme-toggle .th-moon { display: none; }
:root[data-theme="light"] .theme-toggle .th-sun { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme-toggle .th-moon { display: none; }
  :root:not([data-theme="dark"]) .theme-toggle .th-sun { display: block; }
}

/* Appearance: light or dark, and the accent -- the ClickUp Themes card,
   opened from the sun/moon in the top bar or from the account menu. */
.appear-pop { position:fixed; z-index:120; width:340px; padding:14px; border-radius:14px;
  background:var(--panel); border:1px solid var(--line); box-shadow:var(--shadow-lg);
  animation:menuIn .12s cubic-bezier(.2,.8,.3,1); }
.appear-pop h4 { margin:0 0 10px; font-size:13px; letter-spacing:-.01em; }
.appear-pop h5 { margin:12px 0 8px; font-size:10px; font-weight:800; letter-spacing:.09em; text-transform:uppercase; color:var(--subtle); }
.appear-modes { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.appear-mode { border:2px solid var(--line); border-radius:12px; padding:8px; background:transparent; cursor:pointer;
  display:flex; flex-direction:column; gap:7px; color:var(--text); font:inherit; font-size:12px; font-weight:650; text-align:left; }
.appear-mode:hover { border-color:var(--line-strong); }
.appear-mode.on { border-color:var(--blue); box-shadow:0 0 0 3px var(--tint-blue); }
/* A tiny page: rail, bar, two lines. Drawn in the mode's own colours so the
   tile shows what you would get. */
.appear-thumb { height:52px; border-radius:8px; border:1px solid rgba(0,0,0,.12); position:relative; overflow:hidden; }
.appear-thumb::before { content:""; position:absolute; left:0; top:0; bottom:0; width:22%; }
.appear-thumb i { position:absolute; left:30%; height:5px; border-radius:3px; }
.appear-thumb i:nth-child(1) { top:12px; width:50%; }
.appear-thumb i:nth-child(2) { top:24px; width:34%; }
.appear-thumb i:nth-child(3) { top:36px; width:42%; }
.appear-thumb.light { background:#f7f6f3; } .appear-thumb.light::before { background:#e9e7e2; } .appear-thumb.light i { background:#cfcdc7; }
.appear-thumb.dark { background:#131820; border-color:rgba(255,255,255,.1); } .appear-thumb.dark::before { background:#1a212b; } .appear-thumb.dark i { background:#39424f; }
.appear-thumb i.acc { background:var(--blue-solid) !important; width:16px !important; left:auto; right:10px; top:12px; height:8px; }
.appear-colors { display:grid; grid-template-columns:repeat(3,1fr); gap:6px; }
.appear-color { display:flex; align-items:center; gap:8px; padding:7px 9px; border:1.5px solid var(--line); border-radius:9px;
  background:transparent; color:var(--text); font:inherit; font-size:12px; font-weight:600; cursor:pointer; text-align:left; }
.appear-color:hover { border-color:var(--line-strong); background:var(--lift-1); }
.appear-color.on { border-color:var(--blue); background:var(--tint-blue); }
.appear-color b { width:14px; height:14px; border-radius:4px; flex:0 0 auto; background:var(--sw); box-shadow:inset 0 0 0 1px rgba(0,0,0,.08); }
.appear-color.on b::after { content:"✓"; display:block; color:#fff; font-size:10px; line-height:14px; text-align:center; font-weight:800; }
.appear-pop .helper { margin:10px 0 0; font-size:11px; }
@media (max-width:700px) { .appear-pop { width:min(340px, calc(100vw - 16px)); } }

/* Line icons in the rail. Sized in ems so they track the label, and coloured by
   inheritance so hover and active states need no icon-specific rules. */
.nav-glyph { width: 17px; height: 17px; display: block; color: inherit; }
.nav-icon-btn { display: grid; place-items: center; }
.nav-icon-btn.custom { font-size: 15px; line-height: 1; }

/* Light mode is a different material, not an inversion, so a few things that
   read well on black need easing back on paper. */
:root[data-theme="light"] .brand-mark,
:root:not([data-theme="dark"]) .brand-mark { box-shadow: 0 4px 12px color-mix(in srgb, var(--blue) 22%, transparent); }
:root[data-theme="light"] .nav-item.active,
:root:not([data-theme="dark"]) .nav-item.active {
  color: var(--text); background: var(--lift-3);
  box-shadow: inset 2px 0 0 var(--blue);
}
:root[data-theme="light"] .sidebar,
:root:not([data-theme="dark"]) .sidebar { background: var(--sidebar); }

/* ---------- calendar ---------- */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 8px; margin-top: 14px; }
.cal-day { border: 1px solid var(--line); border-radius: 11px; overflow: hidden;
  background: var(--lift-1); min-height: 150px; display: flex; flex-direction: column; }
.cal-day.is-today { border-color: var(--blue); background: var(--tint-blue); }
.cal-dayhead { display: flex; align-items: baseline; gap: 6px; padding: 9px 11px;
  border-bottom: 1px solid var(--line); }
.cal-dow { color: var(--subtle); font-size: 10px; font-weight: 800;
  letter-spacing: .09em; text-transform: uppercase; }
.cal-num { margin-left: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.cal-events { padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.cal-event { border-radius: 8px; padding: 7px 8px; background: var(--panel-2);
  border: 1px solid var(--line); display: flex; flex-direction: column; gap: 2px; }
.cal-event.is-off { opacity: .72; }
.cal-event.is-off .cal-who, .cal-event.is-off .cal-time { text-decoration: line-through; }
/* What happened, in colour: closed is green, a no close is red, a cancelled
   or no-show is crossed out, and only a call still ahead stays blue. */
.cal-event.is-won { border-color: color-mix(in srgb, var(--green, #35c98f) 55%, var(--line));
  background: var(--tint-green); box-shadow: inset 3px 0 0 var(--green, #35c98f); }
.cal-event.is-won .cal-time { color: var(--ink-good); }
.cal-event.is-lost { border-color: color-mix(in srgb, var(--red) 55%, var(--line));
  background: var(--tint-red); box-shadow: inset 3px 0 0 var(--red); }
.cal-event.is-lost .cal-time { color: var(--red); }
.cal-event.is-off .cal-time { color: var(--subtle); }
.cal-time { color: var(--blue); font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.cal-who { font-size: 12.5px; line-height: 1.35; }
.cal-closer { color: var(--subtle); font-size: 10.5px; }
.cal-empty { color: var(--subtle); text-align: center; margin: 10px 0; }
/* Your own Google events, around the bookings: a thin line each, in the
   calendar's own colour, quieter than a call so the calls still read first. */
.cal-gev { display: grid; grid-template-columns: 8px minmax(0,1fr); grid-template-rows: auto auto; column-gap: 6px; row-gap: 1px;
  align-items: center; padding: 4px 7px; border-radius: 7px; border: 1px dashed var(--line); background: transparent;
  color: var(--muted); font-size: 11.5px; line-height: 1.3; text-decoration: none; }
.cal-gev:hover { background: var(--lift-2); color: var(--text); border-style: solid; }
.cal-gev.is-past { opacity: .6; }
.cal-gdot { width: 8px; height: 8px; border-radius: 50%; grid-row: 1 / span 2; }
.cal-gwho { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-weight: 550; }
.cal-gtime { font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--subtle); white-space: nowrap; }
.cal-gmeet { font-size: 8px; color: var(--blue); vertical-align: middle; }
.cal-gnote { color: var(--muted); }
/* The Account page's list of calendars. */
.gcal-list { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.gcal-cal { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.gcal-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
@media (max-width: 900px) {
  .cal-grid { grid-template-columns: 1fr; }
  .cal-day { min-height: 0; }
}

/* ---------- sub-navigation ----------
   Sits under the top bar, above the page. Quiet by design: the rail is the
   navigation, this only says which view of one job you are looking at. */
/* Drawn as a segmented control rather than a hairline of small text: the
   first version was so quiet that Payroll, one of its two tabs, went
   unfound for weeks. The current segment is filled the way the page tabs
   below it are, so the two rows read as the same kind of thing. */
.subnav { display: inline-flex; gap: 3px; margin: 14px 0 -4px; flex-wrap: wrap;
  padding: 4px; border: 1px solid var(--line); border-radius: 12px;
  background: var(--lift-1); }
.subnav-tab { padding: 7px 14px; color: var(--muted); font-size: 13px; font-weight: 600;
  border-radius: 9px; text-decoration: none;
  transition: color .14s ease, background .14s ease; white-space: nowrap; }
.subnav-tab:hover { color: var(--text); background: var(--lift-2); }
.subnav-tab.on { color: #fff; background: var(--blue-solid); }
.subnav-tab.on:hover { color: #fff; background: var(--blue-solid); }
@media (max-width: 700px) {
  .subnav { display: flex; overflow-x: auto; flex-wrap: nowrap; }
}

/* Setup instructions inside a settings card. Numbered because they are a real
   sequence -- step four fails if step two was skipped. */
.setup-steps { margin: 12px 0 0; padding-left: 20px; color: var(--muted);
  font-size: 12.5px; line-height: 1.85; }
.setup-steps b { color: var(--text); font-weight: 600; }
.setup-uri { display: block; margin-top: 5px; padding: 7px 9px; border-radius: 7px;
  background: var(--field); border: 1px solid var(--line); color: var(--text);
  font-size: 11.5px; word-break: break-all; user-select: all; }
.button.is-off { opacity: .5; pointer-events: none; }

/* A button that reads as a link — used where the sentence is the instruction
   and a boxed button would interrupt it. */
.linky { background: none; border: 0; padding: 0; color: var(--blue);
  font: inherit; cursor: pointer; text-decoration: underline;
  text-underline-offset: 2px; }
.linky:hover { color: var(--text); }
.filedrop.over { border-color: var(--blue); background: var(--tint-blue); }
.filedrop.over svg { color: var(--blue); }

/* The statement grid. Chase descriptions are long enough to squeeze the
   category dropdown to three letters, which is exactly what happened -- the
   column that has to be usable was the one giving up its width. */
#bankLines th:nth-child(2), #bankLines td:nth-child(2) {
  max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#bankLines th:nth-child(4), #bankLines td:nth-child(4) { min-width: 200px; }
#bankLines td:nth-child(4) .pr-mini { max-width: none; }
#bankLines th:nth-child(5), #bankLines td:nth-child(5) { min-width: 200px; }
.bank-desc { cursor: help; }

/* "Looks right" — accepting the categoriser's guess. Quiet until you hover,
   because agreeing is the common case and a row of loud buttons reads as a
   list of problems. */
.ask-yes { padding: 5px 11px; border-radius: 8px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  white-space: nowrap; transition: background .14s ease, color .14s ease,
  border-color .14s ease; }
.ask-yes:hover:not([disabled]) { background: var(--tint-green); color: var(--green);
  border-color: color-mix(in srgb, var(--green) 40%, transparent); }
.ask-yes[disabled] { opacity: .4; cursor: default; }
.ask-foot { margin: 10px 2px 0; }

/* The dates behind a grouped question. Folded away because the answer usually
   does not need them -- but Stefan searches his bank by date, so when he does
   need them he needs every one, not a range, and the raw description too. */
.ask-dates { grid-column: 1 / -1; margin-top: 2px; }
.ask-dates summary { font-size: 11.5px; color: var(--subtle); cursor: pointer;
  list-style: none; display: inline-flex; align-items: center; gap: 4px; }
.ask-dates summary::-webkit-details-marker { display: none; }
.ask-dates summary::before { content: "▸"; font-size: 9px; transition: transform .15s ease; }
.ask-dates[open] summary::before { transform: rotate(90deg); }
.ask-dates summary:hover { color: var(--text); }
.ask-when { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 8px 0 0;
  font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.ask-when b { color: var(--text); font-weight: 600; }

.mr-when { display: flex; align-items: center; gap: 7px; color: var(--muted);
  font-size: 12px; }
.recur { border: 1px solid var(--line); border-radius: 11px; padding: 12px 14px;
  background: var(--lift-1); }
.recur summary { cursor: pointer; font-size: 13px; }
.recur summary .helper { margin-left: 6px; }
.recur-body { margin-top: 4px; }

/* Files waiting to be uploaded. Deliberately looks like a list of things you
   still have to do something to, not like a list of things that happened. */
#bankQueue { margin: 12px 0; padding: 12px 13px; border-radius: 12px;
  border: 1px dashed var(--line-strong); background: var(--lift-1); }
.queue-head { display:flex; align-items:baseline; gap:10px; margin-bottom:9px;
  font-size:11.5px; font-weight:700; color:var(--text); }
.queue-head .linky { margin-left:auto; font-weight:600; }
.queue-row { display:flex; align-items:center; gap:9px; flex-wrap:wrap;
  padding:9px 10px; border-radius:10px; background:var(--panel);
  border:1px solid var(--line); }
.queue-row + .queue-row { margin-top:7px; }
.queue-row.done { opacity:.55; }
.queue-file { display:flex; flex-direction:column; gap:1px; min-width:160px;
  max-width:230px; }
.queue-file strong { font-size:12px; font-weight:650; color:var(--text);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.queue-row input, .queue-row select { height:32px; font-size:12px; }
.queue-row .q-drop { margin-left:auto; }

/* The MRR tables fold. Native <details>, so it works with no JS and keeps
   keyboard and find-in-page behaviour; only the remembered state is scripted.
   The default triangle is replaced because it sits on the text baseline of an
   <h2> and looks like a bullet rather than a control. */
.mr-fold > summary { cursor: pointer; list-style: none; display: flex;
  align-items: baseline; gap: 9px; }
.mr-fold > summary::-webkit-details-marker { display: none; }
.mr-fold > summary::before { content: ""; flex: 0 0 auto; width: 0; height: 0;
  border-left: 5px solid currentColor; border-top: 4px solid transparent;
  border-bottom: 4px solid transparent; color: var(--subtle);
  transition: transform .16s ease; transform-origin: 25% 50%; }
.mr-fold[open] > summary::before { transform: rotate(90deg); }
.mr-fold > summary:hover::before { color: var(--text); }
.mr-fold > summary h2 { margin: 0; }
/* The figures ride to the right of the heading, so a shut fold reads as a row
   of numbers rather than a closed door. Same shape as the stat cards above. */
.mr-fold > summary .fold-kpis { display: flex; flex-wrap: wrap; gap: 4px 16px;
  margin-left: auto; font-size: 11px; color: var(--subtle); }
.mr-fold > summary .fold-kpi b { color: var(--text); font-weight: 700;
  font-variant-numeric: tabular-nums; margin-right: 3px; }
.mr-fold > summary:focus-visible { outline: 2px solid var(--blue);
  outline-offset: 3px; border-radius: 6px; }
/* A shut fold is just its heading, so the card should not keep the padding it
   needs when open. */
.mr-fold:not([open]) { padding-top: 12px; padding-bottom: 12px; }
.pill.ok { background: var(--tint-green); color: var(--green); }

/* ---------- tasks ----------
   One column per list, side by side and scrolling sideways, because that is the
   shape Stefan already reads every day in Google Tasks. Circle ticks, a star on
   the right, and an overdue date that earns colour by being late. */
.tk-board { display: flex; gap: 14px; overflow-x: auto; padding: 4px 2px 20px;
  align-items: flex-start; margin-top: 20px; scrollbar-width: thin; }
.tkc { flex: 0 0 296px; border: 1px solid var(--line); border-radius: 14px;
  background: var(--panel); padding: 14px 12px 10px;
  box-shadow: var(--shadow-sm); }
.tkc-head { display: flex; align-items: center; gap: 6px; padding: 0 4px 4px; }
.tkc-head h2 { margin: 0; font-size: 14.5px; letter-spacing: -.01em; flex: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tkc-menu { border: 0; background: none; color: var(--subtle); font-size: 11px;
  padding: 3px 6px; border-radius: 6px; cursor: pointer; opacity: 0;
  transition: opacity .14s ease, color .14s ease, background .14s ease; }
.tkc:hover .tkc-menu { opacity: 1; }
.tkc-menu:hover { background: var(--lift-2); color: var(--text); }
.tkc-menu.danger:hover { color: var(--red); background: var(--tint-red); }

.tkc-add { display: flex; align-items: center; gap: 8px; width: 100%;
  border: 0; background: none; color: var(--blue); font: inherit; font-size: 12.5px;
  font-weight: 600; padding: 7px 6px; border-radius: 8px; cursor: pointer;
  transition: background .14s ease; }
.tkc-add:hover { background: var(--tint-blue); }
.tkc-plus { font-size: 15px; line-height: 1; }
.tkc-input { padding: 4px 2px 6px; }
/* The box you type a new task into wraps and grows with it, the way Google
   Tasks does -- never a single line that scrolls the start of the sentence
   off to the left. Stefan, 09-19-2026. */
.tkc-input textarea { font-size: 13px; min-height: 36px; padding: 8px 9px;
  line-height: 1.42; resize: none; overflow: hidden; }
.tkc-body { display: flex; flex-direction: column; gap: 2px; min-height: 30px;
  border-radius: 9px; transition: background .14s ease; }
.tkc-body.over { background: var(--tint-blue); }
.tkc-empty { color: var(--subtle); font-size: 12px; padding: 8px 6px; margin: 0; }
.tkc-done { margin-top: 6px; border-top: 1px solid var(--line); padding-top: 6px; }
.tkc-done summary { color: var(--muted); font-size: 12px; cursor: pointer;
  padding: 4px 6px; border-radius: 7px; }
.tkc-done summary:hover { background: var(--lift-2); }
.tkc-new { flex: 0 0 220px; display: flex; gap: 6px; align-items: center;
  background: transparent; border-style: dashed; }
/* The two fixed columns. Assigned is the one that matters -- it is what the
   red count on the sidebar is about -- so it carries the house colour; Given
   is a receipt and stays quiet. Neither takes a drop: they are views. */
.tkc-assigned { --card-color: var(--blue); border-color: color-mix(in srgb, var(--blue) 45%, var(--line)); }
.tkc-assigned .tkc-head h2 { color: var(--blue); }
.tkc-given { background: transparent; border-style: dashed; box-shadow: none; }
.tkc-given .tkc-head h2 { color: var(--muted); }
.tkc-count { flex: 0 0 auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
  background: var(--blue-solid); color: #fff; font-size: 11px; font-weight: 800; line-height: 20px;
  text-align: center; font-variant-numeric: tabular-nums; }
.tkc-given .tkc-count { background: var(--lift-3); color: var(--muted); }
.tkc.is-fixed .tkt { cursor: default; }
.tkc.is-fixed .tkt-grip { visibility: hidden; }
/* Handed to you and not yet looked at: a dot where the grip would be. */
.tkt.is-new .tkt-grip { visibility: visible; opacity: 1; }
.tkt.is-new .tkt-grip::before { content: ""; display: block; width: 7px; height: 7px; margin: 3px 0 0 1px;
  border-radius: 50%; background: var(--red); }
.tkt-client { font-size: 10.5px; padding: 2px 7px; border-radius: 20px; background: var(--tint-green, rgba(53,201,143,.12)); color: var(--ink-good, #35c98f); }
.tkt-list { font-size: 10.5px; padding: 2px 7px; border-radius: 20px; background: var(--lift-3); color: var(--muted); }
/* The Starred view: one column, the star's colour. */
.tkc-starred { --card-color: var(--amber); border-color: color-mix(in srgb, var(--amber) 50%, var(--line)); flex-basis: 360px; }
.tkc-starred .tkc-head h2 { color: var(--amber); }
.tkc-starred .tkc-count { background: var(--amber); color: #1a1408; }

/* One task */
.tkt { display: flex; gap: 7px; align-items: flex-start; padding: 8px 6px 8px 4px;
  border-radius: 9px; cursor: grab; transition: background .14s ease; }
/* The six dots, the same handle as the sidebar's: there on hover, the whole
   card still drags. */
.tkt-grip { flex: 0 0 10px; margin-top: 3px; color: var(--subtle); fill: currentColor; opacity: 0; transition: opacity .12s ease; }
.tkt:hover .tkt-grip, .tkt.is-dragging .tkt-grip { opacity: .7; }
.tkt:active { cursor: grabbing; }
.tk-grow { resize: none; overflow: hidden; line-height: 1.4; min-height: 38px; }
#tkdText { font-size: 14px; font-weight: 650; }
.tkt:hover { background: var(--lift-2); }
.tkt.is-open { background: var(--tint-blue); }
.tkt.is-dragging { opacity: .4; }
.tkt.is-done .tkt-text { text-decoration: line-through; color: var(--muted); }
.tkt.is-done { opacity: .6; }
/* A circle, not a checkbox. Google Tasks uses one and it is the single detail
   that makes a list read as a list rather than as a form. */
.tkt-tick { flex: 0 0 17px; width: 17px; height: 17px; margin-top: 2px;
  border: 1.6px solid var(--line-strong); border-radius: 50%; background: none;
  cursor: pointer; position: relative; transition: border-color .14s ease,
  background .14s ease; }
.tkt-tick:hover { border-color: var(--blue); }
.tkt-tick.on { background: var(--blue-solid); border-color: var(--blue-solid); }
.tkt-tick.on::after { content: ""; position: absolute; left: 4.5px; top: 1.5px;
  width: 4px; height: 8px; border: solid #fff; border-width: 0 1.8px 1.8px 0;
  transform: rotate(42deg); }
.tkt-body { flex: 1; min-width: 0; }
.tkt-text { font-size: 13px; line-height: 1.42; word-break: break-word; }
.tkt-note { color: var(--muted); font-size: 11.5px; line-height: 1.45; margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
.tkt-link { display: block; color: var(--blue); font-size: 11px; margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tkt-meta { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
.tkt-due, .tkt-subs, .tkt-who { font-size: 10.5px; padding: 2px 7px;
  border-radius: 20px; background: var(--lift-3); color: var(--muted); }
.tkt-due.late { background: var(--tint-red); color: var(--red); font-weight: 600; }
.tkt-subs { background: var(--tint-blue); color: var(--blue); }
.tkt-who { background: var(--tint-violet); color: var(--violet); }
.tkt-star { flex: 0 0 22px; border: 0; background: none; color: var(--line-strong);
  cursor: pointer; padding: 2px; border-radius: 6px; margin-top: 1px;
  transition: color .14s ease; }
.tkt:hover .tkt-star { color: var(--subtle); }
.tkt-star.on, .tkt-star.on:hover { color: var(--amber); }
.tkt-star:hover { color: var(--amber); }

/* The detail, to the right, over the board */
.tk-detail { position: fixed; top: 0; right: 0; width: min(380px, 100%);
  height: 100vh; z-index: 30; display: flex; flex-direction: column;
  background: linear-gradient(160deg, var(--panel), var(--panel-2));
  border-left: 1px solid var(--line); box-shadow: -30px 0 80px var(--sink-1); }
.tk-detail-body { padding: 14px; overflow-y: auto; display: flex;
  flex-direction: column; gap: 6px; }
.tk-detail-body label { display: block; margin-top: 6px; }
.tk-fields { grid-template-columns: 1fr 1fr; }
.tk-detail-foot { padding: 12px 14px; border-top: 1px solid var(--line);
  display: flex; align-items: center; gap: 12px; }
.tk-linky { background: none; border: 0; padding: 0; color: var(--muted);
  font: inherit; font-size: 11.5px; cursor: pointer; }
.tk-linky.danger:hover { color: var(--red); }
.tk-links { display: flex; flex-direction: column; gap: 4px; }
.tk-link { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.tk-link a { color: var(--blue); word-break: break-all; }
.tk-linkadd { display: flex; gap: 5px; margin-top: 4px; }
.tk-subs { display: flex; flex-direction: column; gap: 4px; }
.tk-sub { display: flex; gap: 8px; align-items: baseline; font-size: 12.5px;
  color: var(--muted); }
.tk-sub.is-done span { text-decoration: line-through; opacity: .7; }
.tk-x { border: 0; background: none; color: var(--subtle); font-size: 11px;
  padding: 2px 5px; border-radius: 6px; cursor: pointer; }
.tk-x:hover { color: var(--red); background: var(--tint-red); }
@media (max-width: 640px) { .tkc { flex: 0 0 84vw; } .tk-detail { width: 100%; } }

/* ---------- the house card ----------
   Stefan pointed at the corner glow on a metric tile and asked for it
   everywhere: "easier to click on, have some weight, look like they're
   floating." So the treatment that was on one tile type becomes the treatment
   for anything you can open.

   The glow is a radial wash bled off the bottom-right corner. It is deliberately
   faint -- what makes a card read as liftable is the LIFT on hover, and the
   colour is there so the corner is not dead space. --card-color lets a card say
   something with it; unset, it is the house blue. */
.card, .module-card, .tkc, .metric, .stat, .table-wrap {
  position: relative;
}
.card::after, .module-card::after, .tkc::after {
  content: ""; position: absolute; inset: auto -24px -50px auto;
  width: 118px; height: 118px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, var(--card-color, var(--tint-blue)),
              transparent 70%);
  opacity: .85; transition: opacity .18s ease, transform .18s ease;
}
.card > *, .module-card > *, .tkc > * { position: relative; z-index: 1; }
.card, .module-card, .tkc { overflow: hidden; }

/* Anything that opens something lifts. Anything that does not, does not --
   a card that rises under the cursor and then cannot be clicked is a lie. */
.module-card, .tkc, .card.is-clickable {
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.module-card:hover, .card.is-clickable:hover {
  transform: translateY(-2px); border-color: var(--line-strong);
  box-shadow: var(--shadow-lg);
}
.module-card:hover::after, .card.is-clickable:hover::after {
  opacity: 1; transform: scale(1.12);
}
.module-card.is-idle:hover { transform: none; box-shadow: var(--shadow); }
@media (prefers-reduced-motion: reduce) {
  .module-card:hover, .card.is-clickable:hover, .tkc:hover { transform: none; }
  .card::after, .module-card::after, .tkc::after { transition: none; }
}

/* A card can colour its own corner by what it is saying. Semantic, not
   decorative: green means the number is fine, red means it is not. */
.card.tone-good, .module-card.tone-good { --card-color: var(--tint-green); }
.card.tone-warn, .module-card.tone-warn { --card-color: var(--tint-amber); }
.card.tone-bad,  .module-card.tone-bad  { --card-color: var(--tint-red); }
.card.tone-quiet, .module-card.tone-quiet { --card-color: var(--lift-2); }

/* ---------- AI chat rail ----------
   A chat needed three things it did not have: when it was, a way to copy it out,
   and a way to rename or delete it without opening it first. */
.ai-proj-row { display: flex; align-items: stretch; border-radius: 9px;
  transition: background .14s ease; }
.ai-proj-row:hover { background: var(--lift-2); }
.ai-proj-row.on { background: var(--tint-blue); }
.ai-proj-row .ai-proj { flex: 1; min-width: 0; background: none; }
.ai-proj-row:hover .ai-proj, .ai-proj-row.on .ai-proj { background: none; }
.ai-proj-more { flex: 0 0 26px; border: 0; background: none; color: var(--subtle);
  font-size: 15px; line-height: 1; border-radius: 7px; cursor: pointer;
  opacity: 0; transition: opacity .14s ease, color .14s ease; }
.ai-proj-row:hover .ai-proj-more, .ai-proj-row.on .ai-proj-more { opacity: 1; }
.ai-proj-more:hover { color: var(--text); background: var(--lift-3); }

.ai-menu { position: fixed; z-index: 60; min-width: 178px; padding: 5px;
  border: 1px solid var(--line); border-radius: 11px; background: var(--panel-2);
  box-shadow: var(--shadow-lg); display: flex; flex-direction: column; gap: 1px; }
.ai-menu button { text-align: left; border: 0; background: none; color: var(--text);
  font: inherit; font-size: 12.5px; padding: 8px 10px; border-radius: 7px;
  cursor: pointer; }
.ai-menu button:hover { background: var(--lift-3); }
.ai-menu button.danger { color: var(--red); }
.ai-menu button.danger:hover { background: var(--tint-red); }


/* A metric that explains itself. Stefan's reason for wanting these: he should
   not have to come back to a chat log to remember how a number was reached, or
   ask anyone. The "?" shows on hover and on keyboard focus, and opens a note
   over the card without navigating away -- the card itself still links through. */
.metric { position: relative; }
.metric-why { position:absolute; top:10px; right:10px; z-index:3;
  width:19px; height:19px; border-radius:50%; padding:0; line-height:17px;
  font-size:11px; font-weight:800; cursor:pointer;
  border:1px solid var(--line-strong); background:var(--lift-1); color:var(--muted);
  opacity:0; transition:opacity .14s, color .14s, border-color .14s; }
.metric:hover .metric-why, .metric-why:focus-visible, .metric-why[aria-expanded="true"] {
  opacity:1; }
.metric-why:hover, .metric-why[aria-expanded="true"] {
  color:var(--blue); border-color:var(--blue); }
/* The explanation as a popover beside the card -- the one explain component:
   HQ, Payroll, Ads and Finance all use it, so the number and what it means
   can be read together. */
.why-pop { position:fixed; z-index:60; width:min(300px, calc(100vw - 24px));
  padding:13px 15px; border-radius:12px; pointer-events:auto;
  background:var(--panel); border:1px solid var(--blue);
  box-shadow:0 14px 38px -12px rgba(0,0,0,.5), 0 2px 6px rgba(0,0,0,.16);
  color:var(--text); font-size:11.5px; line-height:1.55;
  opacity:0; visibility:hidden; transform:translateY(-4px);
  transition:opacity .13s ease, transform .13s ease; }
.why-pop.open { opacity:1; visibility:visible; transform:translateY(0); }
.why-pop h6 { margin:0 0 6px; font-size:9.5px; font-weight:800; letter-spacing:.09em;
  text-transform:uppercase; color:var(--muted); }
.why-pop p { margin:0; white-space:pre-line; }
@media (prefers-reduced-motion:reduce) { .why-pop { transition:none; } }


/* ---------------------------------------------------------------------------
   Hover, everywhere something can be clicked.

   Stefan's reference is ClickUp: point at a client name, an icon, anything
   actionable, and a quiet highlight appears saying "this is the thing you have
   got". It is not decoration -- it is the answer to "will something happen if I
   click here", given before the click rather than after it.

   Subtle on purpose. --lift-2 is a few percent of ink, so it reads as a change
   of state and never as a colour. One rule set rather than forty, so a new page
   inherits it without anyone remembering to.
   --------------------------------------------------------------------------- */

/* Rows you can open. Marked by the cursor the page already sets, so nothing
   has to be relabelled to take part. */
.grid tbody tr:hover td,
tbody tr[data-id]:hover td,
tbody tr[onclick]:hover td,
tr.row-link:hover td {
  background: var(--lift-2);
}
.grid tbody tr { transition: background .13s ease; }
.grid tbody tr:has(a):hover td,
.grid tbody tr[data-id]:hover td { background: var(--lift-2); }

/* Links inside tables and lists: the whole word lifts, not just the underline. */
.grid td a:hover,
.table-wrap td a:hover {
  color: var(--blue);
  text-decoration: none;
}

/* Anything small and clickable — icon buttons, link buttons, chips, pickers.
   They shared a habit of only changing colour, which on a busy row is easy to
   miss; a ground behind them is not. */
.link-btn, .nav-icon-btn, .status-pick, .msg-x, .chip, .pill-btn,
.tb-btn, .theme-toggle, .metric-why, summary {
  border-radius: 7px;
  transition: background .13s ease, color .13s ease, border-color .13s ease;
}
.link-btn:hover, .nav-icon-btn:hover, .msg-x:hover, .chip:hover,
.pill-btn:hover, .tb-btn:hover {
  background: var(--lift-2);
  color: var(--text);
}
.link-btn.danger:hover { background: var(--tint-red); color: var(--red); }

/* A <summary> is a button that does not look like one until you touch it. */
summary { padding-inline: 6px; margin-inline: -6px; }
summary:hover { background: var(--lift-2); }

/* Cards that navigate. The lift is the same everywhere; only the distance
   changes, so a big card moves as little as a small one. */
.metric-link:hover, .module-card[data-href]:hover, .sop:hover, .wl:hover {
  background: var(--lift-1);
}

/* Focus is the same promise for a keyboard. Never remove it, and never let it
   be quieter than hover -- somebody navigating by keyboard has less to go on,
   not more. */
a:focus-visible, button:focus-visible, summary:focus-visible,
[tabindex]:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
  border-radius: 6px;
}

@media (prefers-reduced-motion: reduce) {
  .grid tbody tr, .link-btn, .nav-icon-btn, .status-pick, .msg-x, .chip,
  .pill-btn, .tb-btn, summary { transition: none; }
}


/* Renewal overdue. Worked out from the end date rather than stored, so it
   reaches In-Person clients too -- their status is a delivery mode, not a
   lifecycle stage, and overwriting it to say "overdue" would lose which of
   Mike's people he actually trains in the gym. Two facts, both kept. */
.chip-overdue {
  display: inline-block; margin-left: 7px; padding: 1.5px 7px;
  border-radius: 20px; font-size: 8.5px; font-weight: 900;
  letter-spacing: .06em; text-transform: uppercase; vertical-align: 1px;
  color: var(--alarm-ink); background: var(--alarm-bg);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--alarm-bg) 22%, transparent);
}
.renew-late {
  color: var(--alarm-ink); background: var(--alarm-bg);
  font-weight: 800; font-size: 10px; padding: 1.5px 6px; border-radius: 5px;
}

/* The count above the roster. Hidden at zero, which is where it should live --
   so when it appears at all, it appears loudly. */
#overdueFilter {
  border: 0; font-weight: 900; letter-spacing: .03em; text-transform: uppercase;
  font-size: 9.5px; padding: 6px 11px; border-radius: 8px;
  color: var(--alarm-ink); background: var(--alarm-bg);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--alarm-bg) 55%, transparent);
  animation: alarmPulse 2.4s ease-out infinite;
}
#overdueFilter:hover { filter: brightness(1.08); }
#overdueFilter.on {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--alarm-bg) 45%, transparent);
  animation: none;
}
@keyframes alarmPulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--alarm-bg) 55%, transparent); }
  70%  { box-shadow: 0 0 0 9px color-mix(in srgb, var(--alarm-bg) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--alarm-bg) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  #overdueFilter { animation: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--alarm-bg) 35%, transparent); }
}

/* ---- Lifetime value (Finance) ------------------------------------------
   The distribution is a table with bars in it, not a chart: each band keeps
   its count and share written beside the bar, and the longest band runs the
   full width so the shape reads at a glance. One hue, since every bar is the
   same thing (clients) and only the magnitude differs. */
.ltv-dist { display:grid; gap:7px; padding:4px 0 2px; }
.ltv-band { display:grid; grid-template-columns: 96px 1fr 44px 52px; align-items:center;
  gap:10px; font-size:12px; font-variant-numeric: tabular-nums; }
.ltv-band-label { color:var(--muted); white-space:nowrap; }
.ltv-band-bar { display:block; height:14px; border-radius:4px; background:var(--tint-blue);
  overflow:hidden; }
.ltv-band-bar i { display:block; height:100%; border-radius:4px; background:var(--blue);
  opacity:.82; transition: width .35s ease; }
.ltv-band-n { text-align:right; font-weight:700; }
.ltv-band-pct { text-align:right; color:var(--subtle); }
@media (max-width: 640px) {
  .ltv-band { grid-template-columns: 80px 1fr 40px 46px; gap:6px; font-size:11px; }
}

/* The lifetime headline on a client's Money tab: the figure first, the
   working beside it. Company rank appears only for people who can see the
   company-wide page, so the block has to read fine without it. */
.ltv-head { display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 14px;
  padding:12px 16px; margin-bottom:14px; border:1px solid var(--line); border-radius:12px;
  background: linear-gradient(160deg, var(--panel-2), var(--panel)); }
.ltv-head .ltv-k { flex-basis:100%; color:var(--muted); font-size:10px; font-weight:800;
  letter-spacing:.08em; text-transform:uppercase; }
.ltv-head .ltv-v { font-size:23px; font-weight:800; letter-spacing:-.035em;
  font-variant-numeric: tabular-nums; }
.ltv-head .ltv-sub { color:var(--subtle); font-size:11.5px; }
.ltv-head .ltv-rank { flex-basis:100%; color:var(--muted); font-size:11.5px; }
.ltv-head .ltv-rank a { color: var(--blue); }
#ltvAll tr.muted td { color: var(--subtle); }
#ltvAll tr.muted td a { color: var(--muted); }

/* ---- loading -------------------------------------------------------------
   Two signals while a page's data is on its way, both driven by the fetch
   wrapper in common.js. The bar along the top edge says "working" the way
   every browser and app already does; the placeholder shapes below say
   where the numbers and rows are about to be, so the page has its layout
   before it has its content instead of arriving blank and then jumping.
   The shapes exist only while html.oo-loading is on -- an empty container
   after loading is just empty. */
.loadbar { position:fixed; top:0; left:0; right:0; height:2px; z-index:90;
  background:linear-gradient(90deg, transparent 0%, var(--blue) 30%, var(--blue) 70%, transparent 100%);
  background-size:40% 100%; background-repeat:no-repeat;
  animation:loadbar 1.1s ease-in-out infinite; pointer-events:none; }
.loadbar[hidden] { display:none; }
@keyframes loadbar { 0% { background-position:-40% 0; } 100% { background-position:140% 0; } }

@keyframes skel { 0% { background-position:-200% 0; } 100% { background-position:200% 0; } }
.oo-loading .metric-grid:empty::before, .oo-loading .stat-row:empty::before,
.oo-loading .kpi-strip:empty::before, .oo-loading .split-list:empty::before,
.oo-loading .bar-list:empty::before, .oo-loading .chart-box:empty::before,
.oo-loading .msg-log:empty::before, .oo-loading .ibx-list:empty::before,
.oo-loading .tk-board:empty::before, .oo-loading .module-grid:empty::before,
.oo-loading .tool-grid:empty::before, .oo-loading .skel:empty::before {
  content:""; display:block; grid-column:1 / -1; flex:1 1 100%; width:100%;
  border-radius:12px; min-height:72px;
  background:linear-gradient(90deg, var(--lift-1) 0%, var(--lift-3) 45%, var(--lift-1) 90%);
  background-size:200% 100%; animation:skel 1.4s ease-in-out infinite; }
.oo-loading .metric-grid:empty::before { min-height:108px; }
.oo-loading .chart-box:empty::before, .oo-loading .msg-log:empty::before,
.oo-loading .ibx-list:empty::before, .oo-loading .tk-board:empty::before { min-height:220px; }
/* Tables: a stack of row-shaped bands instead of one block, so the shape
   says "list" before the list is there. A table with no rows has no height
   of its own, so it is given one while it waits. */
.oo-loading table.grid:empty, .oo-loading table:empty[id] {
  display:block; min-height:150px; border-radius:10px;
  background:repeating-linear-gradient(180deg, var(--lift-2) 0 22px, transparent 22px 34px);
  -webkit-mask:linear-gradient(90deg, #000 0%, #000 60%, rgba(0,0,0,.35) 100%);
  mask:linear-gradient(90deg, #000 0%, #000 60%, rgba(0,0,0,.35) 100%);
  animation:skel-fade 1.4s ease-in-out infinite; }
/* A header already on the page with an empty body under it: the bands go
   under the header, drawn on the wrapper so the header keeps its layout. */
.oo-loading .table-wrap:has(> table > tbody:empty)::after {
  content:""; display:block; min-height:120px; border-radius:0 0 10px 10px;
  background:repeating-linear-gradient(180deg, var(--lift-2) 0 22px, transparent 22px 34px);
  -webkit-mask:linear-gradient(90deg, #000 0%, #000 60%, rgba(0,0,0,.35) 100%);
  mask:linear-gradient(90deg, #000 0%, #000 60%, rgba(0,0,0,.35) 100%);
  animation:skel-fade 1.4s ease-in-out infinite; }
@keyframes skel-fade { 0%, 100% { opacity:.55; } 50% { opacity:1; } }
@media (prefers-reduced-motion: reduce) {
  .loadbar, .oo-loading *::before, .oo-loading *::after, .oo-loading table { animation:none !important; }
}
/* After a failure, a section that stayed empty says so instead of reading as
   "nothing here". Same containers as the placeholders above. */
.oo-failed:not(.oo-loading) .metric-grid:empty::before, .oo-failed:not(.oo-loading) .stat-row:empty::before,
.oo-failed:not(.oo-loading) .kpi-strip:empty::before, .oo-failed:not(.oo-loading) .split-list:empty::before,
.oo-failed:not(.oo-loading) .bar-list:empty::before, .oo-failed:not(.oo-loading) .chart-box:empty::before,
.oo-failed:not(.oo-loading) .msg-log:empty::before, .oo-failed:not(.oo-loading) .ibx-list:empty::before,
.oo-failed:not(.oo-loading) .tk-board:empty::before, .oo-failed:not(.oo-loading) .module-grid:empty::before,
.oo-failed:not(.oo-loading) table.grid:empty::before, .oo-failed:not(.oo-loading) table:empty[id]::before,
.oo-failed:not(.oo-loading) .table-wrap:has(> table > tbody:empty)::after {
  content:"Couldn't load this — reload the page to try again."; display:block; grid-column:1 / -1;
  padding:14px 16px; border:1px dashed rgba(251,100,114,.45); border-radius:10px;
  color:var(--ink-bad); font-size:12.5px; background:var(--tint-red); }
.oo-failed:not(.oo-loading) table.grid:empty, .oo-failed:not(.oo-loading) table:empty[id] { display:block; }

/* ==========================================================================
   Phones. The shell already folds to a rail; these are the PAGES. One
   block, so the next person can see every phone rule in one read. Rule of
   thumb throughout: a row of controls becomes a scrolling strip, a table
   scrolls inside its own frame, a dialog takes the whole screen, and the
   page itself never scrolls sideways.
   ========================================================================== */
@media (max-width: 680px) {
  /* -- the page never scrolls sideways; anything wide scrolls in its frame.
        `clip`, not `hidden`: hidden makes the body a scroll container that
        never scrolls, and a sticky top bar inside it never sticks. */
  html, body { overflow-x: clip; }
  main { overflow-x: clip; }

  /* -- top bar: eight controls have to fit beside the rail on a 375px screen */
  .topbar { gap: 6px 10px; padding-top: 8px; }
  .crumb { flex-basis: 100%; order: 1; font-size: 12px; }
  .topbar-actions { flex-basis: 100%; order: 2; gap: 3px; justify-content: space-between; }
  .topbar-actions .tb-btn { height: 34px; min-width: 34px; padding: 0 6px; }
  .tb-account { margin-left: 0; }
  .tb-account .account-avatar { width: 34px; height: 34px; flex-basis: 34px; }

  /* -- tab rows scroll instead of stacking three deep (Finance had six tabs
        on three lines before a number was visible) */
  .tab-row { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; padding-bottom: 8px; margin-inline: -4px; padding-inline: 4px; }
  .tab-row::-webkit-scrollbar { display: none; }
  .tab-row .tb-btn { flex: 0 0 auto; white-space: nowrap; }

  /* -- cards, stats, folds */
  .stat-row { gap: 8px; }
  .stat-row .stat { flex: 1 1 calc(50% - 8px); min-width: 0; padding: 10px 12px; }
  .stat .v { font-size: 17px; }
  .metric { min-height: 96px; padding: 12px 14px; }
  .metric-value { font-size: 20px; }
  .mr-fold > summary { flex-wrap: wrap; gap: 4px 12px; }
  .mr-fold > summary h2 { font-size: 15px; }
  .mr-fold > summary .fold-kpis { flex-basis: 100%; gap: 3px 12px; }
  .metric-detail { padding: 12px 12px; }
  .metric-detail .working { max-width: none; }

  /* -- dialogs take the screen: the client profile, book-a-call, save a
        document, the end-of-day report -- every .brain-overlay modal */
  .brain-overlay { padding: 0; align-items: stretch; }
  .brain-overlay .brain-panel { width: 100%; max-width: none; height: 100%;
    max-height: none; border-radius: 0; border: 0; }
  .note-dialog, .note-dialog.wide { width: 100%; }
  .note-dialog .brain-head { flex-wrap: wrap; gap: 6px 10px; padding: 12px 14px; }
  .note-dialog .brain-head strong { max-width: calc(100% - 60px); }
  .note-dialog .brain-body { padding: 12px 14px !important; }
  .money-grid { grid-template-columns: 1fr; }
  .convo-head { flex-wrap: wrap; gap: 8px; }

  /* -- Finance */
  .mr-when { flex-wrap: wrap; }
  .mr-when select { width: auto !important; flex: 1 1 120px; }
  .fin-top { flex-wrap: wrap; align-items: stretch; }
  .fin-top .cash-input, .fin-top .button { flex: 1 1 100%; }
  .fin-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .ledger td.lab { max-width: 60vw; }
  #bankQueue .queue-row { grid-template-columns: 1fr; }
  .ltv-band { grid-template-columns: 76px 1fr 36px 44px; gap: 6px; font-size: 11px; }

  /* -- Ads */
  .filter-bar { gap: 10px; }
  .filter-group { flex: 1 1 100%; }
  .filter-bar select { min-width: 0; width: 100%; }
  .filter-row-inner input[type="date"] { flex: 1 1 120px; min-width: 0; }
  .viz-root .metric-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .chart-box { min-height: 200px; }
  .segmented { flex-wrap: wrap; }

  /* -- Clients: the roster scrolls in its frame; the by-coach table too */
  .roster th, .roster td { padding: 8px 8px; font-size: 12px; white-space: nowrap; }
  .tile-panel { width: 100vw; }

  /* -- Inbox: the actions drop under the message instead of squeezing it
        to one word a line */
  .ibx-card { flex-wrap: wrap; padding: 12px 14px; }
  .ibx-card-body { flex: 1 1 calc(100% - 44px); }
  .ibx-actions { flex: 1 1 100%; justify-content: flex-end; padding-top: 6px; }
  .ibx-head { flex-wrap: wrap; gap: 8px 12px; padding: 12px 14px; }
  .ibx-rail { padding: 6px; }
  .ibx-rail .ibx-rail-head { border-top: 0; margin: 0; padding: 8px 8px 2px; }
  .msg-panel-body .msg-turn { max-width: 96%; }

  /* -- Tasks: one column at a time, swipe for the next */
  .tk-board { gap: 10px; }
  .tkc { flex: 0 0 88vw; }

  /* -- Check-ins, Payroll, Calls: the toolbars wrap and the panels fill */
  .ci-panel { width: 100%; }
  .ci-outg-head { flex-wrap: wrap; gap: 6px; }
  .entry-row { grid-template-columns: 1fr !important; }
  .entry-row .span-2 { grid-column: auto; }
  .page-heading .action-row { width: 100%; }
  .page-heading .action-row .button { flex: 1 1 auto; justify-content: center; }

  /* -- the Brain and the search pill */
  .bside { width: 100vw; }
  .gsearch { min-width: 0; }
}

@media (max-width: 480px) {
  .metric-grid, .viz-root .metric-grid, .fin-metrics { grid-template-columns: 1fr !important; }
  .stat-row .stat { flex-basis: 100%; }
  .ltv-band { grid-template-columns: 64px 1fr 32px 40px; }
}

/* ==========================================================================
   Utilities. What the three hundred and eighty most repeated inline styles
   turned into, so spacing and widths come from one short list instead of a
   different number typed on every page. Spacing rhythm: 4 / 8 / 12 / 16 --
   the 10s and 14s that had crept in are 12 now. Widths: four sizes. These
   replace inline styles, so they carry the same authority.
   ========================================================================== */
.mt-4 { margin-top: 4px !important; }   .mt-8 { margin-top: 8px !important; }
.mt-12 { margin-top: 12px !important; } .mt-16 { margin-top: 16px !important; }
.mb-4 { margin-bottom: 4px !important; } .mb-8 { margin-bottom: 8px !important; }
.mb-12 { margin-bottom: 12px !important; } .mb-16 { margin-bottom: 16px !important; }
.block { display: block !important; }
.wrap { flex-wrap: wrap !important; }
.nowrap { white-space: nowrap !important; }
.justify-end { justify-content: flex-end !important; }
.grow { flex: 1 1 0% !important; min-width: 0; }
.hstack { display: flex !important; align-items: center; gap: 6px; }
.pointer { cursor: pointer; }
.select-all { user-select: all; }
.num { text-align: right !important; font-variant-numeric: tabular-nums; }
.tnum { font-variant-numeric: tabular-nums; }
.w-130 { width: 130px !important; } .w-160 { width: 160px !important; }
.w-110 { width: 110px !important; } .w-190 { width: 190px !important; } .w-220 { width: 220px !important; }
.w-full { width: 100% !important; } .w-auto { width: auto !important; }
.ink-bad { color: var(--ink-bad) !important; }
.ink-warn { color: var(--ink-warn) !important; }
.ink-blue { color: var(--blue) !important; }
.fs-11 { font-size: 11px !important; } .fs-12 { font-size: 12px !important; }
@media (max-width: 680px) {
  .w-110, .w-130, .w-160, .w-190, .w-220 { width: auto !important; flex: 1 1 120px; min-width: 0; }
}

/* ---- the re-sign list on the Dashboard ---------------------------------- */
.renew-card { padding:14px 16px; }
.renew-chip { display:inline-flex; align-items:center; gap:5px; padding:4px 10px; border-radius:999px;
  font-size:11.5px; font-weight:600; color:var(--muted); background:var(--lift-2);
  border:1px solid transparent; font-family:inherit; cursor:pointer;
  transition:border-color .14s ease, background .14s ease, transform .12s ease; }
.renew-chip:hover { border-color:var(--line-strong); transform:translateY(-1px); }
.renew-chip.on { border-color:var(--blue); background:var(--tint-blue); color:var(--blue); }
.renew-chip.on b { color:var(--blue); }
.renew-chip.renew-ended.on { border-color:var(--red); }
.renew-chip.renew-urgent.on { border-color:var(--amber); background:var(--tint-amber); color:var(--ink-warn); }
.renew-chip.renew-urgent.on b { color:var(--ink-warn); }
.renew-chip:focus-visible { outline:2px solid var(--blue); outline-offset:2px; }
.renew-chip b { color:var(--text); }
.renew-chip.renew-ended { background:var(--tint-red); color:var(--ink-bad); }
.renew-chip.renew-ended b { color:var(--ink-bad); }
.renew-chip.renew-urgent { background:var(--tint-amber); color:var(--ink-warn); }
.renew-chip.renew-urgent b { color:var(--ink-warn); }
.renew-stage { display:inline-block; margin-left:8px; font-size:10px; font-weight:800;
  letter-spacing:.06em; text-transform:uppercase; color:var(--subtle); }
tr.renew-ended .renew-stage { color:var(--ink-bad); }
tr.renew-urgent .renew-stage { color:var(--ink-warn); }
/* The runway pill under "Contract ends". One hue per band, each a tint with
   its ink, so it reads in both themes; ended is the one solid. */
.due { display:inline-block; min-width:64px; text-align:center; padding:3px 9px; border-radius:999px;
  font-size:11.5px; font-weight:700; font-variant-numeric:tabular-nums; margin-right:6px; }
.due-90 { background:var(--tint-green); color:var(--ink-good); }
.due-60 { background:var(--tint-yellow); color:var(--ink-yellow); }
.due-45 { background:var(--tint-amber); color:var(--ink-warn); }
.due-30 { background:var(--tint-red); color:var(--ink-bad); }
.due-ended { background:var(--alarm-bg); color:var(--alarm-ink); }
/* Compact: six rows on screen, the rest scroll inside the card. */
/* Tall enough to be a view of the roster rather than a peephole. It was six
   rows; Stefan asked on 09-18-2026 to see more at a 10,000-foot view, so it is
   about fourteen now and still scrolls when there are more than that. The
   second value keeps it off a short laptop screen, where a table taller than
   the window buries everything under it. */
.renew-scroll { max-height:min(544px, calc(100vh - 360px)); min-height:232px; overflow-y:auto; }
.renew-scroll.uncapped { max-height:none; }
.renew-table th { position:sticky; top:0; z-index:1; background:var(--panel); }
.renew-table td { padding:6px 10px; font-size:12.5px; }
.renew-touched { font-size:12px; color:var(--ink-good); }
#renewTable td { vertical-align:middle; }
.renew-note-in { width:200px; max-width:50vw; height:30px; font-size:12px; }
.renew-touched { display:inline-block; max-width:360px; }

/* ---- a page rendered for a panel on another page ----------------------
   body.embed: no shell, and on the roster the list is hidden and the client
   card fills the frame instead of floating over a backdrop. */
body.embed .sidebar, body.embed .topbar, body.embed .app-footer, body.embed .subnav { display:none !important; }
body.embed .app-shell { display:block; }
body.embed main { padding:0; }
body.embed .page { padding-top:0; max-width:none; }
body.embed .viz-root, body.embed #tilePanel { display:none !important; }
body.embed #noteOverlay { position:static; padding:0; background:none; backdrop-filter:none;
  display:block; min-height:100vh; }
body.embed #noteOverlay[hidden] { display:none; }
body.embed #noteDialog, body.embed #noteDialog.wide { width:100%; max-width:none; max-height:none;
  min-height:100vh; border:0; border-radius:0; box-shadow:none; }
body.embed .bside { display:none !important; }

/* The panel on the Dashboard that holds the client card. */
.client-panel-backdrop { position:fixed; inset:0; z-index:64; background:rgba(4,7,12,.45); }
.client-panel-backdrop[hidden] { display:none; }
.client-panel { position:fixed; top:0; right:0; bottom:0; width:min(780px, 96vw); z-index:65;
  display:flex; flex-direction:column; background:var(--panel); border-left:1px solid var(--line);
  box-shadow:var(--shadow-lg); animation:tileIn .2s cubic-bezier(.2,.8,.3,1); }
.client-panel[hidden] { display:none; }
.client-panel-head { display:flex; align-items:center; gap:10px; padding:10px 14px;
  border-bottom:1px solid var(--line); flex:0 0 auto; }
.client-panel-head b { flex:1 1 auto; font-size:14px; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.client-panel iframe { flex:1 1 auto; width:100%; border:0; background:var(--panel); }
.tab-row .tb-tab-link { margin-left:auto; color:var(--blue); text-decoration:none; }

/* ---- a payment typed in on the Payroll page ------------------------------ */
.byhand { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.byhand input, .byhand select { width: auto; }
.byhand input[type="date"] { width: 150px; }
.byhand select { width: 110px; }
.byhand-x { font-size: 15px; line-height: 1; padding: 2px 6px; }
@media (max-width: 680px) {
  .byhand input, .byhand select, .byhand input[type="date"] { flex: 1 1 140px; width: auto; }
}

/* ---- Setter Log: today's card and the two daily reports ------------------ */
.today-card { padding:18px 20px; }
.today-row { display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:20px; align-items:start; }
.today-actions { display:flex; gap:10px; flex-wrap:wrap; align-self:center; }
.today-btn { min-height:44px; padding:0 20px; font-size:14px; font-weight:700; }
.today-status { min-width:0; }
.today-status .card-sub { margin:0; font-size:13px; }
.today-date { margin-left:auto; text-align:right; font-size:15px; font-weight:800;
  letter-spacing:-.01em; font-variant-numeric:tabular-nums; white-space:nowrap; }
.today-date-label { display:block; font-size:10px; font-weight:800; letter-spacing:.13em;
  text-transform:uppercase; color:var(--subtle); margin-bottom:2px; }
@media (max-width:760px) {
  .today-row { grid-template-columns:1fr; }
  .today-date { margin-left:0; text-align:left; order:-1; }
}
.today-pri { margin:6px 0 0; padding-left:18px; font-size:12.5px; }
.today-pri li { margin:2px 0; }
.sod-priorities { display:grid; gap:8px; margin-top:6px; }
.eod-h { font-size:11px; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--muted); margin:16px 0 8px; }
.eod-check { display:flex; align-items:center; gap:8px; font-size:12.5px; margin:6px 0; }
.eod-check input { width:auto; }
.day-card { margin-bottom:10px; padding:14px; }
.day-head { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.day-head strong { font-size:14px; }
.day-date { font-size:12px; color:var(--muted); font-variant-numeric:tabular-nums; }
.day-grid { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-top:10px; }
@media (max-width:680px) { .day-grid { grid-template-columns:1fr; } }
/* A report inside the day: a bordered panel that reads as a thing you open.
   The whole panel is the click; "Edit" in the corner says what the click does. */
.day-report { border:1px solid var(--line); border-radius:12px; padding:10px 12px; cursor:pointer;
  background:var(--lift-1); transition:border-color .14s ease, background .14s ease; }
.day-report:hover, .day-report:focus-visible { border-color:var(--blue); background:var(--tint-blue); outline:none; }
.day-report-head { display:flex; justify-content:space-between; align-items:baseline; margin-bottom:4px;
  font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--muted); }
.day-report-edit { font-size:11px; font-weight:700; letter-spacing:0; text-transform:none; color:var(--blue); }
.day-line { font-size:12.5px; margin:2px 0 0; }
.day-part-h { font-size:10.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
  color:var(--muted); margin-bottom:4px; }
.day-text { font-size:12px; white-space:pre-wrap; margin:4px 0 0; }

/* The Day Log (VAs): the setter's day panels, carrying a list instead of
   numbers. One panel a day; the log is a bulleted list, in the day's own
   words. Stefan, 09-19-2026. */
.dl-day { margin-top:8px; }
.dl-day:first-child { margin-top:0; }
.dl-day.dl-theirs { cursor:default; }
.dl-day.dl-theirs:hover { border-color:var(--line); background:var(--lift-1); }
.dl-day .day-report-head { text-transform:none; letter-spacing:0; font-size:12.5px; font-weight:600;
  color:var(--text); }
.dl-day .day-report-head > span:first-child b { font-weight:750; }
.dl-times { font-size:11.5px; font-weight:500; color:var(--muted); white-space:nowrap; }
.dl-times b { color:var(--text); }
.dl-list { margin:4px 0 0; padding-left:18px; font-size:12.5px; line-height:1.5; }
.dl-list li { margin:1px 0; }
.dl-note { color:var(--muted); font-style:italic; }
.dl-empty { color:var(--subtle); }
.dl-block { color:var(--amber); margin-top:4px; }
.dl-block b { color:inherit; }
.dl-opt { font-weight:500; color:var(--subtle); margin-left:4px; }
.dl-grid-2 { grid-template-columns:repeat(2, minmax(0,1fr)); }
@media (max-width:680px) { .dl-times { white-space:normal; } }


/* ---- viewing as somebody else ------------------------------------------- */
.asbar { position: sticky; top: 0; z-index: 60; display: flex; align-items: center; gap: 10px;
  padding: 9px 18px; font-size: 13px; line-height: 1.4; color: #fff;
  background: var(--violet, #7c3aed); box-shadow: 0 1px 0 rgba(0,0,0,.14); }
.asbar b { font-weight: 700; }
.asbar-ico { width: 16px; height: 16px; flex: 0 0 16px; opacity: .9; fill: none; stroke: currentColor; }
.asbar-gap { flex: 1; }
.asbar-back { flex: 0 0 auto; white-space: nowrap; color: #fff; font-weight: 650; padding: 4px 12px;
  border-radius: 999px; background: rgba(255,255,255,.17); border: 1px solid rgba(255,255,255,.3); }
.asbar-back:hover { background: rgba(255,255,255,.3); color: #fff; }
/* The sidebar is sticky at the top of the window; with a bar above it, it has
   to start below the bar or its bottom runs off the screen. */
body[data-asbar] .sidebar { top: var(--asbar, 40px); height: calc(100vh - var(--asbar, 40px)); }
@media (max-width: 680px) { .asbar { padding: 8px 12px; font-size: 12px; } .asbar-more { display: none; } }

/* ---- Conversations: one prospect, whole ---------------------------------
   A name search, then their timeline on every channel with the pre-call
   brief above it. The brief also opens in a side panel from the Call Log
   and the Calendar (brief.js), using the Brain's frame. */
.who-row { display:flex; justify-content:space-between; gap:12px; width:100%; text-align:left;
  font:inherit; padding:9px 12px; border:1px solid var(--line); border-radius:10px;
  background:var(--lift-1); color:var(--text); cursor:pointer; margin-top:6px;
  transition:border-color .14s ease, background .14s ease; }
.who-row:hover, .who-row:focus-visible { border-color:var(--blue-line); background:var(--lift-2); outline:none; }
.who-name { font-weight:650; font-size:13px; }
.who-meta { color:var(--subtle); font-size:11.5px; white-space:nowrap; }
.prospect-head { display:flex; justify-content:space-between; gap:14px; align-items:flex-start; flex-wrap:wrap; }
.prospect-head h3 { margin:0; }
.brief-card { border:1px solid var(--line); border-radius:14px; padding:14px 16px; background:var(--panel-2); }
.brief-card-head { display:flex; justify-content:space-between; align-items:center; gap:10px; margin-bottom:6px; }
.brief-card h4, .brief-empty h4 { margin:0; font-size:13px; }
.brief-empty { display:flex; justify-content:space-between; align-items:center; gap:16px; flex-wrap:wrap; }
.brief-empty p { margin:4px 0 0; max-width:60ch; }
.brief-headline { font-size:14.5px; font-weight:650; line-height:1.45; margin:4px 0 8px; letter-spacing:-.01em; }
.brief-booking { color:var(--muted); font-size:12.5px; margin:0 0 10px; }
.brief-angle { border-left:3px solid var(--blue); padding:6px 12px; margin:0 0 12px;
  background:var(--lift-1); border-radius:0 10px 10px 0; }
.brief-angle p { margin:0; font-size:13px; line-height:1.55; }
.brief-sec { margin-top:10px; }
.brief-sec h5, .brief-angle h5 { margin:0 0 4px; font-size:10.5px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--subtle); }
.brief-list { margin:0; padding-left:18px; font-size:13px; line-height:1.55; }
.brief-list li { margin:2px 0; }
.brief-quote { margin:6px 0; padding:8px 12px; border-radius:10px; background:var(--lift-2);
  font-size:12.5px; line-height:1.5; font-style:italic; }
.brief-quote span { display:block; font-style:normal; color:var(--subtle); font-size:11px; margin-top:3px; }
.brief-stamp { color:var(--subtle); font-size:11px; margin:12px 0 0; }
.brief-stale { color:var(--ink-warn, #c98a2b); }
.brief-link { font:inherit; border:0; background:none; padding:0; color:var(--blue); cursor:pointer; text-decoration:underline; }
.brief-side .brief-body { display:block; }
.brief-side .brief-empty { flex-direction:column; align-items:flex-start; }
.timeline { max-height:min(560px, 62vh); overflow-y:auto; padding:12px 14px; border:1px solid var(--line);
  border-radius:14px; background:var(--lift-1); display:flex; flex-direction:column; gap:8px; scrollbar-width:thin; }
.tl-day { align-self:center; font-size:10.5px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  color:var(--subtle); margin:10px 0 2px; }
.tl-event { align-self:center; max-width:90%; text-align:center; font-size:11.5px; color:var(--subtle);
  padding:4px 10px; border:1px dashed var(--line); border-radius:999px; }
.tl-event span { font-weight:700; margin-right:6px; }
.tl-event em { font-style:normal; margin-left:8px; opacity:.8; }
.tl-turn { display:flex; flex-direction:column; max-width:78%; }
.tl-turn.us { align-self:flex-end; align-items:flex-end; }
.tl-turn.them { align-self:flex-start; align-items:flex-start; }
.tl-bubble { padding:9px 13px; border-radius:16px; font-size:13px; line-height:1.5; white-space:pre-wrap; overflow-wrap:anywhere; }
.tl-turn.us .tl-bubble { background:var(--blue-solid); color:var(--on-accent); border-bottom-right-radius:5px; }
.tl-turn.them .tl-bubble { background:var(--panel); border:1px solid var(--line); border-bottom-left-radius:5px; }
.tl-meta { font-size:10.5px; color:var(--subtle); margin-top:3px; padding:0 4px; }
/* Where a row is a person: the two ways into their conversation. */
.convo-links { display:inline-flex; gap:5px; flex-wrap:wrap; }
.cal-event.has-contact { cursor:pointer; }
.cal-event.has-contact:hover { border-color:var(--blue-line); }
.cal-brief { font-size:10px; color:var(--blue); font-weight:600; }
/* The pick list under a text field (GHL contact on the pitch form). */
.pick { position:relative; }
.pick-list { position:absolute; left:0; right:0; top:calc(100% + 4px); z-index:20; max-height:260px; overflow-y:auto;
  background:var(--panel); border:1px solid var(--line); border-radius:12px; box-shadow:var(--shadow-lg); padding:4px; }
.pick-list[hidden] { display:none; }
.pick-row { display:flex; justify-content:space-between; gap:12px; width:100%; text-align:left; font:inherit;
  font-size:12.5px; padding:8px 10px; border:0; border-radius:8px; background:transparent; color:var(--text); cursor:pointer; }
.pick-row:hover, .pick-row:focus-visible { background:var(--lift-2); outline:none; }
.pick-row .muted { font-size:11px; white-space:nowrap; }
.pitch-hint { margin-top:4px; font-size:11.5px; }
.pitch-hint:not(.muted) { color:var(--ink-warn, #c98a2b); }
/* The chip that should nag: Needs outcome, with its count. */
.chip.attn { border-color:rgba(245,174,78,.55); color:var(--ink-warn, #b7791f); }
.chip.attn b { display:inline-block; min-width:18px; padding:0 5px; margin-left:4px; border-radius:999px;
  background:rgba(245,174,78,.22); color:inherit; font-size:10.5px; text-align:center; }
.chip.attn.active { background:rgba(245,174,78,.18); border-color:rgba(245,174,78,.8); color:var(--ink-warn, #b7791f); }
/* What happened last time: a callout under the headline, not a section among eight. */
.brief-lastcall { border:1px solid rgba(245,174,78,.55); background:rgba(245,174,78,.10); border-radius:12px;
  padding:10px 14px; margin:0 0 12px; }
.brief-lastcall h5 { margin:0 0 6px; font-size:11px; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  color:var(--ink-warn, #b7791f); }
.brief-lastcall .brief-list { font-size:13px; }
.brief-lastcall .brief-list li { margin:3px 0; }
/* The calls themselves, with the notetaker's notes behind a toggle. */
.brief-calls { margin-top:16px; padding-top:12px; border-top:1px solid var(--line); }
.brief-calls h5 { margin:0 0 6px; font-size:10.5px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; color:var(--subtle); }
.brief-call { border:1px solid var(--line); border-radius:10px; padding:8px 12px; margin-top:6px; background:var(--lift-1); }
.brief-call summary { cursor:pointer; font-size:12.5px; list-style:none; display:flex; gap:6px; align-items:center; flex-wrap:wrap; }
.brief-call summary::-webkit-details-marker { display:none; }
.brief-call summary::before { content:"▸"; color:var(--subtle); font-size:11px; }
.brief-call[open] summary::before { content:"▾"; }
.brief-call-notes { margin-top:8px; font-size:12.5px; line-height:1.55; }
.brief-call-notes h1, .brief-call-notes h2, .brief-call-notes h3 { font-size:12px; margin:10px 0 4px; }
.brief-call-notes ul { padding-left:18px; margin:4px 0; }
.brief-flash { animation:briefFlash 1.6s ease-out; }
@keyframes briefFlash { 0% { box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 55%, transparent); } 100% { box-shadow:0 0 0 3px color-mix(in srgb, var(--blue) 0%, transparent); } }
.cal-again { font-size:10px; color:var(--ink-warn, #b7791f); font-weight:600; }
/* Logging an outcome: pick (dashed), then the green tick writes it. */
.chip.pending { border-style:dashed; border-color:var(--green); color:var(--green); }
.confirm-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:11px; padding:9px 12px;
  border:1px dashed rgba(53,201,143,.55); border-radius:10px; background:rgba(53,201,143,.07); }
.confirm-label { font-size:12px; font-weight:650; }
.confirm-cash { display:inline-flex; gap:6px; flex-wrap:wrap; }
.button.confirm { background:var(--green); }
.button.confirm:hover { background:color-mix(in srgb, var(--green) 85%, black); box-shadow:0 3px 12px color-mix(in srgb, var(--green) 45%, transparent); }
/* ---- Prospects: heat, why, follow-up ------------------------------------ */
.heat-bar { display:flex; flex-direction:column; gap:8px; }
.heat-row { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.heat-stars { display:inline-flex; gap:1px; }
.heat-star { font:inherit; font-size:19px; line-height:1; border:0; background:none; padding:0 1px; cursor:pointer;
  color:var(--line-strong, #9aa3af); transition:transform .1s ease, color .1s ease; }
.heat-star.on { color:#e8a33d; }
.heat-star.sug { color:#c9ced6; }
.heat-stars:not(.ro) .heat-star:hover { transform:scale(1.18); color:#e8a33d; }
.heat-stars.ro .heat-star { cursor:default; font-size:15px; }
.heat-sug-note { max-width:52ch; }
.heat-when { display:inline-flex; align-items:center; gap:6px; font-size:12px; font-weight:650; color:var(--text); }
.heat-when input { width:150px; }
.heat-note { margin-top:0; }
.heat-rate { margin-top:4px; }
.heat-who { font-size:11.5px; line-height:1.4; margin-top:-2px; }
.heat-who:empty { display:none; }
.heat-exits { padding-top:6px; border-top:1px dashed var(--line); margin-top:2px; }
.heat-exits .chip { color:var(--subtle); }
.heat-exits .chip:hover { color:var(--text); }
.brief-heat { padding:12px 14px; border-bottom:1px solid var(--line); background:var(--panel-2); flex:0 0 auto; }
.ps-table td { vertical-align:top; }
.ps-table .ps-actions { white-space:nowrap; }
.ps-table tr.ps-due td:first-child { box-shadow:inset 3px 0 0 rgba(245,174,78,.8); }
.ps-due-row { display:flex; justify-content:space-between; align-items:center; gap:12px; padding:9px 0; border-top:1px solid var(--line); }
.ps-due-row:first-child { border-top:0; }
/* ---- an SOP written in the app ------------------------------------------ */
.sop-doc { max-width:78ch; padding:24px 28px; font-size:13.5px; line-height:1.62; }
.sop-doc h2 { font-size:15px; margin:26px 0 8px; letter-spacing:-.01em; display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.sop-doc h2:first-child { margin-top:0; }
.sop-who { font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--subtle);
  border:1px solid var(--line); border-radius:999px; padding:2px 9px; }
.sop-doc ol, .sop-doc ul { padding-left:22px; margin:6px 0 10px; }
.sop-doc li { margin:4px 0; }
.sop-why { border-left:3px solid var(--blue); background:var(--lift-1); padding:8px 12px; border-radius:0 10px 10px 0; margin:8px 0 12px; }
.sop-table { margin:8px 0 14px; }
.sop-table td, .sop-table th { vertical-align:top; }
.sop-dl dt { font-weight:700; margin-top:8px; }
.sop-dl dd { margin:2px 0 0 0; color:var(--muted); }
/* ---- the stage strip, pipeline and tags ---------------------------------- */
.brief-stage { padding:10px 14px; border-bottom:1px solid var(--line); flex:0 0 auto; }
.stage-bar { display:flex; flex-direction:column; gap:8px; }
.stage-row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.stage-strip { display:inline-flex; flex-wrap:wrap; gap:3px; }
.stage-step { font:inherit; font-size:11px; font-weight:650; padding:4px 9px; border:1px solid var(--line); border-radius:999px;
  background:transparent; color:var(--subtle); cursor:default; }
.stage-step.done { background:var(--lift-2); color:var(--muted); }
.stage-step.now { background:var(--blue-solid); border-color:var(--blue-solid); color:var(--on-accent); }
.stage-step.can { cursor:pointer; border-style:dashed; color:var(--blue); }
.stage-step.can:hover { background:color-mix(in srgb, var(--blue) 12%, transparent); }
.stage-step:disabled { opacity:.85; }
.tag-row { gap:6px; }
.tag-list { display:inline-flex; flex-wrap:wrap; gap:4px; }
.tag-chip { display:inline-flex; align-items:center; gap:4px; font-size:11px; font-weight:650; padding:3px 8px; border-radius:999px;
  background:rgba(139,92,246,.14); color:var(--ink-violet, #6d45c9); }
.tag-x { border:0; background:none; color:inherit; cursor:pointer; font-size:13px; line-height:1; padding:0 1px; opacity:.7; }
.tag-x:hover { opacity:1; }
.tag-add { width:110px; font-size:11.5px; padding:4px 8px; }
.stage-form { border:1px dashed var(--line); border-radius:10px; padding:10px 12px; background:var(--lift-1); }
/* ---- the board ------------------------------------------------------------ */
.board { display:flex; gap:12px; overflow-x:auto; padding-bottom:10px; align-items:flex-start; }
.board-col { flex:0 0 250px; background:var(--lift-1); border:1px solid var(--line); border-radius:14px; padding:10px; min-height:140px; }
.board-col.over { border-color:var(--blue); background:color-mix(in srgb, var(--blue) 8%, transparent); }
.board-col h4 { margin:0 0 8px; font-size:11px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--subtle);
  display:flex; justify-content:space-between; }
.board-col h4 b { color:var(--muted); }
.board-card { background:var(--panel); border:1px solid var(--line); border-radius:11px; padding:9px 11px; margin-bottom:8px; cursor:pointer; }
.board-card[draggable="true"] { cursor:grab; }
.board-card:hover { border-color:var(--blue-line); }
.board-card .bc-name { font-weight:700; font-size:13px; }
.board-card .bc-meta { color:var(--subtle); font-size:11px; margin-top:3px; }
.board-card .bc-tags { margin-top:5px; display:flex; flex-wrap:wrap; gap:3px; }
.board-card .bc-tags span { font-size:10px; padding:1px 6px; border-radius:999px; background:rgba(139,92,246,.14); color:var(--ink-violet, #6d45c9); }
.board-card.due { box-shadow:inset 3px 0 0 rgba(245,174,78,.9); }
.board-empty { color:var(--subtle); font-size:12px; text-align:center; padding:14px 0; }
.prospect-controls { border:1px solid var(--line); border-radius:14px; padding:12px 14px; background:var(--panel-2); }
/* ---- the workspace: list · thread · person ------------------------------- */
.ws { display:grid; grid-template-columns:300px minmax(0,1fr) 360px; gap:14px; height:calc(100vh - 150px); min-height:520px; }
.ws-list, .ws-person { border:1px solid var(--line); border-radius:14px; background:var(--panel); display:flex; flex-direction:column; min-height:0; }
.ws-list-head { display:flex; gap:6px; padding:10px; border-bottom:1px solid var(--line); }
/* The search takes the row; the window picker is a small thing beside it. */
.ws-list-head input { flex:1 1 auto; min-width:0; }
.ws-list-head #wsDays { flex:0 0 auto; width:auto; min-width:0; padding:6px 26px 6px 8px; font-size:12px; }
.ws-filters { display:flex; flex-wrap:wrap; gap:4px; padding:8px 10px 4px; }
.ws-stages { display:flex; flex-direction:column; padding:4px 6px 8px; border-bottom:1px solid var(--line); }
.ws-stage { font:inherit; font-size:11.5px; text-align:left; padding:4px 8px; border:0; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer;
  display:flex; justify-content:space-between; }
.ws-stage b { color:var(--subtle); font-weight:600; }
.ws-stage:hover { background:var(--lift-2); }
.ws-stage.active { background:color-mix(in srgb, var(--blue) 12%, transparent); color:var(--blue); }
.ws-people { flex:1; overflow-y:auto; min-height:0; scrollbar-width:thin; }
.ws-row { display:block; width:100%; text-align:left; font:inherit; padding:9px 12px; border:0; border-bottom:1px solid var(--line); background:transparent; color:var(--text); cursor:pointer; }
.ws-row:hover { background:var(--lift-1); }
.ws-row.active { background:color-mix(in srgb, var(--blue) 10%, transparent); box-shadow:inset 3px 0 0 var(--blue); }
.ws-row.waiting .ws-row-name::before { content:""; display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--amber, #f5ae4e); margin-right:6px; vertical-align:middle; }
.ws-row-top { display:flex; justify-content:space-between; gap:8px; }
.ws-row-name { font-weight:700; font-size:13px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws-row-when { color:var(--subtle); font-size:11px; flex:0 0 auto; }
.ws-row-prev { color:var(--muted); font-size:12px; margin-top:2px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws-row-meta { display:flex; align-items:center; gap:5px; margin-top:5px; flex-wrap:wrap; }
.ws-row-meta .heat-stars.ro .heat-star { font-size:12px; }
.ws-pill { font-size:10px; font-weight:700; letter-spacing:.03em; padding:2px 7px; border-radius:999px; background:var(--lift-2); color:var(--muted); }
.ws-pill.s-booked, .ws-pill.s-client { background:rgba(53,201,143,.16); color:var(--green); }
/* A past client reads as a client, quieter: they are not in coaching now. */
.ws-pill.s-past_client { background:color-mix(in srgb, var(--green) 10%, var(--lift-2)); color:var(--muted); }
.ws-pill.s-pitched { background:color-mix(in srgb, var(--blue) 14%, transparent); color:var(--blue); }
.ws-pill.s-held, .ws-pill.s-follow_up { background:rgba(245,174,78,.18); color:var(--ink-warn, #b7791f); }
.ws-tag { font-size:10px; padding:1px 6px; border-radius:999px; background:rgba(139,92,246,.14); color:var(--ink-violet, #6d45c9); }
/* The ad keyword they came in on: the first DM, in the ad's own capitals. */
/* The word they DM'd. A button, because clicking it is the quickest way to
   see everyone who sent the same one. */
.ws-kw { font:inherit; font-size:9.5px; font-weight:800; letter-spacing:.04em; padding:1px 6px; border-radius:5px;
  border:1px solid transparent; background:var(--tint-amber); color:var(--ink-warn); cursor:pointer; }
.ws-kw:hover { border-color:color-mix(in srgb, var(--ink-warn) 45%, transparent); }
.ws-kw.on { background:var(--ink-warn); color:var(--panel); }
.ws-kw.unmatched { background:var(--lift-2); color:var(--muted); }
.ws-kw.unmatched:hover { border-color:var(--line-strong); }
.ws-kw.unmatched.on { background:var(--subtle); color:var(--panel); }
/* The keyword rail: one line each, the count on the right, and the tail
   behind one click so fifty-seven words never push the buckets off screen. */
.ws-rail-item.kw span u { text-decoration:none; font-weight:650; letter-spacing:.02em; }
.ws-rail-group .ws-rail-item.kw.active { background:var(--tint-amber); color:var(--ink-warn); }
.ws-rail-group .ws-rail-item.kw.active b { color:var(--ink-warn); }
.ws-rail-item.kw b.zero { opacity:.45; }
.ws-rail-more { display:block; width:100%; font:inherit; font-size:11px; font-weight:650; text-align:left;
  padding:5px 8px; margin-top:2px; border:0; border-radius:8px; background:transparent; color:var(--blue); cursor:pointer; }
.ws-rail-more:hover { background:var(--lift-2); }
/* The hooks that stopped bringing anyone: still reachable, not in the way. */
.ws-kw-older { width:100%; margin-top:4px; font:inherit; font-size:11.5px; color:var(--muted);
  padding:5px 26px 5px 8px; border:1px solid var(--line); border-radius:8px; background:var(--panel);
  background-image:var(--select-arrow); background-repeat:no-repeat;
  background-position:right 8px center; appearance:none; cursor:pointer; }
.ws-kw-older:hover { border-color:var(--line-strong); color:var(--text); }
/* The keyword in the list's sub-head, with its own way out. */
.ws-sub-kw { font:inherit; font-size:10.5px; font-weight:800; letter-spacing:.04em; padding:1px 6px;
  border:0; border-radius:5px; background:var(--tint-amber); color:var(--ink-warn); cursor:pointer; }
.ws-sub-kw:hover { background:var(--ink-warn); color:var(--panel); }
.ws-thread { display:flex; flex-direction:column; min-height:0; min-width:0; }
.ws-empty { padding:22px 24px; border:1px solid var(--line); border-radius:14px; background:var(--panel); overflow-y:auto; }
.ws-empty h3 { margin:0 0 4px; }
.ws-thread-inner { display:flex; flex-direction:column; min-height:0; height:100%; border:1px solid var(--line); border-radius:14px; background:var(--panel); }
.ws-thread-head { display:flex; justify-content:space-between; align-items:center; gap:10px; padding:10px 14px; border-bottom:1px solid var(--line); }
/* The thread wears the internal inbox's clothes (.msg-log / .msg-turn / .msg-bubble). */
.ws-timeline { flex:1; max-height:none; border:0; border-radius:0; background:var(--panel); padding:22px 18px; gap:14px; }
.ws-timeline .msg-turn { max-width:76%; }
.ws-timeline .msg-time { display:flex; align-items:center; gap:6px; }
.msg-chan { display:inline-flex; align-items:center; gap:4px; }
/* What became of an outbound message: only a failure or a read receipt says anything. */
.msg-state { margin-left:6px; color:var(--subtle); }
.msg-state.bad { color:var(--red); font-weight:700; }
.msg-chan .ch-ico { --ch:11px; }
.msg-turn .msg-bubble .tl-atts { margin-top:8px; }
.msg-turn .msg-bubble.has-att { min-width:min(292px, 100%); }
.msg-turn.mine .msg-bubble .mail-subject { border-bottom-color:rgba(255,255,255,.35); }
.msg-turn.mine .msg-bubble .mail-subject .ch-ico { color:#fff; }
.msg-turn.theirs .msg-bubble .mail-subject .ch-ico { color:var(--blue); }
.msg-turn.mine .msg-bubble .tl-att-link { color:#fff; }
.ws-event span { text-transform:none; letter-spacing:0; font-weight:600; }
.ws-compose { border-top:1px solid var(--line); padding:10px 12px; }
.ws-compose textarea { width:100%; resize:none; min-height:56px; max-height:220px; line-height:1.45; }
.ws-compose-row { display:flex; justify-content:space-between; align-items:center; gap:10px; margin-top:6px; flex-wrap:wrap; }
.ws-person-scroll { overflow-y:auto; padding:12px; min-height:0; scrollbar-width:thin; }
.ws-h { margin:0 0 6px; font-size:10.5px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; color:var(--subtle); }
.ws-call { border:1px solid var(--line); border-radius:11px; padding:9px 11px; margin-bottom:8px; background:var(--lift-1); font-size:12.5px; }
.ws-call-top { display:flex; justify-content:space-between; gap:8px; }
.ws-call .confirm-row { margin-top:8px; }
@media (max-width: 1100px) { .ws { grid-template-columns:260px minmax(0,1fr); } .ws-person { grid-column:1 / -1; height:auto; } }
@media (max-width: 760px) { .ws { grid-template-columns:1fr; height:auto; } .ws-list { max-height:40vh; } }
/* ---- the inbox, four columns --------------------------------------------- */
.ws4 { display:grid; grid-template-columns:236px 320px minmax(0,1fr) 360px; gap:0; height:calc(100vh - 118px); min-height:560px;
  border:1px solid var(--line); border-radius:14px; background:var(--panel); overflow:hidden; }
.ws-rail { border-right:1px solid var(--line); background:var(--panel-2); overflow-y:auto; padding:10px 8px; scrollbar-width:thin; }
.ws-rail-head { display:flex; justify-content:space-between; align-items:baseline; padding:4px 8px 8px; font-size:15px; }
.ws-rail-title { font-size:10px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color:var(--subtle); padding:12px 8px 4px; display:flex; justify-content:space-between; gap:6px; }
/* A hairline above each section title: Team, Stages, Buckets read as three
   groups rather than one long list. */
.ws-rail-group + .ws-rail-title { margin-top:8px; border-top:1px solid var(--line); padding-top:12px; }
.ws-rail-title .helper { font-weight:500; letter-spacing:0; text-transform:none; font-size:10px; }
/* A section that folds: the title is the control. Stages never fold -- they
   are the job -- so only Clients, Keywords and Buckets carry this. */
.ws-fold { align-items:center; width:100%; font:inherit; font-size:10px; font-weight:800; letter-spacing:.08em;
  text-transform:uppercase; color:var(--subtle); text-align:left; border:0; background:transparent; cursor:pointer; }
.ws-fold:hover { color:var(--text); }
.ws-fold .ws-fold-name { flex:0 0 auto; }
.ws-fold .helper { flex:1 1 auto; min-width:0; text-align:right; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws-fold-chev { flex:0 0 auto; margin-right:5px; transition:transform .14s ease; color:var(--subtle); }
.ws-fold.shut .ws-fold-chev { transform:rotate(-90deg); }
/* What the section is holding while it is shut, so nothing disappears quietly. */
.ws-fold-n { flex:0 0 auto; margin-left:6px; padding:1px 6px; border-radius:999px; font-size:10px; font-weight:800;
  letter-spacing:0; background:var(--lift-2); color:var(--muted); }
.ws-fold-n[hidden] { display:none; }
.ws-rail-group { display:flex; flex-direction:column; gap:1px; }
.ws-rail-item { display:flex; justify-content:space-between; align-items:center; gap:8px; width:100%; font:inherit; font-size:12.5px; text-align:left;
  padding:6px 8px; border:1px solid transparent; border-radius:8px; background:transparent; color:var(--muted); cursor:pointer; }
.ws-rail-item span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws-rail-item span i { font-style:normal; display:inline-block; width:16px; color:var(--subtle); font-size:10.5px; }
.ws-rail-item b { font-weight:600; color:var(--subtle); font-size:11px; font-variant-numeric:tabular-nums; }
/* Stages: number · emoji · name in three columns, so a long name wraps
   under itself rather than under the number, and the count is a pill. */
.ws-rail-item.stage { align-items:flex-start; }
.ws-rail-item.stage span { display:grid; grid-template-columns:22px minmax(0,1fr); align-items:baseline; white-space:normal; overflow:hidden; flex:1 1 auto; min-width:0; }
.ws-rail-item.stage > b { flex:0 0 auto; }
.ws-rail-item.stage span i { width:auto; font-size:12px; font-weight:800; color:var(--text); font-variant-numeric:tabular-nums; }
.ws-rail-item.stage span i.em { font-size:13px; font-weight:400; line-height:1; }
.ws-rail-item:not(.stage) span { display:flex; flex-direction:column; white-space:normal; overflow:visible; }
.ws-rail-item:not(.stage) span u { text-decoration:none; }
.ws-rail-item:not(.stage) span small { color:var(--subtle); font-size:10.5px; line-height:1.2; font-weight:500; }
.ws-rail-item.stage.active span i { color:var(--blue); }
.ws-rail-item.stage span u { text-decoration:none; line-height:1.3; }
.ws-rail-item.stage span small { grid-column:1 / -1; padding-left:22px; font-size:10.5px; color:var(--subtle); font-weight:500; line-height:1.25; margin-top:-1px; }
.ws-rail-item.stage b { min-width:22px; padding:1px 5px; border-radius:999px; text-align:center; background:var(--lift-2); color:var(--text); font-size:11px; font-weight:750; }
.ws-rail-item.stage b.zero { background:transparent; color:var(--subtle); font-weight:600; min-width:0; padding:1px 2px; }
.ws-rail-item.stage b.fresh { background:var(--red); color:#fff; margin-right:-3px; white-space:nowrap; font-size:10.5px; min-width:20px; padding:1px 5px; }
.ws-rail-item.stage.active b.fresh { background:var(--red); color:#fff; }
/* A long stage name ("Closed deal / client") shortens rather than wraps
   under its counts, and the emoji keeps its column. */
.ws-rail-item.stage span u { white-space:nowrap; overflow:hidden; text-overflow:ellipsis; display:block; min-width:0; }
/* NEW sits beside the name, in the top line, never over the preview. */
.ws-new { flex:0 0 auto; margin-left:6px; margin-right:auto; font-size:8.5px; font-weight:800; letter-spacing:.06em; padding:2px 5px; border-radius:4px;
  background:var(--red); color:#fff; line-height:1.1; align-self:center; }
.ws-row-top .ws-row-name { flex:0 1 auto; min-width:0; }
.ws-row-top .ws-row-when { margin-left:auto; }
.ws-rail-item.stage.active b { background:color-mix(in srgb, var(--blue) 16%, transparent); color:var(--blue); }
.ws-rail-item:hover { background:var(--lift-2); color:var(--text); }
.ws-rail-item.active { background:color-mix(in srgb, var(--blue) 12%, transparent); color:var(--blue); }
.ws-rail-item.active b { color:var(--blue); }
.ws-rail-item.over { border-color:var(--blue); background:color-mix(in srgb, var(--blue) 14%, transparent); color:var(--blue); }
.ws-list { border-right:1px solid var(--line); display:flex; flex-direction:column; min-height:0; }
/* The team row: All, then an avatar a person, a ring on the one picked. */
/* The quick reference. */
.ws-help-btn { width:28px; height:28px; padding:0; border-radius:50%; font-weight:800; flex:0 0 auto; }
.ws-help-btn.active { background:color-mix(in srgb, var(--blue) 16%, transparent); border-color:color-mix(in srgb, var(--blue) 50%, transparent); color:var(--blue); }
/* Until somebody has opened the guide once, the ? breathes. Then it is a ?. */
.ws-help-btn.unseen { animation:guideBreathe 2.2s ease-in-out infinite; border-color:var(--blue-line); color:var(--blue); }
@keyframes guideBreathe { 0%, 100% { box-shadow:0 0 0 0 color-mix(in srgb, var(--blue) 35%, transparent); } 50% { box-shadow:0 0 0 6px transparent; } }
@media (prefers-reduced-motion: reduce) { .ws-help-btn.unseen { animation:none; } }

/* The guide, beside the page. The same panel the Brain uses, so it sits
   where every side panel sits, and the workspace shrinks to make room rather
   than being covered. */
.ws-guide { width:min(400px, 100vw); }
@media (min-width:1100px) { body.guide-open main, body.ws-page.guide-open main { padding-right:412px; } }
.ws-guide-q { display:inline-grid; place-items:center; width:22px; height:22px; border-radius:50%; font-weight:800; font-size:13px;
  background:color-mix(in srgb, var(--blue) 16%, transparent); color:var(--blue); }
.ws-guide-find { padding:10px 14px; border-bottom:1px solid var(--line); flex:0 0 auto; }
.ws-guide-find input { width:100%; font:inherit; font-size:13px; padding:8px 12px; border:1px solid var(--line); border-radius:10px;
  background:var(--field); color:var(--text); }
.ws-guide-find input:focus { outline:none; border-color:var(--blue); }
.ws-guide-body { flex:1 1 auto; min-height:0; overflow-y:auto; padding:14px 16px 28px; scrollbar-width:thin; }
.ws-guide-intro { margin:0 0 12px; font-size:13px; line-height:1.55; color:var(--muted); }
.ws-guide-toc { display:flex; flex-wrap:wrap; gap:5px; margin:0 0 16px; }
.ws-guide-toc a { font-size:11.5px; font-weight:650; text-decoration:none; color:var(--muted); padding:4px 9px; border-radius:999px;
  border:1px solid var(--line); background:var(--lift-1); }
.ws-guide-toc a:hover { color:var(--blue); border-color:var(--blue-line); }
.ws-guide-toc[hidden] { display:none; }
.ws-guide-sec { padding:12px 0 6px; border-top:1px solid var(--line); scroll-margin-top:8px; }
.ws-guide-sec:first-of-type { border-top:0; }
.ws-guide-sec[hidden] { display:none; }
.ws-guide-sec h4 { display:flex; align-items:center; justify-content:space-between; gap:10px; margin:0 0 6px;
  font-size:12px; font-weight:800; letter-spacing:.02em; color:var(--text); }
.ws-guide-sec p, .ws-guide-sec li { margin:0 0 9px; font-size:12.5px; line-height:1.6; color:var(--muted); }
.ws-guide-sec li { margin-bottom:5px; }
.ws-guide-sec ul, .ws-guide-sec ol { margin:0 0 8px; padding-left:20px; }
.ws-guide-sec b { color:var(--text); font-weight:650; }
.ws-guide-sec i { color:var(--text); font-style:normal; font-weight:600; }
.ws-guide-show { flex:0 0 auto; font:inherit; font-size:10.5px; font-weight:700; padding:2px 8px; border-radius:999px;
  border:1px solid var(--blue-line); background:transparent; color:var(--blue); cursor:pointer; }
.ws-guide-show:hover { background:var(--tint-blue); }
.ws-guide-none { font-size:12.5px; color:var(--muted); padding:16px 0; }
/* "Show me": the thing the section is about, ringed for a moment. */
.guide-ring { animation:guideRing 2.6s ease-out; border-radius:10px; }
@keyframes guideRing { 0% { box-shadow:0 0 0 0 color-mix(in srgb, var(--blue) 70%, transparent); }
  30% { box-shadow:0 0 0 5px color-mix(in srgb, var(--blue) 55%, transparent); }
  100% { box-shadow:0 0 0 12px transparent; } }
/* On a phone the guide is the screen, over the thread, like the other sheets. */
@media (max-width:700px) { .ws-guide { width:100vw; top:0; padding-top:env(safe-area-inset-top, 0px); } .ws-guide-show { display:none; } }
/* The printable page. */
.help-doc section { scroll-margin-top:20px; }
.help-toc { display:flex; flex-wrap:wrap; gap:6px; margin:0 0 18px; }
.help-toc a { font-size:12px; font-weight:650; text-decoration:none; color:var(--muted); padding:5px 10px; border-radius:999px; border:1px solid var(--line); }
.help-toc a:hover { color:var(--blue); border-color:var(--blue-line); }
@media print { .help-toc, .topbar, .sidebar, .page-heading .action-row, .tabbar { display:none !important; } }
.ws-team { display:flex; align-items:center; gap:6px; padding:7px 12px 5px; border-bottom:1px solid var(--line); overflow-x:auto; scrollbar-width:none; }
.ws-team::-webkit-scrollbar { display:none; }
.ws-team-all { flex:0 0 auto; border:1px solid var(--line); background:transparent; color:var(--muted); font:inherit; font-size:10.5px; font-weight:700;
  padding:0 9px; height:26px; border-radius:13px; cursor:pointer; }
.ws-team-all.on { border-color:var(--blue); color:var(--blue); background:var(--tint-blue); }
.ws-team-one { flex:0 0 auto; position:relative; border:0; background:transparent; padding:0; cursor:pointer; border-radius:50%; opacity:.72;
  transition:opacity .12s ease, transform .12s ease; }
.ws-team-one .ws-avatar { width:26px; height:26px; flex-basis:26px; font-size:10px; box-shadow:0 0 0 2px var(--panel); }
.ws-team-one:hover { opacity:1; transform:translateY(-1px); }
.ws-team-one.on { opacity:1; }
.ws-team-one.on .ws-avatar { box-shadow:0 0 0 2px var(--panel), 0 0 0 4px var(--blue); }
.ws-team-one b { position:absolute; top:-4px; right:-6px; min-width:15px; height:15px; padding:0 4px; border-radius:8px; background:var(--panel-2);
  border:1px solid var(--line); color:var(--muted); font-size:9px; font-weight:750; line-height:13px; text-align:center; font-variant-numeric:tabular-nums; }
.ws-team-one.on b { background:var(--blue); border-color:var(--blue); color:#fff; }
.ws-list-sub { padding:6px 12px; font-size:11px; color:var(--subtle); border-bottom:1px solid var(--line);
  display:flex; align-items:center; justify-content:space-between; gap:8px; }
/* All · Unread · Read, on top of whatever else is picked. */
.ws-read-seg { display:inline-flex; gap:2px; padding:2px; border-radius:999px; background:var(--lift-1); border:1px solid var(--line); }
.ws-read-seg button { border:0; background:transparent; font:inherit; font-size:10.5px; font-weight:650; color:var(--subtle);
  padding:2px 8px; border-radius:999px; cursor:pointer; }
.ws-read-seg button b { font-weight:800; }
.ws-read-seg button.on { background:var(--panel); color:var(--text); box-shadow:var(--shadow-sm); }
.ws-row.unread .ws-row-name { font-weight:800; }
.ws-row.unread .ws-row-prev { color:var(--text); }
.ws-row-unread { position:absolute; right:10px; top:10px; width:22px; height:22px; border-radius:6px; border:0;
  background:var(--panel); color:var(--subtle); display:grid; place-items:center; opacity:0; cursor:pointer;
  transition:opacity .12s ease; box-shadow:var(--shadow-sm); }
.ws-row:hover .ws-row-unread { opacity:1; }
.ws-row:hover .ws-row-when { visibility:hidden; }   /* the time yields to the button, same corner */
.ws-row-unread:hover { color:var(--blue); }
@media (hover:none) { .ws-row-unread { opacity:.5; } }
.ws-row { display:flex; gap:10px; align-items:flex-start; padding:10px 12px; border-bottom:1px solid var(--line); cursor:pointer; position:relative; }
.ws-row[draggable="true"] { cursor:grab; }
.ws-row:hover { background:var(--lift-1); }
.ws-row.active { background:color-mix(in srgb, var(--blue) 10%, transparent); box-shadow:inset 3px 0 0 var(--blue); }
.ws-row.waiting .ws-row-name { font-weight:800; }
.ws-row-body { flex:1; min-width:0; }
.ws-row-name::before { content:none; }
/* "They spoke last": a dot on the avatar's shoulder, where nothing else
   lives -- in the corner it sat on top of the channel icon. */
.ws-dot { position:absolute; left:39px; top:8px; width:9px; height:9px; border-radius:50%; background:#e5484d; box-shadow:0 0 0 2px var(--panel); }
.ws-row.active .ws-dot { box-shadow:0 0 0 2px var(--panel); }
.ws-chan { color:var(--subtle); font-size:11px; margin-left:auto; }
.ws-avatar { --hue:212; display:inline-grid; place-items:center; width:34px; height:34px; border-radius:50%; flex:0 0 34px; font-size:12px; font-weight:800;
  color:hsl(var(--hue) 55% 32%); background:hsl(var(--hue) 70% 90%); }
.ws-avatar.big { width:44px; height:44px; flex-basis:44px; font-size:15px; }
.ws-thread-head { display:flex; align-items:center; gap:10px; padding:10px 14px; border-bottom:1px solid var(--line); }
.ws-thread-name { font-size:14px; display:flex; gap:8px; align-items:center; }
.min0 { min-width:0; }
.tl-turn.them { flex-direction:row; align-items:flex-end; gap:8px; max-width:82%; }
.tl-turn.them .ws-avatar { width:26px; height:26px; flex-basis:26px; font-size:10px; }
.tl-col { display:flex; flex-direction:column; min-width:0; }
.tl-turn.them .tl-col { align-items:flex-start; }
.ws-compose-top { display:flex; align-items:center; justify-content:space-between; gap:8px; margin-bottom:6px; flex-wrap:wrap; }
.ws-compose-top .ws-channels { margin-bottom:0; }
.ws-compose-tabs { display:flex; gap:4px; }
.ws-tab { font:inherit; font-size:12px; font-weight:700; padding:4px 10px; border:0; border-radius:8px; background:transparent; color:var(--subtle); cursor:pointer; }
.ws-tab.active { background:var(--lift-2); color:var(--text); }
/* The framework's next line: one strip above the reply box. Ellipsised
   until clicked, so the thread keeps its height; opens to the full text
   and, with Teach it, the box to correct it. */
.ws-next { margin-bottom:6px; padding:5px 6px 5px 10px; border:1px dashed color-mix(in srgb, var(--blue) 45%, transparent); border-radius:10px; background:color-mix(in srgb, var(--blue) 6%, transparent);
  display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.ws-next-text { font:inherit; font-size:12px; color:var(--text); background:none; border:0; padding:0; cursor:pointer; text-align:left;
  flex:1 1 0; min-width:120px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.ws-next.open .ws-next-text { white-space:normal; flex-basis:100%; line-height:1.5; }
.ws-next-text b { color:var(--blue); }
.ws-next-acts { display:flex; gap:4px; flex:0 0 auto; }
.ws-next .ws-teach { flex-basis:100%; }
.ws-card { border-left:1px solid var(--line); min-height:0; display:flex; flex-direction:column; }
.ws-card-top { display:none; align-items:center; justify-content:space-between; padding:10px 14px;
  border-bottom:1px solid var(--line); background:var(--panel-2); font-size:13px; }
/* Details: a sheet on a phone, a column that folds on a desk. Lit while the
   column is out, so the chip says which state you are in. */
.ws-card-btn { display:inline-flex; align-items:center; gap:4px; }
.ws-card-btn .ws-card-chev { transition:transform .14s ease; }
.ws4.cardless .ws-card-btn .ws-card-chev { transform:rotate(180deg); }
/* Up and down only. A long GHL tag list or an email address wraps; the card
   never grows a sideways scrollbar. */
.ws-card-scroll { overflow-y:auto; overflow-x:hidden; padding:12px; scrollbar-width:thin; }
.ws-card-id { display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.ws-card-id b { font-size:14px; display:block; }
.ws-sec { border-top:1px solid var(--line); padding:8px 0; }
.ws-sec summary { cursor:pointer; font-size:10.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--subtle); list-style:none; padding:4px 0; }
.ws-sec summary::-webkit-details-marker { display:none; }
.ws-sec summary::before { content:"▸ "; }
.ws-sec[open] summary::before { content:"▾ "; }
.ws-sec > div { padding-top:6px; }
.ws-stage-now { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.ws-read { font-size:12.5px; line-height:1.5; margin:6px 0 0; }
.ws-kv { font-size:12px; border-collapse:collapse; width:100%; min-width:0; table-layout:fixed; }   /* the global table min-width is for data tables, not a 300px card */
.ws-kv td { padding:2px 8px 2px 0; vertical-align:top; overflow-wrap:anywhere; white-space:normal; border-bottom:0; color:var(--text); }
.ws-kv td:first-child { color:var(--subtle); white-space:nowrap; width:84px; }
.ws-kv .tag-list { gap:3px; }
.tag-chip.sug { background:var(--lift-2); color:var(--muted); }
/* GoHighLevel's own tags, told apart from ours: no colour, no remove. */
.tag-chip.ghl { background:transparent; border:1px solid var(--line); color:var(--muted); font-weight:600; padding:2px 7px; }
.ws-notes { font-size:12.5px; line-height:1.5; white-space:pre-wrap; overflow-wrap:anywhere; color:var(--text); }
/* A file in a team note: a picture as a thumbnail, anything else as its name. */
.ws-note-img { display:inline-block; margin:2px 0; }
.ws-note-img img { display:block; max-width:180px; max-height:140px; border-radius:8px; border:1px solid var(--line); }
.ws-note-file { color:var(--blue); }
.ws-notes-add { margin-top:6px; }
/* The workspace page: the window is the workspace. The tab strip is a size
   down and sits close under the top bar, the side margins go, and nothing is
   left below the grid for the page to scroll to. */
body.ws-page main { padding:0 12px 0; }
body.ws-page .subnav { margin:8px 0 0; padding:3px; }
body.ws-page .subnav-tab { padding:5px 12px; font-size:12.5px; }
body.ws-page .page { max-width:none; padding-top:10px; }
body.ws-page .app-footer { display:none; }
.ws-pill.s-connect, .ws-pill.s-goal, .ws-pill.s-situation, .ws-pill.s-urgency, .ws-pill.s-money, .ws-pill.s-needs { background:color-mix(in srgb, var(--blue) 10%, transparent); color:var(--blue); }
.ws-pill.s-soft_pitch, .ws-pill.s-invited, .ws-pill.s-book_it { background:rgba(139,92,246,.14); color:var(--ink-violet, #6d45c9); }
.ws-pill.s-quiet, .ws-pill.s-dead, .ws-pill.s-other, .ws-pill.s-dq, .ws-pill.s-vendor, .ws-pill.s-fitpro, .ws-pill.s-personal, .ws-pill.s-spam { background:var(--lift-2); color:var(--subtle); }
/* Move to… opens a strip: where, one line on why, the tick. */
.ws-move { display:flex; flex-direction:column; gap:6px; margin-top:8px; padding:8px 10px; border:1px solid var(--line); border-radius:10px; background:var(--lift-1); }
.ws-move-to { font-size:12.5px; color:var(--muted); }
.ws-help-red { color:#fff; background:var(--red); border-radius:999px; padding:0 6px; font-size:11px; }
.ws-move-to b { color:var(--text); font-weight:700; }
.ws-move input { width:100%; font:inherit; font-size:12.5px; padding:6px 8px; border:1px solid var(--line); border-radius:8px; background:var(--panel); color:var(--text); }
.ws-move input:focus { outline:none; border-color:var(--blue); }
.ws-pill.s-no_close { background:rgba(245,174,78,.18); color:var(--ink-warn, #b7791f); }
/* Details, folded away: the conversation takes the column back. The chip in
   the thread's header brings it out again, and the choice is remembered. */
:is(.ws4.cardless, .ws4.guide-fold) .ws-card { display:none; }
:is(.ws4.cardless, .ws4.guide-fold) { grid-template-columns:236px 320px minmax(0,1fr); }
@media (max-width: 1560px) { .ws4 { grid-template-columns:212px 262px minmax(0,1fr) 330px; }
  :is(.ws4.cardless, .ws4.guide-fold) { grid-template-columns:212px 262px minmax(0,1fr); } }
@media (max-width: 1280px) { .ws4 { grid-template-columns:190px 240px minmax(0,1fr) 300px; }
  :is(.ws4.cardless, .ws4.guide-fold) { grid-template-columns:190px 240px minmax(0,1fr); } }
@media (max-width: 1100px) { .ws4 { grid-template-columns:180px 260px minmax(0,1fr); height:auto; } .ws-card { grid-column:1 / -1; border-left:0; border-top:1px solid var(--line); } }
@media (max-width: 760px) { .ws4 { grid-template-columns:1fr; } .ws-rail, .ws-list { border-right:0; border-bottom:1px solid var(--line); max-height:40vh; } }
.ws-row.waiting .ws-row-name::before { content:none; }
.ws-channels { display:flex; align-items:center; gap:5px; flex-wrap:wrap; margin-bottom:6px; }
.ws-channels .chip:disabled { opacity:.45; cursor:not-allowed; }
.ws-chanbar { display:grid; grid-template-columns:repeat(4, 1fr); gap:4px; padding:8px 10px 6px; border-bottom:1px solid var(--line); }
.ws-chanbtn { font:inherit; font-size:12px; font-weight:700; padding:8px 4px; border:1px solid var(--line); border-radius:10px; background:var(--lift-1);
  color:var(--muted); cursor:pointer; display:flex; flex-direction:column; align-items:center; gap:2px; line-height:1.1; }
.ws-chanbtn b { font-size:11px; font-weight:600; color:var(--subtle); }
.ws-chanbtn:hover { background:var(--lift-2); color:var(--text); }
.ws-chanbtn.active { background:color-mix(in srgb, var(--blue) 14%, transparent); border-color:color-mix(in srgb, var(--blue) 50%, transparent); color:var(--blue); }
.ws-chanbtn.active b { color:var(--blue); }
.ws-from { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.ws-teach textarea { width:100%; }

/* Channel glyphs (common.js chanIcon): one colour per channel, Instagram's
   magenta, a text-message green, the app's blue for email, so a row or a
   bubble reads at a glance. */
.ch-ico { --ch:14px; display:inline-flex; width:var(--ch); height:var(--ch); vertical-align:-2px; flex:0 0 auto; }
.ch-ico svg { width:100%; height:100%; fill:none; stroke:currentColor; stroke-width:2.1; stroke-linecap:round; stroke-linejoin:round; }
/* Colour lives on the glyph only -- never on a bubble's words. */
.ch-ico.ch-ig { color:#d6336c; } .ch-ico.ch-sms { color:#2f9e5e; } .ch-ico.ch-email { color:#4387f5; }
.ch-ico.ch-fb { color:#1877f2; } .ch-ico.ch-wa { color:#25a55f; } .ch-ico.ch-call { color:#8b5cf6; } .ch-ico.ch-chat { color:#f59e0b; } .ch-ico.ch-all { color:var(--muted); }
.ws-chanbtn { flex-direction:row; flex-wrap:wrap; justify-content:center; gap:4px 6px; padding:8px 6px; }
.ws-chanbtn .ch-ico { --ch:15px; }
.ws-chanbtn b { flex-basis:100%; text-align:center; }
.ws-chan { margin-left:auto; display:inline-flex; }
.ws-channels .chip { display:inline-flex; align-items:center; gap:5px; }
.tl-meta { display:flex; align-items:center; gap:5px; }
.tl-meta .ch-ico { --ch:12px; }
/* Our bubbles wear the channel: Instagram's gradient, text-message blue, and
   an email as a card with its subject line. Theirs stay plain; the line
   under each says the channel. */
.tl-turn.us .tl-bubble.ch-sms { background:var(--blue-solid); }
.tl-turn .tl-bubble.mail { background:var(--panel); color:var(--text); border:1px solid var(--line); border-radius:12px; min-width:min(280px, 100%); }
.tl-turn.us .tl-bubble.mail { border-color:color-mix(in srgb, var(--blue) 50%, transparent); box-shadow:inset 3px 0 0 color-mix(in srgb, var(--blue) 60%, transparent); border-bottom-right-radius:12px; }
.tl-turn.them .tl-bubble.mail { border-bottom-left-radius:12px; }
.mail-subject { display:flex; align-items:center; gap:6px; font-weight:700; padding-bottom:6px; margin-bottom:6px; border-bottom:1px solid var(--line); }

/* Playbook: the setter-training card. Four tiles, one per entry the AI reads. */
.train-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(200px, 1fr)); gap:10px; }
.train-tile { font:inherit; text-align:left; border:1px solid var(--line); border-radius:12px; background:var(--lift-1); padding:12px 14px; cursor:pointer; color:var(--text);
  display:flex; flex-direction:column; gap:4px; transition:background .14s ease, border-color .14s ease, transform .14s ease; }
.train-tile:hover { background:var(--lift-2); border-color:var(--line-strong); transform:translateY(-1px); }
.train-role { font-size:10.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--blue); }
.train-title { font-size:13px; font-weight:700; }
.train-n { font-size:11px; font-weight:650; color:var(--muted); margin-top:2px; }

/* A person found by a word inside a message, not by name. */
.ws-row.hit .ws-row-prev { color:var(--text); }
.ws-row.hit mark { background:rgba(245,158,11,.28); color:inherit; border-radius:3px; padding:0 1px; }
.ws-row.hit .ws-row-prev { white-space:normal; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }

/* Nobody open: the thread and the person fold away; the list is the page.
   Rows go wide -- name and time on the left, two lines of the last message,
   stage, heat and tags on the right -- and a slim strip of numbers sits in
   the head. Opening someone brings the four columns back. */
.ws4.nobody { grid-template-columns:236px minmax(0,1fr); }
.ws4.nobody .ws-thread, .ws4.nobody .ws-card { display:none; }
.ws4.nobody .ws-list { border-right:0; }
.ws4.nobody .ws-list-head { flex-wrap:wrap; }
.ws4.nobody #wsSearch { max-width:none; }
.ws-strip { display:none; }
.ws4.nobody .ws-strip { display:flex; gap:6px; flex-wrap:wrap; margin-left:auto; }
.ws-stat { font:inherit; font-size:11.5px; font-weight:600; color:var(--muted); border:1px solid var(--line); border-radius:999px; background:var(--lift-1); padding:5px 10px; cursor:pointer; }
.ws-stat b { color:var(--text); font-weight:800; font-variant-numeric:tabular-nums; }
.ws-stat:hover { background:var(--lift-2); color:var(--text); }
.ws-stat.active { background:color-mix(in srgb, var(--blue) 14%, transparent); border-color:color-mix(in srgb, var(--blue) 50%, transparent); color:var(--blue); }
.ws-stat.active b { color:var(--blue); }
.ws4.nobody .ws-chanbar { grid-template-columns:repeat(4, minmax(120px, 150px)); }
.ws4.nobody .ws-row { padding:10px 16px; }
.ws4.nobody .ws-row-body { display:grid; grid-template-columns:minmax(160px, 220px) minmax(0, 1fr) auto; column-gap:16px; align-items:center; }
.ws4.nobody .ws-row-top { flex-direction:column; align-items:flex-start; gap:1px; min-width:0; }
.ws4.nobody .ws-row-name { max-width:100%; }
.ws4.nobody .ws-row-prev { margin-top:0; white-space:normal; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; line-height:1.4;
  overflow-wrap:anywhere; }   /* a pasted Instagram link is one long word; without this it ran out of the row instead of wrapping */
.ws4.nobody .ws-row-meta { margin-top:0; justify-content:flex-end; flex-wrap:nowrap; }
.ws4.nobody .ws-row-meta .ws-tag { max-width:120px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws4.nobody .ws-dot { left:43px; top:8px; }
@media (max-width: 1100px) {
  .ws4.nobody .ws-row-body { grid-template-columns:minmax(140px, 180px) minmax(0, 1fr); }
  .ws4.nobody .ws-row-meta { grid-column:1 / -1; justify-content:flex-start; flex-wrap:wrap; margin-top:4px; }
}
@media (max-width: 760px) { .ws4.nobody { grid-template-columns:1fr; } .ws4.nobody .ws-list { max-height:none; } }
.bside-ctx { font-size:11.5px; color:var(--blue); font-weight:650; margin:0 0 6px; }

/* Voice memos in the reply box: a red dot and a clock while recording, a
   player and Send once stopped. */
.ws-memo { border:1px solid var(--line); border-radius:12px; background:var(--lift-1); padding:8px 10px; margin-bottom:6px; }
.ws-memo-rec, .ws-memo-ready { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.ws-memo-rec b, .ws-memo-ready b { font-variant-numeric:tabular-nums; }
.rec-dot { width:10px; height:10px; border-radius:50%; background:#e5484d; animation:rec-blink 1s ease-in-out infinite; }
@keyframes rec-blink { 0%, 100% { opacity:1; } 50% { opacity:.25; } }
@media (prefers-reduced-motion: reduce) { .rec-dot { animation:none; } }
.ws-memo-ready audio { height:34px; max-width:min(320px, 100%); }
.ws-memo .helper:empty { display:none; }
/* What came with a message. */
.tl-atts { display:flex; flex-direction:column; gap:6px; margin-top:6px; }
.tl-bubble.has-att:empty { padding:6px; }
.tl-atts audio { width:260px; max-width:100%; height:34px; }
.tl-bubble.has-att { min-width:min(292px, 100%); }
.tl-turn .tl-col { min-width:0; flex:0 1 auto; }
.tl-atts img { max-width:min(260px, 100%); max-height:320px; border-radius:10px; display:block; }
.tl-atts video { width:260px; max-width:100%; max-height:320px; border-radius:10px; background:#000; display:block; }
.tl-atts video.audio-only { height:34px; background:transparent; border-radius:999px; }
.tl-att-link { font-size:12px; text-decoration:underline; }
.tl-turn.us .tl-att-link { color:inherit; }
.tl-turn.us .tl-bubble.has-att { padding-bottom:9px; }

/* The week inside the Call Log: quick outcomes on every booking. */
.cal-meta { display:flex; gap:4px; flex-wrap:wrap; margin-top:3px; }
.cal-acts { display:flex; gap:3px; flex-wrap:wrap; margin-top:6px; }
.cal-act { font:inherit; font-size:10.5px; font-weight:650; padding:3px 7px; border:1px solid var(--line); border-radius:999px; background:var(--panel); color:var(--muted); cursor:pointer; }
.cal-act:hover { background:var(--lift-2); color:var(--text); }
.cal-act.on { background:color-mix(in srgb, var(--blue) 14%, transparent); border-color:color-mix(in srgb, var(--blue) 50%, transparent); color:var(--blue); }
.cal-act.pending { background:rgba(245,174,78,.18); border-color:rgba(245,174,78,.6); color:var(--text); }
.cal-move { display:inline-flex; align-items:center; gap:5px; margin-top:7px; padding:0; border:0; background:none;
  font:inherit; font-size:11px; font-weight:650; color:var(--subtle); cursor:pointer; }
.cal-move:hover { color:var(--blue); }
.cal-mover-zone b { color:var(--text); }
.cal-mover { margin-top:8px; padding:8px; border:1px dashed var(--line); border-radius:9px; background:var(--lift-1);
  display:flex; flex-direction:column; gap:7px; font-size:11.5px; }
.cal-mover-row { display:flex; align-items:center; gap:6px; flex-wrap:wrap; }
.cal-mover-row input { font-size:12px; padding:4px 7px; }
.cal-mover-row .dp-wrap input { width:120px; }
.cal-slots { display:flex; flex-wrap:wrap; gap:4px; }
.cal-slot { font:inherit; font-size:11px; font-weight:650; padding:3px 8px; border:1px solid var(--line); border-radius:999px;
  background:var(--panel); color:var(--muted); cursor:pointer; }
.cal-slot:hover { color:var(--text); background:var(--lift-2); }
.cal-slot.on { background:color-mix(in srgb, var(--blue) 14%, transparent); border-color:color-mix(in srgb, var(--blue) 50%, transparent); color:var(--blue); }
.cal-mover-acts { display:flex; align-items:center; gap:6px; }
.cal-confirm { display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-top:6px; font-size:11.5px; }
.cal-confirm-label { flex-basis:100%; color:var(--muted); }
.cal-note { flex-basis:100%; font-size:12px; padding:5px 8px; }
.cal-note[hidden] { display:none; }
.confirm-row .note-in { flex-basis:100%; }

/* Settings: one row per integration, A to Z, opened when needed. */
.int-list { display:flex; flex-direction:column; gap:8px; }
.int { border:1px solid var(--line); border-radius:12px; background:var(--panel); box-shadow:var(--shadow-sm); }
.int[hidden] { display:none; }
.int > summary { list-style:none; display:flex; align-items:center; gap:12px; padding:12px 16px; cursor:pointer; user-select:none; }
.int > summary::-webkit-details-marker { display:none; }
.int > summary:hover { background:var(--lift-1); border-radius:12px; }
.int[open] > summary { border-bottom:1px solid var(--line); border-radius:12px 12px 0 0; }
.int-name { font-weight:700; font-size:13.5px; flex:1; min-width:0; display:flex; align-items:center; gap:8px; }
.int-status { font-size:11.5px; font-weight:650; color:var(--subtle); padding:3px 9px; border-radius:999px; background:var(--lift-1); border:1px solid var(--line); white-space:nowrap; }
.int-status.ok { color:var(--ink-good, #1f9d55); background:rgba(53,201,143,.14); border-color:rgba(53,201,143,.4); }
.int-status.warn { color:var(--ink-warn, #c98a2b); background:rgba(245,174,78,.16); border-color:rgba(245,174,78,.5); }
.int-status:empty { display:none; }
.int-chev { color:var(--subtle); font-size:18px; line-height:1; transition:transform .15s ease; }
.int[open] .int-chev { transform:rotate(90deg); }
.int-body { padding:14px 16px 16px; }
.int-body > .card-sub:first-child { margin-top:0; }
.int-h4 { margin:0 0 6px; font-size:13px; }
/* Stored secrets: the field says a key is in and how it ends; the eye only
   ever reveals what you are typing, never what is stored. */
.secret-wrap .secret-eye[hidden] { display:none; }
.secret-tail { font-size:11px; color:var(--subtle); margin-top:4px; }

/* Sidebar foot: the install link sits above Reset menu order. */
.nav-install { display:flex; align-items:center; justify-content:center; gap:7px; width:100%; margin-bottom:8px; padding:8px 10px;
  border:1px solid var(--line); border-radius:9px; background:var(--panel); color:var(--muted); font-size:11.5px; font-weight:700;
  text-decoration:none; transition:background .14s ease, color .14s ease, border-color .14s ease; }
.nav-install:hover { background:var(--lift-2); color:var(--text); border-color:var(--line-strong); }
.nav-install[hidden] { display:none; }
.sidebar.collapsed .nav-install span { display:none; }
.tb-btn.busy .tb-svg svg { animation:tbspin 1s linear infinite; }
@keyframes tbspin { to { transform:rotate(360deg); } }

/* iMessage vs SMS, said the way the phone says it. */
.svc-chip { display:inline-block; font-size:9.5px; font-weight:800; letter-spacing:.02em; padding:1px 6px; border-radius:6px; line-height:1.5; vertical-align:middle; }
.svc-chip.imessage { background:rgba(59,130,246,.18); color:#2f6fe0; }
.svc-chip.sms { background:rgba(53,201,143,.18); color:#1f9d55; }
.svc-chip.rcs { background:rgba(20,184,166,.18); color:#0f8f83; }
.ws-chan { gap:5px; align-items:center; }

/* ============================================================================
   Phones (≤700px). Not the desktop shell squeezed: the sidebar becomes a drawer
   behind a menu button, the top bar is one row with the search underneath,
   and every page is one column. The 940px rule above turns the sidebar into a
   68px icon rail, which on a 390px screen was a column of glyphs and stars
   with the page crushed beside it -- so here it is undone and replaced.
   ======================================================================== */
.nav-toggle { display:none; }
.nav-backdrop { position:fixed; inset:0; z-index:70; background:rgba(15,18,28,.45);
  backdrop-filter:blur(2px); }
@media (max-width:700px) {
  .app-shell, .app-shell.collapsed { grid-template-columns:minmax(0,1fr); }
  .sidebar, .sidebar.collapsed { position:fixed; top:var(--asbar, 0px); left:0; bottom:0; height:auto;
    width:min(300px, 86vw); padding:18px 14px; gap:22px; z-index:80; overflow-y:auto;
    transform:translateX(-105%); transition:transform .22s ease; border-right:1px solid var(--line); }
  body.nav-open .sidebar { transform:none; box-shadow:0 24px 60px rgba(0,0,0,.35); }
  /* Everything the icon rail hid comes back: this is the full menu, in a drawer. */
  .sidebar .brand-copy, .sidebar .sidebar-note { display:block; }
  .sidebar .nav-label { display:flex; }
  .sidebar .nav-item span.nav-item-label { display:inline; }
  /* Back in the row, after the label, the way the desk shows it. */
  .sidebar .nav-badge { position:static; min-width:18px; height:18px; line-height:18px; font-size:10px; padding:0 5px; margin-left:-3px; box-shadow:none; }
  .sidebar .brand { justify-content:flex-start; }
  .sidebar .collapse { display:none; }
  .sidebar .nav-item { justify-content:flex-start; padding-inline:10px; }
  .nav-toggle { display:inline-flex; padding:0; width:38px; }

  main { padding:0 12px 24px; }
  .topbar { min-height:56px; flex-wrap:wrap; gap:8px; padding:6px 12px; margin:0 -12px; }
  /* One row: menu · crumb · the buttons; the search underneath. The 680px
     rule further up put the crumb and the buttons on rows of their own. */
  .crumb { flex:1 1 0; order:0; min-width:0; font-size:12.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .crumb b { font-size:13px; }
  .topbar-actions { flex:0 0 auto; order:0; gap:4px; justify-content:flex-end; }
  .topbar-actions .theme-toggle { display:none; }   /* the phone follows the system; the toggle lives on the desktop */
  .gsearch { order:3; flex-basis:100%; max-width:none; }
  .page { padding-top:14px; max-width:none; }
  .page-heading { margin-bottom:14px; }
  .page-heading h1 { font-size:24px; }
  .lede { font-size:13.5px; }
  .metric-grid, .metric-grid.flow, .module-grid { grid-template-columns:1fr; }
  .card { padding:14px; }
  .hpop { width:calc(100vw - 12px); left:6px !important; right:6px; max-height:74vh; }
  .subnav { display:flex; overflow-x:auto; flex-wrap:nowrap; max-width:100%; scrollbar-width:none; }
  .subnav::-webkit-scrollbar { display:none; }
  body.ws-page main { padding:0 8px 0; }
  body.ws-page .page { padding-top:8px; }
  /* minmax(0,1fr), not 1fr: a plain 1fr track will not shrink below its
     content's minimum, and on Safari a pasted Instagram link inside a
     clamped preview counts as one unbreakable word -- so the whole list
     column grew past the phone's edge, the channel tiles went with it, and
     nothing could be scrolled into view. The track is the screen, full stop. */
  .ws4, .ws4.nobody { grid-template-columns:minmax(0,1fr); min-height:0; }
  .ws-list, .ws-rail, .ws-thread, .ws-people { min-width:0; max-width:100%; }
  .ws4.nobody .ws-row-prev { word-break:break-all; }   /* Safari: a link breaks inside a clamped box only with this */
  .ws4.nobody { height:auto !important; }
  .ws-rail { max-height:none; }
  /* The rail is a strip of chips on a phone; the list is the page. */
  .ws-rail { display:flex; gap:6px; overflow-x:auto; padding:8px; border-right:0; border-bottom:1px solid var(--line); scrollbar-width:none; }
  .ws-rail-head, .ws-rail-title { display:none; }
  .ws-rail-group { flex-direction:row; gap:4px; flex:0 0 auto; }
  .ws-rail-item { width:auto; flex:0 0 auto; padding:5px 9px; border-radius:999px; background:var(--lift-1); font-size:12px; white-space:nowrap; }
  .ws-rail-item.stage span { display:flex; gap:5px; }
  .ws-rail-item.stage span small, .ws-rail-item:not(.stage) span small { display:none; }
  .ws-list { max-height:none; }
  /* Rows read like the narrow list, not the wide one: name and time, the
     line, the pills. */
  /* Nothing in the list column may be wider than the phone: the channel
     bar's four fixed-width tiles were, and they dragged the whole column
     -- and its text -- out past the edge. */
  .ws4.nobody .ws-chanbar, .ws-chanbar { grid-template-columns:repeat(4, minmax(0,1fr)); gap:4px; padding:8px; }
  .ws-chanbar button, .ws-chanbar .ch { min-width:0; padding-inline:4px; font-size:12px; }
  .ws-list-head { flex-wrap:wrap; }
  .ws-list-head input { flex:1 1 160px; }
  .ws4.nobody #wsSearch { max-width:none; }
  .ws4.nobody .ws-strip { margin-left:0; flex-basis:100%; }
  .ws4.nobody .ws-row { padding:10px 12px; }
  .ws-row-prev { min-width:0; overflow:hidden; text-overflow:ellipsis; }
  .ws4.nobody .ws-row-body { display:block; }
  .ws4.nobody .ws-row-top { flex-direction:row; justify-content:space-between; align-items:baseline; }
  .ws4.nobody .ws-row-prev { margin-top:2px; -webkit-line-clamp:2; overflow-wrap:anywhere; word-break:break-word; font-size:13px; line-height:1.35; }
  .ws4.nobody .ws-row-body { min-width:0; overflow:hidden; }
  /* The rail strip above already says 74 waiting · 4 mine · 0 due; the same
     numbers again under the search box only pushed the list down. */
  .ws4.nobody .ws-strip { display:none; }
  .ws4.nobody .ws-row-meta { justify-content:flex-start; margin-top:5px; flex-wrap:wrap; }
  /* Open a person and the thread is the screen; the × in its header is the
     way back to the list. The card follows the thread, one scroll down. */
  .ws4:not(.nobody) .ws-rail, .ws4:not(.nobody) .ws-list, .ws4:not(.nobody) .ws-card { display:none; }
  /* The person card, as a sheet: over the thread, under the top bar, above
     the tab bar, with its own scroll and its own ×. */
  .ws-card-btn { display:inline-flex; }
  body.ws-card-open .ws4:not(.nobody) .ws-card { display:flex; position:fixed; left:0; right:0;
    top:var(--asbar, 0px); bottom:calc(58px + env(safe-area-inset-bottom, 0px)); z-index:65;
    border:0; border-top:1px solid var(--line); background:var(--panel); animation:hpopIn .16s ease; }
  body.ws-card-open .ws-card-top { display:flex; }
  body.ws-card-open .ws-card-scroll { flex:1; min-height:0; padding:12px 14px 24px; }
  .ws4:not(.nobody) { grid-template-rows:minmax(0,1fr); overflow:hidden; }
  .ws-thread { min-height:0; }
  body.ws-page .app-footer { display:none; }
}

/* The phone's tab bar, and the phone's type. Fingers, not cursors: rows and
   bubbles a size up, inputs at 16px (below that iOS zooms the page when one
   is tapped), targets no smaller than 44px where they matter. */
.tabbar { display:none; }
@media (max-width:700px) {
  .tabbar { position:fixed; left:0; right:0; bottom:0; z-index:60; display:flex; align-items:stretch;
    background:var(--panel); border-top:1px solid var(--line);
    padding:4px 4px calc(4px + env(safe-area-inset-bottom, 0px)); box-shadow:0 -6px 24px rgba(0,0,0,.08); }
  .tabbar .tab { position:relative; flex:1 1 0; min-height:50px; display:flex; flex-direction:column; align-items:center;
    justify-content:center; gap:3px; border:0; background:transparent; border-radius:10px; color:var(--subtle);
    font:inherit; font-size:10.5px; font-weight:650; letter-spacing:.01em; text-decoration:none; cursor:pointer; }
  .tabbar .tab svg { width:22px; height:22px; }
  .tabbar .tab.on { color:var(--blue); }
  .tabbar .tab:active { background:var(--lift-2); }
  .tab-badge { position:absolute; top:4px; left:calc(50% + 6px); min-width:17px; height:17px; padding:0 5px;
    border-radius:9px; display:grid; place-items:center; font-size:10px; font-weight:800; background:#e5484d; color:#fff; }
  /* The drawer is behind Menu on a phone: a dot says something in it carries a count. */
  .tab-dot { position:absolute; top:7px; left:calc(50% + 9px); width:9px; height:9px; border-radius:50%;
    background:#e5484d; box-shadow:0 0 0 2px var(--panel); }
  /* Room for the bar under every page. */
  main { padding-bottom:calc(74px + env(safe-area-inset-bottom, 0px)) !important; }
  body.ws-page main { padding-bottom:calc(64px + env(safe-area-inset-bottom, 0px)) !important; }
  .app-footer { padding-bottom:calc(74px + env(safe-area-inset-bottom, 0px)); }

  input, select, textarea { font-size:16px; }
  .button { min-height:42px; font-size:13.5px; }
  .chip { min-height:34px; font-size:12.5px; }
  .nav-item { min-height:46px; font-size:15px; }
  .nav-label { font-size:11px; }
  /* Messaging is what the phone is for. */
  .ws-row { padding:14px 12px; gap:12px; }
  .ws-row-name { font-size:15px; }
  .ws-row-prev { font-size:13.5px; }
  .ws-row-when { font-size:12px; }
  .ws-avatar { width:40px; height:40px; flex-basis:40px; font-size:13px; }
  .ws-dot { left:44px; top:11px; }
  .ws4.nobody .ws-dot { left:44px; top:11px; }
  .msg-bubble { font-size:15px; line-height:1.45; padding:10px 14px; }
  /* A phone is narrow: 64% of it is a column of two words. */
  .msg-turn { max-width:84%; }
  .msg-time, .msg-day span { font-size:11px; }
  .ws-compose-top .ws-tab { font-size:13px; padding:6px 12px; }
  .ws-chan-btn, .ws-channels button { min-height:38px; font-size:13px; }
  .hpop-bubble { font-size:14.5px; }
  .hpop-person-name { font-size:14.5px; }
  .hpop-person-last { font-size:12.5px; }
  .hpop-tab { font-size:13.5px; padding:10px 12px 11px; }
  .msg-box textarea { font-size:16px; }
  .ibx-card { padding:14px; }
  .ws-rail-item { min-height:36px; font-size:13px; }
  .ws-chanbar button, .ws-chanbar .ch { min-height:44px; }
  .cal-act, .cal-slot { min-height:32px; font-size:12px; }
  /* Team chat on a phone, the way the Prospects tab works: the people are
     the screen you land on, a conversation is the next screen, and the
     notification queue is a third you go to from the chips at the top. No
     stack of cards, no dead space under them. */
  .ibx-shell { height:calc(100dvh - var(--ibx-chrome, 188px)); min-height:0; gap:10px;
    grid-template-rows:minmax(0,1fr); }
  .ibx-rail { overflow-y:auto; min-height:0; }
  /* The queue lives behind the three chips; the people are what is up. */
  body:not(.ibx-queue):not(.ibx-open) #notifPane { display:none !important; }
  body.ibx-queue .ibx-rail { display:none; }
  body.ibx-queue #notifPane, body.ibx-queue .ibx-main { min-height:0; }
  .ibx-rail-head { padding-top:10px; margin-top:2px; }
  /* Inbox · Replies · Prospect mentions: a strip of chips, not a column. */
  .ibx-nav-row { flex-direction:row; gap:6px; overflow-x:auto; scrollbar-width:none;
    padding-bottom:2px; margin:-2px -4px 2px; padding-inline:4px; }
  .ibx-nav-row::-webkit-scrollbar { display:none; }
  .ibx-nav { width:auto; flex:0 0 auto; font-size:13px; padding:8px 12px;
    border:1px solid var(--line); border-radius:999px; background:var(--panel); }
  .ibx-nav.on { border-color:transparent; }
  /* The people are the page: they take the room that is left and scroll. */
  #threadList { flex:1 1 auto; min-height:0; overflow-y:auto; }
  .ibx-rail { gap:0; }
  /* Title and the one action on the first line, the read filter under it --
     three things on one line is how it ran off the edge. */
  .ibx-head { padding:10px 12px; gap:8px 10px; flex-wrap:wrap; }
  .ibx-head h1 { font-size:15px; flex:1 1 auto; }
  .ibx-tabs { order:3; flex:1 1 100%; margin-left:0; justify-content:space-between; }
  .ibx-tab { flex:1 1 auto; padding:7px 10px; font-size:12.5px; }
  #ibxAllRead { flex:0 0 auto; padding:7px 11px; font-size:12px; }
  body.ibx-open .ibx-rail, body.ibx-open #notifPane { display:none !important; }
  body.ibx-open .ibx-shell { grid-template-rows:minmax(0,1fr); overflow:hidden; }
  body.ibx-open .msg-main { min-height:0; display:flex; flex-direction:column; }
  body.ibx-open #msgThread { flex:1; }
  body.ibx-open .app-footer { display:none; }
  /* Typing room: the box is the width of the screen and the tools sit under
     it, so a message is written on a line, not in a stamp. */
  .msg-box { padding:10px 12px 10px; }
  .msg-box textarea { font-size:16px; min-height:46px; }
  .msg-box-row .msg-note { display:none; }
  .msg-box-row .button { margin-left:auto; padding:9px 18px; }
  .msg-tool span { display:none; }
  .msg-tool { min-width:42px; min-height:38px; font-size:16px; }
  .msg-back { display:inline-flex; align-items:center; justify-content:center; width:32px; height:32px;
    border-radius:8px; color:var(--muted); margin-left:-6px; }
  .msg-back:active { background:var(--lift-2); }
  .msg-head { padding:10px 12px; }
  .msg-log { padding:14px 12px; }
  .msg-box { padding:10px 12px 6px; }
}
.msg-back { display:none; }
@media (max-width:700px) { .msg-back { display:inline-flex; } }
/* On a desk the queue is simply up beside everything else -- nothing to go
   back from. */
#ibxBack { display:none; }
@media (max-width:700px) { body.ibx-queue #ibxBack { display:inline-flex; } }

/* The roster as cards, phones only. */
.client-cards { display:none; }
@media (max-width:700px) {
  .client-cards { display:flex; flex-direction:column; gap:8px; }
  .client-cards + .table-wrap, #clientCards ~ .table-wrap { display:none; }
  .section:has(#clientCards) .table-wrap, .section:has(#callCards) .table-wrap { display:none; }
  .ccard-group { display:flex; align-items:center; justify-content:space-between; width:100%; margin-top:10px;
    padding:8px 4px 4px; border:0; background:transparent; font:inherit; font-size:11px; font-weight:800;
    letter-spacing:.06em; text-transform:uppercase; cursor:pointer; text-align:left; }
  .ccard-group:first-child { margin-top:0; }
  .ccard { display:flex; flex-direction:column; gap:4px; width:100%; padding:12px 14px; border:1px solid var(--line);
    border-radius:14px; background:var(--panel); color:inherit; font:inherit; text-align:left; cursor:pointer;
    box-shadow:var(--shadow-sm); }
  .ccard:active { background:var(--lift-2); }
  .ccard-top { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
  .ccard-top strong { font-size:15.5px; letter-spacing:-.01em; }
  .ccard-renew { font-size:12.5px; font-weight:650; flex:0 0 auto; }
  .ccard-line { font-size:13px; color:var(--muted); }
  .ccard-line.muted { color:var(--subtle); font-size:12.5px; }
  .ccard-chips { display:flex; flex-wrap:wrap; gap:4px; margin-top:4px; }
  .ccard-chips:empty { display:none; }
  .ccard-chips .badge, .ccard-chips .chip-overdue, .ccard-chips .chip-monthly { margin:0; }
}

/* Phone polish. */
@media (max-width:700px) {
  /* Under the notch, in the home-screen app: the top bar and the drawer start below it. */
  .topbar { padding-top:calc(6px + env(safe-area-inset-top, 0px)); }
  .sidebar, .sidebar.collapsed { padding-top:calc(18px + env(safe-area-inset-top, 0px)); }
  /* The page name is the crumb; "Operations /" is a desk-sized nicety. */
  .crumb > span, .crumb { font-size:0; }
  .crumb b { font-size:14px; }
  /* Settings lives in the Menu and under your avatar; the top bar keeps to what you tap all day. */
  .topbar-actions a.tb-btn[href="/settings"] { display:none; }
  /* Page ledes explain the page to someone at a desk; on a phone they cost a screen. */
  .page-heading .lede, .page-heading > div > p { display:none; }
  .page-heading h1 { font-size:22px; margin-bottom:0; }
  /* The small coach table fits without a sideways scroll. */
  table:has(> #byCoach) { min-width:0; }
  /* Two-column layouts written inline (the Playbook's entry list beside its
     editor) and header rows that put a button beside a paragraph: one column,
     one thing per line. */
  .main-grid, .two-col, .split { grid-template-columns:1fr !important; }
  .action-row { flex-wrap:wrap; }
  .card > .action-row > .grow { flex:1 1 100% !important; }   /* .grow is !important itself */
  #entryList { max-height:40vh !important; }
  /* The Ads filter panel folds behind one line; open it when you need it. */
  .fold-toggle { display:flex; align-items:center; justify-content:space-between; width:100%; padding:2px 0;
    border:0; background:transparent; font:inherit; font-size:14px; font-weight:700; color:var(--text); cursor:pointer; }
  .fold-toggle::after { content:"▸"; color:var(--subtle); font-size:12px; }
  .fold-toggle[aria-expanded="true"]::after { content:"▾"; }
  .ads-filters .filter-bar { display:none; margin-top:10px; }
  .ads-filters.open .filter-bar { display:block; }
  /* While the keyboard is up. */
  body.kb-open .tabbar { display:none; }
  body.kb-open main { padding-bottom:12px !important; }
}
.fold-toggle { display:none; }
@media (max-width:700px) { .fold-toggle { display:flex; } }

/* Zoom: the join link GHL put on the booking, wherever the booking shows. */
.chip.zoom { background:#0b5cff; border-color:#0b5cff; color:#fff; font-weight:700; }
.chip.zoom:hover { background:#0a52e6; color:#fff; }
.chip.zoom.sm { padding:3px 8px; font-size:10.5px; margin-left:6px; }
.cal-zoom { display:inline-block; margin-top:5px; padding:3px 9px; border-radius:999px; background:#0b5cff; color:#fff;
  font-size:10.5px; font-weight:700; text-decoration:none; }
.cal-zoom:hover { background:#0a52e6; }
.ws-pill { white-space:nowrap; }
.ws-thread-name { flex-wrap:wrap; row-gap:2px; }

/* Tags on the person card: ours, then the Brain's, each a single row read
   left to right -- a short label in a fixed column, the chips beside it --
   so a guess is never mistaken for a GoHighLevel tag and nothing stacks. */
.tag-row { display:flex; align-items:flex-start; gap:8px; }
.tag-row + .tag-row { margin-top:6px; }
.tag-row-label { flex:0 0 46px; display:inline-flex; align-items:center; gap:4px; min-height:24px;
  font-size:10px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--subtle); cursor:default; }
.tag-row .tag-list { flex:1; min-width:0; align-items:center; }
.tag-row .tag-add { width:74px; }
.tag-brain { width:12px; height:12px; flex:0 0 auto; }
.tag-row.brain .tag-row-label { color:var(--blue); }
/* Still used by the link groups on Pricing & Links. */
.tag-group-label { display:flex; align-items:center; gap:5px; font-size:10.5px; font-weight:800; letter-spacing:.05em;
  text-transform:uppercase; color:var(--subtle); margin-bottom:6px; }
.tag-chip.sug { background:color-mix(in srgb, var(--blue) 8%, transparent); color:var(--blue); border:1px dashed color-mix(in srgb, var(--blue) 45%, transparent); gap:5px; }
.tag-chip.sug .tag-brain { width:11px; height:11px; }
/* The card itself: one rhythm. Sections breathe the same amount, the
   summaries sit on a hairline, and the reading text inside is a size up
   from the labels so the labels stay labels. */
.ws-sec { padding:10px 0; }
.ws-sec summary { padding:2px 0; }
.ws-sec > div { padding-top:8px; }
.ws-read { margin:4px 0 0; }
.ws-read + .ws-read { margin-top:6px; }
.ws-stage-now { margin-bottom:2px; }

/* The one button that adds: the brand gradient, the way the Hub's Add client reads. */
.button.brand { background:linear-gradient(135deg, var(--blue), var(--violet)); border-color:transparent; color:#fff;
  font-weight:800; box-shadow:0 6px 18px rgba(79,70,229,.28); }
.button.brand:hover { filter:brightness(1.06); transform:translateY(-1px); }

/* Pricing & Links ----------------------------------------------------------- */
.pr-grid { display:grid; grid-template-columns:minmax(0,1fr) 320px; gap:16px; align-items:start; }
.pr-group { font-size:11px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; color:var(--subtle); margin:18px 0 8px; }
.pr-group:first-child { margin-top:0; }
.pr-program + .pr-program { margin-top:12px; }
.pr-table { width:100%; min-width:0; border-collapse:separate; border-spacing:0; }
.pr-table th { font-size:10.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--subtle); text-align:left;
  padding:6px 8px; border-bottom:1px solid var(--line); white-space:nowrap; }
.pr-table th.num, .pr-table td.num { text-align:right; }
.pr-table td { padding:9px 8px; border-bottom:1px solid var(--line); vertical-align:top; white-space:normal; color:var(--text); font-size:13px; }
.pr-table tbody tr:last-child td { border-bottom:0; }
.pr-len b { font-size:13px; }
.pr-sub { font-size:11px; color:var(--subtle); margin-top:2px; line-height:1.35; }
.pr-cell.empty { color:var(--subtle); }
.pr-price { font-size:15px; font-weight:800; letter-spacing:-.01em; font-variant-numeric:tabular-nums; }
.pr-price small { font-size:11px; font-weight:600; color:var(--muted); }
.pr-links { display:flex; gap:4px; margin-top:5px; }
.pr-link { width:22px; height:22px; border-radius:6px; border:1px solid var(--line); background:var(--panel); font:inherit; font-size:10.5px;
  font-weight:800; cursor:pointer; color:var(--muted); display:grid; place-items:center; }
.pr-link.stripe { color:#635bff; border-color:rgba(99,91,255,.45); }
.pr-link.wave { color:#1c7ed6; border-color:rgba(28,126,214,.45); }
.pr-link:hover { background:var(--lift-2); }
.pr-cell.edit { min-width:150px; }
.pr-edit-nums, .pr-edit-links { display:flex; flex-direction:column; gap:3px; }
.pr-edit-links { margin-top:4px; }
.pr-in { width:100%; font-size:11.5px; padding:4px 6px; }
.pr-table-edit td { padding:6px 4px; }
.pr-edit-head { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.pr-edit-head .pr-name { flex:1 1 240px; font-weight:700; }
.pr-linkgroup + .pr-linkgroup { margin-top:12px; }
.pr-linkbtn { display:flex; flex-direction:column; gap:1px; width:100%; padding:8px 10px; margin-bottom:4px; border:1px solid var(--line);
  border-radius:10px; background:var(--panel); text-align:left; cursor:pointer; font:inherit; color:inherit; }
.pr-linkbtn:hover { background:var(--lift-2); }
.pr-linkname { font-size:12.5px; font-weight:650; }
.pr-linkurl { font-size:11px; color:var(--blue); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pr-linkbtn code { font-size:12px; font-weight:700; letter-spacing:.04em; color:var(--text); }
.pr-links-edit { display:flex; flex-direction:column; gap:6px; }
.pr-link-row { display:grid; grid-template-columns:1fr 1.2fr 1.6fr 1fr 1fr auto; gap:4px; }
.pr-link-row input { font-size:11.5px; padding:4px 6px; }
.pr-deliv { width:100%; min-width:0; }
.pr-deliv th { font-size:10.5px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--subtle); text-align:left; padding:6px 8px; white-space:normal; }
.pr-deliv td { padding:8px; font-size:12.5px; white-space:normal; vertical-align:top; }
.pr-deliv td.muted { color:var(--subtle); }
.pr-deliv input { width:100%; font-size:11.5px; padding:4px 6px; }
@media (max-width:1100px) { .pr-grid { grid-template-columns:1fr; } }
/* The picker in the reply box: every link with a name, filter as you type. */

/* My pay, the owner's view: year rows inside the month table, and folds
   with an h3 rather than the Finance folds' h2. */
.mp-year td { background: var(--lift-1); border-top: 1px solid var(--line-strong); }
.mp-fold > summary h3 { margin: 0; font-size: 14px; }
.mp-fold > summary .helper { margin-left: 10px; }
#mpOwnerTiles .stat { flex: 1 1 200px; }
#mpOwnerTiles .stat .helper { display: block; margin-top: 4px; }
#mpOwnerMonths .pr-tag { margin-left: 6px; }

/* Tasks: the star filter is a button wearing the same star as every task,
   and a column drags by its header -- the six dots show on hover there too. */
.tk-starfilter { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line-strong);
  border-radius: 9px; padding: 8px 12px; background: var(--panel); color: var(--muted);
  font: inherit; font-size: 12px; font-weight: 750; cursor: pointer;
  transition: background .14s ease, color .14s ease, border-color .14s ease; }
.tk-starfilter svg { flex: 0 0 auto; }
.tk-starfilter:hover { background: var(--lift-2); color: var(--text); }
.tk-starfilter[aria-pressed="true"] { background: var(--tint-amber); border-color: var(--amber);
  color: var(--amber); }
.tk-starfilter[aria-pressed="true"] span { color: var(--text); }
/* Naming a new list from inside the New task dialog: one line under the
   pickers, the field wide and the two buttons beside it. */
.tkq-newlist { display: flex; align-items: center; gap: 8px; }
.tkq-newlist[hidden] { display: none; }
.tkq-newlist input { flex: 1 1 auto; }
.tkq-newlist button { flex: 0 0 auto; }
/* The No close dialog on the Call Log: the follow-up question under the note. */
.nc-fu { border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; background: var(--lift-1); }
.nc-ask { display: flex; align-items: center; gap: 9px; font-size: 13px; font-weight: 600; cursor: pointer; margin: 0; }
.nc-ask input { width: 16px; height: 16px; accent-color: var(--blue-solid); }
.nc-fields { margin-top: 10px; }
.nc-grid { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
#ncNote.tk-grow { min-height: 74px; }
/* The onboarding summary on the client card: Stefan's headings, read top to
   bottom by the coach before the onboarding call. */
.onb-body { font-size: 13px; line-height: 1.55; max-height: 64vh; overflow: auto;
  padding-right: 6px; scrollbar-width: thin; }
.onb-body.open { max-height: none; overflow: visible; }
.onb-card .section-head { display: flex; justify-content: space-between; gap: 10px; align-items: flex-start; }
.onb-card .action-row { flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin: 0; }
.term-card.onb-card .helper { margin: 0; }
.term-card.onb-card .onb-body { margin-top: 8px; max-height: 56vh; }
.term-card.onb-card .onb-meta { margin-top: 8px; }
.onb-body h4 { font-size: 13.5px; margin: 14px 0 4px; letter-spacing: 0; }
.onb-body h4:first-child { margin-top: 4px; }
.onb-body p { margin: 2px 0; }
.onb-body ul { margin: 2px 0 4px; padding-left: 20px; }
.onb-body li { margin: 1px 0; }
.onb-body em { color: var(--muted); font-style: normal; font-weight: 600; }
/* Read receipts, in words: under our bubble in the thread, and at the end of
   the preview on the row. Green = seen, amber = delivered and not opened. */
.msg-state.seen { color: var(--ink-good); }
.msg-state.unseen { color: var(--ink-warn); }
.ws-receipt { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 999px;
  font-size: 10px; font-weight: 700; letter-spacing: .02em; vertical-align: 1px; }
.ws-receipt.seen { color: var(--ink-good); background: rgba(53,201,143,.12); }
.ws-receipt.unseen { color: var(--ink-warn); background: rgba(245,174,78,.16); }
.ws-receipt.bad { color: var(--ink-bad); background: var(--tint-red); }

/* Row / Grid: the board's two layouts, side by side so the one you are in is
   always on screen. Same segmented control as the calendar's Day / Week /
   Month, sized to stand level with the filters beside it. */
.tk-views { display: inline-flex; align-items: stretch; border: 1px solid var(--line-strong);
  border-radius: 9px; overflow: hidden; background: var(--panel); }
.tk-views button { display: inline-flex; align-items: center; gap: 6px; border: 0;
  background: none; color: var(--muted); font: inherit; font-size: 12px; font-weight: 750;
  padding: 8px 11px; cursor: pointer; transition: background .14s ease, color .14s ease; }
.tk-views button + button { border-left: 1px solid var(--line-strong); }
.tk-views button:hover { background: var(--lift-2); color: var(--text); }
.tk-views button.on { background: var(--lift-3); color: var(--text); }
.tk-views svg { flex: 0 0 auto; }
.tkc-head { cursor: grab; }
.tkc-head:active { cursor: grabbing; }
.tkc-grip { flex: 0 0 10px; color: var(--subtle); fill: currentColor; opacity: 0; transition: opacity .12s ease; }
.tkc:hover .tkc-grip, .tkc.is-dragging .tkc-grip { opacity: .7; }
.tkc.is-dragging { opacity: .45; }

/* ==========================================================================
   Phones: the messaging screens. Stefan's brief (09-16-2026): "just like I'm
   messaging somebody on iPhone" -- a conversation gets the whole screen, the
   reply box is one field with an arrow, and nothing above the thread costs
   more than one line. Desk defaults first; the phone rules follow.
   ========================================================================== */
.ws-chev, .ws-send-ico, .ws-card-act, .dlg-back, .meta-crm { display:none; }
.button .ws-send-ico { stroke:currentColor; }

@media (max-width:700px) {
  /* -- top bar: the Team tab IS the inbox on a phone, so no second door up
        here; the search pill grows to a thumb's size and the Brain gets its name back. */
  .topbar-actions #inboxBtn { display:none; }
  .gsearch { height:46px; padding:0 5px 0 14px; }
  .gsearch .gs-icon { width:18px; height:18px; }
  #gsInput { font-size:16px; }
  .gs-kbd { display:none; }
  .gs-brain { height:36px; padding:0 14px 0 12px; font-size:13.5px; border-radius:0 999px 999px 0; }
  .gs-brain-label { display:inline; }
  .gs-brain-ico { width:19px; height:19px; }

  /* -- under the notch: iOS paints the status bar over whatever scrolls
        beneath it, blurred, which read as "the top of the page is blurred".
        A solid band the height of the status bar sits there instead, in the
        page's own colour -- the panel's when a conversation has the screen. */
  body::before { content:""; position:fixed; top:0; left:0; right:0; height:env(safe-area-inset-top, 0px);
    background:var(--bg); z-index:95; pointer-events:none; }
  body.ws-open::before, body:has(.brain-overlay:not([hidden]))::before { background:var(--panel); }

  /* -- Prospects Inbox, a thread open: the thread is the screen. -------- */
  body.ws-open .topbar, body.ws-open .subnav, body.ws-open .tabbar, body.ws-open .asbar { display:none; }
  body.ws-open main { padding:0 !important; }
  body.ws-open .page { padding-top:0; }
  /* The thread is a fixed layer and the page behind it cannot move at all:
     no rubber-banding the header down or the reply box up, no drifting the
     bubbles sideways. Only the log scrolls, and it stops at its own ends
     instead of handing the pull on to the page -- iMessage's feel. The
     layer's height and top are only ever set while the keyboard is up
     (fitWorkspace); otherwise inset:0 is the whole screen. */
  html:has(body.ws-open) { overflow:hidden; height:100%; overscroll-behavior:none; }
  body.ws-open { overflow:hidden; height:100%; overscroll-behavior:none; position:fixed; inset:0; width:100%; }
  body.ws-open .ws4:not(.nobody) { position:fixed; inset:0; z-index:50; border:0; border-radius:0; background:var(--panel);
    grid-template-rows:minmax(0,1fr); overflow:hidden; }
  body.ws-open .ws-thread-inner { border:0; border-radius:0; }
  body.ws-open .ws-timeline { overflow-x:hidden; overscroll-behavior:contain; -webkit-overflow-scrolling:touch; }
  body.ws-open .ws-timeline > * { max-width:100%; }
  body.ws-open .ws-timeline audio { width:100%; max-width:240px; }
  body.ws-open .ws-timeline .tl-bubble { max-width:100%; box-sizing:border-box; }
  body.ws-open .ws-card-scroll { overscroll-behavior:contain; }
  /* The head: ‹ · avatar · name and stage · Zoom if there is a call · Details. */
  .ws-thread-head { padding:calc(8px + env(safe-area-inset-top, 0px)) 10px 8px 6px; gap:8px; }
  .ws-thread-head #wsBack { order:-1; width:36px; height:36px; padding:0; border:0; background:transparent;
    display:inline-flex; align-items:center; justify-content:center; color:var(--blue); }
  .ws-thread-head #wsBack .ws-x { display:none; }
  .ws-thread-head #wsBack .ws-chev { display:block; }
  .ws-thread-head .ws-avatar { width:36px; height:36px; flex-basis:36px; font-size:12.5px; }
  .ws-thread-name { font-size:16px; flex-wrap:nowrap; }
  .ws-thread-name b { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
  .ws-thread-name .ws-pill { font-size:10px; padding:2px 7px; flex:0 0 auto; }
  .ws-thread-head #wsSub { font-size:11.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  /* The chips' wrapper dissolves so ‹ can sit at the far left and Details at
     the far right of one row: ‹ · avatar · name · Zoom · Details. */
  .ws-thread-head .action-row { display:contents; }
  .ws-thread-head #wsZoom { order:1; }
  .ws-thread-head .ws-help-thread { order:2; width:32px; height:32px; min-height:32px; padding:0; }
  .ws-thread-head #wsCardBtn { order:3; }
  .ws-thread-head #wsUnread, .ws-thread-head #wsCrm { display:none; }
  .ws-thread-head .chip { min-height:32px; padding:4px 10px; font-size:12px; }
  .ws-card-act { display:inline-flex; }
  .ws-card-top { gap:6px; }
  .ws-card-top b { flex:1; }
  body.ws-open.ws-card-open .ws4:not(.nobody) .ws-card { top:0; bottom:0; padding-top:env(safe-area-inset-top, 0px); z-index:65; }
  /* The log: bubbles nearly edge to edge. */
  .ws-timeline { padding:12px 10px; gap:10px; }
  .ws-timeline .tl-turn, .ws-timeline .tl-turn.them { max-width:86%; }
  .tl-bubble { font-size:15px; line-height:1.4; padding:9px 13px; }
  /* The reply box: one line of chips, then the field with its arrow. */
  .ws-compose { padding:6px 8px calc(8px + env(safe-area-inset-bottom, 0px)); }
  .ws-next { margin-bottom:4px; }
  /* One row of four equal segments -- Instagram · Text · Email · Note --
     each a thumb high, filling the width. Reply is not a button here:
     picking a channel is replying. (Zoom link, when there is a call, rides
     along at its own width.) */
  .ws-compose-top { flex-wrap:nowrap; align-items:stretch; gap:6px; margin-bottom:6px; }
  .ws-compose-top .ws-channels, .ws-compose-top .ws-compose-tabs { display:contents; }
  .ws-channels .chip[data-ch], .ws-compose-top .ws-tab[data-tab="note"] { flex:1 1 0; min-width:0; min-height:40px;
    display:inline-flex; align-items:center; justify-content:center; gap:4px; padding:4px 3px; font-size:12.5px; font-weight:700;
    border:1px solid var(--line); border-radius:999px; background:transparent; color:var(--muted); }
  .ws-channels .chip[data-ch] span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ws-compose-top .ws-tab[data-tab="note"] { flex:0 0 auto; padding:4px 15px; }   /* the three channels share what Note leaves */
  .ws-channels .chip.active, .ws-compose-top .ws-tab[data-tab="note"].active { background:color-mix(in srgb, var(--blue) 14%, transparent); border-color:color-mix(in srgb, var(--blue) 55%, transparent); color:var(--blue); }
  #wsCompose.noting .ws-channels .chip.active { background:transparent; border-color:var(--line); color:var(--muted); }
  .ws-channels #wsZoomInsert { flex:0 0 auto; min-height:40px; font-size:12.5px; padding:4px 10px; }
  .ws-channels #wsChannelNote { display:none; }
  .ws-compose-top .ws-tab[data-tab="reply"] { display:none; }
  #wsReplyPane { display:flex; flex-wrap:wrap; align-items:flex-end; gap:6px; }
  #wsFromRow, #wsSubject { flex:0 0 100%; order:-2; margin:0 !important; }
  #wsToRow { flex:0 0 100%; order:-3; margin:0 !important; gap:6px; min-height:32px; }
  #wsFromRow { gap:6px; }
  /* The From address needs the whole row: .pr-mini caps a select at 170px,
     which on a phone showed "Pursuit — stefan@pursuit-h" under the chevron. */
  #wsFromRow select { flex:1 1 auto; min-width:0; width:auto; max-width:none; font-size:16px; min-height:36px; padding:6px 28px 6px 10px; }
  /* 16px, never less: iOS zooms the whole page in when a smaller field is
     focused, which is what "everything else is cut off" was. */
  #wsSubject { min-height:36px; padding:6px 12px; font-size:16px; }
  .ws-list-head #wsDays, .ws-list-head input { font-size:16px; }
  #wsMemo { flex:0 0 100%; order:-1; }
  .ws-compose textarea { flex:1 1 0; min-width:0; width:auto; min-height:40px; max-height:160px;
    padding:9px 14px; border-radius:20px; font-size:16px; line-height:1.35; }
  #wsReplyPane .ws-compose-row { flex:0 0 auto; margin:0; gap:6px; }
  #wsComposeNote, #wsNoteHint { display:none; }
  #wsReplyPane .ws-compose-row .action-row { gap:6px; flex-wrap:nowrap; }
  #wsMic { width:40px; height:40px; min-height:40px; padding:0; border-radius:50%; justify-content:center; font-size:17px; }
  .ws-mic-label { display:none; }
  #wsSend, #wsNoteSave { width:40px; height:40px; min-height:40px; padding:0; border-radius:50%;
    display:inline-flex; align-items:center; justify-content:center; }
  #wsSend .ws-send-label, #wsNoteSave .ws-send-label { display:none; }
  #wsSend .ws-send-ico, #wsNoteSave .ws-send-ico { display:block; }
  #wsNoteSave { background:var(--blue-solid); border-color:transparent; color:#fff; }

  /* -- a client, open: the conversation gets the screen too. --------------
        The dialog already fills the phone; here its head shrinks to one line
        each, the tab bar steps aside, and the notes log takes what is left
        instead of a 40vh window with a paragraph and two buttons above it. */
  body:has(.brain-overlay:not([hidden])) .tabbar { display:none; }
  /* The page behind a dialog is pinned, like the page behind an open thread. */
  body:has(.brain-overlay:not([hidden])) { position:fixed; inset:0; width:100%; overflow:hidden; overscroll-behavior:none; }
  .brain-overlay { overscroll-behavior:none; }
  .note-dialog .convo .msg-log, .note-dialog .brain-body, .note-dialog .tab-pane { overscroll-behavior:contain; -webkit-overflow-scrolling:touch; }
  .note-dialog .convo .msg-log { overflow-x:hidden; }
  .note-dialog { display:flex; flex-direction:column; }
  .note-dialog .brain-head { flex-wrap:nowrap; gap:8px; padding:calc(8px + env(safe-area-inset-top, 0px)) 10px 8px 6px; }
  .note-dialog .brain-head strong { max-width:none; font-size:16px; line-height:1.3; min-width:0; }
  .note-dialog .brain-head strong .badge, .note-dialog .brain-head strong .chip { font-size:10px; padding:2px 6px; }
  .note-dialog .brain-head #noteClose { order:-1; width:36px; height:36px; padding:0; border:0; background:transparent;
    display:inline-flex; align-items:center; justify-content:center; color:var(--blue); }
  .note-dialog .brain-head #noteClose .dlg-esc { display:none; }
  .note-dialog .brain-head #noteClose .dlg-back { display:block; }
  .note-dialog .brain-body { flex:1; min-height:0; display:flex; flex-direction:column; padding:6px 10px 0 !important; overflow:hidden; }
  .note-dialog .brain-body > * { flex:0 0 auto; }
  #noteMeta { font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; line-height:1.5; }
  #noteMeta.open { white-space:normal; }
  #noteMeta br { display:none; }
  #noteMeta .meta-line2::before { content:" · "; }
  #noteMeta .status-pick { font-size:12px; padding:1px 6px; }
  #noteMeta .meta-crm { display:inline; color:var(--blue); font-weight:700; text-decoration:none; }
  .note-dialog .brain-head strong .photo-chip { display:none; }   /* on the Onboarding tab; the head has one line */
  .note-dialog .tab-row { margin-top:6px; padding-bottom:6px; }
  /* Only the conversation pane fills; the others scroll as they always did. */
  .note-dialog .tab-pane { overflow-y:auto; min-height:0; }
  .note-dialog .tab-pane[data-pane="notes"] { flex:1 1 0; display:flex; flex-direction:column; overflow:hidden; }
  .note-dialog .tab-pane[data-pane="notes"][hidden] { display:none; }
  .note-dialog .convo-head { display:none; }
  .note-dialog .convo-split, .note-dialog .convo-split.open { flex:1 1 0; min-height:0; display:flex; flex-direction:column; gap:0; }
  .note-dialog .convo { flex:1 1 0; min-height:0; border:0; border-radius:0; }
  .brain-panel .convo .msg-log, .note-dialog .convo .msg-log { flex:1 1 0; max-height:none; padding:12px 8px; }
  .note-dialog .convo .msg-turn { max-width:86%; }
  .note-dialog .msg-bubble { font-size:15px; }
  .note-dialog .convo-panel { position:fixed; inset:0; z-index:8; background:var(--panel); padding-top:env(safe-area-inset-top, 0px); }
  .note-dialog .msg-box { padding:6px 4px calc(8px + env(safe-area-inset-bottom, 0px)); gap:6px; align-items:flex-end; }
  .note-dialog .msg-box textarea { min-height:40px; padding:9px 14px; border-radius:20px; font-size:16px; line-height:1.35; }
  .note-dialog .msg-box #noteSave { width:40px; height:40px; min-height:40px; padding:0; border-radius:50%;
    display:inline-flex; align-items:center; justify-content:center; }
  .note-dialog .msg-box #noteSave .ws-send-label { display:none; }
  .note-dialog .msg-box #noteSave .ws-send-ico { display:block; }
  .note-dialog .msg-note { display:none; }
  .note-dialog .reply-to { margin:0 4px; }
}

/* The P&L's entity switch: Pursuit or the whole LLC. */
.pnl-scope button { font-size:12px; padding:6px 12px; }
.pnl-head .action-row { align-items:center; gap:10px; }

/* A Fit Pro figure the feed is sure of but nobody has approved yet. */
.pnl-prov { color: var(--ink-warn); }
.pnl-prov i { font-style: normal; font-weight: 800; margin-left: 2px; }

/* The To line: who this goes to, in one quiet line above the box -- it is a
   check, not a headline, and the box under it wants the room. */
.ws-to { margin-bottom:3px; gap:6px; }
.ws-to .helper { width:auto; font-size:10.5px; }
.ws-to .ws-to-addr { font-size:11.5px; font-weight:600; color:var(--muted); line-height:1.3; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.ws-to .ws-to-addr.muted { color:var(--subtle); font-weight:500; }
.ws-to .ws-to-addr.ws-to-copy { cursor:pointer; }
.ws-to .ws-to-addr.ws-to-copy:hover { color:var(--blue); text-decoration:underline dotted; text-underline-offset:3px; }
.ws-from .helper { flex:0 0 auto; width:34px; }
@media (max-width:700px) { .ws-to .ws-to-addr { font-size:14px; } }

/* Attachments in a chat: the drop highlight, the chips waiting to go, and
   how a picture or a PDF sits inside a bubble. */
.att-over { outline:2px dashed var(--blue); outline-offset:-4px; background:var(--tint-blue) !important; }
.att-chips { display:flex; flex-wrap:wrap; gap:6px; padding:6px 0 4px; }
.att-chip { display:inline-flex; align-items:center; gap:6px; max-width:220px; padding:4px 6px 4px 4px; border:1px solid var(--line);
  border-radius:10px; background:var(--lift-1); font-size:12px; }
.att-chip img { width:36px; height:36px; object-fit:cover; border-radius:6px; }
.att-chip i { font-style:normal; font-size:15px; padding:0 3px; }
.att-chip b { font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.att-chip button { border:0; background:transparent; color:var(--subtle); font-size:15px; line-height:1; padding:2px 4px; cursor:pointer; border-radius:6px; }
.att-chip button:hover { color:var(--red); background:var(--tint-red); }
.msg-files { display:flex; flex-wrap:wrap; gap:6px; margin-top:6px; }
.msg-bubble.has-files:empty, .hpop-bubble.has-files:empty { display:none; }
.msg-img img { display:block; max-width:min(320px, 100%); max-height:320px; border-radius:10px; }
.msg-file { display:inline-flex; align-items:center; gap:4px; padding:6px 10px; border-radius:9px; background:rgba(255,255,255,.18);
  border:1px solid rgba(255,255,255,.35); color:inherit; text-decoration:none; font-size:12.5px; font-weight:600; }
.msg-turn.theirs .msg-file, .hpop-turn.theirs .msg-file { background:var(--lift-1); border-color:var(--line); }
@media (max-width:700px) {
  #wsAttach { width:40px; height:40px; min-height:40px; padding:0; border-radius:50%; justify-content:center; font-size:17px; }
  .msg-img img { max-width:min(260px, 100%); max-height:260px; }
}

/* The thread's way into a client's card. Green because "closed deal / client"
   is; a finished client keeps the door but loses the colour. */
.chip.client-chip { background:rgba(53,201,143,.14); border-color:rgba(53,201,143,.55); color:var(--ink-good); font-weight:700; }
.chip.client-chip.past { background:transparent; border-color:var(--line); color:var(--muted); }
@media (max-width:700px) {
  .ws-thread-head #wsClientBtn { order:1; }
  /* The client panel takes the phone whole. */
  .client-panel { width:100vw; top:0; padding-top:env(safe-area-inset-top, 0px); }
  body.ws-open .client-panel { z-index:66; }
}

/* ---------------------------------------------------------- voice memos
   The speed pill beside every player, and the shelf of ready memos. */
.aud-wrap { display:flex; align-items:center; gap:2px; max-width:100%; }
.aud-wrap audio { flex:1 1 auto; min-width:0; }
.msg-att .aud-wrap, .msg-body .aud-wrap { width:100%; }
/* Legible at every speed, in both themes: ink on the panel at 1×, blue
   once you have changed it, and blue under the cursor either way. (It used
   to go grey at 1× and stay grey on hover -- "blends in".) */
.aud-rate { font: inherit; font-size:10.5px; font-weight:800; line-height:1; letter-spacing:.01em; padding:4px 7px; margin-left:4px;
  flex:0 0 auto; white-space:nowrap;
  border:1px solid var(--line-strong, var(--line)); border-radius:999px; background:var(--panel); color:var(--text); cursor:pointer;
  vertical-align:middle; font-variant-numeric:tabular-nums; min-width:36px;
  transition:background .12s ease, color .12s ease, border-color .12s ease; }
.aud-rate:not(.off) { background:color-mix(in srgb, var(--blue) 14%, transparent); color:var(--blue); border-color:color-mix(in srgb, var(--blue) 35%, transparent); }
/* Hover is ink on paper, inverted -- near-black in the light theme, near-white
   in the dark -- so it stands out on a grey bubble, on the panel and on your
   own blue bubble alike. A blue hover vanished into the blue bubbles. */
.aud-rate:hover, .aud-rate.off:hover, .aud-rate:focus-visible { background:var(--text); color:var(--panel); border-color:var(--text); }
/* In your own bubble (blue, white text) the resting pill is white with the
   speed in blue, whichever speed it is; blue-on-blue was invisible. */
.msg-turn.mine .aud-rate, .msg-turn.mine .aud-rate:not(.off) { background:#fff; color:var(--blue-solid); border-color:transparent; }
.msg-turn.mine .aud-rate:hover, .msg-turn.mine .aud-rate.off:hover, .msg-turn.mine .aud-rate:focus-visible { background:#14161c; color:#fff; border-color:#14161c; }
.mbk-pop { position:fixed; z-index:80; max-height:min(460px, 72vh); display:flex; flex-direction:column; overflow:hidden;
  border:1px solid var(--line); border-radius:14px; background:var(--panel); box-shadow:var(--shadow); }
.mbk-head { display:flex; flex-direction:column; gap:2px; padding:10px 12px 8px; border-bottom:1px solid var(--line); }
.mbk-head b { font-size:13.5px; }
.mbk-list { overflow-y:auto; padding:6px; display:flex; flex-direction:column; gap:2px; }
.mbk-empty { padding:14px 10px; }
.mbk-row { display:flex; align-items:center; gap:9px; padding:8px 8px; border-radius:10px; }
.mbk-row:hover { background:var(--lift-1); }
.mbk-play { flex:0 0 auto; width:28px; height:28px; border-radius:999px; border:1px solid var(--line); background:var(--panel);
  color:var(--text); font-size:11px; cursor:pointer; }
.mbk-play:hover { border-color:var(--blue); color:var(--blue); }
.mbk-what { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:1px; }
.mbk-what b { font-size:13px; }
.mbk-what small { font-size:11px; color:var(--muted); line-height:1.25; }
.mbk-meta { font-size:10.5px; color:var(--subtle); font-variant-numeric:tabular-nums; }
.mbk-audio { width:100%; height:32px; margin:0 8px 8px; }
.mbk-foot { border-top:1px solid var(--line); padding:8px 10px; }
.mbk-edit-box, .mbk-add { display:flex; flex-direction:column; gap:6px; width:100%; padding:8px; }
.mbk-edit-box input, .mbk-add input[type=text] { width:100%; font:inherit; font-size:12.5px; padding:6px 8px;
  border:1px solid var(--line); border-radius:8px; background:var(--panel); color:var(--text); }
.mbk-edit-box input:focus, .mbk-add input[type=text]:focus { outline:none; border-color:var(--blue); }
@media (max-width: 760px) { .mbk-pop { left:12px !important; right:12px; width:auto !important; } }

/* ------------------------------------------------------ comment threads
   Under a setter's day card, and under its notification in the inbox. */
.day-comments { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
.day-comments-btn { font-weight: 650; }
.day-thread { margin-top: 8px; }
.cmt { border: 1px solid var(--line); border-radius: 12px; background: var(--panel); overflow: hidden; }
.cmt .cmt-log { max-height: 360px; padding: 12px 14px; gap: 10px; }
.cmt .cmt-log .msg-turn { max-width: 88%; }
.cmt .msg-box { padding: 10px 12px; }
.cmt .msg-box textarea { min-height: 40px; font-size: 13px; }
.ibx-thread { flex: 1 1 100%; margin-top: 10px; }
.ibx-thread .cmt { border-radius: 10px; }
@media (max-width: 700px) {
  .cmt .cmt-log { max-height: 50vh; }
  .cmt .msg-box-row .msg-note { display: none; }
}
/* A message on its way: on screen the instant Send is pressed, a shade lighter until the server confirms it. */
.msg-turn.pending .msg-bubble { opacity:.72; }
/* The Brain's suggestion chip in the channel row: the wordmark gradient on
   the icon, blue when the suggestion is open under it. */
.ws-brain-chip { display:inline-flex; align-items:center; gap:5px; }
.ws-brain-chip .ws-brain-ico { width:14px; height:14px; color:var(--blue); }
.ws-brain-chip.on { background:color-mix(in srgb, var(--blue) 14%, transparent); color:var(--blue); border-color:transparent; }
/* A thread inside the mention popover: the same bubbles, sized for the popover. */
.hpop-thread { margin-top: 10px; }
.hpop-thread .cmt { border-radius: 10px; }
.hpop-thread .cmt .cmt-log { max-height: 42vh; padding: 10px 12px; }
.hpop-thread .cmt .msg-box { padding: 8px 10px; }
.hpop-thread .cmt .msg-box-row .msg-note { display: none; }
/* Notes on the prospect card: a line and a door. The thread is in the panel. */
.ws-notes-sum .helper { font-size:12.5px; }
/* A memo in a thread bubble: the player at a size a thumb can use, on every
   phone, with the file itself one tap away beside it. */
.tl-av { display:flex; align-items:center; gap:6px; width:100%; }
.tl-av .aud-wrap { flex:1 1 auto; min-width:0; }
.tl-atts audio { width:260px; max-width:100%; min-width:180px; height:40px; }
.tl-att-open { flex:0 0 auto; font-size:13px; text-decoration:none; opacity:.75; padding:2px 4px; }
.msg-turn.mine .tl-att-open { color:#fff; }
@media (max-width:700px) { .tl-atts audio { width:100%; min-width:200px; height:44px; } }
/* ---- the team's notes on a prospect: a panel beside the conversation -----
   Never under the messages: a note drawn there read as one more thing sent
   to the person. The panel takes a column of its own on a desk (the stage
   rail steps aside for it), the whole screen on a phone. Its entries are
   flat and yellow -- every one under its author's name, none of them the
   blue-on-the-right of a message to them. */
.ws4.noting { grid-template-columns:320px minmax(0,1fr) 340px 360px; }
:is(.ws4.noting.cardless, .ws4.noting.guide-fold) { grid-template-columns:320px minmax(0,1fr) 340px; }
.ws4.noting .ws-rail { display:none; }
.ws-npanel { --note-ground:var(--tint-yellow); --note-line:color-mix(in srgb, var(--ink-yellow) 38%, transparent);
  display:flex; flex-direction:column; min-height:0; min-width:0; border-left:1px solid var(--line); background:var(--panel-2);
  animation:panelIn .18s cubic-bezier(.2,.8,.3,1); }
.ws-npanel[hidden] { display:none !important; }
.ws-npanel-head { display:flex; align-items:flex-start; gap:8px; padding:12px 12px 10px 14px; border-bottom:1px solid var(--line); background:var(--panel); }
.ws-npanel-head strong { display:block; font-size:13px; letter-spacing:-.01em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.ws-npanel-sub { display:block; font-size:10.5px; margin-top:1px; }
/* ooComments puts .cmt on the body itself: the log is its child. */
.ws-npanel-body, .ws-npanel-body.cmt { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; border:0; border-radius:0; background:transparent; }
.ws-npanel-body .cmt-log { flex:1 1 auto; min-height:0; max-height:none; padding:14px 14px 10px; gap:12px; }
.ws-npanel-body .cmt-log .msg-blank { padding:26px 14px; font-size:12.5px; }
.ws-npanel-compose { border-top:1px solid var(--line); padding:10px 12px; background:var(--panel); }
.ws-npanel-compose textarea { width:100%; resize:none; min-height:56px; max-height:220px; line-height:1.45; }
.ws-npanel-compose .ws-compose-row { margin-top:6px; }
.ws-npanel-compose #wsNoteHint { flex:1 1 100%; font-size:10.5px; line-height:1.4; }
.ws-npanel-compose .action-row { margin-left:auto; }
/* Flat entries: name on every run, all down the left, on a sticky-note ground. */
.cmt-flat .msg-turn, .cmt-flat .msg-turn.mine { align-self:stretch; align-items:flex-start; max-width:100%; }
.cmt-flat .msg-turn .msg-bubble, .cmt-flat .msg-turn.mine .msg-bubble { background:var(--note-ground, var(--tint-yellow)); color:var(--text);
  border:1px solid var(--note-line, transparent); box-shadow:none; border-radius:12px; border-top-left-radius:6px; }
.cmt-flat .msg-turn.grouped .msg-bubble, .cmt-flat .msg-turn.grouped.mine .msg-bubble { border-top-left-radius:12px; border-top-right-radius:12px; }
.cmt-flat .msg-turn .msg-bubble.gone, .cmt-flat .msg-turn.mine .msg-bubble.gone { background:transparent; border-color:transparent; color:var(--subtle); }
.cmt-flat .msg-turn.mine .msg-bubble.editing, .cmt-flat .msg-turn.mine .msg-bubble.confirming { background:var(--panel-2); border-color:var(--line); }
.cmt-flat .msg-turn.mine .msg-bubble a, .cmt-flat .msg-turn.mine .msg-bubble .mention { color:var(--blue); text-decoration:none; }
.cmt-flat .msg-turn.mine .msg-bubble .mention:hover { background:var(--tint-blue); }
.cmt-flat .msg-turn.mine .msg-reacts { justify-content:flex-start; }
.cmt-flat .msg-turn.mine .msg-replies { align-self:flex-start; }
.cmt-flat .msg-turn.mine .tl-att-open { color:inherit; }
.cmt-flat .msg-time { align-self:flex-start; }
/* The Notes button beside the channels: a chip with the count, lit while the panel is up. */
.ws-tab[data-tab="note"] { display:inline-flex; align-items:center; gap:5px; border:1px solid var(--line); border-radius:999px;
  padding:5px 11px 5px 9px; font-size:11.5px; font-weight:700; color:var(--muted); background:transparent; }
.ws-tab[data-tab="note"]:hover { color:var(--text); background:var(--lift-2); }
.ws-tab[data-tab="note"].active { background:color-mix(in srgb, var(--blue) 16%, transparent); border-color:color-mix(in srgb, var(--blue) 50%, transparent); color:var(--blue); }
.ws-tab-n { min-width:17px; height:17px; padding:0 5px; border-radius:9px; display:inline-grid; place-items:center; font-size:10px; font-weight:800; background:var(--lift-3); color:var(--text); }
.ws-tab[data-tab="note"].active .ws-tab-n { background:var(--blue-solid); color:#fff; }
.ws-tab-n[hidden] { display:none !important; }
@media (max-width:1800px) { .ws4.noting { grid-template-columns:262px minmax(0,1fr) 320px 330px; }
  :is(.ws4.noting.cardless, .ws4.noting.guide-fold) { grid-template-columns:262px minmax(0,1fr) 320px; } }
/* Narrower: the list goes too while the notes are up. You know who you are writing about. */
@media (max-width:1600px) { .ws4.noting { grid-template-columns:minmax(0,1fr) 320px 330px; } .ws4.noting .ws-list { display:none; }
  :is(.ws4.noting.cardless, .ws4.noting.guide-fold) { grid-template-columns:262px minmax(0,1fr) 320px; }
  :is(.ws4.noting.cardless, .ws4.noting.guide-fold) .ws-list { display:flex; } }
/* A small desk: the notes take the card's column; the card is back the moment they close. */
@media (max-width:1280px) { .ws4.noting { grid-template-columns:minmax(0,1fr) 320px; } .ws4.noting .ws-card { display:none; } }
/* Under 1100 the card is already a row under the grid, so it stays. */
@media (min-width:701px) and (max-width:1100px) { .ws4.noting { grid-template-columns:minmax(0,1fr) 300px; } .ws4.noting .ws-card { display:flex; }
  :is(.ws4.noting.cardless, .ws4.noting.guide-fold) .ws-card { display:none; } }
@media (max-width:760px) { .ws4.noting { grid-template-columns:1fr; } }
/* A phone: the notes are a sheet over the thread, like the person card, and
   they follow the keyboard the way the thread does (fitWorkspace sizes .ws4). */
@media (max-width:700px) {
  .ws4:not(.nobody) .ws-npanel { display:none; }
  body.ws-notes-open .ws4:not(.nobody) .ws-npanel { display:flex; position:absolute; inset:0; z-index:66; border:0; background:var(--panel); animation:hpopIn .16s ease; }
  .ws-npanel-head { padding:calc(10px + env(safe-area-inset-top, 0px)) 10px 8px 14px; }
  .ws-npanel-head strong { font-size:16px; }
  .ws-npanel-head .msg-x { width:36px; height:36px; }
  .ws-npanel-body .cmt-log { padding:12px 10px; overscroll-behavior:contain; -webkit-overflow-scrolling:touch; }
  .ws-npanel-compose { padding:6px 8px calc(8px + env(safe-area-inset-bottom, 0px)); display:flex; flex-wrap:wrap; align-items:flex-end; gap:6px; }
  .ws-npanel-compose #wsNoteAtts { flex:0 0 100%; }
  .ws-npanel-compose textarea { flex:1 1 0; min-width:0; width:auto; min-height:40px; max-height:160px; padding:9px 14px; border-radius:20px; font-size:16px; line-height:1.35; }
  .ws-npanel-compose .ws-compose-row { flex:0 0 auto; margin:0; gap:6px; }
  .ws-npanel-compose .action-row { margin:0; gap:6px; flex-wrap:nowrap; }
}

/* ClickUp on its way out: what the hourly watch found, on the Dashboard.
   Temporary by design -- it hides itself once nothing has been written over
   there for three weeks. */
.cu-list { margin: 8px 0 0; padding-left: 18px; }
.cu-list li { font-size: 13.5px; margin: 3px 0; }
.cu-diffs { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.cu-diff { display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; padding: 8px 10px; border: 1px solid var(--line);
  border-radius: 10px; background: var(--panel-2); margin-top: 6px; }
.cu-diff-who { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cu-diff-who b { font-size: 14px; }
.cu-diff-who .helper { font-size: 12.5px; }
.cu-diff .action-row { flex: 0 0 auto; gap: 6px; }

/* Refresh, in the top bar of the installed app only: a browser already has
   one in its address bar, and a second would be clutter. Pages poll and redraw
   themselves when the app comes back to the front; this is for the moment
   somebody does not want to wait. */
.tb-reload { display: none; }
@media (display-mode: standalone) { .tb-reload { display: inline-flex; } }
html[data-standalone] .tb-reload { display: inline-flex; }

/* What a link points at, under the message that carries it.

   Small on purpose: a card the size of the message is a webpage in a chat.
   One line of site, one of title, one of description, and a thumbnail only
   when the page has a real one. It sits inside the bubble, so it is carried
   by the same colour and the same corner radius as the words above it. */
.lp-holder { display: block; }
/* A bubble underlines its links; the card is a card, not a link in a
   sentence, so it takes its own ink back (.msg-bubble a would win otherwise). */
.msg-bubble .lp, .hpop-bubble .lp, .msg-bubble .lp:hover, .hpop-bubble .lp:hover {
  text-decoration: none; color: var(--text); }
.msg-bubble .lp .lp-title, .hpop-bubble .lp .lp-title { text-decoration: none; }
.lp { display: flex; gap: 10px; align-items: stretch; margin-top: 8px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel);
  text-decoration: none; color: var(--text); max-width: 420px;
  transition: border-color .14s ease, transform .14s ease; }
.lp:hover { border-color: var(--line-strong); transform: translateY(-1px); }
.lp-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; justify-content: center; }
.lp-site { display: flex; align-items: center; gap: 5px; font-size: 10.5px; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase; color: var(--subtle);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lp-fav { width: 12px; height: 12px; border-radius: 3px; object-fit: contain; flex: 0 0 auto; }
.lp-title { font-size: 13px; font-weight: 650; line-height: 1.3; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.lp-desc { font-size: 11.5px; line-height: 1.35; color: var(--muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.lp-img { position: relative; flex: 0 0 auto; width: 76px; border-radius: 7px; overflow: hidden; background: var(--lift-2); }
.lp-img img { display: block; width: 100%; height: 100%; min-height: 54px; max-height: 76px; object-fit: cover; }
/* A video says so: the still gets the triangle every player uses. */
.lp-play { position: absolute; inset: 0; display: grid; place-items: center; color: #fff;
  background: rgba(10,12,16,.28); }
.lp-play svg { filter: drop-shadow(0 1px 3px rgba(0,0,0,.5)); }
/* How long it runs, where every player puts it. */
.lp-len { position: absolute; right: 3px; bottom: 3px; padding: 0 4px; border-radius: 4px;
  background: rgba(10,12,16,.82); color: #fff; font-size: 9.5px; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.lp-len.flat { position: static; background: var(--lift-3); color: var(--muted); margin-left: 4px; }
/* The Brain's sentence, marked as the Brain's. */
.lp-brain { display: flex; gap: 5px; align-items: flex-start; }
.lp-brain-ico { flex: 0 0 auto; margin-top: 2px; color: var(--blue); }
.msg-turn.mine .msg-bubble .lp .lp-brain-ico { color: rgba(255,255,255,.85); }
/* In a blue bubble the card keeps its own quiet ground rather than fighting it. */
.msg-turn.mine .msg-bubble .lp, .hpop-turn.mine .hpop-bubble .lp {
  background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.28); color: #fff; }
.msg-turn.mine .msg-bubble .lp .lp-title, .hpop-turn.mine .hpop-bubble .lp .lp-title { color: #fff; }
.msg-turn.mine .msg-bubble .lp .lp-site, .msg-turn.mine .msg-bubble .lp .lp-desc,
.hpop-turn.mine .hpop-bubble .lp .lp-site, .hpop-turn.mine .hpop-bubble .lp .lp-desc { color: rgba(255,255,255,.82); }
.msg-turn.mine .msg-bubble .lp:hover { border-color: rgba(255,255,255,.5); }
/* Notes are flat and yellow; the card follows the ground it is on. */
.cmt-flat .msg-bubble .lp { background: var(--panel); border-color: var(--line); }
@media (max-width: 700px) { .lp { max-width: none; } .lp-img { width: 64px; } }

/* While the guide is open on a desk under 1750px there is not room for the
   rail, the list, the conversation, the card and the guide: the card folds
   for the duration (guide-fold) and comes back when the guide closes, without
   touching what the person had chosen. The rail stays because the guide is
   mostly about the rail, but it and the list take their compact widths so the
   conversation keeps a readable column. */
@media (min-width:1100px) { body.guide-open .ws4.guide-fold:not(.noting):not(.nobody) { grid-template-columns:190px 240px minmax(0,1fr); } }
/* With nobody open the list keeps the whole room, guide or no guide. */
.ws4.nobody.guide-fold { grid-template-columns:236px minmax(0,1fr); }

/* The ClickUp strip, on a day when ClickUp has nothing to say. It keeps its
   two buttons -- "Check now" and "Compare statuses" are the reason it exists
   -- and gives up the heading, the explanation and most of its height. */
#cuSection.cu-quiet { margin-bottom: 10px; }
#cuSection.cu-quiet .section-head { margin-bottom: 0; align-items: center; }
#cuSection.cu-quiet h2 { display: none; }
#cuSection.cu-quiet #cuSub { display: block; font-size: 12px; margin: 0; color: var(--subtle); }
#cuSection.cu-quiet .action-row .button { font-size: 12px; padding: 3px 9px; }

/* Who may look at your day, on the Account page's Google card. */
.gcal-share { display:flex; align-items:center; gap:10px; padding:4px 0; }
.gcal-share > span { flex:1; font-size:13px; }
.gcal-share select { width:auto; min-width:190px; font-size:12px; padding:5px 8px; }

/* The playback-speed menu on a voice memo: Slack's, because Slack's is right.
   Click the pill, see every speed at once, pick one. */
.aud-menu { position:fixed; z-index:95; min-width:148px; padding:6px; background:var(--panel);
  border:1px solid var(--line-strong); border-radius:11px; box-shadow:var(--shadow-lg); }
.aud-menu-h { font-size:11px; letter-spacing:.04em; color:var(--subtle); padding:3px 9px 6px; }
.aud-menu-i { display:flex; align-items:center; gap:8px; width:100%; text-align:left; border:0;
  background:none; color:var(--text); font:inherit; font-size:13px; padding:6px 9px;
  border-radius:7px; cursor:pointer; }
.aud-menu-i:hover { background:var(--lift-3); }
.aud-menu-i.on { color:var(--blue); font-weight:600; }
.aud-tick { width:12px; flex:none; color:var(--blue); }

/* Asking for the follow-up note the moment a date is set: a ring, not a
   dialog, so somebody in a hurry can still ignore it. */
.heat-note-ask { border-color: var(--blue) !important;
  box-shadow: 0 0 0 3px var(--tint-blue); animation: heat-note-pop .4s ease; }
@keyframes heat-note-pop { from { box-shadow: 0 0 0 0 var(--tint-blue); } }

/* The follow-up board on the Sales Floor. One table, read top to bottom, with
   a rule between the bands -- the four separate cards it started as were four
   headings and a lot of scrolling for a list nobody reads out of order. */
.fu-tabs { display:inline-flex; gap:3px; padding:4px; border:1px solid var(--line);
  border-radius:12px; background:var(--lift-1); margin:0 0 12px; flex-wrap:wrap; }
.fu-tab { display:inline-flex; align-items:center; gap:7px; border:0; background:none;
  color:var(--muted); font:inherit; font-size:13px; font-weight:600; padding:7px 13px;
  border-radius:9px; cursor:pointer; }
.fu-tab b { font-size:11.5px; font-weight:700; padding:1px 6px; border-radius:999px;
  background:var(--lift-3); color:var(--muted); }
.fu-tab:hover { color:var(--text); }
.fu-tab.on { background:var(--panel); color:var(--text); box-shadow:var(--shadow-sm); }
.fu-tab.on b { background:var(--tint-blue); color:var(--blue); }
.fu-tab.over b { background:var(--tint-red); color:var(--ink-bad); }
.fu-bar { display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin:0 0 14px; }
.fu-bar .gap { flex:1; }

.fu-card { padding:0; overflow:hidden; }
.fu-table { width:100%; }
.fu-table th { font-size:11px; letter-spacing:.05em; text-transform:uppercase; color:var(--subtle); }
.fu-table td { padding:9px 12px; vertical-align:middle; }
.fu-sep td { padding:7px 12px 5px; font-size:11px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--subtle); background:var(--lift-1); border-top:1px solid var(--line); }
.fu-sep.over td { color:var(--ink-bad); background:var(--tint-red); }
.fu-row { border-top:1px solid var(--line); transition:opacity .18s ease, transform .18s ease; }
.fu-row:hover { background:var(--lift-1); }
.fu-row.fu-gone { opacity:0; transform:translateX(14px); }

.fu-c-tick { width:40px; }
.fu-tick { border:0; background:none; color:var(--subtle); cursor:pointer; padding:2px;
  display:flex; align-items:center; border-radius:50%; }
.fu-tick:hover { color:var(--green); background:var(--tint-green); }
.fu-what b { display:block; font-size:13.5px; }
.fu-what span { display:block; font-size:12.5px; color:var(--muted); overflow-wrap:anywhere; }
.fu-nonote { color:var(--subtle); }
.fu-who b { font-size:13.5px; cursor:pointer; }
.fu-who b:hover { color:var(--blue); text-decoration:underline; }
.fu-who .badge { margin-left:6px; }
.fu-who .helper { display:block; font-size:11.5px; }
.fu-c-own { white-space:nowrap; }
.fu-c-set, .fu-c-due { white-space:nowrap; }
.fu-c-set b, .fu-c-due b { display:block; font-size:13px; }
.fu-c-set span, .fu-c-due span { font-size:11.5px; color:var(--muted); }
.fu-c-set b { font-weight:500; color:var(--muted); }
/* Overdue is red, date and all -- not just the little line underneath it. */
.fu-row.late .fu-c-due b, .fu-row.late .fu-c-due span { color:var(--ink-bad); font-weight:600; }
.fu-c-act { white-space:nowrap; text-align:right; }
.fu-heat { color:var(--amber); font-size:11px; letter-spacing:1px; margin-left:6px; }

/* The two follow-up fields on the client card, stacked. */
.heat-fu { display:flex; flex-direction:column; gap:6px; }

@media (max-width:860px) {
  .fu-table thead { display:none; }
  .fu-table tr { display:grid; grid-template-columns:40px minmax(0,1fr) auto; }
  .fu-table .fu-what { grid-column:2; }
  .fu-table .fu-who { grid-column:2; }
  .fu-c-own, .fu-c-set { display:none; }
  .fu-c-due, .fu-c-act { grid-column:3; text-align:right; }
  .fu-sep td { grid-column:1 / -1; }
}

/* A due count on a subnav tab — same red as the rail's, so it reads the same
   wherever you meet it. */
.subnav-tab .tab-badge { margin-left:7px; }

/* Given to others: who it went to, and how many of theirs are late. A task you
   hand over leaves your board, so this column is the only place it is ever
   seen again — it has to say when one has gone past its date. */
.tkc-late { font-size:11px; font-weight:700; padding:2px 8px; border-radius:999px;
  background:var(--alarm-bg); color:var(--alarm-ink); margin-left:6px; white-space:nowrap; }
.tkc-who-filter { display:flex; gap:4px; flex-wrap:wrap; padding:0 2px 8px; }
.tkw { display:inline-flex; align-items:center; gap:5px; border:1px solid var(--line);
  background:var(--panel); color:var(--muted); border-radius:999px; font:inherit;
  font-size:11.5px; padding:3px 9px; cursor:pointer; }
.tkw:hover { background:var(--lift-2); color:var(--text); }
.tkw b { font-size:10.5px; font-weight:700; padding:0 5px; border-radius:999px;
  background:var(--lift-3); color:var(--muted); }
.tkw.on { background:var(--tint-blue); border-color:var(--blue-line); color:var(--blue); font-weight:600; }
.tkw.on b { background:var(--blue-solid); color:#fff; }
.tkw.late b { background:var(--tint-red); color:var(--ink-bad); }
.tkw.late.on b { background:var(--alarm-bg); color:var(--alarm-ink); }

/* Task columns drag by their grip, and look while dragging exactly like the
   sidebar's entries do — same faded original, same blue wash on what is about
   to be displaced. One drag gesture in the app, not two. */
.tkc-grip { display:none; color:var(--subtle); cursor:grab; fill:currentColor;
  margin-right:2px; align-items:center; }
.tkc-grip:active { cursor:grabbing; }
.tkc-head:hover .tkc-grip { display:inline-flex; opacity:.55; }
.tkc-grip:hover { opacity:1 !important; color:var(--blue); }
.tkc-dragging { opacity:.35; }
.tkc-drag-over { background:color-mix(in srgb, var(--blue) 8%, transparent); border-radius:12px; }
/* The late count on the "Assigned to others" toggle. */
.tk-late-n { margin-left:6px; font-size:10.5px; font-weight:700; padding:1px 6px;
  border-radius:999px; background:var(--alarm-bg); color:var(--alarm-ink); }

/* Grid layout for the task board: the same columns, wrapped onto as many rows
   as they need. Three lists of two tasks each should not cost a sideways
   scroll — Stefan, 09-19-2026: "if I only have two to three tasks in each of
   those, I'd like ... to stack them top to bottom as well." */
#tkBoard.tk-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(268px, 1fr));
  align-items:start; gap:14px; overflow-x:visible; }
#tkBoard.tk-grid .tkc { width:auto; min-width:0; flex:none; }
/* A long list must not make its whole row tall: it scrolls inside itself. */
#tkBoard.tk-grid .tkc-body { max-height:46vh; overflow-y:auto; }
#tkBoard.tk-grid .tkc-new { align-self:start; }

/* List: the board read straight down instead of across — every list a
   heading, every task a full-width row with its dates and people on the right
   and its description underneath. Stefan, 09-19-2026: "not rows ... column
   like the task list on GHL layout (like our resource page kind of)". The
   same rows, the same drag, the same everything the cards do: only the shape
   changes. */
#tkBoard.tk-list { display:block; overflow-x:visible; max-width:1060px; }
#tkBoard.tk-list .tkc { width:auto; min-width:0; flex:none; margin:0 0 14px;
  padding:0; border:0; border-radius:0; background:none; box-shadow:none;
  overflow:visible; }
/* A section is not a card: no corner glow bleeding out at the margin, and it
   does not lift under the cursor — the rows inside it do. */
#tkBoard.tk-list .tkc::after { display:none; }
#tkBoard.tk-list .tkc:hover { transform:none; box-shadow:none; }
/* A section heading, not a card title: the name, then what is in it, then the
   controls out at the right where the rows end. */
#tkBoard.tk-list .tkc-head { padding:0 2px 4px; margin-bottom:5px; border-bottom:0; }
#tkBoard.tk-list .tkc-head h2 { flex:0 0 auto; font-size:11.5px; font-weight:750;
  letter-spacing:.05em; text-transform:uppercase; color:var(--muted); }
#tkBoard.tk-list .tkc-head [data-rename] { margin-left:auto; }
#tkBoard.tk-list .tkc-assigned .tkc-head h2 { color:var(--blue); }
#tkBoard.tk-list .tkc-body { max-height:none; overflow:hidden; gap:0; min-height:0;
  background:var(--panel); border:1px solid var(--line); border-radius:11px; }
#tkBoard.tk-list .tkt { align-items:center; padding:7px 11px; border-radius:0; }
#tkBoard.tk-list .tkt + .tkt { border-top:1px solid var(--line); }
#tkBoard.tk-list .tkt:hover { background:var(--lift-2); }
#tkBoard.tk-list .tkt-grip, #tkBoard.tk-list .tkt-tick, #tkBoard.tk-list .tkt-star { margin-top:0; }
/* Title and dates share the first line, the description sits under them —
   GHL's shape, and the shelf's. */
#tkBoard.tk-list .tkt-body { display:flex; align-items:center; flex-wrap:wrap; gap:1px 14px; }
#tkBoard.tk-list .tkt-text { flex:1 1 55%; font-size:13px; }
#tkBoard.tk-list .tkt-meta { order:2; flex:0 0 auto; margin-top:0; flex-wrap:nowrap; }
#tkBoard.tk-list .tkt-note { order:3; flex:1 1 100%; margin-top:0; -webkit-line-clamp:1; }
#tkBoard.tk-list .tkt-link { order:4; flex:1 1 100%; }
#tkBoard.tk-list .tkc-add { width:auto; padding:3px 6px; margin-bottom:4px; }
#tkBoard.tk-list .tkc-empty { padding:7px 11px; }
#tkBoard.tk-list .tkc-done { margin-top:6px; }
#tkBoard.tk-list .tkc-new { max-width:380px; }
#tkBoard.tk-list .tkc-input { max-width:640px; }
