@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');


/**
 * Cheil × NC — AION 2 Campaign Console.
 *
 * Mirrors the Cheil house style (cheil.com): stark black and white, almost no
 * chrome, Inter at tight tracking, and a single high-voltage yellow used
 * sparingly. Values taken from Cheil's compiled CSS:
 *   #000 / #fff dominant · #a6a6a6 mid grey · #d0d0d0 · #333 · #444
 *
 * The accent departs from Cheil deliberately: their house yellow (#ffe900) is
 * replaced by the AION 2 mark's blue (#1f9edf) with a low-intensity glow, so
 * the console reads as belonging to this campaign rather than to the agency.
 * The structure — stark, chromeless, monochrome — is still Cheil's.
 *
 * Cheil's own face is "Cheil Hangul", which is proprietary; their stack falls
 * back to Inter, so Inter is what we use.
 *
 * Dark only. There is no light theme: the console is a single committed look,
 * and a half-maintained second palette is where contrast bugs hide.
 */

:root {
  --bg: #000000;
  --surface: #0a0a0a;
  --surface-2: #141414;
  --line: #262626;
  --line-strong: #3d3d3d;

  --fg: #ffffff;
  --fg-dim: #a6a6a6;
  --fg-faint: #6b6b6b;

  /*
   * The one chromatic note in an otherwise black-and-white console, taken from
   * the AION 2 mark's own blue. Everything structural stays greyscale; colour
   * here always means "this is interactive" or "this is a state".
   */
  --accent: #1f9edf;
  --accent-fg: #000000;

  /*
   * Status colours are the deliberate exception to the monochrome rule — a
   * red/green that has to be read at a glance cannot be spent on decoration.
   * These are lifted from the AION 2 public palette (--up / --ember / --down
   * in apps/web) so the two surfaces agree on what "good" and "bad" look like.
   */
  --ok: #6ee7a8;
  --warn: #f26822;
  --danger: #f87171;
  --live: #ff3b30;

  /*
   * Glow. The AION 2 mark reads as lit rather than printed, and the console
   * borrows that at low intensity — enough to separate an accent surface from
   * the black behind it, not enough to bloom into neighbouring text.
   */
  --glow: 0 0 12px rgba(31, 158, 223, 0.28);
  --glow-strong: 0 0 18px rgba(31, 158, 223, 0.45);
  --glow-text: 0 0 10px rgba(31, 158, 223, 0.4);

  --invert-bg: #ffffff;
  --invert-fg: #000000;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;
  font-size: 13.5px;
  line-height: 1.5;
  letter-spacing: -0.011em; /* Inter reads tighter than its default at UI sizes */
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: var(--accent);
  color: var(--accent-fg);
}

.boot {
  padding: 3rem;
  color: var(--fg-dim);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

/* --- Brand lockup --------------------------------------------------------- */

.brand {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/*
 * Centre, not baseline. Baseline was correct while the marks were text spans;
 * a replaced element's baseline is its bottom edge, so two logos of different
 * proportions would hang off their undersides instead of sitting level.
 */
.lockup {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--fg);
}

.wordmark {
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
}

/* Cheil sets its wordmark lowercase and very tight. */
.wordmark-cheil {
  font-size: 1.32rem;
  text-transform: lowercase;
}

/* NC is an uppercase monogram. */
.wordmark-nc {
  font-size: 1.32rem;
  text-transform: uppercase;
  letter-spacing: -0.02em;
}

.lockup-x {
  color: var(--accent);
  font-size: 0.9rem;
  font-weight: 400;
}

.lockup-compact .wordmark {
  font-size: 0.95rem;
}

.brand-product {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--fg-faint);
  font-weight: 500;
}

/* --- Login ---------------------------------------------------------------- */

.login-wrap {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 1rem;
}

.login {
  width: 100%;
  max-width: 23rem;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  padding: 2.5rem 2rem;
  background: var(--surface);
}

.login .brand {
  margin-bottom: 2.25rem;
}

.login h1 {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 600;
  margin: 0 0 1.75rem;
  color: var(--fg-dim);
}

.login label,
.inline-form label {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
  margin-bottom: 0.4rem;
}

.login input {
  margin-bottom: 1.15rem;
}

/* --- Shell ---------------------------------------------------------------- */

.shell {
  display: grid;
  grid-template-columns: 236px 1fr;
  min-height: 100vh;
}

/*
 * The sidebar is pinned: nav and Sign out stay reachable no matter how far the
 * content scrolls. It is sticky rather than position:fixed so it keeps its grid
 * column and needs no compensating margin on the content — and it carries its
 * own overflow so a long nav on a short viewport can still scroll itself.
 */
.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--line);
  padding: 1.5rem 1.15rem;
  display: flex;
  flex-direction: column;
  gap: 2rem;
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  overflow-y: auto;
}

nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex: 1;
}

.nav-item {
  background: none;
  border: 0;
  color: var(--fg-dim);
  text-align: left;
  /* NavLink renders an anchor, so these two are needed on top of the
     button-era rules below. */
  display: block;
  text-decoration: none;
  padding: 0.6rem 0.7rem;
  cursor: pointer;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  border-left: 2px solid transparent;
  transition: none;
}

.nav-item:hover {
  color: var(--fg);
  background: var(--surface-2);
}

/* Active state is the yellow bar — the one place accent appears in navigation. */
.nav-item.active {
  color: var(--fg);
  border-left-color: var(--accent);
  background: var(--surface-2);
}

