/* Header / Logo */

/* Hero dancer: dances in bursts, then rests.

     The gameplay dancer (/characterdance.svg) never stops, which is right for
     a screen people watch for one round. This one sits above a page people
     read, so it dances for 4.5s, winds down, and holds still for 7.5s,
     blinking twice while it waits. One cycle is --dc-burst, default 12s.

     Timeline at the default 12s:
       0.0 - 3.0s   two full beats, same amplitude as the gameplay dancer
       3.0 - 4.5s   wind-down: 3deg, then 2.2deg, then 1.1deg, onto rest
       4.5 - 12.0s  still. Blinks at 6.2s and 9.4s.

     The wind-down is not decoration. Cutting the dance at a timer freezes the
     body mid-bounce, which reads as the animation breaking rather than the
     character finishing. Three decaying bounces cost 1.5s and fix it.

     Rest pose is 0 on every part, so the 7.5s hold is the artwork exactly as
     drawn and the browser stops repainting for the whole of it.

     Why this is inlined in index.html rather than an <img> like the gameplay
     dancer: SVG inside <img> is sandboxed, so nothing outside can style it or
     receive its pointer events. Tap-to-dance needs it in the document.

     Two gates, not one:
       .dc-run    loops forever. Applied on load by app.js.
       .dc-once   runs the cycle a single time. Used when the visitor has
                  asked for reduced motion: nothing moves on its own, but a
                  deliberate tap is the visitor asking for it, so a tap still
                  plays one burst and then stops.

     Same structural rule as characterdance.svg: every animation drives a
     wrapper <g> that carries no transform of its own, so the artwork's own
     positioning is never overridden and the headphones stay on the head. */

.hero-dancer {
    display: block;
    margin: 0 auto 8px;
    width: 150px;
    height: auto;
    max-width: 56%;
    /* No pointer cursor on purpose. Tapping is a small reward, not
       navigation, and a pointer cursor would promise a link that isn't
       there. */
  }

.hero-dancer #dc-shadow,
  .hero-dancer #dc-body,
  .hero-dancer #dc-arm-l,
  .hero-dancer #dc-arm-r,
  .hero-dancer #dc-eyes,
  .hero-dancer #Group_26 { transform-box: fill-box; }

/* Arms pivot at the shoulder, so the origin sits at the edge nearest the
     body. The body pivots where the legs meet it, so the feet stay planted. */

.hero-dancer #dc-body { transform-origin: 50% 100%; }
.hero-dancer #dc-arm-l { transform-origin: 100% 6%; }
.hero-dancer #dc-arm-r { transform-origin: 0% 6%; }
.hero-dancer #dc-shadow { transform-origin: 50% 50%; }
.hero-dancer #dc-eyes { transform-origin: 50% 50%; }
.hero-dancer #Group_26 { transform-origin: 50% 72%; }

.hero-dancer.dc-run #dc-body { animation: hbBody var(--dc-burst, 12s) ease-in-out infinite; }
.hero-dancer.dc-run #dc-arm-l { animation: hbArmL var(--dc-burst, 12s) ease-in-out infinite; }
.hero-dancer.dc-run #dc-arm-r { animation: hbArmR var(--dc-burst, 12s) ease-in-out infinite; }
.hero-dancer.dc-run #dc-shadow { animation: hbShadow var(--dc-burst, 12s) ease-in-out infinite; }
.hero-dancer.dc-run #Group_26 { animation: hbCans var(--dc-burst, 12s) ease-in-out infinite; }
.hero-dancer.dc-run #dc-eyes { animation: hbBlink var(--dc-burst, 12s) linear infinite; }

.hero-dancer.dc-once #dc-body { animation: hbBody var(--dc-burst, 12s) ease-in-out 1; }
.hero-dancer.dc-once #dc-arm-l { animation: hbArmL var(--dc-burst, 12s) ease-in-out 1; }
.hero-dancer.dc-once #dc-arm-r { animation: hbArmR var(--dc-burst, 12s) ease-in-out 1; }
.hero-dancer.dc-once #dc-shadow { animation: hbShadow var(--dc-burst, 12s) ease-in-out 1; }
.hero-dancer.dc-once #Group_26 { animation: hbCans var(--dc-burst, 12s) ease-in-out 1; }
.hero-dancer.dc-once #dc-eyes { animation: hbBlink var(--dc-burst, 12s) linear 1; }

