@layer infine.components {
/* =============================================================
   Roster stats panel — clickable breakdowns under the title bar.
   One header row (title + the chart-set filters as clearable
   chips), then a single tile row. Country scope: a Connect-usage
   tile plus one tile per metric pairing that metric's average ring
   with its own band histogram. All-RC scope: one league tile with
   ranked country rows (supplier count, usage bar, paired average
   bars on a shared 0–100% axis).

   Two colour vocabularies, and they do not overlap:
     navy        — aggregate and structure (ring arcs, league bars)
     amber/green — per-band completeness, the SAME language the
                   roster table's .connect-roster-bar__fill speaks
                   a couple of hundred pixels further down the page
   Company and Product are told apart by tile position and label,
   never by hue.
   ============================================================= */

.connect-roster-stats {
    padding: 0 var(--mantine-spacing-xl) var(--mantine-spacing-xl);
    color: var(--infine-blue);
    font-family: var(--mantine-font-family);

    /* The completeness palette, keyed by the bands `ui.field/pct-band`
       returns — the exact structure .connect-roster-bar__fill--low/mid/high/
       full uses in the table below, and for the same reason: today all three
       partial bands are one amber, but keeping them split lets a future
       palette re-introduce gradation without touching any cljs. Read by the
       ring arcs and the league bars via `pct-var`. */
    --connect-rs-pct-low: var(--infine-yellow-bright);
    --connect-rs-pct-mid: var(--infine-yellow-bright);
    --connect-rs-pct-high: var(--infine-yellow-bright);
    --connect-rs-pct-full: var(--infine-green-bright);

    animation: connect-rs-in 260ms ease both;
}

/* --- Panel header ---
   The heading itself is the shared `.connect-section-head` (connect-roster.css)
   so this panel and the supplier list below introduce themselves identically.
   Only the filter chips are panel-specific. */

.connect-roster-stats__chip-label {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.connect-roster-stats__chip-label em {
    font-style: normal;
    opacity: 0.7;
}

/* --- Tiles --- */

.connect-roster-stats__row {
    display: flex;
    gap: var(--mantine-spacing-md);
    align-items: stretch;
}

.connect-roster-stats__tile {
    padding: 14px;
    background: var(--infine-blue-bg-tint);
    /* The hairline is what makes this read as a Connect surface rather than a
       chart widget — every other grouped box on the site has one. */
    border: 1px solid var(--infine-blue-light-fade);
    border-radius: 14px;
    display: flex;
    flex-direction: column;
    gap: var(--mantine-spacing-sm);
}

.connect-roster-stats__tile-title {
    font-family: var(--mantine-font-family-headings);
    font-weight: 700;
    font-size: 15px;
    align-self: flex-start;
}

/* The one axis-caption style, shared by the ring's and the histogram's. They
   are peers naming two charts, so they must not differ in size, weight, case
   or colour — one of them looking like a heading and the other like a
   footnote is what made the pair read as unrelated. Centred to its own graph,
   both on the tile's last line. */
.connect-roster-stats__caption {
    font-family: var(--mantine-font-family-headings);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 9.5px;
    line-height: 1.3;
    color: var(--infine-gray);
    text-align: center;
    white-space: nowrap;
}

/* The usage tile gives up width to the two metric tiles as the page narrows. */
.connect-roster-stats__tile--usage {
    flex: 0 1 340px;
    min-width: 0;
}

.connect-roster-stats__tile--metric {
    flex: 1 1 0;
    min-width: 0;
}

/* Only the body centres in the leftover height — the title stays at the top
   of the tile so all three headings on the row sit on one line. */
.connect-roster-stats__usage-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--mantine-spacing-sm);
}

/* Ring left, that metric's own histogram right. Pairing the aggregate with
   the distribution of the SAME metric is the point of the layout.
   `stretch` (not `center`) so the histogram grows into whatever height the
   row settles at — the usage tile drives it — instead of leaving a band of
   dead space above and below a fixed-height chart. */
