/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* The terminal theme. The layout puts the whole app in Bootstrap's dark mode (`data-bs-theme="dark"` on
   <html>) and this block retints that mode: a near-black background with dull blue text, easy on the eyes
   for long sessions, in the spirit of a Bloomberg terminal. Green and red stay reserved for changes in
   value (`text-success`/`text-danger`), lifted a little so they read on black. Color also says what
   can be acted on: static text is blue (`--term-text`, `--term-text-strong` for headings and table
   heads), while anything clickable or editable — links, inputs and selects, the chartable
   metric labels, the time-slice rows, a chart's drag handle — is white (`--term-interactive`). Buttons go further: a white face with black text (`--term-button`).
   Everything else — tables,
   forms, buttons, charts (chart_controller.js reads the `--term-*` tokens) — takes its colors from here,
   so never hardcode a color elsewhere. */
[data-bs-theme="dark"] {
  --term-bg: #07090d;
  --term-surface: #0d121b;
  --term-surface-raised: #141b28;
  --term-border: #223049;
  --term-text: #7f97bd;
  --term-text-strong: #8fb0e6;
  --term-interactive: #e8edf4;
  --term-interactive-hover: #ffffff;
  --term-button: #e8edf4;
  --term-button-hover: #1b3152;
  --term-button-active: #142540;
  --term-on-button-hover: #ffffff;
  --term-down-button-hover: #4a1416;
  --term-on-button: #000000;
  --term-weight-input: #363c46;
  --term-weight-input-border: #4b5361;
  --term-down-on-button: #c62828;
  --term-muted: #56698c;
  --term-accent: #6f96cf;
  --term-accent-fill: #1b3152;
  --term-accent-border: #2d4d7c;
  --term-up: #3fb950;
  --term-down: #f0524f;
  --term-chart-line: #6f96cf;
  --term-chart-grid: #182233;

  --bs-body-bg: var(--term-bg);
  --bs-body-bg-rgb: 7, 9, 13;
  --bs-body-color: var(--term-text);
  --bs-body-color-rgb: 127, 151, 189;
  --bs-emphasis-color: var(--term-text-strong);
  --bs-emphasis-color-rgb: 143, 176, 230;
  --bs-heading-color: var(--term-text-strong);
  --bs-secondary-color: var(--term-muted);
  --bs-secondary-color-rgb: 86, 105, 140;
  --bs-tertiary-color: var(--term-muted);
  --bs-secondary-bg: var(--term-surface-raised);
  --bs-tertiary-bg: var(--term-surface);
  --bs-tertiary-bg-rgb: 13, 18, 27;
  --bs-border-color: var(--term-border);
  --bs-border-color-translucent: rgba(127, 151, 189, 0.15);
  --bs-link-color: var(--term-interactive);
  --bs-link-color-rgb: 232, 237, 244;
  --bs-link-hover-color: var(--term-interactive-hover);
  --bs-link-hover-color-rgb: 255, 255, 255;
  --bs-primary: var(--term-accent);
  --bs-primary-rgb: 111, 150, 207;
  --bs-primary-text-emphasis: var(--term-accent);
  --bs-primary-bg-subtle: #0f1a2b;
  --bs-primary-border-subtle: var(--term-accent-border);
  --bs-success: var(--term-up);
  --bs-success-rgb: 63, 185, 80;
  --bs-danger: var(--term-down);
  --bs-danger-rgb: 240, 82, 79;
  --bs-form-valid-color: var(--term-up);
  --bs-form-valid-border-color: var(--term-up);
  --bs-form-invalid-color: var(--term-down);
  --bs-form-invalid-border-color: var(--term-down);
}

body {
  font-variant-numeric: tabular-nums;
}

/* Bootstrap's × icons (a chart's close, a filter's reset) are interactive, so full white: dark mode
   already filters the icon white, but draws it at 50% opacity. */
.btn-close {
  --bs-btn-close-opacity: 1;
  --bs-btn-close-hover-opacity: 1;
}

/* The select caret is interactive too. Bootstrap's dark caret is a light grey SVG; this is the same SVG
   stroked in the --term-interactive white (a data URI cannot read a CSS variable, so the hex is
   repeated here — keep it in step with the token). */
