/* VecViz dashboards. One file, no framework.
   Layout mirrors the OpenBB tabs: a 40-column grid where each panel keeps the
   x and w it has in apps.json, collapsing to one column on narrow screens. */

:root {
  --orange: #E0701A;
  --orange-deep: #BC560F;
  --orange-tint: #FBEFE2;
  --slate: #5E6E7E;
  --slate-deep: #3F4D5B;
  --slate-tint: #EDF1F4;
  --paper: #FCFBF8;
  --panel: #F3F1EA;
  --rule: #DFDCD2;
  --ink: #22282E;

  --display: "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --body: "Source Serif 4", Georgia, "Times New Roman", serif;
  --mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace;

  /* One OpenBB grid row. OpenBB's own rows are taller than the 21px this
     started at, which left the VNA table 252px high and unreadable. */
  --row: 30px;
  --chart-min: 480px;
  --table-min: 560px;
  --gap: 14px;
  --radius: 4px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5 { font-family: var(--display); font-weight: 600; letter-spacing: -0.01em; }

a { color: var(--orange-deep); }
a:hover { color: var(--orange); }

.vv-mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.vv-link { font-family: var(--display); font-size: 0.82rem; text-decoration: none; }
.vv-link:hover { text-decoration: underline; }

/* ---------------------------------------------------------------- header */

.vv-header {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 14px 24px;
  background: var(--paper);
  border-bottom: 2px solid var(--slate-deep);
  position: sticky;
  top: 0;
  z-index: 40;
}
.vv-brand { display: flex; align-items: center; flex: 0 0 auto; }
.vv-brand img { display: block; }
.vv-header-title { flex: 1 1 auto; min-width: 0; }
.vv-header-title h1 {
  margin: 0;
  font-size: 1.14rem;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vv-asof {
  margin: 2px 0 0;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--slate);
}
.vv-header-actions { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; }
.vv-header-actions form { margin: 0; }

/* ------------------------------------------------------------------ shell */

.vv-shell {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  gap: 0;
  align-items: start;
}

.vv-nav {
  position: sticky;
  top: 63px;
  padding: 22px 14px 32px 24px;
  border-right: 1px solid var(--rule);
  min-height: calc(100vh - 63px);
}
.vv-nav ol { list-style: none; margin: 0; padding: 0; }
.vv-nav li { margin: 0 0 2px; }
.vv-nav a {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 7px 10px;
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--slate-deep);
  font-family: var(--display);
  font-size: 0.84rem;
  line-height: 1.3;
  border-left: 3px solid transparent;
}
.vv-nav a:hover { background: var(--slate-tint); }
.vv-nav a.is-active {
  background: var(--orange-tint);
  border-left-color: var(--orange);
  color: var(--orange-deep);
  font-weight: 600;
}
.vv-nav-index {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--slate);
  flex: 0 0 auto;
}
.vv-nav a.is-active .vv-nav-index { color: var(--orange); }

.vv-main { padding: 22px 24px 40px; min-width: 0; }
.vv-subtitle {
  margin: 0 0 18px;
  color: var(--slate-deep);
  font-size: 1rem;
  max-width: 68ch;
}

/* --------------------------------------------------------------- controls */

.vv-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 18px;
  align-items: flex-end;
  padding: 13px 16px;
  margin: 0 0 18px;
  background: var(--slate-tint);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.vv-control { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.vv-label {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--slate);
}
.vv-select, .vv-input {
  font-family: var(--mono);
  font-size: 0.84rem;
  padding: 6px 9px;
  background: #fff;
  color: var(--ink);
  border: 1px solid var(--slate);
  border-radius: var(--radius);
  min-width: 148px;
  max-width: 300px;
}
.vv-select:focus-visible, .vv-input:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 1px;
}
.vv-select[multiple] { min-height: 32px; max-height: 108px; }
.vv-check { width: 17px; height: 17px; accent-color: var(--orange); margin: 6px 0; }

