/* Primitives.
 *
 * Rule for this file and patterns.css: no literal colours, ever. Every colour,
 * edge, radius and font resolves through a token, which is what lets one set of
 * markup render as a Winamp window under `llama` and as a warm rounded card under
 * `cantina` with no per-skin selector anywhere.
 *
 * The load-bearing idea is the *edge*. A 90s bevel and a flat modern border are
 * the same CSS -- a four-sided border -- differing only in whether the four
 * sides are given the same colour. So the border colours are four separate
 * tokens rather than one:
 *
 *   llama    --edge-top/left: light grey, --edge-right/bottom: near-black,
 *            --edge-radius: 0            -> extruded plastic
 *   cantina  all four the same brown,
 *            --edge-radius: 18px         -> flat card
 *
 * Sunken surfaces reverse the pair (--edge-inset-*), which is the whole trick
 * behind a well looking carved into the panel above it. No skin needs to
 * override a rule to get either result.
 */

/* ------------------------------------------------------------------ page */

.rk-app {
  background-color: var(--bg-page);
  background-image: var(--bg-page-texture);
  color: var(--ink-primary);
  font-family: var(--font-body);
  min-height: 100dvh;
}

/* ------------------------------------------------------------- scrollbar */

/* Every scrolling surface in the app -- the page, the room overlay, the
   landing page's room list -- takes the skin's own colours: the track is the
   sunken face a well is cut from, the thumb is muted ink riding in it.
   --ink-muted rather than a surface token because a thumb has to stay visible,
   and this exact pair is already contracted: contrast_test.rb holds
   --ink-muted on --surface-sunken to 4.5:1 for every skin, so no future skin
   can paint an invisible scrollbar. A raised face would have been the closer
   metaphor and the wrong colour -- against sunken it lands as low as 1.1:1,
   which is no scrollbar at all on blanc.
   `scrollbar-color` is what Chrome and Firefox read; Safari below 18.2 knows
   only the pseudo-elements, so both are stated and kept to the same colours. */

:root {
  scrollbar-color: var(--ink-muted) var(--surface-sunken);
  scrollbar-width: thin;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: var(--surface-sunken);
}

::-webkit-scrollbar-thumb {
  background: var(--ink-muted);
  border: var(--edge-width) solid var(--surface-sunken);
  border-radius: var(--edge-radius-pill);
}

::-webkit-scrollbar-corner { background: var(--surface-sunken); }

/* ----------------------------------------------------------------- panel */

.rk-panel {
  background: var(--surface-panel);
  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);
  /* Panels are the one surface that sits directly on the page, so they are the
     one surface that can frost it. Skins with an opaque --surface-panel set
     --surface-blur: none and pay nothing. */
  -webkit-backdrop-filter: var(--surface-blur);
  backdrop-filter: var(--surface-blur);
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
}

.rk-panel--floating { box-shadow: var(--edge-shadow-float); }

.rk-panel__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--panel-pad);
  min-width: 0;
  flex: 1 1 auto;
}

.rk-panel__body--loose { gap: var(--space-5); padding: var(--space-5); }
.rk-panel__body--tight { gap: var(--space-2); padding: var(--space-2); }
.rk-panel__body--bare  { padding: 0; gap: 0; }

/* Title bar. Present in every skin; its personality is entirely tokens --
   `llama` gets grooved chrome with window buttons pushed right, `cantina` gets a
   centred wordmark and hides the buttons via --chrome-buttons: none. */
.rk-panel__chrome {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  height: var(--chrome-height);
  padding: 0 var(--space-2);
  background: var(--chrome-bg);
  box-shadow: var(--chrome-shadow);
  color: var(--chrome-ink);
  font-family: var(--chrome-font);
  font-size: var(--chrome-size);
  letter-spacing: var(--chrome-tracking);
  text-transform: var(--chrome-transform);
  white-space: nowrap;
}

.rk-panel__chrome-title {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: var(--chrome-text-align);
  gap: var(--space-2);
  text-align: var(--chrome-text-align);
}

.rk-panel__chrome-rail {
  display: var(--chrome-rail-display);
  flex: 1 1 auto;
  height: 8px;
  background-image: var(--chrome-rail);
  background-repeat: repeat-x;
  background-position: center;
}

.rk-panel__chrome-title-text {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  padding: var(--chrome-title-padding);
  border: var(--chrome-title-border);
  border-radius: var(--chrome-title-radius);
  background: var(--chrome-title-bg);
}

/* Rendered only when a panel has behaviour to offer (collapse, close), so
   visibility is a content decision; the skin decides only how they look.
   The decorative always-on set lives solely in the winamp furniture, which
   still reads --chrome-buttons / --chrome-close-display. */
.rk-panel__chrome-buttons {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex: 0 0 auto;
}