[data-bs-theme="dark"] .form-select {
  --bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23e8edf4' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

/* An editable date input's calendar button, white (Chrome/Safari/Edge; Firefox has no such
   pseudo-element). A disabled date keeps the dim icon, since it cannot be opened. */
.form-control:not(:disabled)::-webkit-calendar-picker-indicator {
  filter: brightness(0) invert(1);
}

/* Header bar: a raised strip rather than Bootstrap's bright primary navbar. */
.app-navbar {
  --bs-navbar-brand-color: var(--term-interactive);
  --bs-navbar-brand-hover-color: var(--term-interactive-hover);
  --bs-navbar-color: var(--term-text);
  background-color: var(--term-surface);
  border: 1px solid var(--term-border);
  border-radius: var(--bs-border-radius);
}

/* The signed-in user's welcome is white like the interactive elements, even though it is static text:
   the user is the most important thing in the bar. */
.app-navbar .app-navbar-user {
  color: var(--term-interactive);
}

/* The resource links' bar under the navbar: a band a step lighter than the page, its links white
   (they are interactive), the current page's link underlined in the accent blue. */
.app-subnav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-top: 0.5rem;
  padding: 0.3rem 0.5rem;
  background-color: var(--term-surface-raised);
  border: 1px solid var(--term-border);
  border-radius: var(--bs-border-radius);
}

.app-subnav-link {
  padding: 0.25rem 0.6rem;
  border-radius: var(--bs-border-radius-sm);
  color: var(--term-interactive);
  text-decoration: none;
  font-size: 0.875rem;
}

.app-subnav-link:hover,
.app-subnav-link:focus {
  color: var(--term-interactive-hover);
  background-color: var(--term-accent-fill);
}

.app-subnav-link[aria-current="page"] {
  box-shadow: inset 0 -2px 0 var(--term-accent);
}

/* Buttons are solid white with black text — the strongest "you can act here" signal on the dark page.
   On hover (and while pressed) a button flips to a dark blue face with white text, its white border
   kept so it holds its shape. Bootstrap compiles its button colors in, so every variant the app uses is
   retinted here. A destructive (danger) button keeps the same white face with red text, so it still
   reads as a removal, and flips to a dark red instead. */
.btn-primary,
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-danger {
  --bs-btn-color: var(--term-on-button);
  --bs-btn-bg: var(--term-button);
  --bs-btn-border-color: var(--term-button);
  --bs-btn-hover-color: var(--term-on-button-hover);
  --bs-btn-hover-bg: var(--term-button-hover);
  --bs-btn-hover-border-color: var(--term-button);
  --bs-btn-active-color: var(--term-on-button-hover);
  --bs-btn-active-bg: var(--term-button-active);
  --bs-btn-active-border-color: var(--term-button);
  --bs-btn-disabled-color: var(--term-muted);
  --bs-btn-disabled-bg: var(--term-surface-raised);
  --bs-btn-disabled-border-color: var(--term-border);
  --bs-btn-focus-shadow-rgb: 111, 150, 207;
}

.btn-outline-danger {
  --bs-btn-color: var(--term-down-on-button);
  --bs-btn-hover-bg: var(--term-down-button-hover);
  --bs-btn-hover-border-color: var(--term-down);
  --bs-btn-active-bg: var(--term-down-button-hover);
  --bs-btn-active-border-color: var(--term-down);
  --bs-btn-focus-shadow-rgb: 240, 82, 79;
}

/* Inputs: a surface a step off the page, and a dull blue focus ring instead of Bootstrap's bright one. */
.form-control,
.form-select,
.input-group-text {
  background-color: var(--term-surface);
  border-color: var(--term-border);
  color: var(--term-interactive);
}

.input-group-text {
  color: var(--term-muted);
}

/* A placeholder ("Filter by ticker…", "Search by ticker…") sits inside an input, so it is white like the
   input's value. */
.form-control::placeholder {
  color: var(--term-interactive);
  opacity: 1;
}

/* Bootstrap's focus rule resets the text to the body color, which would turn a value blue while it is
   being typed; it stays white like any editable value. */
.form-control:focus,
.form-select:focus {
  color: var(--term-interactive);
  background-color: var(--term-surface);
  border-color: var(--term-accent);
  box-shadow: 0 0 0 0.2rem rgba(111, 150, 207, 0.2);
}

.form-control:disabled {
  background-color: var(--term-bg);
  color: var(--term-text);
}

/* Table heads (including the sticky ones over scroll boxes) sit on an opaque raised band. */
.table > thead {
  --bs-table-bg: var(--term-surface-raised);
  --bs-table-color: var(--term-text-strong);
}

