/* Music requests. Drawn like an old one-bit desktop: two inks, hard rules,
   windows with title bars, and a banner that never stops running. Anything a
   colour used to say is said with a pattern or by swapping the two inks. */

:root {
  --paper: #000;
  --ink: #fff;
  --dim: #a3a3a3;

  --rule: 2px;
  --frame: 2px;
  --strip: 132px;

  --face: "Segoe UI", Selawik, system-ui, -apple-system, "Helvetica Neue", Roboto, Arial, sans-serif;
  --small: 0.8125rem;

  /* The one-bit greys: a checkerboard, and bars for trouble. */
  --dither: repeating-conic-gradient(var(--ink) 0 25%, var(--paper) 0 50%) 0 0 / 4px 4px;
  --bars: repeating-linear-gradient(var(--ink) 0 3px, var(--paper) 3px 6px);

  color-scheme: dark;
}

:root[data-theme="light"] {
  --paper: #fff;
  --ink: #000;
  --dim: #595959;
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scrollbar-color: var(--ink) var(--paper); }

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--paper);
  color: var(--ink);
  font: 1rem/1.4 var(--face);
}

[hidden] { display: none !important; }

h1, h2, h3, p, ul { margin: 0; }
ul { padding: 0; list-style: none; }
button, input { border-radius: 0; font: inherit; color: inherit; }
button { cursor: pointer; }

::selection { background: var(--ink); color: var(--paper); }

/* Drawn in the text's own ink and set inside the edge, so it shows on either ink. */
:focus-visible { outline: var(--rule) solid currentColor; outline-offset: -5px; }

/* ---- the running banner ---- */

.marquee {
  padding-top: env(safe-area-inset-top);
  border-bottom: var(--frame) solid var(--ink);
  overflow: hidden;
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  user-select: none;
}
.marquee-line { overflow: hidden; }
.marquee-track { display: flex; inline-size: max-content; animation: run-across 60s linear infinite; }
/* Two identical halves: sliding by one of them loops without a seam. */
.marquee-half { display: flex; flex: none; }
.marquee-half > span { flex: none; padding-inline-end: 0.32em; }
.marquee-name { font-size: clamp(3rem, 15vw, 4.5rem); letter-spacing: -0.02em; }
.marquee-news { padding-block: 0 0.35em; font-size: clamp(1.125rem, 5.4vw, 1.5rem); }
.marquee-news b { font-weight: inherit; }

@keyframes run-across { to { transform: translateX(-50%); } }
@keyframes run-up { to { transform: translateY(-50%); } }

/* ---- menu bar ---- */

.menu {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  min-height: 44px;
  padding: 0 max(4px, env(safe-area-inset-right)) 0 max(4px, env(safe-area-inset-left));
  border-bottom: var(--frame) solid var(--ink);
  font-size: var(--small);
  font-weight: 700;
  text-transform: uppercase;
}
.menu-start { display: flex; flex: 1; min-width: 0; }
.menu-side { display: flex; flex: none; }
.menu-item {
  display: flex;
  align-items: center;
  padding: 0 8px;
  border: 0;
  background: none;
  font-weight: inherit;
  text-transform: inherit;
  white-space: nowrap;
}
.menu-clock { display: none; font-variant-numeric: tabular-nums; }
.menu-brand { flex: none; }

/* The name opens a menu that hangs from the bar, as menus did on the real
   thing: the title turns over while it is open and the menu casts a hard shadow. */
