/* ==========================================================================
   WealthSmith design system
   --------------------------------------------------------------------------
   Structure and density follow GitHub's Primer dark palette; the display
   typography and the gradient brand mark follow MultiversX.

   This file layers over a Bootstrap 5.1.3 build (theme.min.css) that predates
   `data-bs-theme` and hardcodes light surfaces, so every surface, border and
   form control it paints is re-declared here.

   Chart colours are validated, not chosen by eye — see the CHARTS section.
   ========================================================================== */

/* --- tokens ------------------------------------------------------------- */
:root {
  /* surfaces */
  --bg:            #0d1117;
  --surface:       #161b22;
  --surface-2:     #1c2128;
  --surface-3:     #21262d;
  --inset:         #010409;

  /* borders */
  --border:        #30363d;
  --border-muted:  #21262d;

  /* text — all AA on both --bg and --surface */
  --text:          #e6edf3;
  --text-muted:    #8b949e;
  --text-subtle:   #6e7681;

  /* interactive */
  --accent:        #2f81f7;
  --accent-fill:   #1f6feb;
  --accent-wash:   rgba(47, 129, 247, .15);

  /* money direction. The fills are a CVD-validated pair (ΔE 8.5 protan,
     24.4 normal); the -text steps are the AA-contrast versions for figures. */
  --income:        #1a9b6c;
  --income-text:   #3fb950;
  --expense:       #db6d28;
  --expense-text:  #f0883e;

  /* status — reserved, never reused as a series colour */
  --danger:        #f85149;
  --warn:          #d29922;
  --ok:            #3fb950;

  /* brand gradient (MultiversX character) */
  --brand-1:       #23d3ee;
  --brand-2:       #2f81f7;
  --brand-3:       #a371f7;
  --brand-grad:    linear-gradient(110deg, var(--brand-1), var(--brand-2) 55%, var(--brand-3));

  --radius:        6px;
  --radius-lg:     12px;
  --sidebar-w:     248px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica,
          Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
          "Liberation Mono", monospace;
}

/* --- base --------------------------------------------------------------- */
html { -webkit-text-size-adjust: 100%; }

body,
body.bg-light {
  background-color: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 { color: var(--text); font-weight: 600; }
.display-1, .display-2, .display-3, .display-4, .display-5, .display-6 { color: var(--text); }
.lead { color: var(--text-muted); }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent); text-decoration: underline; }
hr { border-color: var(--border); opacity: 1; }
code { color: var(--text-muted); font-family: var(--mono); }

::selection { background: var(--accent-wash); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Scrollbars, so they do not punch a light hole in a dark page. */
* { scrollbar-color: var(--border) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 5px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-subtle); }

/* Bootstrap text utilities, remapped onto the dark ink scale. The vendored
   theme's values are tuned for a white page and go muddy on this surface. */
.text-muted { color: var(--text-muted) !important; }
.text-success   { color: var(--income-text) !important; }
.text-danger    { color: var(--expense-text) !important; }
.text-secondary { color: var(--text-muted) !important; }
.text-warning   { color: var(--warn) !important; }
.text-info      { color: var(--accent) !important; }
.text-primary   { color: var(--accent) !important; }
.text-white     { color: var(--text) !important; }
.text-dark  { color: var(--text) !important; }
.text-inherit { color: inherit !important; }
.bg-light   { background-color: var(--surface) !important; }
.bg-white   { background-color: var(--surface) !important; }
.border-top, .border-bottom, .border { border-color: var(--border) !important; }

/* ==========================================================================
   BRAND
   ========================================================================== */
.ws-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
  border-radius: 8px;
  background: var(--brand-grad);
  color: #04070d;
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -0.03em;
}

.ws-wordmark {
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}

/* ==========================================================================
   APP SHELL
   The admin frame is laid out here rather than by the vendored theme, so the
   sidebar and header do not have to be argued out of their light styling.
   ========================================================================== */
.ws-app {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: 100vh;
}

.ws-sidebar {
  background: var(--inset);
  border-right: 1px solid var(--border);
}