.who {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  border-top: 1px solid var(--line);
  padding-top: 1.15rem;
  font-size: 0.72rem;
}

.who .email {
  color: var(--fg-dim);
  overflow-wrap: anywhere;
}

.role {
  align-self: flex-start;
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  padding: 0.18rem 0.42rem;
  background: var(--invert-bg);
  color: var(--invert-fg);
}

/* Superadmin is the only role that gets the accent — it should feel different. */
.role-superadmin {
  background: var(--accent);
  color: var(--accent-fg);
}

/* Admin sits one step down: outlined in the accent rather than filled. */
.role-admin {
  box-shadow: inset 0 0 0 1px var(--accent);
}

.content {
  padding: 2rem 2.25rem;
  min-width: 0; /* lets wide tables shrink instead of blowing out the grid */
}

.page-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--line);
}

.page-head h1 {
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0;
  text-transform: uppercase;
}

/* --- Controls ------------------------------------------------------------- */

input,
select,
textarea {
  background: var(--bg);
  border: 1px solid var(--line-strong);
  color: var(--fg);
  border-radius: 0; /* Cheil's chrome has no radius */
  padding: 0.5rem 0.65rem;
  font: inherit;
  font-size: 0.82rem;
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
  border-color: var(--accent);
}

button {
  background: var(--invert-bg);
  color: var(--invert-fg);
  border: 1px solid var(--invert-bg);
  border-radius: 0;
  font: inherit;
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: 0.55rem 1.1rem;
  cursor: pointer;
}

button:hover:not(:disabled) {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}

button:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

button.ghost {
  background: transparent;
  color: var(--fg);
  border-color: var(--line-strong);
}

.link {
  background: none;
  border: 0;
  color: var(--fg);
  padding: 0;
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.link:hover {
  color: var(--accent);
  background: none;
}

.link.danger {
  color: var(--danger);
}

fieldset {
  border: 1px solid var(--line);
  border-radius: 0;
  margin: 0 0 1rem;
  padding: 0.75rem 1rem 1rem;
}

legend {
  color: var(--fg-faint);
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-weight: 600;
  padding: 0 0.4rem;
}

.check {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.8rem;
  margin: 0.25rem 0;
}

.check input {
  margin: 0;
  accent-color: var(--accent);
}

.inline-form {
  display: flex;
  flex-direction: column;
}

.inline-form input,
.inline-form select {
  margin-bottom: 1rem;
}

.inline-form button {
  align-self: flex-start;
}

/* --- Cards & tables ------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 1.25rem 1.35rem;
  margin-bottom: 1.25rem;
}

.card h2 {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-weight: 600;
  margin: 0 0 0.4rem;
  color: var(--fg-dim);
}

.grid-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.75rem;
}

.grid-table th {
  text-align: left;
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
  padding: 0 0.7rem 0.6rem;
  border-bottom: 1px solid var(--line-strong);
}

.grid-table td {
  padding: 0.65rem 0.7rem;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  font-size: 0.82rem;
}

.grid-table tr:last-child td {
  border-bottom: 0;
}

.row-disabled {
  opacity: 0.4;
}

/* --- Chips & status ------------------------------------------------------- */

.tag {
  font-size: 0.56rem;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  font-weight: 700;
  border: 1px solid var(--line-strong);
  color: var(--fg-dim);
  padding: 0.1rem 0.35rem;
  margin-left: 0.4rem;
}

.tag-poll {
  border-color: var(--accent);
  color: var(--accent);
}

.state {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  font-weight: 700;
  padding: 0.14rem 0.4rem;
  border: 1px solid var(--line-strong);
  color: var(--fg-dim);
}

.state-active {
  border-color: var(--fg);
  color: var(--fg);
}
.state-warned,
.state-rate_limited {
  border-color: var(--accent);
  color: var(--accent);
}
.state-disqualified,
.state-our_outage {
  border-color: var(--danger);
  color: var(--danger);
}

.faction {
  text-transform: uppercase;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  font-weight: 600;
}
.faction-elyos,
.faction-asmodian {
  color: var(--fg-dim);
}

.live {
  color: var(--danger);
  font-weight: 700;
  font-size: 0.62rem;
  letter-spacing: 0.14em;
}

.muted {
  color: var(--fg-dim);
}
.tiny {
  font-size: 0.7rem;
}
.ok {
  color: var(--ok);
  font-weight: 600;
}
.warn {
  color: var(--warn);
  font-weight: 600;
}
.error {
  color: var(--danger);
  font-size: 0.8rem;
}

.warn-banner {
  border: 1px solid var(--accent);
  border-left-width: 3px;
  color: var(--fg);
  padding: 0.65rem 0.85rem;
  font-size: 0.8rem;
  margin: 0 0 1rem;
  background: var(--surface-2);
}

/* --- Stats ---------------------------------------------------------------- */

.stat-row {
  display: grid;
  gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  margin: 1rem 0;
  background: var(--line);
  border: 1px solid var(--line);
}

.stat {
  background: var(--bg);
  padding: 0.8rem 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.stat-value {
  font-size: 1.32rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.stat-label {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--fg-faint);
  font-weight: 600;
}

/* Tones: ok is the campaign accent (blue) — the number that says "we are
   live"; warn is orange — attention, not celebration. */
.stat-ok .stat-value {
  color: var(--accent);
}

.stat-warn .stat-value {
  color: var(--warn);
}

.gap-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
}

.gap-list li {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.8rem;
  flex-wrap: wrap;
}

.gap-list li:last-child {
  border-bottom: 0;
}

/* --- Key reveal ----------------------------------------------------------- */

.key-reveal {
  border: 1px solid var(--accent);
  border-left-width: 3px;
  background: var(--surface-2);
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  align-items: flex-start;
}

.key-reveal code {
  background: var(--bg);
  border: 1px solid var(--line);
  padding: 0.6rem 0.8rem;
  font-size: 0.8rem;
  overflow-wrap: anywhere;
  width: 100%;
}

code {
  font-family: ui-monospace, 'Cascadia Code', Consolas, monospace;
  font-size: 0.78rem;
}

/* --- Permission matrix ---------------------------------------------------- */

.perm-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.35rem 1rem;
  margin-top: 0.6rem;
}

