/* App shell and screens. Colours from Tokens.css only. */

* { box-sizing: border-box; }

html, body {
    height: 100%;
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 16px/1.4 var(--font);
    -webkit-font-smoothing: antialiased;
}

/* ── Shell ──────────────────────────────────────────────────────────────── */

#AppHeader {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 12px;
    height: 56px;
    padding: 0 16px;
    border-bottom: 1px solid var(--border);
    background: var(--surface);
}

#AppTitle {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--text);
    font-size: 19px;
    font-weight: 700;
    text-decoration: none;
    letter-spacing: -0.01em;
}

#AppTitle .Logo {
    display: inline-grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: 8px;
    background: var(--accent);
    color: var(--accent-text);
    font-size: 15px;
}

#AppHeader .Spacer { flex: 1; }

#AppContent {
    max-width: 1120px;
    margin: 0 auto;
    padding: 24px 16px 48px;
}

.AppView { display: none; }
.AppView.Active { display: block; }

/* The play screen takes the whole viewport - no header, no gutters. */
body.Playing #AppHeader { display: none; }
body.Playing #AppContent { max-width: none; padding: 0; }

h1 { margin: 0 0 6px; font-size: 26px; letter-spacing: -0.02em; }
h2 { margin: 0 0 12px; font-size: 19px; }

#HeaderUser {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.HeaderLink {
    color: var(--text);
    font-weight: 600;
    text-decoration: none;
}

.HeaderName {
    overflow: hidden;
    color: var(--text-muted);
    font-size: 14px;
    white-space: nowrap;
    text-overflow: ellipsis;
}

@media (max-width: 520px) {
    .HeaderName { display: none; }
}

/* ── Pages ──────────────────────────────────────────────────────────────── */

.PageHeader {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px 16px;
    margin-bottom: 20px;
}

.PageHeader p { margin: 4px 0 0; }

.PageActions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.BackLink,
.TextLink {
    color: var(--accent);
    font-weight: 600;
    text-decoration: none;
}

.BackLink {
    display: inline-flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 14px;
    font-size: 15px;
}

.TextLink:hover,
.BackLink:hover { text-decoration: underline; }

.Hint {
    color: var(--text-faint);
    font-size: 13px;
}

.Banner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 12px;
    margin-bottom: 20px;
    padding: 12px 16px;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    background: var(--surface);
}

.Banner span { flex: 1 1 220px; }

.EmptyState {
    padding: 32px 24px;
    text-align: center;
}

.EmptyState p { margin: 0 0 18px; }

.DangerZone {
    margin-top: 28px;
    padding-top: 20px;
    border-top: 1px solid var(--border);
}

/* Landing page */
.Hero {
    max-width: 640px;
    padding: 6vh 0 2vh;
}

.Hero h1 {
    font-size: clamp(32px, 6vw, 48px);
    line-height: 1.1;
}

.Lead {
    margin: 16px 0 28px;
    color: var(--text-muted);
    font-size: 19px;
}

.HeroActions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 20px;
}

/* Sign-in and account-link cards */
.AuthCard {
    max-width: 440px;
    margin: 4vh auto 0;
    padding: 28px 24px;
}

.AuthCard h1 { margin-bottom: 16px; }

.AuthLinks {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 18px;
    color: var(--text-muted);
    font-size: 15px;
}

/* My Songs */
.SongsToolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 4px;
}

.SongsSearch {
    position: relative;
    flex: 1 1 260px;
    min-width: 0;
}

.SongsSearch .fa {
    position: absolute;
    top: 50%;
    left: 14px;
    color: var(--text-faint);
    transform: translateY(-50%);
    pointer-events: none;
}

.SongsSearch .Input { padding-left: 38px; }

.SongsToolbarRow {
    display: flex;
    flex: 1 1 auto;
    gap: 10px;
    min-width: 0;
}

.SongsToolbarRow .Segmented .Button.Chip { min-width: 0; }

.SongsToolbarRow .Input {
    flex: 0 1 200px;
    width: auto;
    min-width: 0;
}

.SongsCount {
    min-height: 1em;
    margin: 0 0 6px;
    font-size: 14px;
}

@media (max-width: 480px) {
    .SongsToolbarRow { flex-wrap: wrap; }
    .SongsToolbarRow .Segmented { flex: 1 1 100%; }
    .SongsToolbarRow .Input { flex-basis: 100%; }
    .SongsToolbarRow .Segmented .Button.Chip { flex: 1 1 0; }
}

.SongList {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.SongRow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 16px;
    padding: 14px 18px;
    color: var(--text);
    text-decoration: none;
}

.SongRow:hover { border-color: var(--text-faint); }

.SongRowMain { flex: 1 1 220px; min-width: 0; }

.SongRowTitle {
    overflow: hidden;
    font-size: 18px;
    font-weight: 700;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.SongRowArtist,
.SongRowMeta { font-size: 14px; }

.SongRowChevron { color: var(--text-faint); }

.SongRow.Compact {
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}

.SongRow.Compact:last-child { border-bottom: 0; }

.SongRowTags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}

.Tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
}

/* Template songs */
.TemplatePicker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 12px;
    margin-bottom: 16px;
}

.TemplateButtons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.TemplateButtons.Centered { justify-content: center; }
.TemplateIntro { margin: 22px 0 10px !important; }

/* Forms on one line: band name + button, email invite + Send */
.InlineForm {
    display: flex;
    gap: 10px;
    margin-bottom: 16px;
}

.InlineForm .Input { flex: 1 1 auto; min-width: 0; }
.InlineForm.JoinCode { margin-top: 16px; }

/* Band page */
.BandGrid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
}

.BandGrid > div {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

@media (min-width: 860px) {
    .BandGrid { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
}

.BandSection h2 { margin-bottom: 10px; }
.BandSection > p { margin: 0 0 12px; }

.MemberList {
    display: flex;
    flex-direction: column;
}

.MemberRow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}

.MemberRow:last-child { border-bottom: 0; }
.MemberName { font-weight: 600; }

.MemberActions {
    display: flex;
    gap: 6px;
    margin-left: auto;
}

.CopyRow {
    display: flex;
    gap: 8px;
    margin-bottom: 8px;
}

.CopyRow .Input { flex: 1 1 auto; min-width: 0; font-size: 14px; }

.InviteCode {
    color: var(--text);
    font-family: ui-monospace, "SF Mono", Consolas, monospace;
    letter-spacing: 0.12em;
}

.BandSection .InlineForm { margin: 14px 0 12px; }

.DangerZone {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* Song sharing */
.SharePanel { margin-top: 16px; }

.ShareRow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 20px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border);
}

.ShareBand { font-weight: 600; }

.Check {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
    cursor: pointer;
}

.Check input {
    width: 20px;
    height: 20px;
    accent-color: var(--accent);
}

/* ── Song editor ───────────────────────────────────────────────────────── */

.EditorGrid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
}

.EditorSummary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 4px 12px;
}

.TextArea.Short { min-height: 150px; }

/* A pick-one pair of chips, such as Cover / Original. */
.Segmented {
    display: flex;
    gap: 6px;
}

.Segmented .Button.Chip { min-width: 96px; }

.SongNotes { margin: 18px 0 0; }

.SectionBlocks {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 12px 0 14px;
}

.SectionBlock {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    border: 1px solid var(--border);
    border-left: 6px solid var(--section, var(--border));
    border-radius: var(--radius);
    background: var(--surface-2);
}

.SectionRow {
    display: flex;
    align-items: center;
    gap: 8px;
}

.SectionRow > select { flex: 1 1 auto; min-width: 0; }
.SectionRow.Texts input { flex: 1 1 0; min-width: 0; }
.SectionRow.Chords { flex-wrap: wrap; }
.SectionRow.Chords input { flex: 1 1 100%; min-width: 0; font-weight: 700; }
.ChordFit { font-size: 13px; }
.ChordFit:empty { display: none; }

.SectionTools {
    display: flex;
    gap: 4px;
    margin-left: auto;
}

