:root {
  --rui-chart-primary: #6366f1;
  --rui-chart-secondary: #0ea5e9;
  --rui-chart-accent: #10b981;
  --rui-chart-muted: #94a3b8;

  /* Categorical slots. Assigned in order and never cycled — the order is what
     keeps adjacent series distinguishable under protanopia and deuteranopia,
     so reorder these only after re-validating the palette. Verified against
     both the white and #171717 surfaces. */
  --rui-chart-series-1: #6366f1;
  --rui-chart-series-2: #ea580c;
  --rui-chart-series-3: #db2777;
  --rui-chart-series-4: #c026d3;
  --rui-chart-series-5: #65a30d;
  --rui-chart-series-6: #0284c7;
  --rui-chart-series-7: #dc2626;
  --rui-chart-series-8: #0d9488;
  --rui-chart-grid: rgba(148, 163, 184, 0.22);
  --rui-chart-text: #64748b;
  --rui-chart-metric-label: #111827;
  --rui-chart-metric-value: #111827;
  --rui-chart-metric-muted: #6b7280;
  --rui-chart-background: transparent;

  /* Touching marks separate with a gap in the surface colour, never a stroke. */
  --rui-chart-surface: #ffffff;
  --rui-chart-border: rgba(17, 24, 39, 0.14);
  --rui-chart-hover: rgba(17, 24, 39, 0.06);
  --rui-chart-switch-off: #d1d5db;
  --rui-chart-skeleton: #f8f9fa;
  --rui-chart-skeleton-line: rgba(148, 163, 184, 0.13);
  --rui-chart-skeleton-sheen: rgba(255, 255, 255, 0.65);
  --rui-chart-positive: #047857;
  --rui-chart-negative: #b91c1c;
  --rui-chart-tooltip-bg: #ffffff;
  --rui-chart-tooltip-text: #111827;
  --rui-chart-tooltip-muted: #6b7280;
  --rui-chart-tooltip-border: rgba(17, 24, 39, 0.14);
  --rui-chart-tooltip-radius: 0.5rem;
  --rui-chart-tooltip-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);

  /* Type. The first three are read by the chart itself: the options ship them
     as `var()` strings and the Stimulus controller resolves them against this
     element before Apex sees them, which is why a chart can be given smaller
     labels by setting a variable on the card it sits in.

     The rest style the parts drawn in HTML — tooltip, metric cards, tables.
     They are deliberately a step larger than the chart chrome: axis labels are
     reference marks, and card text is meant to be read. */
  --rui-chart-font-family: inherit;
  --rui-chart-font-size: 12px;
  --rui-chart-font-size-sm: 11px;
  --rui-chart-text-size: 0.8125rem;
  --rui-chart-text-size-sm: 0.75rem;
  --rui-chart-value-size: 1.375rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --rui-chart-grid: rgba(148, 163, 184, 0.16);
    --rui-chart-text: #94a3b8;
    --rui-chart-metric-label: #f9fafb;
    --rui-chart-metric-value: #f9fafb;
    --rui-chart-metric-muted: #9ca3af;
    --rui-chart-surface: #171717;
    --rui-chart-border: rgba(255, 255, 255, 0.16);
    --rui-chart-hover: rgba(255, 255, 255, 0.08);
    --rui-chart-switch-off: #4b5563;
    --rui-chart-skeleton: rgba(255, 255, 255, 0.05);
    --rui-chart-skeleton-line: rgba(255, 255, 255, 0.06);
    --rui-chart-skeleton-sheen: rgba(255, 255, 255, 0.07);
    --rui-chart-positive: #34d399;
    --rui-chart-negative: #f87171;
    --rui-chart-tooltip-bg: #171717;
    --rui-chart-tooltip-text: #f9fafb;
    --rui-chart-tooltip-muted: #9ca3af;
    --rui-chart-tooltip-border: rgba(255, 255, 255, 0.16);
    --rui-chart-tooltip-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  }
}

/* The Stimulus controller honours a `dark` class and `data-theme="dark"`, so
   the variables answer to both strategies too. */
