/*
 * TV Remote — one stylesheet for every admin page.
 *
 * These pages were built one at a time, each carrying its own <style> block, and
 * the palette forked as they grew: two greens (#34E5B4 and #3DDC97), three
 * ambers, two greys for "muted" and two for body text. The same status word
 * rendered in a different colour depending on which page you were looking at.
 *
 * Everything is a token below. Changing the accent is now one line rather than
 * nine files, and a new page inherits the look by linking this instead of
 * copying the last page's CSS.
 *
 * Loaded by: index, premium_admin, feedback_view, broadcast_admin,
 * channels_admin, ourapps_admin, prank_admin, version.
 *
 * NAMING: button modifiers are scoped (.btn.ok, .btn.bad) rather than bare, so
 * version.php's status words — which are spans reading "ok" and "differs" —
 * cannot pick up a filled green button background by accident.
 */

:root {
  /* ground */
  --bg-1: #101319;
  --bg-2: #06070A;

  /* text, brightest to faintest */
  --ink: #EDEFF2;
  --ink-2: #C9CFD8;
  --muted: #8A929E;
  --dim: #6B7280;
  --faint: #5A626E;
  --placeholder: #5C6673;

  /* accent — one green, was #34E5B4 / #3DDC97 / #4EF0C0 depending on the page */
  --accent: #34E5B4;
  --accent-hi: #4EF0C0;
  --accent-lo: #22C79B;
  --on-accent: #06251C;
  --accent-fill: linear-gradient(180deg, var(--accent-hi), var(--accent-lo));
  --accent-wash: rgba(52, 229, 180, .12);
  --accent-line: rgba(52, 229, 180, .35);

  /* states — one amber, was #E5B84E / #E8B44A / #F0B44E / #C9A227 */
  --danger: #FF7A7A;
  --danger-wash: rgba(255, 90, 90, .12);
  --danger-line: rgba(255, 90, 90, .35);
  --warn: #E5B84E;
  --warn-wash: rgba(229, 184, 78, .08);
  --warn-line: rgba(229, 184, 78, .35);
  --info: #7FC7FF;
  --info-wash: rgba(127, 199, 255, .12);
  --tv: #00E5FF;

  /* surfaces */
  --panel: rgba(255, 255, 255, .05);
  --panel-2: rgba(255, 255, 255, .04);
  --hover: rgba(255, 255, 255, .06);
  --line: rgba(255, 255, 255, .08);
  --line-soft: rgba(255, 255, 255, .06);
  --line-hard: rgba(255, 255, 255, .12);
  --field: rgba(0, 0, 0, .28);

  --r-card: 18px;
  --r-ctl: 10px;
  --r-lg: 12px;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---------- ground ---------- */

* { box-sizing: border-box; margin: 0; }

body {
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  min-height: 100vh;
  color: var(--ink);
  background: radial-gradient(120% 90% at 50% 0%, var(--bg-1), var(--bg-2));
  padding: 32px 16px;
}

.wrap { max-width: 1000px; margin: 0 auto; }

h1 { font-size: 24px; font-weight: 800; margin-bottom: 4px; }

/* The dot is the section marker every page grew independently. */
h2 {
  font-size: 17px; font-weight: 800; margin: 28px 0 12px;
  display: flex; align-items: center; gap: 8px;
}
h2::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 8px rgba(52, 229, 180, .7);
}

.sub { color: var(--muted); font-size: 13px; margin-bottom: 22px; }

.card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 17px 19px; margin-bottom: 12px;
}