@media (max-width: 420px) {
    .SectionRow { gap: 4px; }
    .SectionRow.Texts { flex-direction: column; align-items: stretch; gap: 6px; }
    /* Four presets and five tools still fit on one row of a 375-wide phone. */
    .SectionTools,
    .BarPresets { gap: 2px; }
    .SectionRow .Button.Icon.Small,
    .SectionRow .Button.Chip { width: 28px; min-width: 28px; min-height: 34px; padding: 0; font-size: 13px; }
}

.BarStepper {
    display: flex;
    align-items: center;
    gap: 4px;
}

.BarStepper .Bars {
    width: 64px;
    text-align: center;
}

.BarPresets {
    display: flex;
    gap: 4px;
}

/* Choosing the type of a section being added: one chip per type, edged in its colour. */
.SectionPicker {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 10px 0;
    padding: 10px;
    border: 1px dashed var(--border);
    border-radius: var(--radius);
    background: var(--surface);
}

.SectionBlocks .SectionPicker { margin: 0; }
.SectionPicker > .Muted { flex-basis: 100%; font-size: 13px; }
.SectionPicker .Chip { border-left: 4px solid var(--section, var(--border)); }
.SectionPicker [data-action="cancel"] { margin-left: auto; }

.SectionBlock.JustAdded { animation: JustAdded 1.2s ease-out; }

@keyframes JustAdded {
    from { box-shadow: 0 0 0 3px var(--accent); }
    to { box-shadow: 0 0 0 3px transparent; }
}


/* Read-only blocks */
.SectionName { font-weight: 700; }
.SectionBars,
.SectionNotes { color: var(--text-muted); font-size: 14px; }
.SectionNotes { font-style: italic; }
.SectionChords { font-weight: 700; }

.FieldRow {
    display: flex;
    flex-wrap: wrap;
    gap: 0 12px;
}

.FieldRow .Field { flex: 1 1 120px; min-width: 0; }
.FieldRow .Field.Wide { flex-basis: 200px; }

/* The tempo box and its Tap button share one field and never wrap apart. */
.FieldRow .FieldRow { flex-wrap: nowrap; }
.FieldRow .FieldRow .Input { min-width: 0; }

/* Blocks start at a fixed width per bar (set in View.SongEditor) and wrap onto more rows rather
   than squashing a long song into one. Grow is also proportional to bars, so blocks on a row
   stay in proportion as they stretch to fill it. */
.MiniTimeline {
    --bar-width: 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 3px 2px;
    margin: 4px 0 8px;
}

/* Soaks up the last row's spare space so its blocks keep their natural width instead of
   stretching (one short Outro would otherwise fill the whole row). */
.MiniTimeline::after {
    content: "";
    flex: 1000 1 0;
}

