/* The shared design system.
   The palette and type scale are mirrored in theme.py, which builds the Plotly figures - those
   cannot read a CSS variable. Everything a stylesheet can own lives here. */

@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600&family=Inter:wght@400;450;500;600&family=JetBrains+Mono:wght@400;500&display=swap');

:root {
  --px-bg: #F4F5F0;
  --px-surface: #FFFFFF;
  --px-sunk: #FAFBF7;
  --px-border: rgba(21, 51, 31, 0.16);
  --px-border-strong: rgba(21, 51, 31, 0.34);
  --px-primary: #15331F;
  --px-text: #15331F;
  --px-muted: rgba(21, 51, 31, 0.70);
  --px-faint: rgba(21, 51, 31, 0.50);
  --px-font-display: 'DM Sans', 'Segoe UI', system-ui, sans-serif;
  --px-font-body: 'Inter', 'Segoe UI', system-ui, sans-serif;
  --px-font-mono: 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;
  --px-radius: 10px;
  --px-gap: 18px;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--px-bg);
  color: var(--px-text);
  font-family: var(--px-font-body);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

* { box-sizing: border-box; }

a { color: var(--px-primary); text-decoration: none; border-bottom: 1px solid var(--px-border-strong); }
a:hover { border-bottom-color: var(--px-primary); }

.px-mono { font-family: var(--px-font-mono); font-variant-ligatures: none; }

/* ── Shell ───────────────────────────────────────────────────────────────── */

.px-shell { min-height: 100vh; display: flex; flex-direction: column; }

.px-header {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 20px;
  padding: 12px 32px;
  background: rgba(244, 245, 240, 0.92);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--px-border);
}

.px-brand { display: flex; align-items: center; gap: 10px; border: none; }
.px-brand-name {
  font-family: var(--px-font-display); font-weight: 600; font-size: 15px;
  letter-spacing: -0.01em; color: var(--px-primary);
}
.px-brand-sub { font-family: var(--px-font-mono); font-size: 10px; color: var(--px-faint); letter-spacing: 0.04em; }

.px-nav { display: flex; gap: 4px; margin-left: 12px; }
.px-nav-link {
  padding: 5px 12px; border-radius: 999px; border: none;
  font-size: 13px; font-weight: 450; color: var(--px-muted);
}
.px-nav-link:hover { background: rgba(21, 51, 31, 0.05); color: var(--px-text); border: none; }
.px-nav-link.px-nav-active { background: var(--px-primary); color: #F4F5F0; }

.px-header-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.px-main { flex: 1; padding: 26px 32px 64px; max-width: 1600px; width: 100%; margin: 0 auto; }

/* `theme.busy` wraps a region in a spinner, and dcc.Loading's DOM is worth knowing about: it puts
   the children in a div of their own, adds an *empty sibling* for the spinner, and repeats
   `parent_className` on both the outer node and the content node. So a layout class given to it
   lands twice, and without this the empty spinner is an equal flex child that takes half the room -
   which is how the field picker and the table each ended up at half their width. */
.px-busy { display: flex; min-width: 0; min-height: 0; }
.px-busy > :first-child { flex: 1; min-width: 0; min-height: 0; }
.px-busy > :last-child:not(:first-child) { flex: 0 0 0; }

.px-footer {
  padding: 18px 32px; border-top: 1px solid var(--px-border);
  font-size: 11px; color: var(--px-faint); font-family: var(--px-font-mono);
}

/* ── Type ────────────────────────────────────────────────────────────────── */

.px-page-title {
  font-family: var(--px-font-display); font-size: 26px; font-weight: 600;
  letter-spacing: -0.02em; margin: 0 0 4px;
}
.px-page-sub { color: var(--px-muted); margin: 0 0 20px; font-size: 13.5px; max-width: 78ch; }

.px-section-head { margin: 0 0 12px; }
.px-section-title { font-family: var(--px-font-display); font-size: 14px; font-weight: 600; margin: 0; letter-spacing: -0.005em; }
.px-section-note { font-size: 12px; color: var(--px-muted); margin: 3px 0 0; max-width: 84ch; line-height: 1.5; }

.px-eyebrow {
  font-family: var(--px-font-mono); font-size: 10px; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--px-faint); margin-bottom: 6px;
}

/* ── Surfaces ────────────────────────────────────────────────────────────── */

.px-card {
  background: var(--px-surface);
  border: 1px solid var(--px-border);
  border-radius: var(--px-radius);
  padding: 16px 18px;
}