.row { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
.row-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.grid .full { grid-column: 1 / -1; }
@media (max-width: 620px) { .grid { grid-template-columns: 1fr; } }

/* ---------- type ---------- */

.meta { color: var(--dim); font-size: 12px; line-height: 1.9; }
.meta b { color: var(--ink-2); }
/* Feedback and broadcast lay their meta out as a row of separate facts. */
.meta.inline, .bub .meta, .thead .meta, .sent .meta {
  display: flex; gap: 14px; flex-wrap: wrap; line-height: 1.5; margin-top: 10px;
}
.hint { color: var(--dim); font-size: 12px; line-height: 1.5; margin-top: 8px; }
.mono { font-family: var(--mono); font-size: 12px; }
code { font-family: var(--mono); font-weight: 800; color: var(--accent); }
.u { color: var(--dim); font-size: 11px; word-break: break-all; }
.ttl { font-weight: 800; font-size: 14px; color: var(--ink); }
.no { color: var(--danger); font-weight: 700; }
.off { opacity: .45; }
.empty { color: var(--faint); padding: 16px 0; font-size: 14px; }
/* Floated so it sits at the top RIGHT, on the same line as the heading that
   follows it. Without this it is a plain block above the <h1>: on the pages with
   a nav that reads as part of the header row, but index.php has no nav and the
   link ends up stranded above the title on its own. One rule here fixes every
   page, since they all place it the same way. */
.logout {
  float: right; margin-top: 2px;
  color: var(--muted); font-size: 13px; text-decoration: underline;
}

.err { color: var(--danger); font-size: 13px; margin-bottom: 10px; }
.flash {
  color: var(--accent); font-size: 13px;
  border-color: var(--accent-line); background: rgba(52, 229, 180, .07);
}
/* Scoped to .card: index uses a bare <span class="warn"> inside a dashboard tile
   purely to tint a number, and an unscoped rule would paint an amber panel behind
   it. .stat .warn b below is what colours that one. */
.card.warn {
  color: var(--warn); font-size: 13px; line-height: 1.6;
  border-color: var(--warn-line); background: var(--warn-wash);
}
.card.warn code { color: var(--ink); background: var(--hover); padding: 1px 5px; border-radius: 4px; }

/* ---------- controls ---------- */

label {
  display: block; color: var(--muted); font-size: 12px; font-weight: 700;
  margin-bottom: 6px;
}
/* Uppercase only where a label sits above a whole field group, not on the
   inline ones inside a table row. */
.card > form > label, .card > label { text-transform: uppercase; letter-spacing: .06em; }

input[type=text], input[type=number], input[type=search], input[type=datetime-local],
textarea, select {
  width: 100%; background: var(--field); color: var(--ink);
  border: 1px solid var(--line-hard); border-radius: var(--r-ctl);
  font: inherit; font-size: 14px; padding: 10px 12px; line-height: 1.5;
}
input[type=text], input[type=number], input[type=search], input[type=datetime-local], select {
  height: 42px; padding: 0 12px;
}
textarea { min-height: 96px; resize: vertical; }
::placeholder { color: var(--placeholder); }
input[type=file] { color: var(--ink-2); font-size: 13px; }
/* The dropdown list itself is drawn by the OS — without this it inherits a light
   background and the option text becomes unreadable. */
select option { background: #12161C; color: var(--ink); }
/* Chrome's calendar glyph is black on black without this. */
input[type=datetime-local]::-webkit-calendar-picker-indicator { filter: invert(1); opacity: .6; }
:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 1px; }

.field { margin-bottom: 14px; }
.fieldlbl {
  display: flex; flex-direction: column; gap: 6px;
  color: var(--muted); font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .06em;
}
.confirm {
  display: flex; align-items: flex-start; gap: 10px; color: var(--ink-2);
  font-size: 13px; line-height: 1.5; margin: 4px 0 14px;
}

/* Buttons. .btn alone is the secondary action; .ok is the affirmative one and
   .bad the destructive one, and they only ever apply alongside .btn. */
.btn {
  border: 1px solid var(--line-hard); border-radius: var(--r-ctl);
  padding: 8px 16px; font: inherit; font-size: 13px; font-weight: 800;
  color: var(--ink-2); background: var(--hover); cursor: pointer;
}
.btn:hover { color: var(--ink); border-color: rgba(255, 255, 255, .28); }
.btn.ok { color: var(--on-accent); background: var(--accent-fill); border-color: transparent; }
.btn.ok:hover { color: var(--on-accent); filter: brightness(1.06); }
.btn.bad { color: var(--danger); background: var(--danger-wash); border-color: rgba(255, 90, 90, .3); }
.btn.bad:hover { color: var(--danger); border-color: rgba(255, 90, 90, .6); }
.btn.ghost, .btn.mute { color: var(--ink-2); background: var(--panel); }
.btn.code { color: var(--accent); background: none; border-color: rgba(52, 229, 180, .45); }
.btn.code:hover { color: #6BFFD6; border-color: rgba(52, 229, 180, .8); }
.btn.big { padding: 12px 22px; font-size: 14px; border-radius: var(--r-lg); }

button.primary {
  width: 100%; height: 48px; border: none; border-radius: var(--r-lg); cursor: pointer;
  font: inherit; font-size: 15px; font-weight: 800;
  color: var(--on-accent); background: var(--accent-fill);
}

.del {
  background: none; border: 1px solid var(--danger-line); color: var(--danger);
  border-radius: var(--r-ctl); padding: 5px 12px; font: inherit; font-size: 12px;
  font-weight: 700; cursor: pointer;
}
.del:hover { border-color: rgba(255, 90, 90, .7); }

/* The sign-in card, identical on all eight pages. */
.login input[type=text], input[type=password] {
  width: 100%; height: 48px; border-radius: var(--r-lg);
  border: 1px solid var(--line-hard); background: rgba(0, 0, 0, .3);
  color: var(--ink); font-size: 16px; padding: 0 14px; margin: 14px 0;
}

/* ---------- tables ---------- */

table { width: 100%; border-collapse: collapse; font-size: 13px; }
td, th {
  text-align: left; padding: 9px 10px;
  border-bottom: 1px solid var(--line-soft); vertical-align: top;
}
th {
  color: var(--dim); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
}
tr:last-child td { border-bottom: none; }

/* ---------- navigation ---------- */

.admin-nav {
  display: flex; gap: 8px; margin-bottom: 22px; padding: 5px; flex-wrap: wrap;
  width: fit-content; background: var(--panel);
  border: 1px solid var(--line); border-radius: 14px;
}
.admin-nav a {
  padding: 9px 16px; border-radius: var(--r-ctl); color: var(--muted);
  text-decoration: none; font-size: 13px; font-weight: 800;
}
.admin-nav a:hover { color: var(--ink); background: var(--hover); }
.admin-nav a.active { color: var(--on-accent); background: var(--accent-fill); }
.admin-nav a.ext { color: #5D6673; font-weight: 700; }
.admin-nav a.ext:hover { color: var(--ink); }

/* In-page section tabs (Feedback / Codes / Devices / …) */
.tabs {
  display: flex; gap: 8px; margin: 18px 0 6px; padding: 5px;
  width: fit-content; max-width: 100%; flex-wrap: wrap;
  background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
}
.tabs a {
  display: flex; align-items: center; gap: 8px; padding: 9px 16px;
  border-radius: var(--r-ctl); color: var(--muted); text-decoration: none;
  font-size: 13px; font-weight: 800;
}
.tabs a:hover { color: var(--ink); background: var(--hover); }
.tabs a.active { color: var(--on-accent); background: var(--accent-fill); }
.tabs .count {
  font-size: 11px; font-weight: 800; padding: 1px 8px; border-radius: 999px;
  background: rgba(255, 255, 255, .10); color: var(--ink-2);
}
.tabs a.active .count { background: rgba(6, 37, 28, .25); color: var(--on-accent); }
.tabs .count.hot { background: rgba(229, 184, 78, .18); color: var(--warn); }

/* Filter pills */
.filters { display: flex; gap: 8px; flex-wrap: wrap; margin: 6px 0 16px; }
.filters a {
  padding: 6px 13px; border-radius: 999px; text-decoration: none;
  font-size: 12px; font-weight: 800; color: var(--muted);
  border: 1px solid var(--line-hard);
}
.filters a:hover { color: var(--ink); }
.filters a.active {
  color: var(--on-accent); border-color: transparent; background: var(--accent-fill);
}

.chips { display: flex; gap: 8px; margin-bottom: 20px; flex-wrap: wrap; }
.chip {
  padding: 8px 16px; border-radius: var(--r-lg); font-size: 13px; font-weight: 700;
  text-decoration: none; color: var(--muted);
  background: var(--panel); border: 1px solid var(--line);
}
.chip.active {
  color: var(--on-accent); background: var(--accent-fill); border-color: transparent;
}

.pager {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin: 14px 0 4px; font-size: 13px;
}
.pager a {
  padding: 8px 16px; border-radius: var(--r-ctl); text-decoration: none;
  font-weight: 800; color: var(--ink-2); background: var(--hover);
}
.pager a:hover { color: var(--ink); background: var(--line-hard); }
.pager .disabled { padding: 8px 16px; color: #4A515C; font-weight: 800; }
.pager .pinfo { color: var(--muted); }

/* ---------- badges ---------- */

.st, .cat, .tag, .grp {
  display: inline-block; padding: 3px 10px; border-radius: 8px;
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  white-space: nowrap;
}
.st.pending { color: var(--warn); background: rgba(229, 184, 78, .12); }
.st.approved, .cat.idea { color: var(--accent); background: var(--accent-wash); }
.st.rejected, .cat.bug { color: var(--danger); background: var(--danger-wash); }
.cat.other { color: var(--ink-2); background: rgba(255, 255, 255, .08); }
.grp, .tag.direct { color: var(--accent); background: var(--accent-wash); }
.tag { color: var(--info); background: var(--info-wash); }
.tag.tv { color: var(--tv); background: rgba(0, 229, 255, .12); }
.tag.yt { color: var(--danger); background: var(--danger-wash); }
/* "hidden" on a pulled Our Apps row — was undefined and fell back to the info
   blue, which read as a feature rather than as something switched off. */
.tag.bad { color: var(--danger); background: var(--danger-wash); }
.seen { color: var(--accent); font-weight: 700; }

.logo {
  width: 34px; height: 34px; object-fit: contain;
  border-radius: 8px; background: var(--hover);
}
.shot {
  display: block; max-width: 260px; width: 100%; border-radius: var(--r-lg);
  border: 1px solid var(--line-hard);
}

/* Claimed/total fill bar on a share code */
.bar {
  height: 5px; width: 120px; max-width: 100%; margin: 6px 0 5px;
  border-radius: 999px; background: rgba(255, 255, 255, .10); overflow: hidden;
}
.bar span {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-hi), var(--accent-lo));
}

/* ---------- premium: messages, search, copy toast ---------- */

.searchbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 14px; }
.searchbar input[type=search] { flex: 1 1 280px; min-width: 200px; font-size: 13px; }

.msg {
  font-size: 14px; line-height: 1.55; white-space: pre-wrap; word-break: break-word;
  margin-top: 4px;
}
/* A submitted message in the Premium admin is a quoted block, not body text. */
.premium-msg, .row > .msg {
  flex: 1 1 320px; min-width: 260px; max-width: 520px; color: var(--ink-2);
  line-height: 1.6; background: var(--panel-2);
  border: 1px solid rgba(255, 255, 255, .09); border-radius: var(--r-lg);
  padding: 12px 14px; margin-top: 0;
}

.copycode { cursor: pointer; }
.copycode:hover { text-decoration: underline; }
.codechip { color: var(--accent); font-family: var(--mono); letter-spacing: .04em; }
.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: var(--accent-fill); color: var(--on-accent);
  font-size: 13px; font-weight: 800; padding: 10px 18px; border-radius: var(--r-lg);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .4); opacity: 0; pointer-events: none;
  transition: opacity .18s, transform .18s;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(-4px); }