.vv-button {
  font-family: var(--display);
  font-size: 0.82rem;
  font-weight: 600;
  padding: 7px 15px;
  border-radius: var(--radius);
  border: 1px solid var(--slate);
  background: #fff;
  color: var(--slate-deep);
  cursor: pointer;
}
.vv-button:hover { border-color: var(--orange); color: var(--orange-deep); }
.vv-button-primary {
  background: var(--orange);
  border-color: var(--orange-deep);
  color: #fff;
  width: 100%;
  padding: 10px 15px;
  margin-top: 16px;
}
.vv-button-primary:hover { background: var(--orange-deep); color: #fff; }
.vv-button-quiet { border-color: var(--rule); }

/* ------------------------------------------------------------------- grid */

.vv-grid {
  display: grid;
  grid-template-columns: repeat(40, minmax(0, 1fr));
  gap: var(--gap);
  align-items: start;
}
.vv-panel {
  grid-column: var(--vv-x) / span var(--vv-w);
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  min-width: 0;
}
.vv-panel-head {
  display: flex;
  align-items: center;
  gap: 8px 12px;
  flex-wrap: wrap;
  padding: 8px 14px;
  background: var(--slate-tint);
  border-bottom: 1px solid var(--rule);
}
.vv-panel-head h2 { margin: 0; font-size: 0.9rem; flex: 1 1 auto; min-width: 0; }
.vv-panel-meta {
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--slate);
  white-space: nowrap;
  flex: 0 0 auto;
  order: 99;
}
.vv-panel-body {
  padding: 12px 14px;
  min-height: 90px;
  min-width: 0;
  overflow: auto;
}
/* Charts and tables get the height their OpenBB grid rows imply, floored so a
   short widget is still usable; markdown runs to its natural length rather than
   scrolling inside a box.

   `resize: vertical` is the whole drag-to-resize feature: the browser draws the
   handle and does the dragging. A ResizeObserver in panels.js is what tells
   Plotly and Tabulator to refill the new box, since dragging an element does
   not fire window's resize event. */
.vv-panel[data-kind="chart"] .vv-panel-body,
.vv-panel[data-kind="table"] .vv-panel-body {
  resize: vertical;
  overflow: auto;
}
.vv-panel[data-kind="chart"] .vv-panel-body {
  height: max(calc(var(--vv-h) * var(--row)), var(--chart-min));
  min-height: 260px;
  /* Every chart renders with paper_bgcolor #FFFFFF. Without this the panel's
     cream (--panel) framed each one and showed through wherever the Plotly div
     did not fill the body -- which read as a peach chart background rather than
     as panel chrome. White here means the figure and its surround are the same
     colour and the seam disappears. */
  background: #fff;
}
.vv-panel[data-kind="table"] .vv-panel-body {
  height: max(calc(var(--vv-h) * var(--row)), var(--table-min));
  min-height: 260px;
}
/* Markdown keeps its natural height until it would run past most of the screen,
   then scrolls inside the panel. That cap is also what makes the sticky header
   on a report table work: a sticky cell needs a scrolling ancestor, and without
   this the page itself is the scroller and the header slides under the site
   header instead. */
.vv-panel[data-kind="markdown"] .vv-panel-body {
  max-height: 78vh;
  resize: vertical;
  overflow: auto;
}

/* Expanded: the panel takes the viewport. Above the sticky header, which is
   z-index 40. */
.vv-panel.is-expanded {
  position: fixed;
  inset: 0;
  z-index: 60;
  border-radius: 0;
  border: none;
  box-shadow: 0 0 0 100vmax rgba(34, 40, 46, 0.35);
}
.vv-panel.is-expanded .vv-panel-body {
  height: calc(100vh - 46px) !important;
  max-height: none;
  resize: none;
}
body.vv-has-expanded { overflow: hidden; }

/* Small control in a panel header: Expand, and the column toggle on wide
   tables. */
