/*
 * portal.css — the RepOS partner-portal shell.
 *
 * Tokens, spacing and component classes are carried over from Viva_Portal_Mockup.html
 * unchanged, so the built portal and the mockup stay the same object. Two things are added
 * at the bottom, marked and explained: a real mobile navigation, and empty-state styling.
 *
 * Brand-variable accents (--acc, --acc-bg) are overwritten at boot by brand.js. Everything
 * else is shared, because the difference between Riser and Viva is a name and an accent,
 * not a different product.
 */

/* ── tokens ─────────────────────────────────────────────────────────────────────────────── */
:root{
  --bg:#0a0f18;--panel:#0f1622;--card:#141d2c;--card2:#1a2537;--line:#22304a;--line2:#2c3c5a;
  --t1:#f2f5fa;--t2:#a9b6c9;--t3:#6f7f97;
  --acc:#3a8dde;--acc-bg:#12304f;--teal:#1fb58f;--teal-bg:#0f3a30;--amber:#e6a23c;--amber-bg:#3d2c0f;--red:#e5534b;--red-bg:#3d1714;--purple:#8b7cf6;--purple-bg:#2a2450;
  --r:12px;--rs:8px;
}
[data-theme="light"]{
  --bg:#f4f6fa;--panel:#ffffff;--card:#ffffff;--card2:#f1f4f9;--line:#e1e6ef;--line2:#cbd3e1;
  --t1:#101827;--t2:#4b5a72;--t3:#7a879b;
  --acc:#1d6fc4;--acc-bg:#e4effb;--teal:#0f8a6a;--teal-bg:#dff5ee;--amber:#b56e0f;--amber-bg:#fbefd8;--red:#c43a33;--red-bg:#fbe3e1;--purple:#5b4bd6;--purple-bg:#e9e6fb;
}

*{box-sizing:border-box}
html,body{margin:0;background:var(--bg);color:var(--t1);font:14px/1.5 Inter,system-ui,sans-serif}
a{color:var(--acc);text-decoration:none}
h1{font:500 30px/1.15 Fraunces,Georgia,serif;margin:0 0 4px;letter-spacing:-.01em}
h2{font:500 18px/1.3 Inter,system-ui,sans-serif;margin:0}
h3{font:600 13px/1.3 Inter,system-ui,sans-serif;margin:0;color:var(--t2)}

/* ── frame ──────────────────────────────────────────────────────────────────────────────── */
.app{display:flex;min-height:100vh}
/* The drawer SCROLLS. It is a fixed-height flex column, and without overflow-y anything past
   the fold is simply unreachable - on a 390x844 phone with the keyboard open the visible
   area is roughly 390x380, which put the account block and every control below it out of
   reach with no way to get at them. overscroll-behavior stops the scroll chaining to the
   page behind the drawer once it hits the end. */
