/* ============================================================================
   Twain Macro Hub — demo styling
   Cobalt Institutional palette (navy / cool paper / cobalt) on a felix-style shell.
   ========================================================================== */

/* -- bundled fonts (latin subset, offline) -- */
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/inter-400.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('fonts/inter-500.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/inter-600.woff2') format('woff2');}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/inter-700.woff2') format('woff2');}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/space-grotesk-400.woff2') format('woff2');}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url('fonts/space-grotesk-500.woff2') format('woff2');}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:600;font-display:swap;src:url('fonts/space-grotesk-600.woff2') format('woff2');}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/space-grotesk-700.woff2') format('woff2');}
@font-face{font-family:'Space Mono';font-style:normal;font-weight:400;font-display:swap;src:url('fonts/space-mono-400.woff2') format('woff2');}
@font-face{font-family:'Space Mono';font-style:normal;font-weight:700;font-display:swap;src:url('fonts/space-mono-700.woff2') format('woff2');}

/* ===== Cobalt Institutional ===== */
:root {
  --bg:        #eef1f6;
  --surface:   #ffffff;
  --surface-2: #f1f4fa;
  --ink:       #0b1b2b;
  --ink-soft:  #3a4b5c;
  --muted:     #7a879a;
  --line:      #e3e8f0;
  --line-2:    #d3dae6;
  --accent:    #2f6bff;
  --accent-2:  #1f4fd1;
  --accent-bg: #e6edff;
  --green:     #12a594;
  --green-bg:  #d8f3ee;
  --red:       #e0483d;
  --red-bg:    #fbe3e1;
  --amber-bg:  #f4ead2;
  --amber-tx:  #9c6b16;
  --blue-bg:   #e2ebff;
  --blue-tx:   #2f5fd0;

  --side-bg:   #0b2545;
  --side-bg-2: #12315c;
  --side-tx:   #c7d6ea;
  --side-tx-2: #7f97b8;
  --side-line: #1b3a63;

  --radius:    12px;
  --radius-sm: 8px;
  --shadow:    0 1px 2px rgba(11,27,43,.05), 0 6px 20px rgba(11,27,43,.06);
  --shadow-lg: 0 12px 44px rgba(11,27,43,.18);
  --display:   'Space Grotesk', 'Segoe UI', system-ui, sans-serif;
  --sans:      'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono:      'Space Mono', ui-monospace, Menlo, Consolas, monospace;
}

:root[data-theme="dark"] {
  --bg:        #0a1626;
  --surface:   #0f2136;
  --surface-2: #16304d;
  --ink:       #e6eef8;
  --ink-soft:  #b8c6da;
  --muted:     #8296b0;
  --line:      #1c3651;
  --line-2:    #244269;
  --accent:    #4c86ff;
  --accent-2:  #6f9fff;
  --accent-bg: #16305a;
  --green:     #17b39d;
  --green-bg:  #0e3b39;
  --red:       #ef6b60;
  --red-bg:    #3a1f1d;
  --amber-bg:  #33290f;
  --amber-tx:  #d8b869;
  --blue-bg:   #16305a;
  --blue-tx:   #9fbcff;
  --side-bg:   #071626;
  --side-bg-2: #0f2743;
  --side-tx:   #c7d6ea;
  --side-tx-2: #6f88a8;
  --side-line: #14304f;
  --shadow:    0 1px 2px rgba(0,0,0,.35), 0 6px 20px rgba(0,0,0,.3);
  --shadow-lg: 0 12px 44px rgba(0,0,0,.55);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--sans); -webkit-font-smoothing: antialiased;
  font-size: 14px; line-height: 1.5;
}
.num { font-variant-numeric: tabular-nums; }
.pos { color: var(--green) !important; }
.neg { color: var(--red)   !important; }
.mono { font-family: var(--mono); }

/* ---- App shell --------------------------------------------------------- */
.app { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }

/* ---- Sidebar ----------------------------------------------------------- */
.side {
  background: var(--side-bg); color: var(--side-tx);
  display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh;
  border-right: 1px solid var(--side-line);
}
.side-brand { padding: 20px 20px 16px; border-bottom: 1px solid var(--side-line); }
.side-brand .mark {
  display: flex; align-items: center; gap: 10px;
}
.side-brand .glyph {
  width: 30px; height: 30px; border-radius: 8px; flex: none;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  display: grid; place-items: center; color: #fff; font-family: var(--display);
  font-weight: 700; font-size: 16px;
}
.side-brand .name { font-family: var(--display); font-size: 16px; color: #fff; line-height: 1.1; }
.side-brand .sub  { font-size: 10.5px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--side-tx-2); margin-top: 2px; }

.side-nav { padding: 12px 12px; flex: 1; overflow-y: auto; }
.side-group { font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--side-tx-2); margin: 14px 10px 6px; }
.side-link {
  display: flex; align-items: center; gap: 11px; padding: 8px 11px; border-radius: 8px;
  color: var(--side-tx); cursor: pointer; font-size: 13px; margin-bottom: 1px; border: none; background: none; width: 100%; text-align: left;
}
.side-link svg { width: 16px; height: 16px; opacity: .8; flex: none; }
.side-link:hover { background: var(--side-bg-2); color: #fff; }
.side-link.active { background: var(--side-bg-2); color: #fff; box-shadow: inset 2px 0 0 var(--accent); }
.side-link.active svg { opacity: 1; color: var(--accent-2); }

.side-foot { padding: 14px 16px; border-top: 1px solid var(--side-line); font-size: 11px; color: var(--side-tx-2); }
.side-foot b { color: var(--side-tx); font-weight: 600; }
.side-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--green); margin-right: 6px; box-shadow: 0 0 0 3px rgba(18,165,148,.20); }

