/* ═══════════════════════════════════════════════════════════
   Charts & statistics — the reporting surface.

   For ScanEasy's statistics pages: stock reports, movement history,
   throughput, and the specialised reports that get generated and exported.
   Built from the same tokens as everything else, so a report screen reads
   as part of the product rather than a bolted-on analytics tool.

   THE SERIES PALETTE IS COMPUTED, NOT CHOSEN. Every colour below was run
   through a six-check validator (lightness band, chroma floor, colour-vision
   separation, normal-vision separation, contrast vs the plot surface) in
   BOTH modes. Notes on what that changed:

   • The brand teal (#0D7377) is NOT series 1. At chart scale its chroma
     (0.083) falls under the floor — as a small mark it reads grey rather
     than teal. Series 1 is a raised-chroma teal that still reads as the
     family.
   • Green and rose sat adjacent in the first draft at ΔE 2.2 for
     deuteranopes — effectively the same colour for ~5% of men. Reordered so
     no adjacent pair collides.
   • Dark mode is a SEPARATE set of steps, not the light one reused: reused
     light steps measured under 3:1 against the dark card. The dark steps
     also need a recessed plot surface (--tn-chart-surface) to clear it,
     which is why the plot area is darker than the card it sits in.

   Rules that come with the palette, not optional decoration:
   - Assign series in fixed order. A 9th series is never a new hue — fold it
     into "Other" or facet the chart.
   - Colour follows the entity, never its rank; filtering must not repaint
     the survivors.
   - Status colours (--tn-success etc) are reserved for state and never
     reused as "series 4".
   - Text keeps text tokens. A value label is never painted in its series
     colour; the mark beside it carries the identity.
   ═══════════════════════════════════════════════════════════ */

:root {
    /* Plot surface — the ground marks are measured against */
    --tn-chart-surface: var(--tn-bg-card);
    --tn-chart-grid: var(--tn-border-light);

    /* Categorical series, fixed order */
    --tn-series-1: #0E9594;
    --tn-series-2: #C77800;
    --tn-series-3: #3B5BDB;
    --tn-series-4: #D6336C;
    --tn-series-5: #7048E8;
    --tn-series-6: #2F9E44;

    /* Sequential ramp — one hue, light to dark, for magnitude */
    --tn-seq-1: #E0F2F1;
    --tn-seq-2: #A7DAD6;
    --tn-seq-3: #6DC1BC;
    --tn-seq-4: #2FA79F;
    --tn-seq-5: #0E7C77;
}

/* Dark mode isn't a flip — these are their own validated steps, and they
   need the recessed plot surface below to clear 3:1. */
html[data-theme="philip-dark"],
html[data-theme="dark-blue"] {
    --tn-chart-surface: #2E3440;
    --tn-chart-grid: rgba(255, 255, 255, 0.09);

    --tn-series-1: #1FA894;
    --tn-series-2: #C4841F;
    --tn-series-3: #6B84EC;
    --tn-series-4: #DF5386;
    --tn-series-5: #8F72E6;
    --tn-series-6: #55A755;

    --tn-seq-1: #1B3A3B;
    --tn-seq-2: #235B58;
    --tn-seq-3: #2F7D77;
    --tn-seq-4: #3FA096;
    --tn-seq-5: #58C4B7;
}

/* ═══════════════ Stat tiles ═══════════════
   A single number is often the right answer instead of a chart. The delta
   carries an arrow AND a sign, so direction never depends on colour alone. */
.tn-stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: var(--tn-space-md);
}

.tn-stat {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: var(--tn-space-lg);
    background: var(--tn-bg-card);
    border: 1px solid var(--tn-border);
    border-radius: var(--tn-radius-lg);
}

.tn-stat-label {
    font-size: var(--tn-font-size-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--tn-text-secondary);
}

.tn-stat-value {
    font-size: clamp(1.5rem, 1.1rem + 1.2vw, 2rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--tn-text-primary);
    /* Digits line up across tiles and across updates */
    font-variant-numeric: tabular-nums;
}

.tn-stat-unit {
    font-size: 0.5em;
    font-weight: 600;
    color: var(--tn-text-secondary);
    margin-left: 4px;
}

.tn-stat-delta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: var(--tn-font-size-sm);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.tn-stat-delta--up { color: var(--tn-success-text, var(--tn-success)); }
.tn-stat-delta--down { color: var(--tn-danger-text, var(--tn-danger)); }
.tn-stat-delta--flat { color: var(--tn-text-muted); }

.tn-stat-note {
    font-size: var(--tn-font-size-xs);
    color: var(--tn-text-muted);
}

/* ═══════════════ Chart frame ═══════════════ */
.tn-chart {
    display: flex;
    flex-direction: column;
    gap: var(--tn-space-md);
    padding: var(--tn-space-lg);
    background: var(--tn-bg-card);
    border: 1px solid var(--tn-border);
    border-radius: var(--tn-radius-lg);
}

.tn-chart-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--tn-space-md);
    flex-wrap: wrap;
}

.tn-chart-title {
    margin: 0;
    font-size: var(--tn-font-size-lg);
    font-weight: 700;
    letter-spacing: -0.01em;
}

.tn-chart-sub {
    margin: 2px 0 0;
    font-size: var(--tn-font-size-sm);
    color: var(--tn-text-secondary);
}

/* Legend is always present for 2+ series — identity must never be colour
   alone. The swatch carries the colour; the label stays in text ink. */
.tn-chart-legend {
    display: flex;
    align-items: center;
    gap: var(--tn-space-md);
    flex-wrap: wrap;
}