.vv-chip {
  font-family: var(--display);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 3px 9px;
  margin-left: auto;
  background: transparent;
  color: var(--slate-deep);
  border: 1px solid var(--slate);
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  flex: 0 0 auto;
}
.vv-chip:hover { border-color: var(--orange); color: var(--orange-deep); background: var(--orange-tint); }
.vv-chip[aria-pressed="true"] { background: var(--orange); border-color: var(--orange-deep); color: #fff; }
.vv-chip + .vv-chip, .vv-chip ~ .vv-panel-meta { margin-left: 8px; }
.vv-panel-note {
  margin: 8px 0 0;
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--slate);
}

.vv-chart, .vv-table { width: 100%; height: 100%; min-height: 220px; }

/* ----------------------------------------------------------------- states */

.vv-state {
  margin: 0;
  padding: 20px 0;
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--slate);
  text-align: center;
}
.vv-state-loading::after {
  content: "";
  animation: vv-dots 1.4s steps(4, end) infinite;
}
@keyframes vv-dots { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; } }
.vv-state-error { color: var(--orange-deep); background: var(--orange-tint); border-radius: var(--radius); }

@media (prefers-reduced-motion: reduce) {
  .vv-state-loading::after { animation: none; content: "..."; }
}

/* --------------------------------------------------------------- markdown */

/* Prose holds a readable measure; tables and images use the full panel. */
.vv-markdown { font-size: 0.95rem; line-height: 1.6; }
.vv-markdown > * { max-width: 76ch; }
.vv-markdown > table, .vv-markdown > .vv-table-scroll, .vv-markdown > img { max-width: 100%; }

.vv-markdown h1 { font-size: 1.34rem; margin: 0 0 4px; line-height: 1.25; }
.vv-markdown h2 {
  font-size: 1.1rem;
  margin: 30px 0 8px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--rule);
  color: var(--slate-deep);
}
.vv-markdown h3 { font-size: 1rem; margin: 22px 0 5px; }
.vv-markdown h4, .vv-markdown h5 {
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin: 18px 0 4px;
  color: var(--slate);
}
.vv-markdown > h1:first-child, .vv-markdown > h2:first-child { margin-top: 0; }
.vv-markdown p { margin: 0 0 11px; }
.vv-markdown ul, .vv-markdown ol { margin: 0 0 12px; padding-left: 22px; }
.vv-markdown li { margin: 0 0 4px; }

/* The explainers are overwhelmingly "**Term** - definition" paragraphs. A
   hanging indent turns each one into a labelled entry, which is what makes a
   glossary scannable instead of a wall. */
.vv-markdown p > strong:first-child {
  color: var(--orange-deep);
  font-family: var(--display);
}
.vv-markdown p:has(> strong:first-child) {
  padding-left: 18px;
  text-indent: -18px;
  margin-bottom: 9px;
}

.vv-markdown hr {
  border: none;
  border-top: 1px solid var(--rule);
  margin: 22px 0;
}
.vv-markdown img { max-width: 100%; height: auto; border-radius: var(--radius); margin: 6px 0 12px; }
.vv-markdown code { font-family: var(--mono); font-size: 0.85em; background: var(--slate-tint); padding: 1px 4px; border-radius: 3px; }
.vv-markdown pre { overflow-x: auto; background: var(--slate-tint); padding: 10px 12px; border-radius: var(--radius); }
.vv-markdown pre code { background: none; padding: 0; }
.vv-markdown blockquote {
  margin: 0 0 12px;
  padding: 8px 14px;
  background: var(--orange-tint);
  border-left: 3px solid var(--orange);
  border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--slate-deep);
}
.vv-markdown blockquote p:last-child { margin-bottom: 0; }

/* Report tables run to 13 columns by 111 rows. They wrap rather than forcing a
   horizontal scroll, keep their header visible while scrolling, and align their
   numerals so columns of figures can be compared down the page. */