.dark,
[data-theme="dark"] {
  --rui-chart-grid: rgba(148, 163, 184, 0.16);
  --rui-chart-text: #94a3b8;
  --rui-chart-metric-label: #f9fafb;
  --rui-chart-metric-value: #f9fafb;
  --rui-chart-metric-muted: #9ca3af;
  --rui-chart-surface: #171717;
  --rui-chart-border: rgba(255, 255, 255, 0.16);
  --rui-chart-hover: rgba(255, 255, 255, 0.08);
  --rui-chart-switch-off: #4b5563;
  --rui-chart-skeleton: rgba(255, 255, 255, 0.05);
  --rui-chart-skeleton-line: rgba(255, 255, 255, 0.06);
  --rui-chart-skeleton-sheen: rgba(255, 255, 255, 0.07);
  --rui-chart-positive: #34d399;
  --rui-chart-negative: #f87171;
  --rui-chart-tooltip-bg: #171717;
  --rui-chart-tooltip-text: #f9fafb;
  --rui-chart-tooltip-muted: #9ca3af;
  --rui-chart-tooltip-border: rgba(255, 255, 255, 0.16);
  --rui-chart-tooltip-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

.railsui-chart {
  position: relative;
  width: 100%;
}

/* -------------------------------------------------------- small multiples */

.railsui-small-multiples {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1rem 1.25rem;
}

@media (min-width: 640px) {
  .railsui-small-multiples {
    grid-template-columns: repeat(var(--rui-small-multiple-columns, 3), minmax(0, 1fr));
  }
}

.railsui-small-multiple__title {
  margin: 0 0 0.25rem;
  font-size: var(--rui-chart-text-size-sm);
  font-weight: 600;
  line-height: 1rem;
  color: var(--rui-chart-metric-value);
}

/* ----------------------------------------------------------------- states */

.railsui-chart-state {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 1rem;
  border: 1px dashed var(--rui-chart-border);
  border-radius: 0.5rem;
  text-align: center;
}

.railsui-chart-state__title {
  margin: 0;
  font-size: var(--rui-chart-text-size);
  font-weight: 500;
  line-height: 1.25rem;
  color: var(--rui-chart-metric-muted);
}

.railsui-chart-state__description {
  margin: 0.25rem 0 0;
  max-width: 44ch;
  font-size: var(--rui-chart-text-size);
  line-height: 1.25rem;
  color: var(--rui-chart-text);
}

.railsui-chart-state--error {
  border-style: solid;
  border-color: var(--rui-chart-negative);
}

.railsui-chart-state--error .railsui-chart-state__title {
  color: var(--rui-chart-negative);
}

.railsui-chart-state--loading {
  align-items: center;
  justify-content: flex-start;
  border-style: none;
  padding: 1rem;
  text-align: left;
}

.railsui-chart-state--loading-center {
  justify-content: center;
}

.railsui-chart-state--loading-right {
  justify-content: flex-end;
}

/* Shared placeholder surface: a fill plus the sheen that crosses it. */
.railsui-skeleton-bar {
  position: relative;
  overflow: hidden;
  background-color: var(--rui-chart-skeleton);
}

/* Stand-ins for the card's text. The plot area is left empty on purpose — a
   slab where the chart goes claims more about the shape of the data than a
   loading state can know. */
.railsui-skeleton-bar {
  display: block;
  border-radius: 0.25rem;
}

.railsui-skeleton-bar--label { width: 4.5rem; height: 0.6875rem; margin-bottom: 0.4375rem; }
.railsui-skeleton-bar--value { width: 9.5rem; height: 1.375rem; margin-bottom: 0.5rem; }
.railsui-skeleton-bar--meta { width: 7rem; height: 0.75rem; }
.railsui-skeleton-bar--footer { width: 6.5rem; height: 0.75rem; }

/* Same rule as the metric card skeleton: stand in for surrounding text and
   controls, but leave the plot area empty. A filled chart slab claims too much
   about data that has not arrived. */
.railsui-chart-skeleton {
  display: flex;
  flex-direction: column;
  width: clamp(18rem, 48%, 42rem);
  max-width: 100%;
  gap: 0.5rem;
}

.railsui-chart-skeleton .railsui-skeleton-bar--label { width: 36%; }
.railsui-chart-skeleton .railsui-skeleton-bar--value { width: 76%; }
.railsui-chart-skeleton .railsui-skeleton-bar--meta { width: 54%; }
.railsui-chart-skeleton .railsui-skeleton-bar--footer { width: 48%; }

.railsui-chart-skeleton__plot {
  display: block;
  min-height: 4rem;
}

.railsui-chart-skeleton .railsui-skeleton-bar--footer {
  margin-top: 0.25rem;
}

/* A sheen sweeping across, rather than the whole block breathing. Pulsing reads
   as a broken element; a sweep reads as work in progress. */
.railsui-skeleton-bar::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background-image: linear-gradient(
    90deg,
    transparent 0,
    var(--rui-chart-skeleton-sheen) 50%,
    transparent 100%
  );
  animation: railsui-chart-sweep 1.6s ease-in-out infinite;
}