.ws-sidebar__inner {
  position: sticky;
  top: 0;
  max-height: 100vh;
  overflow-y: auto;
  padding: 16px 12px;
}

.ws-sidebar__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px 18px;
  color: var(--text);
}
.ws-sidebar__brand:hover { text-decoration: none; }

.ws-nav { list-style: none; margin: 0; padding: 0; }

.ws-nav__heading {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-subtle);
  padding: 16px 8px 6px;
}

.ws-nav__link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  margin-bottom: 1px;
  border-radius: var(--radius);
  color: var(--text-muted);
  font-weight: 500;
  line-height: 1.4;
}
.ws-nav__link:hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}
.ws-nav__link.is-active {
  background: var(--surface-3);
  color: var(--text);
  font-weight: 600;
}
/* The active row is marked by weight and an accent rule as well as fill, so
   it does not rely on a background colour alone. */
.ws-nav__link.is-active { box-shadow: inset 2px 0 0 var(--accent); }
.ws-nav__link svg { flex: 0 0 16px; width: 16px; height: 16px; }
.ws-nav__count { margin-left: auto; }

.ws-main { min-width: 0; display: flex; flex-direction: column; }

.ws-topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 24px;
  background: rgba(13, 17, 23, .85);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
}

.ws-topbar__title { font-size: 14px; font-weight: 600; margin: 0; }
.ws-topbar__actions { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.ws-content { padding: 24px; flex: 1 1 auto; }

.ws-topbar .ws-sidebar-toggle { display: none; }

@media (max-width: 1024px) {
  .ws-app { grid-template-columns: minmax(0, 1fr); }
  .ws-sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--sidebar-w);
    z-index: 40;
    transform: translateX(-100%);
    transition: transform .18s ease;
  }
  .ws-app.is-open .ws-sidebar { transform: none; }
  .ws-sidebar__inner { max-height: 100%; height: 100%; }
  .ws-app.is-open::after {
    content: "";
    position: fixed;
    inset: 0;
    background: rgba(1, 4, 9, .6);
    z-index: 30;
  }
  .ws-topbar .ws-sidebar-toggle { display: inline-flex; }
  .ws-content { padding: 16px; }
}

/* ==========================================================================
   PAGE HEADER
   ========================================================================== */
.ws-page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 20px;
}
.ws-page-head h1 {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0 0 2px;
}
.ws-page-head p { margin: 0; color: var(--text-muted); }
.ws-page-head__actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/* ==========================================================================
   CARDS / SURFACES  (Bootstrap overrides)
   ========================================================================== */
.card {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
}
.card-header {
  background-color: transparent;
  border-bottom: 1px solid var(--border);
  padding: 12px 16px;
  font-weight: 600;
  color: var(--text);
}
.card-header .h5, .card-header h4, .card-header h5 { color: var(--text); margin: 0; }
.card-header.bg-white { background-color: transparent !important; }
.card-body { padding: 16px; }
.card-footer { background-color: transparent; border-top: 1px solid var(--border); }
.smooth-shadow-md { box-shadow: 0 8px 24px rgba(1, 4, 9, .5); }

/* --- stat tiles --------------------------------------------------------- */
.ws-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}

.ws-stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
}
.ws-stat__label {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: 6px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.ws-stat__value {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}
.ws-stat__meta { font-size: 12px; color: var(--text-muted); margin-top: 4px; }

/* Figures line up column-wise only with tabular numerals. */
.ws-amount, .ws-stat__value, td.ws-amount, .ws-figure {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
}

.ws-positive { color: var(--income-text); }
.ws-negative { color: var(--expense-text); }
.ws-muted    { color: var(--text-muted); }

/* --- delta chip --------------------------------------------------------- */
.ws-delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12px;
  font-weight: 500;
}
.ws-delta svg { width: 12px; height: 12px; }

/* ==========================================================================
   INSIGHTS
   ========================================================================== */
.ws-insights { display: grid; gap: 8px; margin-bottom: 20px; }
@media (min-width: 992px) { .ws-insights { grid-template-columns: 1fr 1fr; } }

