/* ---------------------------------------------------------------------------
   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;
  --blue: #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: #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%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: rgba(67,135,245,.16);
  --blue-line: rgba(67,135,245,.45);
  --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);

}

/* 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: #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: rgba(47,111,208,.16);
  --blue-line: rgba(47,111,208,.40);
  --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: #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: rgba(47,111,208,.16); --tint-green: rgba(18,128,90,.17);
    --blue-line: rgba(47,111,208,.40);
    --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); }
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: 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), var(--violet)); box-shadow: 0 8px 24px rgba(79,70,229,.3); 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; }
.nav-item:hover { background: var(--lift-2); color: var(--text); }
.nav-item.active { color: white; background: linear-gradient(90deg, rgba(67,135,245,.18), rgba(67,135,245,.04)); 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 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: rgba(67,135,245,.2);
  box-shadow: inset 0 0 0 1px rgba(67,135,245,.4); }

/* 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; }
.topbar { min-height: 72px; border-bottom: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.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: #3a7ae8; 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: rgba(67,135,245,.16); border-color: rgba(67,135,245,.5); 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, rgba(67,135,245,.13)), 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(#6ea7ff, 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:rgba(67,135,245,.12); } .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); }
.toast { position:fixed; right:18px; bottom:18px; z-index:10; border:1px solid rgba(53,201,143,.35); background:var(--tint-green); color:var(--green); border-radius:9px; padding:10px 12px; box-shadow:var(--shadow); font-size:12px; transform:translateY(10px); opacity:0; pointer-events:none; transition:.18s ease; }
.toast.show { transform:translateY(0); opacity:1; }
.toast.error { border-color: rgba(251,100,114,.4); background:var(--tint-red); color:var(--red); }
.toast { pointer-events:auto; display:flex; align-items:center; gap:10px; max-width:min(440px, calc(100vw - 36px)); }
.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,.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; } }
@media (max-width:680px) { main { padding:0 14px 26px; } .topbar { min-height:64px; } .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:rgba(67,135,245,.16); 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:rgba(67,135,245,.3); background:rgba(67,135,245,.06); }
.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:rgba(67,135,245,.08); 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:rgba(67,135,245,.10); border:1px solid rgba(67,135,245,.32); }
.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:rgba(67,135,245,.16); 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 rgba(67,135,245,.14); }
.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); background:var(--tint-blue); cursor:pointer; white-space:nowrap;
  transition:background .14s ease, color .14s ease; }
.gs-brain-ico { width:15px; height:15px; }
.gs-brain:hover, .gs-brain[aria-expanded="true"] { background:var(--blue-solid);
  color:var(--on-accent); }
.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:rgba(67,135,245,.14); 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 { padding:8px 10px; border-radius:8px; font-size:12px; color:var(--muted);
  text-decoration:none; }
.tb-menu a: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 rgba(67,135,245,.14); }
.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; }


/* ---- 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,#4387f5); 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 drag handle is absolutely positioned at right:6px, so margins on it do
   nothing -- and the star's margin-left:auto parks it in the same place. Give
   the star a right margin wide enough to clear the handle, or the two hit
   targets sit on top of each other and it is luck which one you get. */
.nav-star { margin-right:22px; }

