/* ==========================================================================
   Corvus Command additions to the Corvus design system v2.
   corvus.css is a byte-for-byte copy of the Hub's (the upstream) and is never
   edited here. This file loads after it and holds only what Command adds.
   Never restyle a corvus.css class here; add a Command class instead.

   Sections
     1. Tokens: the eight creator colours corvus.css does not define
     2. Global fixes
     3. Shared bits: app name in the top bar, small labels, state dot, error detail
     4. Overview: layout, section heads, the roster KPI strip
     5. Overview: cross-app mirror sections
     6. Revenue panel (shared with /chatting from batch 5)
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Creator tokens.

   corvus.css defines and binds six: Lucia, Lexie, Romy, Kayla, Cherry,
   Katherine. Tyra, Sofia and Yumi are copied unchanged from Socials'
   socials.css. Evie, Kada, Leah, Sara and Vanessa are new here: they share
   mass-message post rows with the creators who already own colours.

   Derived in OKLCH against the panel tokens (#141518 dark, #f7f8fa light):
   lightness for ~6.6:1 dark / ~6.2:1 light, chroma at the gamut edge. The
   five hues are the best five-hue set on a one-degree circle by worst-mode
   separation, with hues 68-105 excluded (DESIGN.md rejects gold beside
   Lexie), assigned so creators who share a post row sit furthest apart.
   Numbers and reasoning: DESIGN.md section 2.

     token        dark      on panel   light     on panel   OKLCH hue
     --c-tyra     #9b8cff     6.60:1    #5b48c9    6.15:1    287 / 284
     --c-sofia    #17a9cb     6.58:1    #02657c    6.26:1    220 / 221
     --c-yumi     #f17c43     6.70:1    #9e3f00    6.24:1     45 /  45
     --c-evie     #ff63a3     6.58:1    #b60064    6.23:1    358
     --c-kada     #00b086     6.57:1    #006a50    6.22:1    168
     --c-leah     #00b512     6.62:1    #006c06    6.28:1    143
     --c-sara     #c778ff     6.57:1    #9300d4    6.19:1    309
     --c-vanessa  #f751ff     6.59:1    #a400ac    6.23:1    326

   Separation, OKLab dE x100, worse of the two modes: every pair of the
   fourteen >= 7.3 (the floor the nine already had); every pair with a new
   token >= 7.5. Vanessa sits 7.7 from Romy in light mode (12.8 dark): same
   hue family, so wherever the two can appear together the name label always
   travels with the dot, never a bare dot pair.

   Keys: data-creator is the creator key from the `ckey` filter, the name
   lower-cased with platform suffixes (Fansly, OF, Free OF, Paid OF) and
   "(Deleted)" removed. "Leah Blaze" keeps its own key and so the grey dot:
   it is not confirmed to be Leah (open question in design-v2/CHANGELOG.md).
   -------------------------------------------------------------------------- */
:root {
    --c-tyra: #9b8cff;
    --c-sofia: #17a9cb;
    --c-yumi: #f17c43;
    --c-evie: #ff63a3;
    --c-kada: #00b086;
    --c-leah: #00b512;
    --c-sara: #c778ff;
    --c-vanessa: #f751ff;
}
html[data-theme="light"] {
    --c-tyra: #5b48c9;
    --c-sofia: #02657c;
    --c-yumi: #9e3f00;
    --c-evie: #b60064;
    --c-kada: #006a50;
    --c-leah: #006c06;
    --c-sara: #9300d4;
    --c-vanessa: #a400ac;
}
[data-creator="tyra"]    { --creator: var(--c-tyra); }
[data-creator="sofia"]   { --creator: var(--c-sofia); }
[data-creator="yumi"]    { --creator: var(--c-yumi); }
[data-creator="evie"]    { --creator: var(--c-evie); }
[data-creator="kada"]    { --creator: var(--c-kada); }
[data-creator="leah"]    { --creator: var(--c-leah); }
[data-creator="sara"]    { --creator: var(--c-sara); }
[data-creator="vanessa"] { --creator: var(--c-vanessa); }
/* "Lexi" as well as "Lexie", as in socials.css: the persona is written both ways. */
[data-creator="lexi"]    { --creator: var(--c-lexie); }

/* --------------------------------------------------------------------------
   2. Global fixes.
   -------------------------------------------------------------------------- */

/* The hidden attribute must beat component display values (Studio and Socials
   carry the same rule for the same reason). */
[hidden] { display: none !important; }

/* Upstream declares `.show-sm { display: none; }` after the 699px rule that
   shows it, so the utility never appears. Restated here, after corvus.css,
   until the Hub corrects the order (recorded under Upstream in the changelog). */
@media (max-width: 699px) {
    .show-sm { display: block; margin-top: 4px; }
}

/* --------------------------------------------------------------------------
   3. Shared bits.
   -------------------------------------------------------------------------- */

/* The app name beside the wordmark in the narrow-screen top bar (Studio and Socials do the same). */
.wordmark-app { color: var(--ink-3); font-weight: 500; margin-left: 4px; }

/* corvus.css's small grey label, unscoped (Socials generalises it the same way). */
.k { font-size: var(--t-xs); color: var(--ink-3); }

.visually-hidden {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* A steady dot for "Live": these sections are read on every load, they do not poll, so the dot
   does not pulse (Socials' pulsing dot marks a panel that polls). */
.state-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--good); flex: none; }

.empty-sm { padding: 8px 0; font-size: var(--t-sm); color: var(--ink-3); }

/* The raw exception behind an Unreachable section, folded away. */
.err-detail { margin-top: 6px; font-size: var(--t-sm); }
.err-detail summary { cursor: pointer; color: var(--ink-2); }
.err-detail code {
    display: block; margin-top: 6px; white-space: pre-wrap; overflow-wrap: anywhere;
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: var(--t-xs); color: var(--ink-2);
}
.delta svg { width: 12px; height: 12px; vertical-align: -1px; margin-right: 2px; stroke-width: 2; }