/* ---------- broadcast: picture picker ---------- */

.picks { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.pick {
  width: 92px; height: 52px; object-fit: cover; border-radius: 8px; cursor: pointer;
  border: 2px solid transparent; opacity: .75;
}
.pick:hover { opacity: 1; }
.pick.on { border-color: var(--accent-hi); opacity: 1; }
.chosen { margin-top: 8px; font-size: 12.5px; font-weight: 700; color: var(--dim); }
.chosen.on { color: var(--accent); }

/* ---------- feedback: two panes and the conversation ---------- */

.panes { display: grid; grid-template-columns: 268px 1fr; gap: 14px; align-items: start; }
.list {
  background: var(--panel-2); border: 1px solid rgba(255, 255, 255, .07);
  border-radius: var(--r-card); padding: 8px; position: sticky; top: 16px;
  max-height: calc(100vh - 60px); overflow-y: auto;
}
.conv {
  display: block; text-decoration: none; padding: 11px 12px;
  border-radius: var(--r-lg); border: 1px solid transparent; margin-bottom: 4px;
}
.conv:hover { background: var(--panel); }
.conv.active { background: rgba(52, 229, 180, .10); border-color: rgba(52, 229, 180, .28); }
.conv .id {
  font-family: var(--mono); font-weight: 800; font-size: 12.5px;
  color: var(--ink); letter-spacing: .03em;
}
.conv .line { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.conv .when { color: var(--dim); font-size: 11px; white-space: nowrap; }
.conv .who { color: var(--dim); font-size: 11px; margin-top: 3px; }
/* Their message is the newest one: nothing has been said back yet. */
.conv .waiting { color: var(--accent-hi); font-weight: 700; }
/* The line that matched the search, under the conversation's summary. Clamped:
   it is a reason to open the thread, not a substitute for reading it. */
.conv .hit {
  color: var(--muted); font-size: 11.5px; line-height: 1.45; margin-top: 5px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* Search over every conversation. Sits with the filter chips because it is one
   more way of narrowing the same list. */
.search { display: flex; gap: 8px; margin: -8px 0 16px; flex-wrap: wrap; }
.search input[type="search"] {
  flex: 1; min-width: 220px; font: inherit; font-size: 13px;
  color: var(--ink); background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 8px 12px;
}
.search input[type="search"]:focus {
  outline: none; border-color: rgba(52, 229, 180, .5);
}
.search .btn { align-self: stretch; display: flex; align-items: center; }
mark {
  background: rgba(52, 229, 180, .26); color: inherit;
  border-radius: 3px; padding: 0 1px;
}
@media (max-width: 780px) {
  .panes { grid-template-columns: 1fr; }
  .list { position: static; max-height: 260px; }
}

.thead {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  flex-wrap: wrap; padding-bottom: 12px; margin-bottom: 16px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
}
.thead .dev {
  font-size: 14px; font-weight: 800; letter-spacing: .03em; font-family: var(--mono);
}
.thead .meta { margin-top: 0; }
.stream { display: flex; flex-direction: column; gap: 14px; }
/* Their messages hug the left, yours the right — the one glance that says who
   said what without reading a label. */
.bub { max-width: 82%; border-radius: 16px; padding: 12px 14px; }
.bub.in {
  align-self: flex-start; border-bottom-left-radius: 6px;
  background: var(--panel); border: 1px solid var(--line);
}
.bub.out {
  align-self: flex-end; border-bottom-right-radius: 6px;
  background: rgba(52, 229, 180, .08); border: 1px solid rgba(52, 229, 180, .20);
}
.bub .msg { margin-top: 0; font-size: 14px; }
.bub .meta { margin-top: 8px; gap: 10px; font-size: 11px; }
.bubtop {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 8px;
}
.bub .del { padding: 2px 8px; font-size: 11px; opacity: .5; }
.bub .del:hover { opacity: 1; }
.who {
  font-size: 11px; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--accent);
}
.replybox { margin-top: 12px; }
.replybox textarea { min-height: 74px; font-size: 13px; }
.replyrow { display: flex; align-items: center; gap: 12px; margin-top: 8px; flex-wrap: wrap; }
.composer {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid rgba(255, 255, 255, .07);
}
.composer .replybox { margin-top: 0; }
/* Only shown when a reload would have thrown away something half-typed. */
#newmsg {
  display: none; position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  background: var(--accent-fill); color: var(--on-accent); font-weight: 800;
  font-size: 13px; padding: 10px 18px; border-radius: 999px; cursor: pointer;
  border: none; box-shadow: 0 8px 24px rgba(0, 0, 0, .45);
}

/* ---------- version: file states ----------
   Bare words, not buttons — see the naming note at the top of this file. */

.sum { display: flex; gap: 16px; flex-wrap: wrap; font-weight: 800; }
.sum .ok, .sum .differs, .sum .missing, .sum .extra { font-weight: 800; }
.ok { color: var(--accent); }
.differs { color: var(--danger); }
.missing { color: var(--warn); }
.extra { color: var(--muted); }
/* .btn.ok is defined above and wins on specificity, so an affirmative button
   keeps its fill rather than turning into green text. */

/* ---------- dashboard tiles (index) ---------- */

/* Its own grid, not the two-column .grid the form pages use: tiles should reflow
   by available width, and forcing them into two columns wastes a wide screen. */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px;
}

a.tile {
  display: block; text-decoration: none; color: inherit;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 20px;
  transition: border-color .15s, transform .15s;
}
a.tile:hover { border-color: var(--accent-line); transform: translateY(-2px); }
.ico {
  width: 44px; height: 44px; border-radius: var(--r-lg);
  display: flex; align-items: center; justify-content: center; font-size: 22px;
  background: linear-gradient(180deg, rgba(52, 229, 180, .18), rgba(52, 229, 180, .06));
}
.tname { font-size: 17px; font-weight: 800; margin: 14px 0 4px; }
.tdesc { color: var(--muted); font-size: 13px; line-height: 1.5; }
.stat { margin-top: 14px; font-size: 13px; color: var(--ink-2); font-weight: 700; }
.stat b { color: var(--accent); font-size: 20px; }
.stat .warn b { color: var(--warn); }
.foot { color: #4A515C; font-size: 12px; margin-top: 30px; }
.foot a { color: var(--muted); text-decoration: none; font-weight: 700; }
.foot a:hover { color: var(--ink); text-decoration: underline; }