/* 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,rgba(67,135,245,.18)); 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:rgba(67,135,245,.06); }

/* 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(--blue), #3a76d8);
  box-shadow:0 4px 14px rgba(67,135,245,.28);
  transition:transform .12s ease, box-shadow .15s ease; }
.ai-new:hover { box-shadow:0 6px 18px rgba(67,135,245,.4); }
.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,
  rgba(67,135,245,.20), rgba(67,135,245,.05)); }
.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:rgba(67,135,245,.16);
  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:rgba(67,135,245,.6);
  box-shadow:0 0 0 3px rgba(67,135,245,.14); }
.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(--blue), #3a76d8);
  box-shadow:0 4px 12px rgba(67,135,245,.32);
  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,
  rgba(67,135,245,.14), rgba(67,135,245,.03)); }
.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,
  rgba(67,135,245,.20), rgba(67,135,245,.05)); }
.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; }
.msg-person-last { font-size:11.5px; color:var(--subtle); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.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); color:#fff; font-size:9.5px; font-weight:800;
  display:grid; place-items:center; box-shadow:0 2px 8px rgba(67,135,245,.45); }

.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(--blue), #3a76d8); border-color:transparent; color:#fff;
  border-bottom-right-radius:6px; box-shadow:0 4px 14px rgba(67,135,245,.28); }
.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:rgba(67,135,245,.16);
  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; }
.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 rgba(67,135,245,.14); }
@media (hover: none) { .msg-more { opacity:.45; pointer-events:auto; } }

.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:rgba(67,135,245,.14); 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:rgba(67,135,245,.12);
  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:rgba(67,135,245,.2);
  border-color:rgba(67,135,245,.36); }
.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:rgba(67,135,245,.2); }
.msg-replies.fresh::after { content:""; width:6px; height:6px; border-radius:50%;
  background:var(--blue); box-shadow:0 0 0 3px rgba(67,135,245,.2); }

/* 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 rgba(67,135,245,.14); }
.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); 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); }

.msg-box { display:flex; gap:10px; padding:14px 18px 8px;
  border-top:1px solid var(--line); background:var(--panel-2); }
.msg-box textarea { flex:1; resize:none; font-size:13.5px; line-height:1.5;
  padding:10px 13px; border-radius:11px; 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 rgba(67,135,245,.14); }
.msg-box .button { align-self:flex-end; }
.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, rgba(67,135,245,.18), rgba(139,92,246,.14));
  border:1px solid rgba(67,135,245,.22); }

/* 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; }
/* 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:rgba(67,135,245,.14); 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); 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:rgba(67,135,245,.16); 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; 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:rgba(67,135,245,.14); 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. */
.hpop { position:fixed; z-index:70; width:380px; max-height:min(560px, 78vh);
  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); 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 rgba(67,135,245,.14); }
.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); 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 { display:flex; align-items:flex-end; gap:7px; padding:9px 10px;
  border-top:1px solid var(--line); background:var(--panel-2);
  position:sticky; bottom:0; }
.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 rgba(67,135,245,.14); }
.hpop-send { display:grid; place-items:center; width:32px; height:32px;
  border-radius:9px; border:0; background:var(--blue); 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-note { display:flex; align-items:flex-start; gap:9px; padding:11px 12px;
  border-bottom:1px solid var(--line); }
.hpop-note-body { flex:1; min-width:0; }
.hpop-note-line { 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 { margin:3px 0 0; font-size:11.5px; line-height:1.45;
  color:var(--subtle); overflow-wrap:anywhere; }
.hpop-go { flex:0 0 auto; padding:4px 10px; border-radius:7px; font-size:11px;
  font-weight:650; text-decoration:none; color:var(--muted);
  border:1px solid var(--line); transition:color .14s ease, border-color .14s ease; }
.hpop-go:hover { color:var(--blue); border-color:rgba(67,135,245,.4); }

/* 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:rgba(67,135,245,.1); 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:rgba(67,135,245,.2); }

/* 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 rgba(67,135,245,.45); }
.msg-turn.threaded.mine .msg-bubble { box-shadow:0 0 0 2px rgba(255,255,255,.5),
  0 4px 14px rgba(67,135,245,.28); }
.msg-replies.open { background:rgba(67,135,245,.22);
  border-color:rgba(67,135,245,.45); }

/* 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:rgba(67,135,245,.12); border:1px solid rgba(67,135,245,.3); }
.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:rgba(67,135,245,.1); }
.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 rgba(67,135,245,.14); }

.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); }
.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 rgba(67,135,245,.16); }

.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 rgba(67,135,245,.14); }
.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:rgba(67,135,245,.16); 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 rgba(67,135,245,.14); }
.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 rgba(67,135,245,.14); }
/* 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); 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 rgba(67,135,245,.14); }
.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:rgba(67,135,245,.1); }
.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:rgba(67,135,245,.14); }
.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:rgba(67,135,245,.16);
  border:1px solid rgba(67,135,245,.34); }
.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:rgba(67,135,245,.5);
  background:rgba(67,135,245,.1); }


/* 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:rgba(67,135,245,.45); }
.filedrop.over { border-color:var(--blue); background:rgba(67,135,245,.1);
  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); 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-auto { display: block; }
:root[data-theme="dark"] .theme-toggle .th-auto,
:root[data-theme="light"] .theme-toggle .th-auto { display: none; }
:root[data-theme="dark"] .theme-toggle .th-moon { display: block; }
:root[data-theme="light"] .theme-toggle .th-sun { display: block; }

/* 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 rgba(47,111,208,.22); }
: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: .5; text-decoration: line-through; }
.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; }
@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; }
.tkc-input input { font-size: 13px; }
.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; }

/* One task */
.tkt { display: flex; gap: 9px; align-items: flex-start; padding: 8px 6px;
  border-radius: 9px; cursor: grab; transition: background .14s ease; }
.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); border-color: var(--blue); }
.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 */
  html, body { overflow-x: hidden; }
  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 { flex-direction: row; flex-wrap: wrap; gap: 4px; padding: 6px; }
  .ibx-rail .ibx-rail-head { flex-basis: 100%; border-top: 0; margin: 0; padding: 8px 8px 2px; }
  .ibx-nav { width: auto; padding: 7px 10px; }
  .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. */
