/* Qivity CSM — styles.
 *
 * The design tokens are copied VERBATIM from Qivity CRM's app.css so the two
 * products are visibly one platform (§89). Same font, same radii, same
 * transition curve, same accent, same dark/light palettes. Do not invent a
 * colour here: if a shade is needed, add it to both products or use an
 * existing token.
 *
 * Copied rather than imported because this application is deployed
 * independently and must not fetch a stylesheet from another host at runtime —
 * that would make the CRM's availability a dependency of this product's
 * appearance, which is the whole thing we are avoiding.
 */

:root{--font:'Roboto',system-ui,-apple-system,'Segoe UI',sans-serif;--r:10px;--rlg:14px;--rsm:7px;--tr:.18s cubic-bezier(.4,0,.2,1)}
/* Fills for bars and the health ring: light tints of the status colours. The
   status colours themselves are deep shades in the light theme (they are text
   and badge colours), and as solid bars they read heavy. Same tints on both
   themes — light enough for the light theme, bright enough on the dark one.
   Used through QA.barTint(). */
:root{--bar-gr:#6ee7b7;--bar-am:#fcd34d;--bar-rd:#fca5a5;--bar-ac:#a5b4fc;--bar-bl:#93c5fd;--bar-t3:#cbd5e1}

[data-theme="dark"]{
  --bg:#0c0c11;--bg2:#131318;--bg3:#1e1e28;--bg4:#252530;--surf:#2e2e3a;
  --b:rgba(255,255,255,.08);--b2:rgba(255,255,255,.15);--b3:rgba(255,255,255,.26);
  --t:#eeeef8;--t2:#b0b0c8;--t3:#808098;
  --ac:#7c6fff;--ac2:#c4bcff;--acb:rgba(124,111,255,.16);--acbr:rgba(124,111,255,.42);
  --gr:#34d399;--grb:rgba(52,211,153,.14);--grbr:rgba(52,211,153,.38);
  --am:#fbbf24;--amb:rgba(251,191,36,.14);--ambr:rgba(251,191,36,.35);
  --rd:#f87171;--rdb:rgba(248,113,113,.14);--rdbr:rgba(248,113,113,.35);
  --bl:#60a5fa;--blb:rgba(96,165,250,.14);
  --cg:rgba(255,255,255,.08);--ch:rgba(255,255,255,.04);
  --sh:0 4px 24px rgba(0,0,0,.55);
  color-scheme:dark;
}
[data-theme="light"]{
  --bg:#f0f0f7;--bg2:#ffffff;--bg3:#e8e8f2;--bg4:#dddde8;--surf:#d4d4e0;
  --b:rgba(0,0,0,.08);--b2:rgba(0,0,0,.15);--b3:rgba(0,0,0,.26);
  --t:#141428;--t2:#484860;--t3:#787890;
  --ac:#5e52e0;--ac2:#3d33c0;--acb:rgba(94,82,224,.1);--acbr:rgba(94,82,224,.32);
  --gr:#059669;--grb:rgba(5,150,105,.09);--grbr:rgba(5,150,105,.28);
  --am:#d97706;--amb:rgba(217,119,6,.09);--ambr:rgba(217,119,6,.28);
  --rd:#dc2626;--rdb:rgba(220,38,38,.09);--rdbr:rgba(220,38,38,.28);
  --bl:#2563eb;--blb:rgba(37,99,235,.09);
  --cg:rgba(0,0,0,.06);--ch:rgba(0,0,0,.025);
  --sh:0 4px 24px rgba(0,0,0,.1);
  color-scheme:light;
}

*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%;font-family:var(--font);font-size:13.5px;line-height:1.5;color:var(--t);background:var(--bg);overflow:hidden}
button{font-family:var(--font);cursor:pointer;border:none;background:none;color:inherit}
a{color:var(--bl);text-decoration:none}
a:hover{text-decoration:underline}
input,select,textarea{font-family:var(--font)}
::-webkit-scrollbar{width:5px;height:5px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--surf);border-radius:3px}

/* Visible focus on every interactive element. Removing an outline without
   replacing it makes the product unusable by keyboard, which is not a
   trade-off anyone consented to. */