.ws-insight {
  display: flex;
  gap: 10px;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
}
.ws-insight__title { font-weight: 600; margin-bottom: 1px; }
.ws-insight__detail { color: var(--text-muted); font-size: 13px; }
.ws-insight svg { flex: 0 0 16px; width: 16px; height: 16px; margin-top: 2px; }

.ws-insight.level-good    { border-left-color: var(--ok); }
.ws-insight.level-good    svg { color: var(--ok); }
.ws-insight.level-warning { border-left-color: var(--warn); }
.ws-insight.level-warning svg { color: var(--warn); }
.ws-insight.level-danger  { border-left-color: var(--danger); }
.ws-insight.level-danger  svg { color: var(--danger); }
.ws-insight.level-info    { border-left-color: var(--accent); }
.ws-insight.level-info    svg { color: var(--accent); }

/* ==========================================================================
   CATEGORY BREAKDOWN
   A sorted magnitude ranking, so it is bars rather than a ring: the label
   carries identity and the bar length carries the value. The category's own
   colour appears only as a small chip, never as the sole encoding.
   ========================================================================== */
.ws-rank { display: flex; flex-direction: column; gap: 14px; }

.ws-rank__row { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 10px; }
.ws-rank__chip { width: 10px; height: 10px; border-radius: 3px; margin-top: 5px; }
.ws-rank__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 5px;
}
.ws-rank__name { color: var(--text); min-width: 0; }
.ws-rank__value { font-weight: 600; white-space: nowrap; }
.ws-rank__meta { font-size: 12px; color: var(--text-muted); margin-top: 4px; }

/* 4px rounded data-end anchored to the baseline. */
.ws-bar {
  height: 8px;
  border-radius: 4px;
  background: var(--surface-3);
  overflow: hidden;
}
.ws-bar > span {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--accent-fill);
  min-width: 2px;
}
.ws-bar > span.is-over  { background: var(--danger); }
.ws-bar > span.is-warn  { background: var(--warn); }
.ws-bar > span.is-ok    { background: var(--income); }

/* ==========================================================================
   TABLES
   ========================================================================== */
.table {
  color: var(--text);
  border-color: var(--border);
  margin-bottom: 0;
}
.table > :not(caption) > * > * {
  background-color: transparent;
  border-bottom-color: var(--border-muted);
  padding: 10px 12px;
  box-shadow: none;
}
.table thead th {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table-hover > tbody > tr:hover > * {
  background-color: var(--surface-2);
  color: var(--text);
}
.table-striped > tbody > tr:nth-of-type(odd) > * { background-color: transparent; }
.table-responsive { border-radius: var(--radius); }

.ws-cell-sub { font-size: 12px; color: var(--text-muted); }

/* A disabled row stays in the list — it is the row you turn back on. Greyed
   rather than made translucent: opacity on the row would fade the "disabled"
   badge and the switch with it, and those are the two things you need to read
   and reach. Opacity does not un-nest, so exempting them is not an option. */
.ws-row-off > td { color: var(--text-subtle); }
.ws-row-off .ws-dot,
.ws-row-off .ws-bar > span { filter: grayscale(1); }

/* Row actions sit on one line; a narrow column was wrapping them into a stack. */
.ws-row-actions { white-space: nowrap; display: flex; gap: 4px; justify-content: flex-end; }

/* Small colour chip used beside a name in dense rows. */
.ws-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex: 0 0 auto;
  vertical-align: middle;
}

.ws-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius);
  color: #fff;
  flex: 0 0 28px;
}
.ws-dot svg { width: 14px; height: 14px; }

/* ==========================================================================
   FORMS  (Bootstrap overrides)
   ========================================================================== */