.side{width:236px;flex:none;background:var(--panel);border-right:1px solid var(--line);display:flex;flex-direction:column;position:sticky;top:0;height:100vh;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.brand{display:flex;align-items:center;gap:10px;padding:18px 16px;border-bottom:1px solid var(--line)}
.logo{width:36px;height:36px;border-radius:10px;background:var(--acc);display:grid;place-items:center;color:#fff;font:700 18px Inter,system-ui,sans-serif}
.brand b{display:block;font-size:16px;font-weight:600}.brand small{color:var(--t3);font-size:12px}
.toggle{width:32px;height:32px;border-radius:50%;border:1px solid var(--line);background:transparent;color:var(--t2);cursor:pointer;display:grid;place-items:center;font-size:15px;flex:none}
.brand .toggle{margin-left:auto}
.nav{padding:10px 10px;display:flex;flex-direction:column;gap:2px}
.nav button{all:unset;display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:10px;color:var(--t2);cursor:pointer;font-size:15px}
/* all:unset + display:flex above outrank the browser's own [hidden] rule, so a nav button shipped hidden (Kevin's Console) showed to every partner. This puts hidden back above it. */
.nav button[hidden]{display:none}
/* The same for the practice page's admin account picker (.bar, display:flex): a practice signed in
   with its own link saw the operator's picker (run item 3). */
.bar[hidden]{display:none}
.nav button svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;flex:none}
.nav button.on{background:var(--card2);color:var(--t1);outline:1px solid var(--line2)}
.nav button:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.nav .b{margin-left:auto;min-width:20px;height:20px;padding:0 6px;border-radius:10px;font-size:11px;font-weight:600;display:grid;place-items:center;color:#fff}
.b.teal{background:var(--teal)}.b.blue{background:var(--acc)}
.who{margin-top:auto;padding:14px 16px;border-top:1px solid var(--line);display:flex;align-items:center;gap:10px}
.who b{display:block;font-weight:600}.who small{color:var(--t3);font-size:12px}
.main{flex:1;min-width:0;padding:22px 28px 60px}
.screen{display:none}.screen.on{display:block}
/* The same rule for TABS, which was simply never written. showTab() toggles .on on the
   right pane and always has, but with no style behind the class every pane stayed
   visible: My business rendered Selling, Recruiting, Account, Help and Settings stacked
   on one page, which is how a partner came to see the platform Connections panel — and
   the Precision DX Group account behind it — underneath their own price list. */
.pane{display:none}.pane.on{display:block}

/* ── tabs ───────────────────────────────────────────────────────────────────────────────── */
.subtabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin:0 0 20px;flex-wrap:wrap}
.subtabs span{padding:10px 16px;color:var(--t2);cursor:pointer;border-bottom:2px solid transparent;font-size:15px;display:flex;align-items:center;gap:6px}
.subtabs span.on{color:var(--t1);border-color:var(--acc)}
.subtabs span:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
.pill-tabs{display:inline-flex;gap:2px;background:var(--card);border:1px solid var(--line);padding:4px;border-radius:12px;margin-bottom:18px;flex-wrap:wrap}
.pill-tabs span{padding:8px 14px;border-radius:9px;color:var(--t2);cursor:pointer;font-size:14px;display:flex;align-items:center;gap:6px}
.pill-tabs span.on{background:var(--card2);color:var(--t1)}

/* ── components ── moved to components.css (Kevin, 2026-09-10: one sheet, every pane uses it).
   What stays here is layout that is not a shared piece. */
.chart{height:220px;border-radius:10px;background:var(--card2);position:relative;overflow:hidden}
.chart svg{width:100%;height:100%}
.hdr{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:18px;flex-wrap:wrap}
.sub{color:var(--t2);font-size:15px}
.footer{padding:28px 0 0;color:var(--t3);font-size:12px;text-align:center}
.footer b{color:var(--t2);font-weight:500}

/* ── empty states ───────────────────────────────────────────────────────────────────────────
 * An unbuilt section must SAY it is unbuilt. A blank panel reads as "you have nothing" —
 * which is a claim about the rep's business, and a false one. The two are styled differently
 * on purpose: .empty is a real answer (no data yet), .notbuilt is an admission (no code yet).
 */
.empty{text-align:center;padding:70px 20px;color:var(--t2)}
.empty svg{width:60px;height:60px;stroke:var(--t3);fill:none;stroke-width:1.2;margin-bottom:14px}
.empty b{display:block;font-size:16px;color:var(--t1);margin-bottom:6px}
.empty p{margin:0 auto;max-width:44ch;font-size:14px}
.notbuilt{border:1px dashed var(--line2);border-radius:var(--r);padding:44px 24px;text-align:center;color:var(--t2)}
.notbuilt .tag{margin-bottom:12px}
.notbuilt b{display:block;font-size:16px;color:var(--t1);margin-bottom:6px}
.notbuilt p{margin:0 auto;max-width:52ch;font-size:14px}

/* ── mobile ─────────────────────────────────────────────────────────────────────────────────
 * The mockup parks the sidebar at left:-236px below 900px with nothing to bring it back, so
 * on a phone the portal has ten sections and no way to reach nine of them. Layout carries the
 * navigation here, so this is not a detail that can be left to "later": a shell you cannot
 * click through on a phone is not a shell.
 *
 * So: a top bar with the brand, a menu button and the theme toggle; the same .side element
 * slides in as a drawer; a scrim closes it. One nav, two presentations — no second copy of
 * the markup to drift out of sync with the first.
 */
.topbar{display:none;position:sticky;top:0;z-index:30;background:var(--panel);border-bottom:1px solid var(--line);padding:10px 14px;align-items:center;gap:12px}
.topbar .logo{width:30px;height:30px;border-radius:9px;font-size:15px}
.topbar b{font-size:15px;font-weight:600}
.topbar .sp{flex:1}
.menubtn{all:unset;width:36px;height:36px;border-radius:9px;border:1px solid var(--line);display:grid;place-items:center;color:var(--t2);cursor:pointer;flex:none}
.menubtn:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.menubtn svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round}
.scrim{display:none;position:fixed;inset:0;background:rgba(4,8,14,.6);z-index:40}
.scrim.on{display:block}