.renew-scroll { max-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; }


/* ---- 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 rgba(67,135,245,.55); } 100% { box-shadow:0 0 0 3px rgba(67,135,245,0); } }
.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; color:var(--muted); }
.heat-when input { width:150px; }
.heat-note { margin-top:2px; }
.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:rgba(67,135,245,.12); }
.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:rgba(67,135,245,.08); }
.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); }
.ws-list-head input { flex:1; min-width:0; }
.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:rgba(67,135,245,.12); 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:rgba(67,135,245,.10); 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); }
.ws-pill.s-pitched { background:rgba(67,135,245,.14); 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); }
.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); }
.ws-timeline { flex:1; max-height:none; border:0; border-radius:0; background:var(--lift-1); }
.ws-compose { border-top:1px solid var(--line); padding:10px 12px; }
.ws-compose textarea { width:100%; resize:vertical; min-height:56px; }
.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:200px 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; }
.ws-rail-title .helper { font-weight:500; letter-spacing:0; text-transform:none; font-size:10px; }
.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; }
.ws-rail-item:hover { background:var(--lift-2); color:var(--text); }
.ws-rail-item.active { background:rgba(67,135,245,.12); color:var(--blue); }
.ws-rail-item.active b { color:var(--blue); }
.ws-rail-item.over { border-color:var(--blue); background:rgba(67,135,245,.14); color:var(--blue); }
.ws-list { border-right:1px solid var(--line); display:flex; flex-direction:column; min-height:0; }
.ws-list-sub { padding:6px 12px; font-size:11px; color:var(--subtle); border-bottom:1px solid var(--line); }
.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:rgba(67,135,245,.10); 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; }
.ws-dot { position:absolute; right:12px; bottom:12px; width:8px; height:8px; border-radius:50%; background:#e5484d; }
.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-tabs { display:flex; gap:4px; margin-bottom:6px; }
.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); }
.ws-next { margin-bottom:8px; padding:8px 10px; border:1px dashed rgba(67,135,245,.45); border-radius:10px; background:rgba(67,135,245,.06); display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.ws-card { border-left:1px solid var(--line); min-height:0; display:flex; flex-direction:column; }
.ws-card-scroll { overflow-y:auto; 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; }
.ws-kv td { padding:2px 8px 2px 0; vertical-align:top; }
.ws-kv td:first-child { color:var(--subtle); white-space:nowrap; }
.tag-chip.sug { background:var(--lift-2); color:var(--muted); }
.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:rgba(67,135,245,.10); 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 { background:var(--lift-2); color:var(--subtle); }
.ws-pill.s-no_close { background:rgba(245,174,78,.18); color:var(--ink-warn, #b7791f); }
@media (max-width: 1560px) { .ws4 { grid-template-columns:180px 272px minmax(0,1fr) 330px; } }
@media (max-width: 1280px) { .ws4 { grid-template-columns:170px 250px minmax(0,1fr) 300px; } }
@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:rgba(67,135,245,.14); border-color:rgba(67,135,245,.5); color:var(--blue); }
.ws-chanbtn.active b { color:var(--blue); }
.ws-from { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.ws-next { flex-direction:column; align-items:stretch; gap: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; }
.ch-ig { color:#d6336c; } .ch-sms { color:#2f9e5e; } .ch-email { color:#4387f5; }
.ch-fb { color:#1877f2; } .ch-wa { color:#25a55f; } .ch-call { color:#8b5cf6; } .ch-chat { color:#f59e0b; } .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-ig { background:linear-gradient(135deg, #7c3aed 0%, #d6336c 100%); }
.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:rgba(67,135,245,.5); box-shadow:inset 3px 0 0 rgba(67,135,245,.6); 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:200px 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:340px; }
.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:rgba(67,135,245,.14); border-color:rgba(67,135,245,.5); 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; }
.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 { top:14px; bottom:auto; }
@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; } }