/* ---- Top bar ----------------------------------------------------------- */
.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
  position: sticky; top: 0; z-index: 20; background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px); border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 16px; padding: 12px 26px;
}
.topbar .tb-title { font-family: var(--display); font-size: 18px; }
.topbar .tb-as-of { font-size: 12px; color: var(--muted); }
.tb-spacer { flex: 1; }
.tb-btn {
  border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-soft);
  border-radius: 8px; padding: 7px 12px; font-size: 12.5px; cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--sans);
}
.tb-btn:hover { border-color: var(--accent); color: var(--accent); }
.tb-btn svg { width: 15px; height: 15px; }

/* user switcher */
.user-switch { position: relative; }
.user-chip {
  display: flex; align-items: center; gap: 9px; border: 1px solid var(--line-2);
  background: var(--surface); border-radius: 999px; padding: 4px 12px 4px 4px; cursor: pointer;
}
.user-chip:hover { border-color: var(--accent); }
.avatar {
  width: 30px; height: 30px; border-radius: 50%; flex: none; display: grid; place-items: center;
  color: #fff; font-size: 11.5px; font-weight: 700; letter-spacing: .3px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}
.user-chip .u-name { font-size: 13px; font-weight: 600; line-height: 1.1; }
.user-chip .u-role { font-size: 10.5px; color: var(--muted); }
.user-chip svg { width: 14px; height: 14px; color: var(--muted); }
.user-menu {
  position: absolute; right: 0; top: 46px; width: 250px; background: var(--surface);
  border: 1px solid var(--line-2); border-radius: 12px; box-shadow: var(--shadow-lg); padding: 6px; z-index: 40;
  display: none;
}
.user-menu.open { display: block; animation: pop .12s ease-out; }
.user-menu .um-head { font-size: 10px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--muted); padding: 8px 10px 4px; }
.user-menu button {
  display: flex; align-items: center; gap: 10px; width: 100%; border: none; background: none;
  padding: 7px 10px; border-radius: 8px; cursor: pointer; text-align: left; color: var(--ink);
}
.user-menu button:hover { background: var(--surface-2); }
.user-menu .um-name { font-size: 13px; font-weight: 600; }
.user-menu .um-role { font-size: 11px; color: var(--muted); }
.user-menu .um-you { margin-left: auto; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--accent); }
.user-menu .um-admin { background: var(--accent); color: #fff; padding: 2px 7px; border-radius: 8px; }
.badge-admin { display: inline-block; margin-left: 7px; font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: #fff; background: var(--accent); padding: 1px 6px; border-radius: 7px; vertical-align: middle; }
@keyframes pop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* ---- Content ----------------------------------------------------------- */
.content { padding: 26px; max-width: 1240px; width: 100%; margin: 0 auto; }
.view { display: none; }
.view.active { display: block; animation: fade .25s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.section-head { display: flex; align-items: baseline; gap: 12px; margin: 34px 0 14px; }
.section-head:first-child { margin-top: 4px; }
.section-head h2 { font-family: var(--display); font-size: 20px; margin: 0; font-weight: 500; }
.section-head .sh-note { font-size: 12.5px; color: var(--muted); }
.kicker { font-size: 11px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--accent); }

.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* ---- Morning digest ---------------------------------------------------- */
.digest { padding: 26px 28px; margin-bottom: 8px; position: relative; overflow: hidden; }
.digest::after {
  content: ""; position: absolute; right: -60px; top: -60px; width: 240px; height: 240px;
  background: radial-gradient(circle, rgba(47,107,255,.10), transparent 70%); pointer-events: none;
}
.digest h1 { font-family: var(--display); font-size: 30px; margin: 6px 0 6px; font-weight: 600; }
.digest .d-line { font-size: 15px; color: var(--ink-soft); max-width: 720px; margin: 0 0 18px; }
.regime {
  display: inline-flex; align-items: center; gap: 10px; background: var(--green-bg); color: var(--green);
  border-radius: 999px; padding: 6px 14px; font-weight: 700; font-size: 13px; margin-bottom: 6px;
}
.regime .r-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); }
.regime-note { font-size: 13px; color: var(--muted); margin: 10px 0 0; max-width: 660px; }

.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 22px; }
.stat {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 14px 16px;
}
.stat .s-k { font-size: 10.5px; text-transform: uppercase; letter-spacing: .7px; color: var(--muted); margin-bottom: 8px; }
.stat .s-v { font-family: var(--display); font-size: 24px; line-height: 1; }
.stat .s-s { font-size: 11.5px; color: var(--muted); margin-top: 7px; }

.movers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-top: 14px; }
.mover {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 13px 15px; display: flex; flex-direction: column; gap: 3px;
}
.mover .m-top { display: flex; justify-content: space-between; align-items: baseline; }
.mover .m-name { font-weight: 600; font-size: 13.5px; }
.mover .m-chg { font-family: var(--mono); font-weight: 700; font-size: 13px; }
.mover .m-val { font-family: var(--mono); font-size: 12px; color: var(--muted); }
.mover .m-note { font-size: 11.5px; color: var(--muted); margin-top: 2px; }