.MiniTimeline .Block {
    display: block;
    min-width: 3px;
    height: 28px;
    padding: 0 6px;
    overflow: hidden;
    border-radius: 6px;
    color: rgba(0, 0, 0, 0.75);
    font-size: 12px;
    font-weight: 700;
    line-height: 28px;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.SongTotals {
    color: var(--text-muted);
    font-size: 14px;
}

/* ── Section colours ────────────────────────────────────────────────────── */

[data-section-type="Intro"] { --section: var(--section-intro); }
[data-section-type="Verse"] { --section: var(--section-verse); }
[data-section-type="Pre-Chorus"] { --section: var(--section-pre-chorus); }
[data-section-type="Chorus"] { --section: var(--section-chorus); }
[data-section-type="Post-Chorus"] { --section: var(--section-post-chorus); }
[data-section-type="Bridge"] { --section: var(--section-bridge); }
[data-section-type="Solo"] { --section: var(--section-solo); }
[data-section-type="Instrumental"] { --section: var(--section-instrumental); }
[data-section-type="Breakdown"] { --section: var(--section-breakdown); }
[data-section-type="Outro"] { --section: var(--section-outro); }
[data-section-type="Custom"] { --section: var(--section-custom); }

.MiniTimeline .Block,
.SongMap .Block { background: var(--section, var(--section-custom)); }

/* ── Play screen ────────────────────────────────────────────────────────── */

.PlayScreen {
    display: flex;
    flex-direction: column;
    gap: 2.2vh;
    height: 100vh;
    height: 100dvh;
    padding: 2.4vh 3vw;
    overflow: hidden;
}

.PlayTop {
    display: flex;
    align-items: center;
    gap: 16px;
    min-height: 44px;
}

/* Short of room (a phone with the video above), only the current card gives way: squeezed, these
   would run under the next row. */
.PlayTop,
.BeatRow { flex-shrink: 0; }

.PlaySongTitle {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    font-size: clamp(16px, 2.6vh, 26px);
    font-weight: 700;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.PlaySongTitle .Meta {
    margin-left: 10px;
    color: var(--text-muted);
    font-weight: 500;
}

/* Where the band is in the bar, under the top row in every layout: a block per beat in the
   section's colour (beat 1 in the text colour, so the downbeat stands out), and the bar number. */
.BeatRow {
    display: flex;
    align-items: center;
    gap: 2vw;
}

.BeatBar {
    flex: 1;
    display: flex;
    gap: clamp(4px, 0.8vw, 10px);
    height: clamp(22px, 4.5vh, 48px);
}

.BeatBar span {
    position: relative;
    flex: 1;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--surface-3);
}

.BeatBar i {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0;
    background: var(--section, var(--accent));
}

.BeatBar span.Downbeat i { background: var(--text); }

/* The bar's chord, at the start of the beat row, when the chords are written in bars. */
.BarChord {
    font-size: clamp(28px, 6vh, 64px);
    font-weight: 800;
    line-height: 1;
    white-space: nowrap;
}

.BarChord:empty { display: none; }

.BarCount {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    min-width: 4.2em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.BarCount .Caption {
    color: var(--text-muted);
    font-size: clamp(11px, 1.6vh, 16px);
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.BarCount .Number { font-size: clamp(28px, 6vh, 64px); font-weight: 800; }
.BarCount .Number small { color: var(--text-muted); font-size: 0.5em; font-weight: 700; }
.BarCount.Ending .Caption,
.BarCount.Ending .Number { color: var(--section, var(--accent)); }
/* Kept in the row while empty, so the beats don't change width as the count comes and goes. */
.BarCount.Empty { visibility: hidden; }

/* Beat 1: the card's border lights up for a moment, where an eye on the chart will catch it. */
.PlayScreen.DownbeatFlash .CurrentCard { border-color: var(--text); }

.BeatDots {
    display: flex;
    gap: 8px;
}

.BeatDots span {
    width: clamp(12px, 1.8vh, 20px);
    height: clamp(12px, 1.8vh, 20px);
    border-radius: 50%;
    background: var(--surface-3);
    transition: background 60ms linear, transform 60ms linear;
}

.BeatDots span.On { background: var(--text); transform: scale(1.15); }
.BeatDots span.On.Downbeat { background: var(--accent); }

/* Current section: the big card. */
.CurrentCard {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* Too much to fit (a phone, with chords and a long cue): the name stays, the bottom clips. */
    justify-content: safe center;
    padding: 3vh 3vw;
    overflow: hidden;
    border: 3px solid var(--section, var(--border));
    border-radius: var(--radius-lg);
    background: var(--surface);
}

.CurrentCard .Fill {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0;
    background: var(--section, var(--surface-3));
    opacity: 0.22;
    pointer-events: none;
}

.CurrentCard .Label {
    position: relative;
    font-size: clamp(40px, 13vh, 150px);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -0.03em;
    text-transform: uppercase;
}

/* A section's own label under its type ("CHORUS" / Woo-hoo), on the cards and the highway. */
.SectionLabel {
    display: block;
    margin-top: 0.15em;
    overflow: hidden;
    font-size: 0.45em;
    font-weight: 700;
    letter-spacing: 0;
    text-transform: none;
    text-overflow: ellipsis;
    white-space: nowrap;
    opacity: 0.85;
}

.UpcomingCard .Name .SectionLabel { margin-top: 2px; font-size: 0.75em; }
.HighwayLabel .SectionLabel { font-size: 0.5em; }

/* The section's chords under its name. Written in bars, each bar is a cell between hairlines
   and the one sounding is lit; a plain list is all lit. */
.CurrentCard .ChordRow {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: 0.15em 0;
    margin-top: 1.6vh;
    font-size: clamp(22px, 5.5vh, 60px);
    font-weight: 800;
    line-height: 1.15;
}

.CurrentCard .ChordRow:empty { display: none; }
.ChordRow span { padding: 0 0.45em; border-radius: var(--radius); white-space: nowrap; }
.ChordRow span:first-child { padding-left: 0; }
.ChordRow.List span { padding: 0 0.6em 0 0; }
.ChordRow.PerBar span { color: var(--text-muted); }
.ChordRow.PerBar span + span { border-left: 2px solid var(--surface-3); }
.ChordRow.PerBar span.On { color: var(--text); }

.CurrentCard .ProgressBar {
    position: relative;
    height: clamp(10px, 2vh, 22px);
    margin-top: 3vh;
    overflow: hidden;
    border-radius: 999px;
    background: var(--surface-3);
}

.CurrentCard .ProgressBar div {
    width: 0;
    height: 100%;
    background: var(--section, var(--accent));
}

.CurrentCard .BarTicks {
    position: absolute;
    inset: 0;
    display: flex;
}

.CurrentCard .BarTicks span {
    flex: 1;
    border-right: 2px solid var(--surface);
}

.CurrentCard .BarTicks span:last-child { border-right: 0; }

.CurrentCard .Notes {
    position: relative;
    margin-top: 2.4vh;
    color: var(--text-muted);
    font-size: clamp(16px, 3.4vh, 36px);
    font-style: italic;
}

.CurrentCard.Idle .Label { color: var(--text-muted); }

/* Next / Then. */
.UpcomingRow {
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    gap: 2vw;
}

.UpcomingCard {
    display: flex;
    align-items: center;
    gap: 16px;
    min-width: 0;
    padding: 2vh 2vw;
    border: 2px solid var(--border);
    border-left: 10px solid var(--section, var(--border));
    border-radius: var(--radius-lg);
    background: var(--surface);
}

.UpcomingCard.Then { opacity: 0.55; }
.UpcomingCard.Empty { visibility: hidden; }

.UpcomingCard .Caption {
    color: var(--text-muted);
    font-size: clamp(12px, 1.8vh, 18px);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.UpcomingCard .UpcomingText {
    flex: 1;
    min-width: 0;
}

.UpcomingCard .FirstLine {
    overflow: hidden;
    color: var(--text-muted);
    font-size: clamp(13px, 2vh, 22px);
    font-style: italic;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.UpcomingCard .FirstLine:empty { display: none; }

.UpcomingCard .UpcomingChords {
    overflow: hidden;
    color: var(--text-muted);
    font-size: clamp(14px, 2.4vh, 26px);
    font-weight: 700;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.UpcomingCard .UpcomingChords:empty { display: none; }

.UpcomingCard .Name {
    overflow: hidden;
    font-size: clamp(20px, 4.6vh, 52px);
    font-weight: 800;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
}

.UpcomingCard .Bars {
    color: var(--text-muted);
    font-size: clamp(14px, 2.4vh, 26px);
    font-weight: 600;
    white-space: nowrap;
}

.UpcomingCard .Countdown {
    display: none;
    min-width: 1.2em;
    color: var(--section, var(--accent));
    font-size: clamp(28px, 6vh, 64px);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

/* Change warning: last bar of a section. */
.UpcomingCard.Warning {
    border-color: var(--section, var(--accent));
    animation: WarningPulse 0.5s ease-in-out infinite alternate;
}

.UpcomingCard.Warning .Countdown { display: block; }

@keyframes WarningPulse {
    from { box-shadow: 0 0 0 0 transparent; }
    to { box-shadow: 0 0 0 6px var(--section, var(--accent)); }
}

/* Whole-song strip with a playhead. */
.SongMap {
    position: relative;
    display: flex;
    gap: 3px;
    height: clamp(26px, 4.4vh, 46px);
}

.SongMap .Block {
    display: flex;
    align-items: center;
    min-width: 4px;
    padding: 0 6px;
    overflow: hidden;
    border-radius: 6px;
    color: rgba(0, 0, 0, 0.75);
    font-size: clamp(10px, 1.5vh, 15px);
    font-weight: 700;
    white-space: nowrap;
    opacity: 0.45;
}

.SongMap.Clickable .Block { cursor: pointer; }

.SongMap .Block.Done { opacity: 0.25; }
.SongMap .Block.Current { opacity: 1; }

.SongMap .Playhead {
    position: absolute;
    top: -4px;
    bottom: -4px;
    left: 0;
    width: 3px;
    border-radius: 2px;
    background: var(--text);
    pointer-events: none;
}

.PlayControls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 10px;
}

.PlayControls .Button.Toggled {
    border-color: var(--accent);
    color: var(--accent);
}

/* The backing track video, sized per device (View.PlayScreen, "Video:"). An <audio> takes no
   room. YouTube's rules for an embedded player shape all three sizes: nothing may be drawn over
   it (so it's beside the chart, never behind it, and sits above the count-in overlay), and it
   must be at least 200 x 200. */
.PlayMain {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: inherit;
    min-width: 0;
    min-height: 0;
}

.BackingMedia { display: none; }

.PlayScreen.VideoSide .BackingMedia,
.PlayScreen.VideoBig .BackingMedia,
.PlayScreen.VideoSmall .BackingMedia {
    position: relative;
    z-index: 21;
    display: flex;
    align-items: center;
    justify-content: center;
}

.PlayScreen .BackingMedia .YouTubeFrame {
    width: 100%;
    max-width: none;
    min-height: 200px;
    border-radius: var(--radius-lg);
}

/* In the card: placed over the right of the current card by View.PlayScreen (placeCardVideo),
   which keeps that part of the card clear - the name, bar and cue stay to its left. */
.PlayScreen.VideoCard .BackingMedia {
    position: absolute;
    z-index: 21;
    display: flex;
}

.PlayScreen.VideoCard .BackingMedia .YouTubeFrame {
    height: 100%;
    min-height: 0;
    aspect-ratio: auto;
    border-radius: var(--radius);
}

.PlayScreen.VideoCard .CurrentCard { padding-right: var(--card-video-space, 3vw); container-type: inline-size; }
/* Highway and Rising: the highway narrows, and the video sits at the end of its row. */
.PlayScreen.VideoCard.LayoutHighway .Highway { margin-right: var(--highway-video-space, 0px); }
/* The name has the card's left side only, so it's sized by what's left - BREAKDOWN fits too. */
.PlayScreen.VideoCard .CurrentCard .Label { font-size: clamp(28px, min(13vh, 15cqw), 150px); overflow-wrap: break-word; }

/* Side by side: the chart keeps most of the room. Big: the video does, the chart beside it. */
.PlayScreen.VideoSide,
.PlayScreen.VideoBig { flex-direction: row; }
.PlayScreen.VideoSide .BackingMedia { flex: 0 0 38%; min-width: 356px; }
.PlayScreen.VideoBig .BackingMedia { flex: 0 0 62%; min-width: 356px; }

/* Beside a video the chart's column is narrower than the screen, so its big text is sized by
   the column (container units) as well as the screen's height - names fit instead of being cut
   off. Big leaves room for the Next card only. */
.PlayScreen.VideoSide .PlayMain,
.PlayScreen.VideoBig .PlayMain { container-type: inline-size; }
.PlayScreen.VideoSide .CurrentCard .Label,
.PlayScreen.VideoBig .CurrentCard .Label { font-size: clamp(28px, min(13vh, 13cqw), 150px); }
.PlayScreen.VideoSide .UpcomingCard .Name,
.PlayScreen.VideoBig .UpcomingCard .Name { font-size: clamp(16px, min(4.6vh, 3.4cqw), 52px); }
.PlayScreen.VideoSide .UpcomingRow { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.PlayScreen.VideoBig .UpcomingRow { grid-template-columns: minmax(0, 1fr); }
/* Side by side: the video's top lines up with the current card's, under the top bar. */
.PlayScreen.VideoSide .BackingMedia { align-items: flex-start; padding-top: calc(44px + 2.2vh); }
.PlayScreen.VideoBig .UpcomingCard.Then { display: none; }
.PlayScreen.VideoBig .UpcomingCard .Name { font-size: clamp(16px, min(4.6vh, 6cqw), 52px); }

/* Small: a window in the corner, with the rows beside it (the Next/Then cards, the song map,
   the highway) leaving it room rather than running under it. */
.PlayScreen.VideoSmall .UpcomingRow,
.PlayScreen.VideoSmall .SongMap,
.PlayScreen.VideoSmall.LayoutHighway .Highway { margin-right: calc(356px + 2vw); }
.PlayScreen.VideoSmall .UpcomingRow { container-type: inline-size; }
.PlayScreen.VideoSmall .UpcomingCard .Name { font-size: clamp(16px, min(4.6vh, 3cqw), 52px); }
.PlayScreen.VideoSmall .BackingMedia {
    position: fixed;
    right: 3vw;
    bottom: calc(2.4vh + 76px);
    width: 356px;
    box-shadow: var(--shadow);
}

/* Upright phones and tablets: no room beside the chart, so the video goes across the top -
   and Big drops the Next/Then cards to make room for it. */
@media (max-aspect-ratio: 1/1) {
    .PlayScreen.VideoSide,
    .PlayScreen.VideoBig,
    .PlayScreen.VideoSmall { flex-direction: column; }
    .PlayScreen.VideoSide .BackingMedia,
    .PlayScreen.VideoBig .BackingMedia,
    .PlayScreen.VideoSmall .BackingMedia {
        position: relative;
        right: auto;
        bottom: auto;
        order: -1;
        flex: 0 0 auto;
        width: 100%;
        min-width: 0;
        padding-top: 0;
        box-shadow: none;
    }
    .PlayScreen.VideoSmall .UpcomingRow,
    .PlayScreen.VideoSmall .SongMap,
    .PlayScreen.VideoSmall.LayoutHighway .Highway { margin-right: 0; }
    .PlayScreen.VideoBig .BackingMedia .YouTubeFrame { min-height: 34vh; }
    .PlayScreen.VideoBig .UpcomingRow { display: none; }
    /* With the video on top, the current section needs the room: smaller type, Next card only. */
    .PlayScreen.VideoSide .CurrentCard .Label,
    .PlayScreen.VideoBig .CurrentCard .Label,
    .PlayScreen.VideoSmall .CurrentCard .Label { font-size: clamp(28px, 6.5vh, 72px); }
    .PlayScreen.VideoSide .CurrentCard .Notes,
    .PlayScreen.VideoBig .CurrentCard .Notes,
    .PlayScreen.VideoSmall .CurrentCard .Notes { font-size: clamp(14px, 2.2vh, 22px); }
    .PlayScreen.VideoSide .UpcomingCard.Then,
    .PlayScreen.VideoSmall .UpcomingCard.Then { display: none; }
}

/* Count-in: giant number over everything. */
.CountInOverlay {
    position: fixed;
    inset: 0;
    z-index: 20;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: rgba(14, 17, 22, 0.86);
    pointer-events: none;
}

.CountInOverlay.Visible { display: flex; }

.CountInOverlay .Number {
    font-size: min(55vh, 60vw);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.CountInOverlay .Number.Downbeat { color: var(--accent); }

.CountInOverlay .Then {
    color: var(--text-muted);
    font-size: clamp(18px, 4vh, 40px);
    font-weight: 700;
    text-transform: uppercase;
}

.EndCard .Label { color: var(--text-muted); }

.TopExtras:empty { display: none; }

/* Phones in portrait: stack Next above Then, smaller gaps. */
@media (max-aspect-ratio: 1/1) {
    .PlayScreen { gap: 1.6vh; padding: 2vh 16px; }
    .PlayTop { flex-wrap: wrap; gap: 8px 12px; }
    /* The beat row only as tall as the beats, leaving the card what room there is. */
    .BarCount .Number { font-size: clamp(26px, 4.5vh, 44px); }
    .BarChord { font-size: clamp(26px, 4.5vh, 44px); }
    .CurrentCard .ChordRow { font-size: clamp(20px, min(5vh, 7.5vw), 44px); }
    /* The title gets a row of its own under the controls rather than being squeezed out. */
    /* Wraps rather than cutting off, so the tempo and loop badges stay visible to everyone. */
    .PlaySongTitle { order: 10; flex-basis: 100%; white-space: normal; }
    .PlaySongTitle .Meta { font-size: 0.8em; }
    .UpcomingRow { grid-template-columns: 1fr; gap: 1.2vh; }
    /* Sized so a long single word (PRE-CHORUS) fits a phone's width; breaks mid-word only as a last resort. */
    .CurrentCard .Label { font-size: clamp(32px, 10.5vw, 110px); overflow-wrap: break-word; }
    /* Extra .PlayScreen so this beats the lyrics rule further down the file. */
    .PlayScreen .CurrentCard.HasLyrics .Label { font-size: clamp(26px, min(6vh, 10.5vw), 64px); }
    /* Caption gets its own line so the name has the card's full width, and wraps to two lines before it truncates. */
    .UpcomingCard { flex-wrap: wrap; gap: 2px 12px; padding: 1.2vh 14px; border-left-width: 8px; }
    .UpcomingCard > div:first-child { flex-basis: 100%; }
    .UpcomingCard .Caption { font-size: 11px; }
    .UpcomingCard .Name {
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        font-size: clamp(18px, 6.5vw, 32px);
        line-height: 1.1;
        overflow-wrap: break-word;
        white-space: normal;
    }
    .SongMap .Block { padding: 0; font-size: 0; }
}

@media (min-width: 860px) {
    .EditorGrid { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); }
}

/* ── Lyrics on the play screen ──────────────────────────────────────────── */

.CurrentCard.HasLyrics { justify-content: flex-start; }
.CurrentCard.HasLyrics .Label { font-size: clamp(26px, 6vh, 64px); }
.CurrentCard.HasLyrics .ProgressBar { margin-top: 1.6vh; }
.CurrentCard.HasLyrics .Notes { margin-top: 1.2vh; font-size: clamp(14px, 2.4vh, 26px); }

.LyricsPane {
    position: relative;
    display: none;
    flex: 1 1 auto;
    min-height: 0;
    margin-top: 2vh;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 8%, #000 85%, transparent);
    mask-image: linear-gradient(to bottom, transparent, #000 8%, #000 85%, transparent);
}

.CurrentCard.HasLyrics .LyricsPane { display: block; }

.LyricsLines {
    transition: transform 300ms ease;
}

.LyricLine {
    padding: 0.25em 0;
    color: var(--text-muted);
    font-size: clamp(20px, 4.4vh, 52px);
    font-weight: 600;
    line-height: 1.25;
    transition: color 150ms linear;
}

.LyricLine.Past { color: var(--text-faint); }

.LyricLine.Active {
    color: var(--text);
    font-weight: 800;
}

.ControlStatus:empty { display: none; }

/* Lyrics box in the song editor */
details.Lyrics summary,
details.SectionTime summary {
    color: var(--text-muted);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    user-select: none;
}

details.Lyrics[open] summary,
details.SectionTime[open] summary { margin-bottom: 8px; }
details.SectionTime .SectionRow > input { flex: 0 1 140px; min-width: 0; }
details.SectionTime .SectionRow > select { flex: 0 1 160px; }
.TextArea.Lyrics { min-height: 110px; font-family: var(--font); }
.LyricsText { color: var(--text-muted); font-size: 14px; white-space: pre-wrap; }

/* ── Jams ───────────────────────────────────────────────────────────────── */

.ConnectionDot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--text-faint);
    vertical-align: middle;
}

.ConnectionDot.Ok { background: var(--success); }
.ConnectionDot.Warn { background: var(--accent); animation: WarningPulse 0.6s ease-in-out infinite alternate; }

.Tag.Warn { border-color: var(--accent); color: var(--accent); }
.Tag.Original { border-color: var(--accent); color: var(--accent); }

.JamBanner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 12px;
    margin-bottom: 16px;
    padding: 12px 16px;
    border: 1px solid var(--success);
    border-radius: var(--radius);
    background: var(--surface);
}

.JamBanner span:nth-child(2) { flex: 1 1 200px; font-weight: 600; }

.HomeJam { max-width: 460px; margin-top: 8px; }

.JamLobby { max-width: 640px; }

.JamCodeBlock { margin-bottom: 14px; }

.JamCode {
    font-family: ui-monospace, "SF Mono", Consolas, monospace;
    font-size: 40px;
    font-weight: 800;
    letter-spacing: 0.14em;
}

.JamCodeBlock .Hint { word-break: break-all; }

.JamLeader {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 12px;
    font-weight: 600;
}

.JamLeader .fa-star { color: var(--accent); }

.JamPanelContent h3 {
    margin: 20px 0 8px;
    font-size: 16px;
}

.JamSongs {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 40vh;
    overflow-y: auto;
}

.JamGroupTitle {
    margin-top: 6px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.JamSong {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2);
    color: var(--text);
    font: 15px var(--font);
    text-align: left;
    cursor: pointer;
}

.JamSong:hover { border-color: var(--text-faint); }
.JamSong.Current { border-color: var(--accent); }
.JamSongTitle { font-weight: 700; }
.JamSong .Muted { font-size: 13px; }

.JamButtons {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 20px;
}

.JamButton { gap: 6px; }

/* The jam panel slides over the play screen from the right. */
.JamPanel {
    position: fixed;
    inset: 0;
    z-index: 30;
    display: none;
}

.JamPanel.Open { display: block; }

.JamPanelScrim {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
}

.JamPanelSheet {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    width: min(420px, 100%);
    border-left: 1px solid var(--border);
    background: var(--surface);
    box-shadow: var(--shadow);
}

.JamPanelHeader {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border);
}

.JamPanelHeader h2 { margin: 0; }

.JamPanelBody {
    flex: 1;
    padding: 16px;
    overflow-y: auto;
}

/* ── TV ─────────────────────────────────────────────────────────────────── */

body.Tv .PlayControls .PlayLyrics,
body.Tv .PlayControls .PlayClick { display: none; }

.TvWaiting {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2vh;
    height: 100vh;
    height: 100dvh;
    padding: 4vh 4vw;
    text-align: center;
}

.TvBand { color: var(--text-muted); font-size: clamp(20px, 4vh, 44px); font-weight: 700; }
.TvJoinLabel { font-size: clamp(28px, 6vh, 64px); font-weight: 800; }

.TvCode {
    color: var(--accent);
    font-family: ui-monospace, "SF Mono", Consolas, monospace;
    font-size: clamp(64px, 20vh, 240px);
    font-weight: 800;
    letter-spacing: 0.12em;
    line-height: 1;
}

.TvLink { color: var(--text-muted); font-size: clamp(16px, 3vh, 32px); }
.TvPeople { font-size: clamp(16px, 3vh, 32px); font-weight: 600; }
.TvStatus { color: var(--text-faint); font-size: clamp(14px, 2.4vh, 26px); }

.TvTopCode {
    color: var(--text-muted);
    font-family: ui-monospace, "SF Mono", Consolas, monospace;
    font-size: clamp(14px, 2.4vh, 24px);
    font-weight: 700;
    letter-spacing: 0.1em;
}

/* ── Setlists ───────────────────────────────────────────────────────────── */

.SetlistItems {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.SetlistItem {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: start;
    gap: 6px 10px;
    padding: 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2);
}

.SetlistItem.Unavailable { opacity: 0.55; }

.SetlistNumber {
    min-width: 1.6em;
    color: var(--text-faint);
    font-size: 20px;
    font-weight: 800;
    text-align: right;
}

.SetlistSong {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.SetlistSong .Muted { font-size: 13px; }
.SetlistNote { grid-column: 2 / 4; }

.JamSongs.Tall { max-height: 60vh; }

/* Setlists in a jam */
.JamTopExtras {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
}

.SetlistStrip:empty { display: none; }
.SetlistStrip { font-size: clamp(13px, 2vh, 18px); font-weight: 600; }
.Tag.Note { border-color: var(--accent); color: var(--accent); font-size: inherit; }

.SetlistButtons {
    display: inline-flex;
    gap: 8px;
}

/* Ready in the lobby (3.8): the players' button, and the leader's count beside Start. */
/* The wrappers step aside so their buttons sit in the controls row and can be ordered there. */
.PlayControls .ControlsExtras,
.JamControlsExtras { display: contents; }
.JamReady:empty { display: none; }
/* First among the controls, after the status line: beside the leader's Start, and the first
   thing a player sees under "Waiting for…". */
.PlayControls .ControlStatus { order: -2; }
.PlayControls .JamReady { order: -1; display: inline-flex; }
.ReadyCount {
    align-self: center;
    color: var(--text-muted);
    font-size: clamp(15px, 2.2vh, 20px);
    font-weight: 700;
    white-space: nowrap;
}
.ReadyCount.All { color: var(--success); }
.Tag.Ready { border-color: var(--success); color: var(--success); }

.JamSetlist {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 4px 0 8px;
}

.JamSetlistItem {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text);
    font: 15px var(--font);
    text-align: left;
}

button.JamSetlistItem { cursor: pointer; }
button.JamSetlistItem:hover { border-color: var(--border); }
.JamSetlistItem.Current { border-color: var(--accent); background: var(--surface-2); }
.JamSetlistItem.Done { opacity: 0.55; }
.JamSetlistItem .SetlistNumber { min-width: 1.4em; font-size: 15px; }
.JamSetlistItem .JamSongTitle { flex: 1; }

/* ── Practice tools: tempo % and loop ───────────────────────────────────── */

.PracticeBadges { margin-left: 8px; }
.PracticeBadges:empty { display: none; }
.Tag.Practice { margin-right: 6px; border-color: var(--accent); color: var(--accent); font-size: 0.7em; vertical-align: middle; }

.SongMap .Block.InLoop {
    opacity: 1;
    outline: 3px solid var(--accent);
    outline-offset: 2px;
}

.PlayScreen { position: relative; }

.PracticePanel {
    position: absolute;
    right: 3vw;
    bottom: calc(2.4vh + 70px);
    /* Above the count-in overlay, so the leader can change the loop or tempo during a count-in. */
    z-index: 25;
    width: min(380px, calc(100% - 32px));
    padding: 16px;
    box-shadow: var(--shadow);
}

.PracticePanel h3 { margin: 0 0 12px; font-size: 17px; }

.PracticeClose {
    position: absolute;
    top: 10px;
    right: 10px;
}

.TempoRow {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 6px;
}

.TempoValue {
    min-width: 3.2em;
    font-size: 30px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.TempoPresets { flex-wrap: wrap; margin-top: 12px; }

.LoopRow {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 8px 10px;
    margin-bottom: 12px;
}

.LoopRow label { color: var(--text-muted); font-size: 14px; font-weight: 600; }

.LoopButtons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 8px;
}

@media (max-aspect-ratio: 1/1) {
    .PracticePanel { right: 16px; bottom: calc(2vh + 110px); }
}

/* ── QR codes ───────────────────────────────────────────────────────────── */

/* Always dark-on-white with a margin, whatever the theme - phone cameras read that reliably. */
.QrCode {
    flex: none;
    width: 150px;
    padding: 0;
    border-radius: 8px;
    background: #fff;
    overflow: hidden;
}

.QrCode svg { display: block; width: 100%; height: auto; }
.QrCode.Small { width: 120px; margin-bottom: 12px; }
.QrCode.Unavailable { display: none; }

.JamCodeBlock {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 20px;
}

.JamCodeText { flex: 1 1 200px; min-width: 0; }

.TvJoinRow {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5vw;
}

.TvQr .QrCode { width: min(34vh, 40vw); }

@media (max-aspect-ratio: 1/1) {
    .TvJoinRow { flex-direction: column; gap: 3vh; }
}

/* ── Drag to reorder ────────────────────────────────────────────────────── */

.DragHandle {
    display: inline-grid;
    flex: none;
    place-items: center;
    width: 30px;
    height: 36px;
    color: var(--text-faint);
    cursor: grab;
    touch-action: none;       /* the finger drags the item, not the page */
    user-select: none;
}

.DragHandle:hover { color: var(--text-muted); }
.Sorting .DragHandle { cursor: grabbing; }

.Sorting .SectionBlock,
.Sorting .SetlistItem { transition: transform 120ms ease; }

.SectionBlock.Dragging,
.SetlistItem.Dragging {
    position: relative;
    z-index: 5;
    box-shadow: var(--shadow);
    transition: none;
    opacity: 0.95;
}

.SetlistNumber {
    display: inline-flex;
    align-items: center;
}

/* ── Highway layout ─────────────────────────────────────────────────────── */

.Highway,
.HighwayLyric { display: none; }

.PlayScreen.LayoutHighway .CurrentCard,
.PlayScreen.LayoutHighway .UpcomingRow { display: none; }

.PlayScreen.LayoutHighway .Highway {
    position: relative;
    display: block;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
}

/* Track, now line and countdown share one plane, so tilting it keeps them lined up. */
.HighwayStage {
    position: absolute;
    inset: 0;
}

/* Rising: tip the plane back a little, so the blocks narrow as they rise into the distance.
   Layout still uses the untransformed size; the transform only changes how it's drawn. */
.Highway.Rise .HighwayStage {
    transform: perspective(1000px) rotateX(6deg);
}

.HighwayTrack {
    position: absolute;
    inset: 0;
    will-change: transform;
}

.HighwayBlock {
    position: absolute;
    top: 10%;
    bottom: 10%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.6vh;
    padding: 0 1.4vw;
    overflow: hidden;
    border-radius: 12px;
    /* Section colour, with a darker hairline at the start of each bar. */
    background-color: var(--section, var(--section-custom));
    background-image: linear-gradient(to right, rgba(0, 0, 0, 0.55) 3px, transparent 3px);
    color: rgba(0, 0, 0, 0.82);
    opacity: 0.6;
    transition: opacity 150ms linear;
}

.HighwayBlock.Current { opacity: 1; box-shadow: 0 0 0 3px var(--text); }
.HighwayBlock.Done { opacity: 0.25; }

.HighwayLabel {
    overflow: hidden;
    font-size: clamp(22px, 7vh, 80px);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1;
    text-transform: uppercase;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.HighwayBars { font-size: clamp(13px, 2.4vh, 26px); font-weight: 700; }
.HighwayNotes { font-size: clamp(13px, 2.4vh, 26px); font-style: italic; }
.HighwayChords { font-size: clamp(14px, 2.8vh, 30px); font-weight: 800; white-space: nowrap; }

/* The "now" line - where the band is. */
.HighwayNow {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 4px;
    margin-left: -2px;
    border-radius: 2px;
    background: var(--text);
    box-shadow: 0 0 12px var(--text);
    pointer-events: none;
}

.HighwayCountdown {
    position: absolute;
    top: 50%;
    display: none;
    padding: 0 12px;
    border-radius: 12px;
    background: var(--bg);
    color: var(--accent);
    font-size: clamp(40px, 14vh, 140px);
    font-variant-numeric: tabular-nums;
    font-weight: 800;
    transform: translate(-50%, -50%);
    pointer-events: none;
}

.HighwayCountdown.Visible { display: block; }

/* With lyrics on, the track gives up about 40% of its height so the lines below it - the one
   being sung and the next ones coming - are big enough to read from the drum stool. */
.PlayScreen.LayoutHighway.HighwayLyrics .Highway { flex: 3 1 0; }

.PlayScreen.LayoutHighway .HighwayLyric {
    display: flex;
    flex-direction: column;
    gap: 0.8vh;
    min-height: 1.3em;
    overflow: hidden;
    text-align: center;
}

.PlayScreen.LayoutHighway.HighwayLyrics .HighwayLyric { flex: 2 1 0; }

.HighwayLyricLine {
    display: -webkit-box;
    overflow: hidden;
    color: var(--text-muted);
    font-size: clamp(17px, 3.4vh, 40px);
    font-weight: 600;
    line-height: 1.2;
    /* Up to two lines on a phone rather than cutting the line off. */
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.HighwayLyricLine.Current {
    color: var(--text);
    font-size: clamp(20px, 4.4vh, 52px);
    font-weight: 700;
}

/* The first line of a section still to come, marked with that section's name and colour. */
.HighwayLyricSection {
    padding: 0 0.4em;
    border-radius: 6px;
    background: var(--section, var(--section-custom));
    color: rgba(0, 0, 0, 0.82);
    font-size: 0.7em;
    font-weight: 800;
    text-transform: uppercase;
    vertical-align: 0.15em;
}

.HighwayContent {
    display: flex;
    flex-direction: column;
    /* Only as wide as its text, so it has room to ride along the block. */
    align-self: flex-start;
    gap: 0.6vh;
    max-width: 100%;
    /* A halo of the block's own colour: the bar lines run right across the block, but break
       around the letters rather than cutting through them. */
    text-shadow:
        0 3px 0 var(--section, var(--section-custom)),
        0 -3px 0 var(--section, var(--section-custom)),
        0 5px 2px var(--section, var(--section-custom)),
        0 -5px 2px var(--section, var(--section-custom)),
        3px 0 0 var(--section, var(--section-custom)),
        -3px 0 0 var(--section, var(--section-custom));
    will-change: transform;
}

/* Portrait: the label sits at the bottom of the block - the end the band reaches first. */
.Highway.Vertical .HighwayBlock { justify-content: flex-end; }

.HighwayLyric.Empty { visibility: hidden; }

/* Portrait: the track runs top to bottom and the blocks come down towards the line. */
.Highway.Vertical .HighwayBlock {
    top: auto;
    bottom: auto;
    left: 10%;
    right: 10%;
    padding: 1vh 4vw;
    background-image: linear-gradient(to bottom, transparent calc(100% - 3px), rgba(0, 0, 0, 0.55) calc(100% - 3px));
}

.Highway.Vertical .HighwayNow {
    top: auto;
    left: 0;
    right: 0;
    bottom: auto;
    width: auto;
    height: 4px;
    margin: -2px 0 0;
}

.Highway.Vertical .HighwayCountdown {
    top: auto;
    left: 50%;
}

/* Rising: blocks come up the screen towards a line near the top, carrying their lyrics. The
   lyric pane under the track isn't needed. */
.PlayScreen.LayoutRise .HighwayLyric { display: none; }

.Highway.Rise .HighwayBlock {
    justify-content: flex-start;
    background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.55) 3px, transparent 3px);
}

/* Landscape and TV: a narrower column, so the lines stay a comfortable reading width. */
.Highway.Rise.Wide .HighwayBlock {
    left: 18%;
    right: 18%;
}

/* With lyrics, the name turns sideways into a strip down the left; the lines fill the rest. */
.Highway.Rise .HighwayBlock.WithLyrics {
    flex-direction: row;
    gap: 0;
    padding: 0;
}

.HighwayBlock.WithLyrics .HighwayContent {
    flex: 0 0 auto;
    padding: 0.4em 0.15em;
}

.HighwayBlock.WithLyrics .HighwayLabel {
    font-size: clamp(14px, 2.6vh, 28px);
    writing-mode: vertical-rl;
    transform: rotate(180deg);
}

.HighwayBlock.WithLyrics .HighwayBars,
.HighwayBlock.WithLyrics .HighwayNotes { display: none; }

.HighwayBlockLyrics {
    position: relative;
    flex: 1 1 auto;
    border-left: 2px solid rgba(0, 0, 0, 0.25);
}

.HighwayBlockLine {
    position: absolute;
    left: 0;
    right: 0;
    display: -webkit-box;
    padding: 0.2em 0.5em;
    overflow: hidden;
    font-size: clamp(16px, 3.4vh, 44px);
    font-weight: 700;
    line-height: 1.15;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.HighwayBlockLine.Current {
    background: rgba(255, 255, 255, 0.4);
    color: #000;
}

.HighwayBlockLine.Past { opacity: 0.4; }

/* ── Editing a section from the play screen (while paused) ─────────────── */

.SongMap.Editable .Block {
    opacity: 0.9;
    cursor: pointer;
    outline: 1px dashed rgba(255, 255, 255, 0.35);
    outline-offset: -1px;
}

.SongMap .Block.Editing {
    opacity: 1;
    outline: 3px solid var(--text);
    outline-offset: 2px;
}

.SectionPopup {
    position: absolute;
    left: 50%;
    bottom: calc(2.4vh + 120px);
    z-index: 26;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: min(440px, calc(100% - 32px));
    max-height: 70vh;
    padding: 16px;
    overflow-y: auto;
    box-shadow: var(--shadow);
    transform: translateX(-50%);
}

.SectionPopup[hidden] { display: none; }
.SectionPopup h3 { margin: 0 0 4px; font-size: 17px; }
.SectionPopup .SectionRow > select { flex: 1 1 auto; }
.SectionPopup .TextArea.Lyrics { min-height: 90px; }
.SectionPopup .SectionAdd {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding-top: 10px;
    border-top: 1px solid var(--border);
}
.SectionPopup .SectionAdd .Button,
.SectionPopup .SectionBack { padding: 6px 12px; font-size: 14px; }
.SectionPopup .SectionBack { align-self: flex-start; }

/* Where a new section will go: a bar on that side of the section it sits next to. */
.SongMap .Block.InsertBefore,
.SongMap .Block.InsertAfter { opacity: 1; }
.SongMap .Block.InsertBefore { box-shadow: -5px 0 0 var(--accent); }
.SongMap .Block.InsertAfter { box-shadow: 5px 0 0 var(--accent); }

@media (max-aspect-ratio: 1/1) {
    .SectionPopup { bottom: calc(2vh + 150px); }
}

/* ── Backing track (song editor) ────────────────────────────────────────── */

.VisuallyHidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.BackingTrack { gap: 8px; }

.BackingChoices {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.BackingChoices .Input { flex: 1 1 200px; min-width: 0; }

/* A still of the video until it's pressed, then the video itself - no YouTube load until asked. */
.YouTubePreview {
    position: relative;
    display: block;
    width: 100%;
    max-width: 480px;
    aspect-ratio: 16 / 9;
    padding: 0;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface-2);
    cursor: pointer;
}

.YouTubePreview img { width: 100%; height: 100%; object-fit: cover; display: block; }

.YouTubePreview .PlayBadge {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text);
    font-size: 56px;
    text-shadow: 0 2px 12px var(--bg);
}

.YouTubeFrame {
    width: 100%;
    max-width: 480px;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--radius);
    background: var(--bg);
}

.YouTubeFrame iframe { width: 100%; height: 100%; border: 0; display: block; }

/* YouTube refused the video: a way to watch it there instead, in the video's place. */
.YouTubeFrame.Failed {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px;
    text-align: center;
    border: 1px solid var(--border);
    background: var(--surface-2);
}

.YouTubeFrame.Failed > .fa { color: var(--accent); font-size: 32px; }
.YouTubeFrame.Failed p { margin: 0; }
.YouTubeFrame.Failed .Hint { color: var(--text-muted); font-size: 0.85em; }

.AudioPreview { display: flex; flex-direction: column; gap: 6px; }
.AudioPreview audio { width: 100%; max-width: 480px; }
.AudioName { font-weight: 600; overflow-wrap: anywhere; }
.AudioDetails { font-size: 13px; font-variant-numeric: tabular-nums; }
.AudioDetails:empty { display: none; }
/* The click over the preview, under its player. */
.PreviewClick { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 14px; }

/* Upload (or replace) the file for the band, with the rights line under it. */
.BackingUpload { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.BackingUpload:empty { display: none; }
.BackingUpload .Hint, .BackingUpload .ErrorText { flex-basis: 100%; margin: 0; }
.BackingUpload .ErrorText:empty { display: none; }

.BackingRow {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.StartAt {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    color: var(--text-muted);
    font-size: 14px;
}

.StartAt .Input { width: 90px; }

/* ── Transcribe Chart ───────────────────────────────────────────────────── */

/* Its own top bar instead of the app's, and room at the bottom for the tap bar. */
body.Transcribing #AppHeader { display: none; }
body.Transcribing #AppContent { padding: 12px 16px 220px; }

.TranscribeTop {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

.TranscribeTitle { flex: 1; min-width: 0; }
.TranscribeTitle h1 { margin: 0; font-size: 20px; }
.TranscribeTitle .Muted { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }

.TranscribeGrid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
}

@media (min-width: 900px) {
    .TranscribeGrid { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); align-items: start; }
    .TranscribePlayer { position: sticky; top: 12px; }
}

.TranscribePlayer {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.TranscribeMedia .YouTubeFrame { max-width: none; }

.TapVideoHint {
    margin: 8px 0 0;
    padding: 10px 12px;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    color: var(--accent);
    font-weight: 600;
}

.AudioCard {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--surface);
    font-weight: 600;
    overflow-wrap: anywhere;
}

.AudioCard .fa { color: var(--accent); font-size: 24px; }

.Scrubber {
    display: flex;
    align-items: center;
    gap: 10px;
}

.Scrubber input { flex: 1; min-width: 0; accent-color: var(--accent); }

.Time { font-variant-numeric: tabular-nums; font-size: 14px; }

.Transport {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
}

.Transport .Button.Icon { position: relative; }
.Transport .Button.Icon small { position: absolute; right: 6px; bottom: 3px; font-size: 10px; font-weight: 700; }

.Transport .PlayPause {
    width: 64px;
    height: 64px;
    padding: 0;
    border-radius: 50%;
    font-size: 24px;
}

.TranscribeSettings {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 20px;
}

.TranscribeSettings .Setting {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-muted);
    font-size: 14px;
}

.TranscribeSettings .Setting .Input { width: 76px; }
.TranscribeSettings .Setting .Time { color: var(--text); font-weight: 600; }

.NowPlaying {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 8px;
}

.NowPlaying .Where { font-size: 20px; font-weight: 700; }

.BeatDots { display: flex; gap: 6px; }

.BeatDots span {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--surface-3);
}

.BeatDots span.On { background: var(--accent); }
.BeatDots span:first-child.On { box-shadow: 0 0 0 3px var(--surface-3); }

/* The chart so far, a block per section, with the playhead running over it. */
.TranscribeMap {
    position: relative;
    min-height: 36px;
    border-radius: var(--radius);
    background: var(--surface-2);
}

.MapBlocks { display: flex; gap: 2px; min-height: 36px; }

.MapBlocks .Block {
    display: flex;
    align-items: center;
    min-width: 6px;
    padding: 0 6px;
    overflow: hidden;
    border-radius: 6px;
    background: var(--section, var(--section-custom));
    color: var(--accent-text);
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.MapPlayhead {
    position: absolute;
    top: -4px;
    bottom: -4px;
    width: 3px;
    border-radius: 2px;
    background: var(--text);
    transform: translateX(-50%);
    pointer-events: none;
}

.TranscribeSections {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 14px;
}

.TranscribeEmpty { color: var(--text-muted); }
.TranscribeEmpty p { margin: 0 0 8px; }

.TranscribeSection {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    border: 1px solid var(--border);
    border-left: 6px solid var(--section, var(--border));
    border-radius: var(--radius);
    background: var(--surface);
}

.TranscribeSection.Current { border-color: var(--accent); border-left-color: var(--section, var(--accent)); }
.TranscribeSection.Newest { background: var(--surface-2); }

.TranscribeSection .Stamp { font-variant-numeric: tabular-nums; padding: 0 8px; }
.TranscribeSection .Bars { min-width: 30px; text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; }


/* The tap grid, always under the thumb: Play, a hint, Undo and End, then one button per type. */
.TapBar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px 16px calc(10px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border);
    background: var(--surface);
}

.TapControls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.TapControls .Button { min-height: 44px; }
.TapControls .TapPlay { width: 52px; padding: 0; font-size: 20px; }
.TapHint { flex: 1; min-width: 0; color: var(--text-muted); font-size: 14px; font-weight: 600; }

.TapGrid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 6px;
}

.TapGrid .TapType {
    position: relative;
    min-height: 56px;
    padding: 0 6px;
    border-top: 5px solid var(--section, var(--border));
    font-size: 15px;
    font-weight: 800;
}

/* Long names (Pre-Chorus, Breakdown) wrap onto two lines on a phone rather than be cut off. */
.TapGrid .TapType span { line-height: 1.15; overflow-wrap: anywhere; }
.TapGrid .TapType kbd { display: none; }
.TapGrid .TapType.Flash { animation: TapFlash 0.35s ease-out; }
.TranscribeSettings .LineUp { flex-basis: 100%; flex-wrap: wrap; }
.TranscribeSettings .Check { flex-basis: 100%; flex-wrap: wrap; gap: 6px; }

/* Taps against the click: a line in the middle for "on it", early to the left, late to the right. */
.TapMeter {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 4px 8px;
    flex-basis: 100%;
    max-width: 420px;
    font-size: 12px;
}

.TapMeter[hidden] { display: none; }
.TapMeter .MeterEnd { color: var(--text-faint); }

.MeterTrack {
    position: relative;
    height: 22px;
    border-radius: 999px;
    background: var(--surface-2);
}

.MeterCentre {
    position: absolute;
    top: 2px;
    bottom: 2px;
    left: 50%;
    width: 2px;
    transform: translateX(-50%);
    background: var(--accent);
}

.MeterDot {
    position: absolute;
    top: 50%;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--text);
    transform: translate(-50%, -50%);
}