@media (max-width:900px){
  .topbar{display:flex}
  .side{position:fixed;top:0;left:0;height:100dvh;z-index:50;transform:translateX(-100%);transition:transform .22s ease;box-shadow:0 0 40px rgba(0,0,0,.45);overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;padding-bottom:env(safe-area-inset-bottom)}
  .side.open{transform:translateX(0)}
  .main{padding:16px 16px 60px}
  h1{font-size:24px}
}
@media (max-width:560px){
  .subtabs{overflow-x:auto;flex-wrap:nowrap}
  .subtabs span{white-space:nowrap;padding:10px 12px}
}
@media (prefers-reduced-motion:reduce){
  .side{transition:none}
}

/* ── "How did it go?" ────────────────────────────────────────────────────────────────────────
 * Centred, and it scrolls: four outcomes, three temperatures, seven follow-up chips and a
 * textarea do not fit in 380px of visible height with a keyboard open.
 */
.disp-scrim{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:70;display:flex;align-items:center;justify-content:center;padding:20px;overflow-y:auto;-webkit-overflow-scrolling:touch}
.disp{background:var(--bg);border:1px solid var(--line);border-radius:16px;padding:20px;width:min(420px,100%);max-height:calc(100vh - 40px);overflow-y:auto;overscroll-behavior:contain}
.disp h3{margin:0 0 2px;font-size:18px}
.disp-sub{margin-bottom:16px;font-size:14px}
.disp-group{margin-bottom:16px}
.disp-group>.k,.disp-group>label.k{display:block;margin-bottom:8px}
.disp-group i{font-style:normal;color:var(--t3)}
.disp-opts{display:flex;flex-direction:column;gap:8px}
.disp-opt{text-align:left;background:var(--card);border:1px solid var(--line);border-radius:10px;padding:11px 13px;color:inherit;font:inherit;cursor:pointer;min-height:44px}
.disp-opt b{display:block;font-size:14px}
.disp-opt span{display:block;font-size:12.5px;color:var(--t3);margin-top:2px}
.disp-opt.on{border-color:var(--acc);background:var(--card2)}
.disp-opt:focus-visible,.disp-chip:focus-visible{outline:2px solid var(--acc);outline-offset:1px}
.disp-chips{display:flex;flex-wrap:wrap;gap:6px}
.disp-chip{background:var(--card);border:1px solid var(--line);border-radius:999px;padding:8px 13px;color:inherit;font:inherit;font-size:13px;cursor:pointer;min-height:36px}
.disp-chip.on{border-color:var(--acc);background:var(--card2);color:var(--t1)}
.disp textarea{width:100%;box-sizing:border-box;background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 12px;color:inherit;font:14px Inter,system-ui,sans-serif;font-size:16px;resize:vertical}
.disp-foot{display:flex;gap:8px;justify-content:flex-end;margin-top:4px}
.disp-foot .btn{min-height:44px}
#disp-msg{margin-bottom:10px}
#disp-msg.err,.note.err{color:var(--amber,#f0b429)}


/* ── pricing table ───────────────────────────────────────────────────────────────────────────
 * The price is an input, not a figure: this screen exists so a rep can set retail between the
 * floor and the ceiling. 16px on the field, or iOS zooms the page the moment they tap it and
 * the table jumps under them.
 */
.pr-in{width:96px;text-align:right;font-size:16px;padding:8px 10px;border-radius:8px;border:1px solid var(--line);background:var(--card);color:inherit;font-family:inherit;min-height:40px}
.pr-in:focus-visible{outline:2px solid var(--acc);outline-offset:1px}
.pr-sf{display:inline-flex;align-items:center;gap:7px;cursor:pointer;font-size:13px;color:var(--t2)}
.pr-sf input{width:18px;height:18px;accent-color:var(--acc);cursor:pointer}
.pr-comm{font-variant-numeric:tabular-nums}
.pr-bar{display:flex;align-items:center;gap:12px;margin-top:14px;flex-wrap:wrap}
.pr-bar .btn{min-height:44px}
#pr-msg.err{color:var(--amber,#f0b429)}

@media(max-width:560px){
  /* The table scrolls sideways in its own container rather than making the page do it. */
  .pr-in{width:78px}
}

/* ── quick actions + nav badges ──────────────────────────────────────────────────────────────
 * The strip is navigation to places that already exist. It wraps rather than scrolling, so on
 * a phone it becomes two rows of reachable targets instead of a rail with something hidden off
 * the right edge that nobody discovers.
 */