@keyframes railsui-chart-sweep {
  100% { transform: translateX(100%); }
}

/* Turbo marks a frame busy while it fetches. Holding the previous render at
   reduced opacity keeps the numbers on screen and the layout still — a
   skeleton here would throw the chart away and flash. */
[aria-busy="true"] .railsui-chart,
[aria-busy="true"] .railsui-metric-card {
  opacity: 0.55;
  transition: opacity 120ms ease;
}

@media (prefers-reduced-motion: reduce) {
  /* The skeleton still reads as a placeholder standing still. */
  .railsui-skeleton-bar::after {
    animation: none;
    opacity: 0.4;
    transform: none;
  }

  [aria-busy="true"] .railsui-chart,
  [aria-busy="true"] .railsui-metric-card {
    transition: none;
  }
}

/* ---------------------------------------------------------------- filters */

/* One row above everything it scopes. Never inside a chart card — per-card
   date pickers let two cards disagree about what "this week" means. */
.railsui-chart-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin-bottom: 1.25rem;
}

.railsui-chart-filters__field {
  display: flex;
  align-items: center;
  gap: 0.375rem;
}

.railsui-chart-filters__label {
  font-size: var(--rui-chart-text-size);
  color: var(--rui-chart-metric-muted);
}

.railsui-chart-filters__control {
  position: relative;
  display: inline-flex;
  align-items: center;
}

/* Drawn from borders rather than a background image so it inherits
   currentColor and follows the theme without a second asset. */
.railsui-chart-filters__control::after {
  content: "";
  position: absolute;
  right: 0.6875rem;
  width: 0.375rem;
  height: 0.375rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-25%) rotate(45deg);
  opacity: 0.65;
  pointer-events: none;
}

/* Bare until hover. Filter chrome sits above the data all day; it earns its
   weight only while someone is reaching for it. */
.railsui-chart-filters__select {
  appearance: none;
  -webkit-appearance: none;
  padding: 0.25rem 1.875rem 0.25rem 0.625rem;
  border: 0;
  border-radius: 9999px;
  background-color: transparent;
  /* Tailwind's forms plugin paints an arrow on every select. The wrapper draws
     ours, so drop that one rather than stacking two chevrons. */
  background-image: none;
  color: var(--rui-chart-metric-value);
  font-family: inherit;
  font-size: var(--rui-chart-text-size);
  font-weight: 500;
  line-height: 1.25rem;
  cursor: pointer;
  transition: background-color 120ms ease;
}

/* A hairline with the wash. On a near-black page a bare fill reads as a soft
   grey blob with no edge; the inset ring gives the pill a boundary without
   reserving border width in the resting state. */
.railsui-chart-filters__select:hover {
  background-color: var(--rui-chart-hover);
  box-shadow: inset 0 0 0 1px var(--rui-chart-border);
}

.railsui-chart-filters__select:focus-visible {
  outline: 2px solid var(--rui-chart-primary);
  outline-offset: 1px;
}

.railsui-chart-filters__compare {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--rui-chart-text-size);
  color: var(--rui-chart-metric-muted);
  cursor: pointer;
}

.railsui-chart-filters__compare--switch {
  padding: 0.25rem 0.75rem 0.25rem 0.5rem;
  border-radius: 9999px;
  transition: background-color 120ms ease;
}

.railsui-chart-filters__compare--switch:hover {
  background-color: var(--rui-chart-hover);
  box-shadow: inset 0 0 0 1px var(--rui-chart-border);
}