.MeterDot.Latest { width: 14px; height: 14px; box-shadow: 0 0 0 2px var(--accent); }
.TapMeter .MeterNote { grid-column: 1 / -1; color: var(--text); font-size: 13px; font-weight: 600; }
.TranscribeSettings .MoveBy { flex-basis: 100%; flex-wrap: wrap; gap: 6px; }
.TranscribeSettings .MoveBy > span { margin-right: 2px; }

/* A phone: the four moves share one row evenly; the group's own label names it for screen readers. */
@media (max-width: 520px) {
    .TranscribeSettings .MoveBy { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .TranscribeSettings .MoveBy > span { display: none; }
    .TranscribeSettings .MoveBy .Button { padding: 0 4px; }
}
.TranscribeSettings .LineUp .Button.Flash { animation: TapFlash 0.35s ease-out; }

@keyframes TapFlash {
    from { box-shadow: 0 0 0 6px var(--section, var(--accent)); }
    to { box-shadow: 0 0 0 0 transparent; }
}

/* Room below the content for the bar: two rows of types and the controls. */
body.Transcribing #AppContent { padding-bottom: 220px; }

/* Wide: the player stays in view beside the chart (no second Play), and the types fit one row,
   with their number keys shown. */
@media (min-width: 900px) {
    .TapControls .TapPlay { display: none; }
    .TapGrid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
    .TapGrid .TapType { min-height: 60px; }
    .TapGrid .TapType kbd {
        display: block;
        position: absolute;
        top: 4px;
        right: 6px;
        color: var(--text-faint);
        font: 600 11px var(--font);
    }
    body.Transcribing #AppContent { padding-bottom: 150px; }
}

.TranscribeSection .SectionRow > select { flex: 1 1 auto; min-width: 0; }
.TranscribeSection .SectionRow > input { flex: 1 1 auto; min-width: 0; }

@media (max-width: 520px) {
    .TapBar { gap: 6px; padding-left: 10px; padding-right: 10px; }
    .TapControls .Button { width: 48px; padding: 0; font-size: 18px; }
    .TapControls .Label { display: none; }
    .TapHint { font-size: 13px; }
    .TapGrid { gap: 5px; }
    .TapGrid .TapType { font-size: 13px; padding: 0 3px; }
    .TranscribeSection .SectionRow { gap: 4px; }
    .TranscribeSection .Stamp { padding: 0 6px; font-size: 13px; }
    .TranscribeSection .SectionRow .Button.Icon.Small { width: 30px; min-width: 30px; }
}

/* ── Waveform (backing track) ───────────────────────────────────────────── */

.Waveform { display: flex; flex-direction: column; gap: 6px; }

.WaveformBar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 6px 10px;
    font-size: 13px;
}