.px-grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--px-gap); }
.px-grid-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--px-gap); }
.px-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.px-stack { display: flex; flex-direction: column; gap: var(--px-gap); }

/* Prose beside the figure it describes. `.px-grid-2` puts whole cards side by side; this splits
   one card. The figure gets the larger share, and below 1100px there is no room for two. */
.px-split {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: var(--px-gap);
  align-items: center;
}

/* Bounded by its column now, so the 74ch cap would only reintroduce the gap it is meant to close. */
.px-split .px-prose { max-width: none; }

@media (max-width: 1100px) {
  .px-split { grid-template-columns: 1fr; }
}

/* ── Stats ───────────────────────────────────────────────────────────────── */

.px-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 1px; background: var(--px-border);
  border: 1px solid var(--px-border); border-radius: var(--px-radius); overflow: hidden; }
.px-stat { background: var(--px-surface); padding: 14px 18px 16px; }
.px-stat-label {
  font-family: var(--px-font-mono); font-size: 10px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--px-faint);
}
.px-stat-value { font-family: var(--px-font-display); font-size: 25px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.25; }
.px-stat-note { font-size: 11.5px; color: var(--px-muted); line-height: 1.45; margin-top: 2px; }

/* ── Badges ──────────────────────────────────────────────────────────────── */

.px-badge {
  display: inline-block; border-radius: 5px; padding: 2px 8px;
  font-family: var(--px-font-mono); font-size: 10.5px; font-weight: 500;
  letter-spacing: 0.03em; white-space: nowrap;
}

/* ── Key/value ───────────────────────────────────────────────────────────── */

.px-kv { padding: 9px 0; border-bottom: 1px solid var(--px-border); }
.px-kv:last-child { border-bottom: none; }
.px-kv-label {
  font-family: var(--px-font-mono); font-size: 10px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--px-faint);
}
.px-kv-value { font-size: 14px; margin-top: 1px; word-break: break-word; }
.px-kv-note { font-size: 11.5px; color: var(--px-muted); margin-top: 1px; }

/* ── Empty states ────────────────────────────────────────────────────────── */

.px-empty {
  border: 1px dashed var(--px-border-strong); border-radius: var(--px-radius);
  padding: 28px 24px; text-align: center; background: var(--px-sunk);
}
.px-empty-title { font-family: var(--px-font-display); font-size: 13.5px; font-weight: 500; color: var(--px-muted); }
.px-empty-reason { font-size: 12.5px; color: var(--px-faint); margin: 5px auto 0; max-width: 56ch; line-height: 1.5; }

/* ── Panel tabs ──────────────────────────────────────────────────────────── */

.px-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--px-border); margin-bottom: 18px; flex-wrap: wrap; }
.px-tab {
  padding: 8px 14px; font-size: 13px; color: var(--px-muted); cursor: pointer;
  border: none; background: none; border-bottom: 2px solid transparent; margin-bottom: -1px;
  font-family: var(--px-font-body);
}
.px-tab:hover { color: var(--px-text); }
.px-tab-active { color: var(--px-primary); font-weight: 500; border-bottom-color: var(--px-primary); }
.px-tab-empty { color: var(--px-faint); }

/* ── Filters ─────────────────────────────────────────────────────────────── */

.px-filters { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; align-items: end; }
.px-field-label {
  font-family: var(--px-font-mono); font-size: 10px; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--px-faint); margin-bottom: 4px; display: block;
}
.px-input {
  width: 100%; padding: 7px 10px; font-size: 13px; font-family: var(--px-font-body);
  border: 1px solid var(--px-border); border-radius: 7px; background: var(--px-surface); color: var(--px-text);
}
.px-input:focus { outline: none; border-color: var(--px-border-strong); }