/* Kept in the accessibility tree and focusable; the track is what you see. */
.railsui-chart-filters__switch {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.railsui-chart-filters__track {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
  width: 1.75rem;
  height: 1rem;
  border-radius: 9999px;
  background-color: var(--rui-chart-switch-off);
  transition: background-color 140ms ease;
}

.railsui-chart-filters__track::after {
  content: "";
  position: absolute;
  top: 0.125rem;
  left: 0.125rem;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 9999px;
  background-color: #ffffff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.25);
  transition: transform 140ms ease;
}

.railsui-chart-filters__switch:checked + .railsui-chart-filters__track {
  background-color: var(--rui-chart-primary);
}

.railsui-chart-filters__switch:checked + .railsui-chart-filters__track::after {
  transform: translateX(0.75rem);
}

.railsui-chart-filters__switch:focus-visible + .railsui-chart-filters__track {
  outline: 2px solid var(--rui-chart-primary);
  outline-offset: 2px;
}

.railsui-chart-filters__apply {
  padding: 0.25rem 0.75rem;
  border: 1px solid var(--rui-chart-border);
  border-radius: 9999px;
  background-color: var(--rui-chart-surface);
  font-family: inherit;
  font-size: var(--rui-chart-text-size);
}

@media (prefers-reduced-motion: reduce) {
  .railsui-chart-filters__select,
  .railsui-chart-filters__compare--switch,
  .railsui-chart-filters__track,
  .railsui-chart-filters__track::after {
    transition: none;
  }
}

/* ---------------------------------------------------------------- metric */

.railsui-metric {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.railsui-metric-label {
  margin: 0;
  font-size: var(--rui-chart-text-size);
  font-weight: 500;
  color: var(--rui-chart-metric-muted);
  line-height: 1.25rem;
}

.railsui-metric-value-row {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.railsui-metric-value {
  font-size: var(--rui-chart-value-size);
  font-weight: 600;
  line-height: 1.15;
  color: var(--rui-chart-metric-value);
}

/* ----------------------------------------------------------- metric card */

.railsui-metric-card {
  display: flex;
  flex-direction: column;
  padding: 1rem 1.125rem 0.75rem;
  border: 1px solid var(--rui-chart-border);
  border-radius: 0.5rem;
  background-color: var(--rui-chart-surface);
}

.railsui-metric-card__head {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
}

.railsui-metric-card__label {
  margin: 0;
  font-size: var(--rui-chart-text-size);
  font-weight: 600;
  line-height: 1.25rem;
  color: var(--rui-chart-metric-label);
}

.railsui-metric-card__value-row {
  display: flex;
  align-items: baseline;
  gap: 0.4375rem;
}

.railsui-metric-card__value {
  font-size: var(--rui-chart-value-size);
  font-weight: 600;
  line-height: 1.25;
  color: var(--rui-chart-metric-value);
  /* Proportional figures: tabular digits make a large standalone number
     look loose at display sizes. */
  font-variant-numeric: proportional-nums;
}

.railsui-metric-card__previous {
  margin: 0;
  font-size: var(--rui-chart-text-size);
  line-height: 1.25rem;
  color: var(--rui-chart-metric-muted);
}

.railsui-metric-card__chart {
  margin-top: 0.5rem;
}

.railsui-metric-card__chart .railsui-chart,
.railsui-metric-card__chart .apexcharts-canvas,
.railsui-metric-card__chart .apexcharts-svg {
  overflow: visible !important;
}

/* Rendered outside the plot so the first and last labels sit flush with the
   card edges. Apex centres them on their data point and clips at the canvas
   edge, which costs either the label's first characters or plot width. */
.railsui-metric-card__axis {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.125rem;
  font-size: var(--rui-chart-text-size-sm);
  line-height: 1rem;
  color: var(--rui-chart-text);
}

.railsui-metric-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.75rem;
  padding-top: 0.625rem;
  border-top: 1px solid var(--rui-chart-border);
  font-size: var(--rui-chart-text-size);
  line-height: 1.25rem;
}

.railsui-metric-card__updated {
  color: var(--rui-chart-metric-muted);
}

.railsui-metric-card__details {
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: inherit;
  font-weight: 500;
  line-height: inherit;
  color: var(--rui-chart-primary);
  text-decoration: none;
  cursor: pointer;
}

.railsui-metric-card__details:hover {
  text-decoration: underline;
}

/* --------------------------------------------------------- expanded view */

.railsui-metric-dialog {
  width: min(64rem, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  padding: 0;
  border: 1px solid var(--rui-chart-border);
  border-radius: 0.75rem;
  background-color: var(--rui-chart-surface);
  color: var(--rui-chart-metric-value);
  opacity: 0;
  overflow: auto;
  transform: translateY(0.5rem) scale(0.98);
  transition: opacity 160ms ease, transform 180ms ease;
}

.railsui-metric-dialog::backdrop {
  background-color: transparent;
  transition: background-color 160ms ease;
}

.railsui-metric-dialog--open {
  opacity: 1;
  transform: translateY(0) scale(1);
}

.railsui-metric-dialog--open::backdrop {
  background-color: rgba(15, 23, 42, 0.48);
}

.railsui-metric-dialog--closing {
  opacity: 0;
  transform: translateY(0.25rem) scale(0.99);
}

.railsui-metric-dialog__panel {
  min-width: 0;
  padding: 1.25rem 1.75rem 1.5rem;
}

.railsui-metric-dialog__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.railsui-metric-dialog__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2.5rem;
  height: 2.5rem;
  border: 0;
  border-radius: 0.375rem;
  background-color: transparent;
  color: var(--rui-chart-metric-muted);
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease;
}

.railsui-metric-dialog__close:hover,
.railsui-metric-dialog__close:focus-visible {
  background-color: var(--rui-chart-hover);
  color: var(--rui-chart-metric-value);
}

.railsui-metric-dialog__close:focus-visible {
  outline: 2px solid var(--rui-chart-primary);
  outline-offset: 2px;
}

.railsui-metric-dialog__close-icon {
  width: 1.5rem;
  height: 1.5rem;
  pointer-events: none;
}

.railsui-metric-dialog__chart,
.railsui-metric-dialog__chart .railsui-chart,
.railsui-metric-dialog__chart .apexcharts-canvas,
.railsui-metric-dialog__chart .apexcharts-svg {
  overflow: visible !important;
}

@media (max-width: 640px) {
  .railsui-metric-dialog {
    width: calc(100vw - 1rem);
    max-height: calc(100dvh - 1rem);
    border-radius: 0.625rem;
  }

  .railsui-metric-dialog__panel {
    padding: 1rem;
  }

  .railsui-metric-dialog__head {
    gap: 0.75rem;
    margin-bottom: 0.75rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .railsui-metric-dialog,
  .railsui-metric-dialog::backdrop,
  .railsui-metric-dialog__close {
    transition: none;
  }
}

/* ---------------------------------------------------------------- deltas */

/* Plain coloured text. A filled pill competes with the value beside it. */
.railsui-metric-delta {
  font-size: var(--rui-chart-text-size);
  font-weight: 600;
  line-height: 1.25rem;
  font-variant-numeric: proportional-nums;
}

.railsui-metric-delta--positive {
  color: var(--rui-chart-positive);
}

.railsui-metric-delta--negative {
  color: var(--rui-chart-negative);
}

.railsui-metric-delta--neutral {
  color: var(--rui-chart-metric-muted);
}

/* --------------------------------------------------------------- tooltip */

/* Apex ships a dark slab whatever the page is doing. Overriding the container
   lets the tooltip sit on the same surface as the card it belongs to. */
.railsui-chart .apexcharts-tooltip.apexcharts-theme-light,
.railsui-chart .apexcharts-tooltip.apexcharts-theme-dark {
  border: 1px solid var(--rui-chart-tooltip-border) !important;
  border-radius: var(--rui-chart-tooltip-radius) !important;
  background: var(--rui-chart-tooltip-bg) !important;
  box-shadow: var(--rui-chart-tooltip-shadow) !important;
  overflow: hidden;
}

.railsui-chart-tooltip {
  min-width: 11rem;
  padding: 0.5rem 0.625rem 0.5625rem;
  font-family: inherit;
  font-size: var(--rui-chart-text-size-sm);
  line-height: 1rem;
  color: var(--rui-chart-tooltip-text);
}

.railsui-chart-tooltip__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  padding-bottom: 0.375rem;
  margin-bottom: 0.375rem;
  border-bottom: 1px solid var(--rui-chart-tooltip-border);
}

.railsui-chart-tooltip__title {
  font-weight: 600;
}

.railsui-chart-tooltip__delta {
  font-weight: 600;
}

.railsui-chart-tooltip__delta--positive { color: var(--rui-chart-positive); }
.railsui-chart-tooltip__delta--negative { color: var(--rui-chart-negative); }
.railsui-chart-tooltip__delta--neutral { color: var(--rui-chart-tooltip-muted); }

.railsui-chart-tooltip__rows {
  width: 100%;
  border-collapse: collapse;
}

.railsui-chart-tooltip__rows th {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.0625rem 0.75rem 0.0625rem 0;
  font-weight: 400;
  text-align: left;
  color: var(--rui-chart-tooltip-muted);
  white-space: nowrap;
}

/* Values line up in a column, so they read tabular here even though the
   card's headline figure does not. */
.railsui-chart-tooltip__rows td {
  padding: 0.0625rem 0;
  text-align: right;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.railsui-chart-tooltip__key {
  width: 0.5rem;
  height: 0.5rem;
  flex-shrink: 0;
  border-radius: 0.125rem;
}