.WaveformStatus { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; }

.WaveformCanvas {
    display: block;
    width: 100%;
    height: 72px;
    border-radius: var(--radius);
    cursor: pointer;
    /* Dragging the start flag mustn't scroll the page instead. */
    touch-action: none;
}

.AudioPreview .Waveform { max-width: 480px; }

.WaveformTools { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }

/* The pop-out: a big close-up of the waveform for putting the start flag exactly on the beat. */
body.WaveDialogOpen { overflow: hidden; }

.WaveDialogBackdrop {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: var(--scrim);
}

.WaveDialog {
    display: flex;
    flex-direction: column;
    gap: 12px;
    width: min(1100px, 100%);
    max-height: 100%;
    overflow-y: auto;
    padding: 16px;
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    box-shadow: var(--shadow);
}

.WaveDialogHead { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.WaveDialogHead h2 { margin: 0; font-size: 18px; }

.WaveDialog .WaveOverview { height: 40px; cursor: ew-resize; }
.WaveDialog .WaveCloseUp { height: 220px; }

.WaveDialogRow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.WaveDialogGap { flex: 1; }
.WaveZoom { min-width: 7.5em; text-align: center; font-variant-numeric: tabular-nums; color: var(--text-muted); }
.WaveStartTime { min-width: 5.5em; text-align: center; font-size: 20px; font-variant-numeric: tabular-nums; }
.WaveDialog .Hint { margin: 0; }

/* A phone: the whole screen, and a shorter close-up so the controls fit under it. */
@media (max-width: 560px) {
    .WaveDialogBackdrop { padding: 0; }
    .WaveDialog { height: 100%; border-radius: 0; padding: 12px 16px; }
    .WaveDialog .WaveCloseUp { height: 170px; }
    .WaveDialogGap { display: none; }
}

/* A section's own tempo or meter beside its name on the current card ("½ time", "3/4"). */
.CurrentCard .Label .TempoTag {
    display: inline-block;
    margin-left: 0.4em;
    padding: 0.08em 0.35em;
    border: 2px solid currentColor;
    border-radius: var(--radius);
    font-size: 0.32em;
    letter-spacing: 0;
    vertical-align: middle;
}

/* ── Find tempo and start ─────────────────────────────────────────────────
   Transcribe's player column on the left (on top on a phone), the three steps beside it. */
body.FindingTempo #AppHeader { display: none; }
body.FindingTempo #AppContent { padding: 12px 16px 40px; }

.TempoSteps { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.TempoStep { display: flex; flex-direction: column; gap: 10px; }
.TempoStep h2 { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 18px; }
.TempoStep .Hint { margin: 0; }
.StepNumber {
    display: inline-grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent);
    color: var(--accent-text);
    font-size: 15px;
    font-weight: 800;
}

/* A big target to tap in time - timed on pointerdown, so it must not wait for anything. */
.TapPad { min-height: 64px; font-size: 18px; touch-action: manipulation; user-select: none; }
.TapPad.Flash { animation: TapFlash 0.35s ease-out; }
.TempoNote { min-height: 1.4em; color: var(--text-muted); font-weight: 600; }
.TempoNote.Steady { color: var(--success); }
.TempoStep .TempoRow { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 8px; }
.TempoStep .TempoRow .Setting { display: inline-flex; align-items: center; gap: 8px; color: var(--text-muted); font-size: 14px; font-weight: 600; }
.TempoStep .TempoRow .Input { width: 90px; }
.TempoStep .ClickToggle.Block { width: 100%; }

/* The grid's bar and beat, big: watch it land on the music. */
.TempoNow { justify-content: space-between; }
.TempoNow .Where { font-variant-numeric: tabular-nums; }

/* The song editor's backing track: Find tempo and start beside Transcribe Chart. */
.BackingActions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
@media (max-width: 420px) {
    .BackingActions { grid-template-columns: 1fr; }
}

/* The play screen's Track start panel: a row of nudges either side of where the song starts. */
.StartNudges { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; }
.StartNudges .StartValue { min-width: 5em; font-size: 24px; text-align: center; font-variant-numeric: tabular-nums; }
/* A phone: earlier on one row, where it starts, later on the next. */
@media (max-width: 560px) {
    .StartNudges { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .StartNudges .StartValue { grid-column: 1 / -1; }
}
