/* Patterns.
 *
 * Jukebox-shaped compositions built out of primitives. Same no-literal-colours
 * rule as primitives.css. Every one of these appears in all three source
 * designs; the differences between those designs live in skins/, not here.
 */

/* ------------------------------------------------------------ visualizer */

/* width/flex are explicit because the bars are all `flex: 1 1 0`, giving the
   container a min-content width of nearly nothing. Dropped into a flex row it
   would otherwise collapse to a sliver instead of filling the space. */
.rk-viz {
  display: flex;
  align-items: flex-end;
  gap: var(--viz-gap);
  width: 100%;
  flex: 1 1 auto;
  min-width: 0;
  height: var(--rk-viz-height, 100%);
  min-height: 32px;
  padding: var(--space-1);
}

.rk-viz__bar {
  flex: 1 1 0;
  height: 100%;
  background: var(--viz-gradient);
  border-radius: var(--viz-radius);
  transform-origin: bottom;
  transform: scaleY(var(--viz-floor));
  animation: rk-eq var(--rk-bar-period, var(--viz-period))
             var(--ease) var(--rk-bar-delay, 0ms) infinite;
}

/* --------------------------------------------------------------- marquee */

.rk-marquee {
  display: flex;
  align-items: center;
  overflow: hidden;
  white-space: nowrap;
  min-width: 0;
}

.rk-marquee__track {
  display: flex;
  flex: 0 0 auto;
  animation: rk-marquee var(--marquee-duration) linear infinite;
}

.rk-marquee--chrome {
  height: var(--chrome-height);
  padding: 0 var(--space-2);
  background: var(--chrome-bg);
}

.rk-marquee--chrome .rk-marquee__item { color: var(--chrome-ink); }

.rk-marquee__item {
  padding-inline-end: var(--space-6);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  letter-spacing: var(--title-tracking);
  color: var(--accent);
}

/* ------------------------------------------------------------------- art */

.rk-art {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  width: var(--rk-art-size, 62px);
  background-color: var(--art-bg);
  background-image: var(--art-texture);
  border-radius: var(--art-radius);
  overflow: hidden;
}

.rk-art__disc {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--art-radius);
  animation: var(--art-spin);
}

.rk-art__ring {
  position: absolute;
  width: 52%;
  aspect-ratio: 1;
  border-radius: var(--edge-radius-pill);
  background: var(--art-label);
}

.rk-art__label {
  position: relative;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  color: var(--art-ink);
}

/* A record's spindle. Skins whose art is a square sleeve set --art-spindle and
   --art-hole to transparent, so the same element simply stops being visible --
   no display toggle, no skin-specific selector. */
.rk-art__spindle {
  position: absolute;
  width: 19%;
  aspect-ratio: 1;
  border-radius: var(--edge-radius-pill);
  background: var(--art-spindle);
}

.rk-art__hole {
  position: absolute;
  width: 5%;
  aspect-ratio: 1;
  border-radius: var(--edge-radius-pill);
  background: var(--art-hole);
}

/* ----------------------------------------------------------- now playing */

.rk-now {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
}

.rk-now__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  flex: 1 1 auto;
}

.rk-now__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--title-weight);
  letter-spacing: var(--title-tracking);
  color: var(--ink-primary);
}

.rk-now__artist { color: var(--ink-secondary); font-size: var(--text-sm); }

.rk-now__eq {
  flex: 0 0 auto;
  width: 26px;
  height: 22px;
}

.rk-now__progress {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-readout);
  font-size: var(--text-md);
  font-variant-numeric: tabular-nums;
  color: var(--ink-muted);
}

/* ----------------------------------------------------------------- queue */

.rk-queue { display: flex; flex-direction: column; gap: var(--row-gap); min-width: 0; }

/* Dense mode is the playlist-window look: zero gap, full-bleed rows, no
   per-row border. Both source pixel skins use it; cantina uses the airy
   default. It is a modifier rather than a skin override so any skin can pick. */
.rk-queue--dense { gap: 0; }

.rk-queue__row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--row-height);
  padding: 0 var(--space-3);
  background: var(--surface-row);
  color: var(--ink-on-row);
  border-radius: var(--edge-radius-sm);
  min-width: 0;
}

.rk-queue--dense .rk-queue__row {
  min-height: 34px;
  border-radius: 0;
  font-family: var(--font-readout);
  font-size: var(--text-lg);
}

.rk-queue__row--active {
  background: var(--surface-row-active);
  color: var(--ink-on-active-row);
}

.rk-queue__row--active .rk-queue__artist,
.rk-queue__row--active .rk-queue__duration { color: var(--ink-on-active-row); }

.rk-queue__index {
  flex: 0 0 auto;
  width: 24px;
  font-family: var(--font-readout);
  font-size: var(--text-lg);
  font-variant-numeric: tabular-nums;
  color: var(--ink-on-row-dim);
}

