/* ---------- Chart detail drawer ---------- */

.drawer-backdrop {
  position: fixed;
  z-index: 50;
  inset: 0;
  background: rgba(21, 27, 36, 0.34);
  backdrop-filter: blur(2px);
  animation: fade-in 180ms ease both;
}

.song-drawer {
  position: fixed;
  z-index: 60;
  top: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  width: min(920px, 98vw);
  height: 100dvh;
  overflow: hidden;
  border-left: 1px solid var(--line-2);
  background: var(--bg);
  box-shadow: -24px 0 60px rgba(21, 27, 36, 0.2);
  /* No fill mode: once settled the drawer carries no transform, so the phone layout's
     floating close button stays fixed to the viewport. */
  animation: drawer-in 240ms cubic-bezier(0.22, 0.8, 0.35, 1);
}

/* Keep the close button fixed even when the title makes the header taller. */
.drawer-header {
  display: flex;
  flex: 0 0 auto;
  align-items: flex-start;
  justify-content: space-between;
  position: relative;
  gap: 18px;
  padding: 18px 22px 16px;
  border-bottom: 1px solid color-mix(in srgb, #1fa7c0 26%, var(--line));
  background:
    linear-gradient(90deg, rgba(38, 176, 201, 0.55), rgba(111, 116, 245, 0.4) 45%, transparent 80%) top / 100% 2px no-repeat,
    radial-gradient(70% 140% at 0% 0%, rgba(38, 176, 201, 0.16), transparent 70%),
    linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.45) 96%),
    repeating-linear-gradient(90deg, rgba(31, 120, 170, 0.07) 0 1px, transparent 1px 24px),
    repeating-linear-gradient(0deg, rgba(31, 120, 170, 0.055) 0 1px, transparent 1px 24px),
    linear-gradient(118deg, #d8eef6, #e5eafa 50%, #f1f3f9 82%);
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.9);
}

.drawer-header > div:first-child {
  --drawer-meta-indent: 30px;
  display: grid;
  flex: 1;
  grid-template-columns: minmax(220px, 1fr) auto;
  grid-template-rows: auto auto auto auto;
  align-items: end;
  column-gap: 24px;
  min-width: 0;
}

.drawer-header .section-kicker,
.drawer-header .drawer-title-line,
.drawer-header .drawer-meta-row,
.drawer-header .drawer-period-summary { grid-column: 1; }

/* Title line: ☆level · title · [SP ANOTHER] (speed) (S乱). The level and chart tags are
   smaller than the title and carry the difficulty colour; conditions are compact chips. */
/* The level hangs to the left so a long title wraps under itself, not under the level; the
   tags follow the title inline and wrap as one unit. */
.drawer-title-line {
  position: relative;
  min-width: 0;
  margin: 4px 0 6px;
  padding-left: 46px;
  line-height: 1.22;
}

.drawer-level {
  position: absolute;
  top: 5px;
  left: 0;
  color: var(--difficulty, var(--ink-2));
  font-family: var(--font-num);
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* The title area's information system, under the title and indented to sit between the
   ☆level and the title text (not flush with either): one fixed-height chart line — 収録Ver.,
   BPM, ノーツ数, then the difficulty-table labels — and one fixed-height period line. Both
   are typographic rows (small label + figure) with hairline separators, not boxed tables, and
   keep their height whether or not a field or table label exists. */
.drawer-meta-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  height: 24px;
  margin: 0 0 2px var(--drawer-meta-indent);
  overflow: hidden;
}

.drawer-meta {
  display: inline-flex;
  /* Shrinks before the table cards: a long version name ellipsizes (full name in its title). */
  flex: 0 1 auto;
  align-items: baseline;
  min-width: 0;
  margin: 0;
  padding: 0;
}

.drawer-meta[hidden] { display: none; }

/* The 170px cap sits on the dd so the item's own width never exceeds the visible badge. */
.drawer-meta-version { min-width: 0; }
.drawer-meta-version dd { min-width: 0; max-width: 170px; }

