/* ==========================================================================
   REPORT BUILDER + BACKTEST SANDBOX                          [F09, F24 · Y12]
   Package Y12. Loads AFTER static/instrument.css.
   --------------------------------------------------------------------------
   Covers three things with one sheet, because they are one feature:

     .sgrb*   the report composer  (frontend/report_builder.js)
     .sgrb*   the rendered report preview, whose markup comes from
              app/services/report_builder.py and uses the SAME prefix on
              purpose — the composer and the document it produces should not
              look like two products
     .sgbt*   the backtest sandbox (frontend/backtest.js)

   --------------------------------------------------------------------------
   WHY EVERY CLASS NAME HERE IS HYPHEN-FREE camelCase

   static/obsidian_orchid.css and static/instrument.css between them match 180+
   selectors of the form `[class*="-word"]` / `[class$="-word"]` under
   `#app-root`, several with `!important`:

     [class$="-title"] [class$="-label"] [class$="-heading"]  -> uppercase
     [class*="-field"] [class*="-input"] [class*="-search"]   -> input chrome
     [class*="-value"] [class*="-metric"] [class*="-num"]     -> tabular figures
     [class*="-tile"] [class*="-chip"] [class*="-pane"]       -> pill geometry

   A hyphen-free prefix makes that whole family unmatchable BY CONSTRUCTION, so
   `sgbtField` is not an input, `sgrbBlockTitle` is not uppercased, and nothing
   here can be silently restyled by a sheet that never heard of this package.
   The consequence is that this file must set what it wants explicitly — which
   is the trade it is making deliberately.

   THE ONE THING IT DOES NOT FIGHT: real `<input>`, `<select>` and `<textarea>`
   elements ARE styled by the bare element selectors with `!important`, and
   that is the house field chrome. This sheet sets only their box size, which
   those rules do not touch.

   --------------------------------------------------------------------------
   NO RAW HEX ANYWHERE. static/instrument.css is the authoritative token layer
   and is the only file in this project allowed a colour literal. Every colour
   below is a `var(--i-*)` / `var(--oo-*)`.

   NO `@media print` BLOCK. The in-app print stylesheet is another package's
   file. What this package supplies are the hooks it targets:
   `[data-sgrbprintable]` on the preview container, `[data-sgrbblock]` on every
   block and `[data-sgrbbreak]` on a page break. The DOWNLOADED report is a
   standalone file that carries its own print rules from report_builder.py and
   needs nothing from here.
   ========================================================================== */

/* ==========================================================================
   1 — SHARED SHELL
   ========================================================================== */

.sgrbRoot,
.sgbtRoot {
  display: flex;
  flex-direction: column;
  gap: 18px;
  color: var(--i-ink-2);
  font-family: var(--oo-font-ui);
  font-size: var(--i-t-body);
  line-height: 1.55;
}

.sgrbHead,
.sgbtHead {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--i-hair);
}

.sgrbHeadline,
.sgbtHeadline {
  margin: 0;
  font-size: var(--i-t-xl);
  font-weight: 600;
  letter-spacing: var(--i-track-tight);
  color: var(--i-ink-1);
}

.sgrbRule,
.sgbtLede {
  margin: 0;
  max-width: 78ch;
  color: var(--i-ink-3);
  font-size: var(--i-t-sm);
}

.sgrbStatus,
.sgbtStatus {
  margin: 0;
  min-height: 1.2em;
  font-size: var(--i-t-sm);
  color: var(--i-ink-3);
}

.sgrbStatus[data-sgrbtone="ok"],
.sgbtStatus[data-sgbttone="ok"] { color: var(--i-bull); }

.sgrbStatus[data-sgrbtone="warn"],
.sgbtStatus[data-sgbttone="warn"] { color: var(--i-amber); }

.sgrbCard,
.sgbtCard,
.sgbtStanding,
.sgbtFriction {
  background: var(--i-surface-1);
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-card);
  box-shadow: var(--i-elev-1);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sgrbCardHeadline,
.sgbtCardHeadline {
  margin: 0;
  font-size: var(--i-t-xs);
  font-weight: 600;
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  color: var(--i-ink-3);
}