:focus-visible{outline:2px solid var(--ac);outline-offset:2px;border-radius:4px}

/* ── layout ──────────────────────────────────────────────────────────────── */

.shell{display:flex;height:100vh;overflow:hidden}

.sidebar{width:224px;min-width:224px;background:var(--bg2);border-inline-end:1px solid var(--b);
  display:flex;flex-direction:column;padding:18px 10px;height:100vh;overflow:hidden}
/* The nav scrolls; the brand above it does not. The sidebar scrolling as a
   whole took the product name off-screen as soon as the nav was taller than
   the viewport. */
.nav-scroll{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden}
.brand{position:relative;padding:0 4px 16px;margin-bottom:8px}
/* The whole block is the switcher: mark, product, organization, chevron. A
   chevron alone beside a title is a target people do not see. */
.brand-switch{display:flex;align-items:center;gap:10px;inline-size:100%;
  padding:6px;border:1px solid transparent;border-radius:10px;
  background:none;color:var(--t);cursor:pointer;text-align:start;
  transition:background .12s,border-color .12s}
.brand-switch:hover{background:var(--bg3);border-color:var(--b)}
.brand-switch[aria-expanded="true"]{background:var(--acb);border-color:var(--acbr)}
.brand-text{min-inline-size:0;flex:1}
.brand-switch>svg{flex-shrink:0;opacity:.5}

.app-menu{position:absolute;inset-inline:4px;inset-block-start:calc(100% - 8px);
  z-index:9000;padding:6px;background:var(--bg2);border:1px solid var(--b2);
  border-radius:12px;box-shadow:0 12px 32px rgba(0,0,0,.28)}
.app-menu-head{font-size:10px;text-transform:uppercase;letter-spacing:.7px;
  color:var(--t3);padding:5px 8px 6px;font-weight:600}
.app-menu-note{font-size:11.5px;color:var(--t2);padding:9px 8px;line-height:1.5}
.app-item{display:flex;align-items:center;gap:9px;inline-size:100%;
  padding:8px 9px;border-radius:8px;font-size:12.5px;color:var(--t);
  text-decoration:none;cursor:pointer}
.app-item:hover{background:var(--acb);color:var(--ac2)}
.app-dot{inline-size:7px;block-size:7px;border-radius:50%;flex-shrink:0;
  background:var(--ac)}
.is-current{color:var(--t2);cursor:default}
.is-current:hover{background:none;color:var(--t2)}
.is-current .app-dot{background:var(--gr)}
.app-here{margin-inline-start:auto;font-size:10px;color:var(--t3)}

/* Search moved to the trailing edge, beside the controls it belongs with. */
.topbar-end{margin-inline-start:auto;gap:10px}
/* No background fill: the mark is a transparent PNG that carries its own
   colour, and painting --ac behind it would box the logo in a purple square. */
.brand-mark{width:32px;height:32px;border-radius:8px;color:#fff;
  display:flex;align-items:center;justify-content:center;font-weight:600;flex-shrink:0}
.brand-mark img{width:100%;height:100%;object-fit:contain;display:block}
/* Matches the CRM's lockup, so moving between the two products the brand
   block does not change shape. */
.brand-name{font-size:15px;font-weight:700;letter-spacing:-.03em;line-height:1.2}
.brand-sub{font-size:10.5px;color:var(--t3)}

/* An area (Accounts, Renewals …): one heading row that opens its pages beneath
   it, in ordinary case and ordinary weight like every other label. The same
   rules as Qivity Accounts' sidebar. */
.ng{margin-top:2px}
.ng-head{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:var(--rsm);
  color:var(--t2);font-size:12.5px;font-weight:400;width:100%;text-align:start;border:1px solid transparent;
  background:none;cursor:pointer;transition:all var(--tr)}
.ng-head:hover{background:var(--bg3);color:var(--t)}
.ng-head .ic{flex-shrink:0}
/* Quiet: the arrow only hints that the row opens; the area name is the point. */
.ng-chev{margin-inline-start:auto;display:inline-flex;color:var(--t3);opacity:.45;
  transition:transform var(--tr),opacity var(--tr)}