.drawer-meta > div {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 0 11px;
  border-left: 1px solid color-mix(in srgb, var(--ink-4) 55%, transparent);
  line-height: 18px;
}

.drawer-meta > div:first-child { padding-left: 0; border-left: 0; }

.drawer-meta dt {
  color: var(--ink-3);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.1;
  white-space: nowrap;
}

/* 収録Ver.: recognisable version identity, adapted to the header's calm palette. The
   payload keeps the familiar heading colours (--version-bg / --version-ink); the badge shows
   them through one key colour (--version-key): a soft tint, a key-coloured leading edge, a
   hairline and a faint glow, with ink pulled toward the key — never a flat pasted plate.
   RED and later lead with their release number in a lighter numeric face. */
.release-version-badge {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  font-family: var(--font-ui);
  font-weight: 800;
  text-overflow: ellipsis;
  vertical-align: bottom;
}

.release-version-badge.has-version-colour {
  padding: 1px 7px 1px 8px;
  border-radius: 4px;
  color: color-mix(in srgb, var(--version-key) 42%, var(--ink));
  background:
    linear-gradient(90deg, var(--version-key) 0 3px, transparent 3px),
    linear-gradient(180deg, color-mix(in srgb, var(--version-key) 20%, #ffffff), color-mix(in srgb, var(--version-key) 11%, #ffffff));
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--version-key) 38%, transparent),
    0 0 6px color-mix(in srgb, var(--version-key) 22%, transparent);
}

.release-version-number {
  font-family: var(--font-num);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  opacity: 0.78;
}

.drawer-meta dd {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-num);
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: 0.01em;
  line-height: 18px;
  white-space: nowrap;
}

.drawer-meta-version dd { font-size: 12px; }

/* At a non-1.00x speed the effective BPM follows the base in red; the base keeps the
   ordinary ink. */
.bpm-effective {
  margin-left: 1px;
  color: #d0283a;
  font-weight: 700;
}

.drawer-header h2 {
  display: inline;
  margin: 0 8px 0 0;
  font-size: 22px;
  font-weight: 800;
  line-height: 1.22;
  overflow-wrap: anywhere;
}

.drawer-chart-tags {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  vertical-align: 3px;
}

.chart-tag {
  display: inline-flex;
  align-items: center;
  min-height: 19px;
  padding: 0 6px;
  border: 1px solid var(--line-2);
  border-radius: 4px;
  color: var(--ink-2);
  background: var(--surface);
  font-family: var(--font-num);
  font-size: var(--fs-meta);
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1;
  white-space: nowrap;
}

.chart-tag-difficulty {
  border-color: color-mix(in srgb, var(--difficulty) 45%, transparent);
  color: var(--difficulty-text, var(--difficulty));
  background: color-mix(in srgb, var(--difficulty) 8%, var(--surface));
}