.form-control,
.form-select {
  background-color: var(--inset);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  padding: 5px 12px;
  font-size: 14px;
}
.form-control:focus,
.form-select:focus {
  background-color: var(--inset);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
  color: var(--text);
}
.form-control::placeholder { color: var(--text-subtle); }
.form-control:disabled, .form-select:disabled { background-color: var(--surface-2); color: var(--text-subtle); }
.form-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%238b949e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='4 6 8 10 12 6'/%3e%3c/svg%3e");
  background-size: 14px;
}
.form-label { font-size: 13px; font-weight: 500; margin-bottom: 4px; color: var(--text); }
.form-text { color: var(--text-muted); font-size: 12px; }
.form-control-color { padding: 3px; height: 34px; background-color: var(--inset); }

.input-group-text {
  background-color: var(--surface-3);
  border: 1px solid var(--border);
  color: var(--text-muted);
  border-radius: var(--radius);
}

/* Checkboxes and switches. Bootstrap draws the switch knob as rgba(0,0,0,.25)
   and fills an indeterminate box with the old theme's violet, so against these
   surfaces an "off" switch was a featureless black pill and a part-selected
   table header came out purple. Knob, track and fill are restated per state.
   The unchecked outline is --text-subtle, not --border: a box holding nothing
   is all outline, and --border disappears on anything darker than a card. */
.form-check-input {
  background-color: var(--inset);
  border: 1px solid var(--text-subtle);
}
.form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
  background-color: var(--accent-fill);
  border-color: var(--accent-fill);
}
.form-check-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}
.form-check-label { color: var(--text); }

/* The knob is the whole reason a switch reads as a switch rather than a pill,
   so it stays legible when off. :focus is matched too, or focusing an off
   switch flashes the theme's violet knob. */
.form-switch .form-check-input,
.form-switch .form-check-input:focus:not(:checked) {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%238b949e'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:checked {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e");
}

/* Disabled is a dimmer version of the states above, nothing more — swapping in
   fainter colours as well as Bootstrap's opacity dimmed it twice and put it
   back under the floor. .5 is a shade too far on a dark surface; .6 reads. */
.form-check-input:disabled { opacity: .6; }

/* ==========================================================================
   BUTTONS
   ========================================================================== */