/* Quarter-beat keyframes, 0.375s apart, so 3.125% per step at 12s. The legs
     sit outside #dc-body and never animate, and there is no vertical travel,
     so body and legs never come apart. The scaleY squash lands on the
     zero-crossings, which is where the weight settles. */

@keyframes hbBody {
    0%      { transform: rotate(0deg) scaleY(1); }
    3.125%  { transform: rotate(3deg) scaleY(1); }
    6.25%   { transform: rotate(0deg) scaleY(1.025); }
    9.375%  { transform: rotate(-3deg) scaleY(1); }
    12.5%   { transform: rotate(0deg) scaleY(1.025); }
    15.625% { transform: rotate(3deg) scaleY(1); }
    18.75%  { transform: rotate(0deg) scaleY(1.025); }
    21.875% { transform: rotate(-3deg) scaleY(1); }
    25%     { transform: rotate(0deg) scaleY(1.025); }
    28.125% { transform: rotate(2.2deg) scaleY(1); }
    31.25%  { transform: rotate(0deg) scaleY(1.012); }
    34.375% { transform: rotate(-1.1deg) scaleY(1); }
    37.5%   { transform: rotate(0deg) scaleY(1); }
    100%    { transform: rotate(0deg) scaleY(1); }
  }

/* The arms hang down and outward and are drawn behind the body, so the sign
     that lifts each one differs: the left arm lifts on positive rotation, the
     right on negative. Getting this backwards tucks them out of sight. They
     alternate which one goes higher, one per bounce. */

@keyframes hbArmL {
    0%      { transform: rotate(0deg); }
    3.125%  { transform: rotate(34deg); }
    6.25%   { transform: rotate(2deg); }
    9.375%  { transform: rotate(14deg); }
    12.5%   { transform: rotate(4deg); }
    15.625% { transform: rotate(34deg); }
    18.75%  { transform: rotate(2deg); }
    21.875% { transform: rotate(14deg); }
    25%     { transform: rotate(4deg); }
    28.125% { transform: rotate(20deg); }
    31.25%  { transform: rotate(2deg); }
    34.375% { transform: rotate(8deg); }
    37.5%   { transform: rotate(0deg); }
    100%    { transform: rotate(0deg); }
  }

@keyframes hbArmR {
    0%      { transform: rotate(0deg); }
    3.125%  { transform: rotate(-14deg); }
    6.25%   { transform: rotate(-2deg); }
    9.375%  { transform: rotate(-34deg); }
    12.5%   { transform: rotate(-4deg); }
    15.625% { transform: rotate(-14deg); }
    18.75%  { transform: rotate(-2deg); }
    21.875% { transform: rotate(-34deg); }
    25%     { transform: rotate(-4deg); }
    28.125% { transform: rotate(-8deg); }
    31.25%  { transform: rotate(-2deg); }
    34.375% { transform: rotate(-20deg); }
    37.5%   { transform: rotate(0deg); }
    100%    { transform: rotate(0deg); }
  }

/* Shadow shifts weight with the sway rather than pulsing, since nothing
     leaves the ground. */

@keyframes hbShadow {
    0%      { transform: translateX(0); }
    3.125%  { transform: translateX(4px); }
    6.25%   { transform: translateX(0); }
    9.375%  { transform: translateX(-4px); }
    12.5%   { transform: translateX(0); }
    15.625% { transform: translateX(4px); }
    18.75%  { transform: translateX(0); }
    21.875% { transform: translateX(-4px); }
    25%     { transform: translateX(0); }
    28.125% { transform: translateX(3px); }
    31.25%  { transform: translateX(0); }
    34.375% { transform: translateX(-1.5px); }
    37.5%   { transform: translateX(0); }
    100%    { transform: translateX(0); }
  }

/* Headphones counter-rotate a touch so they read as having weight. */

