:root {
  --bg: #04060b;
  --rule: #4dffd2;
  --amber: #ffcf33;
  --dim: #6b7d93;
  --panel: #0a1220;
  /* ONE inset for the whole shell. The header set its own, main set another and
     the panes inherited main's, so the header rule and the content under it
     started at different x and nothing lined up with anything. */
  --pad: 12px;
  /* ONE height for every form control. Each type used to size itself off its
     own padding — a 35px text input beside a 26px select beside a 26px colour
     swatch beside a 34px button — so no two rows in the settings pane were the
     same height and the search row stepped down twice across three controls.
     Set the height, drop the vertical padding, and let them agree. */
  --ctl-h: 34px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: #c8d6e4;
  font-family: "Courier New", ui-monospace, monospace;
  font-size: 14px;
  min-height: 100vh;
  background-image:
    linear-gradient(rgba(77, 255, 210, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(77, 255, 210, 0.035) 1px, transparent 1px);
  background-size: 48px 48px;
}

[hidden] { display: none !important; }

header { border-bottom: 1px solid var(--rule); padding: 8px var(--pad); }
h1 { color: var(--amber); font-size: 16px; letter-spacing: 2px; }
#status { color: var(--dim); margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 12px; }
#status .now-playing { color: var(--amber); }

.tabs {
  display: flex;
  border-bottom: 1px solid rgba(77, 255, 210, 0.4);
}
.tab-btn {
  flex: 1;
  background: transparent;
  border: none;
  border-right: 1px solid rgba(77, 255, 210, 0.25);
  color: var(--dim);
  font: inherit;
  font-size: 12px;
  letter-spacing: 2px;
  padding: 8px 4px;
  cursor: pointer;
}
.tab-btn:last-child { border-right: none; }
.tab-btn.active { color: var(--amber); background: rgba(255, 207, 51, 0.08); }

/* The panes carry the inset, not main. Same variable as the header, so the
   content edge sits under the header rule instead of 2px inside it. */
main { padding: 0; }
main > section { padding: var(--pad); }

#gate {
  text-align: center;
  padding: 24px var(--pad) 12px;
}
#gate h2 { color: var(--amber); font-size: 14px; letter-spacing: 2px; margin-bottom: 14px; }
#gate input { width: 100%; }
#gate #go { width: 100%; margin-top: 8px; }

input {
  width: 100%;
  height: var(--ctl-h);
  background: #060a12;
  color: var(--amber);
  border: 1px solid var(--rule);
  /* Horizontal only. The height is the height; padding that also sets it is
     what made every control a different size. */
  padding: 0 9px;
  font: inherit;
  font-size: 13px;
  outline: none;
}
input:focus { box-shadow: 0 0 8px rgba(77, 255, 210, 0.3); }

button {
  background: transparent;
  color: var(--amber);
  border: 1px solid var(--amber);
  font: inherit;
  font-size: 12px;
  height: var(--ctl-h);
  padding: 0 12px;
  cursor: pointer;
}
/* The tabs are a nav strip, not a form row — they set their own height. */
.tab-btn { height: auto; }
button:hover { background: rgba(255, 207, 51, 0.15); }
button.primary { color: var(--rule); border-color: var(--rule); }
button.primary:hover { background: rgba(77, 255, 210, 0.15); }

.dim { color: var(--dim); font-size: 12px; }

#results, #qlist { list-style: none; margin-top: 10px; }