.sgrbHint,
.sgbtHint,
.sgrbFieldHint,
.sgbtFieldHint {
  margin: 0;
  font-size: var(--i-t-xs);
  line-height: 1.5;
  color: var(--i-ink-3);
}

.sgrbWarn,
.sgbtWarn {
  margin: 0;
  font-size: var(--i-t-sm);
  color: var(--i-amber);
}

.sgrbEmptyState,
.sgbtEmptyState {
  border: 1px dashed var(--i-hair-strong);
  border-radius: var(--i-r-control);
  padding: 16px 18px;
  color: var(--i-ink-3);
  font-size: var(--i-t-sm);
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sgrbEmptyState p,
.sgbtEmptyState p { margin: 0; }

.sgrbBtnRow,
.sgbtBtnRow {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

/* The bare `#app-root button` rules own the button chrome and carry
   !important; this only sizes the box and the label, which they leave alone. */
.sgrbBtn,
.sgbtBtn {
  font-size: var(--i-t-sm);
  white-space: nowrap;
  cursor: pointer;
}

.sgrbIconBtn { min-width: 2.2em; }

/* ==========================================================================
   2 — FORM FIELDS
   ========================================================================== */

.sgrbField,
.sgbtField {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 12rem;
  flex: 1 1 12rem;
}

.sgrbFieldLabel,
.sgbtFieldLabel {
  font-size: var(--i-t-xs);
  font-weight: 600;
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  color: var(--i-ink-3);
}

.sgrbInput,
.sgbtInput,
.sgrbSelect,
.sgbtSelect,
.sgrbTextarea {
  width: 100%;
  box-sizing: border-box;
}

.sgrbTextarea {
  min-height: 5.5em;
  resize: vertical;
  font-family: var(--oo-font-ui);
}

.sgbtFormRow,
.sgrbInline {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
}

.sgrbInline .sgrbSelect { flex: 0 0 5rem; width: 5rem; }
.sgrbInline .sgrbInput { flex: 1 1 16rem; }

/* ==========================================================================
   3 — THE COMPOSER
   ========================================================================== */

.sgrbColumns {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

@media (min-width: 1100px) {
  .sgrbColumns { grid-template-columns: minmax(0, 4fr) minmax(0, 5fr); }
}

.sgrbCompose,
.sgrbOutput {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.sgrbCaptureList {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sgrbCaptureRow {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
  padding: 8px 10px;
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  background: var(--i-surface-2);
}

.sgrbCaptureName {
  flex: 1 1 12rem;
  min-width: 0;
  color: var(--i-ink-1);
  font-size: var(--i-t-sm);
  font-weight: 600;
}

.sgrbCaptureMeta {
  flex: 2 1 18rem;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  align-items: baseline;
  font-size: var(--i-t-xs);
}

.sgrbTag {
  display: inline-block;
  padding: 1px 7px;
  border: 1px solid var(--i-hair-strong);
  border-radius: var(--i-r-pill);
  font-size: var(--i-t-xs);
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  color: var(--i-ink-3);
  white-space: nowrap;
}

/* The whole point of the feature, in two colours: attributable, or a stated
   gap. There is deliberately no third state that shows a number quietly. */
.sgrbProvOk { margin: 0; color: var(--i-ink-3); font-size: var(--i-t-xs); }
.sgrbProvGap { margin: 0; color: var(--i-amber); font-size: var(--i-t-xs); }

.sgrbBlockRow {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--i-hair);
  border-left: 3px solid var(--i-hair-strong);
  border-radius: var(--i-r-control);
  background: var(--i-surface-2);
}

.sgrbBlockGap { border-left-color: var(--i-amber); }

.sgrbBlockHead {
  display: flex;
  gap: 8px;
  align-items: center;
}

.sgrbBlockIndex {
  font-family: var(--oo-font-data);
  font-variant-numeric: tabular-nums;
  font-size: var(--i-t-xs);
  color: var(--i-ink-4);
  min-width: 1.6em;
}

.sgrbBlockControls {
  display: flex;
  gap: 4px;
  margin-left: auto;
}

.sgrbBlockBody {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.sgrbBlockTitle {
  margin: 0;
  color: var(--i-ink-1);
  font-size: var(--i-t-sm);
  font-weight: 600;
}

.sgrbStatRow,
.sgbtStatRow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: 10px;
}

.sgrbStat,
.sgbtStat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  background: var(--i-surface-2);
  min-width: 0;
}

.sgrbStatLabel,
.sgbtStatLabel {
  font-size: var(--i-t-xs);
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  color: var(--i-ink-3);
}

.sgrbStatValue,
.sgbtStatValue,
.sgbtCellValue {
  font-family: var(--oo-font-data);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: var(--i-t-md);
  color: var(--i-ink-1);
  overflow-wrap: anywhere;
}

/* The sentence that stands in for a figure the engine would not compute. It is
   the same size as a hint, NOT the same size as the number it replaces —
   a missing statistic must not look like a quiet zero. */
.sgbtStatWhy {
  display: block;
  font-family: var(--oo-font-ui);
  font-size: var(--i-t-xs);
  line-height: 1.45;
  color: var(--i-amber);
}

.sgrbSources {
  width: 100%;
  font-size: var(--i-t-xs);
}

/* No `display` on the <details> itself. `display: flex` on a details element
   makes the closed state lay its hidden content out as a flex item in several
   engines, so the box grows when it should be shut. Spacing goes on the
   children instead. */
.sgrbDetails {
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  padding: 8px 12px;
  font-size: var(--i-t-xs);
  color: var(--i-ink-3);
}

.sgrbDetails > summary {
  cursor: pointer;
  color: var(--i-ink-2);
}

.sgrbDetails > summary + * { margin-top: 8px; }
.sgrbDetails > p { margin: 8px 0; }

.sgrbMarkup {
  font-family: var(--oo-font-data);
  font-size: var(--i-t-xs);
  white-space: pre;
  overflow-wrap: normal;
  min-height: 12em;
}

/* ==========================================================================
   4 — THE BACKTEST SANDBOX
   ========================================================================== */

.sgbtFormHost,
.sgbtFrictionHost,
.sgbtResultHost,
.sgbtRefusedHost {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-width: 0;
}

.sgbtStanding { border-left: 3px solid var(--i-orchid); }

.sgbtStandingRow,
.sgbtFrictionRow,
.sgbtDisclosureRow,
.sgbtRefusedRow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 14px;
}

.sgbtStandingItem,
.sgbtFrictionCol,
.sgbtDisclosure,
.sgbtRefused {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.sgbtStandingItem p,
.sgbtFrictionCol p,
.sgbtDisclosure p,
.sgbtRefused p,
.sgbtSpec p {
  margin: 0;
  font-size: var(--i-t-sm);
  line-height: 1.5;
}

/* Two selectors deep on purpose, not `!important`: the `.sgbtStandingItem p`
   rule above is (0,2,0) and would otherwise win the font-size on a <p> that
   also carries this class. Everything with this class lives inside .sgbtRoot,
   so the compound is always satisfied. */
.sgbtRoot .sgbtStandingLabel {
  font-size: var(--i-t-xs);
  font-weight: 600;
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  color: var(--i-ink-1);
}

.sgbtFriction { border-left: 3px solid var(--i-amber); }

.sgbtList {
  margin: 0;
  padding-left: 1.1em;
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-size: var(--i-t-xs);
  color: var(--i-ink-3);
}

.sgbtSpec {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 10px 12px;
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  background: var(--i-surface-2);
}

.sgbtDisclosure {
  padding: 10px 12px;
  border: 1px solid var(--i-hair);
  border-left: 3px solid var(--i-hair-strong);
  border-radius: var(--i-r-control);
  background: var(--i-surface-2);
}

.sgbtDisclosure[data-sgbtseverity="high"] { border-left-color: var(--i-amber); }
.sgbtDisclosure[data-sgbtseverity="medium"] { border-left-color: var(--i-orchid); }

.sgbtRefused {
  padding: 10px 12px;
  border: 1px dashed var(--i-hair-strong);
  border-radius: var(--i-r-control);
}

/* A refusal is a result, so it is presented as one: a full card, not a toast
   and not a red box that reads as a crash. */
.sgbtRefusalCard {
  background: var(--i-surface-1);
  border: 1px solid var(--i-amber);
  border-left: 3px solid var(--i-amber);
  border-radius: var(--i-r-card);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sgbtRefusalBody {
  margin: 0;
  font-size: var(--i-t-md);
  line-height: 1.5;
  color: var(--i-ink-1);
}

.sgbtTable {
  width: 100%;
  font-size: var(--i-t-sm);
}

.sgbtTable th {
  text-align: left;
  color: var(--i-ink-3);
}

.sgbtTable td {
  font-variant-numeric: tabular-nums lining-nums;
  vertical-align: top;
}

.sgbtDetails {
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  padding: 8px 12px;
  font-size: var(--i-t-xs);
  color: var(--i-ink-3);
}

.sgbtDetails > summary {
  cursor: pointer;
  color: var(--i-ink-2);
}

/* ==========================================================================
   5 — THE RENDERED REPORT PREVIEW

   Markup from app/services/report_builder.py. Scoped under .sgrbPreview so
   these rules cannot reach the composer, which reuses two of the same class
   names on purpose (.sgrbRule, .sgrbHint).
   ========================================================================== */

.sgrbPreview {
  background: var(--i-surface-2);
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  padding: 22px 24px;
  max-height: 70vh;
  overflow-y: auto;
  color: var(--i-ink-2);
}

.sgrbPreview .sgrbDocHead {
  border-bottom: 1px solid var(--i-hair-strong);
  padding-bottom: 12px;
  margin-bottom: 18px;
}

.sgrbPreview .sgrbTitle {
  margin: 0 0 4px;
  font-size: var(--i-t-xl);
  font-weight: 600;
  letter-spacing: var(--i-track-tight);
  color: var(--i-ink-1);
}

.sgrbPreview .sgrbSubtitle {
  margin: 0 0 6px;
  font-size: var(--i-t-md);
  color: var(--i-ink-2);
}

.sgrbPreview .sgrbDocMeta,
.sgrbPreview .sgrbCount,
.sgrbPreview .sgrbRule {
  margin: 0;
  font-size: var(--i-t-xs);
  color: var(--i-ink-3);
}

.sgrbPreview .sgrbKicker {
  margin: 0 0 4px;
  font-size: var(--i-t-xs);
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  color: var(--i-ink-3);
}

.sgrbPreview .sgrbBlock { margin: 0 0 20px; }

.sgrbPreview .sgrbHeading,
.sgrbPreview .sgrbBlockHeading {
  margin: 0 0 8px;
  font-size: var(--i-t-lg);
  font-weight: 600;
  color: var(--i-ink-1);
}

.sgrbPreview .sgrbBlockHeading { font-size: var(--i-t-md); }

.sgrbPreview .sgrbNoteBody p { margin: 0 0 8px; }

.sgrbPreview .sgrbFigureGrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 10px;
}

.sgrbPreview .sgrbFigure {
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  padding: 8px 10px;
  background: var(--i-surface-3);
}

.sgrbPreview .sgrbFigureLabel {
  display: block;
  font-size: var(--i-t-xs);
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  color: var(--i-ink-3);
}

.sgrbPreview .sgrbFigureValue {
  display: block;
  font-family: var(--oo-font-data);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: var(--i-t-md);
  color: var(--i-ink-1);
}

.sgrbPreview .sgrbTableScroll { overflow-x: auto; }
.sgrbPreview .sgrbTable { font-size: var(--i-t-sm); }

/* A withheld block is dashed and amber-edged: the reader must be able to see,
   at a glance and without reading, that something was taken out. */
.sgrbPreview .sgrbWithheld {
  border: 1px dashed var(--i-amber);
  border-radius: var(--i-r-control);
  padding: 12px 14px;
  background: var(--i-amber-wash);
}

.sgrbPreview .sgrbWithheldBody {
  margin: 0 0 8px;
  color: var(--i-ink-1);
  font-size: var(--i-t-sm);
}

.sgrbPreview .sgrbProvenance {
  border-top: 1px solid var(--i-hair);
  margin: 10px 0 0;
  padding-top: 6px;
  font-size: var(--i-t-xs);
  color: var(--i-ink-3);
}

.sgrbPreview .sgrbProvenance > span { margin-right: 8px; }

.sgrbPreview .sgrbProvState {
  letter-spacing: var(--i-track-label);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--i-ink-2);
}

.sgrbPreview [data-sgrbprov="stale"] .sgrbProvState,
.sgrbPreview [data-sgrbprov="unavailable"] .sgrbProvState { color: var(--i-amber); }

.sgrbPreview .sgrbProvSentence {
  display: block;
  margin-top: 3px;
}

.sgrbPreview .sgrbProvUrl {
  font-family: var(--oo-font-data);
  word-break: break-all;
}

.sgrbPreview .sgrbDisclosures {
  margin: 0;
  padding-left: 1.1em;
  font-size: var(--i-t-xs);
  color: var(--i-ink-3);
}

.sgrbPreview .sgrbDisclosures li { margin-bottom: 5px; }

.sgrbPreview .sgrbContents {
  border: 1px solid var(--i-hair);
  border-radius: var(--i-r-control);
  padding: 10px 14px;
  margin-bottom: 18px;
}

.sgrbPreview .sgrbContents ol {
  margin: 0;
  padding-left: 1.2em;
  font-size: var(--i-t-sm);
}

.sgrbPreview .sgrbAppendix {
  border-top: 1px solid var(--i-hair-strong);
  margin-top: 26px;
  padding-top: 14px;
}

.sgrbPreview .sgrbGaps {
  border: 1px dashed var(--i-amber);
  border-radius: var(--i-r-control);
  padding: 10px 14px;
  margin: 12px 0;
}

.sgrbPreview .sgrbGaps ul {
  margin: 0;
  padding-left: 1.1em;
  font-size: var(--i-t-xs);
  color: var(--i-ink-2);
}

/* A page break is invisible in the exported file and must be VISIBLE here,
   because the author is deciding where it goes. */
.sgrbPreview .sgrbPageBreak {
  height: 0;
  border-top: 1px dashed var(--i-hair-strong);
  margin: 18px 0;
}

.sgrbPreview .sgrbEmpty {
  color: var(--i-ink-3);
  font-size: var(--i-t-sm);
}

/* ===========================================================================
   THE PAGE HEADING — /reports and /backtest
   ---------------------------------------------------------------------------
   Both modules were built as terminal INSTALLERS: they draw panels into a
   shell that already carries the heading. Mounted as standalone pages there
   was no shell, so neither page had an <h1> at all — the document announced no
   title and the heading outline started at <h3>.

   NOT `pk-section` / `pk-eyebrow` / `pk-lede`, which is what these rules were
   first written against. tests/test_reports_y12.py holds these two modules to
   HYPHEN-FREE class names, and the reason is structural rather than stylistic:
   obsidian_orchid.css and instrument.css carry 180+ `[class*="-word"]`
   selectors with !important, and a camelCase name cannot be matched by any of
   them. One hyphen re-opens the whole family.
   =========================================================================== */

#page-root .sgrbPageHead,
#page-root .sgbtPageHead {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 26px;
}

#page-root .sgrbPageEyebrow,
#page-root .sgbtPageEyebrow {
  display: block;
  font-size: 10.5px;
  letter-spacing: var(--i-track-label, 0.08em);
  text-transform: uppercase;
  color: var(--i-ink-3);
  margin-bottom: 6px;
}

#page-root .sgrbPageHead h1,
#page-root .sgbtPageHead h1 {
  margin: 0;
  font-size: clamp(24px, 3vw, 32px);
  line-height: var(--i-lh-tight, 1.15);
  color: var(--i-ink-1);
}

#page-root .sgrbPageLede,
#page-root .sgbtPageLede {
  margin: 0;
  max-width: var(--i-measure, 68ch);
  font-size: 14px;
  line-height: var(--i-lh-body, 1.6);
  color: var(--i-ink-2);
}