.ng-chev .ic{stroke-width:1.4}
.ng-head:hover .ng-chev{opacity:.75}
.ng.open>.ng-head{color:var(--t)}
.ng.open .ng-chev{transform:rotate(180deg)}
/* Closed but holding the page you are on: the area name says so. */
.ng.has-active:not(.open)>.ng-head{color:var(--ac2)}
.ng-items{display:flex;flex-direction:column;gap:1px;margin:2px 0 6px;
  margin-inline-start:15px;padding-inline-start:8px;border-inline-start:1px solid var(--b2)}
.ng-items[hidden]{display:none}
.nb-sub{font-size:12px;padding-block:6px}
.nb{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:var(--rsm);
  color:var(--t2);font-size:12.5px;width:100%;text-align:start;transition:all var(--tr);
  border:1px solid transparent;background:none;cursor:pointer}
.nb:hover{background:var(--bg3);color:var(--t);text-decoration:none}
/* The accent bar on the start edge is the CRM's most recognisable navigation
   cue, and its absence here was the clearest sign the two were different
   products. The transparent border above reserves the same box on every item,
   so gaining one does not shift the row. */
.nb.active{background:var(--acb);color:var(--ac2);font-weight:500;
  border-color:var(--acbr);border-inline-start:3px solid var(--ac);padding-inline-start:6px}
.nb[disabled]{opacity:.42;cursor:not-allowed}
.nb[disabled]:hover{background:none;color:var(--t2)}
.nb .ic{flex-shrink:0}
.nb-soon{margin-inline-start:auto;font-size:9px;color:var(--t3);border:1px solid var(--b2);
  border-radius:10px;padding:0 5px}

.main{flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden}
.topbar{height:56px;min-height:56px;border-bottom:1px solid var(--b);display:flex;
  align-items:center;justify-content:space-between;gap:16px;padding:0 22px;background:var(--bg2)}
.content{flex:1;overflow-y:auto;padding:22px}

.page-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:18px;flex-wrap:wrap}
.page-title{font-size:19px;font-weight:600}
.page-sub{font-size:12px;color:var(--t2);margin-top:2px}

/* ── components ──────────────────────────────────────────────────────────── */

.card{background:var(--bg2);border:1px solid var(--b);border-radius:var(--rlg);padding:16px}
.card + .card{margin-top:14px}
.card-title{font-size:13px;font-weight:600;margin-bottom:12px}