.connect-roster-stats__metric-body {
    flex: 1;
    display: flex;
    align-items: stretch;
    gap: var(--mantine-spacing-md);
    min-width: 0;
}

/* Stretches (rather than centring) so its caption sits on the same last line
   as the histogram's; __ring-body takes the slack, so the ring itself still
   centres in the space above the caption. */
.connect-roster-stats__ring {
    flex: 0 0 auto;
    align-self: stretch;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}

.connect-roster-stats__ring-body {
    flex: 1;
    display: flex;
    align-items: center;
}

.connect-roster-stats__usage-headline {
    font-family: var(--mantine-font-family-headings);
    /* Light, like every other large numeral in Connect (.co-donut__pct,
       .co-lede__h, .connect-title-bar__heading). An 800 here fought the
       300-weight page title 60px above it. */
    font-weight: 300;
    font-size: 34px;
    line-height: 1.1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
}

/* The .co-donut__pct em pattern: the qualifier sits under the number instead
   of competing with it. */
.connect-roster-stats__usage-headline-suffix {
    font-size: 15px;
    font-weight: 400;
    letter-spacing: 0;
    color: var(--infine-gray);
}

/* --- Ring gauges (display, not filters) --- */

.connect-roster-stats__ring-label {
    display: block;
    text-align: center;
    font-family: var(--mantine-font-family-headings);
    font-weight: 300;
    font-size: 26px;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--infine-blue);
}

/* The unit reads as a unit, not as part of the figure — the Overview hero's
   .co-donut__pct em treatment, scaled down. It does NOT inherit the figure's
   300 weight: Raleway Light at 13px is too fine to survive, so the unit trades
   size for weight and a darker ink to stay legible while still reading as
   secondary to the number. */
.connect-roster-stats__ring-label em {
    font-style: normal;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--infine-gray-active);
    margin-left: 1px;
}

/* --- Usage bar (100%-stacked, segments are real buttons) --- */

.connect-roster-stats__bar {
    display: flex;
    width: 100%;
    height: 44px;
    border-radius: var(--mantine-radius-sm);
    overflow: hidden;
    gap: 2px;
}

/* No inline label in the league rows — the split is in the tooltip, so the
   bar is free to be just the shape. */
.connect-roster-stats__bar--slim {
    height: 18px;
}

.connect-roster-stats__bar-seg {
    border: none;
    padding: 0;
    /* flex-grow (set inline per segment) carries the count share; the tiny
       flex-basis keeps a 1-count segment visible next to a 20-count one. */
    flex-basis: 6px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--mantine-font-size-sm);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--infine-blue);
    transition: filter 120ms ease;
}

.connect-roster-stats__bar-seg--on-dark {
    color: var(--mantine-color-white);
}

.connect-roster-stats__bar-seg:hover:not(:disabled) {
    filter: brightness(1.08);
}

/* The league's no-single-country row has nothing to scope a filter to, so its
   segments still carry the shape and the tooltip but not the affordance. */
.connect-roster-stats__bar-seg:disabled {
    cursor: default;
}

/* Selection is additive — the chosen segment gains an outline and everything
   else keeps its colour. Dimming the rest turned the panel grey exactly when
   it was doing its job. The offset is negative because segments sit 2px
   apart; a positive one would overlap the neighbours. */
.connect-roster-stats__bar-seg--selected {
    outline: 2px solid var(--infine-blue-bright);
    outline-offset: -2px;
}

.connect-roster-stats__bar-empty {
    font-size: var(--mantine-font-size-xs);
    color: var(--infine-gray);
    align-self: center;
}

/* --- Progress histogram (bands on x, columns are real buttons) --- */

.connect-roster-stats__hist {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-width: 0;
    gap: 8px;
}

.connect-roster-stats__hist-track {
    display: flex;
    gap: 6px;
    flex: 1;
    min-height: 110px;
}

.connect-roster-stats__hist-band {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
}