.perm {
  font-size: 0.7rem;
  color: var(--fg-dim);
  font-family: ui-monospace, Consolas, monospace;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.perm::before {
  content: '';
  width: 5px;
  height: 5px;
  background: var(--fg-faint);
  flex-shrink: 0;
}

.perm-dual::before {
  background: var(--accent);
}

.role-card {
  border: 1px solid var(--line);
  padding: 1rem 1.15rem;
  margin-bottom: 0.75rem;
  background: var(--surface);
}

.role-card h3 {
  margin: 0 0 0.15rem;
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

.role-card p {
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  color: var(--fg-dim);
}

@media (max-width: 860px) {
  .shell {
    grid-template-columns: 1fr;
  }
  .sidebar {
    border-right: 0;
    border-bottom: 1px solid var(--line);
    height: auto;
    position: sticky;
    top: 0;
    z-index: 10;
  }
  nav {
    flex-direction: row;
    flex-wrap: wrap;
  }
  .content {
    padding: 1.25rem;
  }
}

/* --- Filter bar ------------------------------------------------------------ */

.filter-bar {
  border: 1px solid var(--line);
  background: var(--surface);
  padding: 0.85rem 1rem 0.65rem;
  margin-bottom: 1rem;
}

.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  align-items: flex-end;
}

.filter-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 9rem;
}

.filter-field label {
  font-size: 0.56rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
}

.filter-field select,
.filter-field input {
  font-size: 0.78rem;
  padding: 0.4rem 0.5rem;
}

.filter-search {
  min-width: 14rem;
  flex: 1;
}

.filter-meta {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-top: 0.7rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--line);
}

/* --- Roster detail --------------------------------------------------------- */

.detail-title {
  display: flex;
  align-items: center;
  gap: 0.85rem;
}

.avatar {
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-strong);
  object-fit: cover;
  flex-shrink: 0;
}

.detail-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  align-items: start;
}

.detail-grid .card {
  margin-bottom: 0;
  display: flex;
  flex-direction: column;
}

/**
 * Masonry variant — cards pack vertically instead of lining up in rows.
 *
 * A grid row is as tall as its tallest cell, so one long card (the dashboard's
 * Helix budget is ~3x its neighbours) leaves the card beside it sitting above a
 * hole the height of the difference. Multi-column layout has no rows to align
 * to: each card starts where the previous one ended.
 *
 * The trade is reading order — content flows down a column and then to the next,
 * rather than left-to-right. That is fine for a wall of independent cards and
 * wrong for a form, which is why this is opt-in rather than folded into
 * .detail-grid itself.
 *
 * `columns: 330px` is the multicol spelling of the grid's minmax(330px, 1fr):
 * as many columns of at least 330px as fit, one on narrow screens.
 */
.detail-grid.masonry {
  display: block;
  columns: 330px;
  column-gap: 1.25rem;
}

.detail-grid.masonry > .card {
  /* Without this a card is free to split across a column boundary — half a
     table at the bottom of one column and the rest at the top of the next. */
  break-inside: avoid;
  /* Multicol has no `gap` for the block direction; the row gap is a margin. */
  margin-bottom: 1.25rem;
}

.detail-grid label {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
  margin: 0.85rem 0 0.3rem;
}

.detail-grid input,
.detail-grid select,
.detail-grid textarea {
  width: 100%;
}

.detail-grid button {
  align-self: flex-start;
  margin-top: 1rem;
}

.detail-grid .check {
  margin-top: 0.85rem;
}

/* Definition list used for read-only Twitch facts. */
dl.kv {
  display: grid;
  grid-template-columns: minmax(7rem, auto) 1fr;
  gap: 0.35rem 0.85rem;
  margin: 0.5rem 0 0.75rem;
  font-size: 0.78rem;
}

dl.kv dt {
  color: var(--fg-faint);
  text-transform: uppercase;
  font-size: 0.56rem;
  letter-spacing: 0.12em;
  font-weight: 600;
  padding-top: 0.2rem;
}

dl.kv dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.state-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.75rem 0;
}

button.ghost.danger {
  color: var(--danger);
  border-color: var(--danger);
}

button.ghost.danger:hover:not(:disabled) {
  background: var(--danger);
  border-color: var(--danger);
  color: #000;
}

.lookup-result {
  border-top: 1px solid var(--line);
  margin-top: 1rem;
  padding-top: 1rem;
  display: flex;
  flex-direction: column;
}

.lookup-result label {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
  margin: 0.85rem 0 0.3rem;
}

.lookup-result button {
  align-self: flex-start;
  margin-top: 1rem;
}