@keyframes hbCans {
    0%      { transform: rotate(0deg); }
    3.125%  { transform: rotate(-1.5deg); }
    6.25%   { transform: rotate(0deg); }
    9.375%  { transform: rotate(1.5deg); }
    12.5%   { transform: rotate(0deg); }
    15.625% { transform: rotate(-1.5deg); }
    18.75%  { transform: rotate(0deg); }
    21.875% { transform: rotate(1.5deg); }
    25%     { transform: rotate(0deg); }
    28.125% { transform: rotate(-1deg); }
    31.25%  { transform: rotate(0deg); }
    34.375% { transform: rotate(0.6deg); }
    37.5%   { transform: rotate(0deg); }
    100%    { transform: rotate(0deg); }
  }

/* Two blinks during the rest, at 6.2s and 9.4s, deliberately not evenly
     spaced. Even spacing reads as a metronome rather than a living thing. */

@keyframes hbBlink {
    0%, 51.6% { transform: scaleY(1); }
    52.5%     { transform: scaleY(0.08); }
    53.5%     { transform: scaleY(1); }
    78.3%     { transform: scaleY(1); }
    79.2%     { transform: scaleY(0.08); }
    80.2%     { transform: scaleY(1); }
    100%      { transform: scaleY(1); }
  }

/* Reduced motion kills .dc-run outright, so nothing moves on its own. It
     deliberately does NOT kill .dc-once: that class is only ever applied by a
     tap, and a tap is the visitor asking for the animation. */

@media (prefers-reduced-motion: reduce) {
    .hero-dancer.dc-run #dc-shadow,
    .hero-dancer.dc-run #dc-body,
    .hero-dancer.dc-run #dc-arm-l,
    .hero-dancer.dc-run #dc-arm-r,
    .hero-dancer.dc-run #dc-eyes,
    .hero-dancer.dc-run #Group_26 { animation: none; }
  }

/* The lobby header icon is the character (/characterdance-blink.svg), where
     the other two games still use their flat webp logo. base.css sizes the
     shared .lobby-head-icon at 56px, which is right for those, but the
     character carries a shadow ellipse and some padding the webp does not, so
     at an identical height the figure itself reads smaller. This nudge is
     dance-only on purpose: .lobby-head-icon is shared, and changing it in
     base.css would resize the word and draw lobbies too. */

.lobby-head-char { height: 60px; }

.logo .discuss-art {
    display: block;
    margin: 0 auto 28px;
    width: 320px;
    height: auto;
    max-width: 80%;
  }

/* Game-master banner (Host Picks mode) — the imposter banner's neutral
     twin: the host isn't playing, so it reads calm teal, not alarm red. */

.gm-banner {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(47, 158, 148, 0.08);
    border: 1.5px solid rgba(47, 158, 148, 0.5);
    border-radius: 999px;
    padding: 6px 16px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--accent-teal);
  }

/* Vote screen */

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

.vote-row {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    background: #fff;
    border: 2px solid transparent;
    border-radius: 18px;
    padding: 14px 16px;
    box-shadow: var(--shadow);
    cursor: pointer;
    font-family: inherit;
    color: var(--ink);
    text-align: left;
    transition: transform 0.15s ease, background 0.2s, border-color 0.2s, color 0.2s;
  }

.vote-row:active:not(:disabled) { transform: scale(0.985); }

.vote-row:disabled { cursor: default; }

.vote-row.voted {
    background: var(--accent-teal);
    border-color: var(--accent-teal);
    color: #fff;
  }