.digest-foot {
  margin-top: 18px; padding: 12px 15px; background: var(--accent-bg); border-radius: var(--radius-sm);
  font-size: 13px; color: var(--accent-2); display: flex; gap: 9px; align-items: flex-start;
}
.digest-foot svg { width: 16px; height: 16px; flex: none; margin-top: 1px; }

/* ---- Metric table ------------------------------------------------------ */
.grid-card { padding: 6px 6px 10px; overflow-x: auto; }
table.grid { width: 100%; border-collapse: collapse; font-size: 13px; }
table.grid th, table.grid td { padding: 8px 12px; border-bottom: 1px solid var(--line); text-align: right; white-space: nowrap; }
table.grid th { font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); border-bottom: 2px solid var(--line-2); font-weight: 700; position: sticky; }
table.grid th:first-child, table.grid td.metric { text-align: left; white-space: normal; }
table.grid td.metric { font-weight: 600; }
table.grid tr.cat td {
  background: var(--surface-2); font-weight: 700; font-size: 11px; text-transform: uppercase;
  letter-spacing: .6px; color: var(--ink); text-align: left; padding-top: 11px; padding-bottom: 11px;
}
table.grid tbody tr.data:hover td { background: color-mix(in srgb, var(--accent) 5%, transparent); }
td.spot { font-weight: 700; font-family: var(--mono); }
td.dim { color: var(--muted); }
td.z { font-weight: 600; font-family: var(--mono); }
.spark { display: inline-block; vertical-align: middle; }
.pctile-cell { position: relative; min-width: 60px; }
.pctile-bar { display: inline-block; height: 5px; border-radius: 3px; background: var(--accent); opacity: .55; vertical-align: middle; margin-left: 6px; }

.pill {
  display: inline-block; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px;
  padding: 2px 7px; border-radius: 9px; margin-left: 8px; vertical-align: middle;
}
.pill.free_api    { background: var(--green-bg); color: var(--green); }
.pill.proxy       { background: var(--amber-bg); color: var(--amber-tx); }
.pill.derived     { background: var(--blue-bg);  color: var(--blue-tx); }
.pill.proprietary { background: var(--red-bg);   color: var(--red); }
.cav { font-weight: 400; font-size: 11px; color: var(--muted); margin-top: 2px; }

.legend { display: flex; flex-wrap: wrap; gap: 16px; font-size: 11.5px; color: var(--muted); margin: 12px 2px 0; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.legend .dot { width: 9px; height: 9px; border-radius: 3px; }

/* ---- Commodities ------------------------------------------------------- */
.commod-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.commod {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 17px; box-shadow: var(--shadow);
}
.commod .c-top { display: flex; justify-content: space-between; align-items: flex-start; }
.commod .c-name { font-family: var(--display); font-size: 17px; }
.commod .c-tk { font-family: var(--mono); font-size: 11px; color: var(--muted); background: var(--surface-2); padding: 2px 7px; border-radius: 6px; }
.commod .c-spot { font-family: var(--mono); font-size: 22px; font-weight: 700; margin-top: 10px; }
.commod .c-row { display: flex; align-items: baseline; gap: 8px; margin-top: 3px; }
.commod .c-chg { font-family: var(--mono); font-weight: 700; font-size: 13px; }
.commod .c-unit { font-size: 11.5px; color: var(--muted); }
.commod .c-fut { font-size: 12px; color: var(--muted); margin-top: 8px; }
.commod .c-fut b { color: var(--ink-soft); font-family: var(--mono); }
.commod .c-spark { margin: 10px 0 6px; }
.commod .c-note { font-size: 11.5px; color: var(--muted); line-height: 1.45; border-top: 1px solid var(--line); padding-top: 9px; margin-top: 8px; }

/* ---- News -------------------------------------------------------------- */
.news-cols { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; align-items: start; }
.news-col .nc-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.news-col .nc-head h3 { font-family: var(--display); font-size: 15px; margin: 0; font-weight: 500; }
.news-col .nc-tier { font-size: 9px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase; padding: 2px 7px; border-radius: 8px; background: var(--surface-2); color: var(--muted); }
.news-item { padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); margin-bottom: 9px; box-shadow: var(--shadow); }
.news-item:hover { border-color: var(--line-2); }
.news-item .ni-meta { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--muted); margin-bottom: 5px; }
.news-item .ni-src { font-weight: 700; color: var(--ink-soft); }
.news-item .ni-tag { margin-left: auto; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px; color: var(--accent); background: var(--accent-bg); padding: 2px 6px; border-radius: 7px; }
.news-item .ni-head { font-size: 13px; line-height: 1.4; color: var(--ink); }