/* The face and the target are deliberately two different boxes. A skin that has
   dropped the border and the background has nothing left to enlarge -- growing
   the glyph to thumb size would just be a huge glyph -- so --chrome-button-pad
   grows the hit area instead and `content-box` keeps every painted thing
   (background, image, border) on the --chrome-button-size face inside it. With
   the padding at zero the two boxes coincide, which is what the bitmap skins
   want. */
.rk-panel__chrome-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: content-box;
  width: var(--chrome-button-size);
  height: var(--chrome-button-size);
  padding: var(--chrome-button-pad);
  cursor: pointer;
  text-decoration: none;
  background-color: var(--chrome-button-bg);
  background-origin: content-box;
  background-clip: content-box;
  background-position: center;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  border-style: solid;
  border-width: var(--chrome-button-border-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);
}

.rk-panel__chrome-button--min { background-image: var(--chrome-button-minimize-image); }
.rk-panel__chrome-button--max { background-image: var(--chrome-button-maximize-image); }

/* A window button that changes where the panel lives is a form, not a link,
   and the chrome row is a flex line: without this the form becomes the flex
   item and the button stops sitting with its neighbours. */
.rk-panel__chrome-form { display: contents; }

.rk-panel__chrome-button--close {
  background-color: var(--chrome-close-bg);
  background-image: var(--chrome-button-close-image);
}

/* Drawn rather than typed, so the mark is the same shape at any button size and
   in any of the skins' very different fonts. It paints in currentColor, which is
   how a skin whose button image already carries the glyph switches it off:
   --chrome-button-ink goes transparent and the bitmap underneath is all that is
   left. */
.rk-panel__chrome-glyph {
  width: 100%;
  height: 100%;
  color: var(--chrome-button-ink);
}

/* ------------------------------------------------------------ sunken well */

.rk-well {
  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(--edge-radius-sm);
  min-width: 0;
}

/* --------------------------------------------------------------- readout */

/* The LCD. Under `cantina` this is a lit bar sign rather than a phosphor
   screen -- same element, different --readout-* values. */
.rk-readout {
  background-color: var(--readout-bg);
  background-image: var(--readout-texture);
  color: var(--readout-ink);
  font-family: var(--font-readout);
  text-shadow: var(--readout-glow);
  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(--edge-radius-sm);
  padding: var(--space-2) var(--space-3);
  min-width: 0;
}

.rk-readout__time {
  font-size: var(--text-3xl);
  line-height: 0.85;
  font-variant-numeric: tabular-nums;
  flex: 0 0 auto;
}

.rk-readout__body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1 1 0%;
  min-width: 0;
}

.rk-readout__line {
  font-size: var(--text-lg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rk-readout__meta {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--readout-ink-dim);
  font-family: var(--font-label);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-transform: var(--label-transform);
  text-shadow: none;
}

/* ---------------------------------------------------------------- button */

.rk-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--control-height);
  padding: 0 var(--control-pad);
  background-color: var(--control-face);
  background-image: var(--control-texture);
  background-repeat: repeat-x;
  background-position: center;
  background-size: auto 100%;
  color: var(--control-ink);
  font-family: var(--control-font);
  font-size: var(--control-size);
  letter-spacing: var(--control-tracking);
  text-transform: var(--control-transform);
  border-style: solid;
  border-width: var(--control-border-width);
  border-top-color: var(--control-light);
  border-left-color: var(--control-light);
  border-right-color: var(--control-dark);
  border-bottom-color: var(--control-dark);
  border-radius: var(--control-radius);
  border-image-source: var(--control-frame-image);
  border-image-slice: var(--control-frame-slice);
  border-image-width: var(--control-frame-width);
  border-image-outset: var(--control-frame-outset);
  border-image-repeat: stretch;
  box-shadow: var(--control-shadow);
  text-shadow: var(--control-content-shadow);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--motion-fast) var(--ease),
              color var(--motion-fast) var(--ease),
              filter var(--motion-fast) var(--ease),
              box-shadow var(--motion-fast) var(--ease);
}

.rk-button:hover:not(:disabled):not(:active) {
  filter: var(--control-hover-filter);
  box-shadow: var(--control-shadow-hover);
}

/* Pressing swaps the pair, so the control sinks. */
.rk-button:active {
  background-color: var(--control-face-active);
  border-top-color: var(--control-dark);
  border-left-color: var(--control-dark);
  border-right-color: var(--control-light);
  border-bottom-color: var(--control-light);
  border-image-source: var(--control-frame-image-active);
  box-shadow: var(--control-shadow-active);
  text-shadow: var(--control-content-shadow-active);
}

.rk-button--accent {
  background-color: var(--accent);
  color: var(--ink-on-accent);
}

.rk-button--danger {
  background-color: var(--control-face);
  color: var(--danger);
}

.rk-button--ghost {
  background-color: transparent;
  background-image: none;
  color: var(--ink-secondary);
  border-color: transparent;
  border-image-source: none;
  box-shadow: none;
  text-shadow: none;
}

.rk-button--ghost:hover:not(:disabled):not(:active) {
  background-color: var(--control-ghost-hover-face);
}

