/* ============================================================
   U1 room shell — ported from docs/design (Button, ChannelHeader,
   NowPlayingHero, ArtworkSlot, EqBars, SyncStatus, TabBar, Card).
   Rules here intentionally override the legacy room markup.
   ============================================================ */

/* Button.jsx: sans, sentence case, pill, hard shadow */
.button{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:var(--space-2);
  font-family:var(--font-sans);
  font-weight:700;
  letter-spacing:-.01em;
  border:var(--stroke) solid var(--border);
  border-radius:var(--radius-pill);
  cursor:pointer;
  transition:box-shadow 140ms var(--ease-snap),transform 140ms var(--ease-snap)
}
.button[hidden]{display:none}
.button-primary{min-height:44px;padding:0 var(--space-5);background:var(--text);color:var(--bg);box-shadow:2px 2px 0 var(--shadow-ink);font-size:15px}
.button-primary:hover{transform:translate(-1px,-1px);box-shadow:var(--shadow-hard)}
.button-primary:active{transform:translate(3px,3px);box-shadow:1px 1px 0 var(--shadow-ink)}
.button-primary[disabled]{opacity:.4;cursor:not-allowed;transform:none;box-shadow:2px 2px 0 var(--shadow-ink)}
.button-secondary{min-height:44px;padding:0 var(--space-5);background:var(--surface);color:var(--text);box-shadow:2px 2px 0 var(--shadow-ink);font-size:var(--text-sm)}
.button-secondary:hover{transform:translate(-1px,-1px);box-shadow:var(--shadow-hard)}
.button-secondary:active{transform:translate(3px,3px);box-shadow:1px 1px 0 var(--shadow-ink)}
.primary{border:var(--stroke) solid var(--border);background:var(--text);color:var(--bg);font-family:var(--font-sans);font-weight:700;border-radius:var(--radius-pill);box-shadow:2px 2px 0 var(--shadow-ink)}
.primary:hover{transform:translate(-1px,-1px);box-shadow:var(--shadow-hard)}

/* ChannelHeader */
.channel-header{position:relative;display:flex;align-items:center;gap:var(--space-4);padding:14px 20px;background:var(--surface);border-bottom:var(--stroke-bold) solid var(--border);margin:0 0 var(--space-5)}
.channel-wordmark{font-family:var(--font-display);font-weight:800;font-size:var(--text-xl);letter-spacing:-.035em;white-space:nowrap;flex:0 0 auto}
.channel-header .host-avatar{width:44px;height:44px;background:var(--accent);color:var(--on-accent);border:var(--stroke) solid var(--border)}
.channel-copy{flex:1;min-width:0}
.channel-name{display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;font:800 var(--text-xl)/1.12 var(--font-display);letter-spacing:-.035em}
.channel-meta{display:flex;align-items:baseline;gap:6px;font:var(--text-xs) var(--font-mono);color:var(--text-faint);letter-spacing:.04em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.channel-actions{display:flex;align-items:center;gap:var(--space-2);margin-left:auto;flex:0 0 auto}
.icon-button{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:40px;
  height:40px;
  padding:0;
  color:var(--text);
  background:var(--surface);
  border:var(--stroke) solid var(--border);
  border-radius:var(--radius-pill);
  box-shadow:2px 2px 0 var(--shadow-ink);
  cursor:pointer;
  transition:box-shadow 140ms var(--ease-snap),transform 140ms var(--ease-snap)
}
.icon-button svg{width:18px;height:18px}
.icon-button:hover{transform:translate(-1px,-1px);box-shadow:var(--shadow-hard)}
.icon-button:active{transform:translate(3px,3px);box-shadow:1px 1px 0 var(--shadow-ink)}
.icon-button[hidden]{display:none}
.signed-in-chip{padding:0;overflow:hidden}
.signed-in-chip .signed-in-avatar,.signed-in-avatar{display:block;width:36px;height:36px;border-radius:var(--radius-pill);background-color:var(--bg-sunken);background-size:cover;background-position:center}
.account-menu{position:absolute;z-index:7;top:calc(100% + 4px);right:20px;display:flex;flex-direction:column;gap:var(--space-3);min-width:190px;padding:var(--space-3);background:var(--surface);border:var(--stroke) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-hard)}
.account-menu[hidden]{display:none}
.account-menu .signed-in-meta{display:flex;flex-direction:column;gap:2px}
.probe-badge{font:700 var(--text-xs) var(--font-mono);letter-spacing:.1em;text-transform:uppercase;color:var(--text-faint);border:var(--stroke) solid var(--border-soft);border-radius:var(--radius-pill);padding:1px 7px}
.probe-badge[hidden]{display:none}