/* ---- Watchlist --------------------------------------------------------- */
.watch-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.watch {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 13px 15px; display: flex; align-items: center; gap: 12px; box-shadow: var(--shadow);
}
.watch .w-tk { font-family: var(--mono); font-weight: 700; font-size: 13px; width: 46px; }
.watch .w-mid { flex: 1; min-width: 0; }
.watch .w-name { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.watch .w-px { font-family: var(--mono); font-size: 14px; font-weight: 700; }
.watch .w-chg { font-family: var(--mono); font-size: 11.5px; font-weight: 700; text-align: right; }

/* U3. A live card carries a name and a reason and no price, so the middle column
   is the whole card and the two right-hand ones are absent rather than blank.
   Built only from variables already declared above, so no new value enters the
   palette: the same rule U2's Share and Delete controls were held to. */
.watch.live { align-items: flex-start; }
.watch .w-top { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.watch .w-full { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.watch .w-kind {
  margin-left: auto; font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .4px; color: var(--accent); background: var(--accent-bg);
  padding: 2px 6px; border-radius: 7px;
}
.watch .w-note { font-size: 11.5px; line-height: 1.45; color: var(--muted); }
.watch-empty { color: var(--muted); font-size: 13.5px; padding: 26px 4px; }

/* ---- Agent console ----------------------------------------------------- */
.agent-wrap { display: grid; grid-template-columns: 1fr; gap: 0; }
.agent {
  background: linear-gradient(180deg, var(--surface), var(--surface));
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden;
}
.agent-head {
  display: flex; align-items: center; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
.agent-head .a-glyph {
  width: 34px; height: 34px; border-radius: 9px; flex: none; display: grid; place-items: center; color: #fff;
  background: linear-gradient(135deg, var(--accent), var(--accent-2)); font-family: var(--display); font-weight: 700;
}
.agent-head .a-title { font-family: var(--display); font-size: 16px; }
.agent-head .a-sub { font-size: 11.5px; color: var(--muted); }
.agent-head .a-badge { margin-left: auto; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); border: 1px solid var(--line-2); padding: 4px 9px; border-radius: 999px; }

.agent-body { padding: 18px 20px; min-height: 220px; max-height: 460px; overflow-y: auto; }
.a-empty { color: var(--muted); font-size: 13.5px; text-align: center; padding: 30px 10px; }
.a-empty .ae-big { font-family: var(--display); font-size: 18px; color: var(--ink-soft); margin-bottom: 6px; }

.msg { display: flex; gap: 11px; margin-bottom: 18px; animation: fade .25s ease; }
.msg .m-av { width: 28px; height: 28px; border-radius: 8px; flex: none; display: grid; place-items: center; font-size: 11px; font-weight: 700; }
.msg.user .m-av { background: var(--ink); color: var(--bg); }
.msg.bot  .m-av { background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff; font-family: var(--display); }
.msg .m-body { flex: 1; min-width: 0; }
.msg.user .m-body { font-weight: 600; padding-top: 4px; }
.msg .m-title { font-family: var(--display); font-size: 15.5px; margin: 2px 0 8px; }
.msg .m-body p { margin: 0 0 10px; font-size: 13.5px; line-height: 1.55; }
.a-list { margin: 4px 0 10px; padding-left: 20px; }
.a-list li { font-size: 13px; line-height: 1.5; margin-bottom: 5px; }
.a-foot { font-size: 12.5px; color: var(--muted); font-style: italic; }
.a-table { border-collapse: collapse; margin: 4px 0 12px; font-size: 13px; min-width: 260px; }
.a-table td { padding: 5px 14px 5px 0; border-bottom: 1px solid var(--line); }
.a-table td.num { text-align: right; font-family: var(--mono); }
.pills { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.src-pill { font-size: 10px; font-weight: 600; color: var(--accent); background: var(--accent-bg); padding: 3px 9px; border-radius: 7px; }

.typing { display: inline-flex; gap: 4px; align-items: center; padding: 4px 0; }
.typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); opacity: .3; animation: td 1.4s infinite; }
.typing i:nth-child(2) { animation-delay: .2s; }
.typing i:nth-child(3) { animation-delay: .4s; }
@keyframes td { 0%,20%{opacity:.25} 40%,100%{opacity:1} }

.agent-foot { border-top: 1px solid var(--line); padding: 14px 16px; }
.suggests { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 11px; }
.suggest {
  border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-soft);
  border-radius: 999px; padding: 6px 13px; font-size: 12px; cursor: pointer; font-family: var(--sans);
}
.suggest:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-bg); }
.ask-row { display: flex; gap: 9px; }
.ask-input {
  flex: 1; border: 1px solid var(--line-2); background: var(--surface); border-radius: 10px;
  padding: 11px 14px; font-size: 13.5px; color: var(--ink); font-family: var(--sans); outline: none;
}
.ask-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(47,107,255,.14); }
.ask-send {
  border: none; background: var(--accent); color: #fff; border-radius: 10px; padding: 0 16px;
  cursor: pointer; display: grid; place-items: center;
}
.ask-send:hover { background: var(--accent-2); }
.ask-send svg { width: 17px; height: 17px; }

/* ---- Custom Views ------------------------------------------------------ */
.cv-wrap { display: grid; grid-template-columns: 268px 1fr; gap: 20px; align-items: start; }
.cv-rail { display: flex; flex-direction: column; gap: 9px; position: sticky; top: 78px; }
.cv-newbtn {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
  border: 1px dashed var(--line-2); background: transparent; color: var(--accent);
  border-radius: var(--radius-sm); padding: 11px; cursor: pointer; font-family: var(--sans);
  font-size: 13px; font-weight: 600;
}
.cv-newbtn:hover { border-color: var(--accent); background: var(--accent-bg); }
.cv-newbtn svg { width: 15px; height: 15px; }
.cv-vcard {
  text-align: left; border: 1px solid var(--line); background: var(--surface); border-radius: var(--radius-sm);
  padding: 12px 14px; cursor: pointer; box-shadow: var(--shadow); display: block; width: 100%;
}
.cv-vcard:hover { border-color: var(--line-2); }
.cv-vcard.active { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent), var(--shadow); }
.cvv-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cvv-name { font-family: var(--display); font-size: 14px; font-weight: 600; color: var(--ink); }
.cvv-tag { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px; padding: 2px 7px; border-radius: 8px; }
.cvv-tag.shared  { background: var(--accent-bg); color: var(--accent); }
.cvv-tag.private { background: var(--surface-2); color: var(--muted); }
.cvv-desc { font-size: 11.5px; color: var(--muted); margin: 6px 0 8px; line-height: 1.4; }
.cvv-owner { display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--ink-soft); }
.avatar.mini { width: 20px; height: 20px; font-size: 8.5px; border-radius: 50%; }

