/* css/vip-charts.css — the VIP 18 charts tab (js/vip-charts.js).
 *
 * Prefix `vch-` (DESIGN.md §4 registry). Tokens only, so both themes follow with nothing
 * wired up. Chart chrome is deliberately recessive: hairline solid rules, no gridlines, no
 * borders drawn around marks — a 2px surface gap does the separating (marks-and-anatomy).
 */

.vch-wrap { display: flex; flex-direction: column; gap: 26px;
             /* The cap's height — constant across every column, by design. Small, because
                the glass is a flat-faced panel and not a fat cylinder. */
             --vch-cap: 4px; }

/* ── the KPI row ───────────────────────────────────────────────
   Headline numbers are figures, not one-bar charts. Exactly ONE hero. */
.vch-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 10px; }
.vch-tile { display: flex; flex-direction: column; gap: 3px; padding: 14px 16px;
            background: var(--bg-2); border: 1px solid var(--border-1); border-radius: 14px; }
.vch-tile-v { font-size: 26px; font-weight: 700; line-height: 1.05; color: var(--text-1);
              /* Proportional figures on a standalone value — tabular-nums makes 121 look
                 loose at display sizes and is for columns that must align. */
              font-variant-numeric: proportional-nums; }
.vch-tile-l { font-size: 11.5px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-3); }
.vch-tile.is-hero { grid-column: span 2; border-color: var(--accent-border); background: var(--accent-glow-2); }
.vch-tile.is-hero .vch-tile-v { font-size: 48px; color: var(--accent); }

/* ── a chart ───────────────────────────────────────────────────── */
/* ⚠ `min-width: 0` IS REQUIRED, not tidiness. A flex item defaults to `min-width: auto`,
   which refuses to shrink below its content — so the scrolling column strip pushed its
   ancestors wide and the whole PAGE scrolled sideways (measured: .vip-wrap 669px inside a
   430px viewport) while `.vch-cols` itself never scrolled at all. The overflow must be
   allowed to land on the strip. */
.vch-fig { margin: 0; min-width: 0; }
.vch-plot { min-width: 0; }
.vch-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
            margin: 0 0 12px; }
.vch-title { font-size: 15px; font-weight: 700; color: var(--text-1); margin: 0; }
.vch-sub { font-size: 12.5px; line-height: 1.45; color: var(--text-2); margin: 3px 0 0; max-width: 62ch; }
.vch-note { font-size: 11.5px; line-height: 1.45; color: var(--text-3); margin: 9px 0 0; }
.vch-toggle { flex: 0 0 auto; font: inherit; font-size: 11.5px; cursor: pointer;
              color: var(--text-2); background: var(--bg-2); border: 1px solid var(--border-2);
              border-radius: 999px; padding: 5px 12px; }
.vch-toggle[aria-pressed="true"] { color: var(--accent); border-color: var(--accent-border); background: var(--accent-glow); }
.vch-toggle:focus-visible, .vch-col:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── the columns ────────────────────────────────────────────────
   A 6px gap IS the separation between marks — no borders, no strokes drawn round a bar. */
.vch-plot[hidden] { display: none; }          /* ⚠ `hidden` loses to display (CLAUDE.md) */
/* ⚠ The PLOT scrolls sideways, never the page. 16 segment columns cannot fit a 390px phone
   at a legible width, and the alternative — squeezing them to 18px — costs the labels. */
/* 🔴 `flex-start`, NOT `flex-end`. Aligning the columns on their BOTTOM makes each tube's
   position depend on everything below it, so a label that wraps to two lines ("N. America")
   lifts that column's tube off the shared baseline — measured at 12.7px on the continents
   chart, more than the whole bar for Africa. Aligning on the TOP anchors every tube to the
   same Y, because the value row is one line and the stack is a fixed height; the labels then
   hang below and can be any height they like without touching the chart. A `min-height` on
   the chip alone would only ever be a magic number racing the longest label — this is the
   structural fix, and `drive-vipcharts.mjs` asserts the baselines are identical. */
.vch-cols { display: flex; align-items: flex-start; gap: 6px; overflow-x: auto;
            padding: 0 1px 2px;
            scrollbar-width: thin; }
.vch-col { flex: 1 1 0; min-width: 38px; display: flex; flex-direction: column;
           align-items: center; gap: 5px; border-radius: 8px; padding: 4px 2px; }