.quick{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 18px}
.qa{flex:1 1 auto;min-width:150px;min-height:44px;padding:11px 14px;border-radius:10px;border:1px solid var(--line);background:var(--card);color:inherit;font:inherit;font-size:14px;cursor:pointer;text-align:left}
.qa:hover{border-color:var(--acc)}
.qa:focus-visible{outline:2px solid var(--acc);outline-offset:1px}

/* A badge is only ever drawn for a real, non-zero count — see paintBadges(). It never renders
 * a zero, because a zero badge tells a rep nothing needs them and that may not be true. */
.nav button{position:relative}
.badge{margin-left:auto;min-width:20px;height:20px;padding:0 6px;border-radius:10px;background:var(--acc);color:#fff;font-size:11.5px;font-weight:600;line-height:20px;text-align:center;font-variant-numeric:tabular-nums}

@media(max-width:560px){
  .qa{flex:1 1 calc(50% - 4px);min-width:0}
}

/* ── my business: kit shelf and notification switches ────────────────────────────────────────
 * A piece that is not in the kit is SHOWN and greyed rather than hidden. Hiding it leaves a rep
 * believing the shelf is complete, and the shelf is the answer to "what can I send".
 */
.kitlist{display:flex;flex-direction:column;gap:8px}
.kititem{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:11px 13px;border:1px solid var(--line);border-radius:10px}
.kititem .btn{min-height:38px}
.kititem.off{opacity:.55}
.nrow{align-items:flex-start;gap:14px;cursor:pointer}
.nrow input{width:18px;height:18px;accent-color:var(--acc);cursor:pointer;flex:0 0 18px;margin-top:2px}
#n-msg.err,#bug-msg.err{color:var(--amber,#f0b429)}
#bug-text{width:100%;box-sizing:border-box;background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 12px;color:inherit;font:14px Inter,system-ui,sans-serif;font-size:16px;resize:vertical}

/* ── analytics: rail and charts ──────────────────────────────────────────────────────────────
 * The rail wraps rather than scrolling, so on a phone it becomes two rows of reachable chips
 * instead of a strip with the window nobody uses hidden off the right edge.
 */
/* .rail already exists above and does exactly this. Reused rather than redeclared — a
   second .rail rule silently wins over the first and leaves a dead one behind. */

/* The chart is drawn at a fixed aspect and scaled by its wrapper, so strokes keep their weight
 * instead of being stretched by preserveAspectRatio="none". */
.chartwrap{width:100%;overflow-x:auto}
.chart{display:block;width:100%;height:120px;min-width:280px}

/* ── directory filters ───────────────────────────────────────────────────────────────────────
 * Wraps, and each control is a real target. A filter strip that scrolls sideways hides the one
 * nobody uses until they need it.
 */
.dfilters{display:flex;flex-wrap:wrap;gap:12px;margin:0 0 14px}
.dsel{display:flex;flex-direction:column;gap:4px}
.dsel select{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:9px 11px;color:inherit;font:inherit;font-size:16px;min-height:40px}
.dsel select:focus-visible{outline:2px solid var(--acc);outline-offset:1px}
/* 16px, not 15: iOS Safari zooms the whole page on focusing any control under 16px. */
/* An amount never breaks from its sign. At 390px "−$138.00" wrapped to a lone minus over "$138.00",
   which reads as a positive number. The table scrolls in its wrapper instead. */
.tablewrap td.r{white-space:nowrap}
#comm-earn-body td:first-child{white-space:nowrap}

/* ── customers toolbar ───────────────────────────────────────────────────────────────────────
 * Search at 16px or iOS zooms the page the moment it is tapped. Wraps rather than scrolling. */
.ctools{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:0 0 14px}
.csearch{flex:1 1 220px;min-width:0;background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 12px;color:inherit;font:inherit;font-size:16px;min-height:44px}
.csearch:focus-visible,.crep:focus-visible{outline:2px solid var(--acc);outline-offset:1px}
.crep{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:9px 11px;color:inherit;font:inherit;font-size:15px;min-height:44px}
.ctools .btn{min-height:44px}

/* ── CRM mailbox bar ─────────────────────────────────────────────────────────── */
.mbar{display:flex;flex-wrap:wrap;gap:10px 14px;align-items:center;justify-content:space-between;background:var(--card2);border-radius:10px;padding:10px 14px;margin:0 0 14px}
.mbar .acts{display:flex;gap:8px;flex-wrap:wrap}
.mbar .acts .btn{min-height:40px;text-decoration:none}

/* My business → Recruiting (PARITY row 4) and the Help contact card (row 6). */
.rec-up{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;flex-wrap:wrap;margin:10px 0 12px}
.rec-name{font-size:18px}
.rec-contact,.help-b{display:flex;gap:8px;flex-wrap:wrap}
.rec-team{font-size:14px;color:var(--acc);text-decoration:none}
.rec-tile{border:1px solid var(--line);border-radius:10px;padding:14px 16px;display:flex;flex-direction:column;gap:4px}
.rec-k{font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--t2);font-weight:600}
.rec-v{font-size:14px;color:var(--t2)}
.rec-v b{font-size:28px;color:var(--t1);font-variant-numeric:tabular-nums;margin-right:4px}
.rec-h{font-size:12px;color:var(--t3)}
.rec-tiles{margin-top:12px}