.grid{display:grid;gap:14px}
.grid-4{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.grid-2{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}

.stat{background:var(--bg2);border:1px solid var(--b);border-radius:var(--r);padding:16px}
.stat-label{font-size:11px;color:var(--t2);text-transform:uppercase;letter-spacing:.04em}
.stat-value{font-size:26px;font-weight:600;margin-top:6px;line-height:1.1}

.btn{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border-radius:var(--rsm);
  font-size:12.5px;font-weight:500;transition:all var(--tr);border:1px solid transparent;cursor:pointer}
.btn:hover{text-decoration:none}
.btn-p{background:var(--ac);color:#fff}
.btn-p:hover{filter:brightness(1.08)}
.btn-s{background:var(--bg3);color:var(--t);border-color:var(--b2)}
.btn-s:hover{background:var(--bg4);border-color:var(--b3)}
.btn-ghost{color:var(--t2);background:transparent;padding:6px 9px}
.btn-ghost:hover{background:var(--bg3);color:var(--t)}
.btn-danger{background:var(--rdb);color:var(--rd);border-color:var(--rdbr)}
.btn-icon{padding:7px;border-radius:var(--rsm);background:var(--bg3);border:1px solid var(--b2);
  color:var(--t2);display:inline-flex;align-items:center;justify-content:center}
.btn-icon:hover{background:var(--bg4);color:var(--t)}
.btn[disabled]{opacity:.5;cursor:not-allowed}

.badge{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:20px;
  font-size:10.5px;font-weight:500;background:var(--bg3);color:var(--t2);border:1px solid transparent}
.badge-ac{background:var(--acb);color:var(--ac2);border-color:var(--acbr)}
.badge-gr{background:var(--grb);color:var(--gr);border-color:var(--grbr)}
.badge-am{background:var(--amb);color:var(--am);border-color:var(--ambr)}
.badge-rd{background:var(--rdb);color:var(--rd);border-color:var(--rdbr)}
.badge-bl{background:var(--blb);color:var(--bl)}

.inp,.sel{background:var(--bg3);border:1px solid var(--b2);color:var(--t);border-radius:var(--rsm);
  padding:8px 12px;font-size:13px;width:100%;transition:border-color var(--tr)}
.inp:focus,.sel:focus{border-color:var(--acbr);outline:none}
.inp::placeholder{color:var(--t3)}
textarea.inp{resize:vertical;min-height:80px}
.field{margin-bottom:12px}
.field label{display:block;font-size:11.5px;color:var(--t2);margin-bottom:5px;font-weight:500}
.field-err{color:var(--rd);font-size:11px;margin-top:4px}
.inp.is-invalid{border-color:var(--rd)}

table.tw{width:100%;border-collapse:collapse;font-size:12.5px}
table.tw th{text-align:start;font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;
  color:var(--t3);font-weight:600;padding:8px 10px;border-bottom:1px solid var(--b);white-space:nowrap}
table.tw td{padding:10px;border-bottom:1px solid var(--b);vertical-align:middle}
table.tw tbody tr{cursor:pointer;transition:background var(--tr)}
table.tw tbody tr:hover{background:var(--ch)}
/* Wide tables scroll inside their own container; the page body never does. */
.table-wrap{overflow-x:auto;border:1px solid var(--b);border-radius:var(--rlg);background:var(--bg2)}

.tabs{display:flex;gap:2px;border-bottom:1px solid var(--b);margin-bottom:18px;overflow-x:auto}
.tab{padding:9px 14px;font-size:12.5px;color:var(--t2);border-bottom:2px solid transparent;
  white-space:nowrap;background:none;border-top:none;border-inline:none;cursor:pointer}
.tab:hover{color:var(--t)}
.tab.active{color:var(--ac2);border-bottom-color:var(--ac)}

.empty{text-align:center;padding:44px 20px;color:var(--t3)}
.empty-title{font-size:13.5px;color:var(--t2);margin:10px 0 4px;font-weight:500}
.empty-text{font-size:12px;max-width:420px;margin:0 auto}

.banner{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:var(--r);
  font-size:12.5px;border:1px solid var(--b2);background:var(--bg3);margin-bottom:14px}
.banner-info{background:var(--acb);border-color:var(--acbr);color:var(--ac2)}
.banner-success{background:var(--grb);border-color:var(--grbr);color:var(--gr)}
.banner-warning{background:var(--amb);border-color:var(--ambr);color:var(--am)}
.banner-neutral{background:var(--bg3);border-color:var(--b2);color:var(--t2)}
.banner-title{font-weight:600;display:block;margin-bottom:2px}

.timeline{position:relative;padding-inline-start:22px}
.timeline::before{content:'';position:absolute;inset-inline-start:5px;top:6px;bottom:6px;width:1px;background:var(--b2)}
.tl-item{position:relative;padding-bottom:18px}
.tl-dot{position:absolute;inset-inline-start:-21px;top:4px;width:11px;height:11px;border-radius:50%;
  background:var(--bg2);border:2px solid var(--ac)}
.tl-title{font-size:12.5px;font-weight:500}
.tl-meta{font-size:11px;color:var(--t3);margin-top:1px}
.tl-body{font-size:12px;color:var(--t2);margin-top:5px;white-space:pre-wrap}

.modal-back{position:fixed;inset:0;background:rgba(0,0,0,.5);display:flex;align-items:center;
  justify-content:center;z-index:9000;padding:20px}
.modal{background:var(--bg2);border:1px solid var(--b);border-radius:var(--rlg);box-shadow:var(--sh);
  width:100%;max-width:560px;max-height:88vh;display:flex;flex-direction:column}
.modal-head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;
  border-bottom:1px solid var(--b)}
.modal-title{font-size:14px;font-weight:600}
.modal-body{padding:18px;overflow-y:auto}
.modal-foot{display:flex;justify-content:flex-end;gap:8px;padding:14px 18px;border-top:1px solid var(--b)}

.toast-wrap{position:fixed;inset-block-end:18px;inset-inline-end:18px;z-index:9600;
  display:flex;flex-direction:column;gap:8px;max-width:340px}
.toast{background:var(--bg2);border:1px solid var(--b2);border-radius:var(--r);box-shadow:var(--sh);
  padding:11px 14px;font-size:12.5px}
.toast-err{border-color:var(--rdbr);color:var(--rd)}
.toast-ok{border-color:var(--grbr);color:var(--gr)}

.search-wrap{position:relative;flex:1;max-width:420px}
.search-results{position:absolute;inset-inline:0;top:calc(100% + 6px);background:var(--bg2);
  border:1px solid var(--b2);border-radius:var(--r);box-shadow:var(--sh);max-height:340px;
  overflow-y:auto;z-index:9500}
.search-item{display:block;width:100%;text-align:start;padding:9px 12px;font-size:12.5px;
  color:var(--t);border:none;background:none;cursor:pointer}
.search-item:hover{background:var(--bg3);text-decoration:none}
.search-item small{display:block;color:var(--t3);font-size:11px}

.pager{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 4px;
  font-size:12px;color:var(--t2)}

.chip-row{display:flex;flex-wrap:wrap;gap:6px}

/* Users & Roles: the permission picker in the role editor. */
.perm-grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}
.perm-group{border:1px solid var(--b);border-radius:var(--r);padding:8px 10px 6px;margin:0;min-width:0}
.perm-group legend{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--t2);
  font-weight:600;padding:0 4px}