/* State chips for the FR-001 lifecycle. */
.state-drafted { border-color: var(--line-strong); color: var(--fg-dim); }
.state-confirmed { border-color: var(--fg); color: var(--fg); }
.state-locked { border-color: var(--accent); color: var(--accent); }
.state-withdrawn { border-color: var(--fg-faint); color: var(--fg-faint); }
.state-removed { border-color: var(--danger, #c0392b); color: var(--danger, #c0392b); border-style: dashed; }

/* --- Imports --------------------------------------------------------------- */

.file-drop {
  display: block;
  border: 1px dashed var(--line-strong);
  padding: 1.5rem;
  text-align: center;
  cursor: pointer;
  margin-top: 0.85rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--fg-dim);
}

.file-drop:hover {
  border-color: var(--accent);
  color: var(--fg);
}

.file-drop input {
  display: none;
}

.map-grid {
  display: grid;
  gap: 0.85rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  margin: 0.85rem 0 1rem;
}

.map-grid .filter-field {
  min-width: 0;
}

.grid-table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Import batch lifecycle chips. */
.state-uploaded, .state-profiled { border-color: var(--line-strong); color: var(--fg-dim); }
.state-validated { border-color: var(--fg); color: var(--fg); }
.state-committed { border-color: var(--accent); color: var(--accent); }
.state-reverted { border-color: var(--fg-faint); color: var(--fg-faint); }
.state-failed { border-color: var(--danger); color: var(--danger); }
/* Provenance chip beside the lifecycle chip: the batch came in by email. */
.state-auto { border-color: var(--accent); color: var(--accent); margin-left: 0.35rem; }

/* Email ingestion log chips. */
.state-received { border-color: var(--line-strong); color: var(--fg-dim); }
.state-ingested { border-color: var(--accent); color: var(--accent); }
.state-needs_review { border-color: var(--warn, #c9a227); color: var(--warn, #c9a227); }
.state-rejected { border-color: var(--fg-faint); color: var(--fg-faint); }

.recipient-list { list-style: none; padding: 0; margin: 0.5rem 0; display: flex; flex-wrap: wrap; gap: 0.4rem; }
.recipient-list li { display: inline-flex; align-items: center; gap: 0.35rem; border: 1px solid var(--line-strong); padding: 0.2rem 0.5rem; font-size: 0.85rem; }
.recipient-list li button { background: none; border: 0; color: var(--fg-dim); cursor: pointer; padding: 0; line-height: 1; }
.recipient-add { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.4rem; }
.recipient-add input { flex: 1; max-width: 22rem; }

/* --- Password requirement checklist --------------------------------------- */

.pw-rules {
  list-style: none;
  margin: -0.6rem 0 1rem;
  padding: 0;
  display: grid;
  gap: 0.15rem;
}

.pw-rules li {
  font-size: 0.72rem;
  color: var(--fg-faint);
  font-variant-numeric: tabular-nums;
}

.pw-rules li.met {
  color: var(--fg);
}

/* Unmet rules stay muted rather than turning red — the operator is mid-typing,
   not failing. Red on every keystroke reads as an error when it is progress. */
.pw-rules li.unmet {
  color: var(--fg-faint);
}

/* --- Modal + danger zone --------------------------------------------------- */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  display: grid;
  place-items: center;
  z-index: 100;
  padding: 1rem;
}

.modal {
  width: 100%;
  max-width: 24rem;
  display: flex;
  flex-direction: column;
  margin: 0;
}

.modal label {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
  margin: 0.85rem 0 0.3rem;
}

.modal input { width: 100%; }

/* Destructive actions are separated by a rule rather than colour alone, so the
   boundary is visible before the button is read. */
.danger-zone {
  border-top: 1px solid var(--line);
  margin-top: 1.25rem;
  padding-top: 1rem;
}

.danger-zone h3 {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--danger);
  margin: 0 0 0.4rem;
}

.panel-head-inline {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

.sub-head {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
  margin: 1.5rem 0 0;
}

/* --- bulk selection ------------------------------------------------------ */

/* Sticks to the top of the scroll area so the action stays reachable when a
   long roster is scrolled — the selection it acts on is off-screen by then. */
.bulk-bar {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.75rem;
  background: var(--surface-2);
  border: 1px solid var(--accent);
  font-size: 0.82rem;
}

.bulk-bar strong {
  font-variant-numeric: tabular-nums;
}

/* Push the destructive action to the far end, away from "Clear selection". */
.bulk-bar .danger {
  margin-left: auto;
}

.grid-table th.pick,
.grid-table td.pick {
  width: 2.2rem;
  padding-right: 0;
}

.grid-table td.pick input,
.grid-table th.pick input {
  cursor: pointer;
}

.grid-table tr.picked {
  background: var(--surface-2);
}

/* The row that is ours — AION 2 in the top-games table. */
.grid-table tr.row-accent {
  background: var(--surface-2);
}
.grid-table tr.row-accent td {
  color: var(--accent);
  font-weight: 600;
}


/* ---------------------------------------------------------------------------
   AION 2 accent treatment
   --------------------------------------------------------------------------- */

/*
 * The glow belongs to accent-coloured surfaces, not to every prominent one.
 * Primary buttons stay white-on-black — that is Cheil's stark style and it is
 * already monochrome — and a blue halo around a white button reads as a
 * rendering fault rather than as branding.
 */

/* The active nav bar is the one place accent appears in navigation. */
.nav-item.active {
  box-shadow: inset 3px 0 14px -8px var(--accent), -1px 0 10px -5px var(--accent);
}

/* A light bloom on accent text, not a hard halo. */
.stat-value,
.state-locked {
  text-shadow: var(--glow-text);
}

/* Focus stays a solid outline; the glow supplements it and never replaces it,
   because a glow alone fails at high contrast and for low vision. */
:focus-visible {
  box-shadow: var(--glow-strong);
}

/* Accent-bordered chrome: lit from behind rather than merely outlined. */
input:focus,
select:focus,
textarea:focus,
.state-locked,
.tag-poll {
  box-shadow: var(--glow);
}

.live {
  color: var(--live);
  text-shadow: 0 0 10px rgba(255, 59, 48, 0.5);
}

.ok-text { color: var(--ok); }
.bad-text { color: var(--danger); }

/* ---------------------------------------------------------------------------
   Dashboard
   --------------------------------------------------------------------------- */

.campaign-strip {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.7rem 0.9rem;
  margin-bottom: 1.1rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent);
  box-shadow: inset 3px 0 16px -10px var(--accent);
}

.phase {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--line-strong);
  color: var(--fg-dim);
}
.phase-running { border-color: var(--ok); color: var(--ok); }
.phase-complete { border-color: var(--fg-faint); color: var(--fg-faint); }