/* --------------------------------------------------------------------------
   4. Overview: layout and the roster strip.
   -------------------------------------------------------------------------- */
.ov { display: flex; flex-direction: column; gap: var(--s-4); }
.ov > .page-head, .ov > .stack-alerts { margin-bottom: 0; }

/* A heading for a group of panels (not itself a panel). */
.section-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px var(--s-3); margin-top: var(--s-3); }
.section-head h2 { font-size: var(--t-md); }

/* The roster strip carries five figures, each a link to its roster page. */
.kpis-5 { overflow: hidden; }
.kpi-link { color: inherit; transition: background var(--dur-1); }
.kpi-link:hover { background: var(--hover); color: inherit; }
.kpi-link:hover .kpi-label { color: var(--ink); }
@media (min-width: 1181px) {
    .kpis-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
/* 901-1180: upstream steps to 3-up, which would leave a hole after the fifth figure; 3 + 2 spans
   fill both rows instead, and upstream's divider rules for the 4th and 5th still fit. */
@media (min-width: 901px) and (max-width: 1180px) {
    .kpis-5 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
    .kpis-5 .kpi { grid-column: span 2; }
    .kpis-5 .kpi:nth-child(n+4) { grid-column: span 3; }
}
@media (max-width: 900px) {
    .kpis-5 .kpi:last-child { grid-column: 1 / -1; }
}

/* --------------------------------------------------------------------------
   5. Overview: cross-app mirror sections.

   Every app gets the same section: the app's switcher icon and name, its state badge, a link out,
   its figures, its detail lists. Full-width sections put the figures in a left column and the
   lists beside them; Corvus Hub and Corvus Studio, which carry figures only, share a row.
   -------------------------------------------------------------------------- */
.mirror .panel-head h2 svg, .rev-panel .panel-head h2 svg { color: var(--ink-3); }

.mirror-body { display: grid; grid-template-columns: minmax(200px, 260px) minmax(0, 1fr); box-shadow: inset 0 1px 0 var(--line); }
.mirror-kpis { display: flex; flex-direction: column; }
.mirror .mirror-kpis .kpi { box-shadow: none; }
.mirror .mirror-kpis .kpi + .kpi { box-shadow: inset 0 1px 0 var(--line); }
.mirror-detail {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-3) var(--s-6);
    align-content: start; padding: var(--s-3) var(--s-4) var(--s-4); box-shadow: inset 1px 0 0 var(--line);
}
.mirror-detail.one { grid-template-columns: minmax(0, 1fr); }
.mini { min-width: 0; }
.mini > .k { margin: 2px 0 4px; }
.tbl.mini-tbl td { padding: 7px 0; }
.tbl.mini-tbl td:first-child { padding-left: 0; }
.tbl.mini-tbl td:last-child { padding-right: 0; }
.tbl.mini-tbl tbody tr:hover td { background: transparent; }
.tbl.mini-tbl tr.mini-total td { box-shadow: inset 0 1px 0 var(--line-strong); font-weight: 600; }
.tbl.mini-tbl .strong { font-weight: 600; color: var(--ink); }
.tbl.mini-tbl .st { height: 20px; margin-left: 6px; }

.mirror-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); box-shadow: inset 0 1px 0 var(--line); }
.mirror-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4); }
.mirror-pair > .panel { display: flex; flex-direction: column; }
.mirror-pair > .panel > .panel-foot { margin-top: auto; }
.mirror-foot { flex-wrap: wrap; row-gap: 6px; }
.mirror-foot-end { margin-left: auto; }
/* Studio's viral count: emphasised while there is at least one viral reel, as the old page
   highlighted it; quiet at zero. Neutral either way. */
.st-idle.st-strong b, .st-idle.st-strong svg { color: var(--ink); }
.mirror-error { padding-top: var(--s-2); }

/* Pool level: neutral meters (a pool level is a magnitude, not a verdict). */
.pool-row { grid-template-columns: minmax(110px, 180px) minmax(0, 1fr) 110px; }
.pool-row + .pool-row { margin-top: 10px; }
.pool-row .v b { color: var(--ink); font-weight: 600; }
progress.meter-neutral::-webkit-progress-value { background: var(--chart-1); }
progress.meter-neutral::-moz-progress-bar { background: var(--chart-1); }