.vote-row.voted .player-name { color: #fff; }

.vote-row .check { margin-left: auto; opacity: 0; transition: opacity 0.2s; }

.vote-row.voted .check { opacity: 1; }

.vote-summary {
    margin: 14px 0 4px;
    text-align: center;
    font-size: 13px;
    color: var(--ink-soft);
  }

.vote-summary b { color: var(--ink); font-weight: 600; }

.gameplay-header {
    text-align: center;
    margin-bottom: 16px;
  }

.gameplay-header .role {
    font-size: 11px;
    letter-spacing: 2px;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 6px;
    font-weight: 600;
  }

.gameplay-header .now-playing {
    font-family: 'Literata', Georgia, serif;
    font-size: 24px;
    font-weight: 400;
  }

.visualizer {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 5px;
    height: 130px;
    padding: 16px 0 2px;
    margin: 8px 0 0;
  }

/* Bars keep a fixed layout height and bounce via scaleY so the
     animation never triggers layout shifts (CLS) or reflow. */

.visualizer .bar {
    width: 8px;
    height: 150px;
    background: rgba(9, 19, 20, 0.16);
    border-radius: 4px;
    transform-origin: bottom;
    transform: scaleY(0.05);
    transition: transform 0.1s ease-out;
  }

/* The dancer sits on no backdrop of its own. The stage takes all the space
     left between the header and the progress bar and centres the character in
     it, which puts the character mid-screen and pushes the progress bar down
     next to the hint text. */

.dancer-stage {
    flex: 1;
    min-height: 180px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

/* The dancer is /characterdance.svg, which carries its own animation and
     honours prefers-reduced-motion on its own. */

.dancer-stage .dancer-svg { width: 200px; height: 208px; }

/* Progress bar */

/* Sits close under the visualizer, so the two read as one block */

.progress-wrap { margin: 6px 0 16px; }

.progress-info {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
    font-size: 13px;
    color: var(--ink-soft);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
  }

.progress-bar {
    width: 100%;
    height: 6px;
    background: var(--bg-soft);
    border-radius: 3px;
    overflow: hidden;
  }

.progress-fill {
    height: 100%;
    background: var(--accent-teal);
    width: 0%;
    transition: width 0.2s linear;
    border-radius: 3px;
  }

/* Reveal */

.reveal-extras { margin: 32px 32px 0 32px; }

.track-section { margin-top: 22px; text-align: left; }

.track-section + .track-section { padding-top: 22px; border-top: 1px solid var(--border); }

/* Reveal subtitle under the "The Reveal!" title (group modes). */

.reveal-emoji { display: block; font-size: 40px; line-height: 1; margin-bottom: 6px; }

.reveal-sub {
    text-align: center;
    color: var(--ink-soft);
    font-size: 17px;
    margin-top: -4px;
  }

/* Group-mode reveal — one card per squad: a colored tag, its song, and
     member chips. The viewer's own squad is teal ("YOUR SQUAD"), the other
     is red ("THE OTHER SQUAD"). */

.reveal-groups { display: flex; flex-direction: column; gap: 20px; margin-top: 8px; }

.reveal-squad {
    border: 1px solid var(--border);
    border-radius: 20px;
    padding: 20px;
    text-align: left;
    background: var(--card);
    box-shadow: var(--shadow);
  }

.reveal-squad-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 14px;
  }

.reveal-squad-tag {
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 1px;
    text-transform: uppercase;
    border-radius: 999px;
    padding: 5px 12px;
    flex-shrink: 0;
  }

.reveal-squad.mine  .reveal-squad-tag { color: var(--accent-teal); background: rgba(47,158,148,0.12); }

.reveal-squad.other .reveal-squad-tag { color: var(--accent-red);  background: rgba(208,74,47,0.10); }

/* Song sits at the bottom of the card: neutral text, but the note icon
     keeps the squad's colour (teal for yours, red for the other). */

.reveal-squad-song {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: 14px;
    font-size: 15px;
    font-weight: 400;
    line-height: 1.3;
    color: var(--ink-soft);
  }

.reveal-squad-song span { min-width: 0; word-break: break-word; }

.reveal-squad-song svg { flex-shrink: 0; margin-top: 2px; }

.reveal-squad.mine  .reveal-squad-song svg { color: var(--accent-teal); }

.reveal-squad.other .reveal-squad-song svg { color: var(--accent-red); }

.reveal-squad-members { display: flex; flex-wrap: wrap; gap: 10px; }

.squad-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 6px 14px 6px 6px;
    background: var(--card);
  }

.squad-chip .player-avatar { width: 30px; height: 30px; font-size: 12px; flex-shrink: 0; }

.squad-chip-name { font-size: 16px; font-weight: 600; color: var(--ink); }

.squad-chip .you-pill { margin-left: 2px; }

/* Audio-blocked overlay — stays up until playback really starts */

.audio-overlay {
    position: fixed;
    inset: 0;
    z-index: 160;
    display: none;
    align-items: center;
    justify-content: center;
    background: rgb(222 208 191 / 55%);
    padding: 20px;
    cursor: pointer;
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
  }

