html, body { height: 100%; margin: 0; }
#setup { width: min(880px, calc(100vw - 48px)); max-width: 100vw; max-height: calc(100vh - 48px); overflow: auto; padding: 0; box-sizing: border-box; }
#setup-body { padding: 28px 36px; }
#setup footer { display: flex; gap: 10px; align-items: center; padding: 16px 36px; position: sticky; bottom: 0; background: var(--bg); }
#setup footer > span { flex: 1; }
#setup footer button { min-width: 64px; min-height: 44px; white-space: nowrap; }
#setup .settings-row { display: flex; justify-content: space-between; gap: 16px; align-items: center; margin: 12px 0; }
#setup input[type="number"] { width: 100px; }
#setup-offset-box { display: inline-flex; align-items: center; gap: 8px; }
#setup-offset-down, #setup-offset-up { min-width: 44px; }
#setup-lanes { display: grid; gap: 2px; max-width: 100%; overflow-x: auto; margin: 16px auto; }
#setup-pad, #setup .sr-only { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
#setup-pad:focus { outline: 0; }
#setup .key-lane[data-pending]:not([aria-current="true"]) .key-track { opacity: .35; }
/* The preview takes the height left in the dialog (its 48px of window margin plus about 251px of heading, speed row and footer),
   and the dialog widens on the scroll step to the width that height needs (plus its 72px of side padding). */