.perm-check{display:flex;align-items:center;gap:8px;font-size:12.5px;padding:3px 0;cursor:pointer;min-height:28px}
.perm-check input{accent-color:var(--ac)}
tr.muted-row td{color:var(--t3)}
.role-pick{min-width:210px}
.tw td .btn{white-space:nowrap}
.kv{display:grid;grid-template-columns:130px 1fr;gap:8px 14px;font-size:12.5px}
.kv dt{color:var(--t3)}
.kv dd{color:var(--t)}

.journey{display:flex;align-items:center;gap:0;flex-wrap:wrap;margin:4px 0 2px}
.journey-step{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--t3)}
.journey-step .dot{width:9px;height:9px;border-radius:50%;background:var(--bg4);border:1px solid var(--b2)}
.journey-step.done .dot{background:var(--ac);border-color:var(--ac)}
.journey-step.done{color:var(--t2)}
.journey-step.current{color:var(--ac2);font-weight:600}
.journey-sep{width:18px;height:1px;background:var(--b2);margin:0 6px}

.relmap{width:100%;min-height:280px;background:var(--bg3);border-radius:var(--r);border:1px solid var(--b)}

.skel{background:var(--bg3);border-radius:6px;animation:pulse 1.4s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}

.mut{color:var(--t2)}
.dim{color:var(--t3)}
.small{font-size:11.5px}
.row{display:flex;align-items:center;gap:8px}
.row-between{display:flex;align-items:center;justify-content:space-between;gap:12px}
.wrap{flex-wrap:wrap}
.spacer{flex:1}
.mt{margin-top:14px}
.hidden{display:none!important}
.nowrap{white-space:nowrap}
.trunc{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}

/* The scrim behind an open drawer. Declared outside the media query so the
   element can exist at any width and simply never be shown above it. */
.side-scrim{display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:7999}
.side-scrim.on{display:block}

/* Below 860px the sidebar becomes a drawer — the SAME width the CRM switches
   at. They used to differ (900 here, 860 there), which meant a tablet in
   landscape showed a drawer in one product and a sidebar in the other. */
@media (max-width:860px){
  /* dvh, not vh: a mobile browser counts the collapsing URL bar in vh, which
     leaves the bottom of the drawer unreachable. */
  .shell{height:100dvh}
  .sidebar{position:fixed;inset-block:0;inset-inline-start:0;z-index:8000;
    height:100dvh;width:252px;min-width:252px;
    transform:translateX(-110%);transition:transform var(--tr);box-shadow:var(--sh)}
  .sidebar.open{transform:none}
  .content{padding:16px}
  .topbar{padding:0 14px}
  .kv{grid-template-columns:1fr}
}
@media (min-width:861px){
  .menu-btn{display:none}
  /* Never over the desktop layout, whatever state the drawer was left in when
     the window was widened. */
  .side-scrim{display:none!important}
}
/* The drawer parks off the inline-END edge in RTL. Inside the 860px query, as
   in the CRM: at top level it applied at EVERY width and pushed the desktop
   sidebar clean off the screen in a right-to-left language. */
