/* Lifted near-verbatim from _preexisting/trade-reports_6.html, with small
   additions for the multi-page shell (role switcher, audit form, owner views). */

:root{
  --ink:#11161c; --ink-2:#2b3640; --line:#dde3ea; --line-2:#eef2f6;
  /* --muted is the secondary-text token and lands on every `th` (10.5px). At #6b7783 it
     cleared 4.5:1 on white (4.57) but not on --paper (4.30) or the th background
     (4.41) — i.e. it failed WCAG 1.4.3 AA wherever a table header actually sits.
     #57616c clears all three (6.30 / 5.92 / 6.08). */
  --paper:#f6f8fa; --card:#ffffff; --muted:#57616c;
  --zebra:#f5f6f8;  /* even-row stripe — soft grey, a system-wide default for every data table */
  --accent:#0f5a52; --accent-soft:#e6f2f0;
  /* Each status fg lands on its own soft bg at ~11-13px (flags, seg tags, banners), so
     it is normal text: 4.5:1. --ok was 4.47 and --warn 4.41 — both just under, on
     compliance surfaces (the both-sides punching flag, the DEBT tag). Darkened to 5.45
     and 5.26; the soft backgrounds carry the visual language and are unchanged. Both
     also appear on white (.pos) and improve there too. --block/--accent/--fam already
     pass (6.28 / 7.04 / 7.65) and are untouched. */
  --ok:#16703f; --ok-soft:#e7f5ec;
  --warn:#8a5c00; --warn-soft:#fdf3da;
  --block:#a3261f; --block-soft:#fbe9e7;
  --fam:#0b4a8f; --fam-soft:#e8f0fb;
}
*{box-sizing:border-box;margin:0;padding:0}
/* `hidden` must win. The UA stylesheet's [hidden]{display:none} is a plain element
   rule, so ANY `display:` an author writes beats it — a `.occ-send{display:flex}` panel
   marked hidden stays on screen, which is how the reminders strip rendered every send
   row open at once. One rule here rather than a defensive [hidden] beside every
   component that sets display. */
[hidden]{display:none!important}
body{font-family:'IBM Plex Sans',sans-serif;background:var(--paper);color:var(--ink);
  line-height:1.45;-webkit-font-smoothing:antialiased}
.mono{font-family:'IBM Plex Mono',monospace;font-variant-numeric:tabular-nums}
/* client/account code shown beside a name — teal monospace so the code reads as
   a distinct identifier while the name stays the primary text */
.ccode{font-family:'IBM Plex Mono',monospace;font-variant-numeric:tabular-nums;
  color:var(--accent);font-size:.92em}
.wrap{max-width:1160px;margin:0 auto;padding:0 24px}
.muted{color:var(--muted)}
.hidden{display:none}

/* Auth-page top bar — matches the app's solid teal .topnav (see base.html). */
header.top{border-bottom:none;background:var(--accent);min-height:50px;display:flex;
  align-items:center;padding:0;position:sticky;top:0;z-index:30}
.brandrow{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}
.brand{display:flex;align-items:baseline;gap:10px}
.brand h1{font-size:16px;font-weight:700;letter-spacing:-.01em}
.brand .tag{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.12em;
  color:var(--accent);background:var(--accent-soft);padding:3px 8px;border-radius:4px}