.table {
  --bs-table-color: var(--term-text);
}

body {
  font-family: system-ui, -apple-system, sans-serif;
  margin: 2rem auto;
  max-width: 80rem;
  padding: 0 1rem;
}

main {
  margin-bottom: 10rem;
}

.scroll-box {
  max-height: 24rem;
  overflow-y: auto;
}

/* The portfolio history form's columns, locked or not: every table in them — totals, metrics, drift, the
   rebalance picker, the locked company list, search results — centers all of its cells.
   !important to beat Bootstrap's own !important `.text-end` utilities and `.metrics-table td`. */
.centered-tables table :is(th, td) {
  text-align: center !important;
}

/* Fixed table column widths, so a numeric column does not jump as its values change. */
.col-width-sm {
  width: 9rem;
}

.col-width-md {
  width: 12rem;
}

.col-width-lg {
  width: 14rem;
}

/* A company's weight input: narrow enough that it and its `%` addon fit a .col-width-sm column.
   Scoped like Bootstrap's own `.input-group > .form-control` (width: 1%; flex: 1 1 auto) to win. */
.input-group > .weight-input {
  flex: 0 0 auto;
  width: 5.5rem;
}

/* The weight inputs are the page's main thing to type into, so they stand apart from the other inputs:
   a dull grey face (--term-weight-input) with white text — still white, so still reads as interactive —
   focused or not. */
.input-group > .weight-input,
.input-group > .weight-input:focus {
  background-color: var(--term-weight-input);
  border-color: var(--term-weight-input-border);
  color: var(--term-interactive);
}

/* The `%` beside a weight input is part of the weighting the user edits, so it is white too, on the same
   grey face so input and unit read as one control. */
.input-group > .weight-input + .input-group-text {
  background-color: var(--term-weight-input);
  border-color: var(--term-weight-input-border);
  color: var(--term-interactive);
}

/* The portfolio history form's time-slice header: one row per slice, seven columns (label, date,
   unlock, arrow, label, date, unlock). Each row is a subgrid of the shared columns so they line up
   across rows; buttons and text share the row's vertical center. */
.time-slices {
  display: grid;
  /* After the seven content columns, a 1fr filler and a last track of up to 50%: the slice rows stop
     before that last track (so they fill roughly the left half of the header) while the charts under
     them span all of it. The last track can shrink to nothing (`minmax(0, …)`), so when the slice
     content needs more than half the header the rows run past the middle rather than wrapping. */
  grid-template-columns: repeat(7, auto) 1fr minmax(0, 50%);
  justify-content: start;
  column-gap: 0.75rem;
  row-gap: 0.25rem;
}

/* Every row carries the same padding and border width, so the outlined row stays in line. Each row
   reads as a clickable card: a faint border and background at rest, the primary color on hover, and
   the shown slice (aria-current) outlined and tinted so it stays distinct from a hovered one. The
   selected ring is a box-shadow, not a thicker border, so it never shifts the row's columns. */