@media (min-width: 700px) and (max-width: 900px) {
    .mirror .mirror-strip .kpi:nth-child(3) { box-shadow: inset 1px 0 0 var(--line); }
}
@media (max-width: 900px) {
    .mirror-body { grid-template-columns: minmax(0, 1fr); }
    .mirror-kpis { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
    .mirror .mirror-kpis .kpi + .kpi { box-shadow: inset 1px 0 0 var(--line); }
    .mirror-detail { grid-template-columns: minmax(0, 1fr); box-shadow: inset 0 1px 0 var(--line); }
    .mirror-pair { grid-template-columns: minmax(0, 1fr); }
    .pool-row { grid-template-columns: 100px minmax(0, 1fr) 90px; }
}
@media (max-width: 699px) {
    .mirror-kpis { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mirror .mirror-kpis .kpi:nth-child(3) { grid-column: 1 / -1; box-shadow: inset 0 1px 0 var(--line); }
    .mirror-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mirror .mirror-strip .kpi:nth-child(3) { grid-column: 1 / -1; }
    .mirror-foot-end { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   6. Revenue panel.

   Neutral throughout; creator colours appear only on creator rows (dot and share bar) and on the
   "By creator" donut, whose slices are creators, each named beside its dot. The sale types are a
   ranked share table on the neutral meter. app.js toggles .on, .show and .rev-loading; they are
   styled here.
   -------------------------------------------------------------------------- */
#revenue-panel.rev-loading { opacity: 0.55; transition: opacity var(--dur-2); }
.rev-badges { flex-wrap: wrap; justify-content: flex-end; gap: var(--s-2); }
/* Upstream keeps a panel title on one line below 700px; this one carries a scope tag, which drops
   under the title instead of running into the padding (17px over at 390, 32px at 375). */
@media (max-width: 699px) {
    .rev-panel .panel-head h2 { flex-wrap: wrap; white-space: normal; row-gap: 4px; }
    .rev-panel .panel-head h2 .tag { white-space: nowrap; }
}

.rev-controls { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2) var(--s-3); padding: 0 var(--s-4) var(--s-3); }
.rev-seg { flex-wrap: wrap; }
.rev-seg > .rev-tf.on { background: var(--raised); color: var(--ink); box-shadow: var(--shadow-1); }
/* Custom sits beside the four fixed ranges rather than in them, because it opens the date fields;
   that also keeps the ranges on one line at 375px. Sunken while a custom range is showing. */
.rev-custom-btn.on, .rev-custom-btn[aria-pressed="true"] { color: var(--ink); background: var(--bg); box-shadow: inset 0 0 0 1px var(--line-strong); }
.rev-custom { display: none; align-items: center; gap: 6px; }
.rev-custom.show { display: inline-flex; }
input[type="date"].control.rev-date { min-width: 0; width: 150px; }
.rev-sel { margin-left: auto; font-size: var(--t-sm); white-space: nowrap; }

.rev-main { display: grid; grid-template-columns: minmax(200px, 260px) minmax(0, 1fr); box-shadow: inset 0 1px 0 var(--line); }
.rev-kpis { display: flex; flex-direction: column; }
.rev-panel .rev-kpis .kpi { box-shadow: none; }
.rev-panel .rev-kpis .kpi + .kpi { box-shadow: inset 0 1px 0 var(--line); }
.rev-creators { min-width: 0; padding: var(--s-2) 0; box-shadow: inset 1px 0 0 var(--line); }
.rev-tbl td.rev-bar { width: 42%; }
/* Below 700px the bar column folds away and the same bar runs under the creator's name instead. */
.rev-tbl progress.rev-meter.show-sm { display: none; margin-top: 6px; height: 4px; }
@media (max-width: 699px) {
    .rev-tbl progress.rev-meter.show-sm { display: block; }
}
.rev-tbl .tag { margin-left: 6px; vertical-align: 1px; }
.rev-tbl tfoot td { font-weight: 600; box-shadow: inset 0 1px 0 var(--line-strong); }
progress.rev-meter {
    display: block; width: 100%; height: 6px; border: 0; border-radius: 3px; overflow: hidden;
    appearance: none; -webkit-appearance: none; background: var(--bg); box-shadow: inset 0 0 0 1px var(--line);
}
progress.rev-meter::-webkit-progress-bar { background: transparent; }
progress.rev-meter::-webkit-progress-value { background: var(--creator); border-radius: 3px; }
progress.rev-meter::-moz-progress-bar { background: var(--creator); border-radius: 3px; }

/* Splits and trend. Laid out by the panel's own width (container queries), so an open or collapsed
   sidebar never squeezes a column: the sale-type table and the creator donut sit side by side from
   760px of panel, and stack below that; the monthly bars take the full width underneath. The
   thresholds are measured: a legend beside its donut needs 400px ("RecurringSubscription" plus a
   month's "$1,234.56"), the type table's meter needs 400px, and ten upright bars need 440px. */
.rev-panel { container: rev / inline-size; }
.rev-charts { display: grid; grid-template-columns: minmax(0, 1fr); box-shadow: inset 0 1px 0 var(--line); }
.rev-splits { display: grid; grid-template-columns: minmax(0, 1fr); min-width: 0; }
.rev-charts figure { margin: 0; min-width: 0; padding: var(--s-3) var(--s-4) var(--s-4); }
.rev-splits > figure + figure, .rev-charts > .rev-growth { box-shadow: inset 0 1px 0 var(--line); }
@container rev (min-width: 760px) {
    .rev-splits { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
    .rev-splits > figure + figure { box-shadow: inset 1px 0 0 var(--line); }
}

/* Sale types: Socials' share table (Analytics, countries and devices). The figures carry the values,
   the neutral meter carries the comparison, and the meter folds away when the slot is under 400px
   because Share already says the same thing as a number. */
.rev-types { container: revtypes / inline-size; }
.rev-types .share-table { margin-top: var(--s-1); }
.rev-types .tbl td:first-child, .rev-types .tbl th:first-child { padding-left: 0; }
.rev-types .tbl td:last-child, .rev-types .tbl th:last-child { padding-right: 0; }
.rev-types .tbl tbody tr:hover td { background: transparent; }
.share-table th.meter-col, .share-table td.meter-col { width: 140px; min-width: 96px; }
.share-table td.num { font-variant-numeric: tabular-nums; }
.share-table tfoot td { font-weight: 600; box-shadow: inset 0 1px 0 var(--line-strong); }
@container revtypes (max-width: 399px) {
    .share-table .meter-col { display: none; }
    .rev-types .tbl td:nth-last-child(2), .rev-types .tbl th:nth-last-child(2) { padding-right: 0; }
}

.donut-card { container: donut / inline-size; }
.donut-row { display: flex; flex-direction: column; align-items: center; gap: var(--s-3); margin-top: var(--s-2); }
.donut-row > .donut-legend { align-self: stretch; }
@container donut (min-width: 400px) {
    .donut-row { flex-direction: row; gap: var(--s-4); }
    .donut-row > .donut-legend { align-self: center; }
}
svg.donut { width: 112px; height: 112px; flex: none; }
.donut-track { stroke: var(--bg); }
.donut .slice { stroke: var(--creator); }
.donut-center { fill: var(--ink); font-family: var(--font-sans); font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }
.donut-legend { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.leg { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); font-size: var(--t-sm); }
.leg .who { min-width: 0; }
.leg-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.leg-val { white-space: nowrap; font-variant-numeric: tabular-nums; }

.rev-growth { container: revgrowth / inline-size; }
.rev-bars { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 6px; align-items: end; height: 132px; margin-top: var(--s-2); }
.rev-gbar { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 0; height: 100%; }
.rev-gval { font-size: var(--t-xs); color: var(--ink-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.rev-gtrack { flex: 1 1 auto; display: flex; align-items: flex-end; width: 100%; max-width: 40px; }
.rev-gtrack i { display: block; width: 100%; height: var(--h); min-height: 2px; border-radius: 3px 3px 0 0; background: var(--chart-1); }
/* The month still in progress: hatched, so a partial bar never reads as a finished month. */
.rev-gbar.live .rev-gtrack i { background: repeating-linear-gradient(135deg, var(--chart-2) 0 3px, transparent 3px 6px); box-shadow: inset 0 0 0 1px var(--chart-2); }
.rev-glabel { font-size: var(--t-xs); color: var(--ink-3); }
/* Too narrow for ten upright bars and their labels: one row per month, the figure at the end. */
@container revgrowth (max-width: 439px) {
    .rev-bars { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: minmax(0, 1fr); height: auto; align-items: stretch; }
    .rev-gbar { display: grid; grid-template-columns: 32px minmax(0, 1fr) 52px; align-items: center; gap: var(--s-2); height: auto; }
    .rev-glabel { order: 1; }
    .rev-gtrack { order: 2; height: 8px; max-width: none; align-items: stretch; border-radius: 4px; overflow: hidden; background: var(--bg); box-shadow: inset 0 0 0 1px var(--line); }
    .rev-gtrack i { width: var(--h); height: 100%; border-radius: 4px; }
    .rev-gval { order: 3; text-align: right; }
}

@media (max-width: 900px) {
    .rev-main { grid-template-columns: minmax(0, 1fr); }
    .rev-kpis { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .rev-panel .rev-kpis .kpi + .kpi { box-shadow: inset 1px 0 0 var(--line); }
    .rev-creators { box-shadow: inset 0 1px 0 var(--line); }
    .rev-sel { margin-left: 0; }
    .rev-badges { justify-content: flex-start; }
}

/* --------------------------------------------------------------------------
   7. Roster pages (batch 2): client detail and Teams.

   The client detail page is Socials' creator edit page in shape: back link and title in the head,
   the table in the main column, the client's facts in a "This client" list beside it. When the table
   is narrow, personas, lane and status fold under the creator's name, the pattern DESIGN.md gives
   for secondary columns. Teams keeps its two forms and its disclosure rows; corvus.css has no <details> row, so
   the row here follows Studio's bundle editor: a quiet summary line that opens a form in place.
   -------------------------------------------------------------------------- */
.client-creators td { vertical-align: top; }
.client-creators .who { font-weight: 600; color: var(--ink); }
.client-creators .name-cell .st { height: 20px; margin-left: 6px; vertical-align: 1px; }
.client-creators td.personas { white-space: normal; font-size: var(--t-sm); color: var(--ink-2); line-height: 1.55; }
.client-creators .fold-line { display: none; }
.client-creators .cell-more { font-size: var(--t-xs); color: var(--ink-3); white-space: normal; }
.client-creators .cell-status { margin-top: 6px; }
/* The table folds by its own width, not the screen's: under 700px of panel (a phone, or 901 to 1280
   beside "This client") personas, lane and status move under the name and three columns remain. */
.client-panel { container: clienttable / inline-size; }
@container clienttable (max-width: 699px) {
    .client-creators .col-fold { display: none; }
    .client-creators .fold-line { display: block; }
    .client-creators .name-cell { white-space: normal; }
    .client-creators .name-cell .cell-status .st { margin-left: 0; }
}
.client-notes { white-space: pre-line; color: var(--ink-2); }

.teams-layout, .side-form-layout { display: grid; grid-template-columns: minmax(260px, 320px) minmax(0, 1fr); gap: var(--s-4); align-items: start; }
.team-rows, .edit-rows { box-shadow: inset 0 1px 0 var(--line); }
.team-row + .team-row, .edit-row + .edit-row { box-shadow: inset 0 1px 0 var(--line); }
.team-row > summary, .edit-row > summary {
    display: flex; align-items: center; gap: 6px var(--s-3);
    padding: 10px var(--s-4); cursor: pointer; list-style: none; user-select: none;
    transition: background var(--dur-1);
}
.team-row > summary::-webkit-details-marker, .edit-row > summary::-webkit-details-marker { display: none; }
.team-row > summary:hover, .edit-row > summary:hover { background: var(--hover); }
.team-row > summary:focus-visible, .edit-row > summary:focus-visible { outline: 2px solid var(--ink-3); outline-offset: -2px; }
.team-name, .edit-row-name { font-weight: 600; color: var(--ink); }
/* A long note wraps in its own column, so Open and Edit stay on the name's line. */
.team-notes, .edit-row-meta { flex: 1 1 auto; min-width: 0; font-size: var(--t-sm); color: var(--ink-3); overflow-wrap: anywhere; }
.team-actions, .edit-row-actions { margin-left: auto; display: inline-flex; align-items: center; gap: var(--s-2); flex: none; }
.team-edit, .edit-row-edit { display: inline-flex; align-items: center; gap: 6px; padding: 0 4px; color: var(--ink-2); font-size: var(--t-sm); font-weight: 500; }
.team-edit svg, .edit-row-edit svg { width: 14px; height: 14px; }
.team-row > summary:hover .team-edit, .team-row[open] > summary .team-edit,
.edit-row > summary:hover .edit-row-edit, .edit-row[open] > summary .edit-row-edit { color: var(--ink); }
.team-row[open] > summary, .edit-row[open] > summary { box-shadow: inset 0 -1px 0 var(--line); }
.team-edit-form { padding: var(--s-3) var(--s-4) var(--s-4); }
@media (max-width: 900px) {
    .teams-layout, .side-form-layout { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 699px) {
    .team-row > summary, .edit-row > summary { flex-wrap: wrap; }
    .team-notes, .edit-row-meta { flex-basis: 100%; order: 3; }
}

/* --------------------------------------------------------------------------
   8. Clients list and the Content section (batch 3).

   The clients list and the content pieces reuse section 7's form-beside-list layout and its
   disclosure rows, now named for what they are (.side-form-layout, .edit-row); Teams keeps its own
   class names on the same rules. An open row stacks its edit form over a hairline-topped strip of
   the row's other actions (archive, delete).

   The delivery grid is corvus.css's posting grid (.grid-scroll + .post-grid: sticky header row and
   sticky creator column in a scroll box) with two header rows, so the second row sticks under the
   first. The boxes keep app.js's hook: input.deliv-check, disabled while saving and outlined on
   --bad when a save fails (.toggle-err). The empty state is what the live page shows today.
   -------------------------------------------------------------------------- */
.edit-row-body { display: flex; flex-direction: column; gap: var(--s-3); padding: var(--s-3) var(--s-4) var(--s-4); }
.edit-row-danger { display: flex; flex-wrap: wrap; gap: var(--s-2); padding-top: var(--s-3); box-shadow: inset 0 1px 0 var(--line); }
.edit-row-danger form { display: contents; }

.content-filter { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2) var(--s-3); }
.content-filter .chip[aria-current="true"] { background: var(--ink); color: var(--ink-inverse); box-shadow: none; }

.empty-state { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--s-2); padding: var(--s-8) var(--s-4); }
.empty-state svg { width: 28px; height: 28px; color: var(--ink-3); stroke-width: 1.5; margin-bottom: var(--s-1); }
.empty-state h2 { font-size: var(--t-md); }
.empty-state p { margin: 0; max-width: 46ch; color: var(--ink-3); font-size: var(--t-sm); }

.content-grid { min-width: 0; }
.content-grid .group-row th { height: 30px; padding-top: 0; padding-bottom: 0; }
.content-grid thead tr + tr th { top: 30px; }
.content-grid .group-head { font-size: var(--t-xs); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); box-shadow: inset 1px 0 0 var(--line), inset 0 -1px 0 var(--line); }
.content-grid .piece-head { white-space: normal; vertical-align: bottom; min-width: 76px; max-width: 140px; line-height: 1.3; }
.content-grid .piece-name { color: var(--ink); font-weight: 500; }
.content-grid .piece-notion { display: inline-flex; color: var(--ink-3); vertical-align: -1px; }
.content-grid .piece-notion:hover { color: var(--ink); }
.content-grid .piece-notion svg { width: 12px; height: 12px; }
/* A stored link that is not http(s) is shown, never linked: plain text, clipped to its place. */
.link-inert { display: inline-block; max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: var(--t-xs); color: var(--ink-3); }
.content-grid .link-inert { display: block; max-width: 100%; }
.content-grid .pcount { display: block; margin-top: 3px; font-size: var(--t-xs); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.content-grid .row-head .who { color: var(--ink); }
.content-grid .row-head .tag { margin-left: 6px; }
.content-grid tbody tr:hover td { background: var(--hover); }
input.deliv-check { width: 18px; height: 18px; margin: 0; vertical-align: middle; accent-color: var(--ink); cursor: pointer; }
input.deliv-check:disabled { cursor: progress; opacity: 0.6; }
input.deliv-check.toggle-err { outline: 2px solid var(--bad); outline-offset: 2px; }

.label-add { display: flex; gap: var(--s-2); }
.label-add .control { flex: 1 1 auto; min-width: 0; }
.label-rows { box-shadow: inset 0 1px 0 var(--line); }
.label-row { display: flex; align-items: center; gap: var(--s-2); padding: 8px var(--s-4); }
.label-row + .label-row { box-shadow: inset 0 1px 0 var(--line); }
.label-rename { display: flex; align-items: center; gap: var(--s-2); flex: 1 1 auto; min-width: 0; }
.label-rename .control { flex: 1 1 auto; min-width: 0; }
.label-actions { display: inline-flex; gap: 4px; flex: none; }
.label-actions form { display: contents; }

/* A creator title carries the dot (.who is inline-flex); as Socials does, the title takes its own line
   under the back link. */
.page-head h1.who { display: flex; }
h1.who .tag { margin-left: 6px; }
/* Two tabs stay on one line even where corvus.css lets a page-head seg wrap (under 900px). */
.page-head .seg.content-tabs { flex-wrap: nowrap; }
.delivery-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2) var(--s-3); padding: 10px var(--s-4); }
.delivery-row + .delivery-row { box-shadow: inset 0 1px 0 var(--line); }
.delivery-check { display: inline-flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0; cursor: pointer; }
.delivery-name { font-weight: 600; color: var(--ink); }
.delivery-row.is-missing .delivery-name { color: var(--ink-3); }
.delivery-date { display: flex; align-items: center; gap: var(--s-2); margin-left: auto; }
.delivery-date .control { width: auto; }
.delivery-missing { margin-left: auto; }

@media (max-width: 699px) {
    input.deliv-check { width: 22px; height: 22px; }
    .delivery-date { margin-left: 0; }
}

/* --------------------------------------------------------------------------
   9. Chatting (batch 5a).

   The chatting back end's seven tables on the corvus.css table. Wide tables scroll inside their panel.
   In the per-chatter rollup the chatter column stays in view while the figures scroll, as .tbl-sticky
   keeps a leaderboard's rank and name. On a phone the on-shift table moves Team under the chatter
   (.hide-sm and .show-sm, DESIGN.md section 7).
   -------------------------------------------------------------------------- */
.chat-rollup th:first-child, .chat-rollup td:first-child { position: sticky; left: 0; z-index: 1; background: var(--panel); }
.chat-rollup tbody tr:hover td:first-child { background: var(--panel); background-image: linear-gradient(var(--hover), var(--hover)); }
.chat-sub { font-size: var(--t-xs); color: var(--ink-3); }
.panel-foot .link svg { width: 13px; height: 13px; margin-left: 3px; vertical-align: -2px; }

/* --------------------------------------------------------------------------
   10. Mass messages (batch 5b).

   Six pages under one tab bar: the same five tabs as before, as a segmented control under the page head,
   which scrolls sideways on a phone rather than wrapping. Post rows name every creator with the creator's
   dot (the name always beside it, DESIGN.md section 2) and mark confirmed, missed and skipped sends with an
   icon on the semantic tokens. Rotation and Pool reuse section 8's form-beside-list layout and disclosure
   rows; a paused message and an inactive creator are dimmed, as the old pages did.
   -------------------------------------------------------------------------- */
.mm-tabs { display: flex; width: max-content; max-width: 100%; overflow-x: auto; margin-bottom: var(--s-4); scrollbar-width: none; }
.mm-tabs::-webkit-scrollbar { display: none; }
.mm-sub { display: block; font-size: var(--t-xs); color: var(--ink-3); }
/* Slot, team, language and message fold under time and creators on a phone; .mm-sub must not undo .show-sm. */
.mm-sub.show-sm, .mm-fold-links.show-sm { display: none; }
.mm-attention ul { margin: 2px 0 0; padding-left: 18px; }
.mm-attention li { font-size: var(--t-base); }
.mm-creators { white-space: normal; min-width: 220px; max-width: 360px; }
.mm-who { display: inline-flex; align-items: center; gap: 6px; margin: 2px 12px 2px 0; white-space: nowrap; }
.mm-mark { display: inline-flex; color: var(--ink-3); }
.mm-mark svg { width: 13px; height: 13px; stroke-width: 2.5; }
.mm-mark-ok { color: var(--good); }
.mm-mark-bad { color: var(--bad); }
.mm-preview { display: block; }
.mm-preview + .mm-preview { margin-top: 4px; }
@media (min-width: 901px) {
    .mm-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .mm-kpis .kpi:nth-child(4) { box-shadow: inset 1px 0 0 var(--line); }
}
@media (max-width: 900px) {
    .mm-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .mm-kpis .kpi:nth-child(3) { box-shadow: inset 0 1px 0 var(--line); }
    .mm-kpis .kpi:nth-child(4) { box-shadow: inset 1px 0 0 var(--line), inset 0 1px 0 var(--line); }
}
.mm-per-team { box-shadow: inset 0 1px 0 var(--line); }
.mm-filter-body { padding-top: var(--s-4); }
.mm-filter-actions { align-self: end; padding-top: 0; }
.mm-scope { padding-bottom: var(--s-2); }
.mm-scope .hint { margin: 0; font-size: var(--t-sm); color: var(--ink-3); }
.mm-text { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink); }
.mm-message { margin-bottom: var(--s-4); }
h1 .st { vertical-align: 4px; margin-left: 6px; }
.edit-row.is-inactive .edit-row-name, .edit-row.is-paused > summary { opacity: 0.6; }
.mm-toggle { display: contents; }
.mm-mpd { max-width: 180px; }
.mm-id { font-size: var(--t-sm); color: var(--ink-3); font-variant-numeric: tabular-nums; }
.mm-msg-preview { font-weight: 500; min-width: 0; overflow-wrap: anywhere; }
.mm-pager { justify-content: space-between; }
.mm-window-form { display: flex; align-items: center; gap: var(--s-2); }
.mm-window-form .control-sm { width: 110px; }
.mm-const { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
@media (max-width: 699px) {
    .mm-tabs svg { display: none; }
    .mm-sub.show-sm, .mm-fold-links.show-sm { display: block; }
    .mm-fold-links { margin-top: 6px; }
    /* With slot, team, language and message folded, Time, Creators and Status fit the phone without a sideways scroll. */
    .mm-today td { white-space: normal; }
    .mm-today td, .mm-today th { padding-left: 8px; padding-right: 8px; }
    .mm-today td:first-child, .mm-today th:first-child { padding-left: var(--s-4); }
    .mm-today td:first-child { width: 1%; }
    .mm-today .mm-fold { min-width: 64px; }
    .mm-today .st svg { display: none; }
    .mm-today .mm-who { margin-right: 8px; }
    .mm-creators { min-width: 0; max-width: none; }
    .mm-windows td { white-space: normal; }
    .mm-window-form { flex-wrap: wrap; row-gap: 6px; }
    .mm-window-form .control-sm { width: 96px; }
}

/* --------------------------------------------------------------------------
   11. Masked roster and the Finance step-up (batch 6a).

   Creators, Chatters and Staff reuse section 8's form-beside-list layout and disclosure rows. Their money fields
   (wallet, hourly rate, salary) are left out of the markup until Finance is unlocked, never hidden here; the note
   that says so is a quiet alert with the lock. The step-up stays inside the app shell, so the nav and its lock stay
   in view: one centred auth panel (corvus.css) in the content, the enrolment QR codes beside their
   manual keys.
   -------------------------------------------------------------------------- */
.alert-link { color: inherit; text-decoration: none; transition: box-shadow var(--dur-1); }
.alert-link:hover { color: inherit; box-shadow: var(--shadow-2); }
.alert .alert-go { width: 14px; height: 14px; margin: 0 0 0 4px; vertical-align: -2px; }
.tier-note > svg { color: var(--ink-3); }
/* A row that holds a money field: while the field is left out, its neighbour takes the whole row. */
.form-row.masked-row > .field:only-child { grid-column: 1 / -1; }
.persona-editor { container: persona / inline-size; display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-2); }
.persona-rows { display: flex; flex-direction: column; gap: var(--s-2); width: 100%; }
.persona-row { display: grid; grid-template-columns: minmax(96px, 128px) minmax(0, 1fr) auto; gap: var(--s-2); align-items: center; }
/* In a narrow form (the add form beside the list) the platform takes its own line, so the name field keeps its width. */
@container persona (max-width: 300px) {
    .persona-rows { gap: var(--s-3); }
    .persona-row { grid-template-columns: minmax(0, 1fr) auto; }
    .persona-row > select { grid-column: 1 / -1; }
}
.team-grid { align-items: start; }
.staff-intro { margin: 0 0 var(--s-3); }
.staff-salary { font-variant-numeric: tabular-nums; }
.stepup { display: flex; justify-content: center; padding: var(--s-6) 0 var(--s-8); }
.stepup-panel { max-width: 384px; }
.stepup-panel.stepup-setup { max-width: 560px; }
.stepup-head { display: flex; align-items: center; gap: var(--s-3); }
.stepup-head .tag { margin-left: auto; }
.stepup-mark { display: inline-grid; place-items: center; width: 32px; height: 32px; flex: none; border-radius: var(--r-sm); background: var(--raised); box-shadow: var(--shadow-1); color: var(--ink-2); }
.stepup-mark svg { width: 16px; height: 16px; }
.stepup-panel > .sub { margin-top: var(--s-3); }
.stepup-code { font-variant-numeric: tabular-nums; letter-spacing: 0.08em; }
.stepup-foot { margin-top: var(--s-4); }
.enrol { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: var(--s-4); align-items: start; padding: var(--s-4) 0; box-shadow: inset 0 1px 0 var(--line); }
.enrol img { width: 180px; height: 180px; border-radius: var(--r-sm); background: #fff; }
.enrol-title { font-weight: 600; color: var(--ink); margin-bottom: var(--s-2); }
.enrol-key { display: flex; flex-direction: column; gap: 4px; }
.enrol-key code { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: var(--t-sm); color: var(--ink); overflow-wrap: anywhere; }
.stepup-form { padding-top: var(--s-4); box-shadow: inset 0 1px 0 var(--line); }
@media (max-width: 699px) {
    .stepup { padding: var(--s-2) 0 var(--s-6); }
    .enrol { grid-template-columns: 1fr; justify-items: start; }
}

/* --------------------------------------------------------------------------
   12. Finance, daily pages (batch 6b): $ Home, What I owe, P&L, Payees, Payments, Ledger.

   The Finance tabs are a segmented control with the Lock action beside them, like the mass-message tabs; the pages
   that batch 6c moves keep the old tabs until then. Break-even and the cost lines are KPI strips; the tables are the
   standard table, with every amount right-aligned in tabular figures. Pay links keep their pre-fill hrefs.
   -------------------------------------------------------------------------- */
.fin-tabs { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-4); min-width: 0; }
.fin-seg { max-width: 100%; overflow-x: auto; scrollbar-width: none; flex-wrap: nowrap; }
.fin-seg::-webkit-scrollbar { display: none; }
.fin-lock { margin-left: auto; }
.fin-breakeven .panel-head, .fin-state-head { justify-content: flex-start; flex-wrap: wrap; }
.fin-state { margin-left: auto; }
.fin-go svg { width: 22px; height: 22px; color: var(--ink-3); }
.kpi-link:hover .fin-go svg { color: var(--ink); }
@media (min-width: 901px) {
    .fin-kpis-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .fin-kpis-4 .kpi:nth-child(4) { box-shadow: inset 1px 0 0 var(--line); }
    .fin-kpis-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
    .fin-kpis-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .fin-kpis-4 .kpi:nth-child(3) { box-shadow: inset 0 1px 0 var(--line); }
    .fin-kpis-4 .kpi:nth-child(4) { box-shadow: inset 1px 0 0 var(--line), inset 0 1px 0 var(--line); }
}
.fin-kpis-3, .fin-kpis-4, .pnl-lines { overflow: hidden; }

/* What I owe */
.owe-hours { margin-top: var(--s-3); }
.owe-form .form-actions { flex-wrap: wrap; }
.owe-alert { padding-bottom: var(--s-3); }
.owe-muted { color: var(--ink-3); font-size: var(--t-sm); }
.owe-pay { white-space: nowrap; }
.owe-table td { vertical-align: middle; }
.owe-total { font-variant-numeric: tabular-nums; }
.owe-unrouted td { background: var(--warn-bg); }

/* Payments */
.pay-row-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pay-prefill { margin-bottom: var(--s-4); }
.pay-filter-body { padding-top: 0; }
.pay-filter-actions { align-self: end; padding-top: 0; }
.pay-table td { vertical-align: middle; }
.pay-date { white-space: nowrap; font-variant-numeric: tabular-nums; }
.pay-period { color: var(--ink-3); font-size: var(--t-sm); }
.pay-muted { color: var(--ink-3); font-size: var(--t-sm); }
.pay-total { font-variant-numeric: tabular-nums; }

/* P&L */
.pnl-period-body { padding-top: var(--s-4); }
.pnl-period-actions { align-self: end; padding-top: 0; }
.pnl-profit { padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-2); }
.pnl-profit-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; }
.pnl-profit-label { font-size: var(--t-md); font-weight: 600; color: var(--ink); }
.pnl-profit-val { font-size: var(--t-2xl, 28px); font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; color: var(--good); }
.pnl-profit.is-loss .pnl-profit-val { color: var(--bad); }
.pnl-profit-sum { margin: 0; color: var(--ink-3); font-size: var(--t-sm); font-variant-numeric: tabular-nums; }
.pnl-month { white-space: nowrap; }
/* .tbl .strong sets the ink colour; a loss keeps its warning colour. */
.tbl .strong.c-warn { color: var(--warn); }

/* Payees */
.payee-intro { margin: 0 0 var(--s-3); }
.payee-wallet { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: var(--t-xs); overflow-wrap: anywhere; }
.payee-wallet.is-empty { font-family: inherit; font-size: var(--t-sm); }

/* Ledger */
.ledger-mode { flex-wrap: nowrap; }
.ledger-cat { box-shadow: inset 0 1px 0 var(--line); }
.ledger-cat > summary { display: flex; align-items: center; gap: 6px; padding: var(--s-3) var(--s-4); cursor: pointer; font-size: var(--t-sm); font-weight: 500; color: var(--ink-2); list-style: none; }
.ledger-cat > summary::-webkit-details-marker { display: none; }
.ledger-cat > summary:hover { color: var(--ink); }
.ledger-cat > summary svg { width: 14px; height: 14px; }
.ledger-note { display: block; color: var(--ink-3); font-size: var(--t-sm); }
.ledger-muted { color: var(--ink-3); font-size: var(--t-sm); }
.ledger-runrate { font-variant-numeric: tabular-nums; }

@media (max-width: 699px) {
    .fin-tabs { flex-wrap: wrap; }
    .fin-seg { width: 100%; }
    .fin-seg svg { display: none; }
    .fin-lock { margin-left: 0; }
    .fin-kpis-3 .kpi:last-child { grid-column: 1 / -1; box-shadow: inset 0 1px 0 var(--line); }
    .pay-row-3 { grid-template-columns: 1fr; }
    .fin-state { margin-left: 0; }
    .pnl-profit-val { font-size: var(--t-xl); }
}

/* ==========================================================================
   13. Finance, the tools (batch 6c): Sales import, Reconciliation, Worker ROI, Payroll run and its
   detail, Creator onboarding and its form, and the five pages that are reached by URL only —
   the payout calculator, invoices, manual payroll, additional costs and agency revenue.

   Nothing new in kind: the period pickers are the filter grid with the Prev/Next pair in the form's
   actions, the wide tables are the standard table inside a scroll box, and a figure's second line
   (a count, a note, a warning) is a small muted line under it rather than its own column. The paid
   toggles are the state chip on a submit button, so a chip that can be pressed still reads as a
   chip. The payout breakdown keeps its own small table, because it is a calculation read top to
   bottom, not a list.
   -------------------------------------------------------------------------- */
.recon-sub, .roi-sub, .payroll-sub, .onboard-sub {
    display: block; margin-top: 2px; font-size: var(--t-sm); color: var(--ink-3); font-weight: 400;
}
.num .recon-sub, .num .payroll-sub { font-variant-numeric: tabular-nums; }
.recon-inline, .roi-inline { font-size: var(--t-sm); color: var(--ink-3); font-weight: 400; }

/* Period pickers: the two dates, then Prev / Apply / Next / This half-month on one line. */
.recon-period, .roi-period, .payroll-period { align-items: end; }
.recon-period-actions, .roi-period-actions { flex-wrap: wrap; gap: var(--s-2); align-self: end; }
.recon-period-body, .roi-period-body { padding-bottom: var(--s-4); }
.payroll-hours { margin-top: var(--s-3); }
.payroll-save { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; margin: 0; }

/* The sales month picker sits in the panel head, where the page's tag would be. */
.sales-month { display: flex; align-items: center; gap: var(--s-2); margin-left: auto; }
.sales-month .label { margin: 0; }
.sales-month .control { width: auto; }
.sales-split { gap: 0; }
.sales-split > .tbl-scroll:last-child { box-shadow: inset 1px 0 0 var(--line); }
.sales-status { box-shadow: inset 0 1px 0 var(--line); }
@media (max-width: 900px) {
    .sales-split > .tbl-scroll:last-child { box-shadow: inset 0 1px 0 var(--line); }
}

/* A state chip that is also a submit button (paid / unpaid toggles). */
.st-button {
    border: 0; cursor: pointer; font: inherit; font-size: var(--t-sm);
    transition: filter var(--dur-1);
}
.st-button:hover { filter: brightness(1.12); }
.st-button:focus-visible { outline: 2px solid var(--ink-3); outline-offset: 2px; }

/* Onboarding: what Infloww says about the candidate, as label/value pairs above the deal terms. */
.kv-row { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); }
.kv { font-size: var(--t-sm); color: var(--ink-3); }
.kv b { color: var(--ink); font-weight: 600; }

/* The payout calculation: gross down to the two shares, read top to bottom. */
.payout-breakdown { margin-top: var(--s-4); box-shadow: inset 0 1px 0 var(--line); padding-top: var(--s-4); }
.payout-title { font-weight: 600; color: var(--ink); margin-bottom: var(--s-2); }
.payout-table td { padding: 6px var(--s-3); }
.payout-table td:first-child { color: var(--ink-2); }
.payout-sub td { color: var(--ink-3); }
.payout-total td { box-shadow: inset 0 1px 0 var(--line); }
.payout-agency td { color: var(--ink-2); }
.payout-save { margin-top: var(--s-4); }

/* The wide tables keep their figures in tabular numerals; the note columns wrap. */
.recon-table .num, .roi-table .num, .payroll-table .num, .payroll-detail .num,
.payroll-manual .num, .invoice-table .num, .costs-table .num, .revenue-table .num { font-variant-numeric: tabular-nums; }
.payroll-pay { white-space: nowrap; }
@media (max-width: 699px) {
    .recon-period-actions, .roi-period-actions { width: 100%; }
    .sales-month { margin-left: 0; width: 100%; }
    .sales-month .control { flex: 1 1 auto; }
}