/* The bins are NOT equal: 0–25, 26–50, 51–75 and 76–99 each span ~25 points,
   while 100% spans exactly one value. Drawing all five the same width is a
   plain histogram error, and it also hid the more useful reading — that
   "done" is a terminal state rather than a fifth step. So the last bin is
   narrowed toward its true share and pushed off the run of quarters by an
   extra gap. It is not narrowed all the way to 1/101 of the axis: at ~4px it
   would be neither legible nor clickable, and it is the one column anyone
   actually wants to watch grow. */
.connect-roster-stats__hist-band:last-child {
    position: relative;
    flex: 0.55 1 0;
    margin-left: 16px;
}

/* A hairline in the widened gap, so the last bin reads as a category break
   rather than as a column that came out oddly thin. Drawn as a pseudo-element
   centred in the margin, so it costs the column no width. */
.connect-roster-stats__hist-band:last-child::before {
    content: "";
    position: absolute;
    left: -9px;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--infine-blue-light-fade);
}

.connect-roster-stats__hist-plot {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: 3px;
}

.connect-roster-stats__hist-count {
    text-align: center;
    font-size: var(--mantine-font-size-xs);
    line-height: 1;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--infine-gray-active);
    min-height: 12px;
}

.connect-roster-stats__hist-bar {
    border: none;
    padding: 0;
    border-radius: 3px 3px 0 0;
    cursor: pointer;
    transition: filter 120ms ease, height 200ms ease;
    transform-origin: bottom;
    animation: connect-rs-grow 320ms cubic-bezier(0.2, 0.7, 0.3, 1) backwards;
}

/* Column colour is the roster table's own completeness rule, not a per-metric
   hue: short of 100% is amber, 100% is green — the same statement
   .connect-roster-bar__fill--low/mid/high/full makes in the rows below. The
   four amber bands are kept as separate classes for the same reason that rule
   keeps four: a future palette can re-introduce gradation here without
   touching the cljs. */
.connect-roster-stats__hist-bar--band-1 { background: var(--connect-rs-pct-low); }
.connect-roster-stats__hist-bar--band-2 { background: var(--connect-rs-pct-mid); }
.connect-roster-stats__hist-bar--band-3,
.connect-roster-stats__hist-bar--band-4 { background: var(--connect-rs-pct-high); }
.connect-roster-stats__hist-bar--band-5 { background: var(--connect-rs-pct-full); }

/* Zero columns keep their axis slot visible as a faint baseline stub. This
   used to be an off-palette grey mix, because on the old magenta product ramp
   a blue stub read as the other metric's colour. Metric hue-coding is gone,
   so the constraint is gone with it and the stub can be the house hairline. */
.connect-roster-stats__hist-bar--zero {
    background: var(--infine-blue-light-fade);
    cursor: default;
}

.connect-roster-stats__hist-bar:hover {
    filter: brightness(1.08);
}

.connect-roster-stats__hist-bar--selected {
    outline: 2px solid var(--infine-blue-bright);
    outline-offset: 2px;
}

/* Stagger the columns left to right so the reveal reads in the same direction
   the axis does. */
.connect-roster-stats__hist-band:nth-child(1) .connect-roster-stats__hist-bar { animation-delay: 0ms; }
.connect-roster-stats__hist-band:nth-child(2) .connect-roster-stats__hist-bar { animation-delay: 40ms; }
.connect-roster-stats__hist-band:nth-child(3) .connect-roster-stats__hist-bar { animation-delay: 80ms; }
.connect-roster-stats__hist-band:nth-child(4) .connect-roster-stats__hist-bar { animation-delay: 120ms; }
.connect-roster-stats__hist-band:nth-child(5) .connect-roster-stats__hist-bar { animation-delay: 160ms; }

/* Band label under each column — the histogram's x-axis. At rest it matches
   the roster table's own column headers (xs / 600 / uppercase tracking), so
   the two read as one system; the filled navy pill is reserved for the ACTIVE
   band, where it means "this is the filter" instead of being decoration on
   all ten ticks at once. */