.cv-main { min-width: 0; }
.cv-head { border-bottom: 1px solid var(--line); padding-bottom: 16px; margin-bottom: 18px; }
.cv-h-top { display: flex; align-items: center; gap: 12px; }
.cv-head h3 { font-family: var(--display); font-size: 22px; font-weight: 600; margin: 0; }
.cv-desc { font-size: 14px; color: var(--ink-soft); margin: 8px 0 10px; }
.cv-owner { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); }
.cv-meta { margin-left: auto; font-size: 11.5px; color: var(--muted); font-family: var(--mono); }
.cv-panel-head { font-size: 11px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--muted); margin: 20px 2px 10px; }

/* U2 (TWAIN-FCON-FEAT-002). The saved-view controls. An addition to the approved
   drawing rather than a redraw of it: without them the D and the U of the CRUD
   are unreachable from the console. Every value below is a token this stylesheet
   already defines, so both themes are covered and no new colour enters the
   palette. They appear only on a view the signed-in account owns. */
.cv-actions { margin-left: auto; display: flex; gap: 7px; }
.cv-act {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid var(--line-2); background: var(--surface); color: var(--ink-soft);
  border-radius: var(--radius-sm); padding: 5px 10px;
  font-family: var(--sans); font-size: 11.5px; font-weight: 600;
}
.cv-act svg { width: 13px; height: 13px; }
.cv-act:hover { border-color: var(--accent); color: var(--accent); }
.cv-act.danger:hover { border-color: var(--red); color: var(--red); background: var(--red-bg); }
.cv-act:disabled { opacity: .5; cursor: progress; }

/* A failed save or delete, said on the panel. Same shape as the sign-in error
   for the same reason: this is the other place on the console where a person
   pressed something and the API refused. */
.cv-error:not(:empty) {
  font-size: 12px; line-height: 1.45; color: var(--red);
  background: var(--red-bg); border-radius: var(--radius-sm);
  padding: 8px 10px; margin-bottom: 14px;
}

/* Disabled rather than hidden while the views feed is not live. A control that
   disappears reads as a feature nobody built; one that visibly refuses, with
   the reason on its tooltip, reads as a console that is unwell. */
.cv-newbtn:disabled { cursor: not-allowed; color: var(--muted); border-style: dashed; }
.cv-newbtn:disabled:hover { border-color: var(--line-2); background: transparent; }

.cv-kpis { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 16px; }
.kpi { border: 1px solid var(--line); background: var(--surface); border-radius: var(--radius-sm); padding: 13px 15px; box-shadow: var(--shadow); }
.kpi .k-name { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin-bottom: 8px; }
.kpi .k-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.kpi .k-val { font-family: var(--mono); font-size: 19px; font-weight: 700; }
.kpi .k-chg { font-family: var(--mono); font-size: 12.5px; font-weight: 700; }
.kpi .k-spark { margin-top: 8px; }
.cv-main .grid-card { margin-top: 4px; }

/* ---- Modal ------------------------------------------------------------- */
.modal-overlay {
  position: fixed; inset: 0; z-index: 80; background: rgba(11,27,43,.44);
  backdrop-filter: blur(3px); display: grid; place-items: center; padding: 20px; animation: fade .18s ease;
}
.modal {
  background: var(--surface); border: 1px solid var(--line-2); border-radius: 16px;
  box-shadow: var(--shadow-lg); width: 100%; max-width: 460px; padding: 22px 24px; animation: pop .16s ease-out;
}
.modal-head { display: flex; align-items: center; justify-content: space-between; }
.modal-head h3 { font-family: var(--display); font-size: 18px; font-weight: 600; margin: 0; }
.modal-x { border: none; background: none; color: var(--muted); font-size: 16px; cursor: pointer; padding: 4px; }
.modal-x:hover { color: var(--ink); }
.modal-sub { font-size: 12.5px; color: var(--muted); margin: 6px 0 16px; line-height: 1.45; }
.mlabel { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); margin: 0 0 7px; }
.modal .ask-input { width: 100%; margin-bottom: 16px; }
.mcats { display: grid; grid-template-columns: 1fr 1fr; gap: 7px 12px; margin-bottom: 16px; }
.mcat { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ink-soft); cursor: pointer; }
.mcat input { accent-color: var(--accent); width: 15px; height: 15px; }
.mswitch { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--ink-soft); cursor: pointer; margin-bottom: 20px; }
.mswitch input { accent-color: var(--accent); width: 16px; height: 16px; }
.modal-foot { display: flex; justify-content: flex-end; gap: 10px; }
.btn-primary {
  border: none; background: var(--accent); color: #fff; border-radius: 9px; padding: 9px 18px;
  font-size: 13px; font-weight: 600; cursor: pointer; font-family: var(--sans);
}
.btn-primary:hover { background: var(--accent-2); }