/* Dashboard groups: a small uppercase heading separates each band of cards so
   the page scans as sections rather than a wall of tiles. */
.dash-group {
  margin: 1.8rem 0 0.7rem;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-faint);
}

/* Fixed two-up grid for the dashboard bands (three-up on wide screens),
   replacing the masonry that let cards land anywhere. */
.dash-grid {
  grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
}

.dash-live {
  margin-top: 0;
}

.dash-live-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}

.dash-live-head h2 {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.dash-live .live-dot.is-off {
  background: var(--fg-faint);
  box-shadow: none;
  animation: none;
}

.dash-live-table .row-dim {
  color: var(--fg-dim);
}

.dash-live-table .row-dim .link {
  color: var(--fg-dim);
}

.dash-live-table .tag {
  margin-left: 0.4rem;
}

.tag-live {
  border-color: var(--accent);
  color: var(--accent);
}

.dash-details {
  margin-top: 1rem;
  border-top: 1px solid var(--line);
  padding-top: 0.6rem;
}

.dash-details summary {
  cursor: pointer;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-dim);
  list-style: none;
}

.dash-details summary::before {
  content: '▸ ';
  color: var(--fg-faint);
}

.dash-details[open] summary::before {
  content: '▾ ';
}

/* The headline row is the "is the campaign healthy right now" answer, so it
   gets more weight than the stat rows inside cards. */
.dash-headline {
  margin-bottom: 1.4rem;
}
.dash-headline .stat {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 0.9rem 1rem;
}
.dash-headline .stat-value {
  font-size: 1.9rem;
}

.stat-hint {
  display: block;
  font-size: 0.66rem;
  color: var(--fg-faint);
  margin-top: 0.2rem;
}

/* --- Explanations for non-experts (Reports) --------------------------------- */

/* A word with a hover explanation. Dotted underline says "there is more here". */
.term {
  text-decoration: underline dotted;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--fg-faint);
  cursor: help;
}

.term:hover,
.term:focus {
  text-decoration-color: var(--accent);
  outline: none;
}

.stat-help {
  margin-left: 0.35rem;
  font-size: 0.72rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--fg-faint);
  cursor: help;
}

.stat-help:hover,
.stat-help:focus {
  color: var(--accent);
  outline: none;
}

/* "How to read this page": a collapsed glossary at the top of Reports. */
.reading-guide {
  margin: 0.75rem 0 1rem;
  border: 1px solid var(--line);
  background: var(--surface);
}

.reading-guide summary {
  cursor: pointer;
  padding: 0.6rem 0.9rem;
  font-size: 0.8rem;
  color: var(--fg-dim);
}

.reading-guide summary:hover {
  color: var(--fg);
}

.reading-guide dl {
  margin: 0;
  padding: 0.4rem 0.9rem 0.9rem;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.35rem 1rem;
  font-size: 0.78rem;
}

.reading-guide dt {
  color: var(--fg);
  font-weight: 600;
}

.reading-guide dd {
  margin: 0;
  color: var(--fg-dim);
}

@media (max-width: 720px) {
  .reading-guide dl {
    grid-template-columns: 1fr;
  }
}

.breakdown {
  list-style: none;
  margin: 0 0 0.9rem;
  padding: 0;
}
.breakdown li {
  display: flex;
  justify-content: space-between;
  padding: 0.32rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.82rem;
}
.breakdown li:last-child { border-bottom: 0; }
.breakdown .num { font-variant-numeric: tabular-nums; color: var(--fg-dim); }

/* Utilisation bar. Deliberately thin — at sub-1% usage the fill is a sliver,
   and that sliver is the honest picture. */
.budget-bar {
  height: 4px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  margin: 0.5rem 0 0.6rem;
  overflow: hidden;
}
.budget-fill {
  height: 100%;
  transition: width 300ms ease;
}
.budget-ok { background: var(--ok); }
.budget-warn { background: var(--warn); }
.budget-bad { background: var(--danger); }

/* ---------------------------------------------------------------------------
   Brand marks
   --------------------------------------------------------------------------- */

/*
 * The two supplied marks need different handling, because they were exported
 * differently.
 *
 * Cheil ships white with an alpha channel, so it is already correct for a black
 * console and is left alone.
 *
 * NCSOFT ships navy on an *opaque white* background — no alpha at all. Naively
 * filtering it to white would produce a solid white rectangle. Instead:
 *
 *   invert(1)      navy -> pale peach,      white -> black
 *   grayscale(1)   collapses hue, keeping the two far apart in luma
 *   brightness(2)  drives the artwork to pure white, leaves black at black
 *
 * which lands the artwork on rgb(255,255,255) and the background on
 * rgb(0,0,0) exactly. `mix-blend-mode: screen` then composites that black away
 * against whatever is behind it, so the mark keys cleanly without needing the
 * asset re-exported with transparency.
 */