.tn-chart-legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: var(--tn-font-size-sm);
    color: var(--tn-text-secondary);
}

.tn-chart-swatch {
    width: 10px;
    height: 10px;
    flex-shrink: 0;
    border-radius: 3px;
    background: var(--tn-series-1);
}

/* ── Plot area. Wide charts scroll inside their own box so the page never
   scrolls sideways. ── */
.tn-chart-plot {
    position: relative;
    overflow-x: auto;
    background: var(--tn-chart-surface);
    border-radius: var(--tn-radius);
}

/* ═══════════════ Bar chart (CSS-only) ═══════════════
   Enough for the common case — category vs magnitude — without pulling in a
   charting library. Grid lines sit behind, recessive. */
.tn-bars {
    display: flex;
    align-items: flex-end;
    gap: var(--tn-space-sm);
    height: 200px;
    padding: var(--tn-space-md) var(--tn-space-sm) 0;
    min-width: 100%;
}

.tn-bar-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    flex: 1 1 0;
    min-width: 34px;
    height: 100%;
}

/* The stack of segments within one column. 2px gaps between segments so
   adjacent fills read as separate marks rather than one blended block. */
.tn-bar-stack {
    display: flex;
    flex-direction: column-reverse;
    justify-content: flex-start;
    gap: 2px;
    width: 100%;
    max-width: 44px;
    height: 100%;
}

.tn-bar {
    width: 100%;
    background: var(--tn-series-1);
    /* Rounded only at the free end, anchored flat to the baseline */
    border-radius: 4px 4px 0 0;
    transition: filter var(--tn-transition);
}

.tn-bar-stack .tn-bar:not(:last-child) {
    border-radius: 0;
}

.tn-bar:hover {
    filter: brightness(1.08);
}

.tn-bar-label {
    font-size: var(--tn-font-size-xs);
    color: var(--tn-text-secondary);
    white-space: nowrap;
}

.tn-bar-value {
    font-size: var(--tn-font-size-xs);
    font-weight: 700;
    color: var(--tn-text-primary);
    font-variant-numeric: tabular-nums;
}

/* Series assignment — fixed order, applied by class not by position, so a
   filtered-out series never repaints the ones that remain. */
.tn-bar--s1 { background: var(--tn-series-1); }
.tn-bar--s2 { background: var(--tn-series-2); }
.tn-bar--s3 { background: var(--tn-series-3); }
.tn-bar--s4 { background: var(--tn-series-4); }
.tn-bar--s5 { background: var(--tn-series-5); }
.tn-bar--s6 { background: var(--tn-series-6); }

.tn-chart-swatch--s1 { background: var(--tn-series-1); }
.tn-chart-swatch--s2 { background: var(--tn-series-2); }
.tn-chart-swatch--s3 { background: var(--tn-series-3); }
.tn-chart-swatch--s4 { background: var(--tn-series-4); }
.tn-chart-swatch--s5 { background: var(--tn-series-5); }
.tn-chart-swatch--s6 { background: var(--tn-series-6); }

/* ── Horizontal magnitude rows — often more readable than vertical bars
   when categories have long names (which warehouse/article names do). ── */
.tn-barlist {
    display: flex;
    flex-direction: column;
    gap: var(--tn-space-sm);
}

.tn-barlist-row {
    display: grid;
    grid-template-columns: minmax(90px, 1fr) 3fr auto;
    align-items: center;
    gap: var(--tn-space-md);
}

.tn-barlist-label {
    font-size: var(--tn-font-size-sm);
    color: var(--tn-text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.tn-barlist-track {
    height: 10px;
    border-radius: 999px;
    background: var(--tn-bg-page);
    overflow: hidden;
}

.tn-barlist-fill {
    height: 100%;
    border-radius: 999px;
    background: var(--tn-series-1);
}

.tn-barlist-value {
    font-size: var(--tn-font-size-sm);
    font-weight: 700;
    color: var(--tn-text-primary);
    font-variant-numeric: tabular-nums;
}

/* ── Sparkline slot — a bare trend beside a number, no axes ── */
.tn-spark {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 32px;
}

.tn-spark-bar {
    flex: 1;
    min-width: 2px;
    border-radius: 1px;
    background: var(--tn-series-1);
    opacity: 0.45;
}

.tn-spark-bar:last-child {
    opacity: 1;
}

/* ═══════════════ Report builder ═══════════════
   The generate-and-export panel. Composition, mostly: .tn-card + form
   groups + .tn-segmented for the format toggle + a block button. Only the
   pieces the system didn't already have live here. */
.tn-report-range {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--tn-space-md);
}

@media (max-width: 560px) {
    .tn-report-range {
        grid-template-columns: 1fr;
    }
}

/* A run that takes time needs a state, not a frozen button */
.tn-report-progress {
    display: flex;
    align-items: center;
    gap: var(--tn-space-sm);
    font-size: var(--tn-font-size-sm);
    color: var(--tn-text-secondary);
}

.tn-report-spinner {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    border: 2px solid var(--tn-border);
    border-top-color: var(--tn-accent);
    border-radius: 50%;
    animation: tnReportSpin 0.7s linear infinite;
}

@keyframes tnReportSpin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .tn-report-spinner {
        animation-duration: 2.4s;
    }
}

/* ── Mobile ── */
@media (max-width: 640px) {
    .tn-stat {
        padding: var(--tn-space-md);
    }

    .tn-barlist-row {
        grid-template-columns: 1fr auto;
    }

    /* The track drops to its own row rather than being crushed to a sliver */
    .tn-barlist-track {
        grid-column: 1 / -1;
        grid-row: 2;
    }
}