.song {
  border: 1px solid rgba(77, 255, 210, 0.35);
  background: var(--panel);
  margin-bottom: 6px;
}
.song .head {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: center;
  padding: 7px 9px;
  cursor: pointer;
}
.song .head:hover { background: rgba(77, 255, 210, 0.06); }
.song .t { color: #dbe7f4; font-size: 13px; }
.song .a { color: var(--dim); font-size: 11px; }
.song .meta { color: var(--dim); font-size: 11px; white-space: nowrap; }
.song .charts { border-top: 1px dashed rgba(107, 125, 147, 0.4); }

/* A directory row, in the table browser. Same shell as a song so the list reads
   as one thing; the arrow is what says it opens rather than expands. */
.song.folder .t::before { content: "▸ "; color: var(--rule); }
.song.folder .head { border-left: 2px solid var(--rule); }

.crumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-size: 12px;
}
.crumb .sep { color: var(--dim); }
.crumb .crumb-here { color: #dbe7f4; }
.crumb button.crumb-link {
  padding: 2px 6px;
  font-size: 12px;
  color: var(--rule);
  border-color: rgba(77, 255, 210, 0.35);
}

.chart-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 5px 9px 5px 16px;
  border-bottom: 1px dashed rgba(107, 125, 147, 0.25);
}
.chart-row:last-child { border-bottom: none; }
.chart-row .lbl { font-size: 12px; color: #b9c8d8; }
.chart-row .md { font-size: 11px; color: var(--dim); }
.chart-row button { min-width: 26px; padding: 2px 6px; }
/* Community table ratings. Wrap rather than scroll: a chart can sit in half a
   dozen tables and a phone row is narrower than that. */
.chart-row .tables { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.chart-row .tag {
  font-size: 10px;
  line-height: 1;
  padding: 2px 5px;
  cursor: pointer;
  color: var(--rule);
  border: 1px solid rgba(77, 255, 210, 0.35);
  background: rgba(77, 255, 210, 0.07);
}
.chart-row .tag:hover { background: rgba(77, 255, 210, 0.18); }

#qlist li {
  padding: 6px 4px;
  border-bottom: 1px dashed rgba(107, 125, 147, 0.4);
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: center;
  font-size: 12px;
}
#qlist .user { color: var(--rule); font-size: 11px; }
#qlist .song { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#qlist .me { color: var(--amber); }

#settings label { display: block; margin: 8px 0 4px; }
#settings button { margin-top: 8px; width: 100%; }

.sec {
  color: var(--amber);
  font-size: 11px;
  letter-spacing: 2px;
  border-top: 1px dashed rgba(77, 255, 210, 0.35);
  margin-top: 12px;
  padding-top: 8px;
}
.row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 7px;
}
.row label { flex: 1; margin: 0; }
/* Every control in the right-hand half is the same width and the same height,
   whatever kind of control it happens to be. */
.row input[type="number"], .row input[type="text"], .row select,
.row input[type="range"] { flex: 1 1 0; min-width: 0; width: auto; }

/* Checkbox. The OS one is a rounded blue tick that belongs to a different
   century of interface than the rest of this. Same box as every other control,
   with an amber block dropped into it when it is on. */
input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: 0 0 var(--ctl-h);
  width: var(--ctl-h);
  height: var(--ctl-h);
  padding: 0;
  background: var(--panel);
  border: 1px solid rgba(77, 255, 210, 0.45);
  cursor: pointer;
  position: relative;
}
input[type="checkbox"]:checked { border-color: var(--amber); }
input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  inset: 26%;
  background: var(--amber);
}
input[type="checkbox"]:focus-visible { outline: 1px solid var(--amber); outline-offset: 1px; }

.msg { color: var(--amber); margin-top: 8px; min-height: 1em; font-size: 12px; }
.err { color: #ff6a7a; }

/* Two buttons sharing a row, each still --ctl-h tall. */
.row2 { display: flex; gap: 8px; }
.row2 > button { flex: 1 1 0; }

/* Queue confirmation, over the viewport rather than at the top of the results
   pane: on a phone the "+" you tapped is usually several screenfuls below it,
   so the existing message scrolled off and queueing read as a no-op.
   Fixed, not sticky — sticky still needs its ancestor on screen. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translate(-50%, 12px);
  max-width: min(92vw, 460px);
  padding: 10px 14px;
  border: 1px solid var(--rule);
  border-radius: 3px;
  background: #0b0f18;
  color: var(--rule);
  font-size: 12px;
  text-align: center;
  /* Above everything, and never eats a tap meant for the list under it. */
  z-index: 50;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.toast.err { border-color: #ff6a7a; color: #ff6a7a; }
.toast.show { opacity: 1; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; }
}

@media (max-width: 640px) {
  main { padding: 8px; }
  h1 { font-size: 14px; }
  .chart-row { padding-left: 12px; }
}

/* Tabs are inert until the viewer has given a name: the flow is
   gate -> name -> everything else. Disabled alone is easy to miss on a dark
   panel, so dim them too. */
.tab-btn.locked,
.tab-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* ---------------- phone ----------------
   The panel is opened on a phone as often as on a desktop. Three things were
   actively hostile there: the + button on a chart row could be pushed off the
   right edge by a long title, every control was under the ~44px a thumb needs,
   and iOS zooms the whole page when it focuses an input under 16px. */

.chart-row .info,
.song .head > div:first-child {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
}
.chart-row .lbl,
.chart-row .md,
.song .t,
.song .a {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: block;
}
.chart-row .lbl, .chart-row .md { display: inline; }
/* The + never shrinks and never scrolls away. */
.chart-row button { flex: 0 0 auto; min-width: 34px; min-height: 30px; }

/* Search row: the box on its own line, then the two filters and the two
   buttons sharing the next one. Every item is --ctl-h tall, so the row reads as
   one strip rather than as four controls of three different sizes. */
.search-row { flex-wrap: wrap; }
.search-row #q { flex: 1 1 100%; }
.search-row select { flex: 1 1 0; min-width: 0; }
.search-row button { flex: 0 0 auto; }

@media (max-width: 520px) {
  :root {
    /* One bump, not eight. 16px is the threshold below which iOS Safari zooms
       the page on focus, and a 40px target is the thumb-sized one. */
    --ctl-h: 40px;
  }
  input, select, button, textarea { font-size: 16px; }
  .tab-btn { padding: 10px 6px; }
  .song .head { padding: 10px 9px; }
  .chart-row { padding: 8px 9px 8px 14px; }
}

#preview {
  display: block;
  width: 100%;
  max-width: 320px;
  height: auto;
  margin: 8px auto 0;
  border: 1px solid rgba(77, 255, 210, 0.35);
  background: #04060b;
  image-rendering: pixelated;
  touch-action: manipulation;
}
.hint { text-align: center; margin-top: 4px; font-size: 11px; min-height: 1.2em; }