.menu-account { position: relative; display: flex; }
.menu-title { gap: 6px; max-width: min(16rem, 52vw); }
.menu-title[aria-expanded="true"] { background: var(--ink); color: var(--paper); }
.menu-user { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.caret { flex: none; width: 10px; height: 10px; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: square; }

.drop {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 10;
  display: grid;
  min-width: 11rem;
  padding: 4px 0;
  border: var(--frame) solid var(--ink);
  background: var(--paper);
  box-shadow: var(--frame) var(--frame) 0 var(--ink);
}
.drop-item {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 16px 0 0;
  border: 0;
  background: none;
  font-weight: inherit;
  text-align: left;
  text-transform: inherit;
  white-space: nowrap;
}
/* Room for a tick by every item, so the words line up; the theme in use gets it. */
.drop-item::before { content: ""; flex: none; width: 28px; text-align: center; }
.drop-item[aria-pressed="true"]::before { content: "\2713"; }
.drop-rule { height: var(--rule); margin: 4px 0; background: var(--dither); }

/* ---- the sombra logo ---- */

/* Drawn in black; turned over to white on the dark side, like everything else. */
.logo { display: block; }
:root:not([data-theme="light"]) .logo { filter: invert(1); }

.sign-off { display: flex; justify-content: center; padding: 0 16px max(96px, calc(env(safe-area-inset-bottom) + 80px)); }
/* Not before the page knows which of its two sides to show. */
#signin[hidden] + #app[hidden] + .sign-off { display: none; }

/* ---- windows ---- */

.desk {
  padding: 8px max(8px, env(safe-area-inset-right)) 24px max(8px, env(safe-area-inset-left));
}

.windows { display: grid; gap: 8px; max-width: 640px; margin: 0 auto; }

.window { min-width: 0; border: var(--frame) solid var(--ink); background: var(--paper); }

/* Title bars stay black in both modes, as they do on the real thing. */
.bar {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
  padding: 0 8px;
  border-bottom: var(--frame) solid var(--ink);
  background: #000;
  color: #fff;
}
.bar-name { overflow: hidden; font-size: 1rem; font-weight: 400; text-overflow: ellipsis; text-transform: lowercase; white-space: nowrap; }
.glyph { flex: none; width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: square; }

.tabs { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); border-bottom: var(--frame) solid var(--ink); }
.tab {
  min-height: 44px;
  border: 0;
  background: var(--paper);
  color: var(--ink);
  font-size: var(--small);
  font-weight: 700;
  text-transform: uppercase;
}
.tab + .tab { border-left: var(--frame) solid var(--ink); }
.tab[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

.pane { padding: 16px 14px 18px; }

/* ---- shared pieces ---- */

.button {
  flex: none;
  min-height: 44px;
  padding: 0 16px;
  border: var(--rule) solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-size: var(--small);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.button:active { background: var(--ink); color: var(--paper); }
.button:disabled { border-color: var(--dim); background: var(--paper); color: var(--dim); cursor: default; }

.plain {
  flex: none;
  min-height: 44px;
  padding: 0 4px;
  border: 0;
  background: none;
  font-size: var(--small);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-thickness: var(--rule);
  text-underline-offset: 4px;
  text-transform: uppercase;
}

.note { padding: 14px; max-width: 52ch; }

/* Buttons for a whole window, at its foot. Tighter than a pane on any screen. */
.pane.actions { display: flex; flex-wrap: wrap; gap: 10px; padding-top: 14px; padding-bottom: 14px; }
.rows:not(:empty) + .actions { border-top: var(--rule) solid var(--ink); }

/* Trouble is the two inks swapped. */
.problem { padding: 8px 12px; background: var(--ink); color: var(--paper); font-weight: 700; }

/* What a request is up to, as how full its band is: empty while it waits its
   turn, grey in the queue, solid once it is moving, barred when it went wrong. */
.band {
  flex: none;
  align-self: stretch;
  width: 14px;
  margin-block: -10px;
  border-right: var(--rule) solid var(--ink);
  background: var(--paper);
}
[data-tone="wait"] > .band { background: var(--dither); }
[data-tone="go"] > .band { background: var(--ink); }
[data-tone="warn"] > .band { background: var(--bars); }

@media (hover: hover) {
  .menu-item:is(button):hover, .drop-item:hover, .button:hover:enabled, .plain:hover, .field-clear:hover { background: var(--ink); color: var(--paper); text-decoration: none; }
  .tab:hover { font-style: italic; }
}

/* ---- sign in ---- */

.dialog { max-width: 440px; margin: clamp(0px, 6vh, 72px) auto 0; }

.site-name { font: italic 700 clamp(2rem, 11vw, 2.75rem)/0.95 var(--face); letter-spacing: -0.01em; text-transform: uppercase; }

.lede { margin-top: 14px; max-width: 44ch; }

.form { display: grid; margin-top: 22px; }
.form label { font-size: var(--small); font-weight: 700; }
.form input {
  width: 100%;
  min-height: 48px;
  margin: 6px 0 18px;
  padding: 0 12px;
  border: var(--rule) solid var(--ink);
  background: var(--paper);
  appearance: none;
}
.form input:focus-visible { outline-offset: 0; }
/* Keeps a remembered password from tinting the box. */
.form input:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  box-shadow: 0 0 0 100px var(--paper) inset;
  caret-color: var(--ink);
}
.form .problem { margin-bottom: 18px; }
.form .button { min-height: 48px; }
.form .button + .button { margin-top: 10px; }
.form .plain { margin-top: 6px; }

/* ---- access requests ---- */

.access .pane { border-bottom: var(--rule) solid var(--ink); }
/* Who is asking and the username they want are read in full, not cut short. */
.access .about > * { overflow-wrap: anywhere; white-space: normal; }
.access .form { max-width: 400px; margin-top: 14px; }

/* ---- the question ---- */

.prompt { font: italic 700 clamp(1.75rem, 8.6vw, 2.5rem)/0.98 var(--face); letter-spacing: -0.01em; text-transform: uppercase; text-wrap: balance; }

.field { display: flex; margin-top: 14px; border: var(--rule) solid var(--ink); }
.field input {
  flex: 1;
  min-width: 0;
  min-height: 52px;
  padding: 0 12px;
  border: 0;
  background: none;
  font-size: 1.125rem;
  outline: none;
  appearance: none;
}
.field input::placeholder { color: var(--dim); opacity: 1; }
.field:focus-within { outline: var(--rule) solid var(--ink); }
.field-clear {
  flex: none;
  padding: 0 12px;
  border: 0;
  border-left: var(--rule) solid var(--ink);
  background: none;
  font-size: var(--small);
  font-weight: 700;
  text-transform: uppercase;
}

.hint { margin-top: 12px; color: var(--dim); font-size: var(--small); max-width: 52ch; }

/* ---- rows: search results and requests ---- */

.results { border-top: var(--rule) solid var(--ink); }

.rows:empty { display: none; }
.rows > li, .opened { display: flex; align-items: center; gap: 12px; padding: 10px 12px; }
.rows > li + li, .note:not([hidden]) + .lists:not(:empty) { border-top: var(--rule) solid var(--ink); }
.requests .rows > li { padding-left: 0; }

/* An opened artist: who it is, then what they have released under a bar for
   each sort, which names the sort and says how many there are. */
.opened { border-bottom: var(--rule) solid var(--ink); }
.opened .title { font: italic 700 1.375rem/1.1 var(--face); letter-spacing: -0.01em; text-transform: uppercase; }
.group {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 5px 12px 6px;
  background: var(--ink);
  color: var(--paper);
  font-size: var(--small);
  font-weight: 700;
  text-transform: uppercase;
}

.cover {
  flex: none;
  width: 56px;
  height: 56px;
  border: var(--rule) solid var(--ink);
  background: var(--dither);
  object-fit: cover;
  filter: grayscale(1) contrast(1.08);
}

.about { flex: 1; min-width: 0; }
.about > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.title { font-weight: 700; }
.more { color: var(--dim); font-size: var(--small); }

.status { margin-top: 3px; font-size: var(--small); white-space: normal; }
[data-tone="warn"] > .about > .status { width: fit-content; padding: 1px 6px 2px; background: var(--ink); color: var(--paper); font-weight: 700; }

/* Once asked for, the button gives way to a plain word. */
.rows .button:disabled { padding: 0; border-color: transparent; font-style: italic; }

/* What can be done with a request, stacked at the end of its row so that on a
   phone its title keeps the room it has. */
.row-actions { display: flex; flex: none; flex-direction: column; align-items: flex-end; margin-block: -10px; }

.strip { height: 12px; margin-top: 8px; border: var(--rule) solid var(--ink); }
.strip > span { display: block; height: 100%; background: var(--ink); transition: width 0.6s steps(6); }

/* ---- requests ---- */

.downloads {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px 10px 0;
  border-bottom: var(--rule) solid var(--ink);
  font-size: var(--small);
}

.toast {
  position: fixed;
  left: 50%;
  bottom: max(16px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: 10px 14px;
  border: var(--rule) solid var(--paper);
  background: var(--ink);
  box-shadow: 0 0 0 var(--rule) var(--ink);
  color: var(--paper);
  font-weight: 700;
}

/* On a phone the search takes the screen; the requests come back when it is cleared. */
@media (max-width: 999.98px) {
  .searching :is(.requests, .access) { display: none; }
}

@media (min-width: 560px) {
  .menu { min-height: 36px; }
  .menu-brand .logo { width: auto; height: 22px; }
  .menu-clock { display: flex; }
  .pane { padding: 22px 20px 24px; }
  .cover { width: 64px; height: 64px; }
}

/* Room for a desktop: the banner stands up along the left edge, reading
   upwards, and the two windows sit side by side. */
@media (min-width: 1000px) {
  :root { --frame: 4px; }

  body { padding-left: var(--strip); }

  .marquee {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: var(--strip);
    padding: 0;
    border-bottom: 0;
    /* Turned half round below, so this is the edge that faces the page. */
    border-left: var(--frame) solid var(--ink);
    writing-mode: vertical-rl;
    transform: rotate(180deg);
  }
  .marquee-track { animation-name: run-up; }
  .marquee-name { font-size: 5rem; }
  .marquee-news { padding-block: 0 0.2em; font-size: 1.75rem; }

  .desk { padding: 24px 32px; }
  .windows { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; gap: 24px; max-width: 1180px; }
  .access { grid-column: 1 / -1; }
  .dialog { margin-top: clamp(24px, 12vh, 140px); }

  .toast { left: calc(50% + var(--strip) / 2); }
}

@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
  .strip > span { transition: none; }
}