.px-button {
  padding: 7px 14px; font-size: 13px; font-family: var(--px-font-body);
  border-radius: 7px; border: 1px solid var(--px-border-strong);
  background: var(--px-surface); color: var(--px-text); cursor: pointer;
}
.px-button:hover { background: var(--px-sunk); }
.px-button-primary { background: var(--px-primary); color: #F4F5F0; border-color: var(--px-primary); }
.px-button-primary:hover { background: #1d4429; }

.px-toggle { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--px-text); }

/* Dash dcc.Dropdown overrides, so the controls match the rest of the page. */
.Select-control, .is-focused .Select-control {
  border: 1px solid var(--px-border) !important; border-radius: 7px !important;
  background: var(--px-surface) !important; font-size: 13px; min-height: 34px;
}
.Select-placeholder, .Select-value-label { color: var(--px-text) !important; }
.Select-menu-outer { border-radius: 7px !important; border-color: var(--px-border) !important; font-size: 13px; }
.Select--multi .Select-value {
  background: #D7E4D6 !important; border-color: rgba(27, 69, 41, 0.3) !important;
  color: #1B4529 !important; border-radius: 4px !important;
  font-family: var(--px-font-mono); font-size: 11px;
}

/* ── AG Grid ─────────────────────────────────────────────────────────────── */

.ag-theme-balham {
  --ag-font-family: var(--px-font-body);
  --ag-font-size: 13px;
  --ag-background-color: var(--px-surface);
  --ag-odd-row-background-color: var(--px-surface);
  --ag-row-hover-color: rgba(21, 51, 31, 0.055);
  --ag-header-background-color: var(--px-sunk);
  --ag-header-foreground-color: var(--px-faint);
  --ag-border-color: var(--px-border);
  --ag-row-border-color: var(--px-border);
  --ag-selected-row-background-color: rgba(31, 74, 46, 0.08);
  --ag-foreground-color: var(--px-text);
  --ag-header-height: 34px;
  --ag-row-height: 34px;
  --ag-borders: 1px solid;
  --ag-border-radius: 10px;
}
.ag-theme-balham .ag-header-cell-text {
  font-family: var(--px-font-mono); font-size: 10px;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.ag-theme-balham .ag-root-wrapper { border-radius: var(--px-radius); overflow: hidden; }
.ag-theme-balham .px-cell-mono { font-family: var(--px-font-mono); font-size: 12px; }
.ag-theme-balham .px-cell-num { font-family: var(--px-font-mono); font-size: 12px; text-align: right; }
.ag-theme-balham .px-cell-id { font-family: var(--px-font-mono); font-size: 12px; color: var(--px-primary); font-weight: 500; }
.ag-theme-balham .px-cell-link { color: var(--px-primary); font-weight: 500; }

/* ── Notebook ────────────────────────────────────────────────────────────── */

.px-prose { font-size: 14px; line-height: 1.65; max-width: 74ch; }

/* The introduction runs the width of its card instead of holding the 74ch measure. On a page this
   wide the measure leaves a column of text against an empty half, which reads as a two-column
   layout with one column missing; an opening paragraph is short enough to carry the longer line. */
.px-prose-full { max-width: none; }
.px-prose h1, .px-prose h2, .px-prose h3 { font-family: var(--px-font-display); letter-spacing: -0.01em; }
.px-prose code { font-family: var(--px-font-mono); font-size: 12.5px; background: var(--px-sunk); padding: 1px 4px; border-radius: 4px; }

.px-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.px-table th {
  text-align: left; font-family: var(--px-font-mono); font-size: 10px;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--px-faint);
  border-bottom: 1px solid var(--px-border-strong); padding: 7px 10px 7px 0;
}
.px-table td { padding: 7px 10px 7px 0; border-bottom: 1px solid var(--px-border); vertical-align: top; }
.px-table td.px-num { font-family: var(--px-font-mono); text-align: right; padding-right: 0; }

.px-scroll-x { overflow-x: auto; }

/* A prose block that says what it is doing gets the weight that job deserves. Without these a
   caveat, a headline and a table are three identical white cards, and a reader skims all three. */
.px-note {
  border-radius: var(--px-radius);
  padding: 15px 18px 15px 20px;
  border-left: 3px solid var(--px-border-strong);
  background: var(--px-sunk);
}
.px-note .px-prose { margin: 0; }
.px-note .px-prose > :first-child { margin-top: 0; }
.px-note .px-prose > :last-child { margin-bottom: 0; }

/* The TL;DR. Set larger than body and given the page's own ink, because it is the one paragraph
   a reader who opens the page and leaves again will have read. */
.px-note-lead {
  border-left-color: var(--px-primary);
  background: linear-gradient(90deg, rgba(46,125,70,0.08), rgba(46,125,70,0.02));
}
.px-note-lead .px-prose { font-size: 15.5px; line-height: 1.6; max-width: 68ch; color: var(--px-text); }

/* The claims. A card rather than a tint, because it is the body of the report. */
.px-note-finding {
  background: var(--px-surface);
  border: 1px solid var(--px-border);
  border-left: 3px solid #2E7D46;
}
.px-note-finding .px-prose ul { margin: 0; padding-left: 18px; }
.px-note-finding .px-prose li { margin: 0 0 7px 0; }
.px-note-finding .px-prose li:last-child { margin-bottom: 0; }

/* What the analysis could not measure. Amber, never red: nothing here is an error, it is a
   qualification on a number - the same reason `theme.TONES` puts `caution` in amber. */
.px-note-caution { border-left-color: #C8860D; background: rgba(247, 212, 141, 0.16); }
.px-note-note { border-left-color: var(--px-border-strong); }

/* A figure sits in lighter chrome than prose, so a page reads as sections rather than a stack of
   identical boxes. */
.px-card-figure { background: var(--px-sunk); }

/* ── Loading ─────────────────────────────────────────────────────────────── */

.px-skeleton {
  background: linear-gradient(90deg, var(--px-sunk) 25%, rgba(21,51,31,0.06) 50%, var(--px-sunk) 75%);
  background-size: 200% 100%; animation: px-shimmer 1.4s infinite; border-radius: 6px;
}
@keyframes px-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

@media (max-width: 720px) {
  .px-header { padding: 10px 16px; flex-wrap: wrap; }
  .px-main { padding: 18px 16px 48px; }
}

/* ── Assistant ───────────────────────────────────────────────────────────── */

.px-transcript { display: flex; flex-direction: column; gap: 14px; margin-bottom: 18px; }
.px-msg { border-radius: var(--px-radius); padding: 14px 18px; border: 1px solid var(--px-border); }
.px-msg-user { background: var(--px-sunk); align-self: flex-end; max-width: 72%; }
.px-msg-assistant { background: var(--px-surface); }
.px-msg .px-card { border: none; padding: 0; margin-top: 12px; }
.px-msg .px-prose { margin: 4px 0 0; }

/* ── Structure viewer ────────────────────────────────────────────────────────
   Moves with `ui/structure_view/`. Nothing here reaches into Mol*'s own markup: what the canvas
   looks like is set through the library's parameters, because WebGL cannot read a CSS variable.
   Only the canvas height is an inline style, since it is a per-instance config value. */

.px-sv { display: flex; flex-direction: column; gap: 10px; }
.px-sv-toolbar { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.px-sv-btn {
  font-family: var(--px-font-mono); font-size: 11px; padding: 5px 10px; cursor: pointer;
  background: var(--px-surface); color: var(--px-text); border: 1px solid var(--px-border);
  border-radius: 6px; line-height: 1.3; text-decoration: none; display: inline-block;
}
.px-sv-btn:hover { background: var(--px-sunk); border-color: var(--px-border-strong); }
.px-sv-btn-off { color: var(--px-faint); background: var(--px-sunk); }
.px-sv-canvas {
  width: 100%; border: 1px solid var(--px-border); border-radius: var(--px-radius); overflow: hidden;
}
.px-sv-chains { display: flex; gap: 6px; flex-wrap: wrap; }
.px-sv-note { font-size: 12px; color: var(--px-muted); margin: 0; line-height: 1.5; max-width: 84ch; }
.px-sv-metrics { display: flex; gap: 22px; flex-wrap: wrap; margin-top: 6px; }
.px-sv-metric-label {
  font-family: var(--px-font-mono); font-size: 10px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--px-faint);
}
.px-sv-metric-value { font-family: var(--px-font-display); font-size: 16px; margin-top: 2px; }

.px-sv-title { font-size: 12px; color: var(--px-muted); margin-bottom: 6px; }
.px-sv-picker { max-width: 420px; margin-bottom: 4px; }

/* Ours rather than Mol*'s `layoutIsExpanded`, which is fixed when the component mounts. */
.px-sv-expanded {
  position: fixed; inset: 0; z-index: 60; background: var(--px-bg); padding: 18px; overflow: auto;
}
.px-sv-expanded .px-sv-canvas { height: calc(100vh - 150px) !important; }

/* dash-bio titles the conservation bar's axis "Bar weights" whenever that bar is the only one
   shown, and exposes no prop to rename or remove it - it is a Plotly axis title rendered inside the
   component. Plotly wraps every axis title in a `g-<axis>title` group, which is the only handle
   there is. Scoped to the alignment, where the bar axis is the one titled thing. */
.px-alignment g[class$="title"] { display: none; }