.vv-markdown table {
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  width: 100%;
  margin: 0 0 16px;
}
.vv-markdown th, .vv-markdown td {
  border: 1px solid var(--rule);
  padding: 6px 10px;
  text-align: left;
  vertical-align: top;
  overflow-wrap: anywhere;
}
.vv-markdown th {
  background: var(--slate-tint);
  font-family: var(--display);
  font-weight: 600;
  position: sticky;
  top: 0;
  z-index: 1;
  box-shadow: inset 0 -1px 0 var(--slate);
}
.vv-markdown tbody tr:nth-child(even) { background: rgba(255, 255, 255, 0.6); }
.vv-markdown tbody tr:hover { background: var(--orange-tint); }
/* Everything after the first column in a report table is a figure. */
.vv-markdown td:not(:first-child) { text-align: right; }
.vv-markdown th:not(:first-child) { text-align: right; }

/* --------------------------------------------------------------- tabulator */

.tabulator {
  background: transparent;
  border: none;
  font-family: var(--mono);
  font-size: 0.75rem;
}
.tabulator .tabulator-header {
  background: var(--slate-tint);
  border-bottom: 1px solid var(--slate);
  font-family: var(--display);
  font-size: 0.72rem;
}
.tabulator .tabulator-col { background: var(--slate-tint); }
.tabulator .tabulator-row { background: transparent; border-bottom: 1px solid var(--rule); }
.tabulator .tabulator-row.tabulator-row-even { background: rgba(255, 255, 255, 0.55); }
.tabulator .tabulator-row:hover { background: var(--orange-tint); }
.tabulator .vv-num { font-variant-numeric: tabular-nums; }

/* Header filters. The inputs sit inside the header cell, so they stay put while
   the rows scroll under them. */
.tabulator .tabulator-header-filter input,
.tabulator .tabulator-header-filter select {
  font-family: var(--mono);
  font-size: 0.7rem;
  width: 100%;
  padding: 2px 5px;
  background: #fff;
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 3px;
}
.tabulator .tabulator-header-filter input:focus-visible,
.tabulator .tabulator-header-filter select:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 0;
  border-color: var(--orange);
}
.tabulator .tabulator-header-filter input::placeholder { color: var(--slate); opacity: 0.75; }
/* The dropdown a "list" header filter opens. */
.tabulator-edit-list {
  font-family: var(--mono);
  font-size: 0.74rem;
  background: #fff;
  border: 1px solid var(--slate);
  border-radius: var(--radius);
  max-height: 260px;
}
.tabulator-edit-list .tabulator-edit-list-item.active,
.tabulator-edit-list .tabulator-edit-list-item:hover {
  background: var(--orange-tint);
  color: var(--orange-deep);
}
/* A frozen column sits above the scrolling ones, so it needs its own ground. */
.tabulator .tabulator-frozen { background: var(--panel); }
.tabulator .tabulator-row.tabulator-row-even .tabulator-frozen { background: #fbfaf6; }
.tabulator .tabulator-col.tabulator-frozen { background: var(--slate-tint); }

/* ------------------------------------------------------------------ index */

.vv-index {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: var(--gap);
}
.vv-index-card a {
  display: grid;
  gap: 4px;
  padding: 16px 18px;
  height: 100%;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--orange);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--ink);
}
.vv-index-card a:hover { background: var(--orange-tint); border-color: var(--orange); border-left-color: var(--orange-deep); }
.vv-index-num { font-family: var(--mono); font-size: 0.68rem; color: var(--orange-deep); }
.vv-index-title { font-family: var(--display); font-weight: 600; font-size: 1rem; }
.vv-index-sub { font-size: 0.88rem; color: var(--slate-deep); }
.vv-index-meta { font-family: var(--mono); font-size: 0.66rem; color: var(--slate); margin-top: 4px; }

/* ------------------------------------------------------------------ login */