/* ---- misc / responsive ------------------------------------------------- */
.grid-2 { display: grid; grid-template-columns: 1.6fr 1fr; gap: 20px; align-items: start; }

#menu-btn { display: none; }
@media (max-width: 720px) { #menu-btn { display: inline-flex; } }

@media (max-width: 1080px) {
  .stat-row, .movers, .commod-grid, .watch-grid, .cv-kpis { grid-template-columns: repeat(2, 1fr); }
  .news-cols, .grid-2 { grid-template-columns: 1fr; }
  .cv-wrap { grid-template-columns: 1fr; }
  .cv-rail { position: static; flex-direction: row; flex-wrap: wrap; }
  .cv-rail .cv-vcard, .cv-newbtn { flex: 1 1 200px; }
}
@media (max-width: 720px) {
  .app { grid-template-columns: 1fr; }
  .side { position: fixed; left: -240px; transition: left .2s; z-index: 60; }
  .side.open { left: 0; }
  .stat-row, .movers, .commod-grid, .watch-grid { grid-template-columns: 1fr; }
  .content { padding: 16px; }
}

/* ---- W5, the live rates panel (TWAIN-FCON-UI-001) -----------------------
   Added by the port, not by a redesign. Every value below is one of the
   variables already declared at the top of this file, so the approved palette
   is the only palette and light and dark both follow it for free.
   ------------------------------------------------------------------------ */

/* Where a panel's numbers come from, on its header row. */
.cat-badge {
  display: inline-block; margin-left: 10px; padding: 2px 8px; border-radius: 9px;
  font-size: 9px; font-weight: 700; letter-spacing: .4px;
  background: var(--line); color: var(--muted);
}
.cat-badge.live   { background: var(--green-bg); color: var(--green); }
.cat-badge.stale  { background: var(--amber-bg); color: var(--amber-tx); }
.cat-badge.demo   { background: var(--surface);  color: var(--muted); border: 1px solid var(--line-2); }

/* The banner over the grid. Says which numbers are real before a reader reads
   any of them. */
.live-note {
  background: var(--accent-bg); color: var(--ink-soft); border: 1px solid var(--line-2);
  border-radius: 11px; padding: 11px 14px; margin: 0 2px 14px;
  font-size: 12.5px; line-height: 1.5;
}
.live-note b { color: var(--ink); }
.live-note.stale  { background: var(--amber-bg); color: var(--amber-tx); }
.live-note.stale b { color: var(--amber-tx); }
.live-note.failed { background: var(--red-bg); color: var(--red); }
.live-note.failed b { color: var(--red); }

/* A metric that is on the board with no number behind it yet. */
.awaiting {
  font-family: var(--sans); font-weight: 500; font-size: 11.5px;
  color: var(--muted); font-style: italic;
}
table.grid tr.pending td { opacity: .78; }

/* A row V1 does not carry at all. It recedes rather than disappearing: hiding it
   would also hide that Twain chose Option B, and a console listing 69 metrics
   would disagree with the 139-row coverage sheet they approved. So the row stays
   on the board, tinted back from the live rows, and says which it is.

   **Tinted rather than dimmed, and that is an accessibility decision.** The first
   draft used `opacity: .58` on the row, which put "not in V1" at 1.98 against the
   card and the badge at 2.43, well under the 4.5 floor for normal text. These are
   new furniture rather than the approved mockup's, so the floor applies to them
   rather than the rule about not redrawing the client's look.

   **The opacity is switched off rather than merely not added**, which is the part
   the first fix got wrong. Every one of these rows is emitted as `pending
   out-of-scope`, so `tr.pending td` above was still compositing the text and the
   tint over the card and holding the badge at 4.25. Recession is carried by the
   ground here and the text is left alone: `--ink-soft` on this tint measures 7.92
   in the light theme and 10.49 in the dark, and the amber badge 7.50 and 8.28.

   The tint is `--bg` and deliberately not `--surface-2`, which is the category
   header's fill six rules above: a header and a metric row should not share a
   ground. TWAIN-FCON-UI-003. */
table.grid tr.pending.out-of-scope td { opacity: 1; background: var(--bg); }

/* The reason under the metric name. `.cav` is the approved mockup's caveat face
   and stays exactly as it is on every live row; this overrides it only where the
   text is UI-003's own. The explanation is the entire reason these rows are still
   on the board, so it is the last thing that should be hard to read. */
table.grid tr.out-of-scope td.metric .cav { color: var(--ink-soft); }

/* "not in V1" is a fact about scope rather than a pending state, so it drops the
   italic that marks a waiting row and takes a face that can actually be read. */
.awaiting.out { font-style: normal; color: var(--ink-soft); }

/* The scope badge, beside the tier badge. Quieter than all four of them, because
   a tier is a claim about a number that exists and this is a note about one that
   does not, and quiet here is a lighter ground rather than fainter text. */
.pill.scope { background: var(--surface); color: var(--ink-soft); border: 1px solid var(--line-2); }

/* The amber ground separates an open coverage gap from a contractual exclusion at
   a glance. The text on it is `--ink-soft` and deliberately not `--amber-tx`,
   which is the pair `.pill.proxy` uses and measures 3.87 on this ground: that
   combination is the approved mockup's and stays where it is, and a new element
   does not get to inherit a value below the floor. */
.pill.scope.no_free_source { background: var(--amber-bg); border-color: transparent; }

/* The pinned tile, same three answers as the grid row. `.no-range` is the tile's
   own footnote face and carries the reason here, so it takes `--ink-soft` for the
   reason `.cav` does: 8.14 and 7.75 against `--muted`'s 3.31 and 4.44. */
.kpi.pending.out-of-scope { background: var(--surface-2); border-radius: 8px; }
.kpi.pending.out-of-scope .no-range { color: var(--ink-soft); }

/* The range marker. It replaces the demo sparkline on a live row, because the
   snapshot carries no history and a drawn trend over a real number would be an
   invention. Track is the trailing-year low to high, tick is the mean, dot is
   the spot. */
.range { display: inline-block; vertical-align: middle; overflow: visible; }
.range .r-track { stroke: var(--line-2); stroke-width: 2; stroke-linecap: round; }
.range .r-cap   { stroke: var(--line-2); stroke-width: 1.5; stroke-linecap: round; }
.range .r-mean  { stroke: var(--muted); stroke-width: 1.5; stroke-linecap: round; opacity: .7; }
.range .r-spot  { fill: var(--accent); }
.no-range { font-size: 11px; color: var(--muted); font-style: italic; }

/* The legend key for it. */
.legend .range-key {
  width: 22px; height: 9px; border-radius: 3px;
  background: linear-gradient(to right, var(--line-2) 45%, var(--accent) 45%, var(--accent) 62%, var(--line-2) 62%);
}

.kpi.live .k-spark { display: flex; align-items: center; min-height: 30px; }
.kpi.pending .k-val { font-size: 14px; }

/* ---- B7, the rest of the console goes live (TWAIN-FCON-UI-002) ----------
   Same rule as the W5 block above: every value is one of the variables
   declared at the top of this file, so the approved palette stays the only
   palette and both themes follow it for free. Nothing here restyles a demo
   element; each selector needs a `.live` or a state class to apply.
   ------------------------------------------------------------------------ */

/* How much of a category is computed, beside its Live badge. The board is 43
   of 139 and the shape of that is per category, so this is where the coverage
   story is actually readable. */
.cat-count {
  margin-left: 8px; font-family: var(--sans); font-weight: 500;
  font-size: 10px; color: var(--muted); letter-spacing: 0;
  text-transform: none;
}

/* A pinned tile whose metric the live board does not carry under that name. */
.kpi.missing .no-range { display: block; line-height: 1.4; }

/* ---- live commodity cards ----------------------------------------------
   A live card carries no change cell and no sparkline, because the commodity
   table holds neither a prior close nor a window. What is missing says so
   instead of being drawn. */
.commod.unpriced { border-style: dashed; }
.commod .c-spot.none {
  font-family: var(--sans); font-size: 15px; font-weight: 500;
  color: var(--muted); font-style: italic;
}
.commod .c-fut b.none {
  font-family: var(--sans); font-weight: 500; font-style: italic; color: var(--muted);
}
.commod.live .c-spark { display: flex; align-items: center; min-height: 44px; }
.commod.live .c-spark .no-range { line-height: 1.4; }
.commod.live .c-row { min-height: 18px; }

/* ---- live news cards ----------------------------------------------------
   Two fields the approved demo had no place for: Claude's one-line summary,
   and the story itself. The headline links out because a tiered headline a
   reader cannot go and check is worth less than one they can. */
.news-item .ni-head a { color: inherit; text-decoration: none; }
.news-item .ni-head a:hover { color: var(--accent); text-decoration: underline; }
.news-item .ni-sum {
  margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--line);
  font-size: 11.5px; line-height: 1.5; color: var(--muted);
}
.news-item.empty {
  border-style: dashed; background: transparent; box-shadow: none;
}
.news-item.empty .ni-head { font-size: 11.5px; color: var(--muted); font-style: italic; }