.chart-tag-speed {
  border-color: color-mix(in srgb, #2458d6 40%, transparent);
  color: #1d4fc4;
  background: #edf2ff;
}

.chart-tag-srandom {
  border-color: color-mix(in srgb, #b0306f 40%, transparent);
  color: #9c2a63;
  background: #fdeef5;
}

/* Catalog classifications only (地力表 HARD / ノマゲ tiers), right of the metadata group:
   each table is its own small card (Tier-colour edge over a faint Tier tint). The line
   keeps room for one more table card (a future score tier) without reflowing the header. */
.drawer-tier-line {
  display: flex;
  /* Cards keep their natural width; the metadata group gives way to them. */
  flex: 0 0 auto;
  flex-wrap: nowrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: hidden;
  margin: 0;
  color: var(--ink-3);
  font-size: var(--fs-meta);
  font-weight: 700;
}

.drawer-tier-line.is-empty { margin: 0; }

.drawer-tier-chip {
  display: inline-flex;
  flex: 0 0 auto;
  white-space: nowrap;
  align-items: baseline;
  gap: 1px;
  min-height: 20px;
  padding: 3px 8px 3px 9px;
  border: 1px solid color-mix(in srgb, var(--tier-color) 50%, #1b2332);
  border-radius: 3px;
  color: var(--ink-2);
  background: linear-gradient(180deg, #ffffff, color-mix(in srgb, var(--tier-color) 10%, #ffffff));
  box-shadow: inset 3px 0 0 var(--tier-color), inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 0 6px color-mix(in srgb, var(--tier-color) 18%, transparent);
  line-height: 1;
}

.drawer-tier-chip small {
  color: var(--ink-3);
  font-size: var(--fs-micro);
  font-weight: 700;
}

.drawer-tier-chip b {
  color: color-mix(in srgb, var(--tier-color) 82%, #1b2332);
  font-family: var(--font-ui);
  font-size: var(--fs-control);
  font-weight: 800;
}

/* Period line: 期間内 (named period) then プレイ / 平均 / ベスト, all clearly the period's
   values, never the all-time plate's. Fixed height: a chart without a period play shows
   0回 / — rather than collapsing. */
.drawer-period-summary {
  display: flex;
  align-items: baseline;
  gap: 12px;
  min-width: 0;
  height: 24px;
  margin: 0 0 0 var(--drawer-meta-indent);
  /* Clipped sideways only: the period best's score sub-row hangs below the line. */
  overflow-x: clip;
  overflow-y: visible;
  line-height: 20px;
}

.drawer-stats {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: baseline;
  margin: 0;
}

.drawer-stats > div {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 0 11px;
  border-left: 1px solid color-mix(in srgb, var(--ink-4) 55%, transparent);
}

.drawer-stats > div:first-child { padding-left: 0; border-left: 0; }

.drawer-stats dt {
  color: var(--ink-3);
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
}

.drawer-stats dd {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-num);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}

/* The period best's EX score sits on the shared baseline like its neighbours (▲ in the
   gap after it when updated in the period); under it, the conventional score sub-row: the
   red rank distance right-aligned to the score, its rate to the left. The sub-row hangs
   below the line, so the line keeps its height. */
.drawer-stats #drawer-best { display: inline-flex; align-items: baseline; }

body .drawer-stats #drawer-best > .detail-score-stack {
  position: relative;
  display: inline-block;
  overflow: visible;
}

body .drawer-stats #drawer-best > .detail-score-stack > strong { display: block; font-size: 15px; font-weight: 700; line-height: inherit; text-align: right; }
body .drawer-stats #drawer-best .period-score-marker { top: 1px; right: -8px; }

body .drawer-stats #drawer-best .score-secondary {
  position: absolute;
  top: calc(100% - 3px);
  right: 0;
  gap: 4px;
}

body .drawer-stats #drawer-best .score-secondary > * { font-size: var(--fs-unit); }

/* All-time best as one result plate: score, rank and lamp, then supporting metrics. The
   plate is the chart's trophy: it takes the light of its best lamp, and a MAX adds a
   prismatic rim. */
.drawer-alltime-best {
  position: relative;
  display: grid;
  grid-column: 2;
  grid-row: 1 / -1;
  grid-template-columns: auto auto auto;
  grid-template-rows: auto auto auto auto;
  align-items: center;
  justify-content: start;
  justify-items: start;
  gap: 6px 8px;
  min-width: 0;
  padding: 11px 16px 12px 18px;
  border: 1px solid color-mix(in srgb, var(--light, var(--line-2)) 48%, var(--line));
  border-radius: var(--radius);
  /* A clean white plate washed with the lamp's own light (not a grey base, which turned the
     lower lamps muddy), with the lamp body as its edge. */
  background:
    radial-gradient(120% 160% at 100% 0%, color-mix(in srgb, var(--lamp-hi, var(--light, #e2e6ea)) 30%, transparent), transparent 62%),
    linear-gradient(110deg, color-mix(in srgb, var(--light, #d3d8de) 13%, var(--surface)) 0%, var(--surface) 64%);
  box-shadow:
    inset 5px 0 0 var(--lamp, var(--line-2)),
    0 6px 18px -10px color-mix(in srgb, var(--light, #8a94a0) 70%, transparent);
}

.drawer-alltime-best.lamp-fullcombo {
  background:
    linear-gradient(120deg, rgba(255, 143, 162, 0.13), rgba(255, 212, 94, 0.11) 30%, rgba(143, 224, 122, 0.11) 55%, rgba(111, 202, 245, 0.14) 78%, rgba(179, 155, 255, 0.2)),
    var(--surface-2);
}

.drawer-alltime-best.lamp-fullcombo,
.drawer-alltime-best.lamp-perfect { box-shadow: inset 4px 0 0 var(--light), 0 0 14px -4px var(--light); }

.drawer-alltime-best.lamp-perfect {
  background:
    linear-gradient(120deg, rgba(255, 243, 176, 0.55), rgba(246, 194, 26, 0.16) 58%, rgba(255, 232, 131, 0.4)),
    var(--surface-2);
}

.drawer-alltime-best.is-max-score::after {
  content: "";
  position: absolute;
  inset: -1px;
  padding: 1.5px;
  border-radius: inherit;
  background: linear-gradient(100deg, #ff6f91, #ffd24a 28%, #67d98b 52%, #4cc3ff 74%, #a98bff);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
}

.drawer-alltime-best:empty { display: none; }

.drawer-alltime-best .alltime-label {
  grid-column: 1 / -1;
  color: var(--ink-3);
  font-size: var(--fs-micro);
  font-weight: 800;
  letter-spacing: 0.08em;
}

/* One grid, one left edge: the label, the score (rank and lamp centred on its figure line),
   its rate and rank distance directly under the figure, then the supporting metrics. */
.drawer-alltime-best > .detail-score-stack { display: contents; }

.drawer-alltime-best > .detail-score-stack > strong {
  grid-column: 1;
  grid-row: 2;
  margin-right: 12px;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.drawer-alltime-best > .detail-score-stack > .score-secondary {
  grid-column: 1 / -1;
  grid-row: 3;
  justify-content: flex-start;
  gap: 5px;
  margin-top: -3px;
}

.drawer-alltime-best > .dj-rank-badge {
  grid-column: 2;
  grid-row: 2;
}

.drawer-alltime-best > .lamp-pill {
  grid-column: 3;
  grid-row: 2;
}

.alltime-secondary {
  display: inline-flex;
  flex-wrap: wrap;
  grid-column: 1 / -1;
  grid-row: 4;
  align-items: center;
  gap: 5px;
}

.alltime-secondary:empty { display: none; }

.drawer-close {
  flex: 0 0 auto;
  width: 36px;
  min-height: 36px;
  padding: 0;
  font-size: 20px;
  line-height: 1;
}

.drawer-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 22px 56px;
}

/* Speed cards are compared with each other: the score sits in a fixed box, right-aligned. */
body .speed-result-score > .detail-score-stack {
  justify-items: end;
  min-width: 78px;
  overflow: visible;
}

body .speed-result-score > .detail-score-stack > small,
body .speed-result-score > .detail-score-stack > .score-secondary {
  grid-row: 2;
  justify-self: end;
}

.drawer-section { margin-top: 18px; }

.drawer-body > .drawer-section:first-child { margin-top: 0; }

.drawer-section h3 {
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 800;
}

.drawer-section-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.drawer-section-heading > span,
#drawer-score-range {
  color: var(--ink-3);
  font-size: var(--fs-meta);
  font-variant-numeric: tabular-nums;
}

.detail-scope-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.detail-scope-control button {
  min-height: 28px;
  padding: 0 11px;
  border: 1px solid var(--line-2);
  border-radius: 7px;
  color: var(--ink);
  background: var(--surface);
  font-size: var(--fs-meta);
  font-weight: 700;
  white-space: nowrap;
  transition: background-color 140ms var(--ease), border-color 140ms var(--ease);
}

.detail-scope-control button:hover:not(:disabled) {
  border-color: var(--ink-4);
  background: var(--surface-2);
}

.detail-scope-control button:disabled {
  color: var(--ink-3);
  cursor: default;
  opacity: 0.7;
}

.detail-scope-control .options-popover > summary { min-height: 28px; }

/* Chart overlays are occasional settings: one list inside the 表示設定 popover. */
.options-popover-panel.detail-event-toggles {
  gap: 2px;
  width: 250px;
  padding: 6px;
}

.detail-event-toggles legend {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.detail-event-toggles label {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 0 8px;
  border-radius: 7px;
  color: var(--ink-3);
  cursor: pointer;
  font-size: var(--fs-control);
  font-weight: 700;
  transition: color 140ms var(--ease), background-color 140ms var(--ease);
}

.detail-event-toggles label:hover { background: var(--surface-2); }

.detail-event-toggles label:has(input:checked) { color: var(--ink); }

.detail-event-toggles input {
  width: 15px;
  height: 15px;
  margin: 0;
}

.detail-event-toggles .bpi-custom-line input[type="number"] { order: 2; }
.detail-event-toggles .bpi-custom-line input[type="checkbox"] { order: -1; }

/* Below this width the chart control wraps to the drawer's left edge. */
@media (max-width: 620px) {
  .detail-display-options .detail-event-toggles { left: 0; right: auto; }
}

.bpi-custom-line input[type="number"] {
  width: 52px;
  height: 24px;
  padding: 0 4px;
  border: 1px solid var(--line-2);
  border-radius: 5px;
  color: var(--ink);
  background: var(--surface);
  font-family: var(--font-num);
  font-size: var(--fs-meta);
}

.detail-chart-wrap {
  position: relative;
  height: 390px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

/* A canvas is a replaced element: with auto width/height it takes its bitmap size, and
   prepareCanvas() would then grow it on every redraw. Match the chart's content box
   (the wrapper's 8px padding) explicitly instead. */
.detail-chart-wrap > .score-hover-chart {
  position: absolute;
  top: 8px;
  left: 8px;
  width: calc(100% - 16px);
  height: calc(100% - 16px);
  pointer-events: none;
}

.detail-tooltip {
  min-width: 220px;
  font-size: var(--fs-meta);
}

.score-navigation {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 7px;
  color: var(--ink-3);
  font-size: var(--fs-meta);
}

.score-navigation button {
  min-height: 26px;
  padding: 0 10px;
  border: 1px solid var(--line-2);
  border-radius: 7px;
  color: var(--ink);
  background: var(--surface);
  font-size: var(--fs-meta);
  font-weight: 700;
  white-space: nowrap;
}

.score-navigation button:disabled { opacity: 0.45; }

.score-navigation > span:first-child {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Vertical scale: default / A以上 / AA以上 / AAA以上 as one compact segmented control. */
.score-scale-control {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 0;
}

.score-scale-control > span {
  margin-right: 6px;
  color: var(--ink-3);
  font-size: var(--fs-micro);
  font-weight: 700;
}

.score-navigation .score-scale-control button {
  min-height: 24px;
  padding: 0 8px;
  border-radius: 0;
  margin-left: -1px;
  font-weight: 600;
}

.score-navigation .score-scale-control button:first-of-type { border-radius: 7px 0 0 7px; }
.score-navigation .score-scale-control button:last-of-type { border-radius: 0 7px 7px 0; }

.score-navigation .score-scale-control button.is-active {
  position: relative;
  border-color: var(--ink);
  color: #ffffff;
  background: var(--ink);
}

.drawer-lamp-updates { margin-top: 14px; }

.lamp-update-heading {
  display: block;
  margin-bottom: 7px;
  color: var(--ink);
  font-size: var(--fs-control);
  font-weight: 800;
}

/* Keep each lamp transition beside its date instead of across the full drawer. */
.lamp-update-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(420px, 100%), 1fr));
  gap: 5px;
}

/* Date | CPI | update: the update (previous → reached lamp) is right-aligned so arrows and
   reached lamps line up down the list, and the CPI sits directly to its left in a column that
   absorbs the free space. Glow and marks are paint-only and never move the grid. */
.lamp-update-event {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  min-height: 34px;
  padding: 4px 10px 4px 12px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
}

.lamp-update-event time {
  min-width: 108px;
  color: var(--ink-2);
  font-family: var(--font-num);
  font-size: var(--fs-control);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.lamp-update-cpi {
  display: inline-flex;
  justify-self: end;
  align-items: center;
  min-width: 0;
}

.lamp-update-transition {
  display: inline-grid;
  grid-template-columns: minmax(78px, auto) auto minmax(78px, auto);
  justify-items: center;
  align-items: center;
  gap: 6px;
}

.lamp-update-transition .lamp-pill { justify-self: stretch; justify-content: center; }

.lamp-update-event i {
  color: var(--ink-4);
  font-size: var(--fs-meta);
  font-style: normal;
}

.drawer-meta-grid {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 18px;
}

.option-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.option-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 26px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink-2);
  background: var(--surface);
  font-size: var(--fs-meta);
  font-weight: 700;
}

.option-chip strong {
  color: var(--ink);
  font-family: var(--font-num);
  font-weight: 600;
}

.speed-results-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.speed-results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(218px, 1fr));
  gap: 8px;
}

.speed-result-card {
  display: grid;
  grid-template-rows: 18px auto 22px;
  gap: 6px;
  min-width: 0;
  min-height: 88px;
  padding: 9px 11px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: inherit;
  background: var(--surface);
  text-align: left;
  cursor: pointer;
  transition: border-color 140ms var(--ease), background-color 140ms var(--ease), box-shadow 140ms var(--ease);
}

.speed-result-card:hover {
  border-color: var(--ink-4);
  background: var(--surface-2);
}

.speed-result-card.is-current {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}

.speed-result-card header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 5px;
  min-width: 0;
}

.speed-result-card header strong {
  overflow: hidden;
  font-family: var(--font-num);
  font-size: var(--fs-body);
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.speed-result-card header span {
  flex: 0 0 auto;
  color: var(--ink-3);
  font-size: var(--fs-meta);
}

/* "1.15x BPM230": the BPM at that speed, beside its multiplier; red when it differs from
   the chart's own (non-1.00x), like the header's effective BPM. */
.speed-result-card header .speed-bpm {
  margin-left: 7px;
  color: var(--ink-2);
  font-family: var(--font-num);
  font-size: var(--fs-control);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* The figure scans first; the BPM unit is a smaller, quieter caption fused to it (both ends
   of a SOFLAN range share the figure's size). */
.speed-result-card header .speed-bpm > small {
  margin-right: 2px;
  color: var(--ink-3);
  font-size: var(--fs-unit);
  font-weight: 600;
  letter-spacing: 0.04em;
}

.speed-result-card header .speed-bpm.is-effective > small { color: color-mix(in srgb, #d0283a 62%, var(--ink-3)); }

.speed-result-card header .speed-bpm.is-effective { color: #d0283a; }

.speed-result-score,
.speed-result-lamp {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-width: 0;
}

.speed-result-score > span:not(.detail-score-stack) {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}

.speed-result-score .detail-score-stack > strong { font-size: 18px; }

.speed-result-lamp .metric-badge { margin-right: auto; }

.speed-result-bp {
  margin-left: auto;
  color: var(--ink-3);
  font-family: var(--font-num);
  font-size: var(--fs-meta);
  font-weight: 600;
  white-space: nowrap;
}

.speed-empty {
  color: var(--ink-3);
  font-size: var(--fs-meta);
}

.history-list {
  margin: 0;
  padding: 0 0 28px;
  list-style: none;
  border-top: 1px solid var(--line);
}

.history-item {
  display: grid;
  grid-template-columns: 118px minmax(0, 1fr) max-content;
  align-items: center;
  gap: 10px;
  min-height: 54px;
  padding: 4px 4px 4px 8px;
  border-bottom: 1px solid var(--line);
  /* Keep app.js LIVE_MOTION_CONTAINERS in sync with this paint-contained row. */
  content-visibility: auto;
  contain-intrinsic-size: auto 54px;
}

/* A play that improved something keeps a faint warm edge, so updates stand out in a long
   history without a separate marker column. */
.history-item.has-update {
  background-image: linear-gradient(90deg, rgba(232, 89, 12, 0.07), transparent 34%);
  box-shadow: inset 2px 0 0 rgba(232, 89, 12, 0.55);
}

/* Reached from a chart point: a brief outline + wash (paint only, no layout shift), and a
   visible focus ring for keyboard users. */
.history-item.is-jump-target {
  animation: history-jump 1.8s var(--ease) both;
}

.history-item:focus { outline: none; }

.history-item:focus-visible,
.history-item.is-jump-target:focus {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}

@keyframes history-jump {
  0% { background-color: rgba(37, 99, 235, 0.2); box-shadow: inset 0 0 0 2px rgba(37, 99, 235, 0.75); }
  70% { background-color: rgba(37, 99, 235, 0.1); box-shadow: inset 0 0 0 2px rgba(37, 99, 235, 0.45); }
  100% { background-color: transparent; box-shadow: inset 0 0 0 2px rgba(37, 99, 235, 0); }
}

/* UPDATE sits on its own line above the date; it never overlays the timestamp. */
.history-date-cell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  min-height: 28px;
}

.history-update-flag {
  color: var(--event-ink);
  font-family: var(--font-num);
  font-size: var(--fs-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  line-height: 1;
}

.history-date,
.history-date-cell .history-date {
  color: var(--ink-3);
  font-family: var(--font-num);
  font-size: var(--fs-control);
  font-variant-numeric: tabular-nums;
}

/* The metadata line's spare leading becomes space above EX for its delta. */
.history-result { min-width: 0; padding-top: 7.5px; }

.history-result > .history-score-line {
  display: grid;
  grid-template-columns: var(--history-prior-width, 0px) var(--history-ex-width, 90px) max-content;
  justify-content: start;
  align-items: start;
  column-gap: var(--history-score-gap, 4px);
  font-family: var(--font-num);
  font-size: 17px;
  font-variant-numeric: tabular-nums;
}

.history-score-badges {
  grid-column: 3;
  grid-row: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  min-height: 20px;
  margin-left: 4px;
}

/* A list-wide EX lane anchors the actual figure and its secondary edge. */
.history-result .detail-score-stack {
  grid-column: 2;
  grid-row: 1;
  justify-items: end;
  width: 100%;
  min-width: 0;
  margin: 0;
}

.history-result .detail-score-stack > strong { font-size: 17px; }

.history-result .period-score-marker { right: -8px; }

.history-result > small {
  display: block;
  margin-top: 0;
  color: var(--ink-3);
  font-size: var(--fs-meta);
  line-height: 1;
}

.history-bp-updated-value {
  color: var(--event-ink);
  font-weight: 800;
}

/* A trusted prior occupies the shared lane; missing priors leave it empty. */
.history-result .history-score-transition {
  display: grid;
  grid-column: 1 / 3;
  grid-row: 1;
  grid-template-columns: var(--history-prior-width) max-content;
  align-items: start;
  justify-content: end;
  column-gap: 3px;
  padding-bottom: 0;
}
.history-score-prior { grid-column: 1; grid-row: 1; display: flex; justify-content: end; align-items: center; gap: 3px; height: 17px; white-space: nowrap; font-size: 11px; }
.history-score-prior > .score-before { color: var(--ink-3); font-size: 11px; font-weight: 400; }
.history-result .history-score-transition .score-arrow { position: relative; display: grid; grid-template-columns: 1fr; grid-template-rows: 17px; place-items: center; flex: 0 0 var(--history-arrow-width); width: var(--history-arrow-width); padding: 0; }
.history-result .history-score-transition .score-arrow small { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); color: var(--event-ink); font-size: var(--fs-meta); font-weight: 700; line-height: 1; }
.history-result .history-score-transition .score-arrow i { font-size: 14px; line-height: 17px; }
.history-result .history-score-transition > .detail-score-stack { display: grid; min-width: 0; width: auto; margin: 0; justify-items: end; }
.history-result .history-score-transition > .detail-score-stack > strong { font-size: 17px; line-height: 1; }
/* The secondary line may span beneath the prior without widening the EX lane. */
.history-result .history-score-transition > .detail-score-stack > .score-secondary { position: static; min-width: 0; width: 0; overflow: visible; }

.history-bp-transition { display: inline-flex; align-items: baseline; gap: 4px; font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.history-bp-before { color: var(--ink-3); font-size: 10px; font-weight: 400; }
.history-bp-transition > i { color: var(--ink-4); font-style: normal; }
.history-bp-transition > b { font-size: var(--fs-meta); }

.history-item > .lamp-pill,
.history-item > .history-lamp-transition { justify-self: end; min-width: 84px; }
/* The previous lamp sits behind the reached one: the reached lamp stays in front and covers the
   previous lamp's tail (--lamp-tuck), which carries extra padding so its whole word stays
   readable to the left. Only paint changes; the row keeps the reached lamp's width. */
.history-lamp-transition { --lamp-tuck: 22px; position: relative; display: inline-flex; align-items: center; isolation: isolate; }
.history-lamp-transition > .lamp-pill { z-index: 1; min-width: 84px; }
.history-lamp-prior { position: absolute; z-index: 0; top: -6px; right: calc(100% - var(--lamp-tuck)); display: inline-flex; line-height: 1; white-space: nowrap; opacity: 0.7; border-radius: 3px; }
.history-lamp-prior .history-lamp-before.lamp-pill {
  min-height: 15px;
  height: 15px;
  align-items: flex-start;
  padding: 1px calc(6px + var(--lamp-tuck)) 0 5px;
  border: 1px solid color-mix(in srgb, var(--lamp) 55%, var(--surface));
  color: var(--ink);
  background: color-mix(in srgb, var(--lamp) 18%, var(--surface));
  box-shadow: none;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0;
  text-shadow: none;
  animation: none;
}
.history-lamp-prior .history-lamp-before.lamp-pill::before,
.history-lamp-prior .history-lamp-before.lamp-pill::after { content: none; animation: none; }
/* When the reached lamp is stamped in, the previous one starts where the reached lamp lands and
   is pushed back behind it. Reduced motion never adds .is-motion-intro, so it stays still. */
@keyframes history-lamp-prior-recede {
  from { opacity: 0.95; transform: translate(calc(var(--lamp-tuck) + 30px), 6px); }
}
.history-lamp-transition:has(> .lamp-pill.is-motion-intro) > .history-lamp-prior {
  animation: history-lamp-prior-recede 520ms var(--ease) backwards;
}

/* Optional extension action: a quiet secondary action at the row's right edge. */
.history-list.has-row-actions .history-item {
  grid-template-columns: 118px minmax(0, 1fr) max-content 68px;
}

.history-row-actions {
  justify-self: end;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.history-row-action {
  justify-self: end;
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 0 7px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-xs);
  color: var(--ink-2);
  background: var(--surface);
  font-size: var(--fs-micro);
  font-weight: 800;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}

.history-row-action:hover {
  border-color: #cc2f2f;
  color: #b3261e;
}