.vv-login {
  min-height: calc(100vh - 58px);
  display: grid;
  place-items: center;
  padding: 40px 20px;
}
.vv-login-card {
  width: min(400px, 100%);
  padding: 32px;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--orange);
  border-radius: var(--radius);
}
.vv-login-mark { display: block; margin: 0 0 18px; }
.vv-login-card h1 { margin: 0 0 4px; font-size: 1.4rem; }
.vv-login-lede { margin: 0 0 20px; color: var(--slate-deep); font-size: 0.94rem; }
.vv-login-card .vv-input { width: 100%; max-width: none; margin-top: 4px; }
.vv-login-error {
  margin: 0 0 16px;
  padding: 9px 12px;
  background: var(--orange-tint);
  border-left: 3px solid var(--orange-deep);
  border-radius: var(--radius);
  color: var(--orange-deep);
  font-size: 0.86rem;
}
.vv-login-help { margin: 18px 0 0; font-size: 0.82rem; color: var(--slate); }
.vv-login-help p { margin: 0 0 10px; }
.vv-login-help p:last-child { margin-bottom: 0; }
/* Where the key came from, and how to get it again. Set apart from the sign-in
   form, because someone reads it only when the form is not working for them. */
.vv-login-note {
  padding: 10px 12px;
  background: var(--slate-tint);
  border-left: 3px solid var(--slate);
  border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--slate-deep);
  line-height: 1.5;
}
.vv-login-note a { overflow-wrap: anywhere; }

/* ----------------------------------------------------------------- footer */

.vv-footer {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 24px;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--slate);
}
.vv-footer-brand { text-transform: uppercase; }

/* The legal footer is two stacked lines rather than the old left/right pair --
   it no longer fits on one, and wrapping mid-clause reads as broken. */
.vv-footer { flex-direction: column; gap: 4px; align-items: flex-start; }
.vv-footer-legal { margin: 0; line-height: 1.6; }
.vv-footer-legal a { color: inherit; text-decoration: underline; }
.vv-footer-legal a:hover { color: var(--slate-deep); }
.vv-footer-sep { opacity: 0.45; margin: 0 6px; }

}

/* ------------------------------------------------------------- responsive */

@media (max-width: 1000px) {
  .vv-shell { grid-template-columns: minmax(0, 1fr); }
  .vv-nav {
    position: static;
    min-height: 0;
    border-right: none;
    border-bottom: 1px solid var(--rule);
    padding: 12px 16px;
  }
  .vv-nav ol { display: flex; flex-wrap: wrap; gap: 4px; }
  .vv-nav-index { display: none; }
  .vv-main { padding: 18px 16px 32px; }
  /* One column: panels stack in reading order and take their own height. */
  .vv-grid { grid-template-columns: minmax(0, 1fr); }
  .vv-panel { grid-column: 1 / -1; }
  .vv-panel[data-kind="chart"] .vv-panel-body,
  .vv-panel[data-kind="table"] .vv-panel-body { height: 420px; }
}

@media (max-width: 620px) {
  .vv-header { flex-wrap: wrap; gap: 10px 16px; padding: 12px 16px; }
  .vv-header-title { order: 3; flex-basis: 100%; }
  .vv-controls { padding: 12px; }
  .vv-select, .vv-input { min-width: 0; width: 100%; }
  .vv-control { flex: 1 1 100%; }
}

/* ---------------------------------------------------------------------------
   Public demo
   ---------------------------------------------------------------------------
   Rendered by shell.html between the header and the shell grid, so it sits
   above the nav and the panels on all eight pages rather than being repeated
   per page. The only visual difference between the demo and the subscriber
   dashboards: an honest preview should look like the product. */

.vv-demo-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1.5rem;
  padding: 0.7rem 1.25rem;
  background: var(--orange-tint);
  border-bottom: 1px solid var(--orange);
}

.vv-demo-copy {
  margin: 0;
  min-width: 18rem;
  flex: 1 1 32rem;
  color: var(--slate-deep);
  font-size: 0.9rem;
  line-height: 1.45;
}

.vv-demo-copy strong { color: var(--orange-deep); }

.vv-demo-banner .vv-button {
  flex: 0 0 auto;
  background: var(--orange);
  border-color: var(--orange-deep);
  color: #fff;
}

.vv-demo-banner .vv-button:hover {
  background: var(--orange-deep);
  border-color: var(--orange-deep);
  color: #fff;
}

/* A section the viewer's tier does not include. Kept in place and legible
   rather than removed, so the list reads as a preview. */
.vv-select option:disabled { color: var(--slate); }