.audio-overlay.open { display: flex; }

.audio-overlay-card {
    background: var(--card-active);
    color: #fff;
    border-radius: 26px;
    padding: 36px 28px;
    width: 100%;
    max-width: 340px;
    text-align: center;
    box-shadow: 0 24px 80px rgba(0,0,0,0.22);
    animation: catModalIn 0.22s cubic-bezier(0.2, 0.7, 0.3, 1);
  }

.audio-overlay-icon { font-size: 42px; line-height: 1; margin-bottom: 16px; }

.audio-overlay-title {
    font-family: 'Literata', Georgia, serif;
    font-size: 26px;
    margin-bottom: 10px;
  }

.audio-overlay-sub { font-size: 13px; color: rgba(255,255,255,0.65); line-height: 1.5; }

/* Home top bar: back link (left) + account button (right) */

.home-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

.home-topbar .back-btn { margin-bottom: 0; }

.account-slot { display: flex; align-items: center; }

/* Combined Game Mode + Music/Songs card: one container instead of two
     stacked, separated by a thin divider. Sections keep their own spacing. */

/* The mode picker's own look (.mode-card/.mode-music-card, .section-divider,
   .mode-trigger*, .mode-row*) moved to shared/base.css when the word game
   picked up the same picker. Only the dance-specific pieces are left below. */

/* Read-only trigger: players see the current game mode but can't change it,
     so strip the button chrome (border, press affordance, chevron). */

.cat-trigger.readonly {
    border-color: transparent;
    background: transparent;
    cursor: default;
    pointer-events: none;
    padding-left: 0;
  }

.cat-trigger.readonly .cat-trigger-chevron { display: none; }

/* Compact, label-less mode/music card for players — smaller icon, tighter
     spacing, no "GAME MODE"/"MUSIC CATEGORY" labels. Host keeps the full card. */

.mode-music-card.compact { gap: 8px; padding: 16px 18px; }

.mode-music-card.compact .cat-label { display: none; }

.mode-music-card.compact .mode-trigger { padding: 0; margin: 0; }

.mode-music-card.compact .mode-trigger-icon { width: 34px; height: 34px; }

.mode-music-card.compact .mode-trigger .mode-trigger-inner { gap: 10px; font-size: 17px; }

.mode-music-card.compact .cat-display {
    font-size: 21px;
    padding: 0;
    margin: 0;
    display: flex;
    align-items: center;
    gap: 8px;
  }

.mode-music-card.compact .cat-display svg { color: var(--ink-soft); flex-shrink: 0; }

/* Dim the card's art, title, badge and description to signal it isn't
     playable yet — but keep the interest button fully opaque, since it's the
     one actionable thing on the card. (Opacity can't be "restored" on a child
     of a faded parent, so we fade the specific parts instead of the card.) */

.mode-soon { cursor: default; }

.mode-soon .mode-row-icon,
  .mode-soon .mode-row-titrow,
  .mode-soon .cat-row-desc { opacity: 0.5; }

.mode-soon-badge {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--accent-teal);
    border: 1px solid var(--accent-teal);
    border-radius: 999px;
    padding: 2px 8px;
    white-space: nowrap;
  }

.mode-interest-btn {
    margin-top: 12px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    color: #fff;
    background: var(--card-active);
    border: none;
    border-radius: 12px;
    padding: 10px 16px;
    cursor: pointer;
    transition: transform 0.12s ease, opacity 0.15s ease;
  }

.mode-interest-btn:active { transform: translateY(1px); }

.mode-interest-btn.interest-done {
    background: transparent;
    color: var(--accent-teal);
    border: 1px solid var(--accent-teal);
    cursor: default;
  }

/* Host Picks (DJ) mode — song pick buttons reuse the trigger look but
     with body type: song titles are long and the serif display size wraps
     badly. The clear button sits beside the optional impostor pick. */

.song-pick-btn > span {
    font-family: inherit;
    font-size: 16px;
    font-weight: 400;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-right: 10px;
  }

.song-pick-row { display: flex; align-items: center; gap: 8px; }