.brand p{font-size:12.5px;color:var(--muted);margin-top:3px}
/* White brand on the teal auth bar */
header.top .brand h1{color:#fff}
header.top .brand .tag{color:#fff;background:rgba(255,255,255,.18)}
header.top .brand .muted,header.top .muted{color:rgba(255,255,255,.82)}
.roleswitch{display:flex;align-items:center;gap:10px;font-size:12.5px}
.roleswitch span{font-size:12.5px}
.roleswitch form{margin:0}
.roleswitch select{font-family:'IBM Plex Sans';font-size:12.5px;border:1px solid var(--line);border-radius:6px;
  padding:5px 8px;background:var(--card);color:var(--ink)}
.roleswitch select:focus{outline:none;border-color:var(--accent)}

.datebox{font-size:12px;color:var(--muted);margin-top:14px}
.datebox b{color:var(--ink);font-weight:600}
.dateinput{font-family:'IBM Plex Mono',monospace;font-size:12.5px;border:1px solid var(--line);
  border-radius:6px;padding:5px 8px;color:var(--ink);background:var(--card);margin-left:4px}
.dateinput:focus{outline:none;border-color:var(--accent)}
/* A grid cell holding something the desk cannot act on -- currently the trade-idea Scrip
   box, which a <datalist> suggests into but never restricts. Marked, not corrected: see
   rcMarkScrip in templates/ops/reco_batch.html for why the value is left as typed.
   The title attribute carries the reason, so colour is not the only signal. */
.dateinput.rc-bad{border-color:#b91c1c;background:#fdecea}
.dateinput.rc-bad:focus{border-color:#b91c1c}
/* A date the selected account type does not use (client form). Scoped to .datefreeze on
   purpose: other read-only inputs in the app (the scrip box on an existing holdings
   entry) are read-only for different reasons and should not be greyed by this rule.
   Frozen, not disabled -- a disabled input is not submitted, and the field is in the
   form's Meta.fields, so that would delete a stored date on save. */
.dateinput.datefreeze[readonly]{background:var(--bg);color:var(--muted);
  border-style:dashed;cursor:not-allowed}
.datePrompt{background:var(--warn-soft);border:1px solid #ecd79a;color:var(--warn);font-weight:600;
  font-size:13px;border-radius:9px;padding:16px 18px;margin:22px 0}

.uploadzone{margin:26px 0 6px;border:1.5px dashed var(--line);border-radius:10px;background:var(--card);
  padding:30px;text-align:center;transition:.15s;cursor:pointer}
.uploadzone:hover{border-color:var(--accent);background:#fbfdfd}
.uploadzone.drag{border-color:var(--accent);background:var(--accent-soft)}
.uploadzone h2{font-size:15px;font-weight:600;margin-bottom:5px}
.uploadzone p{font-size:12.5px;color:var(--muted)}
.uploadzone .pill{display:inline-block;margin-top:12px;font-size:12px;font-weight:600;color:#fff;
  background:var(--ink);padding:8px 16px;border-radius:6px}
#fileInput{display:none}

/* status gate */
.gate{margin:22px 0;border-radius:10px;border:1px solid var(--line);overflow:hidden;background:var(--card)}
.gate.ok{border-color:#bfe3cd}
.gate.warn{border-color:#ecd79a}
.gatehead{display:flex;align-items:center;gap:12px;padding:14px 18px;font-size:13.5px;font-weight:600}
.gate.ok .gatehead{background:var(--ok-soft);color:var(--ok)}
.gate.warn .gatehead{background:var(--warn-soft);color:var(--warn)}
.dot{width:9px;height:9px;border-radius:50%;flex:none}
.gate.ok .dot{background:var(--ok)} .gate.warn .dot{background:var(--warn)}
.gatebody{padding:4px 18px 16px}

/* password field with a show/hide eye (js/pwtoggle.js, templates/_password_field.html).
   padding-right keeps the typed value from running under the button. */
.pw-wrap{position:relative;display:block}
.pw-wrap .pw-input{width:100%;box-sizing:border-box;padding-right:40px}
.pw-eye{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  background:none;border:none;color:var(--ink);cursor:pointer;padding:4px;
  display:flex;align-items:center;border-radius:5px}
.pw-eye:hover{color:var(--accent)}
.pw-eye:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* Edge draws its OWN reveal control (::-ms-reveal) inside every password input, and it
   appears only while you are actively typing -- so it reads as a button that keeps
   vanishing, which is precisely how it was first reported as a bug.

   Two kinds of field opt out of it, for opposite reasons:
     .pw-wrap        our eye is there instead, always present and always working;
                     Edge's would sit beside it as a flickering duplicate.
     .pw-no-native-reveal  the field is meant to have NO reveal at all -- the confirm
                     field on both password-change forms, where being able to read the
                     value back defeats the point of retyping it.

   Deliberately NOT global. The password fields with neither class (SMTP, approval,
   invite, reset) keep Edge's control, because there it is the only reveal a user has and
   removing it would be a downgrade, not a fix. */
.pw-wrap .pw-input::-ms-reveal,
.pw-no-native-reveal::-ms-reveal{display:none}

/* toasts (js/toast.js, templates/_toasts.html) -- the transient counterpart to .gate.
   Same two colour roles so ok/warn mean the same thing whichever way a page says it.
   z-index clears .modal-overlay (100): a toast about a failed save must not end up
   behind the dialog that triggered it. The container is pointer-events:none so the
   fixed strip never swallows clicks on the page beneath; each toast re-enables them
   for itself, which is the only part the user needs to hit.

   Centred horizontally, pinned near the top -- not dead centre. The pages that use
   toasts are sign-in and the password cards, where the message is almost always about
   the form: a box floating over the vertical middle would land squarely on the fields
   the reader has to go and fix. Top-centre puts it in the eyeline without covering the
   thing it is talking about. Each toast shrinks to its own text (align-items:center),
   so a short "Password changed" is a pill rather than a full-width bar.

   top:62px clears the header rather than straddling it -- both shells put the same
   50px accent bar there (header.top here, .topnav in the app shell), and a pale toast
   half over dark green reads as a rendering fault rather than a message. It is
   min-height, so an unusually tall header can still reach it; the toast stays legible
   over the bar because it is on z-index 200 with its own shadow. */
.toasts{position:fixed;top:62px;left:50%;transform:translateX(-50%);z-index:200;
  display:flex;flex-direction:column;align-items:center;gap:8px;
  width:min(440px,calc(100vw - 32px));pointer-events:none}
.toast{display:flex;align-items:flex-start;gap:10px;padding:12px 12px 12px 14px;
  max-width:100%;border-radius:10px;border:1px solid var(--line);background:var(--card);
  box-shadow:0 10px 30px rgba(15,23,42,.18);font-size:13.5px;font-weight:600;
  line-height:1.45;pointer-events:auto;
  animation:toast-in .3s cubic-bezier(.16,1.02,.3,1.28) both}
/* Entry is an animation, not a JS-toggled class. A class would mean the resting state
   is opacity:0, so a page whose JS never ran (blocked, cached-stale, error earlier in
   the file) would render the toast invisible and swallow the message -- the exact
   failure this feature exists to prevent. An animation plays off the paint and leaves
   the element in its normal visible state.

   The easing overshoots slightly (the 1.28 control point) so the box lands with a small
   bounce instead of sliding to a stop -- enough to catch the eye on a page the user is
   already staring at, which is the whole job of a message that then removes itself. */
@keyframes toast-in{
  from{opacity:0;transform:translateY(-22px) scale(.94)}
  to{opacity:1;transform:none}}
.toast.leaving{animation:none;opacity:0;transform:translateY(-10px) scale(.97);
  transition:opacity .2s ease,transform .2s ease}
.toast.ok{border-color:#bfe3cd;background:var(--ok-soft);color:var(--ok)}
.toast.warn{border-color:#ecd79a;background:var(--warn-soft);color:var(--warn)}
.toast-msg{flex:1;min-width:0;overflow-wrap:anywhere}
.toast-x{flex:none;background:none;border:none;cursor:pointer;color:inherit;opacity:.65;
  font-size:17px;line-height:1;padding:0 2px;font-family:inherit}
.toast-x:hover{opacity:1}
@media (prefers-reduced-motion:reduce){
  .toast{animation:none}
  .toast.leaving{transition:none}
}
.stats{display:flex;gap:26px;flex-wrap:wrap;padding:12px 0 4px}
.stat .n{font-size:20px;font-weight:600}
.stat .l{font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted)}
.exc{border-top:1px dashed var(--line);margin-top:8px;padding-top:12px}
.exc-item{display:flex;align-items:center;gap:12px;background:var(--block-soft);border:1px solid #f0cfca;
  border-radius:7px;padding:10px 13px;margin-bottom:8px;font-size:13px}
.exc-item .x{color:var(--block);font-weight:700;flex:none}
.exc-item .grow{flex:1}
.btn{font-family:inherit;font-size:12.5px;font-weight:600;border:1px solid var(--line);background:var(--card);
  color:var(--ink);padding:7px 13px;border-radius:6px;cursor:pointer;transition:.12s;text-decoration:none;display:inline-block}
.btn:hover{border-color:var(--ink-2)}
.btn.sm{padding:5px 10px;font-size:11.5px}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}
.btn.primary:hover{background:#0c4a43}
/* Rebalance — the desk's flagship analytical action. Lifted in muted gold so it
   reads as special and distinct from the teal primary (Apply) and the plain nav
   buttons; dark-brown ink keeps it legible and un-garish. */
.btn.gold{background:linear-gradient(135deg,#e9c65c 0%,#cca23a 100%);border-color:#b28f24;
  color:#3a2c00;font-weight:700;box-shadow:0 1px 2px rgba(150,110,10,.3)}
.btn.gold:hover{border-color:#8f7018;background:linear-gradient(135deg,#f0d066 0%,#d3ab41 100%);
  box-shadow:0 2px 7px rgba(150,110,10,.42)}
/* Soft-blue action — "go to the related operational page" (e.g. a scorecard to
   its source directory). Distinct from the teal primary and the gold Rebalance;
   matches the app's blue accents (the family-group pill). */
.btn.blue{background:#e8f0fb;border-color:#c3d7f5;color:#1d4ed8;font-weight:600}
.btn.blue:hover{background:#dbe8fb;border-color:#1d4ed8}
.btn:disabled{opacity:.45;cursor:not-allowed}
/* Holdings sub-navigation — a segmented pill (Holdings / Query / Heatmap): equal-width
   tabs in a bordered track, so the labels sit on a consistent grid regardless of length. */
.htabs{display:inline-flex;gap:4px;background:var(--paper);border:1px solid var(--line);
  border-radius:11px;padding:4px;margin:12px 0 6px}
.htabs a{min-width:132px;padding:8px 18px;border-radius:8px;font-size:12.5px;font-weight:600;
  color:var(--muted);text-decoration:none;border:0;background:transparent;
  display:inline-flex;align-items:center;justify-content:center;transition:background .12s,color .12s}
.htabs a:hover{background:var(--line-2);color:var(--ink)}
.htabs a.primary{background:var(--accent);color:#fff}
/* Holdings %-distribution bars (Concentration tab, per-client + per-family sector mix).
   Rows carry data-holds; holdings_prices.js fills width / % / ₹ from live prices. */
.hld-dist{display:flex;flex-direction:column;gap:6px}
.dist-row{display:grid;grid-template-columns:160px 1fr 56px 112px;gap:10px;align-items:center;font-size:12.5px}
.dist-label{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dist-track{height:15px;background:var(--paper);border:1px solid var(--line);border-radius:5px;overflow:hidden}
.dist-fill{height:100%;background:var(--accent);border-radius:4px;width:0;transition:width .5s ease}
.dist-pct{text-align:right;font-family:'IBM Plex Mono',monospace;font-weight:700;color:var(--accent)}
.dist-val{text-align:right;font-family:'IBM Plex Mono',monospace;color:var(--muted);font-size:11.5px}
@media (max-width:640px){.dist-row{grid-template-columns:104px 1fr 50px}.dist-val{display:none}}
/* Over-concentration warning chip (set by holdings_prices.js when a top slice crosses its threshold) */
.conc-flag{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;color:#8a5c00;
  background:#fff4e0;border:1px solid #f0d9a8;border-radius:20px;padding:2px 10px;vertical-align:middle}
.sendbar{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-top:6px;
  padding:14px 18px;border-radius:9px;background:var(--ink);color:#fff}
.sendbar .msg{font-size:13px}
.sendbar .msg b{font-weight:600}

/* reports */
.report{background:var(--card);border:1px solid var(--line);border-radius:11px;margin:18px 0;overflow:hidden}
.rhead{display:flex;align-items:center;gap:14px;padding:15px 18px;border-bottom:1px solid var(--line-2);flex-wrap:wrap}
.rhead .subj{font-size:14.5px;font-weight:700;letter-spacing:-.005em}
.rhead .seg{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;
  padding:3px 7px;border-radius:4px;background:var(--accent-soft);color:var(--accent)}
.rhead .seg.fam{background:var(--fam-soft);color:var(--fam)}
.rhead .to{font-size:12px;color:var(--muted)}
.rhead .to b{color:var(--ink-2);font-weight:500}
.rhead .spacer{flex:1}
.approve-tag{display:none;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--ok)}
.report.approved .approve-tag{display:inline-flex}
.report.approved .btn.approve{display:none}
.report.approved{border-color:#bfe3cd}
.btn.copy{display:inline-flex;align-items:center;gap:6px}
.report.approved .btn.copy{background:var(--accent);border-color:var(--accent);color:#fff}
.report.approved .btn.copy:hover{background:#0c4a43}
.btn.whatsapp{background:#25d366;border-color:#25d366;color:#fff}
.btn.whatsapp:hover{background:#1faa50}
/* email / WhatsApp action-icon glyphs (see templates/_ui.html) */
.aico{width:15px;height:15px;display:block}
.btn.iconly{display:inline-flex;align-items:center;justify-content:center;padding:5px 8px}
.btn.iconly.resent{opacity:.55}
.report.approved .btn.whatsapp{background:#25d366;border-color:#25d366}

.note{font-size:12px;color:var(--warn);background:var(--warn-soft);padding:9px 18px;border-bottom:1px solid #f0e2b8}
/* Data tables scroll inside a capped box so the header row stays frozen while you
   scroll the rows. Short tables (content < cap) are unaffected — no scrollbar, no
   visible change. Horizontal overflow still scrolls (.tablescroll was already an
   overflow container, so this adds no new clipping). The sticky rule targets only
   the OUTER table (> table >), never nested drill-down detail tables. Print uncaps
   so report/export output is never clipped to the box height. */
.tablescroll{overflow:auto;max-height:72vh}
.tablescroll > table > thead th{position:sticky;top:0;z-index:5;
  background:var(--accent-soft);box-shadow:inset 0 -1px 0 #cfe3de}
@media print{.tablescroll{max-height:none;overflow:visible}}
/* ONE NOTCH DENSER on the desk's data tables, 0.136.1: 12.5px to 12px type, cells from
   8px/12px to 6px/10px and heads from 9px to 7px. A dealer reads a trade report the way
   the portal reads a holdings list -- down a column, not across a sentence -- and the
   row was carrying more air than the figure in it. Nothing here goes under the 24x24
   CSS px WCAG 2.5.8 floor: a 12px line in 6px of padding is 24px, and the row is the
   smallest thing that changed. `.hld-table.fit` is untouched -- it is already at 11px
   and 6px, which is where this is heading rather than something to cut again. */
table{border-collapse:collapse;width:100%;font-size:12px}
th{font-family:'IBM Plex Sans';font-weight:700;font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;
  color:var(--accent);text-align:left;padding:7px 10px;border-bottom:1px solid #cfe3de;white-space:nowrap;background:var(--accent-soft)}
td{padding:6px 10px;border-bottom:1px solid var(--line-2);white-space:nowrap}
td.num,th.num{text-align:right;font-family:'IBM Plex Mono',monospace;font-variant-numeric:tabular-nums}
tr.grp td{background:#fafbfc;font-weight:600}
tr.sub td{font-weight:600;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
tr.total td{font-weight:700;background:#f1f4f7;border-top:2px solid var(--ink-2)}
/* Zebra striping — a system-wide default: a subtle shade on even data rows. It sits on
   the <tr>, so any cell that paints its own background (grp/sub/total/flag rows, or an
   inline row style) covers it, and hover (on td, below) always wins. "Unless explicitly
   specified" falls out of the cascade for free. */
tbody tr:nth-child(even){background:var(--zebra)}
/* Fit-to-screen for holdings tables: distribute columns to the viewport (no horizontal
   scroll), wrapping cell text. Toggled by a [data-hld-fit] button (holdings_prices.js). */
.hld-table.fit{table-layout:fixed;width:100%}
.hld-table.fit th,.hld-table.fit td{white-space:normal;word-break:break-word;font-size:11px;padding:6px 6px;vertical-align:top}
/* Per-column widths for the 11-column browse table (Client code · Name · Dep. ·
   Account · Security · ISIN · Sector · Qty · Last price · Value · As of). Without
   these the fixed layout split every non-first column evenly, so the short mono
   code got as much room as the long client Name and the Name wrapped to 3 lines. */
.hld-table.fit col.c-code{width:8%}
.hld-table.fit col.c-name{width:15%}
.hld-table.fit col.c-dep{width:5%}
.hld-table.fit col.c-acct{width:12%}
.hld-table.fit col.c-sec{width:14%}
.hld-table.fit col.c-isin{width:10%}
.hld-table.fit col.c-sector{width:8%}
.hld-table.fit col.c-qty{width:7%}
.hld-table.fit col.c-price{width:6%}
.hld-table.fit col.c-value{width:7%}
.hld-table.fit col.c-asof{width:8%}
/* identity columns read as one token — never wrap them */
.hld-table.fit td.nowrap,.hld-table.fit th.nowrap{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* zebra + hover must win over the top-level tbody rules on this fixed table */
.hld-table.fit tbody tr:nth-child(even) td{background:var(--zebra)}
.hld-table.fit tbody tr:hover td{background:#eceef2}
/* Holdings tables: a mild left indent on the first (name/scrip) column so it lines up
   under the section heading, and align the auto-inserted filter box with that heading
   (its heading auto-detect misses a heading wrapped in a flex header). */
.hld-table th:first-child,.hld-table td:first-child{padding-left:18px}
.hld-card .tv-filter{margin-left:18px}
.neg{color:var(--block)}

/* Summary stat cards — the buy / sell / net language the rebalance worksheet
   established, shared so every page that totals money reads the same way.
   Colours come from the TOKENS, never literals: the rebalance page carried its
   own #1a7f4b, which is the pre-contrast green the --ok token was darkened away
   from (4.47:1 -> 5.45:1), so the two surfaces had quietly drifted apart. */
.stat{display:inline-flex;flex-direction:column;border:1px solid var(--line);
  border-radius:8px;padding:5px 12px;background:var(--card)}
.stat .v{font-family:'IBM Plex Mono',monospace;font-variant-numeric:tabular-nums;
  font-size:15px;font-weight:700;line-height:1.25}
.stat .k{font-size:9.5px;color:var(--muted);text-transform:uppercase;
  letter-spacing:.04em;font-weight:600}
.stat.pos{border-color:var(--ok);background:var(--ok-soft)}
.stat.pos .v,.stat.pos .k{color:var(--ok)}
.stat.neg{border-color:var(--block);background:var(--block-soft)}
.stat.neg .v,.stat.neg .k{color:var(--block)}
.stat.info{border-color:var(--accent);background:var(--accent-soft)}
.stat.info .v{color:var(--accent)}
.stat.info .k{color:var(--accent);opacity:.75}
/* .count — how MUCH you are looking at (rows, clients, scrips), as opposed to
   money. Filled grey rather than a fourth hue: adding a colour here would say
   these numbers carry a direction or a warning, and they carry neither. The
   convention across every totals strip is:
       info   the headline aggregate       turnover, total sent
       pos    money in / a good outcome    buy
       neg    money out / a bad outcome    sell, failures
       count  the size of the result set   rows, clients, scrips
   Anything outside those four is a decision, not a style choice. */
.stat.count{border-color:transparent;background:var(--line-2)}
.stat.count .v{color:var(--ink-2)}
.stat.count .k{color:var(--muted)}

/* Segmented toggle for a low-cardinality filter (segment, channel) — one click,
   options always visible, and each option is a LINK so the control is
   bookmarkable, survives the back button and needs no JavaScript. Shared: Search
   and Comms Activity both use it, and a second copy is how two controls that
   should look identical stop looking identical. */
.segbar{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden}
.segbar a{display:inline-flex;align-items:center;padding:0 12px;height:30px;
  font-size:12px;font-weight:600;color:var(--muted);text-decoration:none;
  background:var(--card);border-right:1px solid var(--line)}
.segbar a:last-child{border-right:0}
.segbar a:hover{color:var(--accent);background:var(--accent-soft)}
.segbar a.on{background:var(--accent);color:#fff}
/* A sub-choice is one level down, not a different KIND of thing — same accent,
   lighter. (--fam blue was the first try and is wrong: on the Search page blue
   already means family group.) */
.segbar.sub a.on{background:var(--accent-soft);color:var(--accent)}
.pos{color:var(--ok)}
/* tableview.js: sortable headers + filter box */
th.th-sort{cursor:pointer;user-select:none;position:relative;padding-right:18px}
th.th-sort:hover{color:var(--accent);background:#dcebe6}
th.th-sort::after{content:'⇅';position:absolute;right:6px;opacity:.32;font-size:10px}
th.th-sort.th-asc::after{content:'▲';opacity:.85}
th.th-sort.th-desc::after{content:'▼';opacity:.85}
/* Top margin so the auto-inserted filter box never hugs a zero-padding card's top
   border (the left edge is aligned to the first column by tableview.js). */
input.tv-filter{width:290px;max-width:100%;margin:10px 0 8px}
/* min-width:0 + a right inset keep the page-size select inside padded/zero-pad
   cards instead of overflowing the card edge. */
.tv-pager{display:flex;align-items:center;gap:8px;margin:8px 0;flex-wrap:wrap;min-width:0;padding-right:12px}
.tv-pager .tv-pginfo{font-size:12px}
.tv-pager select.tv-pgsize{padding:3px 6px;font-size:12px}
.tv-pager button[disabled]{opacity:.45;cursor:default}
tbody tr:hover td{background:#eceef2}  /* soft grey, darker than --zebra so hover reads on striped rows too */
tr.grp:hover td,tr.sub:hover td,tr.total:hover td{background:inherit}
.empty{padding:30px 18px;text-align:center;color:var(--muted);font-size:13px}

/* both-buy-and-sell punching-error flag */
tr.both-sides td{background:#fff7e6 !important}
tr.both-sides:hover td{background:#fff2d6 !important}
tr.warn-row td{padding:0;background:#fff;border-bottom:1px solid var(--line)}
.warn-banner{margin:0;padding:12px 16px;background:var(--warn-soft);border-left:4px solid var(--warn);
  display:flex;flex-direction:column;gap:8px}
.warn-banner .warn-head{font-size:12.5px;color:var(--warn);font-weight:500;line-height:1.5}
.warn-banner .warn-head b{font-weight:700;color:var(--ink)}
.warn-banner .warn-row-input{display:flex;gap:10px;align-items:flex-start;flex-wrap:wrap}
.warn-banner textarea.expl-input{flex:1;min-width:280px;min-height:46px;font-family:inherit;font-size:13px;
  border:1px solid var(--line);border-radius:6px;padding:7px 10px;background:#fff;color:var(--ink);resize:vertical}
.warn-banner textarea.expl-input:focus{outline:none;border-color:var(--accent)}
.warn-banner textarea.expl-input.locked{background:#f4f5f7;color:var(--muted);cursor:not-allowed}
.warn-banner .expl-status{font-size:11.5px;color:var(--muted);min-width:80px;font-weight:600;padding-top:8px}
.warn-banner .flagbox-body{display:flex;flex-direction:column;gap:8px}
.warn-banner .expl-instr{font-size:12px;color:var(--muted)}
.warn-banner .remove-flag{align-self:flex-start;white-space:nowrap}
.flag-pending{font-size:12.5px;color:var(--ink);font-weight:600}
.flag-declined{font-size:12.5px;color:var(--block);font-weight:600}

/* inline approver-authorisation modal */
.modal-overlay{position:fixed;inset:0;background:rgba(15,23,42,.45);z-index:100;
  display:flex;align-items:center;justify-content:center;padding:16px}
.modal{background:var(--card);border:1px solid var(--line);border-radius:12px;
  padding:18px 20px;width:100%;max-width:380px;box-shadow:0 20px 50px rgba(0,0,0,.25);
  display:flex;flex-direction:column;gap:6px}
.modal h3{margin:0 0 2px;font-size:15px;font-weight:700}
.modal label{font-weight:500}
.modal select,.modal input,.modal textarea{width:100%;font-family:inherit;font-size:13px;
  border:1px solid var(--line);border-radius:6px;padding:7px 10px;background:#fff;color:var(--ink)}
.modal .m-err{color:var(--block);font-size:12px;min-height:15px;font-weight:600}
.modal .m-actions{display:flex;gap:8px;margin-top:6px}

/* reusable collapsible accordion */
details.acc{border:1px solid var(--line);border-radius:9px;margin-bottom:10px;background:var(--card);overflow:hidden}
details.acc>summary{cursor:pointer;padding:12px 16px;list-style:none;display:flex;gap:12px;
  align-items:center;flex-wrap:wrap;font-size:14px}
details.acc>summary::-webkit-details-marker{display:none}
details.acc>summary::before{content:'▸';color:var(--muted);font-size:11px}
details.acc[open]>summary::before{content:'▾'}
details.acc>summary:hover{background:var(--accent-soft)}
details.acc>summary .sub{color:var(--muted);font-size:12px;font-weight:400}
.acc-body{padding:2px 16px 16px}
/* inline "add" panel: collapsed above a list, expands on the summary arrow.
   The wrapped .card is flattened so the form blends into the accordion. */
details.acc.acc-add{margin:8px 0 14px}
details.acc.acc-add>summary{font-weight:600}
.acc-formbody{padding:0}
.acc-formbody>.card{border:0;margin:0;background:transparent}

/* dashboard */
.active-window{background:var(--accent)!important;color:#fff!important;border-color:var(--accent)!important}
.dsec{margin:16px 0}
.dsec-head{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:none;border:0;
  border-bottom:1px solid var(--line);cursor:pointer;font-size:15px;font-weight:700;color:var(--ink);padding:6px 2px;margin:0}
.dsec-head:hover{color:var(--accent)}
.dsec-caret{font-size:11px;color:var(--muted);transition:transform .15s}
.dsec.collapsed .dsec-caret{transform:rotate(-90deg)}
.dsec.collapsed .dsec-body{display:none}
.dsec-body{margin-top:12px}
.dsec-sub{font-weight:400;font-size:12px}
.dsec-toolbar{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin:12px 0}
.stat-card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:16px 18px}
.stat-num{font-family:'IBM Plex Mono',monospace;font-size:26px;font-weight:600;color:var(--ink);letter-spacing:-.01em}
.stat-label{font-size:12px;color:var(--muted);margin-top:3px}
.top3-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}
.top3-card{border:1px solid var(--line);border-radius:10px;padding:14px 16px;position:relative;background:var(--accent-soft)}
.top3-rank{position:absolute;top:10px;right:12px;font-weight:700;color:var(--accent);font-size:13px}
.top3-name{font-size:13px;font-weight:600;color:var(--ink);padding-right:24px}
.top3-turn{font-family:'IBM Plex Mono',monospace;font-size:20px;font-weight:600;color:var(--accent);margin-top:6px}
.bar-chart{display:flex;align-items:flex-end;gap:3px;height:170px;padding:6px 0;border-bottom:1px solid var(--line)}
.bar-col{flex:1;height:100%;display:flex;align-items:flex-end;min-width:4px}
.bar{width:100%;background:var(--accent);border-radius:3px 3px 0 0;min-height:2px;opacity:.85}
.bar-col:hover .bar{opacity:1;background:var(--ink)}
.bar-axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted);margin-top:4px}
.line-chart{position:relative;height:180px;margin-top:8px;border-bottom:1px solid var(--line)}
.line-chart svg{position:absolute;inset:0;width:100%;height:100%;display:block}
.line-area{fill:var(--accent-soft)}
.line-path{fill:none;stroke:var(--accent);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.line-hover{position:absolute;inset:0}
.line-dot{position:absolute;width:8px;height:8px;border-radius:50%;background:var(--accent);
  border:2px solid var(--card);transform:translate(-50%,50%);cursor:default}
.line-dot:hover{transform:translate(-50%,50%) scale(1.45)}
.heatmap{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:8px}
.heat-tile{border:1px solid var(--line);border-radius:8px;padding:10px 12px;color:var(--ink);overflow:hidden}
.heat-tile.hot{color:#fff;border-color:transparent}
/* A tile's label is the one thing it exists to say, so it wraps rather than truncating:
   "CHINTAN MAHESH D…" identifies nobody. Two lines, then ellipsis — the tile has the
   height, and a scrip symbol never needs the second line anyway. */
.heat-scrip{font-size:12.5px;font-weight:600;overflow:hidden;text-overflow:ellipsis;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  line-height:1.28;word-break:break-word}
.heat-side{font-size:10px;font-weight:600;opacity:.8;margin-left:2px}
.heat-turn{font-family:'IBM Plex Mono',monospace;font-size:15px;font-weight:600;margin-top:2px}
.heat-bs{font-size:10.5px;opacity:.85;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.heat-key{display:inline-block;width:11px;height:11px;border-radius:3px;vertical-align:-1px}
.heat-key.buy{background:rgba(26,127,75,.85)}
.heat-key.sell{background:rgba(163,38,31,.85)}

/* two-up dashboard panels + horizontal bar lists */
.dash-two{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px}
.hbars{display:flex;flex-direction:column;gap:7px;margin-top:4px}
.hbar-row{display:flex;align-items:center;gap:10px;font-size:12.5px}
.hbar-label{flex:0 0 130px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--ink-2)}
.hbar-track{flex:1;height:14px;background:var(--line-2);border-radius:7px;overflow:hidden}
.hbar-fill{display:block;height:100%;background:var(--accent);border-radius:7px;min-width:2px}
.hbar-fill.alt{background:var(--fam)}
.hbar-val{flex:0 0 44px;text-align:right;font-family:'IBM Plex Mono',monospace;font-weight:600;color:var(--ink)}

/* role-aware collapsible left sidebar */
.app-shell{display:flex;align-items:flex-start;min-height:100vh}
.sidebar{width:208px;flex-shrink:0;background:var(--card);border-right:1px solid var(--line);
  position:sticky;top:0;height:100vh;display:flex;flex-direction:column;
  transition:width .14s ease;z-index:30}
.sidebar.collapsed{width:56px}
.sidebar-brand{display:flex;align-items:center;gap:10px;padding:12px 12px;min-height:53px;
  border-bottom:1px solid var(--line)}
.sidebar-brand .logo{font-weight:700;font-size:15px;letter-spacing:-.01em;white-space:nowrap;overflow:hidden}
.collapse-btn{flex-shrink:0;width:34px;height:34px;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:7px;background:var(--card);color:var(--ink-2);cursor:pointer}
.collapse-btn:hover{background:var(--accent-soft);color:var(--accent)}
.collapse-btn svg{width:18px;height:18px}
.sidebar-nav{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:8px 0;display:flex;flex-direction:column;gap:1px}
.sidebar-foot{flex-shrink:0}
.navlink{display:flex;align-items:center;gap:11px;padding:9px 16px;color:var(--ink-2);
  text-decoration:none;font-size:13px;border-left:3px solid transparent;white-space:nowrap}
.navlink:hover{background:var(--accent-soft);color:var(--ink)}
.navlink.active{color:var(--accent);background:var(--accent-soft);border-left-color:var(--accent);font-weight:600}
.navicon{width:18px;height:18px;flex-shrink:0}
.sidebar.collapsed .sidebar-brand .logo,
.sidebar.collapsed .navlabel{display:none}
.sidebar.collapsed .navlink{justify-content:center;padding:9px 0;gap:0}
.sidebar-foot{border-top:1px solid var(--line);padding:10px 16px;font-size:11px;color:var(--muted)}
.sidebar-foot .ver-short{display:none}
.sidebar.collapsed .sidebar-foot{padding:10px 0;text-align:center}
.sidebar.collapsed .sidebar-foot .ver-full{display:none}
.sidebar.collapsed .sidebar-foot .ver-short{display:inline}
.main-area{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{display:flex;align-items:center;gap:10px;padding:10px 24px;background:var(--card);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20}
.topbar .brand-tag{font-size:13px;font-weight:600;color:var(--ink-2);display:flex;align-items:center;gap:8px}
.topbar-spacer{flex:1}
.main-area > main.wrap{padding-top:6px;padding-bottom:60px;width:100%}
/* The shell's Back control, first thing inside <main> on every page. A row of its own
   rather than a floated element: the pages below open with their own header row, and a
   control sharing that line would sit inside somebody else's flex container and inherit
   its alignment. Margin only -- the button itself is `.btn sm`, so it already carries the
   desk's height, type and hover, and a second set of rules for one instance of it is how
   two buttons stop looking alike. */
.backbar{margin:10px 0 0}

/* segment tag — UNIVERSAL colour rule for EQ / FO / DEBT (and FAMILY bucket).
   Used everywhere a segment is shown (search, scriptwise, clientwise, audit,
   drill-downs). EQ is the base/accent; add a lowercase class for the rest. */
.seg-tag{display:inline-block;font-size:10px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;padding:2px 6px;border-radius:3px;background:var(--accent-soft);color:var(--accent)}
/* eq/fam already used the tokens; fo/debt re-typed the same pairs as literals and so
   drifted away from them (debt kept the old, contrast-failing amber). */
.seg-tag.eq  {background:var(--accent-soft);color:var(--accent)}
.seg-tag.fo  {background:var(--block-soft);color:var(--block)}
.seg-tag.debt{background:var(--warn-soft);color:var(--warn)}
.seg-tag.fam {background:var(--fam-soft);color:var(--fam)}
/* CLIENT is the counterpart of FAMILY wherever the two are distinguished. It was
   plain text next to a coloured FAMILY pill, so the eye read "tagged" vs
   "untagged" rather than two kinds of row. Deliberately the quieter of the pair:
   client is the common case and should not shout. */
.seg-tag.cli {background:var(--accent-soft);color:var(--accent)}

/* drill-down flag tags + per-row explanation banner (auditor + owner) */
.flag-tag{display:inline-block;font-size:11px;font-weight:700;padding:1px 5px;border-radius:3px;
  background:var(--warn-soft);color:var(--warn);margin-right:3px}
.drill-expl-row td{padding:0;background:#fff;border-bottom:1px solid var(--line)}
.drill-expl{padding:8px 14px;font-size:12.5px;line-height:1.5;border-left:4px solid var(--warn);background:var(--warn-soft);color:var(--ink-2)}
.drill-expl.ok{border-left-color:var(--ok);background:var(--ok-soft)}
.drill-expl b{color:var(--ink);font-weight:600}

/* flag badge on the audit + clientwise main rows */
.row-flag{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:700;
  background:var(--warn-soft);color:var(--warn);padding:2px 7px;border-radius:4px;margin-left:6px}
.row-flag.ok{background:var(--ok-soft);color:var(--ok)}

/* double-upload banner */
.double-upload-banner{margin:16px 0 0;padding:14px 18px;border-radius:10px;border:1px solid #ecd79a;
  background:var(--warn-soft);color:var(--warn);font-size:13px}
.double-upload-banner b{color:var(--ink);font-weight:600}

.footnotes{margin:30px 0 0;font-size:12px;color:var(--muted);border-top:1px solid var(--line);padding-top:14px}
.footnotes p{margin-bottom:6px} .footnotes b{color:var(--ink-2)}

/* pick role landing */
.pickrole{margin:60px auto;text-align:center;max-width:560px}
.pickrole h2{font-size:22px;font-weight:700;margin-bottom:6px}
.pickrole p{font-size:13px;margin-bottom:24px}
.pickrole-form{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
.pickrole-form .btn{padding:11px 18px}

/* Sign-in switch — the two doors, on both sign-in pages (templates/_signin_switch.html).
   The current side is carried by aria-current, so the selected styling and the thing a
   screen reader announces cannot disagree; there is no separate .on class to forget. */
.signin-switch{display:grid;grid-template-columns:1fr 1fr;border:1px solid var(--line);
  border-radius:8px;overflow:hidden;background:var(--line-2);margin-bottom:18px}
.signin-switch a{padding:9px 8px;text-align:center;text-decoration:none;line-height:1.25;
  font-size:12.5px;font-weight:600;color:var(--muted);transition:.12s}
.signin-switch a span{display:block;font-size:10.5px;font-weight:500;margin-top:1px;opacity:.85}
.signin-switch a:hover{color:var(--ink)}
.signin-switch a[aria-current]{background:var(--card);color:var(--accent);
  box-shadow:inset 0 -2px 0 var(--accent)}

/* Compliance footer — on every client-facing page, in either shell (the signed-out
   pages render in this one, the signed-in pages in the portal's). It lives here rather
   than in portal.css because portal.css is loaded by only one of the two.
   Sized in rem, against this file's px convention, and deliberately: it is read by
   the portal's audience, and a client who has raised their browser text size must
   actually get larger text — the reason portal.css is in rem at all. */
.cfoot{background:var(--card);border-top:1px solid var(--line);
  padding:1rem 1.125rem;font-size:.8125rem;color:var(--muted);line-height:1.6}
.cfoot b{color:var(--ink-2);font-weight:600}
.cfoot .row{margin-bottom:.25rem}
.cfoot a{color:var(--accent)}
/* The build number, on the signed-out client pages (sign in / forgot / reset), which
   render in THIS shell. The portal's own copy is in portal.css -- the two footers are
   the same partial in two stylesheets, so a change to one wants the other. */
.cfoot .ver{margin-top:8px;font-size:11.5px;color:var(--muted);opacity:.75}

/* audit + owner forms */
.card{background:var(--card);border:1px solid var(--line);border-radius:11px;padding:22px;margin:22px 0}
.card h2{font-size:15px;font-weight:600;margin-bottom:14px}
.card label{display:block;font-size:12px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.07em;margin-bottom:5px;margin-top:14px}
.card input[type=text],.card input[type=number],.card input[type=date],
.card input[type=email],.card input[type=password],.card input[type=tel],
.card input[type=url],.card input:not([type]),.card textarea,.card select{
  font-family:inherit;font-size:13.5px;border:1px solid var(--line);border-radius:7px;
  padding:10px 12px;background:var(--card);color:var(--ink);width:100%;max-width:520px}
.card input:focus,.card textarea:focus,.card select:focus{
  outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.card textarea{min-height:80px;font-family:inherit;resize:vertical}
.card .row{display:flex;gap:18px;flex-wrap:wrap}
.card .row > div{flex:1;min-width:200px}
.card .actions{margin-top:18px;display:flex;gap:10px}
.checkrow{display:flex;align-items:center;gap:8px;margin-top:8px}
.checkrow input{width:auto;margin:0}

.statusgrid{width:100%;margin-top:8px}
.statusgrid td .ok-dot{color:var(--ok);font-weight:700}
.statusgrid td .miss-dot{color:var(--block);font-weight:700}
.kind-plus{color:var(--ok);font-weight:700}
.kind-minus{color:var(--block);font-weight:700}

/* ---- Operations page tabs (payout / broker contacts / employees / …) ---- */
.optabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin:10px 0 0;flex-wrap:wrap}
.optab-btn{font:inherit;font-size:13px;font-weight:600;color:var(--muted);background:none;border:0;
  border-bottom:2px solid transparent;padding:9px 14px;cursor:pointer;margin-bottom:-1px}
.optab-btn:hover{color:var(--ink)}
.optab-btn.active{color:var(--accent);border-bottom-color:var(--accent)}
.optab{display:none}
.optab.active{display:block}

/* Click-through links to Client 360 / Script 360 from inside a table.
   A client's name is data first: left to the browser it renders blue and
   underlined, which reads as decoration in a column of names and was flagged as
   exactly that. It takes the row's colour and earns an underline on hover. */
.link360{color:inherit;text-decoration:none}
.link360:hover{color:var(--accent);text-decoration:underline;text-underline-offset:2px}

/* Day/Month/Year selector — rendered by the `dmysel` macro in templates/base.html and
   auto-wired by static/js/dmysel.js. Used on Approve & Send + Daily Trade Reports. */
.dmysel{display:inline-flex;gap:4px;align-items:center}
.dmysel select{padding-right:4px}
.dmysel .dmy-d{min-width:56px}
.dmysel .dmy-m{min-width:104px}
.dmysel .dmy-y{min-width:72px}

/* Calendar date-picker — rendered by the `datecal` macro in templates/base.html and
   auto-wired by static/js/datecal.js. Used on by-client and by-scrip. */
.datecal{position:relative;display:inline-block}
.dcal-trig{cursor:pointer;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.dcal-pop{position:absolute;top:calc(100% + 6px);left:0;z-index:60;background:#fff;
  border:1px solid #e6ece9;border-radius:12px;box-shadow:0 18px 40px -20px rgba(15,87,76,.5);
  padding:10px;width:250px}
.dcal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}
.dcal-title{font-weight:700;font-size:13px}
.dcal-nav{border:0;background:none;font-size:18px;line-height:1;cursor:pointer;color:#1f8c77;
  padding:2px 9px;border-radius:6px}
.dcal-nav:disabled{color:#cdd8d4;cursor:default}
.dcal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}
.dcal-dow{font-size:10px;font-weight:700;color:#65766f;padding:2px 0}
.dcal-empty{height:30px}
.dcal-day{display:flex;align-items:center;justify-content:center;height:30px;border-radius:7px;
  font-size:12.5px;text-decoration:none;color:#16231f}
/* Three states, because a day means two different things across the two modes:
   `off`  navigation mode, no upload -- there is no page for it, so it is inert.
   `none` field mode, no upload -- selectable (a window bound is a fair question on any
          day) but unmarked, so the marks stay guidance about where the data is.
   `has`  an upload, either mode. */
.dcal-day.off{color:#c3cdc9}
button.dcal-day{font:inherit;font-size:12.5px;border:0;background:transparent;
  cursor:pointer;width:100%;padding:0}
.dcal-day.none{color:#5f6f69}
.dcal-day.none:hover{background:#eef2f0}
.dcal-day.has{background:#e8f3ef;color:#0f574c;font-weight:700}
.dcal-day.has:hover{background:#cfe8e0}
.dcal-day.sel{background:#1f8c77;color:#fff}
.dcal-note{font-size:11.5px;color:#65766f;text-align:center;margin-top:6px}