/* MediaFrame + track block (Liner NowPlaying / MediaFrame) */
.listen-card:after{content:none}
.listen-card{padding:var(--space-5)}
.media-frame{background:var(--lr-card);border-radius:var(--lr-radius-card);padding:10px;box-shadow:var(--lr-shadow-card)}
.media-stage{position:relative;margin:0 auto;width:100%;max-width:420px;aspect-ratio:1/1;max-height:420px;border-radius:var(--lr-radius-media);background:#0E0D0C;overflow:hidden;display:flex;align-items:center;justify-content:center}
.media-stage[data-presentation="video"]{max-width:100%;aspect-ratio:16/9;min-height:200px}
#youtube-slot{position:absolute;inset:0;overflow:hidden}
#youtube-slot[hidden]{display:none}
.youtube-player{width:100%;height:100%;margin:0;border:0;background:#0E0D0C}
/* The embed replaces this node with an iframe of the same id. Key the fill to the container, so it holds even if the
   API ever drops the class or sets a pixel size: the player fills a Wide frame and centres in a Square one. */
#youtube-slot iframe{display:block;width:100%!important;height:100%!important;border:0;background:#0E0D0C}
.youtube-player[hidden]{display:none}
.generated-player{display:none}
.artwork-image{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.artwork-source{position:absolute;left:10px;bottom:10px;padding:4px 8px;border-radius:var(--lr-radius-pill);background:rgba(0,0,0,.55);color:#FFF8F2;font-family:var(--lr-font-ui);font-size:12px;font-weight:600;text-decoration:none}
#soundcloud-slot{display:none;margin-top:var(--space-4)}
#soundcloud-slot:has(.soundcloud-player:not([hidden])){display:block}
.soundcloud-player{width:100%;height:166px;margin:0;border:0;background:#0E0D0C}
.soundcloud-player[hidden]{display:none}
.track-block{margin-top:var(--lr-space-6)}
#room-title{margin:0}
#now-title{display:block;font-family:var(--lr-font-display);font-weight:800;font-size:52px;line-height:.92;letter-spacing:-.045em;color:var(--lr-ink);text-wrap:balance;overflow-wrap:break-word}
#now-title[data-size="lg"]{font-size:64px}
#now-title[data-size="xl"]{font-size:84px}
#now-title[data-size="off"]{font-size:64px}
.hero-artist{margin:8px 0 0;font-family:var(--lr-font-ui);font-size:26px;font-weight:500;color:var(--lr-ink-2);text-wrap:pretty}
.hero-artist:empty{display:none}
.playhead{margin-top:22px;display:grid;grid-template-columns:auto minmax(0,1fr) auto auto auto;gap:18px;align-items:center;font-family:var(--lr-font-time);font-size:17px;font-variant-numeric:tabular-nums;color:var(--lr-ink)}
.playhead[hidden]{display:none}
.playhead .phase-line{display:block;width:100%;min-width:0}
.playhead .phase-line canvas{display:block;width:100%;height:52px}
#timeline-remaining{color:var(--lr-ink-3)}
.round-button{
  width:48px;
  height:48px;
  flex:none;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  padding:0;
  border-radius:50%;
  border:1.5px solid var(--lr-rule-3);
  background:var(--lr-card);
  color:var(--lr-ink);
  cursor:pointer;
  transition:background var(--lr-dur-ui),color var(--lr-dur-ui),border-color var(--lr-dur-ui)
}
.round-button svg{width:22px;height:22px}
.round-button[aria-pressed="true"]{background:var(--lr-ink);border-color:var(--lr-ink);color:var(--lr-page)}
.round-button:disabled{opacity:.5;cursor:wait}
.mute-toggle .mute-cross{display:none}
.mute-toggle[aria-pressed="true"] .mute-cross{display:inline}
.mute-toggle[aria-pressed="true"] .mute-waves{display:none}
.host-pause{display:none}
/* The listener's own pause: two bars while playing, a triangle once paused (the room never pauses with it). */
.listener-pause .play-triangle{display:none}
.listener-pause[data-paused="true"] .pause-bars{display:none}
.listener-pause[data-paused="true"] .play-triangle{display:inline}

/* The first-time pause card (the one onboarding exception): anchored under the pause button by room-view.mjs,
   fixed so no ancestor's overflow can clip it, and always below the playhead row — never over the player. */
.pause-hint{
  position:fixed;
  z-index:7;
  display:flex;
  flex-direction:column;
  gap:6px;
  width:min(300px,calc(100vw - 32px));
  padding:14px 16px;
  border:1.5px solid var(--lr-rule-2);
  border-radius:var(--lr-radius-card-m);
  background:var(--lr-card);
  color:var(--lr-ink);
  box-shadow:var(--lr-shadow-card);
  text-align:left
}
.pause-hint[hidden]{display:none}
.pause-hint-title{margin:0;font:800 16px/1.2 var(--lr-font-display);letter-spacing:-.02em}
.pause-hint-body{margin:0;font:400 14px/1.4 var(--lr-font-ui);color:var(--lr-ink-2)}
.pause-hint-button{align-self:flex-start;min-height:40px;padding:0 16px;margin-top:2px;border:1.5px solid var(--lr-ink);border-radius:999px;background:var(--lr-ink);color:var(--lr-page);font:600 14px var(--lr-font-ui);cursor:pointer}
@media (prefers-reduced-motion: reduce){.pause-hint{transition:none;animation:none}}

/* SyncStatus row: shown only when it carries information (never while synced). */
.sync-status{display:flex;align-items:center;gap:20px;padding-top:22px;border-top:1px solid var(--lr-rule)}
.sync-status[hidden]{display:none}
.sync-glyph{width:40px;flex:none}
.sync-glyph canvas{display:block;width:40px;height:16px}
.sync-status-copy{display:flex;flex-direction:column;gap:3px;flex:1;min-width:0;overflow-wrap:anywhere}
.sync-title{font-family:var(--lr-font-display);font-weight:800;font-size:26px;line-height:1.1;letter-spacing:-.02em;color:var(--lr-ink)}
.sync-detail{font-family:var(--lr-font-ui);font-size:17px;color:var(--lr-ink-2)}
.sync-match{display:none}
/* The compact aside copy of the status (stage 4 retires it) keeps the legacy glyph and text styling. */
.sync-icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;flex:0 0 auto;color:var(--text-faint)}
.sync{font-family:var(--lr-font-display);font-weight:800;font-size:15px;letter-spacing:-.02em;text-transform:none}
.sync-copy{font-size:var(--text-sm);color:var(--text-muted)}
.sync-provider{font:700 var(--text-xs) var(--font-mono);letter-spacing:.1em;text-transform:uppercase;color:var(--text-faint);white-space:nowrap}
.sync-primary{
  min-height:60px;
  padding:0 26px;
  border:0;
  border-radius:var(--lr-radius-pill);
  background:var(--lr-red);
  color:var(--lr-on-red);
  font-family:var(--lr-font-ui);
  font-size:16px;
  font-weight:600;
  box-shadow:var(--lr-shadow-press);
  transition:transform var(--lr-dur-press),box-shadow var(--lr-dur-press)
}
.sync-primary:active{transform:translateY(2px);box-shadow:0 1px 0 var(--lr-red-deep)}
.sync-primary[hidden]{display:none}

/* Phone: the track block steps the title down (48 / 38 / 32) and the status becomes a card with a full-width
   primary button. The host's pause button sits before mute on the playhead row. */
@media (max-width:719px),(max-height:559.98px){
.media-stage{max-width:100%}
/* Square: the frame hugs a square player at every phone width. The stage stays 1:1 (the base max-height cap made it a
   wide box past ~440px, so the player no longer matched the frame) and the MediaFrame shrinks to the square. */
.media-stage[data-presentation="music"]{max-width:420px;max-height:420px}
.media-frame:has(.media-stage[data-presentation="music"]){width:min(100%,440px);margin-left:auto;margin-right:auto}
#now-title{font-size:32px}
#now-title[data-size="lg"]{font-size:38px}
#now-title[data-size="xl"]{font-size:48px}
#now-title[data-size="off"]{font-size:38px}
.hero-artist{font-size:20px}
.track-block{margin-top:var(--lr-space-5)}
.playhead{margin-top:16px;grid-template-columns:auto minmax(0,1fr) auto auto auto auto;gap:12px;font-size:15px}
.playhead .phase-line canvas{height:40px}
/* 200% phone portrait (a 195px viewport): elapsed + timeline + remaining + two or three 44px buttons cannot share
   one row (225px and 279px minimums), so the row becomes two: clock, timeline, remaining / transport buttons. */
@media (max-width:319px){.playhead{grid-template-columns:auto minmax(0,1fr) auto;row-gap:10px}}
.round-button{width:44px;height:44px}
.round-button svg{width:20px;height:20px}
.host-pause:not([hidden]){display:inline-flex}
.sync-status{margin-top:20px;padding:16px;border:0;border-radius:var(--lr-radius-card-m);background:var(--lr-card);box-shadow:var(--lr-shadow-card);display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:4px 14px}
.sync-title{font-size:23px}
.sync-detail{font-size:15px}
.sync-primary{grid-column:1 / -1;width:100%;margin-top:10px}
}

/* Claim card (Card.jsx) */
.claim-slot:empty{display:none}
.claim-card{margin:0 0 var(--space-5);padding:var(--space-5);background:var(--surface);border:var(--stroke) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-hard);display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-2)}
.claim-card[hidden]{display:none}
.claim-card h2{margin:0;font:800 var(--text-2xl)/.96 var(--font-display);letter-spacing:-.035em}
.claim-card p{margin:0 0 var(--space-2);color:var(--text-muted)}

/* CountdownBanner: phone stacks time, title, copy */
.countdown{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-2) var(--space-3)}
.countdown-time{float:none;order:1}
.countdown-body{flex:1;min-width:200px;order:2}
.countdown-body strong{display:block;margin:0}
.countdown-body p{margin:4px 0 0}

/* Tracklist: the design's TrackRow — number, artwork, title over artist, Support pill */
.tracklist-wrap{display:block}
.tracklist-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) 0 var(--space-2)}
.tracklist{list-style:none;padding:0;margin:0;display:grid;gap:var(--space-1)}
.tracklist-row{display:flex;align-items:center;gap:var(--space-3);min-height:var(--tap-min,44px);padding:var(--space-2);border-radius:var(--radius-md);background:transparent}
.tracklist-index{width:24px;flex:0 0 auto;text-align:center;font:700 var(--text-sm) var(--font-mono);color:var(--text-faint)}
.tracklist-art{width:44px;height:44px;flex:0 0 auto;overflow:hidden;border:var(--stroke) solid var(--border);border-radius:var(--radius-md);background:repeating-linear-gradient(135deg,var(--bg-sunken) 0 4px,var(--border-soft) 4px 8px)}
.tracklist-art img{display:block;width:100%;height:100%;object-fit:cover}
.tracklist-copy{min-width:0;flex:1;display:flex;flex-direction:column;gap:1px}
.tracklist-title{font:700 var(--text-sm) var(--font-sans);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tracklist-artist{color:var(--text-faint);font-size:var(--text-sm);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tracklist-actions{display:flex;gap:var(--space-2);align-items:center;flex:0 0 auto}
.tracklist-support{min-height:30px;padding:0 var(--space-3);font-size:var(--text-xs)}
.tracklist-link{color:var(--text-muted);font:700 var(--text-xs) var(--font-mono);letter-spacing:.06em;text-decoration:underline;text-underline-offset:3px}
.tracklist-link:hover,.tracklist-link:focus{color:var(--accent)}
.tracklist-empty{margin:var(--space-3) 0;color:var(--text-muted);font:var(--text-xs) var(--font-mono)}


/* TabBar: icon above label, active icon in a volt pill */
.mobile-tab{flex-direction:column;gap:4px;min-width:0;padding:var(--space-2) 0}
.mobile-tab[hidden]{display:none}
.mobile-tab .mobile-tab-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;width:40px;height:26px;border:var(--stroke) solid transparent;border-radius:var(--radius-pill);font:inherit}
.mobile-tab .mobile-tab-icon svg{width:18px;height:18px}
.mobile-tab.active .mobile-tab-icon{border-color:var(--border);background:var(--accent-2);color:var(--on-accent-2)}
.mobile-tab .mobile-unread{position:absolute;top:-5px;right:-3px;display:none;min-width:16px;height:16px;padding:0 4px;border-radius:var(--radius-pill);background:var(--accent);color:var(--on-accent);font:700 var(--text-xs) var(--font-mono);align-items:center;justify-content:center}
.mobile-tab .mobile-unread:not([hidden])[data-count],.mobile-tab .mobile-unread:not([hidden]){display:inline-flex}

/* Leaks: a listener never sees host controls on any tab */
#host-controls[hidden]{display:none!important}

@media(max-width:790px){
  .channel-header{gap:var(--space-2);margin-bottom:var(--space-4)}
  .channel-wordmark{display:none}
  .channel-name{font-size:var(--text-lg)}
}
@media (max-width:719px),(max-height:559.98px){
/* Phone layout rules now live in app/styles/09-communal-phone.css (Change A, "Communal mobile layout"). The desktop
   bundle only carries rules common to every breakpoint. */
}

/* Desktop room (#160): CJ 2026-10-09 chose a full-width video over the one-screen cap. The 16:9 video stage fills
   the panel's width (width:100%, aspect-ratio:16/9, no max-height cap, no width:auto) and neither the card nor the
   media frame shrinks, so the stage always stays inside its frame; a short window scrolls inside .room-main
   (overflow-y:auto) instead of squeezing the room onto one screen. Music keeps its square 420px stage. The sync
   glyph is hidden here: the playhead's phase line already shows sync state. This file loads before 05/06, so #live
   raises the rail selector above 05's height:100vh. */
@media (min-width:720px) and (min-height:560px){
  .room-main{max-height:calc(100dvh - 140px);overflow-y:auto;display:flex;flex-direction:column}
  .room-main > #countdown-banner,.room-main > .claim-slot:empty,.room-main > #backstage[hidden],.room-main > #host-controls[hidden]{display:none}
  .room-main > #listen-card{flex:0 0 auto;display:flex;flex-direction:column}
  .room-main > #host-controls:not([hidden]){flex:0 0 auto}
  #listen-card > .media-frame{flex:0 0 auto}
  #listen-card > .track-block,#listen-card > .sync-status-slot,#listen-card > #soundcloud-slot{flex:0 0 auto}
  .sync-glyph{display:none}
  .media-stage[data-presentation="video"]{width:100%;aspect-ratio:16/9;min-height:200px;max-height:none}
  #live .room-aside{height:auto;max-height:calc(100dvh - 140px)}
  #live .room-aside .chat-body{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden}
  #live .room-aside .aside-tracklist{max-height:min(44vh,320px)}
}


