:root{
  --bg:#0a0e1a; --bg-soft:#0f1524; --card:#0a0e1a;
  --input:#141b2e; --line:#232c44; --line-2:#2c3754;
  --ink:#e9ecf6; --muted:#8891a8; --label:#b7c0d6;
  --accent:#6d5efc; --accent-2:#8b7bff; --accent-d:#584fd6;
  --cyan:#3ad0e6;
  --user-bubble:#1a2138; --ai-bubble:#121a2c;
  --danger:#e5484d; --danger-soft:#2a1520;
  --glow:rgba(109,94,252,.18); --glow-strong:rgba(109,94,252,.34);
  /* Tell the browser this page is dark. Without it the user agent styles
     buttons, selects, option lists and scrollbars for a light background, so
     any control that does not set its own colour paints dark text on a dark
     panel. */
  color-scheme: dark;
}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{font-family:"Segoe UI",Roboto,system-ui,-apple-system,sans-serif;
  background:var(--bg);color:var(--ink);font-size:15px;line-height:1.55}
h1,h2{margin:0}

/* ---- shared brand logo (gradient rounded square) ---- */
.logo{width:40px;height:40px;border-radius:11px;display:inline-block;flex:0 0 auto;
  background:linear-gradient(135deg,#6d5efc 0%,#7c6cff 45%,#3ad0e6 100%);
  box-shadow:0 3px 12px var(--glow-strong);position:relative}
.logo::after{content:"";position:absolute;inset:11px 12px;border-radius:3px;
  background:linear-gradient(135deg,#fff9 0%,#fff2 60%,transparent);
  clip-path:polygon(0 100%,42% 0,58% 40%,100% 8%,100% 100%)}
.logo.sm{width:30px;height:30px;border-radius:9px}
.logo.sm::after{inset:8px 9px}
.logo.lg{width:56px;height:56px;border-radius:15px}
.logo.lg::after{inset:15px 17px}
.brand-row{display:flex;align-items:center;gap:12px}
.brand-col{display:flex;flex-direction:column;align-items:flex-start;gap:12px}
.brand-name{font-size:22px;font-weight:700;letter-spacing:.2px}
.brand-name.sm{font-size:16px;font-weight:650}
/* Ispahani banner logo */
.logo-img{height:46px;width:auto;display:block;border-radius:6px}
.logo-img.sm{height:26px;border-radius:5px}
.logo-img.lg{height:60px;border-radius:8px}

/* ===================== LOGIN ===================== */
.auth-body{display:grid;place-items:center;min-height:100vh;padding:24px;
  background:radial-gradient(900px 520px at 50% -8%,#161d38 0%,var(--bg) 58%)}
.auth-card{width:min(390px,94vw)}
.auth-sub{color:var(--muted);margin:14px 0 26px;font-size:14.5px}
.field{display:block;margin-bottom:18px}
.field-label{display:block;color:var(--label);font-size:13.5px;font-weight:600;margin-bottom:8px}
.input{width:100%;padding:12px 14px;background:var(--input);color:var(--ink);
  border:1px solid var(--line);border-radius:9px;font-size:15px;transition:.12s;outline:none}
.input::placeholder{color:#5b6478}
.input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--glow)}
.btn-signin{width:100%;margin-top:6px;padding:12px 16px;border:none;border-radius:9px;
  background:linear-gradient(180deg,var(--accent-2),var(--accent));color:#fff;
  font-size:15.5px;font-weight:700;cursor:pointer;transition:.12s;
  box-shadow:0 4px 16px var(--glow-strong)}
.btn-signin:hover{background:linear-gradient(180deg,var(--accent),var(--accent-d))}
.auth-foot{text-align:center;color:var(--muted);font-size:12.5px;margin-top:24px}
.foot-link{color:var(--accent);text-decoration:none;font-weight:600}
.foot-link:hover{text-decoration:underline}
.err{display:block;color:#ff9ea0;font-size:12.5px;margin-top:5px}
.chat-flashes{max-width:760px;margin:0 auto;width:100%;padding:12px 24px 0}

/* flashes */
.flashes:not(:empty){margin-bottom:16px}
.flash{padding:10px 13px;border-radius:8px;font-size:13.5px;font-weight:500;margin-bottom:8px;
  border:1px solid transparent}
.flash-danger{background:var(--danger-soft);color:#ff9ea0;border-color:#5a2530}
.flash-warning{background:#2a2413;color:#e9c877;border-color:#5a4d22}
.flash-success{background:#12271a;color:#7ee0a1;border-color:#255339}

/* ===================== CHAT ===================== */
.chat-body{height:100vh;overflow:hidden}
.app-shell{display:flex;height:100vh;overflow:hidden}
.main-col{flex:1;min-width:0;display:flex;flex-direction:column;height:100vh}

/* Conversation history sidebar */
.sidebar{width:264px;flex:0 0 264px;background:#0b0f1a;border-right:1px solid var(--line);
  display:flex;flex-direction:column;height:100vh}
.sidebar-head{padding:12px}
.new-chat-btn{width:100%;padding:10px 12px;border-radius:9px;border:1px solid var(--line-2);
  background:var(--input);color:var(--ink);font-weight:600;font-size:14px;cursor:pointer;transition:.12s}
.new-chat-btn:hover{border-color:var(--accent);background:#141b2e}
.conv-list{flex:1;overflow-y:auto;padding:2px 8px 12px}
.conv-empty{padding:10px 8px;font-size:13px}
.conv-group{padding:12px 10px 4px;font-size:11px;font-weight:700;letter-spacing:.5px;
  text-transform:uppercase;color:var(--muted)}
.conv-group:first-child{padding-top:4px}
.conv-item{display:flex;align-items:center;gap:2px;border-radius:8px;margin:2px 0}
.conv-item:hover{background:#141b2e}
.conv-item.active{background:#182036}
.conv-title{flex:1;min-width:0;text-align:left;background:transparent;border:none;color:var(--ink);
  font-size:13.5px;padding:9px 10px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.conv-del{background:transparent;border:none;color:var(--muted);font-size:17px;line-height:1;
  padding:6px 9px;cursor:pointer;border-radius:6px;opacity:0}
.conv-item:hover .conv-del,.conv-item.active .conv-del{opacity:1}
.conv-del:hover{color:#ff9ea0}
.icon-btn{display:inline-block;background:transparent;border:1px solid var(--line-2);color:var(--ink);
  border-radius:8px;font-size:15px;padding:6px 10px;cursor:pointer;margin-right:6px}
.icon-btn:hover{border-color:var(--accent);color:var(--accent)}
.sidebar-backdrop{display:none}
/* Collapsed sidebar (desktop) — gives charts the full width */
@media(min-width:821px){
  .sidebar{transition:width .16s ease,flex-basis .16s ease}
  .app-shell.sidebar-collapsed .sidebar{width:0;flex:0 0 0;overflow:hidden;border-right:none}
}
@media(max-width:820px){
  .sidebar{position:fixed;left:0;top:0;bottom:0;z-index:30;transform:translateX(-100%);
    transition:transform .18s ease;box-shadow:2px 0 18px rgba(0,0,0,.45)}
  .sidebar.open{transform:translateX(0)}
  .sidebar-backdrop.show{display:block;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:20}
}
.chat-header{display:flex;justify-content:space-between;align-items:center;
  padding:12px 20px;border-bottom:1px solid var(--line);background:var(--bg-soft)}
.header-right{display:flex;align-items:center;gap:12px}
.who{color:var(--muted);font-size:13.5px}
.model-select{background:var(--input);color:var(--ink);border:1px solid var(--line);
  border-radius:8px;padding:7px 10px;font-size:13.5px;outline:none;cursor:pointer}
.model-select:focus{border-color:var(--accent)}
.ghost-btn{background:transparent;border:1px solid var(--line-2);color:var(--ink);
  padding:7px 12px;border-radius:8px;font-size:13.5px;font-weight:600;cursor:pointer;
  text-decoration:none;transition:.12s}
.ghost-btn:hover{background:#182036;border-color:var(--accent)}

.messages{flex:1;overflow-y:auto;padding:18px 0}
/* Keep the greeting near the top so the cards sit above the fold instead of
   floating in a sea of empty space; scales gently on very tall screens. */
.welcome{max-width:min(1320px,100%);width:100%;box-sizing:border-box;
  margin:clamp(10px,2.5vh,34px) auto 0;padding-inline:clamp(12px,3vw,40px);text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:6px}
.welcome h2{font-size:23px;font-weight:700;margin-top:2px}
.welcome>.muted{margin-bottom:2px}
.muted{color:var(--muted)}
.msg{max-width:760px;margin:0 auto 18px;padding:0 24px;display:flex;gap:12px;flex-wrap:wrap}
/* Action icons sit on their own line beneath the bubble, not beside it. */
.msg-actions{flex:0 0 100%;display:flex;gap:1px;margin:2px 0 0 42px}
.msg.user .msg-actions{justify-content:flex-end;margin-right:0}
.msg .avatar{width:30px;height:30px;border-radius:8px;flex:0 0 auto;display:grid;
  place-items:center;font-size:13px;font-weight:700}
.msg.user .avatar{background:var(--user-bubble);color:#aab6df}
.msg.ai .avatar{background:linear-gradient(135deg,#6d5efc,#3ad0e6);color:#fff}
.msg .bubble{padding:11px 15px;border-radius:11px;white-space:pre-wrap;word-wrap:break-word;
  flex:1;font-size:14.8px}
.msg.user .bubble{background:var(--user-bubble)}
.msg.ai .bubble{background:var(--ai-bubble);border:1px solid var(--line)}
.msg .bubble.thinking{color:var(--muted)}
.msg-time{font-size:10.5px;color:var(--muted);margin-top:6px;text-align:right;opacity:.75}
/* Rendered markdown inside assistant replies */
/* Rendered markdown flows as normal HTML (no pre-wrap, which would turn the
   newlines between tags into blank lines). Plain user messages keep pre-wrap. */
.msg.ai .bubble{white-space:normal}
.msg.ai .bubble > *:first-child{margin-top:0}
.msg.ai .bubble > *:last-child{margin-bottom:0}
.bubble p:empty{display:none}
.bubble p{margin:0 0 10px}
.bubble h1,.bubble h2,.bubble h3,.bubble h4{margin:14px 0 8px;line-height:1.3;font-weight:650}
.bubble h1{font-size:1.35em}.bubble h2{font-size:1.2em}.bubble h3{font-size:1.08em}
.bubble ul,.bubble ol{margin:6px 0 10px;padding-left:22px}
.bubble li{margin:3px 0}
.bubble a{color:var(--accent);text-decoration:underline}
.bubble code{font-family:"Cascadia Code",Consolas,monospace;font-size:.88em;background:#0b1020;
  border:1px solid var(--line);border-radius:5px;padding:1px 5px}
.bubble pre{position:relative;margin:10px 0;border-radius:10px;border:1px solid var(--line);overflow:auto}
.bubble pre code{display:block;padding:12px 14px;border:none;border-radius:10px;background:#0d1117;
  font-size:12.8px;line-height:1.5;white-space:pre}
.bubble table{border-collapse:collapse;margin:10px 0;font-size:.92em;display:block;overflow-x:auto}
.bubble th,.bubble td{border:1px solid var(--line);padding:6px 10px;text-align:left}
.bubble th{background:#141b2e}
.bubble blockquote{border-left:3px solid var(--line-2);margin:8px 0;padding:2px 12px;color:var(--muted)}
.bubble hr{border:none;border-top:1px solid var(--line);margin:12px 0}
.copy-btn{position:absolute;top:7px;right:7px;background:#1a2138;color:var(--muted);
  border:1px solid var(--line-2);border-radius:6px;font-size:11px;padding:3px 8px;cursor:pointer;
  opacity:.6;transition:.12s}
.bubble pre:hover .copy-btn{opacity:1}
.copy-btn:hover{color:var(--ink);border-color:var(--accent)}
.speak-btn,.share-btn,.dl-btn,.copy-msg-btn,.del-msg-btn{align-self:flex-start;flex:0 0 auto;background:transparent;
  border:none;color:var(--muted);cursor:pointer;padding:4px;border-radius:6px;transition:.12s}
.speak-btn:hover,.share-btn:hover,.dl-btn:hover,
.copy-msg-btn:hover,.del-msg-btn:hover{color:var(--ink);background:#182036}
.speak-btn.speaking,.speak-btn.paused{color:var(--accent)}
.share-btn:hover{color:#25d366}
.dl-btn:hover{color:var(--accent)}
.copy-msg-btn:hover{color:var(--accent)}
.copy-msg-btn.ok{color:#3ddc97}
.del-msg-btn:hover{color:#ff7b72;background:rgba(255,123,114,.12)}
.speak-btn svg,.share-btn svg,.dl-btn svg,
.copy-msg-btn svg,.del-msg-btn svg{width:16px;height:16px;display:block}
/* Message actions stay quiet until you hover the message. */
.msg .copy-msg-btn,.msg .del-msg-btn,.msg .speak-btn,.msg .share-btn,.msg .dl-btn{opacity:0;transition:opacity .12s,color .12s,background .12s}
.msg:hover .copy-msg-btn,.msg:hover .del-msg-btn,.msg:hover .speak-btn,
.msg:hover .share-btn,.msg:hover .dl-btn,
.msg .speak-btn.speaking,.msg .speak-btn.paused,.msg .copy-msg-btn.ok{opacity:1}
@media(hover:none){.msg .copy-msg-btn,.msg .del-msg-btn,.msg .speak-btn,.msg .share-btn,.msg .dl-btn{opacity:1}}
.blink::after{content:"▋";margin-left:2px;animation:blink 1s steps(2) infinite;color:var(--accent)}
@keyframes blink{0%,50%{opacity:1}50%,100%{opacity:0}}

.composer{border-top:1px solid var(--line);background:var(--bg-soft);padding:14px 0 10px}
/* Wide screens: input and the tool icons share one row, the input filling the
   space that's left. Narrow screens stack them (input on its own row, icons
   wrapping beneath) — see the width breakpoint and simulated mobile view. */
.composer-inner{max-width:760px;margin:0 auto;padding:0 24px;display:flex;gap:10px;
  align-items:flex-end}
.chat-input{flex:1;min-width:0;resize:none;max-height:180px;background:var(--input);
  color:var(--ink);border:1px solid var(--line);border-radius:12px;padding:12px 14px;
  font-size:15px;font-family:inherit;outline:none;line-height:1.5}
.chat-input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--glow)}
.send-btn{width:44px;height:44px;flex:0 0 auto;border:none;border-radius:11px;cursor:pointer;
  background:linear-gradient(180deg,var(--accent-2),var(--accent));color:#fff;font-size:16px;
  transition:.12s}
.send-btn:hover{background:linear-gradient(180deg,var(--accent),var(--accent-d))}
.send-btn:disabled{opacity:.5;cursor:default}
.send-btn.stopping{background:linear-gradient(180deg,#e5646a,#d63e44)}
.send-btn.stopping:hover{background:linear-gradient(180deg,#d63e44,#b83239)}
/* Non-admins get a dashboard-only view: hide the free-text message box, the
   send button and the AI-model disclaimer, leaving just the read-only dashboard
   shortcut icons (which are meant for every signed-in user). The nodes stay in
   the DOM so chat.js's #input/#send lookups keep working. If the composer has
   no visible controls left for this role, the whole bar collapses cleanly. */
body[data-admin="0"] .chat-input,
body[data-admin="0"] #send,
body[data-admin="0"] .composer-hint{display:none !important}
.stopped-tag{color:var(--muted);font-size:12.5px;font-style:italic}
.mic-btn{width:44px;height:44px;flex:0 0 auto;border:1px solid var(--line);border-radius:11px;
  background:var(--input);color:var(--muted);cursor:pointer;display:flex;align-items:center;
  justify-content:center;transition:.12s}
.mic-btn:hover{border-color:var(--accent);color:var(--ink)}
.mic-btn svg{width:20px;height:20px}
/* The dedicated pause/resume button (non-admins) toggles via the hidden
   attribute; keep that winning over the display:flex above. */
.mic-btn[hidden]{display:none}
.mic-btn.listening{background:#3a1520;border-color:#e5484d;color:#ff9ea0;
  animation:mic-pulse 1.2s ease-out infinite}
/* Same button while a reply is being read aloud: an accent pause/resume
   state, distinct from the red listening pulse. */
.mic-btn.speaking-ctl{background:rgba(56,189,248,.16);border-color:var(--accent);
  color:var(--accent)}
/* Small dedicated Stop button beside the mic, only while a reply is spoken. */
.tts-stop-btn{width:36px;height:44px;flex:0 0 auto;border:1px solid var(--line);
  border-radius:11px;background:var(--input);color:#ff9ea0;cursor:pointer;
  display:flex;align-items:center;justify-content:center;transition:.12s}
.tts-stop-btn:hover{border-color:#e5484d;background:var(--danger-soft,rgba(229,72,77,.14))}
.tts-stop-btn svg{width:15px;height:15px}
.tts-stop-btn[hidden]{display:none}
.db-btn{width:44px;height:44px;flex:0 0 auto;border:1px solid var(--line);border-radius:11px;
  background:var(--input);color:var(--muted);cursor:pointer;display:flex;align-items:center;
  justify-content:center;transition:.12s}
.db-btn:hover{border-color:var(--accent);color:var(--ink)}
.db-btn svg{width:20px;height:20px}
.db-btn.active{background:rgba(56,189,248,.16);border-color:var(--accent);color:var(--accent)}
.db-table{height:44px;flex:0 0 auto;max-width:150px;border:1px solid var(--line);border-radius:11px;
  background:var(--input);color:var(--ink);cursor:pointer;padding:0 10px;font-size:13px;
  transition:.12s}
.db-table:hover{border-color:var(--accent)}
.db-table:focus{outline:none;border-color:var(--accent)}
/* ---- Metric cards (Pulse-style) on the welcome screen ---- */
.pulse-cards{max-width:100%;width:100%;margin:2px auto 0;text-align:left}
.pulse-loading{color:var(--muted);font-size:12.5px;text-align:center}
.db-ran{font-size:11px;color:var(--muted);opacity:.7;margin-top:6px;text-align:right;
  font-family:"IBM Plex Mono",ui-monospace,monospace}
.db-building{font-size:12.5px;color:var(--accent-2,#8b7bff);margin:8px 0;padding:8px 12px;
  font-family:"IBM Plex Mono",ui-monospace,monospace;letter-spacing:.02em}
.db-building::before{content:"⏳ "}
.pulse-head{font-size:13px;font-weight:700;color:var(--label);margin-bottom:6px;letter-spacing:.2px;
  display:flex;align-items:center;flex-wrap:wrap;gap:8px}
/* Title stays left; the action buttons flow to the right and wrap onto a new
   line when the viewport (or a zoom-in) leaves too little room, instead of
   overflowing/clipping. */
.pulse-head-title{font-size:clamp(13px,1.1vw + 9px,15px);font-weight:800;color:var(--ink);letter-spacing:-.1px;
  display:flex;align-items:center;gap:7px;margin-right:auto}
.pulse-head-title::before{content:'';display:inline-block;width:3px;height:16px;border-radius:2px;background:var(--accent);flex-shrink:0}
.pulse-new{border:1px solid var(--accent);background:rgba(109,94,252,.12);color:var(--accent);
  cursor:pointer;border-radius:8px;padding:5px 12px;font-size:clamp(10.5px,.5vw + 9px,11.5px);
  font-weight:700;font-family:inherit;white-space:nowrap;line-height:1.2}
.pulse-new:hover{background:rgba(109,94,252,.22)}
@media (max-width:600px){
  .pulse-head{gap:6px}
  .pulse-new{padding:4px 9px}
}
.pulse-name{position:relative}
.pulse-del{position:absolute;right:0;top:0;border:none;background:none;color:var(--muted);
  cursor:pointer;font-size:12px;padding:0 3px;border-radius:5px;opacity:0;transition:.12s}
.pulse-card:hover .pulse-del{opacity:1}
.pulse-del:hover{color:#ff7b72;background:rgba(255,123,114,.12)}

/* metric definition form */
.metric-form{background:var(--input);border:1px solid var(--line);border-radius:12px;
  padding:14px 16px;margin-bottom:14px;display:grid;
  grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:10px 16px}
.mf-row{display:flex;flex-direction:column;gap:4px;font-size:11.5px;font-weight:600;color:var(--muted)}
.mf-row select,.mf-row input[type=text]{height:36px;border:1px solid var(--line);border-radius:9px;
  background:var(--bg);color:var(--ink);padding:0 9px;font-size:13px;font-family:inherit}
.mf-row select:focus,.mf-row input:focus{outline:none;border-color:var(--accent)}
.mf-row input[type=checkbox]{width:16px;height:16px;accent-color:var(--accent)}
.mf-actions{grid-column:1/-1;display:flex;justify-content:flex-end;gap:10px;margin-top:4px}
.pulse-summary{font-size:12.5px;color:var(--muted);line-height:1.6;margin-bottom:12px}
.pulse-summary strong{color:var(--ink)}
.pulse-tag{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:999px;font-size:9.5px;
  font-weight:700;letter-spacing:.3px;text-transform:uppercase;background:rgba(109,94,252,.18);
  color:var(--accent-2,#8b7bff)}
.pulse-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:14px}
.pulse-card{background:var(--ai-bubble,var(--input));border:1px solid var(--line);border-radius:14px;
  padding:14px 16px;cursor:pointer;transition:.14s}
.pulse-card:hover{border-color:var(--accent);transform:translateY(-1px);
  box-shadow:0 8px 22px rgba(0,0,0,.28)}
.pulse-period{font-size:11px;color:var(--muted);letter-spacing:.2px}
.pulse-name{font-size:13.5px;font-weight:600;color:var(--ink);margin:2px 0 6px}
.pulse-filter{display:inline-block;font-size:10.5px;font-weight:600;color:var(--accent);
  background:rgba(99,102,241,.12);border:1px solid rgba(99,102,241,.32);border-radius:999px;
  padding:2px 9px;margin:0 0 7px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pulse-value{font-size:34px;font-weight:700;color:var(--ink);line-height:1.1}
.pulse-change{font-size:12px;margin-top:4px;font-weight:600}
.pulse-change.up{color:#3ddc97}
.pulse-change.down{color:#ff7b72}
.pulse-change.flat{color:var(--muted);font-weight:500}
.pulse-spark{height:56px;margin:10px 0 8px;position:relative}
.pulse-busy{font-weight:500;color:var(--muted);font-size:11px}
.pulse-card-error{border-style:dashed;cursor:default}
.pulse-card-error:hover{border-color:var(--line);transform:none;box-shadow:none}
.pulse-errmsg{font-size:11.5px;color:#ff9ea0;line-height:1.5;margin-top:6px}
.pulse-spread{font-size:11px;font-weight:600;color:var(--label);margin-bottom:4px;letter-spacing:.2px}
.pulse-contrib{font-size:11.5px;color:var(--muted);line-height:1.5}
.pulse-contrib strong{color:var(--label)}

/* ---- Metric detail page ---- */
.metric-detail{max-width:900px;margin:18px auto 30px;padding:0 24px}
.md-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:14px;flex-wrap:wrap}
/* A real basis, not 0. With flex:1 the title box had nothing to hold on
   to, so the view switcher and the controls took the whole row and the
   heading was squeezed into a column one word wide. Claiming a width
   makes the controls wrap to the next line instead, which is what should
   give way when there isn't room. */
.md-titlebox{flex:1 1 15rem;min-width:11rem}
.md-title{font-size:20px;font-weight:700;color:var(--ink);line-height:1.25;
  overflow-wrap:anywhere}
.md-sub{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:3px;
  font-size:11.5px;color:var(--muted)}
.md-actions{display:flex;align-items:center;gap:6px;flex:0 1 auto;
  flex-wrap:wrap;justify-content:flex-end;margin-top:2px}
.md-actions .md-wa{display:inline-flex;align-items:center;justify-content:center}
.md-actions .md-wa svg{width:15px;height:15px}
.md-actions .md-wa:hover{color:#25d366;border-color:#25d366}
.md-valuerow{display:flex;align-items:center;gap:22px;padding:16px 18px;
  background:var(--ai-bubble);border:1px solid var(--line);border-radius:14px}
.md-big{font-size:42px;font-weight:700;color:var(--ink);line-height:1}
.md-compare{font-size:13px;font-weight:600;border-left:1px solid var(--line);padding-left:22px}
.md-compare .up{color:#3ddc97}
.md-compare .down{color:#ff7b72}
.md-note{font-size:11.5px;color:var(--muted);font-weight:500;margin-top:3px}
.md-tabs{display:inline-flex;gap:2px;background:var(--input);border:1px solid var(--line);
  border-radius:10px;padding:3px;margin:16px 0 12px}
.md-tab{background:none;border:none;color:var(--muted);cursor:pointer;font-size:13px;
  font-weight:600;padding:6px 18px;border-radius:8px;font-family:inherit}
.md-tab.active{background:var(--ai-bubble);color:var(--ink)}
.md-pane{margin-top:4px}
.md-chart{height:180px;position:relative;background:var(--ai-bubble);border:1px solid var(--line);
  border-radius:12px;padding:10px;margin-bottom:10px}
.md-chip-title{font-size:12.5px;font-weight:700;color:var(--label);margin-bottom:8px}
.md-chips{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:14px}
.md-chip{border:1px solid var(--line);background:var(--input);color:var(--ink);cursor:pointer;
  border-radius:999px;padding:6px 14px;font-size:12.5px;font-weight:600;font-family:inherit;
  transition:.12s}
.md-chip:hover{border-color:var(--accent)}
.md-chip.active{border-color:var(--accent);color:var(--accent);background:rgba(109,94,252,.14)}
.md-chip-x{margin-left:7px;opacity:0;color:var(--muted);font-size:10px;
  padding:1px 3px;border-radius:4px;transition:.12s}
.md-chip:hover .md-chip-x{opacity:.7}
.md-chip-x:hover{opacity:1 !important;color:#ff7b72;background:rgba(255,123,114,.15)}
.md-chip-hidden{border-style:dashed;color:var(--muted)}
.md-bars{display:flex;flex-direction:column;gap:7px}
.md-row{display:flex;align-items:center;gap:12px}
.md-label{flex:0 0 150px;font-size:12.5px;color:var(--label);text-align:right;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.md-track{flex:1;height:22px;background:var(--input);border-radius:5px;overflow:hidden}
.md-bar{height:100%;background:var(--accent);border-radius:5px}
.md-val{flex:0 0 165px;font-size:12.5px;font-weight:600;color:var(--ink)}
.md-pct{font-weight:600}
.md-pct.up{color:#3ddc97}
.md-pct.down{color:#ff7b72}
.md-pct.flat{color:var(--muted)}
.md-row.drillable{cursor:pointer;border-radius:6px;padding:2px 4px;margin:-2px -4px}
.md-row.drillable:hover{background:rgba(109,94,252,.10)}
.md-row.drillable:hover .md-bar{filter:brightness(1.2)}
.md-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:5px;font-size:11.5px;margin-bottom:10px}
.md-val-rows{cursor:pointer;border-radius:5px;padding:1px 5px;margin:-1px -5px;transition:.12s}
.md-val-rows:hover{background:rgba(109,94,252,.18);outline:1px solid var(--accent)}
.md-rows-note{font-size:11.5px;color:var(--muted);margin:6px 0 10px}
.md-more{display:block;margin:10px auto 0;background:none;border:none;color:var(--accent);
  cursor:pointer;font-size:12.5px;font-weight:600;font-family:inherit;padding:4px 10px;
  border-radius:7px}
.md-more:hover{background:rgba(109,94,252,.14)}
.md-answer{font-size:13.5px;color:var(--ink);background:var(--ai-bubble);border:1px solid var(--line);
  border-left:3px solid var(--accent);border-radius:10px;padding:10px 14px;margin-bottom:12px}
.md-timing{font-size:11px;color:var(--muted);margin:-4px 0 10px;letter-spacing:.02em}
.md-insights{margin-top:22px;padding-top:16px;border-top:1px solid var(--line)}
.md-insights-title{font-size:14px;font-weight:700;color:var(--ink);margin-bottom:10px}
.md-ask{color:var(--accent);border-color:var(--accent)}

/* ---- Pivot table (nested rows x grouped columns) ---- */
.pivot-view{max-width:none;width:100%}
.pivot-controls{margin-bottom:16px}
.pv-matrix-box{overflow:auto;border:1px solid var(--line);border-radius:12px;
  background:var(--ai-bubble);padding:4px}
.pv-table{border-collapse:collapse;font-size:12px;white-space:nowrap}
.pv-table th,.pv-table td{border:1px solid var(--line);padding:5px 9px}
.pv-corner,.pv-corner-sub{background:var(--input)}
.pv-colhead{background:rgba(109,94,252,.14);color:var(--accent);font-weight:700;text-align:center}
.pv-subhead{background:var(--input);color:var(--muted);font-weight:600;font-size:11px;text-align:center}
.pv-row0{background:rgba(109,94,252,.12);color:var(--accent);font-weight:700;
  text-align:left;vertical-align:top}
.pv-row1{color:var(--label);font-weight:600;text-align:left;background:var(--ai-bubble)}
.pv-cell{position:relative;min-width:78px;text-align:right}
.pv-bar{position:absolute;left:0;top:0;bottom:0;background:rgba(109,94,252,.28);z-index:0}
.pv-val{position:relative;z-index:1;color:var(--ink);font-weight:600}
.pv-cell.drillable{cursor:pointer}
.pv-cell.drillable:hover{outline:2px solid var(--accent);outline-offset:-2px}
.pv-cell.drillable:hover .pv-bar{filter:brightness(1.35)}
.yoy-cell{text-align:center}
.yoy-arrow{font-weight:700;white-space:nowrap}
.yoy-arrow.up{color:#3ddc97}
.yoy-arrow.down{color:#ff7b72}
.yoy-aligned{color:#8b96a8;font-weight:700;margin-left:2px;cursor:help}
/* Row hierarchy: indented labels with an expand toggle in the row header. */
.yoy-hier .pv-row0{white-space:nowrap}
.yoy-hier-cell{font-weight:600}
.yoy-tog{background:none;border:none;color:var(--accent);cursor:pointer;font-size:12px;
  padding:0 6px 0 0;line-height:1;width:20px;text-align:left}
.yoy-tog.leaf{color:#5a6473;cursor:default}
.yoy-hier-msg{color:#ff7b72;font-size:12px;padding:6px 10px}
.db-builder.collapsed{display:none}
.dash-fs.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.yoy-title{cursor:pointer}
.yoy-title:hover{text-decoration:underline dotted;text-underline-offset:4px}
/* Multi-value slicers and year picker: a list, not a one-line dropdown. */
.yoy-multi,.yoy-years{height:auto;min-height:88px;padding:4px}
.yoy-multi option,.yoy-years option{padding:3px 6px;border-radius:4px}
.yoy-multi option:checked,.yoy-years option:checked{background:var(--accent);color:#fff}
/* Sortable column headers. */
.pv-sortable{cursor:pointer;user-select:none}
.pv-sortable:hover{color:#fff;background:rgba(255,255,255,.05)}
.pv-sortable.sorted{color:var(--accent)}
.pv-sort-ind{font-size:9px;margin-left:3px;vertical-align:1px}
/* The '(All)' row sits above the values and reads as a mode, not a value. */
.yoy-multi option[value=""]{font-style:italic;border-bottom:1px solid var(--line, #2a3242)}
.yoy-check{display:flex;align-items:center;gap:7px;padding:7px 0}
.yoy-check input{width:15px;height:15px;accent-color:var(--accent);cursor:pointer;margin:0}
.yoy-check label{font-size:13px;cursor:pointer;white-space:nowrap}
.yoy-note{color:#8b96a8;font-size:12px;margin:8px 2px 0;line-height:1.5}
.yoy-scope{color:var(--accent-2,#8b7bff)}
.pulse-card{position:relative}
.pulse-dash{position:absolute;right:12px;bottom:10px;border:1px solid var(--line);
  background:var(--input);color:var(--muted);border-radius:7px;cursor:pointer;font-size:12px;
  padding:2px 8px;opacity:0;transition:.12s}
.pulse-card:hover .pulse-dash{opacity:1}
.pulse-dash:hover{border-color:var(--accent);color:var(--accent)}

/* ---- One-tap dashboard question chips (welcome screen) ---- */
/* ---- Ready-made dashboards gallery ---- */
.preset-chips{max-width:100%;width:100%;margin:2px auto 0}
.preset-gallery-head{display:flex;align-items:baseline;justify-content:center;gap:10px;
  flex-wrap:wrap;margin-bottom:12px}
.pg-title{font-size:12px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.pg-sub{font-size:12px;color:var(--muted);opacity:.75}
.preset-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:11px}
.preset-card{position:relative;display:flex;align-items:center;gap:12px;text-align:left;
  background:var(--input);border:1px solid var(--line);border-radius:14px;padding:13px 15px;
  cursor:pointer;min-height:60px;transition:transform .14s,border-color .14s,background .14s;
  font-family:inherit}
.pc-del{position:absolute;top:6px;right:8px;color:var(--muted);font-size:12px;line-height:1;
  cursor:pointer;opacity:0;transition:opacity .12s;padding:2px 5px;border-radius:6px}
.preset-card:hover .pc-del{opacity:.55}
.pc-del:hover{opacity:1;color:#ff9ea0;background:rgba(239,68,68,.14)}
.preset-card:hover{border-color:var(--accent);background:rgba(99,102,241,.07);transform:translateY(-1px)}
.pc-icon{font-size:21px;flex:0 0 auto;line-height:1}
.pc-body{display:flex;flex-direction:column;gap:3px;min-width:0}
.pc-name{font-size:13.5px;font-weight:600;color:var(--ink);line-height:1.25;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.pc-sub{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* A saved dashboard whose table isn't on the current connection: shown, dimmed,
   with a dashed edge — visible rather than silently dropped. */
.preset-card-off{opacity:.5;border-style:dashed}
.preset-card-off:hover{opacity:.75}
.preset-card-new{border-style:dashed}
.preset-card-new .pc-name{color:var(--ink)}
.preset-card-new .pc-icon{color:var(--accent);font-weight:700}
.preset-card-new:hover{border-style:solid;border-color:var(--accent);background:rgba(99,102,241,.07)}

/* ---- Screen-view preview switcher ---- */
.view-switch{display:inline-flex;border:1px solid var(--line);border-radius:9px;overflow:hidden}
.view-btn{background:var(--input);border:none;color:var(--muted);cursor:pointer;padding:6px 9px;
  font-size:13px;line-height:1}
.view-btn+.view-btn{border-left:1px solid var(--line)}
.view-btn:hover{color:var(--ink)}
.view-btn.active{background:rgba(56,189,248,.16);color:var(--accent)}
.main-col.view-tablet .messages,.main-col.view-tablet .composer{max-width:768px;
  margin-left:auto;margin-right:auto;width:100%}
.main-col.view-mobile .messages,.main-col.view-mobile .composer{max-width:390px;
  margin-left:auto;margin-right:auto;width:100%}
.main-col.view-tablet .messages,.main-col.view-mobile .messages{border-inline:1px dashed var(--line)}
/* The mobile preview constrains width without shrinking the viewport, so the
   width breakpoint won't fire — stack the composer here the same way. */
.main-col.view-mobile .composer-inner{flex-wrap:wrap}
.main-col.view-mobile .chat-input{flex:1 1 100%}
.main-col.view-mobile .send-btn{margin-left:auto}

.db-preset{height:44px;flex:0 0 auto;max-width:150px;border:1px solid var(--accent);border-radius:11px;
  background:rgba(56,189,248,.1);color:var(--accent);cursor:pointer;padding:0 10px;font-size:13px;
  font-weight:600;transition:.12s}
.db-preset:hover{background:rgba(56,189,248,.18)}
.db-preset:focus{outline:none}
.db-preset:disabled{opacity:.6;cursor:not-allowed}
.db-build{width:44px;height:44px;flex:0 0 auto;border:1px solid var(--line);border-radius:11px;
  background:var(--input);color:var(--muted);cursor:pointer;display:flex;align-items:center;
  justify-content:center;transition:.12s}
.db-build:hover{border-color:var(--accent);color:var(--ink)}
.db-build svg{width:19px;height:19px}

/* ---- Guided query builder panel ---- */
.db-builder{max-width:760px;margin:0 auto 10px;background:var(--panel,#0e1526);
  border:1px solid var(--line);border-radius:14px;padding:12px 14px}
.db-builder-head{display:flex;justify-content:space-between;align-items:center;
  font-size:13px;color:var(--muted);margin-bottom:10px}
.db-builder-head strong{color:var(--ink)}
.qb-close{background:none;border:none;color:var(--muted);cursor:pointer;font-size:15px;
  width:26px;height:26px;border-radius:7px}
.qb-close:hover{background:var(--input);color:var(--ink)}
.db-builder-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
.db-builder-grid label{display:flex;flex-direction:column;gap:4px;font-size:11.5px;
  color:var(--muted);font-weight:600}
.db-builder-grid select,.db-builder-grid input{height:38px;border:1px solid var(--line);
  border-radius:9px;background:var(--input);color:var(--ink);padding:0 9px;font-size:13px}
.db-builder-grid select:focus,.db-builder-grid input:focus{outline:none;border-color:var(--accent)}
.db-builder-grid select:disabled{opacity:.5;cursor:not-allowed}
.db-builder-grid select[multiple]{height:auto;padding:4px 6px}
.db-builder-grid select[multiple] option{padding:3px 4px;border-radius:5px}
.qb-hint{font-weight:400;color:var(--muted);opacity:.75;font-size:10.5px}
.qb-note{font-weight:400;color:var(--muted);opacity:.7;font-size:10.5px;line-height:1.35;margin-top:2px}
.db-builder-filter{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line)}
.db-builder-filter-head{display:flex;justify-content:space-between;align-items:center;
  font-size:11.5px;font-weight:600;color:var(--muted);margin-bottom:8px}
.qb-add{background:none;border:1px solid var(--line);border-radius:8px;color:var(--accent);
  cursor:pointer;font-size:12px;padding:4px 10px;font-weight:600}
.qb-add:hover{border-color:var(--accent);background:rgba(56,189,248,.1)}
.qb-filter-row{display:flex;gap:8px;align-items:center;margin-bottom:8px}
.qb-filter-row select,.qb-filter-row input{height:36px;border:1px solid var(--line);
  border-radius:9px;background:var(--input);color:var(--ink);padding:0 9px;font-size:13px;min-width:0}
.qb-filter-row .qb-f-field{flex:2}
.qb-filter-row .qb-f-op{flex:1.4}
.qb-filter-row .qb-f-val,.qb-filter-row .qb-f-val2{flex:1.6}
.qb-filter-row .qb-f-multi{flex:1.6;height:auto;padding:4px 6px}
.qb-filter-row .qb-f-multi option{padding:2px 4px}
.qb-filter-row select:focus,.qb-filter-row input:focus{outline:none;border-color:var(--accent)}
.qb-f-remove{flex:0 0 auto;width:34px;height:36px;border:1px solid var(--line);border-radius:9px;
  background:var(--input);color:var(--muted);cursor:pointer;font-size:12px}
.qb-f-remove:hover{border-color:#e5484d;color:#ff9ea0}
.qb-drillmap{margin-top:12px;padding-top:10px;border-top:1px dashed var(--line)}
.qb-dm-toggle{background:none;border:none;color:var(--muted);cursor:pointer;font-size:11px;
  font-weight:600;padding:0;font-family:inherit}
.qb-dm-toggle:hover{color:var(--accent)}
.qb-dm-content{margin-top:6px}
.qb-dm-row{font-size:11.5px;color:var(--muted);line-height:1.7}
.qb-dm-src{color:var(--accent);font-weight:600}
.db-builder-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:12px}
.qb-dash{background:transparent;color:var(--accent);border:1px solid var(--accent);border-radius:9px;
  padding:9px 18px;font-size:13px;font-weight:600;cursor:pointer;transition:.12s}
.qb-dash:hover{background:rgba(56,189,248,.12)}
.qb-dash:disabled{opacity:.6;cursor:not-allowed}
.qb-run{background:var(--accent);color:#fff;border:none;border-radius:9px;padding:9px 20px;
  font-size:13px;font-weight:600;cursor:pointer;transition:.12s}
.qb-run:hover{filter:brightness(1.08)}
.qb-run:disabled{opacity:.6;cursor:not-allowed}
/* Settings changed but not applied yet — the table below is still the old run. */
.qb-run.pending{box-shadow:0 0 0 3px rgba(255,255,255,.18);animation:qb-run-nudge 1.6s ease-in-out infinite}
@keyframes qb-run-nudge{0%,100%{opacity:1}50%{opacity:.72}}

/* ---- Interactive dashboards inside a reply ---- */
/* Dashboards need room — let the bubble span the message column. */
.bubble.bubble-wide{max-width:100%;width:100%}
.msg.ai:has(.bubble-wide){max-width:1120px;width:100%}
.dash-fs{min-width:30px;text-align:center}
.icon-btn.active{border-color:var(--accent);color:var(--accent);background:rgba(109,94,252,.14)}
.dash-close{flex:0 0 auto;width:28px;height:28px;border:1px solid var(--line);border-radius:8px;
  background:var(--input);color:var(--muted);cursor:pointer;font-size:12px;line-height:1;
  font-family:inherit;transition:.12s}
.dash-close:hover{border-color:#e5484d;color:#ff9ea0;background:rgba(255,123,114,.12)}
.dash-scope{display:flex;flex-wrap:wrap;gap:6px;margin:-4px 0 10px}
.dash-kpis{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}
.dash-kpi{background:var(--input);border:1px solid var(--line);border-radius:10px;
  padding:8px 15px;min-width:88px}
.dash-kpi .k-label{font-size:10.5px;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--muted)}
.dash-kpi .k-value{font-size:19px;font-weight:700;color:var(--ink);margin-top:2px;
  font-variant-numeric:tabular-nums}
.dash-kpi .k-period{font-size:10px;color:var(--muted);margin-top:2px;font-variant-numeric:tabular-nums}
.dash-kpi .k-delta{font-size:11px;font-weight:700;margin-top:3px;letter-spacing:.02em}
.dash-kpi .k-delta.up{color:#3fb950}
.dash-kpi .k-delta.down{color:#f0795c}
/* ---- Predictive outlook panel ---- */
.fc-method{font-size:12px;color:var(--muted);margin:6px 0 12px;line-height:1.45}
/* Landing-page Forecast launcher — one card for every dataset */
.forecast-launch{margin:10px 0 4px}
.forecast-launch-card{border:1px solid var(--line);border-radius:14px;background:var(--panel);
  padding:14px 16px;max-width:720px}
.flc-head{display:flex;align-items:center;gap:11px;margin-bottom:11px}
.flc-ico{font-size:22px;line-height:1}
.flc-title{font-size:15px;font-weight:700;color:var(--ink)}
.flc-sub{font-size:12px;color:var(--muted);margin-top:1px}
.flc-row{display:flex;flex-wrap:wrap;gap:8px}
.flc-btn{border:1px solid var(--line);border-radius:100px;background:rgba(99,102,241,.08);
  color:var(--ink);font-size:12.5px;font-weight:600;padding:7px 14px;cursor:pointer;font-family:inherit;
  transition:background .12s,border-color .12s}
.flc-btn:hover{background:var(--accent);border-color:var(--accent);color:#fff}
/* Landing-page Metrics / Dashboards toggle */
.landing-tabs{display:inline-flex;gap:4px;background:var(--input);border:1px solid var(--line);
  border-radius:100px;padding:4px;margin:8px 0 10px}
.landing-panel{width:100%}
.landing-tab{display:inline-flex;align-items:center;gap:7px;border:none;background:none;
  color:var(--muted);font-family:inherit;font-size:13px;font-weight:600;padding:7px 16px;
  border-radius:100px;cursor:pointer;transition:background .13s,color .13s}
.landing-tab:hover{color:var(--ink)}
.landing-tab.active{background:var(--panel);color:var(--ink);box-shadow:0 1px 4px rgba(0,0,0,.28)}
.landing-tab .lt-ico{font-size:14px;line-height:1}
.landing-tab .lt-badge{font-size:10px;font-weight:700;background:var(--accent);color:#fff;
  border-radius:100px;padding:1px 7px;min-width:18px;text-align:center;line-height:1.5}
.landing-tab:not(.active) .lt-badge{background:var(--line);color:var(--muted)}
.landing-panel[hidden]{display:none}
.fc-ctl{background:var(--input);border:1px solid var(--line);border-radius:12px;padding:9px 12px;margin-bottom:14px}
.fc-ctl-row{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin:4px 0}
.fc-ctl-l{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);width:82px;flex:0 0 auto}
.fc-chip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:100px;
  background:rgba(99,102,241,.08);color:var(--ink);font-size:12px;font-weight:600;padding:4px 6px 4px 11px;cursor:pointer;font-family:inherit}
.fc-chip.off{opacity:.45;background:transparent}
.fc-chip .fc-dot{width:9px;height:9px;border-radius:3px}
.fc-chip .fc-x{width:16px;height:16px;border-radius:50%;display:grid;place-items:center;font-size:11px;line-height:1;background:var(--accent);color:#fff}
.fc-chip.off .fc-x{background:var(--line)}
/* Auto-fit as many cards per row as fit; never overflow a narrow container
   (min(100%,…) collapses to one column on phones / the mobile view). */
.fc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,340px),1fr));gap:14px;margin-top:6px}
/* The forecast uses the full width available (more columns / bigger charts on
   wide screens) rather than the 900px metric-detail cap, and its KPI tiles
   grow to share the row evenly. Charts are viewBox SVGs at width:100%, so they
   rescale with their card automatically as the grid reflows. */
.forecast-view{max-width:1240px}
.forecast-view .dash-kpis{gap:10px}
.forecast-view .dash-kpi{flex:1 1 140px}
.forecast-view .fc-grid svg{width:100%;height:auto;display:block}
@media (max-width:600px){
  .metric-detail{padding:0 12px}
  .forecast-view .fc-grid{gap:10px}
}
.fc-table{width:100%;border-collapse:collapse;font-size:12.5px}
.fc-table th,.fc-table td{padding:6px 7px;text-align:right;border-bottom:1px solid var(--line);white-space:nowrap}
.fc-table th:first-child,.fc-table td:first-child{text-align:left}
.fc-table th{font-size:10px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.fc-table td{font-family:"IBM Plex Mono",ui-monospace,monospace}
.fc-table .fc-next{color:var(--accent);font-weight:700}
.fc-table .fc-up{color:#3fb950}.fc-table .fc-down{color:#f0795c}
.fc-table tbody tr.fc-row:hover td{background:rgba(99,102,241,.1)}
/* Full dimension list: scrollable, with sticky header + grand-total footer */
.fc-scroll{max-height:320px;overflow:auto;border:1px solid var(--line);border-radius:8px}
.fc-scroll .fc-table{border-collapse:separate;border-spacing:0}
.fc-scroll .fc-table th,.fc-scroll .fc-table td{border-bottom:1px solid var(--line)}
.fc-scroll thead th{position:sticky;top:0;z-index:2;background:var(--panel)}
.fc-scroll tfoot td{position:sticky;bottom:0;z-index:2;background:var(--panel)}
.fc-table tfoot tr.fc-total td{font-weight:700;color:var(--ink);border-top:2px solid var(--line);border-bottom:none}
.fc-count{font-size:10px;font-weight:600;color:var(--muted);background:var(--input);
  border:1px solid var(--line);border-radius:100px;padding:1px 8px;margin-left:8px}
.fc-scroll.fc-noscroll{overflow:visible;max-height:none}
.fc-table tbody tr.fc-others td{font-style:italic;color:var(--muted)}
.fc-toggle{margin-top:7px;background:none;border:none;color:var(--accent);font-family:inherit;
  font-size:12px;font-weight:600;cursor:pointer;padding:2px 0}
.fc-toggle:hover{text-decoration:underline}
/* Floating cursor tooltip for the forecast charts and breakdown rows */
.fc-tip{position:fixed;z-index:9999;pointer-events:none;max-width:240px;
  background:var(--panel);border:1px solid var(--line);border-radius:9px;
  padding:9px 11px;box-shadow:0 8px 26px rgba(0,0,0,.34);
  font-size:12px;line-height:1.35;color:var(--ink)}
.fc-tip .fct-h{font-weight:700;font-size:12px;margin-bottom:3px}
.fc-tip .fct-k{font-weight:600;color:var(--muted);text-transform:uppercase;font-size:9.5px;letter-spacing:.05em}
.fc-tip .fct-sub{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin:1px 0 5px}
.fc-tip .fct-v{font-size:17px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1.15}
.fc-tip .fct-s{font-size:11px;color:var(--muted);margin-top:2px}
.fc-tip .fct-d{font-size:11px;font-weight:700;margin-top:5px}
.fc-tip .fct-d.up{color:#3fb950}.fc-tip .fct-d.down{color:#f0795c}
.fc-tip .fct-hist{display:flex;flex-direction:column;gap:2px;margin:2px 0}
.fc-tip .fct-row{display:flex;justify-content:space-between;gap:14px;font-variant-numeric:tabular-nums}
.fc-tip .fct-row span{color:var(--muted)}
.fc-tip .fct-row b{font-weight:600}
.fc-tip .fct-hint{font-size:10.5px;color:var(--accent);margin-top:5px}
.fc-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:2px;margin:0 0 10px;font-size:13px}
.fc-crumbs .fc-crumb{appearance:none;border:none;background:none;font:inherit;font-size:13px;font-weight:600;
  color:var(--accent);cursor:pointer;padding:3px 6px;border-radius:6px}
.fc-crumbs .fc-crumb:hover{background:rgba(99,102,241,.14)}
.fc-crumbs .fc-crumb:last-child{color:var(--ink-2,var(--muted))}
.fc-crumbs .fc-sep{color:var(--muted);margin:0 1px}
.scope-chip{font-size:11px;font-weight:600;color:var(--accent);background:rgba(109,94,252,.14);
  border:1px solid rgba(109,94,252,.35);border-radius:999px;padding:2px 9px}
/* ---- Auto-generated dashboard header (measure · breakdown · applied scope) ---- */
.dash-subhead{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin:-2px 0 10px}
.dash-subhead-h{font-size:12.5px;font-weight:700;color:var(--ink)}
.dash-subhead-chip{font-size:11px;color:var(--accent);background:rgba(109,94,252,.12);
  border:1px solid rgba(109,94,252,.32);border-radius:999px;padding:2px 9px}
.dash-subhead-chip .dsh-k{color:var(--muted);font-weight:600}
.dash-subhead-chip b{color:var(--accent);font-variant-numeric:tabular-nums}
/* ---- Tableau-style interactive filter bar ---- */
.dash-filter-bar{display:flex;flex-wrap:wrap;align-items:center;gap:5px;margin:0 0 10px;
  padding:6px 8px;background:var(--input);border:1px solid var(--line);border-radius:10px;min-height:38px}
.dfb-clear{flex:0 0 auto;width:26px;height:26px;border:1px solid var(--line);border-radius:7px;
  background:transparent;color:var(--muted);cursor:pointer;font-size:16px;line-height:1;
  display:flex;align-items:center;justify-content:center;transition:.12s;font-family:inherit;padding:0}
.dfb-clear:hover{border-color:#e5484d;color:#ff9ea0;background:rgba(255,123,114,.1)}
.dfb-divider{width:1px;height:20px;background:var(--line);margin:0 2px;flex:0 0 auto}
.dfb-chip{position:relative;display:inline-flex;align-items:center;border:1px solid var(--line);
  border-radius:999px;padding:4px 10px;cursor:pointer;font-size:11.5px;white-space:nowrap;
  user-select:none;transition:border-color .12s,background .12s;background:transparent}
.dfb-chip:hover{border-color:var(--accent)}
.dfb-chip.dfb-chip-active{border-color:var(--accent);background:rgba(99,102,241,.1)}
.dfb-chip-label{color:var(--muted);font-weight:600;font-size:11.5px}
.dfb-chip-sep{color:var(--muted);opacity:.4;margin:0 3px}
.dfb-chip-value{color:var(--ink);font-weight:600;font-size:11.5px}
.dfb-chip-arrow{color:var(--muted);font-size:10px;opacity:.7;margin-left:2px}
.dfb-chips{display:contents}
.dfb-chip-hide{margin-left:6px;color:var(--muted);opacity:0;font-size:13px;line-height:1;
  width:13px;text-align:center;transition:opacity .12s;flex:0 0 auto}
.dfb-chip:hover .dfb-chip-hide,.dfb-chip.dfb-chip-active .dfb-chip-hide{opacity:.55}
.dfb-chip-hide:hover{opacity:1;color:#ff9ea0}
.dfb-more{border-style:dashed;color:var(--muted)}
.dfb-more:hover{color:var(--accent)}
.dfb-dropdown{position:absolute;top:calc(100% + 5px);left:0;z-index:1200;min-width:190px;
  max-height:260px;overflow-y:auto;background:var(--panel,#141929);border:1px solid var(--line);
  border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,.5);padding:5px 4px 0}
.dfb-drop-search{width:100%;box-sizing:border-box;border:1px solid var(--line);border-radius:6px;
  background:var(--input);color:var(--ink);font-size:12px;padding:5px 8px;margin-bottom:4px;
  outline:none;font-family:inherit}
.dfb-drop-opt{display:flex;align-items:center;gap:7px;padding:5px 8px;border-radius:6px;
  font-size:12px;color:var(--ink);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dfb-drop-opt:hover{background:rgba(99,102,241,.12)}
.dfb-drop-all{border-bottom:1px solid var(--line);margin-bottom:3px;padding-bottom:6px}
.dfb-drop-footer{position:sticky;bottom:0;background:var(--panel,#141929);
  border-top:1px solid var(--line);padding:4px}
.dfb-drop-apply{width:100%;border:none;background:var(--accent);color:#fff;font-weight:600;
  font-size:12px;padding:6px;cursor:pointer;border-radius:6px;font-family:inherit;transition:.12s}
.dfb-drop-apply:hover{filter:brightness(1.1)}
.dfb-drop-loading{padding:10px 8px;color:var(--muted);font-size:12px}

/* Non-admin YoY "smart bar": compact measure/aggregation/breakdown selects
   sitting alongside the reused dfb-* dimension filter chips. */
.yoy-smartbar{margin:0 0 12px;padding:8px 10px;border:1px solid var(--line);
  border-radius:10px;background:var(--panel,#0e1526)}
.yoy-sb-ctl{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;
  color:var(--muted);font-weight:600}
.yoy-sb-ctl select{height:30px;border:1px solid var(--line);border-radius:7px;
  background:var(--input,#0e1526);color:var(--ink);font-size:11.5px;padding:0 8px;
  font-family:inherit}
.yoy-sb-ctl select:focus{outline:none;border-color:var(--accent)}
.yoy-sb-hier{display:none;align-items:center;gap:10px;flex-wrap:wrap;
  padding-left:10px;margin-left:2px;border-left:1px solid var(--line)}
.yoy-sb-exec{margin-left:auto;display:inline-flex;align-items:center}
.yoy-sb-run{height:32px;padding:0 16px;border:1px solid var(--accent);border-radius:8px;
  background:var(--accent);color:#fff;font-size:12px;font-weight:600;cursor:pointer;
  font-family:inherit;white-space:nowrap}
.yoy-sb-run:hover{filter:brightness(1.08)}
.yoy-sb-run.pending{box-shadow:0 0 0 3px rgba(99,102,241,.28);animation:yoySbPulse 1.4s ease-in-out infinite}
@keyframes yoySbPulse{0%,100%{box-shadow:0 0 0 3px rgba(99,102,241,.28)}50%{box-shadow:0 0 0 3px rgba(99,102,241,.12)}}

/* Admin "Connect a table" editor (curated joins). */
.link-modal-overlay{position:fixed;inset:0;z-index:2000;background:rgba(0,0,0,.55);
  display:flex;align-items:center;justify-content:center;padding:20px}
.link-modal{width:min(560px,94vw);max-height:86vh;overflow:auto;background:var(--panel,#0e1526);
  border:1px solid var(--line);border-radius:12px;padding:18px 20px;
  box-shadow:0 20px 60px rgba(0,0,0,.5)}
.link-modal-h{font-size:15px;font-weight:700;color:var(--ink);margin-bottom:12px}
.link-modal-body{display:flex;flex-direction:column;gap:8px}
.link-modal-foot{margin-top:16px;display:flex;justify-content:flex-end}
.link-sec-h{font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--muted);margin-top:10px}
.link-muted{color:var(--muted);font-size:12.5px}
.link-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:8px 10px;border:1px solid var(--line);border-radius:8px;font-size:12.5px;color:var(--ink)}
.link-sel{height:36px;border:1px solid var(--line);border-radius:8px;background:var(--input,#0e1526);
  color:var(--ink);font-size:12.5px;padding:0 8px;font-family:inherit}
.link-cols{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0 4px}
.link-col{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--ink);
  border:1px solid var(--line);border-radius:7px;padding:4px 8px;cursor:pointer}
.link-cols .link-col input{margin:0}
.yoy-linked-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:12px;
  padding-top:10px;border-top:1px dashed var(--line)}
.yoy-linked-h{font-size:11px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;
  color:var(--muted);margin-right:2px}
.dfb-chip-linked{border-style:dashed}
.dfb-chip-linked .dfb-chip-label::before{content:"🔗 ";font-size:10px}

.dash-rows{height:28px;border:1px solid var(--line);border-radius:8px;background:var(--input);
  color:var(--muted);font-size:11.5px;font-weight:600;padding:0 8px;cursor:pointer;font-family:inherit}
.dash-rows:hover{border-color:var(--accent);color:var(--accent)}
.dashboard{margin-top:12px}
.dash-head{display:flex;align-items:center;gap:8px;margin:2px 0 10px}
.dash-title{font-size:15px;font-weight:600;color:var(--ink);margin:0;flex:1;min-width:0}
.dash-fs{flex:0 0 auto;border:1px solid var(--line);border-radius:8px;background:var(--input);
  color:var(--muted);cursor:pointer;font-size:11.5px;font-weight:600;padding:5px 11px;white-space:nowrap}
.dash-fs:hover{border-color:var(--accent);color:var(--accent)}

/* Full screen: native :fullscreen and the CSS fallback both enlarge the grid */
.dashboard:fullscreen,.dashboard:-webkit-full-screen,.dashboard.dash-fs-fallback{
  background:var(--bg);overflow:auto;padding:24px}
.dashboard.dash-fs-fallback{position:fixed;inset:0;z-index:1000;margin:0}
.dashboard:fullscreen .dash-grid,.dashboard:-webkit-full-screen .dash-grid,
.dashboard.dash-fs-fallback .dash-grid{grid-template-columns:repeat(auto-fit,minmax(440px,1fr))}
.dashboard:fullscreen .dash-canvas,.dashboard:-webkit-full-screen .dash-canvas,
.dashboard.dash-fs-fallback .dash-canvas{height:min(46vh,520px)}
.dash-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}
.dash-card{background:var(--input);border:1px solid var(--line);border-radius:12px;padding:12px 12px 8px}
.dash-card-title{font-size:12.5px;font-weight:600;color:var(--muted);margin-bottom:8px;
  letter-spacing:.2px;display:flex;align-items:center;justify-content:space-between;gap:8px}
.dash-card-title span{flex:1;min-width:0;text-align:center}
.dash-dl{flex:0 0 auto;border:1px solid var(--line);border-radius:6px;background:var(--input);
  color:var(--muted);cursor:pointer;font-size:10px;font-weight:600;padding:2px 7px;letter-spacing:.3px}
.dash-dl:hover{border-color:var(--accent);color:var(--accent)}
/* Inline chart-type switch (bar / line / table) */
.dash-typ{display:inline-flex;flex:0 0 auto;border:1px solid var(--line);border-radius:6px;overflow:hidden}
.dash-typ-b{border:0;background:var(--input);color:var(--muted);cursor:pointer;font-size:10px;
  font-weight:600;padding:2px 8px;letter-spacing:.3px}
.dash-typ-b+.dash-typ-b{border-left:1px solid var(--line)}
.dash-typ-b:hover{color:var(--accent)}
.dash-typ-b.on{background:var(--accent);color:#fff}
.dash-card-title .dash-dl{margin-left:6px}
.dash-table-wrap{max-width:100%;overflow:auto;max-height:340px;border:1px solid var(--line);border-radius:8px}
.dash-data-table{border-collapse:collapse;width:100%;font-size:12px}
.dash-data-table th,.dash-data-table td{padding:5px 10px;border-bottom:1px solid var(--line);text-align:left;white-space:nowrap}
.dash-data-table th{position:sticky;top:0;background:var(--panel);color:var(--muted);font-weight:600}
.dash-data-table td.num,.dash-data-table th.num{text-align:right;font-variant-numeric:tabular-nums}
.dash-data-table tbody tr:hover{background:var(--input)}
.dash-crumbs{display:flex;flex-wrap:wrap;align-items:center;gap:5px;margin:0 0 8px;font-size:11px}
.dash-crumbs .crumb{background:none;border:none;padding:2px 5px;border-radius:6px;cursor:pointer;
  color:var(--accent);font-size:11px;font-weight:600;font-family:inherit}
.dash-crumbs .crumb:hover{background:rgba(56,189,248,.14);text-decoration:underline}
.dash-crumbs .crumb.current{color:var(--muted);cursor:default;font-weight:700}
.dash-crumbs .crumb-sep{color:var(--muted);opacity:.6}
.dash-crumbs .crumb-reset{margin-left:auto;border:1px solid var(--line);background:var(--input);
  color:var(--muted);border-radius:6px;padding:2px 9px;font-size:10.5px;font-weight:600;cursor:pointer;
  font-family:inherit}
.dash-crumbs .crumb-reset:hover{border-color:var(--accent);color:var(--accent)}
.dash-drill-hint{font-size:10.5px;color:var(--accent);opacity:.85;text-align:center;margin:-2px 0 6px}
.dash-followups{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:14px;
  padding-top:12px;border-top:1px dashed var(--line)}
.dash-fu-title{flex-basis:100%;font-size:11px;font-weight:700;color:var(--muted);
  letter-spacing:.3px;text-transform:uppercase}
.dash-fu{border:1px solid var(--line);background:var(--input);color:var(--accent);cursor:pointer;
  border-radius:999px;padding:7px 14px;font-size:12.5px;font-weight:600;font-family:inherit;
  transition:.12s;text-align:left}
.dash-fu:hover{border-color:var(--accent);background:rgba(109,94,252,.14)}
.drill-menu{position:fixed;z-index:1100;background:var(--input);border:1px solid var(--line);
  border-radius:10px;box-shadow:0 10px 28px rgba(0,0,0,.45);padding:6px;min-width:170px}
.drill-menu{max-height:min(62vh,420px);overflow-y:auto}
.drill-menu.vb-dm{min-width:190px}
.drill-menu-hd{font-size:10.5px;color:var(--muted);font-weight:600;padding:4px 8px 6px;position:sticky;top:0;background:var(--input)}
.drill-menu button{display:block;width:100%;text-align:left;background:none;border:none;color:var(--ink);
  padding:8px;border-radius:7px;cursor:pointer;font-size:12.5px;font-family:inherit}
.drill-menu button:hover{background:rgba(56,189,248,.14);color:var(--accent)}
.drill-menu button.vb-dm-focus{border-top:1px solid var(--line);margin-top:3px;color:var(--muted)}
.vb-dm-item{display:flex;align-items:center;gap:2px}
.vb-dm-item .vb-dm-go{flex:1;width:auto}
.vb-dm-item .vb-dm-hide{flex:0 0 24px;width:24px;text-align:center;padding:6px 0;opacity:.45;color:var(--muted)}
.vb-dm-item .vb-dm-hide:hover{opacity:1;color:#e5646a;background:none}
.vb-dm-item:hover .vb-dm-hide{opacity:.8}
.drill-menu button.vb-dm-hidtoggle{border-top:1px solid var(--line);margin-top:3px;color:var(--muted);font-size:11px}
.drill-menu button.vb-dm-restore{color:var(--muted);font-size:11.5px;padding-left:18px}
.dash-canvas{position:relative;height:240px}
.dash-canvas canvas{max-width:100%}
@keyframes mic-pulse{0%{box-shadow:0 0 0 0 rgba(229,72,77,.4)}
  70%{box-shadow:0 0 0 7px rgba(229,72,77,0)}100%{box-shadow:0 0 0 0 rgba(229,72,77,0)}}
.composer-hint{max-width:760px;margin:8px auto 0;padding:0 24px;color:var(--muted);
  font-size:11.5px;text-align:center}

.messages::-webkit-scrollbar{width:10px}
.messages::-webkit-scrollbar-thumb{background:#1e2740;border-radius:8px}

/* ---- Goals and thresholds on metric cards ---- */
.goal-wrap{margin:8px 0 4px}
.goal-track{height:5px;border-radius:3px;background:rgba(255,255,255,.10);overflow:hidden}
.goal-fill{height:100%;border-radius:3px;background:var(--accent);transition:width .3s ease}
.goal-wrap.met .goal-fill{background:#3ddc97}
.goal-wrap.breached .goal-fill{background:#ff7b72}
.goal-line{font-size:11px;color:#8b96a8;margin-top:5px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.goal-wrap.met .goal-line{color:#3ddc97}
.goal-wrap.breached .goal-line{color:#ff7b72}
.pulse-goal-btn{background:none;border:none;color:#8b96a8;cursor:pointer;font-size:13px;
  padding:0 4px;line-height:1}
.pulse-goal-btn:hover{color:var(--accent)}

/* ---- Modal dialog (goal editor, alert settings) ---- */
.modal-back{position:fixed;inset:0;background:rgba(6,10,18,.72);z-index:1000;
  display:flex;align-items:center;justify-content:center;padding:20px}
.modal-box{background:var(--panel,#141a26);border:1px solid var(--line,#2a3242);
  border-radius:14px;padding:22px 24px;width:min(520px,100%);max-height:90vh;
  overflow:auto;box-shadow:0 20px 60px rgba(0,0,0,.5)}
.modal-box h3{margin:0 0 6px;font-size:18px}
.modal-blurb{margin:0 0 16px;color:#8b96a8;font-size:13px;line-height:1.5}
.modal-field{margin-bottom:14px;display:flex;flex-direction:column;gap:6px}
.modal-field > label{font-size:12px;font-weight:600;color:#c8d0dc}
.modal-field input,.modal-field select{background:#0e131d;color:inherit;
  border:1px solid var(--line,#2a3242);border-radius:8px;padding:9px 11px;font-size:14px}
.modal-static{color:#8b96a8;font-size:14px;padding:2px 0}
.modal-hint{font-size:11px;color:#8b96a8}
.modal-radios{display:flex;flex-direction:column;gap:6px}
.modal-radio{display:flex;align-items:center;gap:8px}
.modal-radio input{width:15px;height:15px;accent-color:var(--accent);margin:0}
.modal-radio label{font-size:14px;cursor:pointer}
.modal-err{color:#ff7b72;font-size:12px;min-height:16px;margin-bottom:4px}
.modal-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:6px}
.modal-actions button{border-radius:9px;padding:9px 20px;font-size:14px;cursor:pointer;
  border:1px solid var(--line,#2a3242)}
.modal-cancel{background:transparent;color:inherit}
.modal-save{background:var(--accent);color:#fff;border-color:var(--accent)}
/* Secondary call-to-action (e.g. "Add Excel repository"), sat at the left. */
.modal-alt{background:transparent;color:var(--accent);border-color:var(--accent);margin-right:auto}
.modal-alt:hover{background:rgba(56,189,248,.12)}
.modal-remove{background:transparent;color:#ff7b72;border-color:#ff7b72;margin-right:auto}
.modal-ok{color:#3ddc97;font-size:12px;min-height:16px}
.modal-sub{margin:18px 0 8px;font-size:13px;font-weight:700;color:var(--accent);
  border-top:1px solid var(--line,#2a3242);padding-top:14px}

/* Admin usage monitor — tenant-wise active BI sessions. */
.usage-box{width:min(600px,100%)}
.usage-head{display:flex;align-items:flex-start;gap:12px;margin-bottom:14px}
.usage-head h3{margin:0 0 3px;font-size:18px}
.usage-sum{font-size:12.5px;color:var(--muted)}
.usage-sum strong{color:var(--ink)}
.usage-note{color:var(--muted);font-weight:400}
.usage-x{margin-left:auto;background:transparent;border:none;color:var(--muted);
  font-size:18px;cursor:pointer;line-height:1;padding:2px 6px}
.usage-x:hover{color:var(--ink)}
.usage-body{display:flex;flex-direction:column;gap:14px}
.usage-empty{color:var(--muted);font-size:13px;padding:14px 2px;text-align:center}
.usage-group{border:1px solid var(--line);border-radius:11px;overflow:hidden}
.usage-group-head{display:flex;align-items:center;gap:10px;padding:9px 13px;
  background:var(--input);border-bottom:1px solid var(--line)}
.usage-cname{font-weight:700;font-size:13.5px;color:var(--ink)}
.usage-gcount{margin-left:auto;font-size:11.5px;color:var(--muted);display:flex;align-items:center;gap:6px}
.usage-row{display:flex;align-items:center;gap:9px;padding:9px 13px;font-size:13px;
  border-top:1px solid rgba(255,255,255,.03)}
.usage-row:first-of-type{border-top:none}
.usage-row.idle{opacity:.62}
.usage-who{font-weight:600;color:var(--ink);white-space:nowrap;display:inline-flex;align-items:center;gap:6px}
.usage-badge{font-size:9px;font-weight:700;letter-spacing:.3px;text-transform:uppercase;
  background:var(--accent);color:#fff;border-radius:999px;padding:1px 6px}
.usage-meta{color:var(--muted);font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.usage-state{margin-left:auto;font-size:11px;color:var(--muted);white-space:nowrap}
.usage-row:not(.idle) .usage-state{color:#3ddc97}
.usage-signout{flex:0 0 auto;background:transparent;border:1px solid var(--line);
  color:var(--muted);border-radius:7px;padding:3px 10px;font-size:11px;cursor:pointer;
  opacity:0;transition:.12s}
.usage-row:hover .usage-signout{opacity:1}
.usage-signout:hover{border-color:#ff7b72;color:#ff7b72}
.usage-signout:disabled{opacity:.5;cursor:default}
.dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;display:inline-block}
.dot.on{background:#3ddc97;box-shadow:0 0 0 3px rgba(61,220,151,.16)}
.dot.off{background:#5a6478}

/* Visual builder — Tableau-style chart building over related tables */
.vb-box{width:min(1100px,98vw);height:88vh;max-height:88vh;display:flex;flex-direction:column;padding:16px 18px}
.vb-head{display:flex;align-items:center;gap:14px;margin-bottom:12px}
.vb-head h3{margin:0;font-size:17px}
.vb-tablepick{font-size:12px;color:var(--muted);display:flex;align-items:center;gap:6px}
.vb-tablepick select{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:6px 9px;font-size:13px;max-width:260px}
.vb-rel{font-size:11.5px;color:var(--muted)}
.vb-head .usage-x{margin-left:auto}
.vb-body{display:grid;grid-template-columns:260px 1fr;gap:14px;flex:1;min-height:0}
.vb-fields{display:flex;flex-direction:column;min-height:0;border:1px solid var(--line);border-radius:11px;overflow:hidden;background:var(--bg)}
.vb-search{border:none;border-bottom:1px solid var(--line);background:var(--input);color:var(--ink);padding:9px 11px;font-size:13px;outline:none}
#vb-fieldlist{overflow-y:auto;padding:4px 0}
.vb-loading,.vb-empty{color:var(--muted);font-size:12.5px;padding:12px}
.vb-fsec{display:flex;align-items:baseline;gap:8px;padding:9px 11px 3px;font-size:12px;font-weight:700;color:var(--accent-2,#8b7bff);position:sticky;top:0;background:var(--bg)}
.vb-fsec em{font-style:normal;font-weight:400;font-size:10.5px;color:var(--muted)}
.vb-field{display:flex;align-items:center;gap:8px;padding:4px 11px;font-size:13px;cursor:grab}
.vb-field:hover{background:var(--input)}
.vb-field:active{cursor:grabbing}
.vb-field.vb-dragging{opacity:.45}
.vb-drop.vb-over{border-style:solid;border-color:var(--accent);background:rgba(109,94,252,.14);color:var(--ink)}
.vb-tag{font-size:9px;font-weight:700;border-radius:4px;padding:1px 4px;flex:0 0 auto}
.vb-tag.num{background:rgba(56,189,248,.16);color:#5ec5e6}
.vb-tag.txt{background:rgba(139,123,255,.16);color:#9a8bff}
.vb-tag.calc{background:rgba(52,211,153,.16);color:#34d399;font-style:italic}
.vb-field-calc .vb-fname{color:#7fe3bd}
.vb-fsec-calc .vb-calc-add{margin-left:auto;border:1px solid var(--line);background:var(--input);color:#34d399;cursor:pointer;font-size:12px;line-height:1;border-radius:5px;padding:1px 6px;opacity:.85}
.vb-fsec-calc .vb-calc-add:hover{border-color:#34d399;opacity:1}
/* Calculated-field editor modal */
.vb-calc-modal{position:fixed;inset:0;z-index:10050;background:rgba(2,6,14,.62);display:flex;align-items:center;justify-content:center;padding:18px}
.vb-calc-card{background:var(--bg);border:1px solid var(--line);border-radius:12px;box-shadow:0 20px 60px rgba(0,0,0,.5);width:460px;max-width:100%;padding:18px 18px 16px;display:flex;flex-direction:column;gap:6px}
.vb-calc-head{font-size:15px;font-weight:700;margin-bottom:4px}
.vb-calc-card label{font-size:11px;font-weight:600;color:var(--muted);margin-top:6px}
.vb-calc-card input,.vb-calc-card textarea{background:var(--input);border:1px solid var(--line);border-radius:7px;color:var(--text,inherit);padding:8px 9px;font-size:13px;font-family:inherit;width:100%;box-sizing:border-box}
.vb-calc-card textarea{font-family:ui-monospace,Menlo,Consolas,monospace;resize:vertical}
.vb-calc-cols{display:flex;flex-wrap:wrap;gap:4px;max-height:78px;overflow:auto;margin-top:4px}
.vb-calc-chip{font-size:11px;border:1px solid var(--line);background:var(--input);color:#5ec5e6;border-radius:5px;padding:2px 7px;cursor:pointer}
.vb-calc-chip:hover{border-color:var(--accent);color:var(--accent)}
.vb-calc-hint{font-size:10.5px;color:var(--muted);line-height:1.45;margin-top:6px}
.vb-calc-hint code{background:var(--input);border-radius:3px;padding:0 3px}
.vb-calc-err{color:#ff7b72;font-size:12px;min-height:14px;margin-top:4px}
.vb-calc-btns{display:flex;justify-content:flex-end;gap:8px;margin-top:8px}
.vb-calc-btns button{font-size:13px;border-radius:7px;padding:7px 14px;cursor:pointer;border:1px solid var(--line);background:var(--input);color:var(--muted)}
.vb-calc-btns .vb-calc-save{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:600}
.vb-fname{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vb-fact{display:flex;gap:4px;opacity:0;transition:.1s}
.vb-field:hover .vb-fact{opacity:1}
.vb-fact button{font-size:10px;border:1px solid var(--line);background:var(--input);color:var(--muted);border-radius:5px;padding:2px 6px;cursor:pointer}
.vb-fact button:hover{border-color:var(--accent);color:var(--accent)}
.vb-canvas{display:flex;flex-direction:column;min-height:0;min-width:0}
.vb-shelves{display:flex;flex-direction:column;gap:6px;margin-bottom:7px}
.vb-shelf{display:flex;align-items:center;gap:10px}
.vb-shelf-lbl{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);width:82px;flex:0 0 auto}
.vb-agg{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:6px 8px;font-size:12.5px}
.vb-drop{flex:1;min-height:38px;border:1px dashed var(--line);border-radius:9px;padding:6px 9px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;color:var(--muted);font-size:12px}
.vb-shelf-hier{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;
  text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
.vb-shelf-hier select{text-transform:none;letter-spacing:0;font-weight:600;background:var(--input);color:var(--ink);
  border:1px solid var(--line);border-radius:7px;padding:5px 7px;font-size:12px}
.re-sub.fed-dims-sub{display:flex;align-items:center;justify-content:space-between;gap:8px}
.vb-drop.has{border-style:solid;background:var(--input);color:var(--ink)}
.vb-pill{display:inline-flex;align-items:center;gap:6px;border-radius:7px;padding:3px 8px;font-size:12px;font-weight:600}
.vb-pill.meas{background:rgba(56,189,248,.18);color:#9fdcf0}
.vb-pill.dim{background:rgba(139,123,255,.18);color:#c3b8ff}
.vb-pill button{border:none;background:none;color:inherit;cursor:pointer;font-size:11px;opacity:.7}
.vb-pill button:hover{opacity:1}
.vb-pill.off{opacity:.42}
.vb-pill-tg{border:none;background:none;color:inherit;cursor:pointer;font-size:11px;opacity:.85;padding:0;margin-right:1px}
.vb-pill-tg:hover{opacity:1}
.vb-fpill{display:inline-flex;align-items:center;gap:5px;background:rgba(245,159,0,.14);border:1px solid rgba(245,159,0,.35);border-radius:8px;padding:3px 6px;font-size:12px}
.vb-fnm{color:#f0c674;font-weight:600;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vb-fop{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:2px 4px;font-size:11px}
.vb-fval{background:var(--bg);color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:2px 6px;font-size:12px;width:96px}
.vb-fvalbox{display:contents}
select.vb-fvalsel{width:auto;max-width:200px;min-width:96px;cursor:pointer;padding-right:4px}
.vb-fpill button{border:none;background:none;color:#f0c674;cursor:pointer;font-size:11px;opacity:.75}
.vb-fpill button:hover{opacity:1}
.vb-relbtn{background:transparent;color:var(--muted);border:1px solid var(--line);border-radius:8px;padding:5px 10px;font-size:12px;cursor:pointer}
.vb-relbtn.vb-speed-on{color:#3ddc97;border-color:#3ddc97}
.vb-relbtn:hover{border-color:var(--accent);color:var(--accent)}
/* Relationships editor */
.vb-rel-box{width:min(680px,98vw)}
.re-list{margin:6px 0 14px;display:flex;flex-direction:column;gap:6px;max-height:260px;overflow:auto}
.re-empty{color:var(--muted);font-size:13px;padding:8px 2px}
.re-row{display:flex;align-items:center;gap:10px;padding:7px 11px;background:var(--input);border:1px solid var(--line);border-radius:9px;font-size:13px}
.re-txt{flex:1}.re-txt b{color:var(--accent-2,#8b7bff)}
.re-del{border:none;background:none;color:var(--muted);cursor:pointer;font-size:12px}
.re-del:hover{color:#ff7b72}
.re-add{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.re-sel{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:6px 8px;font-size:12.5px;max-width:150px}
.re-arrow{color:var(--muted);font-weight:700}
.re-sub{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);margin:14px 0 6px}
.re-row.re-off{opacity:.7}
.re-reconnect{border:1px solid var(--accent);background:transparent;color:var(--accent);border-radius:7px;padding:2px 9px;font-size:11px;cursor:pointer}
.re-reconnect:hover{background:rgba(109,94,252,.12)}
.re-edges{display:flex;flex-direction:column;gap:4px;max-height:200px;overflow:auto}
.re-erow{display:flex;align-items:center;gap:8px;padding:5px 10px;background:var(--bg);border:1px solid var(--line);border-radius:8px;font-size:12px}
.re-etxt{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.re-etxt em{color:var(--accent-2,#8b7bff);font-style:normal;font-size:10.5px}
.re-jt{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:6px;font-size:11px;padding:2px 4px}

/* Cross-database (federated) builder */
.fed-box{width:min(1360px,98vw);height:92vh;max-height:92vh}
.fed-body{display:grid;grid-template-columns:420px 1fr;gap:14px;flex:1;min-height:0}
.fed-sources{overflow:auto;padding-right:6px;border-right:1px solid var(--line)}
.fed-src{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.fed-line{display:flex;align-items:center;gap:6px;margin-bottom:5px}
.fed-on{color:var(--muted);font-size:11px}
.fed-period{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.fed-hint{color:var(--muted);font-size:11px;font-weight:400}
.fed-sources .re-sel{max-width:130px}
.fed-sources .vb-relbtn{margin:4px 0 10px;font-size:11.5px}
.fed-run-row{display:flex;align-items:center;gap:14px;margin-top:14px;border-top:1px solid var(--line);padding-top:12px}
.fed-run-row .vb-run{margin-left:auto}
.fed-canvas{display:flex;flex-direction:column;min-height:0;gap:8px}
.fed-canvas .vb-chart-wrap{flex:1;min-height:300px;position:relative}
.fed-canvas .vb-table{max-height:38%;overflow:auto}
.fed-toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:12px;padding:6px 2px;border-bottom:1px solid var(--line);position:relative}
.fed-showme{display:inline-flex;gap:3px;flex-wrap:wrap}
.fed-cbtn{width:30px;height:28px;display:inline-flex;align-items:center;justify-content:center;font-size:14px;line-height:1;
  border:1px solid var(--line);background:var(--input);color:var(--muted);border-radius:7px;cursor:pointer;transition:all .12s}
.fed-cbtn:hover{color:var(--ink);border-color:var(--accent-2,#8b7bff)}
.fed-cbtn.on{background:var(--accent-2,#6d5efc);border-color:var(--accent-2,#6d5efc);color:#fff}
.fed-drillchip{display:inline-flex;align-items:center;font-size:11.5px;font-weight:600;color:var(--accent-2,#8b7bff);
  background:color-mix(in srgb,var(--accent-2,#8b7bff) 14%,transparent);border:1px solid var(--line);border-radius:12px;padding:2px 10px}

/* Visual builder — modern (Show Me, per-measure agg, KPI, toolbar) */
.vb-box{width:min(1440px,98vw);height:92vh;max-height:92vh}
/* Collapse the field list for a full-width chart. */
.vb-box.vb-collapsed .vb-body{grid-template-columns:1fr}
.vb-box.vb-collapsed .vb-fields{display:none}
.fed-box.fed-collapsed .fed-body{grid-template-columns:1fr}
.fed-box.fed-collapsed .fed-sources{display:none}
/* Maximize to (near) full screen for the biggest possible chart. */
.vb-box.vb-max,.fed-box.vb-max,.fed-box.fed-max{width:100vw;max-width:100vw;height:100vh;max-height:100vh;border-radius:0}
.vb-magg{background:var(--bg);color:var(--ink);border:1px solid var(--line);border-radius:5px;font-size:10.5px;padding:1px 3px;margin:0 2px}
.vb-period{flex:1;min-height:38px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:5px 4px}
.vb-psel{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:6px 9px;font-size:12.5px;max-width:220px}
.vb-psel:disabled{opacity:.5}
.vb-pdate{background:var(--bg);color:var(--ink);border:1px solid var(--line);border-radius:7px;padding:4px 7px;font-size:12px}
.vb-period-none{color:var(--muted);font-size:12px}
.vb-pill.color{background:rgba(58,208,230,.16);color:#8fe6f3}
.vb-toolbar{display:flex;align-items:center;gap:12px;margin:4px 0 8px;flex-wrap:wrap;position:relative}
.vb-showme{display:flex;gap:4px;flex-wrap:wrap;flex:1;min-width:0}
/* Tableau-style "Show Me" button + floating panel */
.vb-showme-btn{display:inline-flex;align-items:center;gap:6px;font-weight:600}
.vb-showme-btn .vb-sm-ico{font-size:14px;line-height:1}
.vb-showme-btn.open{border-color:var(--accent);color:var(--ink)}
.vb-showme-panel{position:absolute;top:calc(100% + 6px);left:0;z-index:60;width:min(560px,94%);
  background:var(--panel,#121826);border:1px solid var(--line);border-radius:12px;padding:12px;
  box-shadow:0 18px 46px rgba(0,0,0,.5)}
.vb-sm-hd{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:0 2px 9px}
.vb-sm-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.vb-sm-card{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px;height:64px;
  border:1px solid var(--line);background:var(--input);color:var(--muted);border-radius:9px;cursor:pointer;transition:.12s;position:relative;padding:4px}
.vb-sm-card .vb-sm-gl{font-size:20px;line-height:1}
.vb-sm-card .vb-sm-lb{font-size:10px;line-height:1.1;text-align:center;color:var(--muted)}
.vb-sm-card:hover:not(:disabled){border-color:var(--accent);color:var(--ink)}
.vb-sm-card:hover:not(:disabled) .vb-sm-lb{color:var(--ink)}
.vb-sm-card.on{background:var(--accent);border-color:var(--accent)}
.vb-sm-card.on .vb-sm-gl,.vb-sm-card.on .vb-sm-lb{color:#fff}
.vb-sm-card.rec:not(.on){border-color:var(--accent);box-shadow:0 0 0 1px var(--accent) inset}
.vb-sm-card.rec:not(.on) .vb-sm-gl{color:var(--accent)}
.vb-sm-card:disabled{opacity:.32;cursor:not-allowed}
.vb-sm-hint{margin-top:10px;font-size:11px;color:var(--muted);line-height:1.4}
/* Share / Export menu */
.vb-sharemenu{position:fixed;z-index:9000;width:264px;background:var(--panel,#121826);border:1px solid var(--line);
  border-radius:11px;padding:6px;box-shadow:0 18px 46px rgba(0,0,0,.55)}
.vb-shm-item{display:flex;flex-direction:column;gap:1px;width:100%;text-align:left;background:transparent;border:0;
  border-radius:8px;padding:9px 11px;cursor:pointer;color:var(--ink)}
.vb-shm-item:hover:not(.dis){background:rgba(109,94,252,.14)}
.vb-shm-item .vb-shm-l{font-size:13px;font-weight:600}
.vb-shm-item .vb-shm-s{font-size:11px;color:var(--muted)}
.vb-shm-item.dis{opacity:.4;cursor:not-allowed}
/* Packed bubbles */
.vb-bub{position:relative;width:100%;height:100%;min-height:320px}
.vb-bub-c{position:absolute;border-radius:50%;display:flex;flex-direction:column;align-items:center;justify-content:center;
  color:#fff;overflow:hidden;box-shadow:inset 0 0 0 1px rgba(0,0,0,.15);cursor:default;text-align:center;padding:2px}
.vb-bub-l{font-size:11px;font-weight:700;line-height:1.1;text-shadow:0 1px 2px rgba(0,0,0,.4);max-width:96%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vb-bub-v{font-size:10px;font-weight:600;opacity:.95;text-shadow:0 1px 2px rgba(0,0,0,.4)}
.vb-cbtn{width:34px;height:30px;border:1px solid var(--line);background:var(--input);color:var(--muted);border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.12s;position:relative}
.vb-cbtn .vb-cgl{font-size:15px;line-height:1}
.vb-cbtn:hover:not(:disabled){border-color:var(--accent);color:var(--ink)}
.vb-cbtn.on{background:var(--accent);color:#fff;border-color:var(--accent)}
.vb-cbtn.rec:not(.on){border-color:var(--accent);color:var(--accent)}
.vb-cbtn.rec::after{content:'';position:absolute;top:-3px;right:-3px;width:6px;height:6px;border-radius:50%;background:#3ddc97}
.vb-cbtn:disabled{opacity:.3;cursor:not-allowed}
.vb-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.vb-tlab{font-size:11.5px;color:var(--muted);display:flex;align-items:center;gap:5px}
.vb-tlab[hidden]{display:none!important}
.vb-tlab select,.vb-tlab input{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:7px;padding:5px 7px;font-size:12px}
.vb-tlab input{width:62px}
.vb-crumbs{display:flex;align-items:center;gap:4px;flex-wrap:wrap;margin:0 0 6px;font-size:12px}
.vb-crumb{border:1px solid var(--line);background:var(--input);color:var(--accent-2,#8b7bff);border-radius:7px;padding:3px 9px;cursor:pointer;font-size:11.5px}
.vb-crumb:hover{border-color:var(--accent);color:var(--accent)}
.vb-crumb-sep{color:var(--muted)}
.vb-crumb-cur{color:var(--ink);font-weight:600;font-size:11.5px;padding:0 3px}
/* Metric-Card-style header + auto narrative above the chart */
.vb-narr{margin:0 0 10px;padding:12px 14px;border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:10px;background:linear-gradient(180deg,rgba(109,94,252,.08),rgba(109,94,252,.02))}
.vb-narr-head{display:flex;flex-direction:column;gap:2px;margin-bottom:8px}
.vb-narr-title{font-size:15px;font-weight:700;color:var(--ink);line-height:1.25}
.vb-narr-ctx{font-size:11.5px;color:var(--muted)}
.vb-narr-body{display:flex;flex-wrap:wrap;gap:8px 10px;align-items:center}
.vb-nchip{font-size:12px;color:var(--ink);background:var(--input);border:1px solid var(--line);
  border-radius:8px;padding:5px 10px;line-height:1.35}
.vb-nchip .vb-nk{font-weight:800;font-variant-numeric:tabular-nums;color:var(--accent-2,#8b7bff)}
.vb-nchip b{font-variant-numeric:tabular-nums}
.vb-nchip b.up{color:#3ddc97}.vb-nchip b.down{color:#e5646a}
.vb-nsub{color:var(--muted)}
/* Read-only saved dashboard: header + narrative + chart only (no builder chrome) */
.vb-readonly .vb-fields,.vb-readonly .vb-shelves,.vb-readonly .vb-toolbar,
.vb-readonly .vb-tablepick,.vb-readonly #vb-collapse,.vb-readonly #vb-speedup,
.vb-readonly #vb-rels,.vb-readonly .fed-sources,.vb-readonly .fed-toolbar,
.vb-readonly #fed-collapse{display:none!important}
.vb-readonly .vb-body,.vb-readonly .fed-body{grid-template-columns:1fr}
.vb-readonly .vb-narr{margin-top:4px}
/* Focus mode — hide the shelves, field list and toolbar so the chart/table
   fills the whole canvas (header + narrative stay). Toggled from the header. */
.vb-focus .vb-fields,.vb-focus .vb-shelves,.vb-focus .vb-toolbar,.vb-focus #vb-collapse,
.fed-box.vb-focus .fed-sources,.fed-box.vb-focus .fed-toolbar,.fed-box.vb-focus #fed-collapse{display:none!important}
.vb-focus .vb-body,.vb-focus .fed-body{grid-template-columns:1fr}
.vb-focus .vb-result{flex:1 1 auto;min-height:0}
.vb-focus .vb-chart-wrap{min-height:60vh}
/* Share mode — a no-login /r/<token> interactive view. Fields, shelves and the
   toolbar STAY visible (self-service drill within the dataset); only editing /
   admin / save / navigation controls are hidden. */
.vb-share.vb-box{width:100vw;max-width:100vw;height:100vh;max-height:100vh;border-radius:0}
.vb-share #vb-home,.vb-share .vb-tablepick,.vb-share #vb-speedup,.vb-share #vb-rels,
.vb-share #vb-share,.vb-share #vb-edit,.vb-share #vb-save,.vb-share #vb-metric,
.vb-share #vb-x,.vb-share #vb-max{display:none!important}
.vb-share .vb-head h3::after{content:' · shared report';font-weight:400;color:var(--muted);font-size:12px}
/* Row-hierarchy table (admin): nested Level 1 ▸ 2 ▸ 3 with subtotals */
.vb-hier{width:100%;border-collapse:collapse}
.vb-hier th,.vb-hier td{padding:4px 10px;border-bottom:1px solid var(--line);font-size:12px;white-space:nowrap}
.vb-hier th{text-align:left;color:var(--muted);font-weight:600;position:sticky;top:0;background:var(--panel,#121826)}
.vb-hier td.num,.vb-hier th.num{text-align:right;font-variant-numeric:tabular-nums}
.vb-hier tr.vb-hgrp1{font-weight:700;color:var(--ink);background:rgba(109,94,252,.10)}
.vb-hier tr.vb-hgrp2{font-weight:600;color:var(--ink);background:rgba(109,94,252,.05)}
.vb-hier tr.vb-hgrp{color:var(--ink)}
.vb-hier tr.vb-hleaf td{color:var(--muted)}
.vb-hier tr.vb-hleaf td:first-child{color:var(--ink)}
.vb-hier tr.vb-hgrand{font-weight:800;color:var(--ink);background:rgba(109,94,252,.16)}
.vb-hier tr.vb-hgrand td{border-bottom:2px solid var(--accent)}
/* Non-canvas visuals host (highlight table, treemap) */
.vb-viz{position:absolute;inset:0;overflow:auto}
.vb-heat{border-collapse:collapse;font-size:11.5px}
.vb-heat th,.vb-heat td{border:1px solid var(--line);padding:4px 8px;white-space:nowrap}
.vb-heat thead th{position:sticky;top:0;background:var(--panel,#121826);color:var(--muted);z-index:2}
.vb-heat tbody th{position:sticky;left:0;background:var(--panel,#121826);color:var(--ink);text-align:left;font-weight:600;z-index:1}
.vb-heat td.num,.vb-heat th.num{text-align:right;font-variant-numeric:tabular-nums}
/* Pivot / crosstab (Tableau text table) */
.vb-pivot-cap{font-size:11.5px;color:var(--muted);padding:4px 2px 8px}
.vb-pivot{border-collapse:collapse;font-size:11.5px}
.vb-pivot th,.vb-pivot td{border:1px solid var(--line);padding:5px 10px;white-space:nowrap}
.vb-pivot thead th{position:sticky;top:0;background:var(--panel,#121826);color:var(--muted);font-weight:600;z-index:2;text-align:right}
.vb-pivot th.vbpv-rh{text-align:left;color:var(--ink);font-weight:600;position:sticky;left:0;background:var(--panel,#121826);z-index:1}
.vb-pivot thead th.vbpv-rh{z-index:3}
.vb-pivot td.num{text-align:right;font-variant-numeric:tabular-nums;color:var(--ink)}
.vb-pivot thead th.vbpv-grp{text-align:center;color:var(--ink);font-weight:600;background:rgba(255,255,255,.03)}
.vb-pivot .vbpv-tot{font-weight:800;background:rgba(109,94,252,.10);color:var(--ink)}
.vb-pivot thead th.vbpv-tot{text-align:center}
.vb-pivot tfoot .vbpv-tot{border-top:2px solid var(--accent)}
.vb-pivot .vbpv-grand{background:rgba(109,94,252,.18)}
.vb-pivot-k{color:var(--muted);font-size:11.5px}
.vb-pivot-k select{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:2px 5px;font-size:11.5px;margin-left:4px}
.vb-pivot-heatlab{cursor:pointer}
.vb-pivot-heatlab input{vertical-align:-1px;margin-right:4px;accent-color:var(--accent)}
/* KPI scorecard — grid of KPI tiles */
.vb-score{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:12px;padding:2px}
.vb-sc-tile{border:1px solid var(--line);border-left:3px solid var(--muted);background:var(--input,rgba(255,255,255,.03));
  border-radius:12px;padding:14px 15px}
.vb-sc-tile.up{border-left-color:#3ddc97}
.vb-sc-tile.amber{border-left-color:#f59f00}
.vb-sc-tile.down{border-left-color:#e5646a}
.vb-sc-spark{width:100%;height:24px;margin-top:8px;display:block;opacity:.9}
.vb-sc-foot{display:flex;justify-content:space-between;align-items:baseline;gap:8px;margin-top:9px;flex-wrap:wrap}
.vb-sc-tgt-lbl{font-size:11px;font-weight:700}
.vb-sc-tgt-lbl.up{color:#3ddc97}.vb-sc-tgt-lbl.amber{color:#f59f00}.vb-sc-tgt-lbl.down{color:#e5646a}
.vb-sc-tgtrow{margin-top:8px;font-size:11px;color:var(--muted);display:flex;align-items:center;gap:6px}
.vb-sc-tgt{flex:1;min-width:0;background:var(--panel,#0e1526);color:var(--ink);border:1px solid var(--line);border-radius:6px;padding:3px 7px;font-size:11.5px}
.vb-sc-lab{font-size:12px;color:var(--muted);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vb-sc-val{font-size:26px;font-weight:800;color:var(--ink);line-height:1.1;margin-top:4px;font-variant-numeric:tabular-nums}
.vb-sc-sub{font-size:11px;color:var(--muted);margin-top:1px}
.vb-sc-track{height:6px;background:rgba(255,255,255,.06);border-radius:4px;margin-top:11px;overflow:hidden}
.vb-sc-bar{height:100%;background:var(--accent);border-radius:4px}
.vb-sc-chg{font-size:12px;font-weight:700;color:var(--muted)}
.vb-sc-chg.up{color:#3ddc97}.vb-sc-chg.down{color:#e5646a}.vb-sc-chg.new{color:#5aa9e6}.vb-sc-chg.flat{color:var(--muted)}
.vb-tm{position:relative;width:100%;height:100%;min-height:320px}
.vb-tm-cell{position:absolute;border-radius:4px;overflow:hidden;padding:5px 7px;box-sizing:border-box;color:#fff;
  display:flex;flex-direction:column;gap:2px;box-shadow:inset 0 0 0 1px rgba(0,0,0,.18);cursor:default}
.vb-tm-l{font-size:11px;font-weight:700;line-height:1.15;text-shadow:0 1px 2px rgba(0,0,0,.4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.vb-tm-v{font-size:10.5px;font-weight:600;opacity:.95;text-shadow:0 1px 2px rgba(0,0,0,.4)}
.vb-live{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--accent-2,#8b7bff)}
.vb-icon-btn.vb-armready{background:var(--accent-2,#6d5efc);color:#fff;border-color:var(--accent-2,#6d5efc);
  box-shadow:0 0 0 0 rgba(109,94,252,.6);animation:vbarm 1.6s ease-out infinite}
@keyframes vbarm{0%{box-shadow:0 0 0 0 rgba(109,94,252,.55)}70%{box-shadow:0 0 0 8px rgba(109,94,252,0)}100%{box-shadow:0 0 0 0 rgba(109,94,252,0)}}
.vb-live-dot{width:7px;height:7px;border-radius:50%;background:currentColor;animation:vblive 1s ease-in-out infinite}
@keyframes vblive{0%,100%{opacity:.3}50%{opacity:1}}
.vb-icon-btn{width:32px;height:30px;border:1px solid var(--line);background:var(--input);color:var(--muted);border-radius:8px;cursor:pointer;font-size:15px}
.vb-icon-btn:hover{border-color:var(--accent);color:var(--accent)}
.vb-result{flex:1;min-height:0;display:flex;flex-direction:column;gap:8px;overflow:hidden;border:1px solid var(--line);border-radius:11px;padding:12px}
.vb-chart-wrap{flex:1;min-height:300px;position:relative}
#vb-chart-cv{max-height:none;width:100%!important;height:100%!important}
/* Tableau Pulse-style contributor list: label · proportional bar · value. */
.vb-pulse{position:absolute;inset:0;overflow:auto;padding:2px 6px 6px}
/* Pulse card headline: big figure + change, over the contributor list. */
.vbp-kpi{display:flex;justify-content:space-between;align-items:flex-end;gap:14px;
  padding:6px 2px 12px;margin-bottom:8px;border-bottom:1px solid var(--line)}
.vbp-kpi-l{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
.vbp-kpi-val{font-size:34px;font-weight:800;color:var(--ink);line-height:1;font-variant-numeric:tabular-nums}
.vbp-kpi-chg{font-size:13px;font-weight:700;color:var(--muted)}
.vbp-kpi-chg.up{color:#3ddc97}.vbp-kpi-chg.down{color:#e5646a}
.vbp-kpi-cap{font-size:11px;color:var(--muted);text-align:right;line-height:1.5}
.vbp-cap{font-size:11.5px;color:var(--muted);padding:2px 2px 5px}
.vbp-head{display:grid;grid-template-columns:minmax(90px,200px) 1fr auto;gap:12px;align-items:center;
  position:sticky;top:0;background:var(--panel,#0e1526);padding:4px 2px 6px;margin-bottom:2px;
  font-size:11px;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:var(--muted)}
.vbp-head span:first-child{text-align:right}
.vbp-head span:last-child{text-align:right}
.vbp-row{display:grid;grid-template-columns:minmax(90px,200px) 1fr auto;gap:12px;align-items:center;padding:3px 2px;border-radius:6px}
.vbp-row:hover{background:rgba(255,255,255,.03)}
.vbp-row.vbp-click{cursor:pointer}
.vbp-row.vbp-click:hover .vbp-bar{filter:brightness(1.14)}
.vbp-lbl{text-align:right;color:var(--ink);font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.vbp-track{height:22px;background:rgba(255,255,255,.05);border-radius:5px;position:relative;overflow:hidden}
.vbp-bar{height:100%;background:var(--accent);border-radius:5px;min-width:2px;transition:width .3s ease}
.vbp-row:hover .vbp-bar{filter:brightness(1.14)}
.vbp-val{color:var(--ink);font-weight:600;font-size:12.5px;font-variant-numeric:tabular-nums;min-width:64px;text-align:right}
/* change vs prior period (Pulse-style) */
.vbp-head,.vbp-row{grid-template-columns:minmax(90px,200px) 1fr auto}
.vb-pulse.vbp-haschg .vbp-head,.vb-pulse.vbp-haschg .vbp-row{grid-template-columns:minmax(90px,200px) 1fr auto auto}
.vbp-head span:nth-child(3),.vbp-head span:nth-child(4){text-align:right}
.vbp-chg{font-size:11.5px;font-weight:600;min-width:74px;text-align:right;font-variant-numeric:tabular-nums;color:var(--muted)}
.vbp-chg.up{color:#3ddc97}.vbp-chg.down{color:#e5646a}.vbp-chg.new{color:#5aa9e6}.vbp-chg.flat{color:var(--muted)}
.vb-kpi{display:flex;flex-wrap:wrap;gap:14px;align-items:center;justify-content:center;height:100%}
.vb-kpi-card{background:var(--input);border:1px solid var(--line);border-radius:14px;padding:20px 28px;text-align:center;min-width:150px}
.vb-kpi-val{font-size:38px;font-weight:800;color:var(--ink);line-height:1.1}
.vb-kpi-lab{font-size:12.5px;color:var(--muted);margin-top:6px}
.vb-tabledet{flex:0 0 auto;max-height:34%;overflow:auto}
.vb-tabledet>summary{cursor:pointer;font-size:12px;color:var(--muted);padding:4px 0;user-select:none;list-style:none}
.vb-tabledet>summary:hover{color:var(--ink)}
.vb-tabledet>summary::before{content:'\25B8 ';font-size:10px}
.vb-tabledet[open]>summary::before{content:'\25BE '}
.vb-busy{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;gap:10px;background:rgba(10,14,26,.5);color:var(--muted);font-size:13px;z-index:5;border-radius:8px}
/* A display:flex/… rule beats the [hidden] attribute's UA display:none, so these
   overlays must re-assert none when hidden or they never turn off. */
.vb-busy[hidden],.vb-kpi[hidden],.vb-live[hidden]{display:none!important}
.vb-spin{width:16px;height:16px;border:2px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:vbspin .7s linear infinite}
@keyframes vbspin{to{transform:rotate(360deg)}}
.vb-fsec .vb-disc{margin-left:auto;border:none;background:none;color:var(--muted);cursor:pointer;font-size:11px;opacity:.6}
.vb-fsec .vb-disc:hover{color:#ff7b72;opacity:1}
.vb-shelf-opts{gap:16px;flex-wrap:wrap}
.vb-shelf-opts label{font-size:12px;color:var(--muted);display:flex;align-items:center;gap:6px}
.vb-shelf-opts select,.vb-shelf-opts input{background:var(--input);color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:6px 8px;font-size:12.5px}
.vb-shelf-opts input{width:70px}
.vb-run{background:var(--accent);color:#fff;border:none;border-radius:9px;padding:8px 22px;font-size:13px;font-weight:600;cursor:pointer}
.vb-run:hover{background:var(--accent-d,#584fd6)}.vb-run:disabled{opacity:.6}
.vb-save{margin-left:auto;background:transparent;color:var(--accent);border:1px solid var(--accent);border-radius:9px;padding:8px 14px;font-size:12.5px;font-weight:600;cursor:pointer}
.vb-save:hover{background:rgba(109,94,252,.12)}.vb-save:disabled{opacity:.6}
.vb-err{color:#ff7b72;font-size:12.5px;min-height:16px;margin-bottom:4px}
.vb-err.ok{color:#3ddc97}
.vb-result{flex:1;min-height:0;display:flex;flex-direction:column;gap:10px;overflow:auto;border:1px solid var(--line);border-radius:11px;padding:12px}
#vb-chart-cv{max-height:320px}
.vb-table{overflow:auto}
.vb-table table{width:100%;border-collapse:collapse;font-size:12.5px}
.vb-table th{text-align:left;color:var(--muted);font-weight:600;border-bottom:1px solid var(--line);padding:6px 10px;position:sticky;top:0;background:var(--bg)}
.vb-table td{padding:5px 10px;border-bottom:1px solid rgba(255,255,255,.04)}
.vb-table td.num{text-align:right;font-variant-numeric:tabular-nums}

/* ---- Metric card: favourite, overflow menu, muted flags ---- */
.pulse-fav,.pulse-more{background:none;border:none;color:var(--muted);cursor:pointer;
  font-size:14px;padding:0 3px;line-height:1}
.pulse-fav.on{color:#f5c451}
.pulse-fav:hover,.pulse-more:hover{color:var(--accent)}
.pulse-more{font-size:17px;letter-spacing:1px}
.pulse-flags{display:flex;gap:6px;flex-wrap:wrap;margin:2px 0 6px}
.pulse-flag{font-size:10.5px;color:var(--muted);background:rgba(255,255,255,.05);
  border:1px solid var(--line);border-radius:20px;padding:1px 8px}
.card-menu{position:fixed;z-index:1100;min-width:230px;padding:5px;
  background:var(--bg-soft,#0f1524);border:1px solid var(--line,#232c44);
  border-radius:10px;box-shadow:0 14px 40px rgba(0,0,0,.55)}
.card-menu-item{display:block;width:100%;text-align:left;background:none;border:none;
  color:var(--ink);font-size:13.5px;padding:8px 12px;border-radius:7px;cursor:pointer}
.card-menu-item:hover{background:#182036}
.card-menu-item.danger{color:#ff9ea0}
.card-menu-item.danger:hover{background:var(--danger-soft,#2a1520)}
.card-menu-sep{height:1px;background:var(--line,#232c44);margin:5px 4px}

/* ---- Expected range and followers ---- */
.pulse-expected{font-size:11px;color:var(--muted);margin:4px 0 2px}
.pulse-expected.out{color:#e9c877}
.pulse-followers{font-size:10.5px;color:var(--muted);margin-top:2px}
.pulse-source{font-size:10.5px;font-weight:600;color:var(--accent-2,#8b7bff);margin-top:6px;letter-spacing:.02em}
.md-insight-line{display:flex;gap:9px;align-items:flex-start;font-size:14px;
  line-height:1.55;background:rgba(255,255,255,.03);border:1px solid var(--line);
  border-radius:10px;padding:11px 14px;margin-bottom:14px}
.md-insight-line.out{border-color:#5a4d22;background:rgba(233,200,119,.07)}
.md-insight-icon{flex:0 0 auto}
.md-hist{margin-top:16px}
.md-hist-title{font-size:12px;color:var(--muted);margin-bottom:6px}
.md-trend-box{display:flex;align-items:flex-start;gap:9px;margin-top:10px;padding:11px 14px;
  background:rgba(255,255,255,.03);border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:10px;font-size:13.5px;line-height:1.55;color:var(--ink)}
.md-trend-icon{flex:0 0 auto;font-size:16px;display:flex;align-items:center}
.md-trend-icon.up{color:#3ec97d}
.md-trend-icon.dn{color:#e05c5c}
.md-trend-text{flex:1}
.md-trend-chip{background:rgba(99,102,241,.08);border-color:var(--accent)!important;color:var(--accent)!important}

/* ---- Metric groups ---- */
.pulse-groups{display:flex;flex-direction:column;gap:18px}
.pulse-group-head{display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  background:none;border:none;color:var(--label);font-size:13px;font-weight:700;
  letter-spacing:.3px;padding:4px 2px 8px;cursor:pointer}
.pulse-group-head:hover{color:var(--ink)}
.pulse-group-caret{color:var(--muted);font-size:11px;width:10px}
.pulse-group-count{background:rgba(255,255,255,.06);border:1px solid var(--line);
  border-radius:20px;font-size:10.5px;font-weight:600;color:var(--muted);padding:1px 8px}

/* ===================== COMPARISON DASHBOARD ===================== */
.cmp-body{display:flex;gap:14px;align-items:flex-start}
.cmp-rail{flex:0 0 190px;display:flex;flex-direction:column;gap:12px;
  background:var(--bg-soft);border:1px solid var(--line);border-radius:12px;padding:12px}
.cmp-field{display:flex;flex-direction:column;gap:5px;font-size:11.5px;
  font-weight:700;color:var(--label);letter-spacing:.2px}
.cmp-field select{font-weight:400;font-size:13px}
.cmp-run{margin-top:2px}
.cmp-panels{flex:1;min-width:0;display:flex;flex-direction:column;gap:16px}
.cmp-panel{border:1px solid var(--line);border-radius:12px;background:var(--bg-soft);
  padding:12px 14px 8px}
.cmp-head{font-size:14px;margin-bottom:10px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.cmp-title{color:#e8615a;font-weight:700}
.cmp-meta{color:var(--muted);font-size:12.5px}
.cmp-warn{color:#e9c877;font-size:11.5px}
.cmp-series{display:flex;gap:10px;align-items:stretch;margin-bottom:14px}
.cmp-ylabel{flex:0 0 16px;writing-mode:vertical-rl;transform:rotate(180deg);
  text-align:center;font-size:11px;color:var(--muted);align-self:center}
.cmp-plot{flex:1;min-width:0}
.cmp-qrow{display:grid;grid-template-columns:repeat(4,1fr);gap:3px;margin-bottom:3px}
.cmp-q{text-align:center;font-size:11.5px;font-weight:700;color:#fff;border-radius:4px;
  padding:2px 0;background:var(--q);opacity:.85}
.cmp-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:3px}
.cmp-month{display:flex;flex-direction:column;min-width:0}
.cmp-bars{height:140px;display:flex;align-items:flex-end;justify-content:center;gap:3px;
  background:rgba(255,255,255,.02);border-radius:4px 4px 0 0;padding:0 2px}
.cmp-bar-stack{flex:1;min-width:0;height:100%;display:flex;flex-direction:column;
  justify-content:flex-end;align-items:center}
.cmp-val{font-size:8.5px;color:var(--muted);white-space:nowrap;margin-bottom:2px}
.cmp-bar{width:100%;border-radius:2px 2px 0 0;transition:height .25s ease}
.cmp-year{font-size:8.5px;color:var(--muted);margin-top:2px}
.cmp-mlabel{text-align:center;font-size:11px;font-weight:600;padding-top:3px;
  border-top:1px solid var(--line)}
.cmp-empty{color:var(--muted);font-size:12.5px;padding:14px 0}
@media(max-width:900px){
  .cmp-body{flex-direction:column}
  .cmp-rail{flex:1 1 auto;width:100%;flex-direction:row;flex-wrap:wrap}
  .cmp-field{flex:1 1 160px}
  .cmp-val,.cmp-year{display:none}
}
.cmp-check{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--label);
  cursor:pointer;padding:2px 0}
.cmp-check input{width:15px;height:15px;accent-color:var(--accent);margin:0;cursor:pointer}

/* ---- Connections (admin) ---- */
.conn-badge{background:var(--input);border:1px solid var(--line-2);color:var(--label);
  border-radius:8px;padding:6px 11px;font-size:12.5px;font-weight:600;cursor:pointer;
  white-space:nowrap;max-width:220px;overflow:hidden;text-overflow:ellipsis}
.conn-badge:hover{border-color:var(--accent);color:var(--ink)}
.conn-badge.multi{border-color:var(--accent);color:var(--accent-2)}
.modal-wide{width:min(720px,100%)}
.conn-list{display:flex;flex-direction:column;gap:8px;margin-bottom:12px}
.conn-row{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:10px;
  border:1px solid var(--line);background:rgba(255,255,255,.02)}
.conn-row.active{border-color:var(--accent);background:var(--glow)}
.conn-row.flash{animation:conn-flash 1.2s ease}
@keyframes conn-flash{0%{background:var(--glow-strong)}100%{background:rgba(255,255,255,.02)}}
.conn-main{flex:1;min-width:0}
.conn-name{font-size:14px;font-weight:650;display:flex;align-items:center;gap:8px}
.conn-sub{font-size:11.5px;color:var(--muted);margin-top:2px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.conn-tag{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;
  background:var(--accent);color:#fff;border-radius:20px;padding:1px 8px}
.conn-tag.warn{background:#e9c877;color:#2a2413}
.conn-acts{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.conn-btn{background:transparent;border:1px solid var(--line-2);color:var(--ink);
  border-radius:7px;padding:5px 11px;font-size:12.5px;cursor:pointer}
.conn-btn:hover{border-color:var(--accent);color:var(--accent)}
.conn-btn.danger{color:#ff9ea0;border-color:#5a2530}
.conn-btn.danger:hover{background:var(--danger-soft)}
.conn-btn:disabled{opacity:.6;cursor:wait}
/* Compact icon variant (e.g. "attach Excel repository" on a client card). */
.conn-btn.conn-icon{padding:5px 9px;font-size:14px;line-height:1}
.conn-group{margin-top:6px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.conn-link-mini{background:none;border:0;padding:0;font-size:11.5px;color:var(--muted);
  cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.conn-link-mini:hover{color:var(--accent)}
.conn-group-pick{max-width:220px;font-size:12px;padding:4px 8px;border-radius:7px;
  border:1px solid var(--line-2);background:rgba(255,255,255,.03);color:var(--ink)}
/* Clickable table names from an Excel repository's load result — each opens the
   metric editor pre-pointed at that table. */
.excel-tbl-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
.excel-tbl-chip{background:rgba(56,189,248,.12);border:1px solid var(--line-2);
  color:var(--accent);border-radius:20px;padding:3px 11px;font-size:12px;cursor:pointer;
  font-family:ui-monospace,Consolas,monospace}
.excel-tbl-chip:hover{border-color:var(--accent);background:rgba(56,189,248,.2)}
/* A client that owns several databases: the primary row is the card header,
   the rest nest beneath a connector so the group reads as one client. */
.conn-card{border:1px solid var(--line);border-radius:10px;background:rgba(255,255,255,.02);
  padding:6px;display:flex;flex-direction:column;gap:8px}
.conn-card > .conn-row{background:transparent;border:0;padding:8px 8px}
.conn-card > .conn-row.active{background:var(--glow);border-radius:8px}
.conn-nest{display:flex;flex-direction:column;gap:8px;margin:0 4px 2px 34px;
  padding-left:16px;border-left:2px solid var(--line-2)}
.conn-row.nested{padding:8px 10px;background:rgba(255,255,255,.02)}
.conn-row.nested .conn-name{font-size:13px;font-weight:600}
.conn-row.nested .conn-mini-logo{width:24px;height:24px}
.conn-two{display:flex;gap:12px}
.conn-two > *{flex:1;min-width:0}
.conn-editor{border:1px solid var(--accent);border-radius:10px;padding:14px;
  background:rgba(255,255,255,.02)}
.conn-pool{font-size:11.5px;color:var(--muted);font-family:ui-monospace,Consolas,monospace;
  padding:3px 0}
.conn-pool.warn{color:#e9c877}

/* ---- Per-client branding ---- */
.conn-mini-logo{width:30px;height:30px;object-fit:contain;border-radius:6px;
  background:rgba(255,255,255,.06);flex:0 0 auto}
.conn-logo{display:flex;align-items:center;gap:12px}
.conn-logo-prev{width:56px;height:40px;object-fit:contain;border-radius:8px;
  background:rgba(255,255,255,.06);border:1px solid var(--line);flex:0 0 auto}
.conn-logo-acts{display:flex;align-items:center;gap:8px;flex-wrap:wrap;flex:1;min-width:0}
.conn-logo-acts input[type=file]{font-size:11.5px;max-width:190px;color:var(--muted)}

/* ---- Metric access control ---- */
.acl-group{margin-bottom:14px}
.acl-title{font-size:11px;font-weight:700;letter-spacing:.4px;text-transform:uppercase;
  color:var(--muted);margin-bottom:6px}
.acl-row{display:flex;align-items:center;gap:9px;padding:4px 2px;font-size:13.5px;cursor:pointer}
.acl-row:hover{color:#fff}
.acl-row input{width:15px;height:15px;accent-color:var(--accent);margin:0;cursor:pointer}
.pulse-flag.restricted{border-color:#5a4d22;color:#e9c877}

/* ---- Client assignment list ---- */
.assign-list{display:flex;flex-direction:column;gap:6px;margin:10px 0}
.assign-row{display:flex;align-items:center;gap:12px;padding:8px 10px;border-radius:9px;
  border:1px solid var(--line);background:rgba(255,255,255,.02)}
.assign-who{flex:1;min-width:0}
.assign-name{font-size:13.5px;font-weight:600;display:flex;align-items:center;gap:8px}
.assign-sub{font-size:11px;color:var(--muted);margin-top:1px}
.assign-row select{flex:0 0 190px;background:#0e131d;color:inherit;
  border:1px solid var(--line);border-radius:8px;padding:6px 9px;font-size:12.5px}
.assign-row select:disabled{opacity:.5;cursor:not-allowed}


/* Client picker: only present when someone serves more than one client, so it
   has to read as part of the brand row rather than as another control. */
.client-switch {
  margin-left: .6rem;
  padding: .18rem .5rem;
  border-radius: 6px;
  border: 1px solid var(--line-2);
  background: var(--input);
  color: var(--ink);
  font-size: .84rem;
  max-width: 12rem;
}
.client-switch:disabled { opacity: .6; }

/* Client ticks in the assignment list: several may apply to one person, so
   they wrap rather than forcing the row wider. */
.assign-picks {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem .7rem;
  justify-content: flex-end;
  max-width: 22rem;
}
.assign-pick {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  font-size: .84rem;
  white-space: nowrap;
}
.assign-pick input { accent-color: var(--accent); }


/* ---- Trading summary ---------------------------------------------------- */
/* Tiles first, then a four-panel grid. Everything collapses to one column on
   a narrow screen rather than scrolling sideways. */
.exec-view .exec-body-wrap { padding: .2rem .1rem 1rem; }

.exec-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: .6rem;
  margin-bottom: .9rem;
}
.exec-tile {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .6rem .75rem;
  border-radius: 10px;
  border: 1px solid var(--line-2);
  background: var(--input);
  /* Stated, not inherited: this element is a <button> whenever the tile
     switches the measure, and a button takes its colour from the user agent
     rather than from its parent. */
  color: var(--ink);
  appearance: none;
  -webkit-appearance: none;
}
.exec-ic {
  font-size: 1.2rem;
  width: 2.1rem; height: 2.1rem;
  display: grid; place-items: center;
  border-radius: 8px;
  background: var(--glow);
  flex: 0 0 auto;
}
.exec-body { min-width: 0; }
.exec-lab {
  font-size: .74rem;
  color: var(--label);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.exec-val { font-size: 1.15rem; font-weight: 650; line-height: 1.25;
            color: var(--ink); }
.exec-chg { font-size: .74rem; font-weight: 600; }
.exec-chg.up { color: #3fb950; }
.exec-chg.down { color: var(--danger); }
.exec-note { font-size: .7rem; color: var(--label); }

.exec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: .7rem;
}
.exec-panel {
  border: 1px solid var(--line-2);
  border-radius: 10px;
  background: var(--input);
  padding: .6rem .7rem .7rem;
  min-width: 0;
}
.exec-ph {
  display: flex; align-items: baseline; gap: .5rem;
  margin-bottom: .4rem; flex-wrap: wrap;
}
.exec-ptitle { font-size: .86rem; font-weight: 600; }
.exec-pcap { font-size: .72rem; color: var(--label); }
/* A fixed height, not a minimum. Chart.js with maintainAspectRatio:false
   sizes the canvas to this box; if the box only had a minimum it would grow to
   fit the canvas, which resized the canvas again — the chart crept taller on
   every mouse move. */
.exec-plot { position: relative; height: 220px; }
.exec-plot.tall { height: 260px; }
.exec-plot > canvas { display: block; }
.exec-dim {
  padding: .2rem .45rem;
  border-radius: 6px;
  border: 1px solid var(--line-2);
  background: var(--input);
  color: var(--ink);
  font-size: .8rem;
}

@media (max-width: 720px) {
  .exec-grid { grid-template-columns: 1fr; }
}

/* Drill breadcrumb: the trail is the control, so each step has to look like
   something you can press. */
.exec-crumbs {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: .3rem; margin: .1rem 0 .6rem;
}
.exec-crumb {
  border: 1px solid var(--line-2);
  background: var(--input);
  color: var(--ink);
  border-radius: 999px;
  padding: .16rem .6rem;
  font-size: .78rem;
  cursor: pointer;
  max-width: 16rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.exec-crumb:hover:not(:disabled) { border-color: var(--accent); }
.exec-crumb.here, .exec-crumb:disabled {
  cursor: default;
  background: var(--glow);
  border-color: transparent;
}
.exec-crumb-sep { color: var(--label); font-size: .75rem; }
.exec-crumb-dim { color: var(--label); font-size: .76rem; }

/* A tile that changes what the screen is about has to look pressable, and the
   one currently driving it has to be obvious. */
.exec-tile.pick { cursor: pointer; text-align: left; font: inherit;
                  color: inherit; width: 100%; }
.exec-tile.pick:hover { border-color: var(--accent); }
.exec-tile.active {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.exec-unfocus {
  margin-left: .5rem;
  border: 1px solid var(--line-2);
  background: var(--glow);
  color: var(--ink);
  border-radius: 999px;
  padding: .05rem .5rem;
  font-size: .72rem;
  cursor: pointer;
}
.exec-unfocus:hover { border-color: var(--accent); }

/* Why the screen is showing something other than what was asked for. Quiet,
   but not so quiet it can be missed: an unexplained fall back to a month
   reads as an answer to the question that was actually put. */
.exec-note { color: var(--label); font-style: italic; }

/* Chart keys. Small, quiet, and always under the thing they explain. */
.exec-legend {
  display: flex; flex-wrap: wrap;
  gap: .25rem .9rem;
  margin-top: .35rem;
  font-size: .72rem;
  color: var(--label);
}
.exec-key { display: inline-flex; align-items: center; gap: .32rem; }
.exec-sw {
  width: .7rem; height: .7rem;
  border-radius: 2px;
  display: inline-block;
  flex: 0 0 auto;
}
.exec-sw.line { height: .2rem; border-radius: 1px; }


/* ---- Sales pulse -------------------------------------------------------- */
/* Three columns: the cascade on the left, the daily shape and ratios in the
   middle, the movers on the right. One column on a narrow screen. */
/* Fill the viewport rather than floating in the top-left of it: the three
   columns share the height, and each one distributes its own contents. */
.pulse-body {
  display: grid;
  grid-template-columns: minmax(210px, .8fr) minmax(320px, 1.75fr) minmax(230px, 1fr);
  gap: .7rem;
  align-items: stretch;
  padding-bottom: .8rem;
  min-height: calc(100vh - 210px);
}
.pulse-rail { justify-content: flex-start; }
/* The cascade grows to take up whatever the hero leaves, so the left column
   reaches the bottom instead of stopping halfway. */
.pulse-rail > .pulse-stage { flex: 1 1 auto; min-height: 3.1rem; align-content: center; }
.pulse-main { height: 100%; }
.pulse-bars { display: flex; flex-direction: column; }
/* Deliberately a fixed height, not a flexible one. A canvas whose height is
   resolved by the layout can feed back into the layout, and this file has
   made that mistake enough times already. */
.pulse-bars > .pulse-barplot { height: 250px; }
.pulse-rings { flex: 0 0 auto; }
.pulse-movers {
  overflow-y: auto;
  max-height: calc(100vh - 210px);
  padding-right: .2rem;
}
.pulse-rail { display: flex; flex-direction: column; gap: .35rem; min-width: 0; }

.pulse-hero {
  border-radius: 10px;
  padding: .9rem .9rem 1rem;
  background: linear-gradient(160deg, #17a398 0%, #0f7f86 100%);
  color: #f2fbfa;
}
.pulse-hero-lab { font-size: .8rem; opacity: .92; }
.pulse-hero-val { font-size: 2.1rem; font-weight: 700; line-height: 1.15; margin: .25rem 0 .35rem; }
.pulse-hero-cap { font-size: .74rem; opacity: .88; line-height: 1.35; }

.pulse-stage {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: .1rem .5rem;
  align-items: baseline;
  border: 0;
  border-radius: 8px;
  padding: .55rem .7rem;
  color: #f2fbfa;
  text-align: left;
  font: inherit;
  width: 100%;
  cursor: default;
}
button.pulse-stage { cursor: pointer; }
button.pulse-stage:hover { outline: 2px solid var(--accent); outline-offset: -2px; }
.pulse-stage-name { font-size: .88rem; font-weight: 600; overflow: hidden;
                    text-overflow: ellipsis; white-space: nowrap; }
.pulse-stage-val { font-size: 1rem; font-weight: 700; }
.pulse-stage-sub { grid-column: 1 / -1; font-size: .68rem; opacity: .85; }

.pulse-main { display: flex; flex-direction: column; gap: .7rem; min-width: 0; }
.pulse-barplot { height: 190px; }
.pulse-rings { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.pulse-ringplot { height: 165px; }

.pulse-movers { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
.pulse-mover {
  border: 1px solid var(--line-2);
  border-radius: 10px;
  background: var(--input);
  color: var(--ink);
  padding: .55rem .7rem .3rem;
  text-align: left;
  font: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}
.pulse-mover:hover { border-color: var(--accent); }
.pulse-mover-top { display: flex; justify-content: space-between; gap: .5rem; }
.pulse-mover-who { min-width: 0; }
.pulse-mover-name { font-size: .92rem; font-weight: 600; overflow: hidden;
                    text-overflow: ellipsis; white-space: nowrap; }
.pulse-mover-role { font-size: .7rem; color: var(--label); }
.pulse-mover-fig { text-align: right; flex: 0 0 auto; }
.pulse-mover-pct { font-size: 1rem; font-weight: 700; }
.pulse-mover-pct.up { color: #3fb950; }
.pulse-mover-pct.down { color: var(--danger); }
.pulse-mover-cap { font-size: .58rem; letter-spacing: .06em; color: var(--label); }
/* A sized box for the sparkline. The canvas fills it; without a height here
   the chart grows to fit the button and the button grows to fit the chart. */
.pulse-sparkbox { position: relative; height: 38px; margin-top: .3rem; }
.pulse-sparkbox > canvas { display: block; }

@media (max-width: 1100px) {
  .pulse-body { grid-template-columns: 1fr 1fr; }
  .pulse-movers { grid-column: 1 / -1; }
}
@media (max-width: 720px) {
  .pulse-body { grid-template-columns: 1fr; }
  .pulse-rings { grid-template-columns: 1fr; }
}


/* ---- Sales performance (KPI) -------------------------------------------- */
.kpi-body { display: flex; flex-direction: column; gap: .7rem; padding-bottom: 1rem; }
.kpi-charts {
  display: grid;
  grid-template-columns: 1.5fr 1.1fr 1.2fr;
  gap: .7rem;
}
/* Definite heights: a canvas sized by the layout can resize the layout. */
.kpi-lineplot { height: 230px; }
.kpi-donutplot { height: 230px; }
.kpi-barplot { height: 230px; }

.kpi-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: .7rem;
}
.kpi-tile {
  border: 1px solid var(--line-2);
  border-radius: 10px;
  background: var(--input);
  color: var(--ink);
  padding: .8rem .9rem .6rem;
  text-align: center;
  font: inherit;
  appearance: none;
  -webkit-appearance: none;
}
.kpi-tile.pick { cursor: pointer; }
.kpi-tile.pick:hover { border-color: var(--accent); }
.kpi-lab { font-size: .82rem; color: var(--label); }
.kpi-val { font-size: 1.75rem; font-weight: 700; margin: .35rem 0 .5rem;
           line-height: 1.15; }
.kpi-foot {
  display: flex; justify-content: center; gap: 1.2rem;
  border-top: 1px solid var(--line); padding-top: .45rem;
}
.kpi-prev-lab { font-size: .66rem; color: var(--label); }
.kpi-prev-val { font-size: .84rem; font-weight: 600; }
.kpi-chg-val { font-size: .84rem; font-weight: 700; }
.kpi-chg.good .kpi-chg-val { color: #3fb950; }
.kpi-chg.bad .kpi-chg-val { color: var(--danger); }
.kpi-chg.flat .kpi-chg-val { color: var(--label); }
.kpi-note { font-size: .62rem; color: var(--label); margin-top: .35rem; }
/* The subject of the figure: which brand, which day. */
.kpi-sub {
  font-size: .72rem; color: var(--label); margin: -.3rem 0 .45rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

@media (max-width: 1000px) {
  .kpi-charts { grid-template-columns: 1fr; }
}


/* ---- Switching between the analytical views ------------------------------ */
.db-viewnav {
  display: flex;
  gap: .2rem;
  padding: .15rem;
  border: 1px solid var(--line-2);
  border-radius: 9px;
  background: var(--bg-soft);
  flex: 0 0 auto;
}
.db-viewbtn {
  width: 1.9rem; height: 1.9rem;
  display: grid; place-items: center;
  border: 0; border-radius: 7px;
  background: transparent;
  color: var(--label);
  cursor: pointer;
  appearance: none; -webkit-appearance: none;
  padding: 0;
}
.db-viewbtn svg { width: 1.05rem; height: 1.05rem; }
.db-viewbtn:hover:not(:disabled) { background: var(--input); color: var(--ink); }
/* Where you are: filled, in the accent, and not clickable. */
.db-viewbtn.on {
  background: var(--accent);
  color: #fff;
  cursor: default;
}
@media (max-width: 700px) {
  .db-viewnav { display: none; }
}


/* ---- One KPI, split every way ------------------------------------------- */
.kpi-drill {
  border: 1px solid var(--accent);
  border-radius: 10px;
  background: var(--input);
  padding: .7rem .8rem .8rem;
  margin-top: .2rem;
}
.kpi-drill-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; margin-bottom: .2rem;
}
.kpi-drill-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: .7rem;
  margin-top: .6rem;
}
.kpi-drill-dim { min-width: 0; }
.kpi-drill-dimhead {
  display: flex; align-items: center; justify-content: space-between;
  gap: .4rem; flex-wrap: wrap;
  font-size: .74rem; font-weight: 600; color: var(--label);
  padding-bottom: .3rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: .3rem;
}
.kpi-drill-count { flex: 1; min-width: 0; }
.kpi-drill-steps { flex-shrink: 0; }
.kpi-drill-rows {
  max-height: 380px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--accent) transparent;
}
.kpi-drill-row {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: .45rem;
  align-items: center;
  width: 100%;
  border: 0; border-radius: 5px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  padding: .22rem .35rem;
  cursor: pointer;
  appearance: none; -webkit-appearance: none;
  overflow: hidden;
}
.kpi-drill-row:hover { outline: 1px solid var(--accent); }
/* The bar sits behind the text rather than beside it, so a long name still
   has the full width to be read in. */
.kpi-drill-fill {
  position: absolute; left: 0; top: 0; bottom: 0;
  background: var(--glow);
  border-radius: 5px;
  pointer-events: none;
}
.kpi-drill-name, .kpi-drill-val, .kpi-drill-chg { position: relative; }
.kpi-drill-name {
  font-size: .78rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kpi-drill-val { font-size: .78rem; font-weight: 600; }
.kpi-drill-chg { font-size: .7rem; min-width: 3.4rem; text-align: right; }
.kpi-drill-chg.up { color: #3fb950; }
.kpi-drill-chg.down { color: var(--danger); }
.kpi-drill-chg.flat { color: var(--label); }


/* ---- Sales board --------------------------------------------------------- */
/* Panels sit side by side and each scrolls on its own, so a long product list
   in one never pushes the others off the screen. */
.board-body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: .7rem;
  align-items: start;
  padding-bottom: 1rem;
}
.board-panel {
  border: 1px solid var(--line-2);
  border-radius: 10px;
  background: var(--input);
  padding: .6rem .7rem .7rem;
  min-width: 0;
}
.board-head { margin-bottom: .4rem; }
.board-title { font-size: .9rem; font-weight: 650; }
.board-src { font-size: .68rem; color: var(--label); }
.board-crumbs { display: flex; flex-wrap: wrap; gap: .25rem; margin: .3rem 0 .4rem; }
.board-scroll { overflow: auto; max-height: 62vh; }
.board-table { width: 100%; border-collapse: collapse; font-size: .76rem; }
.board-table th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg-soft);
  color: var(--label);
  font-weight: 600;
  text-align: right;
  padding: .3rem .4rem;
  white-space: nowrap;
  border-bottom: 1px solid var(--line-2);
}
.board-table th.board-rowhead { text-align: left; }
.board-table td { padding: .22rem .4rem; border-bottom: 1px solid rgba(183,192,214,.07); }
.board-table td.board-rowhead {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--input);
}
.board-table th.board-rowhead {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--bg-soft);
}
.board-rowhead {
  text-align: left; max-width: 15rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board-val { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* A part period is not comparable with a whole one, so it is marked rather
   than left to look like a collapse. */
.board-val.partial { font-style: italic; }
.board-val.partial::after { content: ' \2022'; color: var(--label); }
.board-total { font-weight: 700; border-top: 1px solid var(--line-2); }
.board-table tfoot td { border-bottom: 0; }
.board-drill {
  border: 0; background: transparent; color: var(--ink);
  font: inherit; text-align: left; padding: 0; cursor: pointer;
  text-decoration: underline dotted var(--line-2);
  max-width: 15rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board-drill:hover { color: var(--accent-2); text-decoration-color: var(--accent); }

/* A panel whose own data stops before the shared cut-off. */
.board-warn { font-size: .66rem; color: var(--danger); margin-top: .15rem; }


/* ---- Board cell indicators ---------------------------------------------- */
/* Value and movement on one line: the number right-aligned so columns compare
   at a glance, the change beside it in a fixed width so the arrows line up. */
.board-val {
  background-repeat: no-repeat;
  background-position: left center;
  background-size: 100% 68%;
}
.board-num { font-variant-numeric: tabular-nums; }
.board-delta {
  display: inline-block;
  min-width: 4.6rem;
  margin-left: .5rem;
  text-align: right;
  font-size: .68rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.board-delta.up { color: #3fb950; }
.board-delta.down { color: var(--danger); }
.board-empty { color: var(--label); }
/* The first year has nothing to be compared with, so its cells simply have no
   change shown rather than a zero that would look like standing still. */
.board-total .board-num { font-weight: 700; }


/* ---- Header controls ----------------------------------------------------- */
/* Several views carry three or four pickers. They must not push the heading
   out of shape, and they must not stretch to fill a wide screen either. */
.md-actions .exec-dim {
  flex: 0 1 auto;
  max-width: 11rem;
  min-width: 6.5rem;
}
.md-head .db-viewnav { flex: 0 0 auto; }
/* Below this the switcher is already hidden, so the row is just the heading
   and its controls. */
@media (max-width: 640px) {
  .md-actions { width: 100%; justify-content: flex-start; }
  .md-actions .exec-dim { max-width: none; }
}


/* ---- Narrow screens ------------------------------------------------------ */
/* The board is the widest thing in the app: three panels, each a matrix. Give
   it one panel per row before the panels themselves start to squeeze, and let
   each matrix scroll sideways with its labels pinned. */
@media (max-width: 900px) {
  .board-body { grid-template-columns: 1fr; }
  .board-scroll { max-height: none; }
  .board-panel { min-width: 0; }
}
@media (max-width: 720px) {
  /* A delta beside every value is more than a phone column can hold; stack it
     under the number rather than shrink both to illegibility. */
  .board-delta { display: block; min-width: 0; margin-left: 0; text-align: right; }
  .board-table { font-size: .72rem; }
  .board-rowhead { max-width: 9rem; }
  .exec-grid { grid-template-columns: 1fr; }
  .kpi-drill-grid { grid-template-columns: 1fr; }
  /* Movers already scroll; on a phone let the page do it instead, so there is
     not a scrolling box inside a scrolling page. */
  .pulse-movers { max-height: none; overflow: visible; }
  .board-scroll { max-height: none; }
}
@media (max-width: 520px) {
  .exec-tiles { grid-template-columns: 1fr 1fr; }
  .kpi-tiles { grid-template-columns: 1fr; }
  .kpi-val { font-size: 1.5rem; }
  .exec-plot, .exec-plot.tall { height: 200px; }
  .pulse-barplot { height: 190px; }
}

/* A role per client: name on the left, what they may do on the right. */
.assign-pick { display: flex; align-items: center; gap: .4rem; }
.assign-pick-name {
  font-size: .8rem; color: var(--label);
  max-width: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.assign-role {
  border: 1px solid var(--line-2);
  background: var(--input);
  color: var(--ink);
  border-radius: 6px;
  padding: .12rem .35rem;
  font-size: .76rem;
}
.assign-role:disabled { opacity: .55; }

/* ---- As-at: which moment a figure describes -----------------------------
   Deliberately quiet. It should be findable when someone wonders whether a
   number is current, and invisible the rest of the time — a badge loud enough
   to compete with the figures would be read as a warning on every screen,
   which is exactly how real warnings stop being read. */
.as-at {
  display: inline-block;
  margin-left: .45rem;
  padding: .04rem .38rem;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: var(--input);
  color: var(--muted);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .01em;
  white-space: nowrap;
  vertical-align: middle;
  cursor: help;
}
.as-at-live { color: var(--cyan); border-color: rgba(58, 208, 230, .35); }
/* Two missed rebuilds. This one is meant to be noticed. */
.as-at-stale {
  color: #ffb4b6;
  border-color: #5a2530;
  background: var(--danger-soft);
}
.board-src .as-at { margin-left: .35rem; font-size: .62rem; }
/* The head was a plain block; the download sits at its right edge, so it
   becomes a wrapping row: the title takes a full line to itself, then the
   source line and the button share the next one. */
.board-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .5rem; }
.board-head > .board-title { flex: 1 1 100%; }
.board-head > .board-src { flex: 1 1 auto; min-width: 0; }
.board-head > .board-warn { flex: 1 1 100%; }
.board-head .board-dl {
  margin-left: auto;
  align-self: flex-start;
  flex: 0 0 auto;
  padding: .1rem .3rem;
  font-size: .78rem;
}

@media (max-width: 700px) {
  /* On a narrow screen the subtitle already wraps; let the stamp start its
     own line rather than pushing the sentence around. */
  .md-sub .as-at { margin-left: 0; margin-top: .2rem; }
}

/* ---- Download the summary ----------------------------------------------- */
.xtr-box { max-width: 34rem; }
.xtr-range { display: flex; gap: .5rem; }
.xtr-range input { flex: 1 1 0; min-width: 0; }
.xtr-ticks {
  display: flex; flex-wrap: wrap; gap: .3rem .8rem;
  padding: .45rem .55rem;
  border: 1px solid var(--line, #2a3242);
  border-radius: 8px;
  background: #0e131d;
}
.xtr-tick {
  display: flex; align-items: center; gap: .3rem;
  font-size: .78rem; color: var(--ink); cursor: pointer;
}
/* The size line is the one thing in this dialog people act on, so it holds
   its height whether or not it has something to say — a box that grows and
   shrinks as you tick moves everything under it. */
.xtr-size { min-height: 1.15rem; font-size: .78rem; }
.xtr-size.warn { color: #ffb4b6; }

/* ---- Row-level scope ----------------------------------------------------
   The chip on the landing page is the only place a limited reader learns that
   their figures are a slice. It is not decoration and it does not fade with
   familiarity, so it keeps a border and a colour of its own. */
.scope-chip {
  display: inline-block;
  margin-left: .5rem;
  padding: .08rem .45rem;
  border: 1px solid var(--accent-2);
  border-radius: 999px;
  color: var(--accent-2);
  background: rgba(139, 123, 255, .10);
  font-size: .7rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: help;
}
.assign-scope {
  border: 1px dashed var(--line-2);
  background: transparent;
  color: var(--muted);
  border-radius: 6px;
  padding: .1rem .35rem;
  font-size: .7rem;
  cursor: pointer;
  white-space: nowrap;
}
.assign-scope:hover:not(:disabled) { color: var(--ink); border-color: var(--accent); }
.assign-scope.on {
  border-style: solid;
  border-color: var(--accent-2);
  color: var(--accent-2);
}
.assign-scope:disabled { opacity: .4; cursor: default; }
.scope-values { max-height: 15rem; overflow-y: auto; }

/* ---- Sales Performance: the board-wide slice ---------------------------- */
.kpi-slice {
  display: inline-block;
  margin-left: .5rem;
  padding: .06rem .45rem;
  border: 1px solid var(--accent-2);
  border-radius: 999px;
  color: var(--accent-2);
  background: rgba(139, 123, 255, .10);
  font-size: .7rem;
  font-weight: 600;
  white-space: nowrap;
}
/* Not every table can carry the slice. This says how many could not, and the
   tiles themselves repeat it — a caveat in the header is not attached to the
   number anyone actually quotes. */
.kpi-slice.unreached {
  border-color: #5a2530;
  color: #ffb4b6;
  background: var(--danger-soft);
  cursor: help;
}
.kpi-unreached { color: #ffb4b6; }
.kpi-unfiltered { border-style: dashed; }

/* ---- Sales Pulse: the cascade is nested, and now looks it ---------------
   Each step is measured INSIDE the one above. Read as a flat list of equal
   blocks, a step's value is taken for that member's own total — on this data
   that is a seventeen-fold overstatement waiting to be quoted. */
.pulse-stage {
  position: relative;
  box-sizing: border-box;
  margin-left: var(--indent, 0);
  width: calc(100% - var(--indent, 0px));
  overflow: hidden;
}
.pulse-stage-within {
  grid-column: 1 / -1;
  font-size: .68rem;
  font-style: italic;
  opacity: .9;
}
/* How much of the step above this step is. The number is written beside it;
   this is so it does not have to be read to be seen. */
.pulse-stage-fill {
  position: absolute;
  left: 0; bottom: 0; height: 3px;
  background: rgba(255, 255, 255, .55);
  border-radius: 0 2px 2px 0;
  pointer-events: none;
}
/* Why the troughs are troughs. Sits under the chart rather than in a tooltip:
   the reader who needs it is the one who has already drawn a conclusion. */
.pulse-quiet-note {
  margin: .3rem .1rem 0;
  font-size: .68rem;
  color: var(--label);
  line-height: 1.35;
}

/* ---- Sales Pulse movers: how big, and when ------------------------------
   These cards used to show a percentage and a squiggle. The percentage
   invites a ranking the sizes do not support, and a line drawn against
   1..30 cannot say whether a spike was last week or three weeks ago. */
.pulse-spark-axis {
  position: relative;
  display: flex;
  justify-content: space-between;
  margin-top: .1rem;
  font-size: .62rem;
  color: var(--muted);
  line-height: 1.2;
  min-height: .8rem;
}
/* Positioned under the point it names rather than centred, so the label and
   the marker are read as the same fact. */
.pulse-spark-peak {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  white-space: nowrap;
  color: var(--label);
  font-weight: 600;
}
/* The honest reading behind most extreme percentages. */
.pulse-one-order {
  margin-top: .3rem;
  padding: .18rem .4rem;
  border-radius: 6px;
  background: var(--danger-soft);
  color: #ffb4b6;
  font-size: .64rem;
  line-height: 1.3;
}

/* ---- Sales Performance: the mix picks its own period --------------------
   Two small selects in the panel's own header rather than the view's: they
   change this chart and nothing else, and putting them beside the board's
   other controls would say otherwise. */
.kpi-mixctl { display: flex; gap: .3rem; margin-left: auto; flex: 0 0 auto; }
.kpi-mixctl select {
  padding: .08rem .25rem;
  font-size: .68rem;
  max-width: 8.5rem;
}
.kpi-mixctl select:disabled { opacity: .45; cursor: not-allowed; }
.exec-ph { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }

/* ---- Sales Performance: the mix drills where it stands ------------------
   A donut is a drill control. Clicking a slice used to navigate to another
   screen, which lost both the period and the reader's place. */
.kpi-mixcrumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: .2rem .3rem;
  margin: 0 0 .3rem;
}
/* The denominator, on the same line as the path that sets it. Inside TEA a
   46% brand is 46% of TEA; a reader who takes it for 46% of revenue is out
   by a factor of the parent's own share. */
.kpi-mixdenom {
  margin-left: auto;
  font-size: .66rem;
  color: var(--label);
  font-style: italic;
  white-space: nowrap;
}
.kpi-donutplot { min-height: 0; }

/* The way back, beside the way home. Absent rather than disabled when there
   is nowhere to go: a control that never does anything reads as broken. */
.dash-back { color: var(--accent-2); }
.dash-back:hover { color: var(--ink); }

/* Back and forward sit together, left of the title, in reading order. */
.dash-back + .dash-back { margin-left: -.15rem; }

/* ---- Home, back, forward ------------------------------------------------
   Drawn rather than spelled. Home used to be the character U+2302, whose
   coverage varies by font, and it sat beside two arrow characters in a header
   whose other navigation is inline SVG — so the three read as unrelated even
   where all three rendered. These match .db-viewbtn deliberately: they are
   navigation, and they should look like the navigation already there. */
.dash-nav {
  flex: 0 0 auto;
  width: 1.9rem; height: 1.9rem;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--input);
  color: var(--label);
  cursor: pointer;
  padding: 0;
  appearance: none; -webkit-appearance: none;
  transition: .12s;
}
.dash-nav svg { width: 1rem; height: 1rem; display: block; }
.dash-nav:hover { border-color: var(--accent); color: var(--accent); }
.dash-nav:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Back and forward are one pair; home is a different kind of move. */
.dash-nav.dash-back { color: var(--accent-2); }
.dash-nav.dash-back:hover { color: var(--ink); border-color: var(--accent-2); }
.dash-back + .dash-back { margin-left: -.15rem; }

/* ---- Sales Pulse movers: how many of how many --------------------------
   Six cards were drawn under a selector reading "(60)", with nothing to say
   the other fifty-four existed or how to reach them. */
.pulse-movers-head {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  margin-bottom: .35rem;
  font-size: .68rem;
  color: var(--label);
}
.pulse-more { display: flex; gap: .25rem; margin-left: auto; }
.pulse-more .exec-crumb { padding: .06rem .4rem; font-size: .66rem; }
/* Past a dozen cards the list becomes the page, so it scrolls in its own
   right rather than pushing the rest of the screen out of reach. */
.pulse-movers { max-height: 62vh; overflow-y: auto; }

/* A position, not a total. Marked on the card because a reader scanning a
   grid of money reads the numbers, not the captions. */
.kpi-balance { color: var(--accent-2); font-weight: 600; }

/* ---- Sales KPI wheel ----------------------------------------------------
   Twelve figures around a hub. Radial where there is room; a plain grid
   where there is not, which is why the positions are custom properties and
   not `left`/`top` — one media query drops the whole arrangement instead of
   fighting inline styles. */
.wheel-body { display: flex; flex-direction: column; gap: .8rem; }
.wheel-ring {
  position: relative;
  width: 100%;
  max-width: 46rem;
  margin: 0 auto;
  aspect-ratio: 1 / 0.82;
  min-height: 24rem;
}
.wheel-hub {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 11rem; height: 11rem;
  display: grid; place-content: center; text-align: center;
  gap: .15rem;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%,
              rgba(109,94,252,.22), var(--input) 70%);
  padding: 1rem;
}
.wheel-hub-lab { font-size: .68rem; color: var(--label); line-height: 1.2;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; }
.wheel-hub-val { font-size: 1.35rem; font-weight: 700; color: var(--ink); }
.wheel-hub-sub { font-size: .62rem; color: var(--muted); }

.wheel-spoke {
  position: absolute;
  left: var(--x, 50%); top: var(--y, 50%);
  transform: translate(-50%, -50%);
  width: 8.6rem;
  padding: .4rem .5rem;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--input);
  text-align: center;
}
.wheel-spoke-lab { font-size: .63rem; color: var(--label); line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wheel-spoke-val { font-size: .95rem; font-weight: 700; color: var(--ink); }
.wheel-spoke-chg { font-size: .63rem; font-weight: 600; }
.wheel-spoke-chg.up { color: #3ddc97; }
.wheel-spoke-chg.down { color: var(--danger); }
/* No inherent better direction — a pack mix is not good or bad. */
.wheel-spoke-chg.flat { color: var(--muted); }

.wheel-rows { display: flex; flex-direction: column; gap: .2rem; }
.wheel-rows .kpi-drill-row { grid-template-columns: 1fr auto auto auto; }
.wheel-row-share { font-size: .68rem; color: var(--label); min-width: 3rem;
  text-align: right; }
.wheel-crumbs { margin: .1rem 0 .5rem; }

/* Below this the circle stops being readable: the boxes overlap the hub and
   each other. A grid says the same twelve things and fits. */
@media (max-width: 860px) {
  .wheel-ring { aspect-ratio: auto; min-height: 0;
    display: grid; grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
    gap: .4rem; }
  .wheel-hub { position: static; transform: none; width: auto; height: auto;
    border-radius: 10px; grid-column: 1 / -1; padding: .7rem; }
  .wheel-spoke { position: static; transform: none; width: auto; }
}

/* The level list is the page once it holds twenty-six rows, so it scrolls in
   its own right rather than pushing the wheel off the top. */
.wheel-rows { max-height: 52vh; overflow-y: auto; }

/* A capped, scrolling list has to scroll rather than squash.

   Both of these are column flex containers with a height cap, and a flex
   container shrinks its children before it overflows — so `overflow-y: auto`
   never gets its turn. With twenty-five rows in 52vh every row lost a third
   of its height (26px down to 17px) and the `overflow: hidden` inside it
   cropped the brand name through the middle of the letters.

   The children keep their own height; the container does the scrolling,
   which is what the cap was there for. */
.wheel-rows > *,
.pulse-movers > * { flex: 0 0 auto; }
.wheel-level .exec-ph { display: flex; align-items: center; gap: .5rem;
  flex-wrap: wrap; }

/* "+ New chat" was styled for the sidebar it used to live in, so it is full
   width. In the header it sits beside the brand and must not stretch. */
.new-chat-btn.hdr {
  width: auto;
  flex: 0 0 auto;
  padding: 5px 11px;
  font-size: 12px;
  white-space: nowrap;
}

/* ===== Ready-made chart suggestions (DB search) ======================== */
.chart-suggest-row{max-width:760px;margin:2px auto 10px;padding:0 24px}
.chart-suggest{display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.cs-label{font-size:11.5px;color:var(--muted);font-weight:600;margin-right:2px}
.cs-chip{border:1px solid var(--line);border-radius:100px;background:var(--input);color:var(--ink);
  cursor:pointer;font-size:12px;padding:4px 11px;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.cs-chip:hover{border-color:var(--accent);color:var(--accent)}
@media (max-width:720px){.chart-suggest-row{padding:0 14px}.cs-chip{min-height:30px}}

/* ===== Scheduled digests (subscriptions) =============================== */
.sub-row{display:flex;align-items:center;gap:10px;justify-content:space-between;
  border:1px solid var(--line);border-radius:10px;padding:9px 12px;margin:8px 0;background:var(--input)}
.sub-info{min-width:0}
.sub-name{font-weight:600;font-size:13.5px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sub-meta{font-size:11.5px;color:var(--muted);margin-top:2px}
.sub-acts{display:flex;gap:6px;flex:0 0 auto}
.sub-btn{border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--muted);
  cursor:pointer;font-size:11.5px;padding:5px 9px}
.sub-btn:hover{border-color:var(--accent);color:var(--accent)}
.sub-del:hover{border-color:var(--neg,#c0492f);color:var(--neg,#c0492f)}
.metric-pick{max-height:180px;overflow-y:auto;border:1px solid var(--line);border-radius:9px;
  padding:6px 10px;margin:2px 0 4px}
.metric-pick-row{display:flex;align-items:center;gap:8px;padding:3px 0;font-size:13px;cursor:pointer}

/* ===== Responsive hardening =============================================
   Wide matrices already scroll inside .pv-matrix-box, result tables inside
   .bubble table, and the app shell (.chat-body/.app-shell {overflow:hidden})
   already blocks any page-level sideways scroll — so this block adds the two
   things that were genuinely missing on phones: values that can't stretch a
   chip off-screen, and finger-sized tap targets. */

/* A long dimension value (e.g. "Div Sales Cntr Bogra Buf") shouldn't push a
   filter chip past the screen edge — truncate with an ellipsis instead. */
.dfb-chip-value { max-width: 46vw; overflow: hidden; text-overflow: ellipsis; }
.scope-chip { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.pv-matrix-box { max-width: 100%; }

@media (max-width: 720px) {
  /* Reclaim the ~48px of side gutters that hurt most on a narrow screen. */
  .msg { padding: 0 14px; }
  .metric-detail { padding: 0 14px; }
  .composer-inner { padding: 0 14px; }
  /* Not enough width to keep the icons beside the input — give the input its
     own row and let the tools wrap beneath it, Send at the right. */
  .composer-inner { flex-wrap: wrap; }
  .chat-input { flex: 1 1 100%; }
  .send-btn { margin-left: auto; }
  /* Comfortable tap targets for the icon buttons and chips. */
  .dash-fs, .dash-nav, .dash-close, .dash-dl, .md-more {
    min-height: 34px; min-width: 34px;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .dfb-chip, .tog, .fc-chip { min-height: 32px; }
  .dash-rows, .scopeSel, .db-table { min-height: 38px; }
}

/* On any real touch device, size up the icon buttons regardless of width. */
@media (pointer: coarse) {
  .dash-fs, .dash-nav, .dash-close, .dash-dl, .md-more {
    min-height: 36px; min-width: 36px;
    display: inline-flex; align-items: center; justify-content: center;
  }
}