/* ---- the sign-in gate (U1) ----------------------------------------------
   The console is behind a login from U1, and this is the one screen a person
   sees before there is a session. Ref: web/assets/auth.js.

   Built entirely from the tokens above. No new colour, no new typeface: the
   look was client-approved and W5 ported it close to verbatim on purpose, so a
   screen the approval did not cover should still be unmistakably the same
   product. The card borrows the sidebar's navy for its mark and the board's
   surface, line and accent for everything else. */
#login {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 24px; background: var(--bg);
}
#login[hidden] { display: none; }

/* `.app` is a grid, and `display: grid` beats the `hidden` attribute's own
   `display: none`. Without this the board paints behind the gate. */
.app[hidden] { display: none; }

.login-card {
  width: 100%; max-width: 360px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  padding: 30px 28px 24px;
}
.login-mark {
  width: 40px; height: 40px; border-radius: 10px; margin-bottom: 16px;
  display: flex; align-items: center; justify-content: center;
  background: var(--side-bg);
}
.login-mark .glyph {
  font-family: var(--display); font-weight: 700; font-size: 19px; color: #fff;
}
.login-card h1 {
  font-family: var(--display); font-size: 21px; font-weight: 600;
  color: var(--ink); margin: 0;
}
.login-sub { font-size: 12.5px; color: var(--muted); margin: 4px 0 20px; }

/* Why the gate is up when it is not simply "you are not signed in": a session
   that expired mid-use, a sign-out, or an API that answered something odd. */
.login-note {
  font-size: 12px; line-height: 1.5; color: var(--ink-soft);
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 9px 11px; margin-bottom: 16px;
}

