/*
 * The charts and figures of kiopstudio/chart (templates/components/),
 * loaded with the controller (package.json, "autoimport").
 *
 * Every series sets --chart-series, and its lines, bars, slices and legend
 * swatch take that one colour. The palette goes in turn (chart__series--1 to
 * --8, see Chart::PALETTE_SIZE); a series may name its colour instead - the
 * application gives .chart__series--<name> its --chart-series.
 *
 * The colours are Bootstrap's custom properties, with fallbacks. Grid and
 * text are set without weight (:where), so an application sets
 * --chart-grid and --chart-text on .chart without caring which stylesheet
 * comes first.
 */
:where(.chart) {
    --chart-grid: var(--bs-border-color, #dee2e6);
    --chart-text: var(--bs-secondary-color, rgba(33, 37, 41, 0.75));
}

.chart {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.chart__svg {
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
}

/* In a table row the chart is one line high, however wide the column */
.chart--cell {
    min-width: 5rem;
}

.chart--cell .chart__svg {
    height: 1.5rem;
}

.chart--donut:not(.chart--cell) {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem 1.5rem;
    align-items: center;
}

.chart--donut:not(.chart--cell) .chart__svg {
    width: auto;
    max-width: 100%;
    height: 12rem;
}

.chart--donut.chart--sm .chart__svg {
    height: 8rem;
}

.chart--donut.chart--lg .chart__svg {
    height: 16rem;
}

.chart--donut.chart--cell .chart__svg {
    width: 1.5rem;
}

.chart__series--1 { --chart-series: var(--bs-primary, #0d6efd); }
.chart__series--2 { --chart-series: var(--bs-orange, #fd7e14); }
.chart__series--3 { --chart-series: var(--bs-teal, #20c997); }
.chart__series--4 { --chart-series: var(--bs-purple, #6f42c1); }
.chart__series--5 { --chart-series: var(--bs-pink, #d63384); }
.chart__series--6 { --chart-series: var(--bs-cyan, #0dcaf0); }
.chart__series--7 { --chart-series: var(--bs-indigo, #6610f2); }
.chart__series--8 { --chart-series: #b08900; }

.chart__grid {
    stroke: var(--chart-grid);
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

.chart__grid--zero {
    stroke: var(--chart-text);
}

.chart__tick,
.chart__label {
    font-size: 11px;
    fill: var(--chart-text);
}

/*
 * A strip: as wide as its place, but never higher than its viewBox - as
 * high as a small donut -, so a wide card does not make it nor its labels
 * grow
 */
.chart--wide .chart__svg {
    max-height: 112px;
}

/*
 * SVG text grows with the chart, and a small chart is drawn wider than its
 * viewBox - smaller units keep its labels the size of the others
 */
.chart--sm .chart__tick,
.chart--sm .chart__label {
    font-size: 9px;
}

.chart__line {
    fill: none;
    stroke: var(--chart-series);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}

.chart--sparkline .chart__line {
    stroke-width: 1.5;
}

.chart__point {
    fill: var(--bs-body-bg, #fff);
    stroke: var(--chart-series);
    stroke-width: 2;
    vector-effect: non-scaling-stroke;
}

.chart__bar {
    fill: var(--chart-series);
}

.chart__point:hover,
.chart__bar:hover,
.chart__slice:hover {
    opacity: 0.75;
}

.chart__track {
    fill: none;
    stroke: var(--bs-tertiary-bg, #f8f9fa);
}

.chart__slice {
    fill: none;
    stroke: var(--chart-series);
}

.chart__total {
    font-weight: 700;
    fill: var(--bs-body-color, #212529);
}

.chart__empty {
    color: var(--chart-text);
    font-size: 0.875rem;
}

/*
 * hbar: each row the name and the figure on a line, the bar under them -
 * a long name is cut off before the figure
 */
.chart__rows {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 0.875rem;
}

.chart__row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) max-content;
    gap: 0.25rem 0.75rem;
    align-items: baseline;
}

.chart__row-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.chart__row-value {
    color: var(--chart-text);
    text-align: right;
}

.chart__row-track {
    display: block;
    grid-column: 1 / -1;
    height: 0.5rem;
    border-radius: 0.25rem;
    background: var(--chart-grid);
}

.chart__row-bar {
    display: block;
    height: 100%;
    border-radius: 0.25rem;
    background: var(--chart-series);
}

.chart__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1rem;
    margin: 0.5rem 0 0;
    padding: 0;
    list-style: none;
    font-size: 0.875rem;
}

.chart--donut .chart__legend,
.chart--by-label .chart__legend {
    flex-direction: column;
    margin: 0;
}

/*
 * Bars coloured by their labels: the legend beside them, as a donut's - at
 * most four entries high, the next ones in a column beside, so more labels
 * never make the chart higher. The bars keep at least half the width; where
 * the rest is too narrow, a long name is cut (its title tells it whole).
 */
.chart--by-label {
    display: flex;
    gap: 0.75rem;
    align-items: center;
}

.chart--by-label .chart__svg {
    flex: 1 1 0;
    min-width: 50%;
}

.chart--by-label .chart__legend {
    display: grid;
    flex: 0 1 auto;
    grid-template-rows: repeat(4, auto);
    grid-auto-flow: column;
    gap: 0.125rem 1rem;
    min-width: 0;
    font-size: 0.8125rem;
}

.chart--by-label .chart__legend-item {
    min-width: 0;
}

.chart--by-label .chart__legend-label {
    min-width: 3rem;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chart__legend-item {
    display: flex;
    gap: 0.375rem;
    align-items: center;
    white-space: nowrap;
}

.chart__swatch {
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 0.125rem;
    background: var(--chart-series);
}

/*
 * Pointer box (chart_controller.js): a line at the label nearest the
 * pointer, its points and bars lit, and a box with the figures beside it
 */
.chart[data-controller~="chart"] {
    position: relative;
}

.chart__guide {
    stroke: var(--chart-text);
    stroke-width: 1;
    stroke-dasharray: 3 3;
    vector-effect: non-scaling-stroke;
    pointer-events: none;
}

.chart__point.is-active {
    fill: var(--chart-series);
}

.chart__bar.is-active,
.chart__slice.is-active {
    opacity: 0.75;
}

.chart__hover {
    position: absolute;
    top: 0.5rem;
    z-index: 2;
    min-width: 9rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 0.5rem;
    background: var(--bs-body-bg, #fff);
    box-shadow: var(--bs-box-shadow-sm, 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075));
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

.chart__hover-title {
    margin-bottom: 0.25rem;
    font-weight: 700;
}

.chart__hover-row {
    display: flex;
    gap: 0.375rem;
    align-items: center;
    white-space: nowrap;
}

.chart__hover-value {
    margin-left: auto;
    padding-left: 0.75rem;
    font-weight: 600;
}

.chart__hover-row--total {
    margin-top: 0.25rem;
    padding-top: 0.25rem;
    border-top: 1px solid var(--bs-border-color, #dee2e6);
}

/*
 * Figures: a figure against its budget (Progress) and a figure with its
 * change (Stat). Green, amber and red mean met, close and missed.
 *
 * Their colours are custom properties set without weight (:where), so an
 * application sets --figure-muted, --figure-good and --figure-bad on
 * .progress-figure and .stat - or above them - without caring which
 * stylesheet comes first. The single bar is Bootstrap's .progress, its
 * colours Bootstrap's custom properties, with fallbacks.
 */
:where(.progress-figure, .stat) {
    /* Muted text: the overrun's note, the label, what the change compares with */
    --figure-muted: #6b6b6b;
    /* Within the budget, a change for the better */
    --figure-good: #1f7a3d;
    /* Beyond the budget, a change for the worse */
    --figure-bad: #b23b2e;
}

.progress-figure {
    min-width: 7rem;
    font-variant-numeric: tabular-nums;
}

.progress-figure__figures {
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
    font-size: 0.875rem;
    white-space: nowrap;
}

.progress-figure__note {
    color: var(--figure-muted);
}

/* The share alone tells an overrun by its colour as well */
.progress-figure--over .progress-figure__value--percent {
    color: var(--figure-bad);
    font-weight: 700;
}

.progress-figure__bar {
    height: 0.375rem;
    margin-top: 0.25rem;
}

.progress-figure--ok .progress-bar {
    background-color: var(--bs-primary, #0d6efd);
}

.progress-figure--warn .progress-bar {
    background-color: var(--bs-warning, #ffc107);
}

/* compare: the figure thick on top, the budget a third as high below, both on
   one scale - an overrun shows as the top bar reaching past the bottom one.
   Narrow enough for half a column: the overrun may go to a line of its own */
.progress-figure--compare {
    min-width: 0;
}

.progress-figure--compare .progress-figure__figures {
    flex-wrap: wrap;
    gap: 0 0.5rem;
}

.progress-figure__bars {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    margin-top: 0.25rem;
}

.progress-figure__worked {
    height: 0.5625rem;
    border-radius: 0.125rem;
    background-color: var(--bs-primary, #0d6efd);
}

.progress-figure__planned {
    height: 0.1875rem;
    border-radius: 0.125rem;
    background-color: var(--bs-gray-500, #adb5bd);
}

/* Within the budget green, beyond it red - no amber warning here: the thin bar
   below already shows how close the end is */
.progress-figure--compare.progress-figure--ok .progress-figure__worked,
.progress-figure--compare.progress-figure--warn .progress-figure__worked {
    background-color: var(--figure-good);
}

.progress-figure--over .progress-figure__worked {
    background-color: var(--figure-bad);
}

.progress-figure--over .progress-bar {
    background-color: var(--figure-bad);
}

.progress-figure--over .progress-figure__note {
    color: var(--figure-bad);
    font-weight: 700;
}

.stat {
    font-variant-numeric: tabular-nums;
}

.stat__label {
    color: var(--figure-muted);
    font-size: 0.875rem;
}

.stat__line {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.75rem;
    align-items: baseline;
}

.stat__value {
    font-weight: 800;
    font-size: 1.75rem;
    line-height: 1.2;
}

.stat__change {
    display: inline-flex;
    gap: 0.25rem;
    align-items: center;
    padding: 0.125rem 0.5rem;
    border-radius: 50rem;
    font-size: 0.875rem;
    font-weight: 600;
    white-space: nowrap;
}

.stat__change--good {
    color: var(--figure-good);
    background-color: var(--bs-success-bg-subtle, #d1e7dd);
}

.stat__change--bad {
    color: var(--figure-bad);
    background-color: var(--bs-danger-bg-subtle, #f8d7da);
}

.stat__change--neutral {
    color: var(--figure-muted);
    background-color: var(--bs-tertiary-bg, #f8f9fa);
}

.stat__compare {
    margin-top: 0.125rem;
    color: var(--figure-muted);
    font-size: 0.8125rem;
}

/* In a table row: the figure the size of the text around it */
.stat--sm .stat__value {
    font-weight: 600;
    font-size: 1rem;
}

.stat--sm .stat__change {
    padding: 0 0.375rem;
    font-size: 0.8125rem;
}