#setup-preview-frame { width: min(100%, max(320px, calc((100vh - 300px) * 16 / 9))); margin: 0 auto; aspect-ratio: 16 / 9; }
#setup:has([data-setup-step]:not([hidden]) #setup-preview-frame) { width: min(calc(100vw - 48px), max(880px, calc((100vh - 300px) * 16 / 9 + 72px))); }
#setup footer > span { text-align: right; }
#setup-preview-frame iframe { display: block; width: 100%; height: 100%; }
@media (max-width: 600px) {
    #setup { width: 100vw; max-height: 100%; }
    #setup-body { padding: 16px; }
    #setup footer { flex-wrap: wrap; padding: 12px 16px; }
}
/* Layout rules must not reveal fields or screens hidden by capability checks. */
[hidden] { display: none !important; }
body { padding: 0 12px; box-sizing: border-box; }
#app { display: grid; grid-template-rows: minmax(0, 1fr); grid-auto-rows: auto; height: 100%; }
/* The chart background covers the window behind every screen and takes no grid row. */
#backdrop { position: absolute; inset: 0; z-index: -1; overflow: hidden; }
#bg, #bg-old { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Song select shows the whole picture centred in the window. */
body:has(#songselect:not([hidden])) :is(#bg, #bg-old) { object-fit: contain; object-position: center; }
/* The title picture sits on the right, away from the menu. */
body:has(#title:not([hidden])) :is(#bg, #bg-old) { left: auto; right: 0; width: auto; max-width: 100%; object-fit: contain; object-position: right center; -webkit-mask-image: linear-gradient(to right, transparent, #000 48px); mask-image: linear-gradient(to right, transparent, #000 48px); }
/* The title shows at most a 4:3 picture, centred and cropped at the sides when wider, and crops its right 10% (theme.css slides it in from 25%). */
body:has(#title:not([hidden])) :is(#bg, #bg-old) { max-width: min(133.34vh, 111.12%); object-fit: cover; object-position: center; }
#loader:not([hidden]) { position: fixed; inset: 0; z-index: 1; margin: auto; width: min(420px, 80vw); height: fit-content; box-sizing: border-box; }
#loader-cover { display: block; width: 100%; aspect-ratio: 16 / 9; max-height: 30vh; object-fit: cover; }
#loader-info { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 16px; row-gap: 4px; padding: 16px 20px; overflow-wrap: anywhere; }
#loader-info > * { grid-column: 1; }
#loader-info > #loader-level { grid-column: 2; grid-row: 1 / span 3; align-self: end; }
#loader-rate[hidden] + #loader-level { grid-row: 1 / span 2; }
/* The list keeps the width its columns need in the middle; the rest on the right holds the chat (chat.js). */
#songselect:not([hidden]) { display: grid; grid-template-columns: clamp(280px, 28vw, 360px) minmax(0, 1fr) 0px; grid-template-rows: auto minmax(0, 1fr) auto; grid-template-areas: "info search ." "info list ." "commands commands commands"; gap: 8px 24px; min-height: 0; }
/* The open chat drawer takes the right column (the drawer's 360px), so the list narrows; folded, the list takes it back. theme.css animates the change. */
body:has(.room-chat-panel:not([hidden])) #songselect:not([hidden]) { grid-template-columns: clamp(280px, 28vw, 360px) minmax(0, 1fr) 360px; }
/* The docked chat stops above the bottom command bar (44px buttons + 6px padding twice + the 8px row gap) instead of covering it. */
body:has(#songselect:not([hidden])) .room-chat-panel { bottom: 76px; }
/* The closed chat's button is a tile at the command bar's left end (chat.css), so the bar's own tiles start after it. */
body:has(.room-chat-toggle:not([hidden])) #songselect:not([hidden]) #hints { padding-left: 96px; }
body.background-view > :not(#app):not(#cursor) { display: none !important; }

/* The menu is one column so it hides as little of the background as possible. */
/* Cover the shared body's 12px side gutters, including during title transitions. */
#title:not([hidden]) { position: relative; display: grid; grid-template-rows: minmax(min-content, 1fr) auto; row-gap: 28px; overflow: auto; min-height: 0; margin-inline: -12px; padding: 72px 6vw 24px 7vw; box-sizing: border-box; }
/* A dark panel behind the menu keeps the words readable over any song background. */
#title-menu { justify-self: start; align-self: center; padding: 24px 40px 24px 24px; display: grid; grid-template-columns: minmax(180px, max-content); grid-template-rows: auto auto; gap: 32px; align-content: center; }
/* The scrim reaches past the menu and fades out on every side so it never reads as a box. */
#title-menu { position: relative; isolation: isolate; }
#title-menu::before { content: ""; position: absolute; z-index: -1; inset: -64px -72px -64px -96px; pointer-events: none; -webkit-mask-image: linear-gradient(to right, transparent, #000 64px, #000 calc(100% - 64px), transparent), linear-gradient(to bottom, transparent, #000 64px, #000 calc(100% - 64px), transparent); -webkit-mask-composite: source-in; mask-image: linear-gradient(to right, transparent, #000 64px, #000 calc(100% - 64px), transparent), linear-gradient(to bottom, transparent, #000 64px, #000 calc(100% - 64px), transparent); mask-composite: intersect; }
#title-word { grid-column: 1 / -1; margin: 0; }
#title-home { grid-column: 1; grid-row: 2; }
#title-home { display: flex; flex-direction: column; align-items: stretch; padding-left: 28px; }
#title-menu button { position: relative; display: flex; align-items: center; min-height: 56px; padding: 8px 0; text-align: left; }
.title-cursor { position: absolute; left: -28px; top: 50%; }
/* The website link sits in the window's bottom-left corner, outside the menu's padding. */
#title-web:not([hidden]) { position: absolute; left: 12px; bottom: 12px; display: flex; align-items: center; gap: 12px; padding: 0; text-align: left; }
#title-spot { display: block; width: 44px; height: 44px; }
#title-logo, #title-logo svg { display: block; width: 100%; height: 100%; }
.title-site { display: grid; }
@media (max-width: 700px) {
    #title:not([hidden]) { padding: 64px 24px 24px; }
    #title-menu { grid-template-columns: minmax(0, 1fr); row-gap: 24px; }
    #title-menu button { min-height: 48px; }
}
/* The compact music controls stay at the top right on both menu levels. */
/* One row: song cut with an ellipsis, time, buttons; the progress bar under it. Nothing wraps. */
#title-player:not([hidden]) { position: absolute; top: 10px; right: 0; width: min(560px, 100%); box-sizing: border-box; padding: 4px 8px; display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 2px 8px; }
#title-player p { margin: 0; grid-row: 1; white-space: nowrap; }
/* Title on top with the rate badge, artist under it. */
#title-song { grid-column: 1; overflow: hidden; display: grid; grid-template-columns: minmax(0, auto) auto; justify-content: start; align-items: center; column-gap: 8px; }
#title-song b { grid-row: 1; overflow: hidden; text-overflow: ellipsis; font-size: 20px; line-height: 1.2; }
#title-song em { grid-row: 1; margin-left: 12px; }
#title-song span { grid-row: 2; grid-column: 1 / -1; overflow: hidden; text-overflow: ellipsis; font-size: 13px; }
#title-time { grid-column: 2; font-variant-numeric: tabular-nums; }
/* IconButton's 18px icon, boxes trimmed to 24px and touching; play keeps the same box. */
#title-controls { grid-column: 3; grid-row: 1; display: flex; align-items: center; gap: 0; }
#title-controls button { width: 24px; height: 24px; padding: 3px; display: grid; place-items: center; box-sizing: border-box; }
#title-controls svg { width: 18px; height: 18px; display: block; }
#title-pause:not([data-paused]) .title-play-glyph, #title-pause[data-paused] .title-pause-glyph { display: none; }
/* HoverableProgressBar: 5px, 10px under the pointer; it grows upward, so the box keeps 10px. */
#title-progress { grid-column: 1 / -1; height: 10px; display: flex; flex-direction: column; justify-content: flex-end; touch-action: none; }
.title-track { height: 5px; }
#title-progress:hover .title-track, #title-progress[data-seeking] .title-track { height: 10px; }
#title-progress span { display: block; position: relative; width: 0; height: 100%; }
/* A circle at the play position makes the bar read as a slider; it grows with the track. */
#title-progress span::after { content: ""; position: absolute; right: -6px; top: 50%; width: 12px; height: 12px; translate: 0 -50%; border-radius: 50%; }
#title-progress:hover span::after, #title-progress[data-seeking] span::after { right: -8px; width: 16px; height: 16px; }
/* Volume overlay (osu!lazer): a 300px column at the left edge, meters stacked 10px apart, label beside each ring. */
#volume:not([hidden]) { position: fixed; z-index: 100; top: 0; bottom: 0; left: 0; width: 300px; padding-left: 10px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; gap: 10px; }
.volume-meter { display: flex; align-items: center; gap: 10px; }
.volume-ring { display: grid; place-items: center; }
.volume-ring > * { grid-area: 1 / 1; }
.volume-name { width: 120px; height: 20px; display: grid; place-items: center; }
#medley:not([hidden]) { display: grid; grid-template-columns: clamp(280px, 28vw, 360px) minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; grid-template-areas: "info search" "info list" "commands commands"; gap: 8px 24px; min-height: 0; }
#medley h2, #medley h3, #medley p { margin: 0; }
#medley-detail { grid-area: info; display: grid; align-content: start; gap: 16px; padding: 12px; min-height: 0; overflow: auto; }
#medley-keys { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin-top: 12px; }
#medley-songs { margin: 0; padding-left: 1.5em; display: grid; gap: 12px; }
#medley-songs li { padding: 8px 4px; }
.medley-picked-name { display: block; overflow-wrap: anywhere; }
.medley-picked-chart { display: flex; gap: 8px; align-items: center; }
#medley-top { grid-area: search; display: flex; align-items: center; gap: 12px; padding: 10px 10px 8px; }
#medley-search { flex: 1; min-width: 0; height: 40px; padding: 0 12px; box-sizing: border-box; }
#medley-list { grid-area: list; display: grid; grid-template-rows: auto minmax(0, 1fr); padding: 8px 12px; min-height: 0; }
#medley-list-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; padding-bottom: 12px; }
#medley-candidates { margin: 0; padding: 0; overflow: auto; overflow-x: hidden; min-height: 0; }
#medley-candidates .chart-name { flex: 1; }
#medley-commands { grid-area: commands; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
#medley-status { flex: 1; }
#medley-picked-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
#medley-play { justify-self: start; display: flex; gap: 20px; align-items: center; padding: 10px 20px; }
#medley-summary { max-width: 24em; overflow-wrap: anywhere; }
#medley-commands { flex-wrap: wrap; }
#medley-pages { display: flex; align-items: center; gap: 8px; }
#story:not([hidden]) { display: grid; grid-template-columns: clamp(280px, 28vw, 360px) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "info list" "commands commands"; gap: 8px 24px; min-height: 0; }
#story h2, #story p { margin: 0; }
#story-detail { grid-area: info; display: grid; align-content: start; gap: 16px; padding: 12px; min-height: 0; overflow: auto; }
#story-charts { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }
#story-charts li { padding: 8px 12px; }
#story-list { grid-area: list; margin: 0; padding: 8px 12px; overflow: auto; overflow-x: hidden; min-height: 0; }
#story-list li { grid-template-columns: 64px minmax(0, 1fr); align-items: center; }
#story-list .chart-name { flex: 1; }
.story-photo { width: 64px; height: 64px; object-fit: cover; }
#story-stage { position: relative; aspect-ratio: 1; overflow: hidden; }
#story-cover, .story-fx-copy { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
#story-cover:not([src]) { visibility: hidden; }
#story-fx { position: absolute; inset: 0; pointer-events: none; }
.story-fx-flash { position: absolute; inset: 0; }
.story-fx-side { position: absolute; top: 0; bottom: 0; width: 29%; }
.story-fx-side.left { left: 0; }
.story-fx-side.right { right: 0; }
.story-fx-dot { position: absolute; top: 100%; width: 11%; aspect-ratio: 1; }
.story-fx-star { position: absolute; bottom: 0; width: 2%; aspect-ratio: 1; }
.story-fx-title { position: absolute; left: 0; right: 0; bottom: 12%; text-align: center; white-space: pre; }
.story-fx-title span { display: inline-block; white-space: pre; }
#story-commands { grid-area: commands; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
#story-status { flex: 1; }
#top p { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin: 10px 0 6px; }
#search-text { flex: 1 1 18em; max-width: 36em; height: 40px; box-sizing: border-box; padding: 0 12px; }
#view-switch, #sort-direction, #level-model { display: flex; align-items: center; gap: 4px; }
#top { grid-area: search; padding: 0 10px 8px; }
#menu-fps { margin-left: auto; flex-shrink: 0; white-space: nowrap; font-size: 12px; font-variant-numeric: tabular-nums; }
#filters { margin: 0 0 16px; display: grid; gap: 16px; }
#lamp-filter { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; }
#time-rate { width: 5ch; padding: 0; }
#time-rate::-webkit-inner-spin-button, #time-rate::-webkit-outer-spin-button { display: none; }
#rate-controls { flex-basis: 100%; margin: 12px 0 0; padding: 8px 12px; min-width: 0; }
#rate-value { margin-left: 8px; }
#rate-input:not([hidden]) { display: inline-flex; align-items: baseline; margin-left: 8px; }
#rate-presets { position: relative; height: 30px; margin: 0 6px 12px; }
#rate-presets button { position: absolute; top: 0; padding: 6px 3px; }
#rate-controls .slider { width: auto; margin-bottom: 12px; }
.rate-custom-row { display: flex; align-items: center; gap: 12px; }
/* 임의 설정 and Pitch are on/off toggles: the word alone, lit when on. */
#rate-custom, #pitch-toggle { display: flex; align-items: center; gap: 12px; padding: 2px 6px; }
#rate-custom .feel-label, #pitch-toggle .feel-label { display: flex; align-items: center; gap: 12px; }
#rate-custom .feel-hover, #rate-custom .feel-flash, #pitch-toggle .feel-hover, #pitch-toggle .feel-flash, #rate-presets .feel-hover, #rate-presets .feel-flash { display: none; }
.range { display: grid; grid-template-columns: 3em minmax(14em, 1fr); column-gap: 8px; }
.range-title { grid-row: 1 / span 3; align-self: center; }
.range-chart { position: relative; height: 40px; display: grid; align-items: end; gap: 1px; }
.range-window { position: absolute; top: 0; bottom: 0; }
.range-bar { position: relative; z-index: 1; }
.range-axis { display: grid; gap: 1px; }

#panes { display: contents; }
#detail { grid-area: info; display: grid; grid-template-rows: minmax(0, auto) auto minmax(150px, 1fr); gap: 8px; overflow: hidden; min-height: 0; }
#detail, #list-pane { padding: 8px 12px; }
#selection { max-height: calc(100vh - 288px); overflow: auto; }
/* Hero: the chart background fills the pane width; level, chart name and title sit on its bottom edge. */
#hero { display: grid; grid-template-rows: auto auto; margin: 0 0 8px; overflow: hidden; }
#song-cover, #hero-text { min-width: 0; }
#song-cover { display: block; width: 100%; aspect-ratio: 16 / 9; max-height: 180px; padding: 12px 12px 0; box-sizing: border-box; object-fit: contain; }
#song-cover[hidden] { display: none; }
#hero-text { align-self: end; display: grid; gap: 2px; padding: 6px 12px; overflow-wrap: anywhere; }
#hero-text p, #hero-text h2 { margin: 0; }
#hero-level { flex: none; }
#difficulty { flex: 1 1 140px; min-width: 0; }
#chart-line:not([hidden]) { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; min-width: 0; }
.rate-badge { flex: none; padding: 1px 8px; }
#loader-rate { justify-self: start; margin-top: 6px; }
#song-duration:not([hidden]) { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 7px; padding: 5px 0 2px; }
#song-duration svg { align-self: center; flex: none; width: 14px; height: 14px; }
#duration-value, #duration-original { flex: none; }
/* The clock says what the number is, as osu!lazer's info wedge: the words stay for screen readers only. */
#duration-label { position: absolute; width: 1px; height: 1px; overflow: hidden; }
#song-notes:not([hidden]) { display: flex; flex-wrap: wrap; gap: 4px 14px; padding: 4px 0 2px; }
#song-notes > span { white-space: nowrap; }
#chart-analysis:not([hidden]) { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 0 0 10px; }
.analysis-column { min-width: 0; }
.analysis-column h3, #song-reading { display: flex; align-items: baseline; justify-content: space-between; gap: 3px; margin: 0 0 6px; }
.analysis-column dl { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; margin: 0; }
.analysis-column dl > div, #motor-total, #reading-total { display: flex; justify-content: space-between; gap: 3px; }
.analysis-column dt, .analysis-column dd { margin: 0; }
.analysis-column dd { flex: none; }
.analysis-column dt { min-width: 0; }
#motor-total, #reading-total { margin: 6px 0 0; padding-top: 4px; }
#density-overview { margin-bottom: 6px; }
#info-density { display: flex; align-items: end; gap: 1px; height: 40px; }
#info-density span { flex: 1; min-width: 0; }
#best { margin: 4px 0; }
#preview-status { margin: 6px 0 0; }
#links { margin: 6px 0 0; }
#links-list { margin: 4px 0; padding: 0; list-style: none; display: grid; gap: 4px; }
#links-list li { display: flex; align-items: center; gap: 6px; min-width: 0; }
#links-list .link-pick { flex: 1; min-width: 0; padding: 2px 8px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-align: center; }
#links-list .link-offset, #links-offset { width: 8ch; }
#links-new { display: flex; align-items: center; gap: 6px; }
#links-url { flex: 1; min-width: 0; }
#links-status { margin: 0; }
#chart-menu { position: fixed; margin: 0; min-width: 180px; max-width: min(320px, calc(100vw - 24px)); padding: 8px; z-index: 1200; }
#chart-menu-name { margin: 0 0 6px; overflow-wrap: anywhere; }
#chart-menu [role="menuitem"] { display: block; width: 100%; padding: 10px 12px; }
#chart-menu { overflow: visible; }
#chart-collections:disabled { display: none; }
#collection-menu { position: fixed; margin: 0; min-width: 200px; max-width: min(320px, calc(100vw - 24px)); max-height: 60vh; overflow: auto; padding: 8px; z-index: 1200; }
#chart-collection-list { position: absolute; min-width: 180px; max-width: min(320px, calc(100vw - 24px)); max-height: 60vh; overflow: auto; padding: 8px; box-sizing: border-box; }
#chart-collection-list[hidden] { display: none; }
#collection-items [role^="menuitem"], #chart-collection-list [role^="menuitem"] { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; width: 100%; padding: 10px 12px; text-align: left; }
#chart-collection-list input { display: block; width: 100%; box-sizing: border-box; margin: 4px 0; }
#library-collections { display: inline-flex; }
#library-collection { max-width: 10em; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#collections-dialog { width: min(560px, calc(100vw - 48px)); max-height: calc(100vh - 48px); padding: 24px 28px; box-sizing: border-box; overflow: auto; }
#collections-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
#collections-head h2 { margin: 0; }
#collections-rows { margin: 0 0 16px; padding: 0; list-style: none; }
#collections-rows li { display: grid; grid-template-columns: minmax(0, 1fr) 6ch auto auto; align-items: center; gap: 12px; padding: 6px 0; }
#collections-rows li > span { text-align: right; }
#collection-new { display: flex; gap: 8px; }
#collection-name { flex: 1; min-width: 0; }
#chart-tags:disabled { display: none; }
#tags-dialog { width: min(560px, calc(100vw - 48px)); max-height: calc(100vh - 48px); padding: 24px 28px; box-sizing: border-box; overflow: auto; }
#tags-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
#tags-head h2 { margin: 0; }
#tags-chart { margin: 0 0 12px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#tags-all, #tags-shared { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; padding: 0 4px; }
#tags-all[hidden], #tags-shared[hidden] { display: none; }
#tags-all button, #tags-shared button { display: inline-flex; align-items: baseline; gap: 8px; max-width: 100%; }
#tags-all button span, #tags-shared button span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#tag-new, #tags-share-row { display: flex; gap: 8px; margin-bottom: 12px; }
#tag-name { flex: 1; min-width: 0; }
#collect-dialog { width: min(1000px, calc(100vw - 48px)); height: min(760px, calc(100vh - 48px)); padding: 24px 32px; box-sizing: border-box; overflow: hidden; }
#collect-dialog[open] { display: flex; flex-direction: column; gap: 16px; }
#collect-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex: none; }
#collect-heading { margin: 0; }
#collect-controls { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 16px; padding: 0 8px; flex: none; }
#collect-kinds, #collect-goals { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
#collect-controls button, #collect-foot button, #collect-close { height: 64px; min-width: 64px; padding: 0 12px; }
#collect-list { flex: 1; min-height: 0; overflow: auto; margin: 0; padding: 8px; list-style: none; }
#collect-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 16px; min-height: 64px; padding: 8px 20px; box-sizing: border-box; }
#collect-list strong { overflow-wrap: anywhere; }
#collect-list .collect-count { white-space: nowrap; }
#collect-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: end; gap: 12px; padding: 0 8px; flex: none; }
#collect-status { flex: 1; min-width: 100px; }
#collect-scope { margin: 8px 0 0; overflow-wrap: anywhere; }
.play-options { padding: 0; margin: 0; min-width: 0; }
.mod-section { margin: 0 0 14px; }
.mod-section h3 { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 0 8px; }
.mod-section output { margin-left: 12px; }
.option-buttons, .mod-buttons { display: flex; gap: 8px; }
.option-buttons button { flex: 1; padding: 8px; }
.option-buttons small { display: block; margin-top: 4px; }
/* Effects are one-line chips, as osu!lazer's mod panels without their descriptions: acronym, small picture,
   name. What each does is in its tooltip. Pressed shows by colour, so the OFF/ON words and the section values
   stay hidden; only O2Jam's step (EASY → HARD) shows while it is on. */
/* The default effect buttons are one size; the content is centred in a narrow margin. A long name takes two cells. */
.mod-buttons { display: grid; grid-template-columns: repeat(auto-fill, 136px); gap: 6px; }
/* The heading already names the field-event menu; its label stays for screen readers only. */
label[for="field-event"] { position: absolute; width: 1px; height: 1px; overflow: hidden; }
.mod-buttons button, .mod-buttons .feel-label { display: flex; align-items: center; justify-content: center; gap: 8px; min-width: 0; text-align: center; }
.mod-buttons button { position: relative; padding: 6px 8px; }
#arrangement-buttons [data-scope] { grid-column: span 2; }
/* The five challenges share one row; their value buttons come on the next. */
#fail-buttons { grid-template-columns: repeat(5, 1fr); }
.mod-icon { display: block; flex: none; width: 36px; height: 22px; }
.mod-copy { display: block; min-width: 0; white-space: nowrap; }
.mod-state, .mod-section h3 > output { display: none; }
#mod-o2jam[aria-pressed="true"] .mod-state { display: inline; margin-left: auto; padding: 1px 5px; }
#play-controls { display: grid; grid-template-columns: minmax(0, 1.8fr) minmax(270px, 1fr); gap: 28px; }
.mod-deck, .mod-tuning { min-width: 0; }
.mod-tuning { padding-left: 24px; }
#mode-buttons button, #mode-buttons .feel-label { display: flex; align-items: center; justify-content: center; gap: 12px; }
#mode-buttons svg { width: 30px; height: 30px; flex: none; }
#mode-buttons button { flex: none; padding: 4px 18px; }
#mods-dialog #rate-controls { margin-bottom: 14px; }
#mods-dialog #rate-controls, .health-cell { border-radius: 7px; }
#mods-dialog { border-radius: 12px; }
#mods-dialog .slider-fill, #mods-dialog .slider-rest, #mods-dialog .slider-nub, #mods-dialog .gauge-track, #mods-dialog .gauge-fill { border-radius: 7px; }
#mods-dialog .dropdown-head, #mods-dialog .dropdown-menu { border-radius: 7px; }
.health-range { cursor: pointer; touch-action: none; user-select: none; padding: 28px 0; }
.health-rail { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); }
.health-cell { display: block; padding: 8px 0; text-align: center; font-size: 12px; font-weight: bold; box-sizing: border-box; border-radius: 0; }
:root:lang(ko) .health-cell:not([data-stage="0"])::first-letter { font-size: 22px; }
:root:lang(ko) .health-cell[data-stage="0"] { padding: 0; line-height: 38px; }
.health-thumb { position: absolute; width: 52px; height: 24px; margin: 0; padding: 0; box-sizing: border-box; transform: translateX(-50%); cursor: ew-resize; font-size: 12px; font-weight: bold; }
.health-thumb.start { bottom: 100%; }
.health-thumb.fail { top: 100%; }
.health-range[aria-disabled="true"] { opacity: .35; pointer-events: none; }
#mods-dialog .mod-section:last-child { margin-bottom: 0; }
#mods-dialog .range { grid-template-columns: 1fr; }
#mods-dialog .range-title { grid-row: auto; }
@media (max-width: 800px) {
    #play-controls { grid-template-columns: 1fr; gap: 24px; }
    .mod-tuning { padding-left: 0; }
}
@media (max-width: 480px) {
}
#detail svg { max-width: 100%; height: auto; }
#history-box { display: grid; grid-template-rows: auto auto auto minmax(0, 1fr); min-height: 0; }
#history-heading, #history-status { margin: 4px 0; }
#history-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
#history-rate { padding: 2px 8px; }
#history-status:not(.placeholder) svg { display: none; }
#history-status.placeholder { display: flex; justify-content: center; align-items: center; gap: 10px; padding: 6px 20px; overflow-wrap: anywhere; }
#history-status.placeholder svg { flex: none; width: 22px; height: 22px; }
#history-controls, #history-controls label { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
#history-order { order: 1; margin-left: auto; }
#history-scope { display: flex; gap: 0; }
/* Leave room for the sheared corners of multiline record buttons inside the scroll area. */
#history { overflow: auto; margin: 4px 0 0; padding: 0 20px; }
#history li { display: block; padding: 2px 0; }
#history li.ranked { display: grid; grid-template-columns: 2.5em minmax(0, 1fr) auto 4.5em; align-items: baseline; gap: 8px; }
#history li.ranked > :last-child { justify-self: end; }
.score-open { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; width: 100%; padding: 10px 16px; }
.score-open > .feel-label { min-width: 0; }
.score-points { flex: none; min-width: 9ch; text-align: right; }
.score-mods { display: flex; flex: 1 1 auto; flex-wrap: wrap; justify-content: flex-end; gap: 4px; min-width: 0; margin-left: auto; }
.score-mods > span { padding: 5px 11px; white-space: nowrap; clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 8px 100%, 0 50%); }
.score-date { flex: none; margin-left: auto; }
.score-mods + .score-date { margin-left: 0; }
.score-meta { display: flex; flex: 1 0 100%; flex-wrap: wrap; gap: 4px 10px; min-width: 0; }
/* The four model values live in the hover panel, not the row. */
.score-performance { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 4px; padding-top: 6px; text-align: left; }
.score-performance > span { display: grid; align-content: start; gap: 3px; min-width: 0; }
.score-value { display: grid; gap: 2px; }
#score-tip { position: fixed; z-index: 10; display: grid; gap: 2px; padding: 6px 10px; }
#score-tip[hidden], #score-tip .score-performance[hidden] { display: none; }
#score-tip .tip-head, #score-tip .tip-split { display: flex; justify-content: space-between; gap: 16px; }

#list-pane { grid-area: list; display: grid; grid-template-columns: minmax(0, 1fr) 4px; grid-template-rows: auto auto minmax(0, 1fr); column-gap: 8px; padding-right: 0; margin-right: -12px; min-height: 0; }
#list-head { grid-column: 1; max-width: 66em; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 4px 16px; }
#list-head p { margin: 4px 0; }
#key-filter { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; }
/* Piano key counts on the first line, the game modes (drum, catch, sing) on the line below. */
#key-tabs { flex: 1 1 100%; display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.key-label { white-space: nowrap; }
.key-row { display: flex; align-items: center; gap: 4px; }
#key-tabs button, #key-filter button { display: inline-flex; align-items: center; gap: 6px; }
#key-tabs .mode-icon, #key-filter .mode-icon { width: 16px; height: 16px; flex: none; }
#library-tabs, .chart-progress { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
#list-head #list-summary { flex: 1 1 100%; }
#song-list { grid-area: 3 / 1; min-width: 0; overflow: auto; overflow-x: hidden; margin: 0; padding: 0 12px 0 0; }
/* Header and rows share --table-columns (catalog.js): best mm play, song, each level model, O2Jam, side; the lamp sits in the song cell. */
#level-head, #song-list li:not([role="presentation"]):not(.list-spacer) { display: grid; grid-template-columns: var(--table-columns); column-gap: 12px; align-items: center; }
#level-head { grid-area: 2 / 1; padding: 0 16px 0 8px; }
#level-head > * { min-width: 0; padding: 4px 0; overflow: hidden; }
.level-col { text-align: right; }
/* Best play: the score stays right-aligned in its own part; the rate part is one fixed width so (x1.0) and (x1.25) start on the same column. */
.best-play { display: flex; justify-content: flex-end; column-gap: 0.4em; }
.best-rate { flex: 0 0 7ch; text-align: left; }
.table-col { text-align: left; }
#catalog-loading:not([hidden]), #server-loading:not([hidden]) { grid-area: 3 / 1; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 12px; padding: 24px; }
#catalog-progress { width: 320px; max-width: 100%; height: 12px; }
#catalog-numbers { display: flex; justify-content: space-between; width: 320px; max-width: 100%; margin-top: -6px; }
#catalog-file { max-width: 100%; overflow-wrap: anywhere; text-align: center; }
.song-catalog li { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px; max-width: 52em; padding: 1px 4px; }
#song-list li { max-width: none; }
#song-list li.more { padding-left: calc(16ch + 12px + 32px); }
/* A rail in the song column marks the open song's charts; rows no longer move sideways, so it stays put. */
#song-list li.chart-in-song::before, #song-list li.more::before { content: ''; position: absolute; top: 0; bottom: 0; left: calc(16ch + 12px + 14px); width: 2px; }
#song-list .chart-label { display: contents; }
#song-list .chart-progress { grid-column: -2 / -1; }
.chart-cell { grid-column: 2; display: flex; align-items: center; gap: 8px; min-width: 0; }
.chart-thumb { display: block; flex: none; width: 28px; height: 28px; object-fit: cover; }
#song-list li[role="presentation"]:not(.more) { padding-top: 10px; }
#song-list li.list-spacer { padding: 0; border: 0; }
.chart-progress { justify-content: flex-end; max-width: 26em; }
#song-list .chart-progress time, #song-list .chart-progress .chart-reason { display: flex; justify-content: flex-end; flex: 1 1 100%; }
.chart-label { display: flex; align-items: center; gap: 8px; min-width: 0; }
.chart-name { display: block; min-width: 0; overflow: hidden; }
.chart-title { display: block; position: relative; width: max-content; }
.chart-repeat { position: absolute; top: 0; left: calc(100% + 48px); width: max-content; }
.chart-mark { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.chart-level { display: block; width: 2ch; flex-shrink: 0; }
.source-level { flex-shrink: 0; }
.chart-mark .source-level { min-width: 4ch; }
.chart-lamp { display: block; width: 10px; height: 22px; box-sizing: border-box; flex-shrink: 0; }
.combo-lamp { display: grid; place-items: center; position: relative; }
.lamp-flash { position: absolute; inset: 0; }
.lamp-shine { position: absolute; top: 0; left: 0; right: 0; height: 8px; }
.combo-lamp[data-half] .lamp-flash { top: 50%; }
.combo-lamp[data-half] .lamp-shine { display: none; }
.chart-release { white-space: nowrap; }
.chart-points { display: flex; justify-content: flex-end; width: 6ch; flex-shrink: 0; }

#sort-options { display: grid; grid-template-columns: repeat(auto-fill, minmax(11em, 1fr)); gap: 8px; margin-bottom: 16px; }
#sort-options button { padding: 12px 16px; }
/* Bottom command bar: command buttons left; the player profile and the song-list options side by side at the
   right end. It stops at the list column so the docked chat never covers it. */
/* Command bar: one row of 44px sheared tiles, two tight lines each, command buttons and status tiles alike. The sheared corners overhang
   the box by about a tenth of the height, so the clipping strip keeps 8px at each side. */
#commands { grid-area: commands; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 16px; }
.hints { min-width: 0; display: flex; gap: 8px; align-items: center; align-self: stretch; padding: 6px 8px; overflow: hidden; }
.hints .tile { flex: none; display: grid; align-content: center; justify-items: center; gap: 2px; min-width: 64px; height: 44px; white-space: nowrap; box-sizing: border-box; margin: 0; padding: 2px 8px; text-align: center; }
.hints button > span, .hints button > feel-label > span { max-width: 100%; overflow-wrap: anywhere; text-align: center; }
#hints-end { justify-self: end; justify-content: flex-end; }
/* The effector button is the big frame: F1 and the tiles it controls sit inside, 44px tiles + 4px padding + 2px border. */
.hints .effector { flex: none; display: flex; align-items: center; gap: 6px; height: 56px; padding: 4px 10px; box-sizing: border-box; cursor: pointer; }
.hints .tile strong, .hints button.tile span { font-size: 15px; }
.hints .tile :is(small, kbd) { font-size: 10px; }
.hints output.tile small { order: -1; box-sizing: border-box; width: 100%; padding-bottom: 2px; text-align: center; }
#scroll-summary { width: 72px; padding: 2px 0; }
#scroll-summary:not(:has(strong)) { width: auto; padding: 2px 12px; }
#exposure-summary { align-self: center; flex: none; padding: 0 8px; white-space: nowrap; }
#mod-summary { align-self: center; min-width: 0; padding: 0 16px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#mod-summary .mod-key { padding: 2px 6px 0; }
#player { display: flex; justify-content: center; padding: 2px 16px; }
#player > .feel-label { display: grid; grid-template-columns: 32px auto; gap: 0 12px; align-items: center; justify-content: center; justify-items: start; }
.avatar { flex: none; display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; background-size: cover; background-position: center; font-style: normal; font-weight: 700; font-size: 18px; }
#player-avatar { grid-row: 1 / 3; width: 32px; height: 32px; font-size: 15px; }
#player-name { grid-column: 2; }
#best-head h2 .avatar { align-self: center; width: 56px; height: 56px; font-size: 26px; margin-right: -4px; }
#player .feel-label > span { grid-column: 2; display: flex; gap: 12px; }
#notices { position: fixed; top: 16px; left: 50%; transform: translateX(-50%); z-index: 20; display: grid; gap: 8px; justify-items: center; max-width: min(640px, calc(100vw - 32px)); pointer-events: none; }
#notices > p { margin: 0; padding: 10px 20px; white-space: pre-line; }
#popups { position: fixed; right: 16px; bottom: 72px; z-index: 20; display: grid; gap: 8px; justify-items: end; max-width: min(420px, calc(100vw - 32px)); }
#popups > p { margin: 0; padding: 10px 16px; white-space: pre-line; cursor: pointer; }
#player-input { width: 16em; }
#best-dialog { width: min(820px, calc(100vw - 48px)); max-height: calc(100vh - 48px); padding: 24px 28px; box-sizing: border-box; overflow: auto; }
#best-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
#best-head h2 { display: flex; align-items: baseline; gap: 16px; margin: 0; }
#best-list { margin: 0; padding: 0; list-style: none; }
#best-list li { display: grid; grid-template-columns: 3ch minmax(0, 1fr) auto 100px; align-items: center; gap: 0 16px; }
#best-list li > div { display: grid; gap: 2px; min-width: 0; padding: 10px 0; }
#best-list li > div > span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#best-list .best-mm { justify-items: end; text-align: right; }
#best-list .best-box { align-self: stretch; display: flex; align-items: center; justify-content: center; gap: 2px; padding-left: 12px; clip-path: polygon(14px 0, 100% 0, 100% 100%, 14px 100%, 0 50%); }
#today-dialog { width: min(820px, calc(100vw - 48px)); max-height: calc(100vh - 48px); padding: 24px 28px; box-sizing: border-box; overflow: auto; }
#today-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
#today-head h2 { margin: 0; }
#today-list, #today-list ol { margin: 0; padding: 0; list-style: none; }
#today-list > li { margin-bottom: 16px; }
#today-list h3 { display: flex; align-items: baseline; gap: 16px; margin: 0 0 4px; }
#today-list ol li { display: grid; grid-template-columns: 5ch minmax(0, 1fr) auto 112px; align-items: center; gap: 0 16px; }
#today-list ol li > div { display: grid; gap: 2px; min-width: 0; padding: 10px 0; }
#today-list ol li > div > span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
#today-list .today-value { justify-items: end; text-align: right; }
#today-list .today-kind { align-self: stretch; display: flex; align-items: center; justify-content: center; padding-left: 12px; white-space: nowrap; clip-path: polygon(14px 0, 100% 0, 100% 100%, 14px 100%, 0 50%); }
#mods-dialog { width: min(1020px, calc(100vw - 48px)); max-height: calc(100vh - 48px); padding: 24px 28px; box-sizing: border-box; overflow: auto; }
#downloads { width: min(940px, calc(100vw - 48px)); height: min(760px, calc(100vh - 48px)); padding: 24px 28px; box-sizing: border-box; overflow: visible; }
#downloads[open] { display: flex; flex-direction: column; gap: 12px; }
#downloads > * { flex: none; margin: 0; }
#downloads > footer, #download-form { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
#downloads > footer { justify-content: center; }
#download-title { white-space: nowrap; }
#download-form label { display: flex; align-items: center; gap: 8px; }
#download-form .dropdown { min-width: 10em; }
#download-form .download-query-box { flex: 1 1 16em; min-width: 0; }
#download-query { width: 100%; height: 40px; box-sizing: border-box; padding: 0 12px; border-radius: 5px; }
#download-server { width: 30em; max-width: 65vw; }
#download-summary { min-width: 5ch; text-align: center; font-variant-numeric: tabular-nums; }
#download-list { flex: 1 1 auto; min-height: 0; margin: 0; padding: 0 10px; list-style: none; overflow: auto; }
#download-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 2px 16px; padding: 10px 4px; }
#download-list strong, #download-list span { min-width: 0; overflow-wrap: anywhere; }
#download-list strong { grid-column: 1; }
#download-list span { grid-column: 1; }
#download-list button { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
#download-list .download-preview { grid-column: 2; min-width: 48px; }
#download-progress { width: 100%; }
#download-status { overflow-wrap: anywhere; }
#mods-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; padding-bottom: 10px; }
#mods-dialog h2 { margin: 0; }
#playback-status { margin: 8px 0; min-height: 1.2em; }
#advanced { width: min(900px, calc(100vw - 48px)); max-height: calc(100vh - 48px); box-sizing: border-box; overflow: auto; }
#advanced h2 { margin: 0 0 16px; }

#editor:not([hidden]) { display: grid; grid-template-rows: auto auto minmax(240px, 1fr) auto auto; gap: 8px; min-height: 0; }
#editor header, #edit-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 8px 0; }
#editor header h2, #editor p { margin: 0; }
#edit-title { flex: 1; }
#edit-body { display: grid; grid-template-columns: 300px minmax(280px, 1fr) 44px 280px; gap: 12px; min-height: 0; }
#edit-charts, #edit-inspector { overflow: auto; min-height: 0; }
#edit-charts { padding: 0 12px 0 8px; }
#edit-inspector { padding: 0 8px; }
#edit-charts ul { padding: 0; margin: 8px 0 20px; }
#edit-charts button { width: 100%; margin-bottom: 8px; padding: 8px 10px; }
#edit-new-chart input { width: 100%; box-sizing: border-box; margin-bottom: 8px; }
#edit-chart-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
#edit-chart-list li button + button { width: auto; }
#edit-fb-text { width: 100%; box-sizing: border-box; margin-bottom: 8px; }
#edit-fb-move { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#edit-fb-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
#edit-fb-list li button + button { width: auto; }
#edit-fb-list li button:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
#edit-fb-shown { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0 0 20px; }
#edit-fb-status:empty { display: none; }
#edit-field { display: grid; min-height: 0; overflow: hidden; }
#edit-grid, #edit-map { width: 100%; height: 100%; min-height: 240px; }
#edit-inspector form { display: grid; gap: 6px; }
#edit-inspector form[hidden] { display: none; }
#edit-inspector label { display: grid; grid-template-columns: 6em minmax(0, 1fr); align-items: center; gap: 2px 8px; }
#edit-inspector input, #edit-inspector select { width: 100%; box-sizing: border-box; }
#edit-inspector h3 { margin: 8px 0; }
#edit-inspector ol { padding-left: 20px; }
#edit-inspector li { margin: 4px 0; }
#edit-sv-effects { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
#edit-sv canvas { display: block; width: auto; max-width: 100%; max-height: 190px; margin-top: 6px; }
#edit-sv-apply { margin-top: 6px; width: 100%; }
#edit-retime-modes, .edit-retime-pick { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
#edit-retime-fields { margin-bottom: 6px; }
#edit-retime-summary { display: block; margin: 6px 0; }
#edit-retime-apply { width: 100%; }
#edit-story-sprites { list-style: none; margin: 0 0 6px; padding: 0 8px 0 0; max-height: 120px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
#edit-story-sprites button { width: 100%; text-align: left; }
#edit-story-timeline { position: relative; display: flex; flex-direction: column; gap: 4px; margin-bottom: 6px; }
.edit-story-row { display: grid; grid-template-columns: 24px 1fr; align-items: center; gap: 4px; }
.edit-story-track { position: relative; height: 22px; }
.edit-story-track button { position: absolute; top: 2px; height: 18px; min-width: 8px; padding: 0; }
.edit-story-head { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: 28px; pointer-events: none; }
#edit-story-preview { display: block; width: 100%; max-width: 320px; height: auto; margin-bottom: 6px; }
#edit-story-kinds, #edit-story-easings, #edit-story-ops, #edit-story-shift, #edit-story-values { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; }
#edit-story-summary { display: block; margin: 6px 0; }
#edit-story-apply { width: 100%; }
/* Audio menu (Quaver's editor menu bar): checked items drop down under the button. */
#edit-audio-menu { position: relative; }
#edit-audio-items:not([hidden]) { position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; display: flex; flex-direction: column; min-width: 14em; padding: 4px 0; }
#edit-audio-items label { display: flex; justify-content: space-between; gap: 16px; padding: 6px 12px; }
#edit-audio-items input { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; }
/* osu!lazer editor BottomBar: 50 high; columns time | summary | playback | Test, 15 padding inside each.
   lazer's 150 / 220 columns are 180 / 300 here: Gosu UI digits are wider than Torus and there are five speeds. */
#edit-transport { display: grid; grid-template-columns: 180px minmax(0, 1fr) 300px 110px; height: 50px; }
#edit-clock { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-content: center; padding: 0 15px; min-width: 0; }
#edit-time, #edit-position { grid-column: 1 / -1; justify-self: start; padding: 0 2px; }
#edit-position { width: 128px; height: 26px; box-sizing: border-box; }
#edit-summary { width: 100%; height: 100%; padding: 0 15px; box-sizing: border-box; }
#edit-playback { display: flex; align-items: center; gap: 9px; padding: 0 15px; }
#edit-play { display: grid; place-items: center; width: 36px; height: 36px; padding: 0; flex: none; }
#edit-play svg { width: 28px; height: 28px; }
#edit-speed { display: grid; flex: 1; min-width: 0; }
#edit-rates { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; height: 16px; }
#edit-rates button { padding: 0; text-align: center; }
#edit-test { height: 100%; }
#editor.compact #edit-charts { display: none; }
#editor.compact #edit-body { grid-template-columns: minmax(280px, 1fr) 44px 280px; }
#editor.testing #edit-charts, #editor.testing #edit-inspector, #editor.testing #edit-toolbar { display: none; }
#editor.testing #edit-body { grid-template-columns: minmax(280px, 1fr) 44px; }
#editor.testing { grid-template-rows: auto minmax(240px, 1fr) auto auto; }
#key-controls { display: flex; align-items: center; gap: 12px; }
#key-count { min-width: 6em; padding: 6px 10px; }
#lane-keys { display: grid; gap: 2px; max-width: 100%; margin: 0 auto; }
.key-lane { position: relative; display: grid; grid-template-rows: 48px 180px 24px; min-width: 0; padding: 0; }
.key-arrow { align-self: center; }
.key-track { position: relative; display: block; grid-row: 2; overflow: hidden; box-sizing: border-box; }
.key-name { position: absolute; top: 48px; bottom: 24px; left: 0; right: 0; display: grid; place-items: center; overflow: hidden; }
.key-number { grid-row: 3; }
.key-note { position: absolute; left: 2px; right: 2px; }
#key-status { min-height: 3em; margin: 12px 0 0; }
#key-pad { box-sizing: border-box; margin: 16px 0 0; padding: 10px; }
/* Settings: a fixed panel with section tabs on the left (Quaver's options menu). */
/* One fixed size; the preview column stays while the list scrolls, so sections never reflow. */
#settings[open] { display: grid; grid-template-columns: max-content minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); grid-template-areas: "head head" "tabs panel"; gap: 12px 24px; box-sizing: border-box; width: min(1480px, calc(100vw - 32px)); height: min(680px, calc(100vh - 32px)); max-width: none; max-height: none; margin: auto; padding: 14px 20px; overflow: hidden; }
#settings-head { grid-area: head; display: flex; justify-content: space-between; align-items: center; }
#settings-head h2 { margin: 0; }
/* Scroll boxes clip their children, so pad by the skewed buttons' overhang (height × tan 11.31° / 2) plus the press bounce. */
#settings-tabs { grid-area: tabs; display: grid; align-content: start; gap: 4px; padding: 4px 8px; overflow: auto; }
#settings-tabs button { display: flex; justify-content: flex-start; padding: 10px 14px; white-space: nowrap; }
#preferences:not([hidden]) { display: contents; }
#settings-content { grid-area: panel; min-height: 0; padding: 4px 8px; overflow: auto; }
#settings.with-preview[open] { grid-template-columns: max-content minmax(0, 1fr) minmax(360px, 1.05fr); grid-template-areas: "head head head" "tabs panel preview"; }
#settings-preview { grid-area: preview; min-width: 0; min-height: 0; display: flex; flex-direction: column; align-self: stretch; gap: 8px; overflow-y: auto; padding: 4px 8px; }
#settings-preview header { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
#settings-preview-frame { aspect-ratio: 16 / 9; width: 100%; flex-shrink: 0; }
#settings-preview-frame iframe { display: block; width: 100%; height: 100%; border: 0; }
#settings-preview-retry { align-self: flex-start; }
#settings-live { display: flex; flex-wrap: wrap; gap: 8px; }
#settings-live[hidden] { display: none; }
#settings-live input[type="number"] { width: 6ch; }
#settings-live output, #settings-live p { flex-basis: 100%; }
#settings-live .live-seek { display: flex; align-items: center; gap: 12px; flex-basis: 100%; min-width: 0; }
#settings-live .live-seek .slider { flex: 1; width: auto; min-width: 0; }
#settings-presets > :not(summary) { margin-block: 8px; }
#settings-presets label { display: block; }
#preset-name { max-width: 16ch; }
#lane-offsets { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 8px; }
#lane-offsets label { display: flex; flex-direction: column; gap: 4px; }
#lane-offsets input { width: 100%; box-sizing: border-box; }
@media (max-width: 1050px) {
    #settings.with-preview[open] { grid-template-columns: 8em minmax(0, 1fr); grid-template-rows: auto auto minmax(0, 1fr); grid-template-areas: "head head" "tabs preview" "tabs panel"; }
    #settings-preview { max-height: 40vh; }
    #settings-preview-frame { max-width: 360px; }
    #settings-preview-retry { align-self: start; }
}
@media (max-width: 600px) {
    #settings.with-preview[open] { grid-template-columns: 6em minmax(0, 1fr); gap: 8px; padding: 12px; }
    #settings-preview { display: flex; }
    #settings-preview-frame { max-width: 100%; }
    #settings-preview > p:empty { display: none; }
    #settings.with-preview .settings-row { grid-template-columns: 1fr; gap: 4px; }
    #settings.with-preview .slider { width: min(18em, calc(100vw - 170px)); }
}
#settings [role="tabpanel"] { min-height: 0; }
#panel-hud-layout { height: 100%; display: flex; flex-direction: column; gap: 10px; }
#panel-hud-layout[data-mode="drum"] #hud-layout-form, #panel-hud-layout:not([data-mode="drum"]) #drum-hud-form { display: none; }
.section-heading { margin: 40px 0 8px; }
#settings-content > .section-heading:first-of-type { margin-top: 0; }
/* The preview takes whatever the panel leaves after the item rows, the controls and the status line, however many rows they wrap to. */
#hud-layout-form, #drum-hud-form { flex: 1; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto auto auto; gap: 10px; }
#hud-preview, #drum-hud-preview { container-type: size; min-width: 0; min-height: 0; display: grid; place-items: center; }
#hud-items { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); }
#drum-hud-items { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
#hud-items button, #drum-hud-items button { min-width: 0; white-space: nowrap; }
/* English element names are longer: fewer, wider columns keep each name whole. */
:root[lang="en"] #hud-items { grid-template-columns: repeat(3, minmax(0, 1fr)); }
:root[lang="en"] #drum-hud-items { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#hud-layout-controls, #drum-hud-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
#hud-layout-controls input[type="number"], #drum-hud-controls input[type="number"] { width: 4.5em; }
#hud-preview-keys { margin-left: auto; }
#settings #hud-layout-status, #settings #drum-hud-status { margin: 0; min-height: 1.2em; }
#hud-preview iframe, #drum-hud-preview iframe { display: block; aspect-ratio: 16 / 9; width: min(100cqw, 100cqh * 16 / 9); height: auto; }
.hud-preview-page { padding: 0; overflow: hidden; }
.hud-preview-page canvas { display: block; }
#preview-error { padding: 12px; }
#settings h3 { margin: 4px 0 6px; }
#settings h3:not(:first-child) { margin-top: 16px; }
/* Each panel of a section starts a visible step below the one above; the first sits right under the section name. */
#settings .panel-heading { margin-top: 28px; }
#settings .section-heading + [role="tabpanel"] > .panel-heading { margin-top: 4px; }
#settings p { margin: 6px 0; }
/* Logged out: the empty name would still take a flex gap and push the button right; an empty status line would add a gap below. */
#account-name:empty { display: none; }
#score-server-status:empty { margin: 0; }
/* One "name | value" row per item. */
.settings-row { display: grid; grid-template-columns: 10em minmax(0, 1fr); align-items: center; gap: 16px; padding: 5px 0; }
/* English labels run longer than Korean ones; the label column fits the longest on one line. */
:root[lang="en"] .settings-row { grid-template-columns: 14em minmax(0, 1fr); }
.settings-row > span { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; }
#theme-colors input[type="color"] { width: 48px; height: 32px; padding: 0; }
#folder-list { margin: 0 0 8px; display: grid; gap: 4px; }
#folder-list > div { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px; }
#folder-list span { overflow-wrap: anywhere; }
#folder-path { width: 28em; max-width: 100%; }
/* Settings sliders (settings/slider.js): parts sit under the invisible range input. */
.choice { display: flex; flex-wrap: wrap; gap: 6px; }
/* An on/off setting is one switch: the nub sits left when off and right when on. */
.choice > .switch { position: relative; flex: none; width: 36px; height: 18px; padding: 0; box-sizing: border-box; }
.switch > i { position: absolute; top: 3px; left: 3px; width: 10px; height: 10px; }
.switch[aria-pressed="true"] > i { left: 21px; }
/* Settings gauges (settings/slider.js wrapGauge): track, fill and marks under the invisible range input. */
.slider.gauge > .gauge-track, .slider.gauge > .gauge-fill, .slider.gauge > .gauge-marks { position: absolute; top: 7px; bottom: 7px; left: 0; }
.slider.gauge > .gauge-track, .slider.gauge > .gauge-marks { right: 0; }
.gauge-marks > i { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; }
/* The bar variant (data-reference): a 6px track with a nub and a mark at the reference value; the fill spans the track and is clipped. */
.slider.gauge.bar > .gauge-track, .slider.gauge.bar > .gauge-fill { top: 12px; bottom: 12px; right: 0; border-radius: 3px; }
.slider.bar > .gauge-nub, .slider.bar > .gauge-reference { position: absolute; }
.slider.bar > .gauge-nub { top: 4px; bottom: 4px; width: 10px; margin-left: -5px; border-radius: 3px; }
.slider.bar > .gauge-reference { top: 8px; bottom: 8px; width: 2px; margin-left: -1px; }
/* Long settings choices (settings/dropdown.js), after osu!lazer OsuDropdown: 40px header with 10px padding,
   corner radius 5, menu 4px below with 5px inner padding; each item pads 2px and indents its label 15px. */
.dropdown { position: relative; display: inline-block; min-width: 14em; }
.dropdown-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; box-sizing: border-box; width: 100%; height: 40px; padding: 0 12px 0 10px; border-radius: 5px; text-align: left; }
.dropdown-chevron { flex: none; width: 6px; height: 6px; margin-top: -4px; border-style: solid; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.dropdown.open .dropdown-chevron { transform: scaleY(-1) rotate(45deg); margin-top: 4px; }
.dropdown-menu { position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 20; display: grid; grid-template-rows: 0fr; border-radius: 5px; overflow: hidden; visibility: hidden; opacity: 0; }
.dropdown.open .dropdown-menu { grid-template-rows: 1fr; visibility: visible; opacity: 1; }
.dropdown-list { min-height: 0; display: flex; flex-direction: column; padding: 0 5px; }
.dropdown-list > :first-child { margin-top: 5px; }
.dropdown-list > :last-child { margin-bottom: 5px; }
.dropdown-list > button { position: relative; display: block; padding: 2px 2px 2px 17px; border: 0; border-radius: 5px; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dropdown-mark { position: absolute; left: 5px; top: 50%; width: 4px; height: 4px; border-style: solid; border-width: 0 2px 2px 0; transform: translate(-3px, -50%) rotate(-45deg); }
.slider { position: relative; display: block; width: 18em; height: 30px; margin-inline: 6px; }
.slider-fill, .slider-rest, .slider-nub { position: absolute; top: 0; bottom: 0; }
.slider-fill { left: 0; }
.slider-rest { right: 0; }
.slider-nub { width: 50px; box-sizing: border-box; }
.slider input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; }
/* Equal columns, so the wider 10K label does not stretch the 9K column above it. */
.lane-picker { display: grid; grid-template-columns: repeat(var(--lane-columns, 5), 1fr); width: max-content; gap: 4px; }
.lane-picker[hidden] { display: none; }
.lane-picker button:last-child { grid-column: -2 / -1; }
#skin-picker { display: flex; flex-wrap: wrap; gap: 8px; }
#skin-part-list { display: grid; gap: 4px; min-width: 18em; }
.skin-part-name { display: grid; grid-template-columns: 9em minmax(0, 1fr); gap: 8px; align-items: center; text-align: left; width: 100%; }
.skin-part-name b { font-weight: normal; overflow-wrap: anywhere; }
.skin-part-choices { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 0 4px; }
.skin-part-choices button { display: grid; justify-items: center; gap: 2px; padding: 3px; font-size: 12px; }
.skin-part-choices img { width: 40px; height: 72px; }
#skin-image-list { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.skin-image { display: inline-flex; align-items: center; gap: 4px; }
#skin-picker button { display: grid; justify-items: center; gap: 4px; padding: 4px; }
#skin-picker img { width: 85px; height: 154px; }
#settings.with-preview .settings-row { grid-template-columns: 9em minmax(0, 1fr); gap: 10px; }
:root[lang="en"] #settings.with-preview .settings-row { grid-template-columns: 13em minmax(0, 1fr); }
:root[lang="en"] #settings.with-preview .slider { width: min(14em, 100% - 12px); }
#settings.with-preview .settings-row > span { min-width: 0; }
#settings.with-preview .slider { width: min(18em, 100% - 12px); }
#settings.with-preview #skin-picker { gap: 6px; }
#settings.with-preview #skin-picker img { width: 58px; height: 105px; }
#settings.with-preview #skin-picker button { font-size: 12px; }
.lane-picker button { min-width: 3.2em; padding: 4px 6px; }
#key-binding { margin-top: 8px; }
/* osu!lazer OsuTextBox: 40px tall, 10px either side, text at half the height; the 3px focus border is always
   reserved so focusing does not move the text. Number boxes drop the browser spinners. */
#settings .settings-row input:is([type="text"], [type="number"], [type="url"], :not([type])) { box-sizing: border-box; height: 40px; padding: 0 7px; }
#settings input[type="number"] { width: 5.5em; appearance: textfield; }
#settings #display-ghostScore { width: 8em; }
input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
@media (max-height: 760px) {
    #settings .key-lane { grid-template-rows: 40px 140px 24px; }
    #settings .key-name { top: 40px; }
}
@media (max-height: 680px) {
    #detail { grid-template-rows: minmax(0, auto) auto minmax(220px, 1fr); }
}
/* Keep actions in view; each column can scroll in a short window. */
#result:not([hidden]) { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "record context" "foot foot"; gap: 10px 20px; width: min(1440px, 100%); margin-inline: auto; padding: 12px 16px 10px; box-sizing: border-box; min-height: 0; overflow: hidden; }
#result-record { grid-area: record; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-content: start; gap: 8px 20px; min-width: 0; min-height: 0; overflow: auto; padding-right: 4px; }
#result-record > * { grid-column: 1 / -1; min-width: 0; }
#result-record > #result-score { grid-column: 1; }
#result-record > #result-detail { grid-column: 2; }
#result-context { grid-area: context; display: grid; grid-template-rows: minmax(0, 1fr); grid-template-areas: "ranking"; gap: 10px; min-width: 0; min-height: 0; padding-left: 16px; }
#result-chart { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-content: start; gap: 6px 16px; min-width: 0; }
#result-chart #result-song { grid-column: 1 / -1; }
#result-chart #result-artist, #result-chart-stats { text-align: right; }
#result-chart p { margin: 0; overflow-wrap: anywhere; }
#result-chart p:empty { display: none; }
#result[data-past="false"] #result-heading, #result-total .result-points > dt, #result-total .result-mm > dt, .run-slot dt { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
#result-head { display: grid; grid-template-columns: max-content minmax(0, 1fr) auto; grid-template-areas: "label meta state"; align-items: center; gap: 4px 16px; padding-bottom: 4px; }
#result-head h1, #result-head p { margin: 0; }
#result-heading { grid-area: label; }
#result-song { overflow-wrap: anywhere; }
#result-state { grid-area: state; align-self: center; }
#result-meta { grid-area: meta; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; }
#result-chart-name { overflow-wrap: anywhere; }
#result-flags:not([hidden]) { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
#result-run { min-width: 0; }
#result-run[open] { display: block; }
#result-run summary { display: none; }
#result-run .run-toggle { display: grid; place-items: center; width: 18px; height: 18px; }
#result-run .run-slots { display: grid; grid-template-columns: repeat(7, minmax(0, 64px)) 8px repeat(2, minmax(0, 64px)); justify-content: start; gap: 4px; margin: 0; padding: 6px; }
.run-slot { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
/* The two results of the play (offset, pauses) sit after a gap, apart from the conditions it ran under. */
#result-slot-offset { grid-column: 9; }
#result-slot-pause { grid-column: 10; }
.run-slot[hidden] { display: none; }
.run-slot dt { order: 2; text-align: center; }
.run-slot dd { order: 1; display: grid; grid-template-rows: 1fr auto; place-items: center; gap: 2px; height: 56px; padding: 5px; box-sizing: border-box; }
.run-slot svg { width: 24px; height: 24px; flex-shrink: 0; }
.run-slot strong { max-width: 100%; text-align: center; overflow-wrap: anywhere; }
#result-adjustment-row { margin: 0; padding: 0 6px 6px; }
@media (max-width: 1279px) {
    #result-run .run-slots { grid-template-columns: repeat(5, minmax(0, 1fr)); }
    #result-slot-offset, #result-slot-pause { grid-column: auto; }
}
#result-calibration:not([hidden]) { display: flex; align-items: center; gap: 12px; }
#result-score { min-width: 0; }
#result-total { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 20px; margin: 0; }
.result-points, #result-total .result-mm { grid-column: 1 / -1; }
#result-total > div:not(.result-points) { display: grid; gap: 2px; align-content: start; }
#result-total .result-mm { min-width: 0; }
#result-total .result-mm-value { position: relative; width: fit-content; max-width: 100%; }
#result-ratings { display: none; position: absolute; bottom: 100%; right: 0; z-index: 2; width: 360px; max-width: calc(100vw - 32px); box-sizing: border-box; padding: 14px; }
.result-mm-value:hover #result-ratings { display: block; }
#result-total .result-value { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 8px; }
#result-combo-status { align-self: center; padding: 2px 5px; }
#result-performance { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0; }
#result-performance div { display: grid; gap: 6px; min-width: 0; }
#result-performance dt, #result-performance dd { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#result-mm-status { margin: 0 0 6px; }
#result-mm-status:empty { display: none; }
#result-performance-status { margin: 6px 0 0; }
#result-performance-status:empty { display: none; }
.result-points { display: grid; grid-template-columns: max-content minmax(0, 1fr); align-items: center; align-content: start; gap: 2px 8px; padding: 0; }
.result-points dt { grid-column: 1; grid-row: 1; }
#result-best-status { grid-column: 2; grid-row: 1; }
#result-points { grid-column: 1 / -1; grid-row: 2; }
#result dd { margin: 0; }
#result h2 { margin: 0 0 6px; }
#result-ranking { grid-area: ranking; display: grid; grid-template-rows: auto auto minmax(0, 1fr) auto; align-content: start; min-height: 0; overflow: hidden; padding-top: 8px; }
#result-ranking > header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
#result-ranking > header > div { display: flex; gap: 4px; }
#result-ranking button { padding: 5px 10px; }
#result-ranking p { margin: 8px 0; }
#result-ranking #result-ranking-condition { display: inline-block; margin: 8px 12px 0 0; }
#result-ranking #result-ranking-status { display: inline-block; margin: 8px 0 0; }
#result-ranking p:empty { display: none; }
#result-ranking-rows { min-height: 0; overflow: auto; margin: 8px 0; padding: 0; }
#result-ranking-rows li { display: grid; grid-template-columns: 3em minmax(0, 1fr) auto 4.5em; align-items: baseline; gap: 8px; padding: 6px 8px; }
#result-ranking-rows li > span:nth-child(2) { min-width: 0; overflow: hidden; }
#result-ranking-rows li > :last-child { justify-self: end; }
#result-ranking-expand, #result-ranking-retry { margin-top: 4px; }
#result-comparison { margin-top: 8px; padding-top: 6px; }
#result-comparison:not([hidden]) { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 8px 12px; align-items: baseline; }
#result-comparison h2 { margin: 0; }
#comparison-status { margin: 0; text-align: right; }
#comparison { grid-column: 1 / -1; }
#comparison:not([hidden]) { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0; }
#comparison > div { display: grid; gap: 6px; }
#comparison-legs { grid-column: 1 / -1; }
#comparison-legs p { margin: 0 0 6px; }
#comparison-legs ol { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; margin: 0; padding: 0; list-style: none; }
#comparison-legs li { display: grid; gap: 2px; }
#result-detail { display: flex; flex-direction: column; min-width: 0; }
#result-health-rail { height: 2px; }
#result-health-fill { display: block; height: 100%; }
#result-judgements { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: 4px; margin: 0; }
.result-grade { position: relative; min-width: 0; }
.result-grade dt { position: absolute; top: 0; bottom: 0; left: 8px; z-index: 1; display: flex; align-items: center; }
.result-track { position: relative; height: 26px; overflow: hidden; }
.result-bar { display: block; height: 100%; box-sizing: border-box; }
.result-judge-count { position: absolute; inset: 0; display: flex; align-items: center; justify-content: flex-end; padding: 0 8px; }
#result-timeline:not([hidden]) { position: relative; display: flex; align-items: end; gap: 1px; height: 48px; margin: 0; }
#result-timeline > span { flex: 1; min-width: 0; }
#result-timeline > i { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; }
#result-insight:not([hidden]) { display: grid; gap: 10px; min-width: 0; }
#result-insight svg { display: block; width: 100%; }
#result-insight svg[hidden] { display: none; }
#result-insight text { font-size: 11px; }
#insight-trend .line { fill: none; stroke-width: 1.5; }
#result-review { position: fixed; z-index: 30; box-sizing: border-box; padding: 12px; max-height: calc(100vh - 24px); overflow: auto; }
#result-review header, #result-review footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
#result-review p { margin: 8px 0; }
#result-review header button { padding: 4px 10px; }
#result-review footer { margin-top: 10px; flex-wrap: wrap; }
#result-review footer button { margin-left: auto; padding: 8px 12px; }
.review-tip { position: fixed; z-index: 31; transform: translate(-50%, -100%); padding: 2px 6px; pointer-events: none; }
.review-key { display: flex; align-items: center; gap: 4px 12px; }
.review-key i { display: inline-block; width: 10px; height: 10px; box-sizing: border-box; margin-right: -6px; }
.review-key .note { height: 4px; }
.review-key .down, .review-key .up { border-radius: 50%; }
.review-key .held { height: 3px; width: 16px; }
.review-plot svg { display: block; width: 100%; min-height: 120px; }
.review-hits { max-height: 95px; overflow-y: auto; }
#result-timing:not([hidden]) { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 0; }
#result-timing div { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
#result-mode-counts:not([hidden]) { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; margin: 8px 0 0; }
#result-mode-counts div { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 0 8px; }
#result-mode-counts dd { margin: 0; }
#result-foot { grid-area: foot; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 6px 0 0; }
#result-foot button { min-height: 44px; padding: 6px 22px; }
#result-foot #retry { margin-left: auto; }
#result-foot kbd { margin-left: 12px; }
#result-foot p { flex: 1 1 100%; margin: 0; overflow-wrap: anywhere; }
#result-foot #result-submission { flex: 1 1 auto; order: 1; }
#result-foot #result-share { flex: 1 1 auto; order: 1; }
#result-foot #retry { order: 2; }
#result-foot p:empty { display: none; }
@media (max-height: 720px) {
    #result:not([hidden]) { padding-top: 8px; row-gap: 6px; }
    #result-total { row-gap: 12px; }
}
@media (max-width: 760px) {
    #result:not([hidden]) { grid-template-columns: minmax(0, 1fr); grid-template-rows: repeat(3, max-content); grid-template-areas: "record" "ranking" "foot"; align-content: start; gap: 24px; padding: 16px 12px; overflow: auto; }
    #result-context { display: contents; }
    #result-record { overflow: visible; padding: 0; }
    #result-record > #result-score, #result-record > #result-detail { grid-column: 1 / -1; }
    #result-chart { overflow: visible; }
    #result-total { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .result-points, #result-total .result-mm { grid-column: 1 / -1; }
    #result-ranking { overflow: visible; }
    #result-ranking-rows { max-height: 360px; }
    #result-ratings { right: auto; left: 0; }
    #result-foot { position: sticky; bottom: -16px; }
    #result-foot button { padding-inline: 16px; }
    #result-foot #result-submission { flex-basis: 100%; order: 0; }
}
@media (max-width: 480px) {
    #result-foot { gap: 8px; }
    #result-foot > button { flex: 1; min-width: 0; padding-inline: 8px; }
}
#edit-sync-dialog { width: min(640px, 90vw); max-height: 85vh; overflow: auto; }
#edit-sync-dialog label { display: block; margin: 8px 0; }
#sync-regions { max-height: 160px; overflow: auto; }
@media (max-width: 1000px) {
    #edit-body { grid-template-columns: 200px minmax(240px, 1fr) 32px 220px; gap: 6px; }
    #editor.compact #edit-body { grid-template-columns: minmax(240px, 1fr) 32px 220px; }
    #edit-charts { padding: 0 8px; }
    #edit-charts button { padding: 6px 8px; }
}
#cursor { position: fixed; inset: auto; margin: 0; padding: 0; overflow: visible; }
#cursor svg { display: block; width: 100%; height: 100%; overflow: visible; transform-origin: 0 0; }

/* motion/motion.js: hover and flash layers sit under a button's label. The label wrapper lays its
   children out the way the button itself would, so each button's own layout rules still apply. */
/* osu!lazer ShearedButton: 15 px either side of the label. */
button { padding: 4px 15px; }
button.feel { position: relative; overflow: hidden; z-index: 0; }
.feel-hover, .feel-flash { position: absolute; inset: 0; z-index: -1; }
.feel-label { display: inherit; flex-direction: inherit; flex-wrap: inherit; align-items: inherit; align-content: inherit; justify-content: inherit; justify-items: inherit; gap: inherit; grid-template-columns: inherit; grid-template-rows: inherit; width: 100%; }
/* The leaving title copy covers the window while it slides out. */
#title.leaving-ghost { position: absolute; inset: 0; }
/* A closing popup's dim stays under its fading copy. */
.popup-dim-ghost { position: fixed; inset: 0; z-index: 59; pointer-events: none; }

#song-list { position: relative; }
#list-position { flex: 1 1 100%; }
.list-track { grid-area: 3 / 2; position: relative; width: 4px; }
#list-range-window { position: absolute; left: 0; width: 100%; min-height: min(24px, 100%); max-height: 100%; }

#playing-status:not([hidden]) { position: fixed; inset: 0; z-index: 90; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 12px; padding: 24px; }
#playing-message { display: flex; flex-direction: column; align-items: center; gap: 12px; max-width: 100%; box-sizing: border-box; padding: 28px 36px; text-align: center; overflow-wrap: anywhere; }
#playing-status h2, #playing-status p { margin: 0; }
/* While the game window plays, only the background shows behind the status; open dialogs (HUD settings) stay. */
body:has(#playing-status:not([hidden])) #app > :not(#backdrop):not(#playing-status):not(dialog) { visibility: hidden; }

#web-play:not([hidden]) { position: fixed; inset: 0; z-index: 80; display: grid; grid-template-rows: minmax(0, 1fr); }
#web-play > iframe { width: 100%; height: 100%; min-height: 0; }
#web-youtube { position: absolute; right: 8px; bottom: 8px; width: 356px; height: 200px; z-index: 90; }
#web-youtube iframe { width: 100%; height: 100%; }
/* Desktop sing: the game window is cut away where the player shows (internal/singplay). */
#web-youtube.desktop-background { position: fixed; inset: 0; width: auto; height: auto; }
#web-youtube.desktop-bottom-right { position: fixed; }
#web-youtube.desktop-top-left { position: fixed; right: auto; bottom: auto; left: 8px; top: 8px; } #web-youtube.top-left { right: auto; bottom: auto; left: 8px; top: 8px; } #web-youtube.video-hidden { right: auto; bottom: auto; left: -400px; top: 0; }
#record-tools { margin-top: 8px; }
#record-tools textarea { width: 100%; min-width: 0; box-sizing: border-box; }
/* Toasts (notification.js): 320 px wide, 20 px from the bottom-right corner, newest at the bottom. */
/* UX edit mode (scenes/uxedit.js): boxes follow the edited elements; only the handle and note take the pointer. */
#uxedit:popover-open { position: fixed; inset: 0; width: auto; height: auto; margin: 0; padding: 0; overflow: visible; pointer-events: none; }
.uxedit-box { position: fixed; box-sizing: border-box; pointer-events: none; }
#uxedit-label { position: absolute; left: -2px; bottom: 100%; padding: 0 4px; white-space: nowrap; }
#uxedit-handle { position: absolute; right: -6px; bottom: -6px; width: 10px; height: 10px; pointer-events: auto; }
.uxedit-guide { position: fixed; pointer-events: none; }
.uxedit-guide-x { top: 0; bottom: 0; width: 1px; }
.uxedit-guide-y { left: 0; right: 0; height: 1px; }
#uxedit-count { position: fixed; top: 8px; left: 50%; translate: -50% 0; padding: 2px 10px; }
#uxedit-note { position: fixed; width: 240px; pointer-events: auto; }
#toasts:popover-open { position: fixed; inset: auto 20px 20px auto; width: 320px; margin: 0; padding: 0; overflow: visible; display: flex; flex-direction: column; pointer-events: none; }
.toast { width: 100%; padding: 3px 0; box-sizing: border-box; pointer-events: auto; }
.toast-main { position: relative; overflow: hidden; display: grid; grid-template-columns: 40px minmax(0, 1fr) 28px; min-height: 80px; }
.toast-icon { display: grid; place-items: center; }
.toast-icon svg { width: 16px; height: 16px; }
.toast-text { min-width: 0; margin: 0; padding: 10px; }
.toast-text > span { display: block; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.toast-close { display: grid; place-items: center; padding: 0; }
.toast-close svg { width: 12px; height: 16px; }
.toast-flash { position: absolute; inset: 0; pointer-events: none; }
/* Sing edits source lyric syllables on a time/pitch roll. */
#sing-editor { position:fixed; inset:0; z-index:30; padding:16px 24px; overflow:auto; }
#sing-editor[hidden] { display:none; }
#sing-editor header, #sing-editor nav, #sing-editor footer { display:flex; align-items:center; gap:10px 16px; margin-bottom:12px; flex-wrap:wrap; }
#sing-editor h2, #sing-editor p { margin:0; }
#sing-editor > p { margin-top:12px; }
#sing-editor [data-field=title] { flex:1; }
.sing-edit-body { display:grid; grid-template-columns:minmax(360px,1fr) 260px; grid-template-rows:minmax(0,1fr); gap:20px; height:calc(100vh - 250px); min-height:350px; margin-bottom:12px; }
.sing-edit-roll { display:grid; grid-template-rows:minmax(240px,2fr) auto minmax(70px,1fr); min-width:0; min-height:0; gap:8px; }
#sing-editor [data-field=grid] { width:100%; height:100%; min-height:0; touch-action:none; }
#sing-editor aside, #sing-editor [data-field=notes] { overflow:auto; min-height:0; }
#sing-editor [data-field=notes] { list-style:none; margin:0; padding:0; }
#sing-editor [data-field=notes] button { width:100%; text-align:left; white-space:pre-wrap; }
#sing-editor [data-field=phrase] { min-height:1.5em; white-space:pre-wrap; }
#sing-editor form { display:grid; gap:8px; margin-bottom:16px; }
#sing-editor label { display:flex; align-items:center; justify-content:space-between; gap:8px; }
#sing-editor input, #sing-editor select { min-width:0; }
#sing-editor aside input { width:145px; }
#sing-editor [data-field=breaks] { width:100%; }
#sing-editor [data-field=timeline] { flex:1; min-width:140px; }
#sing-editor [data-field=position] { width:120px; }
#sing-editor [data-field=message] { display:block; min-height:1.5em; overflow-wrap:anywhere; }
@media (max-width:760px) { #sing-editor { padding:12px; } .sing-edit-body { grid-template-columns:minmax(280px,1fr) 210px; gap:10px; } #sing-editor aside input { width:115px; } }
/* Drum keeps source hits, rolls and swells on a horizontal song timeline. */
#drum-editor { position:fixed; inset:0; z-index:30; padding:16px 24px; overflow:auto; display:flex; flex-direction:column; }
#drum-editor[hidden] { display:none; }
#drum-editor header, #drum-editor nav, #drum-editor footer { display:flex; align-items:center; gap:8px 14px; margin-bottom:12px; flex-wrap:wrap; }
#drum-editor h2, #drum-editor p { margin:0; }
#drum-editor [data-field=title] { flex:1; min-width:120px; }
.drum-edit-body { display:grid; grid-template-columns:minmax(340px,1fr) 260px; gap:20px; flex:1; min-height:320px; margin-bottom:12px; }
.drum-edit-track { display:grid; grid-template-rows:minmax(220px,2fr) minmax(70px,1fr); gap:8px; min-height:0; min-width:0; }
#drum-editor [data-field=grid] { width:100%; height:100%; min-height:0; touch-action:none; }
#drum-editor aside, #drum-editor [data-field=objects] { overflow:auto; min-height:0; }
#drum-editor [data-field=objects] { margin:0; padding:0; }
#drum-editor [data-field=objects] button { width:100%; text-align:left; }
#drum-editor form { display:grid; gap:8px; margin-bottom:14px; }
#drum-editor label { display:flex; align-items:center; justify-content:space-between; gap:8px; }
#drum-editor input, #drum-editor select { min-width:0; }
#drum-editor aside input:not([type=checkbox]) { width:130px; }
#drum-editor [data-field=timeline] { flex:1; min-width:140px; }
#drum-editor [data-field=position] { width:120px; }
#drum-editor [data-field=message] { display:block; min-height:1.5em; overflow-wrap:anywhere; }
@media (max-width:760px) { #drum-editor { padding:12px; } .drum-edit-body { grid-template-columns:minmax(280px,1fr) 210px; gap:10px; } #drum-editor aside input:not([type=checkbox]) { width:105px; } }
/* Catch uses a continuous X field rather than piano lanes. */
#catch-editor { position:fixed; inset:0; z-index:30; padding:18px 28px; overflow:auto; }
#catch-editor[hidden] { display:none; }
#catch-editor header, #catch-editor nav, #catch-editor footer { display:flex; align-items:center; gap:14px; margin-bottom:12px; flex-wrap:wrap; }
#catch-editor h2 { margin:0 18px; }
.catch-edit-body { display:grid; grid-template-columns:minmax(400px,1fr) 340px; gap:24px; height:calc(100vh - 230px); min-height:360px; }
.catch-edit-body > svg { width:100%; height:100%; touch-action:none; }
.catch-edit-body aside { overflow:auto; padding-right:12px; }
.catch-edit-body form { display:grid; gap:8px; margin-bottom:16px; }
#catch-editor label { display:flex; align-items:center; justify-content:space-between; gap:8px; }
#catch-editor input[type=number] { width:130px; }
#catch-editor textarea { width:180px; }
#catch-editor [data-field=curve] { width:100%; height:150px; touch-action:none; }
#catch-editor [data-field=timeline] { flex:1; min-width:150px; }
/* Editor forms (editor/controls.js): the sheared slider bar takes the timeline's place in the footer; choice rows,
   dropdowns and number boxes sit beside their labels. Number boxes are lazer text boxes without spinners. */
:is(#catch-editor, #drum-editor, #sing-editor) footer .slider { flex:1; width:auto; min-width:150px; }
:is(#editor, #catch-editor, #drum-editor, #sing-editor) .choice { flex-wrap:nowrap; padding:0 8px; }
:is(#editor, #catch-editor, #drum-editor, #sing-editor) .dropdown { min-width:9em; }
#edit-inspector .dropdown, #edit-sync-dialog .dropdown { width:100%; }
:is(#editor, #catch-editor, #drum-editor, #sing-editor) input[type="number"] { appearance:textfield; }
/* Clausie's dog (dog/dog.js): dragged anywhere, lying just above the chart background (same z, later in the page)
   and under every screen so it never hides text. #dog-top is its twin box above the screens holding the balloon over its head. */
#dog { position: fixed; z-index: -1; width: 150px; height: 150px; touch-action: none; user-select: none; }
#dog-top { position: fixed; z-index: 95; width: 150px; height: 150px; pointer-events: none; }
#dog-top > * { pointer-events: auto; }
#dog > svg { display: block; width: 100%; height: 100%; overflow: visible; }
#dog-balloon:not([hidden]) { position: absolute; right: 30px; bottom: calc(100% + 6px); width: max-content; max-width: 260px; margin: 0; padding: 6px 10px; border-radius: 10px; white-space: pre-line; overflow-wrap: anywhere; }
#dog-balloon[data-side="right"] { right: auto; left: 30px; }

.analysis-column dl > div { position: relative; padding-bottom: 8px; }
.analysis-axis { margin: 0 0 5px; }
.analysis-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; overflow: hidden; }
.analysis-bar i { display: block; height: 100%; }
#chart-analysis > section:last-child { grid-column: 3; }

#reading-total { justify-content: flex-end; }
/* A lit 9's flash sits over the 9 (theme.css .nine). */
.nine { position: relative; }
.nine[data-flash]::before { position: absolute; left: 0; top: 0; pointer-events: none; }
/* Tournament: the side panel, the bracket (one column per round) and the selected match. */
#tournament:not([hidden]) { display: grid; grid-template-columns: clamp(220px, 20vw, 280px) minmax(0, 1fr) clamp(320px, 28vw, 400px); grid-template-rows: minmax(0, 1fr) auto; grid-template-areas: "side bracket match" "commands commands commands"; gap: 8px 24px; min-height: 0; box-sizing: border-box; padding: 40px 0 12px; }
#tournament [hidden] { display: none; }
#tournament h2, #tournament h3, #tournament p { margin: 0; }
#tournament-side { grid-area: side; display: grid; align-content: start; gap: 16px; padding: 20px; min-height: 0; overflow: auto; }
#tournament-roles { display: flex; flex-wrap: wrap; gap: 8px; }
#tournament-roles button { min-height: 40px; padding: 0 14px; }
#tournament-pool, #tournament-maps, #tournament-standings { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
#tournament-bracket { grid-area: bracket; display: flex; gap: 32px; padding: 12px 16px; overflow: auto; min-height: 0; }
#tournament-empty { grid-area: bracket; place-self: center; }
.tournament-round { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 12px; min-width: 200px; flex: 1; }
.tournament-round ol { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; justify-content: space-around; gap: 12px; }
.tournament-match { display: grid; gap: 4px; width: 100%; padding: 8px 12px; text-align: left; box-sizing: border-box; }
.tournament-side { display: grid; grid-template-columns: 2.4em minmax(0, 1fr) 1.6em; align-items: center; gap: 6px; }
.tournament-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tournament-wins, .tournament-score, .tournament-versus-side b { text-align: right; font-variant-numeric: tabular-nums; }
#tournament-match { grid-area: match; display: grid; align-content: start; gap: 12px; padding: 20px; min-height: 0; overflow: auto; }
#tournament-versus { display: grid; gap: 4px; font-size: 19px; font-weight: 700; }
.tournament-versus-side { display: flex; justify-content: space-between; gap: 12px; }
.tournament-map { width: 100%; min-height: 40px; padding: 0 12px; text-align: left; box-sizing: border-box; }
.tournament-map-row { display: grid; grid-template-columns: 3.4em minmax(0, 1fr) auto; align-items: center; gap: 8px; }
.tournament-map-row > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#tournament-result { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
#tournament-result input { width: 6em; height: 36px; padding: 0 8px; box-sizing: border-box; font-variant-numeric: tabular-nums; }
#tournament-result button { min-height: 36px; padding: 0 12px; }
#tournament-standings li { display: grid; grid-template-columns: 2em minmax(0, 1fr) auto; gap: 8px; }
#tournament-commands { grid-area: commands; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; }
#tournament-status { flex: 1; }
#tournament-side, #tournament-match, #tournament-bracket { border-radius: 10px; }
#tournament-new-dialog form { display: grid; gap: 14px; min-width: 26em; }
#tournament-new-dialog label { display: grid; gap: 4px; }
#tournament-new-dialog textarea, #tournament-new-dialog input { box-sizing: border-box; width: 100%; min-width: 0; padding: 6px 8px; }
/* 이벤트 페이지(/arcade): 위 막대, 아래는 옵션 | 곡 휠 | 자켓. 곡 줄의 위치·크기는 wheel.js가 인라인으로 정한다. */
#arcade { position: fixed; inset: 0; z-index: 50; display: grid; grid-template-rows: minmax(0, 1fr); overflow: hidden; }
#arcade-screen { display: grid; grid-template-rows: auto minmax(0, 1fr); min-height: 0; }
#arcade-note { position: absolute; z-index: 3; left: 24px; bottom: 12px; margin: 0; }
.arcade-loading { position: fixed; inset: 0; z-index: 85; }
/* 곡을 고르고 Enter: 선곡 화면 위에 dim을 깔고 시작할지 한 번 더 묻는다. 목록과 미리듣기는 그 뒤에 그대로 있다. */
.arcade-confirm { position: absolute; inset: 0; z-index: 30; display: grid; place-content: center; }
.arcade-ask { display: grid; justify-items: center; gap: 12px; box-sizing: border-box; max-width: min(640px, 90vw); padding: 24px 40px; text-align: center; }
.arcade-ask p { margin: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arcade-ask .arcade-genres { gap: 8px; padding: 0 8px; }
.arcade-ask .arcade-genres button { height: 36px; min-width: 96px; padding: 0 12px; }
.arcade-bar { display: flex; justify-content: space-between; align-items: center; padding: 12px 32px; }
.arcade-bar p { margin: 0; }
.arcade-pick { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 38%); gap: 16px; padding: 0 24px 40px 24px; min-height: 0; }
.arcade-side { position: absolute; z-index: 2; left: 0; top: 0; bottom: 0; width: 178px; box-sizing: border-box; padding: 0 24px; display: flex; flex-direction: column; justify-content: center; gap: 12px; }
.arcade-test { position: absolute; top: 4px; left: 0; right: 0; margin: 0; text-align: center; pointer-events: none; z-index: 5; }
.arcade-standing { display: grid; gap: 2px; margin: 4px 0 0; }
.arcade-standing p, .arcade-between .arcade-rank { margin: 0; }
.arcade-top { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; gap: 8px; }
.arcade-top.graded { grid-template-columns: 24px minmax(0, 1fr) 78px auto repeat(4, 38px); gap: 6px; }
.arcade-top-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arcade-team { margin-right: 6px; }
/* 위 막대 오른쪽: 소속(고정)과 닉네임. 닉네임 칩과 입력칸은 높이가 같아 바꿀 때 막대가 밀리지 않는다. 칩은 기울어 옆으로 튀어나오므로 막대 오른쪽 여백(32px) 안에 둔다. */
.arcade-who { display: flex; align-items: center; min-width: 0; }
.arcade-nick, .arcade-nickbox { height: 36px; box-sizing: border-box; }
.arcade-nick { display: flex; align-items: center; gap: 8px; max-width: 320px; padding: 0 12px; }
.arcade-nick > * { display: block; transform: skewX(11.31deg); }
.arcade-nick-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arcade-nickbox { width: 260px; padding: 0 12px; }
.arcade-pass { width: 280px; height: 44px; box-sizing: border-box; text-align: center; }
.arcade-gate-note { min-height: 1.5em; }
.arcade-genres { display: flex; gap: 4px; list-style: none; margin: 0; padding: 0 16px; }
.arcade-genres li { flex: 0 0 auto; }
.arcade-genres button { display: block; height: 28px; box-sizing: border-box; padding: 0 5px; text-align: center; white-space: nowrap; }
.arcade-options { display: flex; flex-direction: column; gap: 4px; padding: 0; }
.arcade-side .arcade-genres { flex-direction: column; padding: 0; }
.arcade-side .arcade-genres button { width: 100%; }
.arcade-options .arcade-genres { padding: 0; }
.arcade-option { display: flex; justify-content: space-between; align-items: baseline; margin: 0 0 6px; }
.arcade-control { display: block; }
.arcade-options .arcade-control + .arcade-control { margin-top: 20px; }
.arcade-side .arcade-steps { flex-direction: row; align-items: center; margin-top: 6px; }
.arcade-steps li:not(:last-child) { flex: 0 0 34px; }
.arcade-steps li:last-child { flex: 1 1 0; min-width: 0; text-align: right; }
.arcade-steps li:nth-child(2):last-child { flex: 0 0 34px; }
.arcade-options .slider { pointer-events: none; }
.arcade-wheel { position: relative; overflow: hidden; min-height: 0; }
.arcade-row { position: absolute; left: 154px; top: 50%; width: 440px; height: 56px; display: grid; grid-template-columns: 64px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 0 20px 0 12px; box-sizing: border-box; text-align: left; }
.arcade-row > :not(.arcade-plate) { position: relative; }
/* 줄은 서로 붙어 있고(틈 0) 옵션 창 오른쪽 끝에도 붙는다. 판은 직사각형이라 바깥 판(테두리색)은 몸통이 아래 1px만 남겨 줄 사이 선으로 보이고, 선택 줄은 몸통이 2px 안쪽이라 둘레가 테두리가 되며 오른쪽으로 20px 더 나온다. */
.arcade-plate { position: absolute; inset: 0; box-sizing: border-box; }
.plate-body { position: absolute; inset: 0 0 1px 0; overflow: hidden; }
.arcade-row.selected { width: 460px; }
.arcade-row.selected .plate-body { inset: 2px; }
.arcade-row.added .plate-body { inset: 4px; }
.plate-body > * { position: absolute; inset: 0; }
.plate-gloss { bottom: 52%; }
.arcade-text { display: grid; gap: 2px; min-width: 0; }
.arcade-meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arcade-row[hidden] { display: none; }
.arcade-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arcade-thumb { display: block; width: 64px; aspect-ratio: 4 / 3; overflow: hidden; }
.arcade-thumb img, .arcade-jacket img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* 자켓은 겹쳐 놓고 새 것이 위에서 나타난다(교차 전환). 틀 안쪽 4px에 맞춘다. */
.arcade-jacket img { position: absolute; inset: 4px; width: calc(100% - 8px); height: calc(100% - 8px); }
.arcade-preview { display: flex; flex-direction: column; justify-content: center; gap: 8px; min-width: 0; }
/* 자켓은 4:3이고, 창이 낮으면 줄어 제목·난이도·순위표(96px)가 창 아래로 잘리지 않게 한다(430px: 그 아래 칸들과 위 막대·여백). */
.arcade-jacket { position: relative; width: max(160px, min(100%, calc((100vh - 430px) * 4 / 3))); aspect-ratio: 4 / 3; overflow: hidden; box-sizing: border-box; padding: 4px; }
.arcade-title { margin: 8px 0 0; overflow-wrap: anywhere; }
.arcade-artist, .arcade-best { margin: 0; }
/* 기록·순위가 오가도 아래 위 칸이 밀리지 않게 자리를 잡아 둔다. */
.arcade-best { min-height: 1.4em; }
.arcade-standing { min-height: 96px; align-content: start; }
/* R: 오른쪽 칸은 자켓을 곡 이름 옆 썸네일로 줄이고 칩 아래에 순위 10줄(정확도 칸까지)을 둔다. 휠은 그대로다. */
.arcade-preview.ranking { display: grid; grid-template-columns: 56px minmax(0, 1fr); align-content: start; justify-content: stretch; gap: 0 12px; }
.arcade-preview.ranking .arcade-jacket { grid-column: 1; grid-row: 1 / 3; width: 56px; padding: 2px; align-self: center; }
.arcade-preview.ranking .arcade-jacket img { inset: 2px; width: calc(100% - 4px); height: calc(100% - 4px); }
.arcade-preview.ranking .arcade-title { grid-column: 2; grid-row: 1; margin: 0; align-self: end; }
.arcade-preview.ranking .arcade-artist { grid-column: 2; grid-row: 2; }
.arcade-preview.ranking .arcade-diffs { grid-column: 1 / -1; grid-row: 3; margin: 12px 0 8px; }
.arcade-preview.ranking .arcade-standing { grid-column: 1 / -1; grid-row: 4; }
.arcade-preview.ranking :is(.arcade-facts, .arcade-best) { display: none; }
.arcade-preview.ranking .arcade-top { grid-template-columns: 24px minmax(0, 1fr) 78px auto 44px repeat(4, 38px); gap: 6px; }
.arcade-top-grade { text-align: right; }
.arcade-top-acc { text-align: right; }
.arcade-rank[data-open] { cursor: pointer; }
.arcade-key { margin-left: 8px; padding: 0 6px; border-width: 2px; border-style: solid; }.arcade-facts { display: flex; gap: 16px; margin: 0; }
.arcade-attract, .arcade-between, .arcade-final { display: grid; place-content: center; justify-items: center; gap: 16px; text-align: center; min-height: 0; padding: 24px; }
.arcade-results { display: grid; gap: 8px; list-style: none; margin: 0; padding: 0 8px; min-width: min(640px, 90vw); }
.arcade-results li { display: grid; grid-template-columns: 96px minmax(0, 1fr) auto; gap: 16px; align-items: baseline; text-align: left; }
.arcade-results .arcade-song { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arcade-between .arcade-song, .arcade-between .arcade-played { max-width: min(640px, 90vw); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arcade-counts { display: flex; gap: 24px; margin: 0; }
.arcade-count { display: grid; gap: 2px; justify-items: center; min-width: 64px; }
.arcade-count dt, .arcade-count dd { margin: 0; }
.arcade-between .arcade-standing { width: min(360px, 90vw); text-align: left; justify-items: stretch; }
.arcade-between .arcade-rank { text-align: center; }
.arcade-attract h1, .arcade-attract p, .arcade-between p, .arcade-final p { margin: 0; }
.arcade-load { display: flex; gap: 4px; }
.arcade-load span { display: block; width: 14px; height: 22px; }
.arcade-options .slider { width: 100%; margin-inline: 0; box-sizing: border-box; }
#arcade-screen > :is(.arcade-attract, .arcade-between, .arcade-final) { grid-row: 1 / -1; }
/* 화면이 바뀔 때 나가는 쪽은 같은 자리에 겹쳐 두고 사라진다. */
.arcade-ghost { position: absolute; inset: 0; z-index: 1; display: grid; grid-template-rows: auto minmax(0, 1fr); pointer-events: none; }
.arcade-ghost > :is(.arcade-attract, .arcade-between, .arcade-final) { grid-row: 1 / -1; }
/* 스테이지 진입: 가운데 선에서 위아래 막이 갈라진다(motion.js curtain). 화면 위에 얹힌 덮개라 포인터를 받지 않는다. */
.arcade-curtain { position: absolute; inset: 0; z-index: 20; overflow: hidden; pointer-events: none; }
.arcade-curtain-top, .arcade-curtain-bottom { position: absolute; left: 0; right: 0; height: 50%; }
.arcade-curtain-top { top: 0; }
.arcade-curtain-bottom { bottom: 0; }
.arcade-curtain-line { position: absolute; left: 7%; top: 50%; width: 0; height: 2px; margin-top: -1px; z-index: 1; }
.arcade-curtain-title { position: absolute; left: 0; right: 0; bottom: 20px; margin: 0; text-align: center; }
.arcade-diffs { display: flex; gap: 8px; list-style: none; margin: 0; padding: 0 8px; }
.arcade-diffs li { min-width: 72px; padding: 4px 12px; text-align: center; box-sizing: border-box; white-space: nowrap; }