.btn {
  border-radius: var(--radius);
  font-size: 14px;
  font-weight: 500;
  padding: 5px 14px;
  border: 1px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn svg { width: 14px; height: 14px; }
.btn-sm { padding: 3px 10px; font-size: 13px; }
.btn-lg { padding: 10px 22px; font-size: 15px; }

.btn-primary {
  background-color: var(--accent-fill);
  border-color: var(--accent-fill);
  color: #fff;
}
.btn-primary:hover, .btn-primary:focus {
  background-color: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.btn-light, .btn-secondary, .btn-outline-secondary {
  background-color: var(--surface-3);
  border-color: var(--border);
  color: var(--text);
}
.btn-light:hover, .btn-secondary:hover, .btn-outline-secondary:hover {
  background-color: var(--surface-2);
  border-color: var(--text-subtle);
  color: var(--text);
}
.btn-danger { background-color: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover { filter: brightness(1.1); color: #fff; }
.btn-light.text-danger, .btn-light .text-danger { color: var(--danger) !important; }
.btn:disabled, .btn.disabled { opacity: .55; }

.btn-check:checked + .btn-outline-danger {
  background-color: var(--expense); border-color: var(--expense); color: #fff;
}
.btn-check:checked + .btn-outline-success {
  background-color: var(--income); border-color: var(--income); color: #fff;
}
.btn-check:checked + .btn-outline-secondary {
  background-color: var(--surface-3); border-color: var(--text-subtle); color: var(--text);
}
.btn-outline-danger  { color: var(--expense-text); border-color: var(--border); }
.btn-outline-success { color: var(--income-text);  border-color: var(--border); }

/* ==========================================================================
   BADGES / PILLS
   ========================================================================== */
.badge {
  font-weight: 500;
  font-size: 11px;
  padding: 3px 7px;
  border-radius: 999px;
  border: 1px solid var(--border);
}
.badge.bg-light        { background-color: var(--surface-3) !important; color: var(--text-muted) !important; }
.badge.bg-info         { background-color: transparent !important; color: var(--accent) !important; border-color: var(--accent); }
.badge.bg-primary      { background-color: var(--accent-fill) !important; color: #fff !important; border-color: transparent; }
.badge.bg-success      { background-color: transparent !important; color: var(--ok) !important; border-color: var(--ok); }
.badge.bg-warning      { background-color: transparent !important; color: var(--warn) !important; border-color: var(--warn); }
.badge.bg-danger       { background-color: transparent !important; color: var(--danger) !important; border-color: var(--danger); }
.badge.bg-secondary    { background-color: var(--surface-3) !important; color: var(--text-muted) !important; }
.badge.bg-primary-subtle, .badge.bg-warning-subtle, .badge.bg-light.text-dark {
  background-color: var(--surface-3) !important;
  color: var(--text-muted) !important;
}
.text-primary-emphasis { color: var(--accent) !important; }
.text-warning-emphasis { color: var(--warn) !important; }

/* ==========================================================================
   NAV PILLS / TABS
   ========================================================================== */
.nav-pills { gap: 4px; }
.nav-pills .nav-link {
  color: var(--text-muted);
  border-radius: var(--radius);
  padding: 5px 12px;
  font-weight: 500;
  border: 1px solid transparent;
}
.nav-pills .nav-link:hover { color: var(--text); background: var(--surface-2); text-decoration: none; }
.nav-pills .nav-link.active {
  background: var(--surface-3);
  color: var(--text);
  border-color: var(--border);
}

/* ==========================================================================
   PROGRESS
   ========================================================================== */
.progress {
  background-color: var(--surface-3);
  border-radius: 999px;
  height: 8px;
}
.progress-bar { background-color: var(--accent-fill); border-radius: 999px; }
.progress-bar.bg-danger  { background-color: var(--danger) !important; }
.progress-bar.bg-warning { background-color: var(--warn) !important; }
.progress-bar.bg-success { background-color: var(--income) !important; }

/* ==========================================================================
   LIST GROUP
   ========================================================================== */
.list-group { border-radius: var(--radius); }
.list-group-item {
  background-color: transparent;
  border-color: var(--border-muted);
  color: var(--text);
  padding: 10px 16px;
}
.list-group-flush > .list-group-item:last-child { border-bottom: 0; }

/* ==========================================================================
   MODALS / DROPDOWNS / TOASTS
   ========================================================================== */
.modal-content {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  color: var(--text);
}
.modal-header, .modal-footer { border-color: var(--border); padding: 14px 16px; }
.modal-body { padding: 16px; }
.modal-title { font-size: 15px; font-weight: 600; }
.modal-backdrop.show { opacity: .7; }
.btn-close {
  filter: invert(64%) sepia(9%) saturate(430%) hue-rotate(181deg) brightness(93%) contrast(88%);
}

.dropdown-menu {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(1, 4, 9, .6);
  padding: 6px;
  font-size: 14px;
}
.dropdown-item { color: var(--text); border-radius: 4px; padding: 6px 10px; }
.dropdown-item:hover, .dropdown-item:focus { background-color: var(--surface-3); color: var(--text); }
.dropdown-divider { border-color: var(--border); }

.toast {
  background-color: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
}
.toast.text-bg-success { background-color: var(--surface) !important; border-left: 3px solid var(--ok); color: var(--text) !important; }
.toast.text-bg-danger  { background-color: var(--surface) !important; border-left: 3px solid var(--danger); color: var(--text) !important; }
.toast.text-bg-dark    { background-color: var(--surface) !important; color: var(--text) !important; }
.toast .btn-close-white { filter: invert(64%) sepia(9%) saturate(430%) hue-rotate(181deg) brightness(93%); }

/* ==========================================================================
   ALERTS
   ========================================================================== */
.alert { border-radius: var(--radius); border: 1px solid var(--border); padding: 10px 14px; font-size: 13px; }
.alert-danger { background-color: rgba(248, 81, 73, .1); border-color: rgba(248, 81, 73, .4); color: var(--danger); }

/* ==========================================================================
   PAGINATION
   ========================================================================== */
.pagination { gap: 4px; }
.page-link {
  background-color: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius);
  color: var(--text-muted);
  padding: 4px 10px;
  font-size: 13px;
}
.page-link:hover { background-color: var(--surface-2); color: var(--text); border-color: var(--border); }
.page-item.active .page-link {
  background-color: var(--accent-fill);
  border-color: var(--accent-fill);
  color: #fff;
}
.page-item.disabled .page-link { color: var(--text-subtle); background: transparent; }

/* ==========================================================================
   FILTER BAR
   ========================================================================== */
.ws-filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; }
.ws-filters > * { flex: 1 1 150px; min-width: 0; }
.ws-filters .ws-filter-actions { flex: 0 0 auto; }

/* ==========================================================================
   EMPTY STATE
   ========================================================================== */
.ws-empty { padding: 40px 16px; text-align: center; color: var(--text-muted); }
.ws-empty svg { width: 22px; height: 22px; margin-bottom: 8px; color: var(--text-subtle); }
.ws-empty p { margin-bottom: 4px; color: var(--text); }

/* ==========================================================================
   CHARTS
   ApexCharts paints inline styles, so its text and grid are re-coloured here.
   ========================================================================== */
.ws-chart { min-height: 260px; }
.apexcharts-canvas text { fill: var(--text-muted) !important; font-family: var(--font) !important; }
.apexcharts-gridline { stroke: var(--border-muted) !important; }
.apexcharts-xaxis line, .apexcharts-yaxis line { stroke: var(--border) !important; }
.apexcharts-legend-text { color: var(--text-muted) !important; font-family: var(--font) !important; }
.apexcharts-tooltip {
  background: var(--surface) !important;
  border: 1px solid var(--border) !important;
  box-shadow: 0 8px 24px rgba(1, 4, 9, .6) !important;
  color: var(--text) !important;
}
.apexcharts-tooltip-title {
  background: var(--surface-3) !important;
  border-bottom: 1px solid var(--border) !important;
  font-family: var(--font) !important;
}
.apexcharts-xaxistooltip, .apexcharts-yaxistooltip {
  background: var(--surface-3) !important;
  border-color: var(--border) !important;
  color: var(--text) !important;
}

/* A legend swatch reproduced in HTML, for the charts that carry their own. */
.ws-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12px; color: var(--text-muted); }
.ws-legend__item { display: inline-flex; align-items: center; gap: 6px; }

/* ==========================================================================
   PRIVACY MODE
   Every amount is printed inside .ws-num by the money filters, so one class
   on <html> hides the lot — for reading the app on a train. Blur rather than
   a placeholder: the layout does not move, so nothing reflows on toggle.
   ========================================================================== */
.ws-num { transition: filter .12s ease; }

.ws-private .ws-num {
  filter: blur(0.35em);
  -webkit-user-select: none;
  user-select: none;
}

/* ApexCharts prints figures as SVG text, which .ws-num cannot reach. The bars
   and slices stay — a shape is not a number — but every label goes. */
.ws-private .apexcharts-yaxis text,
.ws-private .apexcharts-datalabels text,
.ws-private .apexcharts-datalabel-value,
.ws-private .apexcharts-tooltip,
.ws-private .apexcharts-xaxistooltip,
.ws-private .apexcharts-yaxistooltip {
  filter: blur(5px);
}

/* Two icons ship in the toggle and CSS picks one, so switching states never
   has to re-run feather.replace() on the button. */
.ws-privacy-toggle__on,
.ws-privacy-toggle__off { display: none; }
.ws-private .ws-privacy-toggle__on { display: inline-flex; }
html:not(.ws-private) .ws-privacy-toggle__off { display: inline-flex; }

/* HTMX swaps the table body; dim it while the request is in flight. */
.htmx-request .ws-swap-target { opacity: .5; transition: opacity .15s ease; }

/* ==========================================================================
   INFO / GUIDE
   Long-form prose, so the measure is capped and the type is a step up from the
   dense table scale the rest of the admin uses.
   ========================================================================== */
.ws-info__heading {
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted);
  margin: 24px 0 12px;
}

.ws-info__jump { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.ws-info__jump a { text-decoration: none; }
.ws-info__jump a:hover { background: var(--surface-3) !important; color: var(--text); }

/* The topbar is sticky, so a bare anchor jump parks the card heading behind
   it. Clear its height plus a little breathing room. */
.ws-info__jump + .card,
.ws-info__jump ~ .card[id] { scroll-margin-top: 72px; }

.ws-info__lead { font-size: 14px; color: var(--text); max-width: 78ch; margin-bottom: 12px; }

.ws-info__list { margin: 0; padding-left: 18px; max-width: 78ch; }
.ws-info__list li { color: var(--text-muted); font-size: 13px; margin-bottom: 6px; }
.ws-info__list li::marker { color: var(--text-subtle); }

/* The caveat that stops a section being misused, so it is set apart from the
   how-to rather than buried as one more bullet. */
.ws-info__note {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 14px 0 0;
  padding: 10px 12px;
  border-left: 2px solid var(--accent-fill);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-2);
  max-width: 78ch;
}
.ws-info__note p { margin: 0; font-size: 13px; color: var(--text-muted); }
.ws-info__note svg { width: 15px; height: 15px; flex: 0 0 15px; margin-top: 1px; color: var(--accent); }

/* --- the setup path ----------------------------------------------------- */
.ws-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.ws-step { display: flex; gap: 12px; align-items: flex-start; }
.ws-step__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  flex: 0 0 22px;
  border-radius: 50%;
  background: var(--surface-3);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.ws-step__title { font-size: 14px; font-weight: 600; color: var(--text); }
.ws-step__detail { margin: 2px 0 0; font-size: 13px; color: var(--text-muted); max-width: 78ch; }

/* --- cross-cutting ideas ------------------------------------------------ */
.ws-concepts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 12px;
}
.ws-concept {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
}
.ws-concept__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: var(--surface-3);
  color: var(--accent);
  margin-bottom: 10px;
}
.ws-concept__icon svg { width: 15px; height: 15px; }
.ws-concept h3 { font-size: 14px; font-weight: 600; margin: 0 0 6px; color: var(--text); }
.ws-concept p { font-size: 13px; color: var(--text-muted); margin: 0; }