/* ── the tube ──────────────────────────────────────────────────
   The reference design (owner, 2026-09-08) is a rack of glass tubes with a coloured fill
   rising inside each. The EMPTY part of the tube is doing real work: it shows the ceiling the
   fill is measured against, which a bare column leaves to the reader's imagination.

   ⚠ A FLAT GLASS PANEL, lightly rounded (owner, 2026-09-08, in three passes: skewed isometric
   boxes → "curved and smooth" → "flatter, top and bottom more squarer"). Where it landed, and
   why each part is what it is:
     · the corners are a SMALL radius, not a capsule — the reference's panels are rectangles
       with softened corners, and a capsule reads as a test tube;
     · the depth is a shallow horizontal light→shade gradient rather than a strong one, so the
       glass reads as a panel catching light and not as a fat cylinder;
     · the cap is a flat 4px band with a 2px radius — enough to say "there is a top surface",
       far too shallow to read as an ellipse.
   A box cannot be smoothed by rounding a SKEWED face — that just bends a straight edge — which
   is why the isometric build had to be replaced rather than softened.

   ⚠ THE 3D IS STILL A MATERIAL, NOT A PROJECTION. The cap ellipse is the same height on every
   column in every chart and is drawn OUTSIDE the fill's box, so the fill's measured height is
   exactly `k × 100%` and the scale stays linear. `drive-vipcharts.mjs` asserts it every run.

   Every column grows from ONE baseline and every tube is the same height, so heights stay
   comparable by eye. `--vch-c` is the CHART's hue, set inline per figure. */
.vch-stack { position: relative; width: 100%; max-width: 24px; height: 132px;
             margin: var(--vch-cap) auto 0;
             /* Three layers: the cylinder's shading, then the glass tint doubled so the empty
                tube reads as a VESSEL rather than as page. Both tint layers are the same
                flipping token, so this needs nothing per theme. */
             background:
               linear-gradient(90deg, rgba(255, 255, 255, .07) 0%, transparent 30%,
                               transparent 70%, rgba(0, 0, 0, .11) 100%),
               linear-gradient(var(--glass-bg-3), var(--glass-bg-3)),
               var(--glass-bg-3);
             border: 1px solid var(--border-1);
             border-radius: 5px 5px 4px 4px; }

/* The rim — a flat top band, sitting above everything so the liquid reads as being down
   inside the glass rather than stuck on its front. */
.vch-stack::before {
  content: ''; position: absolute; left: -1px; right: -1px; z-index: 2;
  top: calc(-1 * var(--vch-cap) / 2 - 1px); height: var(--vch-cap);
  background: linear-gradient(var(--glass-bg-3), var(--glass-bg-3)), var(--glass-bg-3);
  border: 1px solid var(--border-1);
  border-radius: 3px;
}

/* The fill. Square at the top because the cap below IS its top edge. */
.vch-3d { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
          /* ⚠ THE FLOOR IS 2px AND MUST STAY SMALL. It exists so the smallest value still
             paints something, but a floor OVERSTATES the value it rescues — it is the one
             place this chart is not perfectly linear. At 4px the single warzone with one
             VIP 18 rendered at 3.6% of the tallest bar where the truth is 1.5%, and the
             driver's height∝value assertion failed on it (err 0.0217 against a 0.02
             tolerance) while every other column was accurate to 0.0002. At 2px the error is
             0.003 and the sliver is still visible. Raise this and you are inflating the
             smallest number on the page. */
          height: calc(var(--k, 0) * 100%); min-height: 2px;
          background:
            linear-gradient(90deg, rgba(255, 255, 255, .17) 0%, transparent 28%,
                            transparent 66%, rgba(0, 0, 0, .17) 100%),
            var(--vch-c, var(--accent));
          border-radius: 0 0 4px 4px; }

/* The liquid's own top surface — the same flat band, one step lighter. */
.vch-3d::before {
  content: ''; position: absolute; left: 0; right: 0;
  top: calc(-1 * var(--vch-cap) / 2); height: var(--vch-cap);
  background: linear-gradient(rgba(255, 255, 255, .34), rgba(255, 255, 255, .34)),
              var(--vch-c, var(--accent));
  border-radius: 3px;
}

