/* ---------- Motion ---------- */

@keyframes spin { to { transform: rotate(360deg); } }

@keyframes pulse {
  0%,
  100% { opacity: 0.45; }
  50% { opacity: 1; }
}

@keyframes drawer-in {
  from { transform: translateX(100%); }
  to { transform: none; }
}

@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes pop-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.985); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  /* Lit labels stay lit but still; update flashes do not play. */
  .lamp-pill.is-lit-update,
  .dj-rank-badge.is-rank-update,
  .dj-rank-badge.is-perpetual-lit,
  .achievement-milestone.is-milestone-glow,
  .lamp-pill.is-lit-update::before,
  .lamp-pill.is-lit-update::after,
  .lamp-pill.lamp-perfect,
  .lamp-pill.lamp-perfect::after,
  .dj-rank-badge.is-rank-update::before,
  .dj-rank-badge.is-perpetual-lit::before,
  .achievement-milestone.is-milestone-glow::before,
  .achievement-milestone.is-milestone-glow::after,
  .goal-wave > span,
  .goal-burst i,
  .kpi-goal-badge {
    animation: none !important;
  }

  .goal-burst,
  .label-burst { display: none; }

  /* A history row reached from the chart keeps a still highlight until it clears. */
  .history-item.is-jump-target {
    animation: none !important;
    background-color: rgba(37, 99, 235, 0.12);
    box-shadow: inset 0 0 0 2px rgba(37, 99, 235, 0.6);
  }
}

/* ---------- Responsive ---------- */

@media (min-width: 1280px) {
  .song-drawer { width: min(1040px, 96vw); }
  .detail-chart-wrap { height: 430px; }
}

/* Two achievement columns stay side by side on laptops/tablets; each row puts the change
   under its title once a column can no longer hold title and result on one line. */
@media (max-width: 1200px) {
  .achievement-row {
    grid-template-columns: 44px minmax(0, 1fr);
    align-items: start;
    gap: 4px 10px;
    padding-top: 7px;
    padding-bottom: 7px;
  }

  .achievement-level { padding-top: 2px; }

  .achievement-value {
    grid-column: 2;
    justify-self: end;
    max-width: 100%;
  }

  .score-achievement-value,
  .lamp-achievement-metrics {
    flex-wrap: wrap;
    min-width: 0;
  }
}

@media (max-width: 1120px) {
  .command-bar {
    align-items: stretch;
    flex-direction: column;
  }

  /* Narrower drawers keep the one-line chart metadata by tightening its rhythm. */
  .drawer-meta-row { gap: 8px; }
  .drawer-meta > div { gap: 4px; padding: 0 8px; }
  .drawer-meta dt { letter-spacing: 0; }
  .drawer-tier-line { gap: 4px; }
  .drawer-tier-chip { padding: 3px 6px 3px 7px; }

  .filter-cluster { justify-content: flex-start; }

  .select-field { flex: 1 1 130px; }

  .kpi-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  .kpi-capture {
    grid-column: 1 / -1;
    grid-template-columns: auto minmax(80px, 1fr) auto auto;
    grid-template-rows: auto;
    align-items: center;
    gap: 14px;
    padding-block: 10px;
    border-top: 1px solid var(--line);
    border-left: 0 !important;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  }

  .insight-grid { grid-template-columns: minmax(0, 1fr); }

  .activity-panel,
  .level-panel { height: 330px; }
}

@media (max-width: 1100px) {
  .drawer-header > div:first-child { grid-template-columns: minmax(190px, 1fr) auto; }
}

/* Where the chart metadata and three table cards cannot share one line (narrow title areas,
   short landscape), the chart line takes the same fixed 44px two-row rhythm as phones. */
@media (max-width: 1279px), (max-height: 480px) and (min-width: 761px) {
  .drawer-meta-row { flex-wrap: wrap; gap: 0 10px; height: 44px; align-content: center; }
}