/* ==========================================================================
   PUBLIC SITE
   Larger display type and the gradient motif; the same tokens underneath.
   ========================================================================== */
.ws-site-nav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(13, 17, 23, .8);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.ws-hero { position: relative; overflow: hidden; padding: 96px 0 72px; }
/* A single soft glow rather than a busy backdrop, so the headline stays first. */
.ws-hero::before {
  content: "";
  position: absolute;
  top: -220px;
  left: 50%;
  width: 900px;
  height: 620px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(47, 129, 247, .22), transparent 70%);
  pointer-events: none;
}
.ws-hero > * { position: relative; }

.ws-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 500;
  margin-bottom: 20px;
}

.ws-display {
  font-size: clamp(2.4rem, 6vw, 4rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.035em;
  margin-bottom: 18px;
}
.ws-display__grad {
  background: var(--brand-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.ws-lede {
  font-size: clamp(1rem, 1.6vw, 1.15rem);
  color: var(--text-muted);
  max-width: 62ch;
  margin: 0 auto 28px;
}

.ws-feature {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 22px;
  height: 100%;
}
.ws-feature__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--surface-3);
  color: var(--accent);
  margin-bottom: 12px;
}
.ws-feature h3 { font-size: 15px; font-weight: 600; margin-bottom: 6px; }
.ws-feature p { color: var(--text-muted); margin: 0; font-size: 14px; }

.ws-section { padding: 72px 0; }
.ws-section__title {
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  margin-bottom: 10px;
}

.ws-site-footer { border-top: 1px solid var(--border); padding: 32px 0; color: var(--text-muted); }

/* A hairline rule that fades out, used between landing sections. */
.ws-rule {
  height: 1px;
  border: 0;
  background: linear-gradient(90deg, transparent, var(--border) 20%, var(--border) 80%, transparent);
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