/* The gloss — one soft VERTICAL highlight down the left of the barrel, which is where the
   specular sits on a cylinder. Above everything, inert to the pointer.

   ⚠ NOT `--glass-shine`. That token is `rgba(255,255,255,.06)` in dark but **`.80` in light**,
   where it is meant as a thin rim on a card edge — used as a full overlay it painted a
   near-opaque white band across every tube and swallowed the fill. `--glass-bg-3` is the right
   token here: it FLIPS (white-alpha in dark, ink-alpha in light) and is 4% in both, so the
   sheen stays a sheen on either ground. */
.vch-gloss { position: absolute; inset: 0; z-index: 3; pointer-events: none;
             border-radius: inherit;
             background: linear-gradient(90deg,
               transparent 4%,
               var(--glass-bg-3) 15%,
               var(--glass-bg-3) 24%,
               transparent 36%); }

/* "Other" is a fold, not a category — de-emphasised so it never competes with a real one. */
.vch-col.is-muted { --vch-c: var(--text-3); }
.vch-col.is-muted .vch-ckey { color: var(--text-3); }

/* Value on the cap, label under the baseline. Both are TEXT TOKENS — a mark carries the
   colour, text never does. */
/* ⚠ The value is the ONE place the chart's hue touches text, and it is legal because it is
   not carrying identity — there is a single series, so the colour says "this chart", the way
   the reference's big percentages do. Every hue clears 4.5:1 on both surfaces. */
.vch-cval { font-family: var(--font-data); font-size: 12px; font-weight: 700;
            font-variant-numeric: tabular-nums; color: var(--vch-c, var(--accent)); line-height: 1; }
/* The reference seats every label on its own little card under the tube; this is that,
   pared back to what a label needs — a frosted chip, no invented caption. */
.vch-ckey { display: flex; flex-direction: column; align-items: center; gap: 1px;
            width: 100%; text-align: center; line-height: 1.15; color: var(--text-2);
            background: var(--glass-bg-3); border: 1px solid var(--border-1);
            border-radius: 8px; padding: 5px 2px;
            /* Tidiness only: a floor of two lines' worth keeps the chips the same size so the
               row reads as one rack. The BASELINE is held by `align-items: flex-start` on the
               strip above, never by this. */
            min-height: 36px; justify-content: center; }
.vch-ck0 { font-size: 11px; }                  /* flag, or the whole short label */
.vch-ck1 { font-size: 9.5px; font-family: var(--font-data); color: var(--text-3); }

@media (hover: hover) and (pointer: fine) {
  .vch-col:hover { background: var(--bg-2); }
}

/* A strip that scrolls has to SAY it scrolls — the class is set from JS after measuring,
   because CSS cannot ask whether a box overflows. */
.vch-scrollnote { font-size: 11.5px; color: var(--text-3); margin: 7px 0 0; }

/* ── the table twin ────────────────────────────────────────────── */
.vch-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.vch-table[hidden] { display: none; }
.vch-table caption { text-align: left; font-size: 11.5px; color: var(--text-3); padding: 0 0 8px; }
.vch-table th, .vch-table td { text-align: left; padding: 7px 10px;
                               border-bottom: 1px solid var(--border-1); }
.vch-table thead th { font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
                      color: var(--text-3); font-weight: 600; }
.vch-table tbody th { font-weight: 500; color: var(--text-2); }
.vch-table td { font-family: var(--font-data); font-variant-numeric: tabular-nums; color: var(--text-1); }

/* ── the tooltip ───────────────────────────────────────────────── */
.vch-tip { position: absolute; z-index: 600; pointer-events: none; display: flex;
           flex-direction: column; gap: 1px; padding: 7px 11px; border-radius: 10px;
           background: var(--bg-3); border: 1px solid var(--border-2);
           box-shadow: 0 8px 24px rgba(0, 0, 0, .28); max-width: 240px; }
.vch-tip[hidden] { display: none; }
/* The value leads, the label follows — the reader already has the category. */
.vch-tip b { font-family: var(--font-data); font-size: 14px; color: var(--text-1); }
.vch-tip span { font-size: 11.5px; color: var(--text-2); }

@media (max-width: 560px) {
  .vch-tile.is-hero .vch-tile-v { font-size: 40px; }
  .vch-stack { height: 112px; }
  .vch-col { min-width: 34px; }
}