@media (max-width: 900px) {
  .custom-range-form {
    right: 0;
    left: auto;
  }

  .tier-row { grid-template-columns: 78px minmax(0, 1fr); }
  .tier-chart-grid { grid-template-columns: repeat(auto-fill, minmax(165px, 1fr)); }
  .song-identity-layout { grid-template-columns: 52px minmax(180px, 1fr); }

  .history-item { grid-template-columns: 108px minmax(0, 1fr) auto; }
  .history-item > .lamp-pill,
  .history-item > .history-lamp-transition {
    grid-column: 3;
    grid-row: 1 / span 2;
  }
  .history-list.has-row-actions .history-item { grid-template-columns: 108px minmax(0, 1fr) auto 68px; }
  .history-row-actions,
  .history-row-action {
    grid-column: 4;
    grid-row: 1 / span 2;
  }
}

@media (max-width: 760px) {
  .app-shell { padding: 0 12px 36px; }

  .topbar {
    gap: 8px;
    min-height: 60px;
  }

  .brand-copy strong { font-size: 15px; }

  .brand-copy small,
  .sync-copy,
  .settings-button span:last-child,
  .reload-button span:last-child { display: none; }

  .settings-button,
  .reload-button {
    flex-shrink: 0;
    justify-content: center;
    width: 40px;
    min-width: 40px;
    min-height: 40px;
    padding: 0;
  }

  .icon-button > span:first-child { font-size: 17px; }

  .command-bar {
    position: relative;
    top: auto;
    gap: 8px;
    margin-top: 4px;
    padding: 8px;
    backdrop-filter: none;
  }

  .period-cluster {
    align-items: stretch;
    flex-direction: column;
    gap: 8px;
  }

  .segmented-control {
    flex-wrap: wrap;
    align-self: stretch;
  }

  .segmented-control button {
    flex: 1;
    min-height: 36px;
  }

  .date-navigator > button { flex-shrink: 0; }

  .date-heading {
    flex: 1;
    min-width: 0;
    text-align: center;
  }

  .date-heading strong {
    /* Wrap at the spaces around "〜", never inside a date. */
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .nav-button,
  .text-button { min-height: 36px; }

  .nav-button { width: 36px; }

  /* Phones: stacked label/value so three filters and the reset share one row. */
  .filter-cluster {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
  }

  .select-field {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    height: 44px;
    padding: 5px 0 0 10px;
  }

  .select-field span {
    font-size: var(--fs-micro);
    line-height: 1.2;
  }

  /* The native arrow already reserves its own space; extra padding clipped "SP / DP". */
  .select-field select {
    height: auto;
    min-height: 22px;
    padding-right: 22px;
    background-position: right 8px center;
  }

  .filter-reset {
    min-height: 44px;
    padding: 0 12px;
  }

  .insight-grid > .panel { min-width: 0; }

  .activity-panel .panel-header { flex-wrap: wrap; }
  .activity-controls { min-width: 0; }

  .achievement-columns { grid-template-columns: minmax(0, 1fr); }

  .achievement-column + .achievement-column {
    border-top: 1px solid var(--line);
    border-left: 0;
  }

  .achievement-list { max-height: 420px; }

  .achievement-row {
    grid-template-columns: 42px minmax(0, 1fr);
    padding-right: 14px;
    padding-left: 14px;
  }

  .achievement-title-line { align-items: flex-start; }

  .achievement-title-line .song-title-button {
    display: block;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .achievement-title-line .song-title-text { overflow: visible; }

  .achievement-title-line .speed-badge { flex-shrink: 0; }

  .achievement-meta {
    flex-wrap: wrap;
    white-space: normal;
  }

  /* When a lamp change wraps, the transition keeps the top line and the CPI drops below it. */
  .lamp-achievement-metrics { flex-wrap: wrap-reverse; }

  .achievement-filter-details > summary {
    min-height: 40px;
    font-size: var(--fs-control);
  }

  /* Touch-sized filter toggle, still riding on the column header. */
  .achievement-column-header { min-height: 46px; }

  .achievement-filter-details > summary {
    top: 5px;
    height: 36px;
    min-height: 36px;
  }

  .song-filter-row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .song-filter-panel label {
    min-height: 34px;
    font-size: var(--fs-control);
  }
  .song-filter-panel input[type="checkbox"] {
    width: 17px;
    height: 17px;
  }
  .song-filter-panel select,
  .song-number-filters input {
    height: 36px;
    font-size: var(--fs-control);
  }
  .filter-relation span { min-height: 32px; }

  .songs-heading {
    align-items: stretch;
    flex-direction: column;
  }

  .song-tools { align-items: stretch; }
  .search-field { flex: 1; }
  .search-field input { width: 100%; }
  .sort-field select { max-width: 190px; }

  /* Phones scroll the records table sideways; the chart identity stays pinned. */
  .songs-table th:first-child,
  .songs-table td:first-child {
    position: sticky;
    z-index: 2;
    left: 0;
    background: var(--surface);
    box-shadow: 1px 0 0 var(--line);
  }

  .songs-table thead th:first-child {
    z-index: 5;
    background: var(--surface-2);
  }

  .songs-table tbody tr:hover td:first-child { background: var(--surface-2); }

  .song-identity-layout { grid-template-columns: 44px minmax(150px, 190px); }

  .table-footer span:last-child { display: none; }

  .tier-lamp-progress {
    flex-basis: 100%;
    flex-wrap: wrap;
  }

  .tier-lamp-scope {
    flex-basis: 100%;
    justify-content: flex-start;
  }

  /* Phones scroll the whole sheet, so the title and all-time plate give their height back to
     the chart; the close button floats and stays reachable. */
  .song-drawer {
    display: block;
    width: 100vw;
    overflow-y: auto;
    overscroll-behavior: contain;
    border-left: 0;
  }

  .drawer-header,
  .drawer-body {
    padding-right: 14px;
    padding-left: 14px;
  }

  .drawer-header { padding-right: 62px; }

  .drawer-body { overflow: visible; }

  .drawer-close {
    position: fixed;
    z-index: 3;
    top: 12px;
    right: 12px;
    width: 40px;
    min-height: 40px;
    background: rgba(255, 255, 255, 0.94);
    box-shadow: 0 2px 10px rgba(21, 27, 36, 0.14);
  }

  .drawer-header > div:first-child { display: block; }

  /* Phones: the chart line keeps its fixed height (table labels move to their own fixed
     line instead of clipping); the period line stays one line. */
  .drawer-header > div:first-child { --drawer-meta-indent: 22px; }
  .drawer-meta-row { flex-wrap: wrap; gap: 0 10px; height: 44px; align-content: center; }
  .drawer-meta > div { padding: 0 8px; }
  .drawer-meta dd { font-size: 13px; }
  .drawer-tier-chip b { font-size: var(--fs-control); }
  .drawer-period-summary { gap: 8px; }
  .drawer-stats > div { padding: 0 7px; }
  .drawer-stats dd { font-size: 14px; }
  body .drawer-stats #drawer-best .score-rank-delta { display: none; }

  .drawer-alltime-best {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 10px 0 0;
  }

  .drawer-alltime-best .alltime-label { flex-basis: 100%; }
  .drawer-alltime-best > * { flex-shrink: 0; }
  .alltime-secondary { flex-basis: 100%; }

  .drawer-section-heading { flex-wrap: wrap; }
  .drawer-section-heading h3 { flex-shrink: 0; }

  .detail-scope-control {
    min-width: 0;
    justify-content: flex-start;
  }

  .detail-chart-wrap { height: 340px; }

  .drawer-meta-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
  }

  .lamp-update-event { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 8px; }
  .lamp-update-event time { grid-column: 1 / -1; }
  .lamp-update-transition { grid-template-columns: minmax(64px, auto) auto minmax(64px, auto); }
  .score-navigation { flex-wrap: wrap; }
  .score-navigation > span:first-child { flex-basis: 100%; }

  .history-item { grid-template-columns: minmax(0, 1fr) auto; }

  /* Full-width row on phones: flag and date share one line. */
  .history-item .history-date-cell {
    grid-column: 1 / -1;
    min-height: 0;
    flex-direction: row;
    align-items: baseline;
    justify-content: flex-start;
    gap: 8px;
  }

  .history-item .history-result {
    grid-column: 1 / -1;
    min-width: 0;
  }

  .history-item > .lamp-pill,
  .history-item > .history-lamp-transition {
    grid-column: 2;
    grid-row: 3;
  }

  .history-list.has-row-actions .history-item { grid-template-columns: minmax(0, 1fr) auto; }
  .history-row-actions,
  .history-row-action {
    grid-column: 2;
    grid-row: 4;
  }

  .history-result > small {
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

@media (max-width: 620px) {
  .kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .kpi-card { padding: 11px 14px 12px; }

  .kpi-card:nth-child(odd) { border-left: 0; }

  .kpi-card:nth-child(n + 3) { border-top: 1px solid var(--line); }

  .kpi-value { font-size: 28px; }

  .kpi-capture {
    grid-template-columns: auto minmax(60px, 1fr);
    row-gap: 6px;
  }

  .kpi-capture small,
  .kpi-capture .data-notice { grid-column: 1 / -1; }

  .capture-card small { white-space: normal; }

  .activity-panel,
  .level-panel { height: 310px; }

  .activity-period-overview {
    order: 3;
    flex-basis: 100%;
  }

  .achievement-filterbar { flex-wrap: wrap; }

  .custom-range-form {
    right: auto;
    grid-template-columns: minmax(0, 1fr);
    width: min(360px, calc(100vw - 24px));
  }

  .custom-range-form > span { display: none; }
  .custom-range-form button { grid-column: 1 / -1; }

  /* Phones: the peek gets its own row instead of overlapping the title. */
  .tier-summary {
    flex-wrap: wrap;
    row-gap: 6px;
  }

  /* Both mode titles use the same two-line heading, keeping the switch row still. */
  .tier-summary > div:first-child { flex: 1 1 0; flex-direction: column; align-items: flex-start; row-gap: 4px; }
  .tier-panel[open] > .tier-summary { flex-wrap: nowrap; }

  .tier-summary-goals {
    order: 3;
    flex-basis: 100%;
    justify-content: flex-start;
  }
}

@media (max-width: 500px) {
  /* Six period units do not fit one phone row; two even rows keep every label on one line. */
  .period-cluster > .segmented-control {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .panel-header { padding: 13px 14px 11px; }

  .updates-heading { align-items: flex-start; }

  .updates-actions {
    flex-wrap: wrap;
    justify-content: flex-end;
  }

  .chart-summary {
    padding-right: 14px;
    padding-left: 14px;
  }

  .song-tools { flex-direction: column; }

  .sort-field select {
    width: 100%;
    max-width: none;
  }

  .speed-results { grid-template-columns: minmax(0, 1fr); }

  .tier-chart-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 400px) {
  .app-shell { padding: 0 10px 32px; }

  .kpi-card { padding: 10px 12px 11px; }

  .kpi-value { font-size: 26px; }

  .filter-cluster { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  .filter-reset {
    grid-column: 1 / -1;
    min-height: 34px;
  }

  .achievement-row { padding: 10px 12px; }
}

@media (max-height: 480px) and (min-width: 761px) {
  /* Short landscape: the two-row command bar scrolls away as on phones, leaving only the
     region's own bar pinned (in a tighter rhythm), so reading rows keep most of the height. */
  .command-bar { position: relative; top: auto; }
  .updates-heading,
  .songs-heading,
  .tier-summary { padding-top: 8px; padding-bottom: 7px; }
  .song-filter-bar { padding-bottom: 6px; }
  .song-drawer { display: block; overflow-y: auto; overscroll-behavior: contain; }
  .drawer-body { overflow: visible; }
  .drawer-close { position: fixed; z-index: 3; top: 12px; right: 12px; background: var(--surface); }
  .detail-chart-wrap { height: calc(100dvh - 56px); }
}

/* Stable inset separators: fractional sticky positions cannot compress a painted stroke. */
.updates-heading, .songs-heading, .tier-summary,
.achievement-column-header, .tier-panel[open] .tier-controls,
.songs-table thead th { box-shadow: inset 0 -1px 0 var(--line); }
.is-region-stuck :is(.updates-heading, .songs-heading),
.tier-panel.is-region-stuck[open] > .tier-summary { border-top: 0; box-shadow: inset 0 1px 0 var(--line), inset 0 -1px 0 var(--line); }
/* Without the top border the bar's corner arcs start at its box top, so the corner repaint
   (styles-shell.css) starts there too: at -1px its arcs sat a pixel above the bar's own and rows
   scrolling underneath showed through the crescent between them. */
.is-region-stuck :is(.updates-heading, .songs-heading)::before,
.tier-panel.is-region-stuck[open] > .tier-summary::before { top: 0; }
.is-region-stuck .achievement-column-header,
.tier-panel.is-region-stuck[open] .tier-body > .tier-controls,
.songs-panel.is-region-stuck .songs-table thead th { box-shadow: inset 0 -1px 0 var(--line), 0 6px 10px -8px rgba(21, 27, 36, 0.28); }
.tier-compact-toggle { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; font-size: var(--fs-control); }

.speed-period-average { display: block; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.drawer-observation-details { margin-top: 12px; color: var(--ink-3); font-size: var(--fs-meta); }
.drawer-observation-details[hidden] { display: none; }
.drawer-observation-details > summary { cursor: pointer; }
.drawer-observation-details > p { margin: 8px 0; }
.drawer-observations { display: grid; gap: 4px; padding: 8px 0; }
.drawer-observations[hidden] { display: none; }
.best-state-note { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; font-size: var(--fs-meta); color: var(--ink-2); }
.best-state-note small { color: var(--ink-3); }
.observed-achievement-row { display: grid; gap: 3px; padding: 10px 16px; border-top: 1px dashed var(--line); font-size: var(--fs-meta); color: var(--ink-2); }
.observed-achievement-row small, .tier-observation-date { color: var(--ink-3); font-size: var(--fs-micro); }

.drawer-initial-state { display: flex; align-items: center; gap: 8px; margin: -4px 0 7px; font-size: var(--fs-meta); color: var(--ink-3); }
.drawer-initial-state[hidden] { display: none; }

/* Reduced evidence: close existing regions up without substitute measurements. */
body.without-measurement_activity .kpi-play,
body.without-measurement_activity .kpi-keys,
body.without-measurement_activity .capture-card,
body.without-measurement_activity .activity-panel,
body.without-measurement_activity .settings-goal,
body.without-bpi .bpi-cell,
body.without-bpi .bpi-column,
body.without-bpi #score-bpi-filter-field,
body.without-bpi #score-bpi-priority-field,
body.without-bpi label:has(#bpi-reference-toggle),
body.without-bpi label:has(#bpi-custom-toggle),
body.without-bpi label:has(#setting-show-bpi),
body.without-perfect_judgement label:has(#setting-use-perfect) {
  display: none !important;
}
body.without-measurement_activity .kpi-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
body.without-measurement_activity .insight-grid {
  grid-template-columns: minmax(0, 1fr);
}

/* Song navigation retains a two-row tool grid on phones after the shared responsive rules. */
@media (max-width: 600px) {
  .songs-heading .song-tools { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
  .songs-heading .search-field { grid-column: 1 / -1; }
  .songs-heading .sort-field select { width: 100%; max-width: 100%; }
}