/*
 * Optical sizing.
 *
 * The two files cannot be sized by their canvas heights, because they are
 * cropped differently — measured off the actual artwork:
 *
 *   Cheil   ink fills 89.7% of its canvas (5.2% padding top and bottom);
 *           cap-height-to-baseline is 85.2%; ink covers 58.1% of its own bbox
 *   NC      ink fills 99.9% — it bleeds edge to edge, no padding at all;
 *           ink covers 72.1% of its bbox, so it is ~24% denser
 *
 * Setting equal CSS heights therefore renders NC's artwork ~11% taller than
 * Cheil's, and the old 15/19px pairing made it 49% taller than Cheil's cap
 * height, which is what read as oversized.
 *
 * The fix is to match NC to Cheil's *cap height* rather than to its box, then
 * take a further allowance off for NC being the denser mark: a solid geometric
 * monogram reads heavier than letterforms at identical height.
 */
.brand-mark {
  display: block;
  width: auto;
}

.lockup {
  /* The Cheil mark's box height — the one number to change to rescale both. */
  --mark-box: 15px;
  /* Cheil cap-height as a fraction of its canvas (626/735), measured. */
  --cheil-cap: 0.852;
  /* Optical allowance for NC's greater ink density. */
  --nc-optical: 0.96;
}

.brand-mark-cheil {
  height: var(--mark-box);
}
.brand-mark-nc {
  height: calc(var(--mark-box) * var(--cheil-cap) * var(--nc-optical));
  filter: invert(1) grayscale(1) brightness(2);
  mix-blend-mode: screen;
}

/* Compact rescales from the same one number; the ratios carry over. */
.lockup-compact { --mark-box: 12px; }

/* ---------------------------------------------------------------------------
   Rich text editor (challenge descriptions)
   --------------------------------------------------------------------------- */

.rte {
  border: 1px solid var(--line-strong);
  background: var(--bg);
}
.rte-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  padding: 0.35rem;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  position: sticky;
  top: 0;
  z-index: 3;
}
.rte-toolbar select {
  padding: 0.25rem 0.4rem;
  font-size: 0.75rem;
}
.rte-btn {
  background: none;
  border: 1px solid transparent;
  color: var(--fg-dim);
  min-width: 2rem;
  padding: 0.3rem 0.45rem;
  font-size: 0.8rem;
  cursor: pointer;
  box-shadow: none;
}
.rte-btn:hover {
  color: var(--fg);
  background: var(--surface-2);
  box-shadow: none;
}
.rte-btn.active {
  color: var(--accent);
  border-color: var(--accent);
  box-shadow: var(--glow);
}
.rte-sep {
  width: 1px;
  height: 1.2rem;
  background: var(--line-strong);
  margin: 0 0.35rem;
}

.rte-surface {
  min-height: 22rem;
  padding: 1.1rem 1.3rem;
  font-size: 0.9rem;
  line-height: 1.65;
  outline: none;
  overflow-y: auto;
  max-height: 60vh;
}
.rte-surface:focus {
  box-shadow: inset 0 0 0 1px var(--accent), var(--glow);
}
.rte-disabled .rte-surface {
  opacity: 0.65;
  pointer-events: none;
}

/* Document vocabulary — shared by the editor and any rendered description. */
.rte-surface h1, .rte-render h1 { font-size: 1.5rem; margin: 1rem 0 0.5rem; }
.rte-surface h2, .rte-render h2 { font-size: 1.2rem; margin: 0.9rem 0 0.4rem; }
.rte-surface h3, .rte-render h3 { font-size: 1rem; margin: 0.8rem 0 0.3rem; }
.rte-surface p, .rte-render p { margin: 0 0 0.6rem; }
.rte-surface blockquote, .rte-render blockquote {
  border-left: 2px solid var(--accent);
  margin: 0.6rem 0;
  padding: 0.2rem 0 0.2rem 0.9rem;
  color: var(--fg-dim);
}
.rte-surface pre, .rte-render pre {
  background: var(--surface-2);
  border: 1px solid var(--line);
  padding: 0.6rem 0.8rem;
  overflow-x: auto;
  font-size: 0.8rem;
}
.rte-surface a, .rte-render a { color: var(--accent); }
.rte-surface hr, .rte-render hr { border: 0; border-top: 1px solid var(--line-strong); margin: 1rem 0; }
.rte-surface ul, .rte-surface ol, .rte-render ul, .rte-render ol { margin: 0 0 0.6rem 1.4rem; }

.align-center { text-align: center; }
.align-right { text-align: right; }

.rte-columns {
  display: flex;
  gap: 1.25rem;
  margin: 0.6rem 0;
}
.rte-column {
  flex: 1;
  min-width: 0;
  border: 1px dashed var(--line);
  padding: 0.5rem 0.7rem;
}
/* The dashed guide is an editing affordance, not content styling. */
.rte-render .rte-column { border: 0; padding: 0; }

/* ---------------------------------------------------------------------------
   Challenge pages
   --------------------------------------------------------------------------- */

.challenge-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(280px, 1fr);
  gap: 1rem;
  align-items: start;
}
@media (max-width: 980px) {
  .challenge-layout { grid-template-columns: 1fr; }
}