.login-card label {
  display: block; font-size: 11px; font-weight: 600; letter-spacing: .02em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.login-card input {
  width: 100%; box-sizing: border-box; margin-bottom: 14px;
  padding: 10px 12px; font-family: var(--sans); font-size: 14px;
  color: var(--ink); background: var(--surface);
  border: 1px solid var(--line-2); border-radius: var(--radius-sm);
}
.login-card input:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-bg);
}

/* Empty until there is something to say, and it holds no height when empty so
   the button does not jump down the card on the first failed attempt. */
.login-error:not(:empty) {
  font-size: 12px; line-height: 1.45; color: var(--red);
  background: var(--red-bg); border-radius: var(--radius-sm);
  padding: 8px 10px; margin-bottom: 12px;
}

.login-card button {
  width: 100%; padding: 11px; cursor: pointer;
  font-family: var(--sans); font-size: 14px; font-weight: 600; color: #fff;
  background: var(--accent); border: none; border-radius: var(--radius-sm);
}
.login-card button:hover { background: var(--accent-2); }
.login-card button:disabled { opacity: .6; cursor: default; }

.login-foot {
  font-size: 11.5px; line-height: 1.5; color: var(--muted);
  margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--line);
}

/* The user menu gains one item at U1: signing out. It is separated from the
   switcher above it because it is the one entry that ends the session rather
   than changing what the page shows. */
.user-menu .um-signout {
  border-top: 1px solid var(--line); margin-top: 4px; padding-top: 8px;
}
.user-menu .um-signout .um-name { color: var(--red); }

/* U4. The switcher lists the firm's real accounts, so three things the approved
   drawing never needed:

   `.um-chip` is the access level beside a name. `role` is a job title and goes
   under the name where the mockup drew it; whether somebody may change the firm's
   watchlist is a different fact and gets its own mark. The Hermes variant reuses
   `--accent` so it reads as the same badge the user chip already carries.

   `.um-note` is the line saying what this list is. It matters most when it is
   saying the list is demo data, so the failed state borrows the red the console
   uses everywhere else for the same statement.

   `.badge-manager` is the user chip's own, next to `.badge-admin`, in the line
   colour rather than the accent so two chips side by side stay legible. */
.user-menu .um-chip {
  margin-left: 6px; font-size: 8.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; padding: 1px 6px; border-radius: 7px; vertical-align: middle;
  color: var(--muted); background: var(--surface-2); border: 1px solid var(--line-2);
}
.user-menu .um-chip.admin { color: #fff; background: var(--accent); border-color: transparent; }
.user-menu .um-note {
  font-size: 10.5px; line-height: 1.45; color: var(--muted);
  padding: 8px 10px 4px; border-top: 1px solid var(--line); margin-top: 4px;
}
.user-menu .um-note.failed, .user-menu .um-note.stale { color: var(--red); }
.badge-manager {
  display: inline-block; margin-left: 7px; font-size: 8.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .5px; padding: 1px 6px; border-radius: 7px;
  vertical-align: middle; color: var(--muted); background: var(--surface-2);
  border: 1px solid var(--line-2);
}

/* ---- UI-004, the panels fold (TWAIN-FCON-UI-004) ------------------------
   The eleven category headers on the board fold, so a page of 139 metrics can be
   scanned. An addition to the approved drawing rather than a redraw of it: the
   header row keeps its ground, its type and its badges, and gains a chevron.
   Every colour below is a token declared at the top of this file, the rule every
   block since W5 has kept. Ref: web/assets/panels.js.
   ------------------------------------------------------------------------ */

/* The whole header row is the control, so the padding moves from the cell to
   the button inside it and a click anywhere on the row folds the panel. The
   button takes the row's face rather than a button's own, which is why most of
   what follows is `inherit`. */
table.grid tr.cat td { padding: 0; }
.cat-toggle {
  display: block; width: 100%; margin: 0; padding: 11px 12px;
  border: 0; background: none; cursor: pointer; text-align: left;
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
}
.cat-toggle svg {
  width: 14px; height: 14px; margin-right: 6px; vertical-align: -3px;
  color: var(--ink-soft); transition: transform 120ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.cat-toggle[aria-expanded="false"] svg { transform: rotate(-90deg); }
.cat-toggle:hover .cat-name { color: var(--accent-2); }

/* Drawn on keyboard focus and not on a click, and inside the cell rather than
   around it, because `.grid-card` scrolls sideways and would clip an outline
   drawn outside the row. */
.cat-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* How many rows a folded panel is holding. Drawn only while it is folded: open,
   the rows themselves are the count. `--ink-soft` rather than `--muted`, for the
   reason UI-003's notes under a metric name use it, which is that `--muted` at
   this size is under the contrast floor. */
.cat-folded {
  display: none; margin-left: 8px; font-weight: 500; font-size: 10px;
  letter-spacing: 0; text-transform: none; color: var(--ink-soft);
}
.cat-toggle[aria-expanded="false"] .cat-folded { display: inline; }

/* Expand all, Collapse all, and the line saying whether a fold is remembered. */
.grid-tools {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 2px 10px;
}
.grid-tools .tb-btn { padding: 5px 10px; font-size: 12px; }
.grid-tools-note {
  flex: 1 1 260px; margin-left: 4px; font-size: 12px; line-height: 1.45; color: var(--ink-soft);
}

@media (prefers-reduced-motion: reduce) {
  .cat-toggle svg { transition: none; }
}