.rk-queue__row--active .rk-queue__index { color: var(--ink-on-active-row); }

.rk-queue__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.rk-queue--dense .rk-queue__text { flex-direction: row; gap: var(--space-2); align-items: baseline; }

.rk-queue__title  { font-size: var(--text-md); font-weight: 600; }
.rk-queue--dense .rk-queue__title { font-weight: 400; font-size: inherit; }
.rk-queue__artist { font-size: var(--text-sm); color: var(--ink-on-row-dim); }
.rk-queue--dense .rk-queue__artist { font-size: var(--label-size);
                                     font-family: var(--font-label); }

.rk-queue__duration {
  flex: 0 0 auto;
  /* Five characters wide whether or not the length is known yet -- the width
     the "--:--" placeholder used to hold open. A song whose duration arrives
     later must not reflow the row under the eyes reading it. */
  min-width: 5ch;
  text-align: right;
  font-family: var(--font-readout);
  font-variant-numeric: tabular-nums;
  color: var(--ink-on-row-dim);
  font-size: var(--text-md);
}

.rk-queue__actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-1); flex: 0 0 auto; }

.rk-queue__empty {
  padding: var(--space-4);
  color: var(--ink-on-row-dim);
  font-family: var(--font-label);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-align: center;
  text-transform: var(--label-transform);
}

/* Phone rows reserve a second line for moderation controls so the song title
   remains readable instead of collapsing to one or two characters. */
.rk-screen .rk-queue__row {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  gap: var(--space-1) var(--space-2);
  padding-block: var(--space-2);
}

.rk-screen .rk-queue__index { grid-column: 1; grid-row: 1 / span 2; }
.rk-screen .rk-queue__text { grid-column: 2; }
.rk-screen .rk-queue__duration { grid-column: 3; }
.rk-screen .rk-queue__actions { grid-column: 2 / -1; }

/* ------------------------------------------------------------- transport */

.rk-transport { display: flex; gap: var(--space-1); }
.rk-transport .rk-button { flex: 1 1 0; }

/* ---------------------------------------------------------------- search */

.rk-search {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--control-height);
  padding: 0 var(--space-3);
  background: var(--surface-sunken);
  border-style: solid;
  border-width: var(--edge-width);
  border-top-color: var(--edge-inset-top);
  border-left-color: var(--edge-inset-left);
  border-right-color: var(--edge-inset-right);
  border-bottom-color: var(--edge-inset-bottom);
  border-radius: var(--control-radius);
  color: var(--ink-muted);
}

.rk-search__input {
  flex: 1 1 auto;
  min-width: 0;
  color: var(--ink-primary);
  font-size: var(--text-md);
}

.rk-search__input::placeholder { color: var(--ink-muted); }

.rk-search:focus-within {
  box-shadow: var(--focus-shadow);
  transition: box-shadow var(--motion-fast) var(--ease);
}

.rk-search__input:focus-visible { outline: none; }

.rk-chips { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* ------------------------------------------------------------------- nav */

.rk-nav {
  display: flex;
  justify-content: center;
  background: var(--surface-panel);
  border-top: var(--edge-width) solid var(--edge-hairline);
  /* The other surface that meets the page directly, so it frosts with the
     panels rather than turning into an opaque bar over a glass room. */
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
}

.rk-nav__item {
  position: relative;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: var(--space-2);
  color: var(--ink-muted);
  font-family: var(--font-label);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-transform: var(--label-transform);
  text-decoration: none;
  white-space: nowrap;
}

.rk-nav__item + .rk-nav__item::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 3px;
  height: 3px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--ink-muted);
  opacity: 0.4;
  pointer-events: none;
}

.rk-nav__item[aria-current] { color: var(--accent); }

/* ------------------------------------------------------------ status bar */

.rk-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1) var(--space-2);
  font-family: var(--font-label);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-transform: var(--label-transform);
  color: var(--ink-muted);
  min-width: 0;
}

.rk-status__action { color: var(--accent); flex: 0 0 auto; }

/* ------------------------------------------------------------- join code */

.rk-joincode {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* The details grow to fill a shared row, so this only bites once the code
     wraps below the QR -- the moment the QR would otherwise hug the left edge
     of a row it has to itself, off-centre from the code sitting under it. */
  justify-content: center;
  gap: var(--space-3);
}

.rk-joincode__details {
  flex: 1 1 130px;
  text-align: center;
}

.rk-joincode__code {
  font-family: var(--font-readout);
  font-size: var(--text-xl);
  letter-spacing: 0.12em;
  color: var(--accent);
}

/* Where to type the code, for the guest whose phone will not scan a QR. */
.rk-joincode__address {
  display: block;
  color: var(--ink-muted);
  font-family: var(--font-label);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  overflow-wrap: anywhere;
}