.rk-button--block { width: 100%; }

.rk-button--icon {
  padding: 0;
  width: var(--control-height);
  flex: 0 0 auto;
  border-width: var(--control-icon-border-width);
  box-shadow: var(--control-icon-shadow);
}

.rk-button--icon:hover:not(:disabled):not(:active) { box-shadow: var(--control-icon-shadow); }
.rk-button--icon:active { box-shadow: var(--control-icon-shadow-active); }

/* A ghost is unframed at every shape. The icon modifier is declared after the
   variant, so without this its rim wins on source order and hands the ghost the
   face it exists not to have -- visible on any skin whose icon shadow is real. */
.rk-button--ghost.rk-button--icon,
.rk-button--ghost.rk-button--icon:hover:not(:disabled):not(:active) { box-shadow: none; }

/* An anchor cannot carry `disabled`, so a disabled link says so with ARIA and
   drops its href instead; both spellings have to look equally unavailable. */
.rk-button[disabled],
.rk-button[aria-disabled="true"] {
  color: var(--ink-muted);
  cursor: not-allowed;
}

.rk-button__icon {
  flex: 0 0 auto;
  filter: drop-shadow(var(--control-content-shadow));
}

.rk-button:active .rk-button__icon {
  filter: drop-shadow(var(--control-content-shadow-active));
}

/* ----------------------------------------------------------------- badge */

.rk-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  padding: 0 var(--space-2);
  min-height: 22px;
  font-family: var(--font-label);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-transform: var(--label-transform);
  font-weight: var(--label-weight);
  border-radius: var(--edge-radius-sm);
  background: var(--surface-raised);
  color: var(--ink-secondary);
  white-space: nowrap;
}

.rk-badge--accent    { background: var(--accent); color: var(--ink-on-accent); }
.rk-badge--danger    { background: transparent; color: var(--danger);
                       box-shadow: inset 0 0 0 var(--edge-width) var(--danger); }
.rk-badge--positive  { background: transparent; color: var(--positive);
                       box-shadow: inset 0 0 0 var(--edge-width) var(--positive); }
.rk-badge--outline   { background: transparent; color: var(--ink-muted);
                       box-shadow: inset 0 0 0 var(--edge-width) var(--edge-hairline); }

/* A selection code (`B-12`) reads as a jukebox key under cantina and as a
   playlist index under the pixel skins. */
.rk-badge--code {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  min-width: 46px;
  min-height: 34px;
  letter-spacing: 0;
  text-transform: none;
}

/* ----------------------------------------------------------------- meter */

.rk-meter {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  min-width: 0;
  height: var(--meter-thumb-height);
}

.rk-meter__track {
  width: 100%;
  height: var(--meter-height);
  background: var(--meter-track);
  border-radius: var(--meter-radius);
  overflow: hidden;
}

.rk-meter__fill {
  display: block;
  height: 100%;
  width: var(--rk-meter-value, 0%);
  background: var(--meter-fill);
  border-radius: var(--meter-radius);
}

.rk-meter__thumb {
  position: absolute;
  left: var(--rk-meter-value, 0%);
  translate: -50% 0;
  width: var(--meter-thumb-width);
  height: var(--meter-thumb-height);
  background: var(--meter-thumb);
  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(--control-radius);
}

.rk-meter--bare .rk-meter__thumb { display: none; }
.rk-meter--bare { height: var(--meter-height); }

/* ---------------------------------------------------------------- avatar */

.rk-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: 0 0 auto;
  border-radius: var(--edge-radius-pill);
  background: var(--surface-raised);
  color: var(--ink-secondary);
  font-family: var(--font-label);
  font-size: var(--text-xs);
  font-weight: var(--label-weight);
  letter-spacing: 0;
  text-transform: uppercase;
}

.rk-avatar-stack { display: flex; align-items: center; }
.rk-avatar-stack .rk-avatar { margin-inline-start: -8px;
                              box-shadow: 0 0 0 var(--edge-width) var(--edge-hairline); }
.rk-avatar-stack .rk-avatar:first-child { margin-inline-start: 0; }

/* ----------------------------------------------------------------- label */

.rk-label {
  font-family: var(--font-label);
  font-size: var(--label-size);
  letter-spacing: var(--label-tracking);
  text-transform: var(--label-transform);
  font-weight: var(--label-weight);
  color: var(--ink-muted);
}

.rk-label--accent { color: var(--accent); }

.rk-title {
  font-family: var(--font-display);
  font-weight: var(--title-weight);
  letter-spacing: var(--title-tracking);
  text-transform: var(--title-transform);
  color: var(--ink-primary);
  text-wrap: balance;
}

.rk-title--xl { font-size: var(--text-3xl); line-height: 1.05; }
.rk-title--lg { font-size: var(--text-2xl); line-height: 1.1; }
.rk-title--md { font-size: var(--text-xl); line-height: 1.2; }

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

.rk-truncate {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