/* Account (PARITY row 36 gate, 2026-09-10): Plya sets it in one centered column; ours matches. */
#s-acct{max-width:1000px;margin-inline:auto}

/* ── Messages: a thread list beside the open conversation (PARITY row 14) ────────────────────
   The list and the pane share .split; on a phone one shows at a time (.msg-open = the thread). */
.split.msg-split{grid-template-columns:320px minmax(0,1fr);gap:16px}
.msg-side{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:6px;display:flex;flex-direction:column;gap:2px;max-height:calc(100vh - 210px);overflow-y:auto}
.msg-item{all:unset;box-sizing:border-box;display:flex;align-items:center;gap:10px;padding:10px;border-radius:10px;cursor:pointer;min-width:0}
.msg-item:hover{background:var(--card2)}
.msg-item.on{background:var(--card2)}
.msg-item:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
.msg-mid{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.msg-top{display:flex;align-items:baseline;gap:8px}
.msg-name{flex:1;min-width:0;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.msg-item.unread .msg-name{font-weight:700}
.msg-when{font-size:12px;color:var(--t3);white-space:nowrap}
.msg-prev{display:flex;align-items:center;gap:6px;font-size:13px;color:var(--t2);min-width:0}
.msg-prev .tag{padding:1px 7px;font-size:11px}
.msg-prev-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.msg-badge{min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:var(--acc);color:#fff;font-size:12px;font-weight:600;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box}
.msg-badge:empty{min-width:10px;width:10px;height:10px;padding:0}
.msg-more{margin:6px auto 4px}
.msg-main{background:var(--card);border:1px solid var(--line);border-radius:var(--r);min-height:420px;display:flex;flex-direction:column;min-width:0}
.msg-none{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:var(--t2);padding:40px 16px}
.msg-none svg{width:44px;height:44px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linejoin:round}
.msg-thread{display:flex;flex-direction:column;min-height:0;flex:1}
.msg-th-h{display:flex;align-items:center;gap:12px;padding:14px 16px;border-bottom:1px solid var(--line)}
.msg-th-who{flex:1;min-width:0}
.msg-th-who .sub{font-size:13px}
.msg-fact{display:inline-block;max-width:100%;overflow-wrap:anywhere}
.msg-backrow{display:none;padding:12px 16px 0}
.msg-list{flex:1;display:flex;flex-direction:column;gap:10px;padding:16px;overflow-y:auto;max-height:calc(100vh - 300px)}
.msg-b{max-width:78%;padding:10px 12px;border-radius:14px;background:var(--card2);align-self:flex-start;min-width:0}
.msg-b.out{align-self:flex-end;background:var(--acc-bg)}
.msg-meta{font-size:12px;color:var(--t3);margin-bottom:4px}
.msg-subj{font-weight:600;margin-bottom:4px;overflow-wrap:anywhere}
.msg-text{white-space:pre-wrap;overflow-wrap:anywhere;font-size:14.5px;line-height:1.45}
.msg-ro{margin:0;padding:10px 16px;border-top:1px solid var(--line);font-size:12.5px;color:var(--t3)}
@media (max-width:759.98px){
  .split.msg-split{grid-template-columns:minmax(0,1fr)}
  .msg-split.msg-open .msg-side{display:none}
  .msg-split:not(.msg-open) .msg-main{display:none}
  .msg-backrow{display:block}
  .msg-th-h .av{display:none}
  .msg-side,.msg-list{max-height:none}
  .msg-b{max-width:90%}
}