.rk-joincode__qr {
  flex: 0 0 auto;
  display: block;
  width: clamp(128px, 35vw, 180px);
  max-width: 100%;
  aspect-ratio: 1;
  padding: var(--space-2);
  border-radius: var(--edge-radius-sm);
  background-color: var(--readout-ink);
  color: var(--readout-bg);
}

.rk-joincode__qr-image { display: block; width: 100%; height: auto; }

.rk-joincode--tv .rk-joincode__qr { width: clamp(220px, 24vw, 460px); }

/* Narrow enough that a column beside the QR would squeeze both: the QR takes a
   row of its own and the code, label and share button centre under it. */
.rk-joincode--stacked { flex-direction: column; justify-content: center; text-align: center; }
.rk-joincode--stacked .rk-joincode__details { flex: 0 0 auto; align-items: center; }

/* ----------------------------------------------------------- room header */

.rk-roomhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-width: 0;
}

.rk-roomhead__name {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--title-weight);
  letter-spacing: var(--title-tracking);
  text-transform: var(--title-transform);
  color: var(--accent);
}

.rk-people {
  position: relative;
  flex: 0 0 auto;
}

.rk-people__trigger {
  display: block;
  list-style: none;
  border-radius: var(--edge-radius-pill);
  cursor: pointer;
}

.rk-people__trigger::-webkit-details-marker { display: none; }

.rk-people__trigger:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.rk-people[open] .rk-people__trigger {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.rk-people__popup {
  position: absolute;
  z-index: 15;
  top: calc(100% + var(--space-2));
  right: 0;
  width: min(380px, calc(100vw - var(--space-6)));
  padding: var(--space-3);
  background: var(--surface-panel);
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
  border-style: solid;
  border-width: var(--edge-width);
  border-top-color: var(--edge-top);
  border-left-color: var(--edge-left);
  border-right-color: var(--edge-right);
  border-bottom-color: var(--edge-bottom);
  border-radius: var(--edge-radius);
  box-shadow: var(--edge-shadow-float);
}

.rk-people__heading,
.rk-people__identity,
.rk-people__actions {
  display: flex;
  align-items: center;
}

.rk-people__heading {
  justify-content: space-between;
  gap: var(--space-2);
  padding-bottom: var(--space-3);
  border-bottom: var(--edge-width) solid var(--edge-hairline);
}

.rk-people__list {
  display: flex;
  flex-direction: column;
  max-height: min(60vh, 420px);
  margin: 0;
  padding: 0;
  overflow-y: auto;
  list-style: none;
}

.rk-people__member {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-block: var(--space-3);
}

.rk-people__member + .rk-people__member {
  border-top: var(--edge-width) solid var(--edge-hairline);
}

.rk-people__identity { gap: var(--space-2); }

.rk-people__name {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-width: 0;
  overflow-wrap: anywhere;
}

.rk-people__account-link {
  color: var(--ink-primary);
  text-decoration: none;
}

.rk-people__account-link:hover { text-decoration: underline; }

.rk-people__edit-toggle {
  width: calc(var(--control-height) - var(--space-2));
  min-height: calc(var(--control-height) - var(--space-2));
  height: calc(var(--control-height) - var(--space-2));
}

.rk-people__edit-form {
  display: block;
}

.rk-people__edit-form[hidden] { display: none; }
.rk-people__edit-form form {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-2);
}
.rk-people__edit-form .rk-label { grid-column: 1 / -1; }
.rk-people__edit-form .rk-input { min-width: 0; }

.rk-people__actions {
  justify-content: flex-end;
  gap: var(--space-2);
}

.rk-people__actions .rk-button {
  min-height: calc(var(--control-height) - var(--space-2));
  padding-inline: var(--space-2);
}

/* --------------------------------------------------------------- layouts */

.rk-stack   { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.rk-stack--tight { gap: var(--space-2); }
.rk-row     { display: flex; align-items: center; gap: var(--space-3); min-width: 0; }
.rk-row--between { justify-content: space-between; }
/* Basis 0, not auto: a nowrap child (a marquee, a long title) would otherwise
   inflate this item's hypothetical main size and wrap the whole layout. */
.rk-grow    { flex: 1 1 0%; min-width: 0; }
.rk-pad     { padding: var(--space-5); }

.rk-row > .rk-label { flex: 0 0 auto; white-space: nowrap; }

/* A phone-sized frame for previewing the controller surface. */
.rk-device {
  width: min(390px, 100%);
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-panel);
  border: var(--edge-width) solid var(--edge-hairline);
  border-radius: var(--device-radius);
  box-shadow: var(--edge-shadow-float);
  /* Deliberately NOT frosted, though it paints --surface-panel on the page: the
     phone frame *contains* panels, and an element with a backdrop-filter becomes
     a backdrop root, which leaves its descendants nothing to blur. Frosting a
     container silently un-frosts everything inside it. */
}