.connect-roster-stats__hist-band-label {
    text-align: center;
    font-size: var(--mantine-font-size-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--infine-gray-active);
    border-radius: var(--mantine-radius-sm);
    padding: 3px 2px;
    margin-top: 8px;
    white-space: nowrap;
}

.connect-roster-stats__hist-band-label--active {
    background: var(--infine-blue);
    color: var(--mantine-color-white);
}

/* --- Small-type legends --- */

.connect-roster-stats__legend {
    display: flex;
    flex-wrap: wrap;
    gap: 2px var(--mantine-spacing-sm);
    font-size: var(--mantine-font-size-xs);
    color: var(--infine-gray-active);
}

.connect-roster-stats__legend-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

.connect-roster-stats__legend-swatch {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    flex-shrink: 0;
}

/* --- All-RC scope: ranked league --- */

.connect-roster-stats__tile--league {
    flex: 1 1 auto;
}

/* One column per metric, each with its own labelled 0–100% axis, so the two
   averages are told apart by position exactly as they are in the country
   tiles — no colour coding anywhere in the panel. Together they hold the same
   half of the width the single shared axis used to; the rest goes to the
   usage bar. */
.connect-roster-stats__league {
    display: grid;
    grid-template-columns: 140px 90px minmax(0, 1fr) 25% 25%;
    column-gap: var(--mantine-spacing-lg);
    align-items: center;
}

/* Rows are subgrid, NOT display:contents. A display:contents element
   generates no box, so it can carry no border, padding, hover fill or focus
   ring — which is exactly why the rows used to blur into each other. Subgrid
   keeps the cells on the shared column tracks while the row is a real box. */
.connect-roster-stats__league-row {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
    align-items: center;
    padding: 3px 0;
    border-bottom: 1px solid var(--infine-blue-light-fade);
    transition: background-color 120ms ease;
}

/* The axis row follows immediately; a border here would read as a second
   rule stacked on it. Matched via :has, NOT :last-of-type — the rows and the
   two foot rows are all divs, so :last-of-type resolves to the legend foot
   and no league row ever matched it. */
.connect-roster-stats__league-row:has(+ .connect-roster-stats__league-foot) {
    border-bottom: none;
}

.connect-roster-stats__league-row:hover {
    background-color: var(--infine-blue-bg);
}

.connect-roster-stats__league-foot {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
}

/* The two axes belong under the two completeness columns; placing the first
   explicitly lets the second auto-flow into the one beside it. */
.connect-roster-stats__league-foot--axes > :first-child { grid-column: 4; }
.connect-roster-stats__league-legend--usage { grid-column: 3; }

.connect-roster-stats__league-head {
    font-size: var(--mantine-font-size-xs);
    font-weight: 600;
    font-family: var(--mantine-font-family-headings);
    color: var(--infine-gray-active);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding-bottom: 6px;
}

.connect-roster-stats__league-name {
    /* Button reset — reads as a link-like row header. */
    border: none;
    background: none;
    padding: 0;
    cursor: pointer;
    text-align: left;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    color: var(--infine-blue);
    font-family: var(--mantine-font-family-headings);
    font-weight: 600;
    font-size: var(--mantine-font-size-md);
    transition: color 120ms ease;
}

.connect-roster-stats__league-name:disabled {
    cursor: default;
    color: var(--infine-gray);
}

/* Clicking the name navigates, so the row telegraphs it on hover the way the
   roster's own rows do — an affordance that appears, not just a colour shift. */
.connect-roster-stats__league-name-chevron {
    opacity: 0;
    transform: translateX(-3px);
    transition: opacity 120ms ease, transform 120ms ease;
}

.connect-roster-stats__league-row:hover .connect-roster-stats__league-name:not(:disabled) {
    color: var(--infine-blue-bright);
}

.connect-roster-stats__league-row:hover .connect-roster-stats__league-name:not(:disabled) .connect-roster-stats__league-name-chevron {
    opacity: 1;
    transform: translateX(0);
}

/* Supplier-count bar: light track proportional to the biggest country,
   count printed on top of it. */