@media (max-width:860px){
  [dir="rtl"] .sidebar{transform:translateX(110%)}
  [dir="rtl"] .sidebar.open{transform:none}
}

/* ── the icon rail (the CRM's model) ───────────────────────────────────────
   `.rail` is set by QA.shell.syncRail: automatically at 861-1180px (a small
   laptop, a tablet in landscape), or at any desktop width by the chevron, whose
   choice is remembered. Before this CSM kept the full 224px sidebar right down
   to the drawer breakpoint and had no way to put it away, so the same person
   moving between products met different sidebars. Below 860px the drawer
   takes over (above).

   Labels are moved out of sight, not removed: a screen reader still announces
   them and `title` gives a pointer the same text. */
.brand{display:flex;align-items:center;gap:4px}
.brand-switch{flex:1;min-inline-size:0}
.rail-toggle{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;
  justify-content:center;border-radius:var(--rsm);border:1px solid transparent;
  background:none;color:var(--t3);cursor:pointer;transition:all var(--tr)}
.rail-toggle:hover{background:var(--bg3);color:var(--t);border-color:var(--b2)}
@media (max-width:860px){ .rail-toggle{display:none} }
@media (min-width:861px){
  .sidebar.rail{width:60px;min-width:60px;padding-inline:8px;overflow:visible}
  .sidebar.rail .brand{flex-direction:column;gap:6px;padding-inline:0}
  .sidebar.rail .brand-switch{justify-content:center;padding:4px}
  .sidebar.rail .brand-text,.sidebar.rail .nb-soon{display:none}
  .sidebar.rail .rail-toggle{width:100%}
  /* The chevron points the way the sidebar will go. */
  .sidebar.rail .rail-toggle svg{transform:scaleX(-1)}
  .sidebar.rail .nb>span{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
  .sidebar.rail .nb{justify-content:center;padding:9px 0;gap:0}
  /* The start bar has nowhere to sit on a centred icon, so the active state is
     carried by the fill and the accent ring instead. */
  .sidebar.rail .nb.active{border-inline-start-width:1px;padding-inline-start:0;
    box-shadow:inset 0 0 0 1px var(--acbr)}
  /* An area is its icon; its open pages are icons too, set apart by a rule
     instead of an indent, which 60px has no room for. */
  .sidebar.rail .ng-head{justify-content:center;padding:9px 0;gap:0}
  .sidebar.rail .ng-head>span{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
    overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
  .sidebar.rail .ng.open>.ng-head,.sidebar.rail .ng.has-active>.ng-head{background:var(--bg3)}
  .sidebar.rail .ng-items{margin:2px 0 6px;padding:4px 0;border-inline-start:none;
    border-block:1px solid var(--b)}
  /* The product menu opens BESIDE a rail: inside 60px it would be unreadable. */
  .sidebar.rail .app-menu{inset-inline-start:calc(100% + 6px);inset-inline-end:auto;
    inset-block-start:0;width:240px}
}

/* ── the customizable dashboard ───────────────────────────────────────────
   GridStack supplies the positioning; everything visual is ours, so a widget
   looks like the rest of the product rather than like the library. */

.grid-stack{margin:0 -8px}
/* No grid library: the cards are already in the DOM, so stack them readably
   instead of leaving them absolutely positioned at 0,0 on top of each other. */
.grid-stack.no-grid{display:flex;flex-direction:column;gap:12px;margin:0}
.grid-stack.no-grid .grid-stack-item{position:static!important;width:auto!important;height:auto!important}

.dash-card{height:100%;display:flex;flex-direction:column;background:var(--bg2);
  border:1px solid var(--b);border-radius:var(--r);padding:14px 15px;overflow:hidden}
.dash-card-head{display:flex;align-items:center;gap:8px;margin-bottom:10px;flex-shrink:0}
.dash-card-title{font-size:12px;font-weight:600;color:var(--t2);letter-spacing:.02em;
  text-transform:uppercase;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dash-card-body{flex:1;min-height:0;overflow:auto}

/* A stat card is one big number; the label is the card's own title, so the
   body carries no second copy of it. */
.dash-card.is-stat .dash-card-body{display:flex;align-items:center}
.dash-stat{width:100%;text-align:start;border:none;background:none;cursor:pointer;padding:0;color:inherit}
.dash-stat-value{font-size:30px;font-weight:600;letter-spacing:-.02em;line-height:1}
.dash-stat:hover .dash-stat-value{color:var(--ac)}

/* The two edit affordances are invisible until Customize is on. Present in the
   DOM either way so turning edit mode on does not rebuild every card. */
.dash-handle,.dash-hide{display:none;align-items:center;justify-content:center;
  width:24px;height:24px;border-radius:var(--rsm);border:1px solid var(--b2);
  background:var(--bg3);color:var(--t2);cursor:pointer;flex-shrink:0}
.dash-handle{cursor:move}
/* A chart is sized by its CARD, never by the canvas.
   The wrapper is `position:relative` with a real height and the canvas is left
   alone inside it — Chart.js's own documented arrangement, and it sizes the
   canvas itself from the parent. Stretching the canvas with `inset:0` instead
   fights that: the element fills the box while its intrinsic bitmap keeps the
   previous size, so the drawing is scaled and cropped. Narrowing the window
   turned the health ring into a quarter arc exactly that way. */
.dash-chart{position:relative;inline-size:100%;block-size:100%;min-block-size:180px}
.dash-hide:hover{border-color:var(--rd);color:var(--rd)}
body.dash-editing .dash-handle,
body.dash-editing .dash-hide{display:inline-flex}
/* Dashed while editing, so it is obvious which things are movable and that the
   page is in a mode at all. */
body.dash-editing .dash-card{border-style:dashed;border-color:var(--acbr)}
body.dash-editing .grid-stack-item-content{cursor:default}

.dash-tray{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:12px;
  padding:10px 12px;border:1px dashed var(--acbr);border-radius:var(--r);background:var(--acb)}
.dash-tray.hidden{display:none}

/* GridStack draws its own resize corner; tint it to the accent so it reads as
   part of this product. */
.grid-stack-item>.ui-resizable-se{background:none;border-inline-end:2px solid var(--ac);
  border-block-end:2px solid var(--ac);width:9px;height:9px;opacity:0;transition:opacity var(--tr)}
body.dash-editing .grid-stack-item>.ui-resizable-se{opacity:.8}

@media (max-width:860px){
  /* One column, and the cards size to their content rather than to a row
     height computed for a 12-column desktop grid. */
  .grid-stack{margin:0}
  .dash-stat-value{font-size:26px}
}

/* ── My Profile ─────────────────────────────────────────────────────────────
   The CRM's tile language, so the two products look like one product: label
   and icon on top, the figure large, a quiet line of context under it, and a
   coloured rail down the inline-start edge carrying the tile's meaning. */
.prof-head{display:flex;align-items:flex-start;gap:18px;flex-wrap:wrap}
.prof-av{inline-size:64px;block-size:64px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  font-size:23px;font-weight:600;letter-spacing:.5px;
  background:var(--acb);color:var(--ac2);border:1px solid var(--acbr)}
.prof-id{flex:1;min-inline-size:200px}
.prof-name{font-size:17px;font-weight:600;line-height:1.3}
.prof-email{font-size:12.5px;color:var(--t2);margin-block-start:2px;
  word-break:break-all}
.prof-chips{margin-block-start:9px;flex-wrap:wrap}
.prof-org{text-align:end;display:flex;flex-direction:column;gap:6px;
  align-items:flex-end}
.prof-org-k{font-size:10.5px;text-transform:uppercase;letter-spacing:.7px;
  color:var(--t3)}
.prof-org-v{font-size:13px;font-weight:600}

/* auto-fit rather than a fixed count: four tiles on a desktop, two on a
   tablet, one on a phone, with no breakpoint to keep in step with the markup. */
.prof-tiles{display:grid;gap:12px;margin-block:14px;
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}
.prof-tile{background:var(--bg2);border:1px solid var(--b);border-radius:12px;
  padding:14px 16px;border-inline-start:3px solid var(--th,var(--ac))}
.prof-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.prof-k{font-size:11px;text-transform:uppercase;letter-spacing:.6px;
  color:var(--t3);font-weight:600}
.prof-ico{color:var(--th,var(--ac));display:flex;opacity:.85}
.prof-v{font-size:27px;font-weight:600;line-height:1.15;margin-block-start:7px}
.prof-m{font-size:11.5px;color:var(--t2);margin-block-start:3px}

.prof-perms{display:flex;flex-direction:column;gap:10px;
  margin-block-start:12px}
.prof-perm{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap}
.prof-perm-k{min-inline-size:110px;font-size:11.5px;font-weight:600;
  text-transform:capitalize;color:var(--t2);padding-block-start:3px}

/* ── the account menu ───────────────────────────────────────────────────────
   A chip that is visibly pressable, and one place behind it for the things
   that are about YOU rather than about an account. The initials used to sit in
   the topbar doing nothing, beside a theme button and a logout arrow — so the
   one thing people go looking for had nowhere to click. */
.user-wrap{position:relative}
.user-chip{display:flex;align-items:center;gap:5px;padding:3px 7px 3px 3px;
  border-radius:20px;border:1px solid var(--b2);background:var(--bg2);
  color:var(--t2);cursor:pointer;transition:border-color .12s,background .12s}
.user-chip:hover{border-color:var(--acbr);background:var(--acb)}
.user-chip[aria-expanded="true"]{border-color:var(--acbr);background:var(--acb)}
.user-av{inline-size:24px;block-size:24px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  font-size:10.5px;font-weight:700;letter-spacing:.3px;
  background:var(--ac);color:#fff}

.user-menu{position:absolute;inset-inline-end:0;inset-block-start:calc(100% + 8px);
  min-inline-size:224px;z-index:9000;padding:8px;
  background:var(--bg2);border:1px solid var(--b2);border-radius:12px;
  box-shadow:0 12px 32px rgba(0,0,0,.26)}
.user-head{padding:6px 8px 8px}
.user-name{font-size:13px;font-weight:600}
.user-mail{font-size:11.5px;color:var(--t2);word-break:break-all;
  margin-block-start:1px}
.user-org{display:flex;align-items:center;gap:5px;margin-block-start:5px;
  font-size:11px;color:var(--t3)}
.user-sep{block-size:1px;background:var(--b);margin:6px 0}
.user-item{display:flex;align-items:center;gap:9px;inline-size:100%;
  padding:8px 9px;border:0;border-radius:8px;background:none;color:var(--t);
  font-size:12.5px;text-align:start;cursor:pointer;text-decoration:none}
.user-item:hover{background:var(--acb);color:var(--ac2)}
.user-danger{color:var(--rd)}
.user-danger:hover{background:var(--rdb);color:var(--rd)}

@media (max-width:620px){
  .prof-org{text-align:start;align-items:flex-start;inline-size:100%}
}

/* ── plans & billing ─────────────────────────────────────────────────────── */
/* The customer-facing pricing page. The /admin console has its own tier cards
   in admin.css: they are a different screen for a different reader, and making
   one set of rules serve both would mean every change to the sales page
   rippling into the operations one. */

.bill-grid{display:grid;gap:14px;margin-top:14px;grid-template-columns:repeat(auto-fit,minmax(250px,1fr))}
.bill-plan{display:flex;flex-direction:column;gap:9px}
.bill-plan.is-current{border-color:var(--acbr);background:var(--acb)}
.bill-plan-name{font-weight:640;font-size:15px}
.bill-plan-price{font-size:25px;font-weight:650;line-height:1.15}
.bill-plan-cycle{font-size:12px;color:var(--t3);font-weight:400}
.bill-points{list-style:none;display:grid;gap:5px;font-size:12.5px;color:var(--t2)}
.bill-points li{display:flex;gap:7px;align-items:flex-start}
.bill-points svg{flex:none;margin-top:2px;color:var(--gr)}
.bill-limits{display:grid;gap:3px;padding-top:7px;border-top:1px solid var(--b);font-size:12px}
.bill-limit{display:flex;justify-content:space-between}
.bill-foot{margin-top:auto;padding-top:8px}
.bill-foot .btn{width:100%;justify-content:center}