.song-pick-row .song-pick-btn { flex: 1; min-width: 0; }

.song-pick-clear {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-soft);
    border: none;
    border-radius: 12px;
    color: var(--ink-soft);
    cursor: pointer;
    transition: background 0.15s;
  }

.song-pick-clear:active { background: #e8e0d0; color: var(--ink); }

/* Song search modal (Host Picks mode) */

.song-search-head {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 0 24px 14px;
    flex-shrink: 0;
  }

.song-search-head .fb-title { margin: 0; }

.song-hint-row { padding: 18px 24px; color: var(--ink-soft); font-size: 14px; }

.song-row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 16px 12px 24px;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    transition: background 0.15s;
  }

.song-row:last-child { border-bottom: none; }

.song-row:active { background: var(--bg-soft); }

.song-row-art {
    width: 48px;
    height: 48px;
    border-radius: 10px;
    flex-shrink: 0;
    background: var(--bg-soft);
    object-fit: cover;
  }

.song-row-info { flex: 1; min-width: 0; }

.song-row-title {
    font-size: 15px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

.song-row-artist {
    font-size: 13px;
    color: var(--ink-soft);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    margin-top: 2px;
  }

.song-row-play {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-soft);
    border: none;
    border-radius: 50%;
    color: var(--ink);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
  }