/* The colour rows are the preview now. The INPUTS stay in the DOM and stay
   focusable — they are still the state profForm reads, and clicking a part
   opens one of them — so this hides them without taking away the keyboard
   route. display:none would also stop .click() opening the picker in some
   browsers, which is the whole mechanism. */
.colorrow {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------------- shell width ----------------
   Outside the Twitch panel this is served as a normal page, and a full-width
   desktop browser stretched a phone-shaped layout across 2000px. The panel
   itself is ~320-500px, so that is the shape the design is for either way. */

body > header,
body > .tabs,
body > main {
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
  width: 100%;
}
body > header, body > .tabs { border-left: 1px solid rgba(77, 255, 210, 0.18); border-right: 1px solid rgba(77, 255, 210, 0.18); }

/* ---------------- selects and sliders ----------------
   Both render as OS widgets by default — a grey rounded box and a blue track,
   neither of which belongs on a terminal. The option LIST is still drawn by the
   OS and cannot be fully styled; colouring the options is as far as it goes. */

select {
  appearance: none;
  -webkit-appearance: none;
  background-color: var(--panel);
  color: #c8d6e4;
  border: 1px solid rgba(77, 255, 210, 0.45);
  font: inherit;
  font-size: 13px;
  height: var(--ctl-h);
  padding: 0 26px 0 9px;
  border-radius: 0;
  /* Chevron drawn in the accent, as a data URI so there is no second request. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='7'><path d='M0 0h10L5 7z' fill='%234dffd2'/></svg>");
  background-repeat: no-repeat;
  background-position: right 8px center;
}
select:focus { outline: none; border-color: var(--amber); }
select option { background: #04060b; color: #c8d6e4; }

input[type="range"] {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: none;
  padding: 0;
  height: var(--ctl-h);
}
/* The track fills the control and PAINTS a 4px line down its middle, rather
   than being a 4px box webkit then pins to the top. That is what lets the
   slider be the same height as everything beside it without sitting high in
   its row. */
input[type="range"]::-webkit-slider-runnable-track {
  height: var(--ctl-h);
  border: none;
  background:
    linear-gradient(rgba(77, 255, 210, 0.45), rgba(77, 255, 210, 0.45))
    center / 100% 6px no-repeat;
}
input[type="range"]::-moz-range-track {
  height: 4px;
  background: rgba(77, 255, 210, 0.25);
  border: 1px solid rgba(77, 255, 210, 0.45);
}
input[type="range"]::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 12px;
  height: 18px;
  /* Centred in a full-height track, not hoisted out of a 4px one. */
  margin-top: calc((var(--ctl-h) - 18px) / 2);
  background: var(--amber);
  border: 1px solid #04060b;
}
input[type="range"]::-moz-range-thumb {
  width: 12px;
  height: 18px;
  border-radius: 0;
  background: var(--amber);
  border: 1px solid #04060b;
}
input[type="range"]:focus { outline: none; }
input[type="range"]:focus::-webkit-slider-thumb { background: var(--rule); }
input[type="range"]:focus::-moz-range-thumb { background: var(--rule); }