.deliverable-row {
  display: grid;
  grid-template-columns: 9rem 1fr auto auto;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.5rem;
}
.check.tiny { font-size: 0.72rem; display: flex; gap: 0.3rem; align-items: center; }

.state-draft { border-color: var(--line-strong); color: var(--fg-dim); }
.state-published { border-color: var(--ok); color: var(--ok); }
.state-archived { border-color: var(--fg-faint); color: var(--fg-faint); }

/* Link styled as a button, for nav-to-page actions beside real buttons. */
a.button {
  display: inline-flex;
  align-items: center;
  padding: 0.5rem 0.9rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  text-decoration: none;
}
a.button.ghost {
  border: 1px solid var(--line-strong);
  color: var(--fg);
}
a.button.ghost:hover { background: var(--surface-2); }

.error-banner {
  border: 1px solid var(--danger);
  color: var(--danger);
  padding: 0.7rem 0.9rem;
  font-size: 0.82rem;
  background: var(--surface);
}

/* Challenge configuration card: stacked document-form fields. Scoped to the
   direct children so the deliverable rows' inline checkbox label is untouched. */
.challenge-layout section.card > label {
  display: block;
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
  margin: 0.75rem 0 0.35rem;
}
.challenge-layout section.card > input,
.challenge-layout section.card > select {
  width: 100%;
  margin-bottom: 0.2rem;
}
.challenge-layout section.card > button {
  margin-top: 0.9rem;
}

/* --- Public site mode control (WFA-1) ------------------------------------- */

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.4rem 0 0.6rem;
}

/* --- Points ledger panel (I-2.1) ------------------------------------------- */

.row-voided td {
  opacity: 0.55;
  text-decoration: line-through;
}

.row-voided td .tag {
  text-decoration: none;
}

.tag-danger {
  color: var(--danger);
  border-color: var(--danger);
  margin-left: 0.35rem;
}

.adjust-form {
  margin-top: 1rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
}

.adjust-form input {
  width: 100%;
  margin-bottom: 0.35rem;
}

.adjust-form button {
  margin-top: 0.75rem;
}

/* --- Web traffic report (L-8) ----------------------------------------------- */

.section-title {
  margin-top: 1.5rem;
}

.ellip {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 16rem;
  display: inline-block;
  vertical-align: bottom;
}

.ip-add-row {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.75rem;
}

.ip-add-row input {
  flex: 1;
  min-width: 12rem;
}

.ip-add-row .muted {
  align-self: center;
}

/* Per-row action pairs (rename / remove) stay on one line. */
td.row-actions {
  white-space: nowrap;
}

td.row-actions button + button {
  margin-left: 0.4rem;
}

/* --- Account settings page --------------------------------------------------- */

.who-settings {
  margin-top: 0.35rem;
  display: inline-block;
}

.who-settings.active {
  color: var(--accent);
}

.settings-tz {
  max-width: 24rem;
  margin: 0.5rem 0;
}

/* --- Scheduled site-mode changes ----------------------------------------------- */

.schedule-row {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
  margin: 0.4rem 0;
}

.schedule-row select,
.schedule-row input {
  font-size: 0.78rem;
  padding: 0.35rem 0.45rem;
}

.schedule-row input[type='datetime-local'] {
  color-scheme: dark;
}

.schedule-row .schedule-reason {
  flex: 1;
  min-width: 12rem;
}

/* --- Inline session metrics (Telemetry) --------------------------------------- */

.row-expanded td {
  border-bottom: 0;
}

.metrics-row > td {
  background: var(--surface);
  border-left: 2px solid var(--accent);
  padding: 0.9rem 1rem 1.1rem;
}

.metrics-row .sub-head {
  margin-top: 0;
}

.metrics-row .stat-row {
  flex-wrap: wrap;
}

/* --- Custom report range ------------------------------------------------------ */

.range-inputs {
  display: flex;
  align-items: flex-end;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.range-inputs label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--fg-faint);
  font-weight: 600;
}

.range-inputs input[type='date'] {
  font-size: 0.78rem;
  padding: 0.3rem 0.4rem;
  color-scheme: dark;
}

/* --- Stream-times heatmap ----------------------------------------------------- */

.hm-card {
  overflow-x: auto;
}

.heatmap {
  display: grid;
  grid-template-columns: 2.4rem repeat(24, minmax(14px, 1fr));
  gap: 2px;
  margin: 0.75rem 0 0.5rem;
  min-width: 480px;
}

.hm-corner {
  /* the empty top-left cell */
}

.hm-hour,
.hm-day {
  font-size: 0.58rem;
  color: var(--fg-faint);
  font-variant-numeric: tabular-nums;
}

.hm-hour {
  text-align: left;
}

.hm-day {
  display: flex;
  align-items: center;
}

.hm-cell {
  aspect-ratio: 1 / 1;
  border-radius: 1px;
  min-height: 14px;
}

.hm-cell.hm-empty {
  background: transparent;
  border: 1px dashed var(--line);
}

/* Present but too few samples to trust — visibly tentative. */
.hm-cell.hm-thin {
  opacity: 0.45;
}

.hm-legend {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.25rem 0 0.5rem;
}

.hm-legend-bar {
  width: 120px;
  height: 8px;
  border-radius: 1px;
  background: linear-gradient(90deg, rgba(31, 158, 223, 0.06), rgba(31, 158, 223, 0.92));
}

.hm-detail {
  min-height: 1.4rem;
  font-size: 0.78rem;
  margin: 0.25rem 0 0;
  font-variant-numeric: tabular-nums;
}