.connect-roster-stats__league-n {
    position: relative;
    height: 20px;
    display: flex;
    align-items: center;
}

.connect-roster-stats__league-n i {
    position: absolute;
    inset: 2px auto 2px 0;
    background: var(--infine-blue-light-fade);
    border-radius: 4px;
}

.connect-roster-stats__league-n b {
    position: relative;
    font-size: var(--mantine-font-size-xs);
    font-weight: 700;
    padding-left: 7px;
    font-variant-numeric: tabular-nums;
}

/* The cell is the track plus reserved trailing room, so a value sitting just
   past a 100% bar's tip still has somewhere to go. The value follows its own
   bar rather than right-aligning into a column: company averages end near the
   halfway mark, and parked at the cell's right edge their numbers sat against
   the NEXT column's bars and read as belonging to those. */
.connect-roster-stats__league-cell {
    --league-val-room: 38px;
    display: flex;
    align-items: center;
    padding-right: var(--league-val-room);
}

/* One average bar per column, on its own axis box; the faint 25%-step
   gridlines make the axis readable without per-row labels. */
.connect-roster-stats__league-track {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 22px;
    padding: 3px 0;
    background: repeating-linear-gradient(
        to right,
        var(--infine-blue-light-fade) 0 1px,
        transparent 1px 25%);
    border-left: 1px solid var(--infine-blue-light-fade);
    border-right: 1px solid var(--infine-blue-light-fade);
}

.connect-roster-stats__league-line {
    position: relative;
    height: 12px;
}

/* Colour says completeness, not which metric — the column header says which
   metric. Fill comes from `pct-var` inline, on the same rule as the table. */
.connect-roster-stats__league-bar {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: 0 4px 4px 0;
}

/* Always OUTSIDE the bar — neither white nor navy clears 4.5:1 against both
   amber (#FF7E05) and green (#179900), so an on-bar label is not available
   now that the bar carries the completeness colour. `left` is the bar tip;
   the 6px pushes clear of it. */
.connect-roster-stats__league-val {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    margin-left: 6px;
    font-size: var(--mantine-font-size-xs);
    font-weight: 700;
    color: var(--infine-gray-active);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Axis labels under the completeness column. */
/* The right inset matches the cell's reserved value room so the ticks line up
   with the track above them, not with the whole cell. */
.connect-roster-stats__league-axis {
    position: relative;
    height: 18px;
    padding-top: 2px;
    margin-right: 38px;
}

.connect-roster-stats__league-axis span {
    position: absolute;
    top: 2px;
    font-size: var(--mantine-font-size-xs);
    color: var(--infine-gray-active);
    font-variant-numeric: tabular-nums;
    transform: translateX(-50%);
}

.connect-roster-stats__league-axis .connect-roster-stats__league-axis-end {
    transform: translateX(-100%);
}

/* --- Keyboard focus ---
   Every chart mark is a real button, and the progress-band filter has NO
   dropdown equivalent in the filter bar — the histogram is the only way to
   reach it. Without a visible ring these controls are unreachable in practice
   for keyboard users, so this is correctness, not polish. */
.connect-roster-stats__bar-seg:focus-visible,
.connect-roster-stats__hist-bar:focus-visible,
.connect-roster-stats__league-name:focus-visible {
    outline: 2px solid var(--infine-blue-bright);
    outline-offset: 2px;
    border-radius: 2px;
}

.connect-roster-stats__bar-seg:focus-visible {
    outline-offset: -2px;
}

/* --- Motion --- */

@keyframes connect-rs-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}

@keyframes connect-rs-grow {
    from { transform: scaleY(0); }
    to   { transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
    .connect-roster-stats,
    .connect-roster-stats__hist-bar {
        animation: none;
    }
    .connect-roster-stats__hist-bar,
    .connect-roster-stats__bar-seg,
    .connect-roster-stats__league-row,
    .connect-roster-stats__league-name,
    .connect-roster-stats__league-name-chevron {
        transition: none;
    }
}
}