.song-row-play:active { background: #e8e0d0; }

.song-row-play.playing { background: var(--accent-teal); color: #fff; }

/* --- Song groups: builder + My Groups rows --- */

.song-row-add {
    flex-shrink: 0;
    width: 26px; text-align: center;
    font-size: 22px; font-weight: 700; line-height: 1;
    color: var(--accent-teal);
  }

.song-row.added .song-row-add { color: var(--ink-soft); }

.song-row-remove {
    flex-shrink: 0;
    width: 32px; height: 32px;
    border: none; border-radius: 50%;
    background: var(--bg-soft); color: var(--ink-soft);
    font-size: 20px; line-height: 1; cursor: pointer;
  }

.song-row-remove:active { background: #e8e0d0; }

.group-builder-title { font-size: 17px; font-weight: 700; color: var(--ink); }

/* Column so the song list can absorb whatever height the sheet has left;
     min-height:0 lets it actually shrink instead of forcing the sheet taller. */

.group-builder-body {
    padding: 8px 24px 10px;
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
  }

/* Search box: leading magnifier + trailing clear button. */

.group-search-wrap { position: relative; }

.group-search-icon {
    position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
    color: var(--ink-soft); pointer-events: none;
  }

.group-search-field { padding-left: 40px !important; padding-right: 40px !important; margin: 0 !important; }

/* Suppress the browser's built-in search clear so only our custom ✕ shows. */

.group-search-field::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.group-search-clear {
    position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
    width: 30px; height: 30px; border: none; background: none; color: var(--ink-soft);
    cursor: pointer; display: flex; align-items: center; justify-content: center;
  }

/* An explicit display above beats [hidden]; restore hide-when-empty behaviour. */

.group-search-clear[hidden] { display: none; }

/* Middle area: search results OR the picked-songs list (one at a time). */

.group-mid { flex: 1; min-height: 0; overflow-y: auto; margin: 10px 0; }

/* Count line under the search box: "N songs" plus, while short, the minimum
     hint ("3 songs | Add at least 4 songs"). */

.group-count-row {
    display: flex;
    align-items: baseline;
    padding: 2px 2px 6px;
  }

.group-count-row:not(:has(:not([hidden]))) { display: none; }

.group-results-count { font-size: 13px; font-weight: 600; color: var(--ink-soft); }

.group-min-hint::before { content: '|'; margin: 0 8px; opacity: 0.45; }

.group-results-count[hidden] + .group-min-hint::before { content: none; }

.group-selected-list .song-row, #group-search-results .song-row { padding-left: 4px; padding-right: 4px; }

.group-selected-list:empty::after {
    content: 'No songs yet — search above to add.';
    display: block; padding: 16px 4px; color: var(--ink-soft); font-size: 13px; text-align: center;
  }

.group-name-field { margin: 0 !important; }

.group-min-hint { font-size: 12px; color: var(--ink-soft); }

/* Footer: wide Save + a trash button, plus a full-width sign-in link below
     (signed-out hosts only — a shortcut to keep the group on an account). */

.group-footer { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; }

.group-signin-link {
    width: 100%;
    border: none;
    background: none;
    cursor: pointer;
    font-family: inherit;
    font-size: 14px;
    color: var(--ink-soft);
    text-decoration: underline;
    text-underline-offset: 3px;
    padding: 6px 0 0;
  }

.group-signin-link[hidden] { display: none; }

.group-signin-link:active { color: var(--ink); }

.group-footer .cat-done { flex: 1; }

.group-trash {
    flex-shrink: 0; width: 54px;
    border: none; border-radius: 16px; cursor: pointer;
    background: #f7e4e4; color: #c0392b;
    display: flex; align-items: center; justify-content: center;
  }

.group-trash:active { background: #f0d4d4; }

/* Edit pencil on a saved-group row (mirrors .cat-check placement). */

.group-edit {
    position: absolute; right: 16px; top: 50%; transform: translateY(-50%);
    width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
    border-radius: 50%; color: var(--ink-soft); cursor: pointer;
  }

.cat-row.selected .group-edit { color: var(--ink-on-dark); }

.group-edit:active { background: rgba(0,0,0,0.08); }

.group-create .cat-row-title { color: var(--accent-teal); }

/* Small centred choice sheets shown to signed-out hosts: "Group Created!"
     (keep it or stay a guest) and "Lose your song group?" on the way out.
     Both are one heading block over a primary and a secondary action. */

.choice-sheet {
    max-width: 340px;
    /* Less top room than the old emoji needed: the success illustration
       carries its own whitespace around the confetti. */
    padding: 32px 24px 24px;
    text-align: center;
  }

/* Icon, title and subtitle move as one block, so the gap down to the buttons
     is set once here instead of riding on whichever element happens to be last. */

.choice-head { margin-bottom: 40px; }

.choice-title { margin: 12px 0 4px; font-size: 22px; font-weight: 700; }

.choice-sub { margin: 0; font-size: 14px; color: var(--ink-soft); }

.choice-sheet .cat-done { margin: 0; }

.choice-note {
    margin: 8px 0 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--ink-soft);
  }

.choice-secondary {
    width: 100%;
    margin-top: 18px;
    border: 1px solid var(--border);
    border-radius: 16px;
    background: none;
    cursor: pointer;
    font-family: inherit;
    font-size: 16px;
    font-weight: 600;
    color: var(--ink);
    padding: 13px 20px;
  }

.choice-secondary:active { background: rgba(0,0,0,0.05); }

/* Success illustration, only on the "Group Created!" sheet. */

.group-saved-check { display: block; width: 120px; height: auto; margin: 0 auto; }

/* One-time "new mode" nudge in the lobby, pointing up at the mode picker
     (host only). Same look as .cat-hint; tap to dismiss. */

.mode-section { position: relative; }

.music-section { position: relative; }

.mode-hint {
    position: absolute;
    top: calc(100% + 6px);
    left: 4px;
    z-index: 10;
    max-width: 264px;
    background: var(--card-active);
    color: var(--ink-on-dark);
    font-size: 13.5px;
    font-weight: 600;
    line-height: 1.35;
    padding: 10px 14px;
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.18);
    cursor: pointer;
    animation: catHintIn 0.28s ease-out;
  }

.mode-hint[hidden] { display: none; }

.mode-hint::before {
    content: '';
    position: absolute;
    top: -5px;
    left: 28px;
    width: 12px;
    height: 12px;
    background: var(--card-active);
    transform: rotate(45deg);
    border-radius: 2px;
  }

/* Host share-code screen: the boxes are display divs (not inputs), so they
     need flex centering and a copy cursor. Scoped to #share-code-boxes so
     these rules no longer leak onto the join-screen inputs above. */

.cat-group-hint {
    font-size: 13px;
    line-height: 1.4;
    color: var(--ink-soft);
    padding: 12px 24px 14px;
    border-bottom: 1px solid var(--border);
  }

/* Sticky footer that commits the multi-selection. */

.cat-done:disabled { opacity: 0.4; cursor: default; }