/* --- Timezone picker (sidebar + reports) ------------------------------------- */

.tz-picker-block {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin: 0.5rem 0;
}

/* Inline variant for the Reports toolbar: wide enough to read a zone name. */
.tz-picker.tz-inline {
  min-width: 18rem;
}

.tz-picker.tz-inline input {
  font-size: 0.8rem;
  padding: 0.4rem 0.5rem;
}

.tz-label {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--fg-faint);
  font-weight: 600;
}

.tz-picker {
  position: relative;
}

.tz-picker input {
  width: 100%;
  font-size: 0.72rem;
  padding: 0.3rem 0.4rem;
  text-overflow: ellipsis;
}

.tz-list {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 30;
  margin: 0.2rem 0 0;
  padding: 0;
  list-style: none;
  max-height: 15rem;
  overflow-y: auto;
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
}

.tz-option {
  padding: 0.35rem 0.5rem;
  font-size: 0.72rem;
  cursor: pointer;
  color: var(--fg-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tz-option.is-highlighted {
  background: var(--surface);
  color: var(--fg);
}

.tz-option.is-current {
  color: var(--accent);
}

.tz-empty {
  padding: 0.35rem 0.5rem;
  font-size: 0.68rem;
  color: var(--fg-faint);
}

/* --- Reports: period tabs + trend charts ------------------------------------ */

.period-tabs {
  display: flex;
  gap: 0.4rem;
  align-items: center;
}

.period-tab {
  background: transparent;
  border: 1px solid var(--line);
  color: var(--fg-dim, inherit);
}

.period-tab.active {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: var(--glow);
}

.trend {
  position: relative;
}

.trend-svg {
  width: 100%;
  height: auto;
  display: block;
}

.trend-grid {
  stroke: rgba(255, 255, 255, 0.07);
  stroke-width: 1;
}

.trend-crosshair {
  stroke: rgba(255, 255, 255, 0.25);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

/* Axis text wears text tokens, never the series colour. */
.trend-tick {
  fill: var(--fg-faint);
  font-size: 10px;
  font-family: inherit;
}

.trend-tip {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  background: var(--invert-bg, #fff);
  color: var(--invert-fg, #000);
  border-radius: 2px;
  padding: 0.25rem 0.55rem;
  font-size: 0.72rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: none;
  white-space: nowrap;
}

.trend-tip span {
  opacity: 0.7;
  font-size: 0.62rem;
}

/* Live indicator dot (dashboard live list). */
.live-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--live);
  box-shadow: 0 0 8px var(--live);
  animation: live-pulse 1.6s ease-in-out infinite;
}

@keyframes live-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}

/* --- Clip submissions ------------------------------------------------------- */

.state-pending { border-color: var(--accent); color: var(--accent); }
.state-approved { border-color: var(--ok); color: var(--ok); }
.state-declined { border-color: var(--fg-faint); color: var(--fg-faint); }

/* --- Off-platform completions (War Orders, Wildcards) ----------------------- */
/* Prefixed so a completion status never collides with a roster or challenge
   state chip of the same word ("pending" belongs to both). */

.state-completion-complete { border-color: var(--ok); color: var(--ok); }
.state-completion-incomplete { border-color: var(--fg-faint); color: var(--fg-faint); }
.state-completion-not_applicable { border-color: var(--line-strong); color: var(--fg-dim); }
.state-completion-pending { border-color: var(--accent); color: var(--accent); }

/* The status legend on the assessment page: label and meaning on one line,
   reading left to right rather than pushed to opposite edges. */
.status-key > div {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--line);
}
.status-key > div:last-child { border-bottom: 0; }
.status-key dt {
  font-weight: 700;
  min-width: 9rem;
}
.status-key dd { margin: 0; }

.code-chip {
  display: inline-block;
  padding: 0.2rem 0.55rem;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--fg);
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
}

.code-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0.5rem 0 0.75rem;
  /* Limit names are long sentences now ("Once per scoring period, when that
     period's total reaches n"), so the row wraps rather than pushing the
     number field out of its card. */
  flex-wrap: wrap;
}

.code-row > select,
.code-row > input {
  min-width: 0;
}
.code-row > select {
  flex: 1 1 16rem;
}

.sub-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.sub-row {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr) auto;
  gap: 1rem;
  align-items: start;
  margin: 0;
}

.sub-row.sub-declined {
  opacity: 0.7;
}

.sub-thumb {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  background: var(--surface-2);
  border: 1px solid var(--line);
  overflow: hidden;
}

.sub-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.sub-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.6rem;
  color: #fff;
  background: rgba(0, 0, 0, 0.25);
  opacity: 0;
  transition: opacity 0.15s;
}

.sub-thumb:hover .sub-play {
  opacity: 1;
}

.sub-main {
  min-width: 0;
}

.sub-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 0.3rem;
}

.sub-title {
  font-weight: 600;
  font-size: 0.95rem;
}

.sub-meta {
  margin: 0.15rem 0;
  font-size: 0.8rem;
}

.sub-meta .tag {
  margin-left: 0.4rem;
}

.tag-warn {
  border-color: var(--warn);
  color: var(--warn);
}

.sub-actions {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 8rem;
}

.sub-actions button,
.sub-actions .link {
  margin-top: 0;
  align-self: stretch;
}

@media (max-width: 720px) {
  .sub-row {
    grid-template-columns: minmax(0, 1fr);
  }
  .sub-thumb {
    max-width: 320px;
  }
}