.time-slice {
  display: grid;
  grid-column: 1 / -2;
  grid-template-columns: subgrid;
  align-items: center;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  background-color: var(--bs-body-bg);
  color: var(--term-interactive);
  cursor: pointer;
  transition: border-color 0.15s ease-in-out, background-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.time-slice:hover {
  border-color: var(--bs-primary);
  background-color: var(--bs-primary-bg-subtle);
}

.time-slice[aria-current="true"] {
  border-color: var(--bs-primary);
  background-color: var(--bs-primary-bg-subtle);
  box-shadow: 0 0 0 1px var(--bs-primary);
}

/* The metrics charted across the shown slice sit under that slice's row, spanning the full header
   width four to a line (two on narrower screens), in the order they were opened. */
.slice-charts {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
  padding: 0.5rem 0 0.75rem;
}

@media (max-width: 991.98px) {
  /* Too narrow to halve: the rows take the full width again. */
  .time-slices {
    grid-template-columns: repeat(7, auto) 1fr 0;
  }

  .slice-charts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.slice-chart {
  min-width: 0;
}

/* A maximized slice chart takes two of the row's four columns. */
.slice-chart.is-maximized {
  grid-column: span 2;
}

/* The maximize / minimize toggle beside a chart's ×: a bare white icon (interactive), showing the
   outward arrows normally and the inward ones while the chart is maximized. */
.slice-chart-size {
  display: inline-flex;
  padding: 0;
  border: 0;
  background: none;
  color: var(--term-interactive);
  line-height: 1;
}

.slice-chart-size:hover,
.slice-chart-size:focus-visible {
  color: var(--term-interactive-hover);
}

.slice-chart-size svg {
  width: 0.75rem;
  height: 0.75rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.slice-chart-contract,
.slice-chart.is-maximized .slice-chart-expand {
  display: none;
}

.slice-chart.is-maximized .slice-chart-contract {
  display: inline;
}

/* Two to a row (the narrow layout above), a chart is already half the row: nothing to maximize to. */
@media (max-width: 991.98px) {
  .slice-chart-size {
    display: none;
  }

  .slice-chart.is-maximized {
    grid-column: auto;
  }
}

/* Reordering a slice's charts (chart_order_controller.js): the grip and name are the handle (the only
   place with a grab cursor); the dragged chart fades, and a primary bar marks the side of the target
   it will land on. */
.slice-chart-handle {
  color: var(--term-interactive);
  cursor: grab;
  user-select: none;
}

.slice-chart-grip {
  color: var(--term-interactive);
}

.slice-chart.is-dragging {
  opacity: 0.4;
}

.slice-chart.drop-before {
  box-shadow: -3px 0 0 var(--bs-primary);
}

.slice-chart.drop-after {
  box-shadow: 3px 0 0 var(--bs-primary);
}

/* A slice with no charts open keeps its (hx-preserve) container in the DOM, just hidden. */
.slice-charts:not(:has(.slice-chart)) {
  display: none;
}

.slice-chart-plot {
  height: 9rem;
}

/* A slice row's labels, dates and buttons never wrap onto a second line. */
.time-slice > * {
  white-space: nowrap;
}

/* The × that closes one chart, scaled down from Bootstrap's 1em default. */
.slice-chart .btn-close {
  font-size: 0.6rem;
}

/* Dates align right so the day and year columns stack. */
.time-slice-date {
  text-align: right;
}

#security_results {
  margin-top: 0.5rem;
}

table {
  border-collapse: collapse;
  width: 100%;
}

th, td {
  border-bottom: 1px solid var(--bs-border-color);
  padding: 0.35rem 0.75rem;
  text-align: left;
}

th {
  border-bottom-width: 2px;
}

td:last-child {
  text-align: right;
}

form .field {
  margin-bottom: 0.75rem;
}

form label {
  display: block;
  margin-bottom: 0.25rem;
  font-weight: 600;
}

form input[type="text"],
form textarea {
  padding: 0.35rem;
  width: 24rem;
  max-width: 100%;
}

.filter-row {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.filter-row > label {
  flex: 0 0 auto;
  width: 5rem;
  margin-bottom: 0;
}

.filter-row > .form-select {
  flex: 0 0 auto;
  width: 15rem;
}

/* The × beside a set Sector / Industry filter (shared/_filter_clear): a small white close icon (Bootstrap's
   btn-close, full white like every × — see .btn-close above). */
.filter-clear {
  flex: 0 0 auto;
  font-size: 0.65rem;
  margin-left: 0.25rem;
}

.form-errors {
  color: var(--term-down);
  margin-bottom: 1rem;
}

.metrics-table {
  font-size: 0.72rem;
  line-height: 1.2;
}

.metrics-table td {
  padding: 0.12rem 0.5rem;
  vertical-align: baseline;
  text-align: left;
  border-right: 1px solid var(--term-border);
  border-bottom: 1px solid var(--term-border);
  background-color: var(--term-surface);
}

.metrics-table td:last-child {
  border-right: none;
}

.metrics-table .metrics-cell {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  white-space: nowrap;
}

/* In the portfolio history form's columns, each metric fills its cell: label at the left edge,
   value at the right. Scoped so the securities and portfolio pages keep their compact pairs. */
.centered-tables .metrics-table .metrics-cell {
  display: flex;
  justify-content: space-between;
}

.metrics-table .metrics-label {
  color: var(--term-muted);
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.metrics-table .metrics-link {
  color: var(--term-interactive);
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
}

.metrics-table .metrics-link:hover,
.metrics-table .metrics-link:focus {
  color: var(--term-interactive-hover);
  text-decoration: underline;
}

.metrics-table .metrics-value {
  font-weight: 600;
  font-size: 0.72rem;
}

.chart-loading-overlay {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background-color: rgba(var(--bs-body-bg-rgb), 0.7);
  z-index: 10;
}

.chart-loading-overlay.is-loading {
  display: flex;
}

