/* ===========================================================
   NEON — the Music Studio look, applied everywhere
   -----------------------------------------------------------
   Loaded after styles.css on every page. It does two jobs:

   1. Re-paints the existing dark theme in violet rather than blue.
      Because styles.css is built on 154 design tokens, redefining
      about thirty of them re-skins all twenty pages at once —
      every card, button, input and panel that already reads from
      them. Nothing here restyles a component that already works.

   2. Adds the pieces the old design had no equivalent for: the
      artwork hero, the picture tiles that replace dropdowns, the
      gradient generate bar, the credit pill and the mobile bottom
      bar. Those are new components, named nx- so they cannot
      collide with anything in styles.css.

   Dark is the design now. Light still works — every token below
   lives under [data-theme="dark"] — but the bootstrap in config.js
   starts there unless somebody has chosen otherwise.
   =========================================================== */

:root[data-theme="dark"] {
  /* The page: a violet black, deep enough that the glow has somewhere to sit. */
  --bg:            #0A0616;
  --surface:       #150C28;
  --surface-2:     #1D1236;

  /* Borders carry a little of the accent, which is what makes a dark
     interface read as lit rather than as grey boxes on black. */
  --border:        rgba(167, 139, 250, 0.16);
  --border-strong: rgba(167, 139, 250, 0.34);

  --text:          #F4EFFF;
  --text-dim:      #B8A8DC;
  --text-faint:    #8B7BB4;

  --accent:        #A855F7;
  --accent-strong: #C026D3;
  --accent-dim:    rgba(168, 85, 247, 0.16);
  --beam:          linear-gradient(115deg, #7C3AED 0%, #A855F7 50%, #C026D3 100%);
  --on-accent:     #FFFFFF;

  --gold:          #FFC53D;
  --gold-dim:      rgba(255, 197, 61, 0.14);

  --success:       #34D399;
  --success-dim:   rgba(52, 211, 153, 0.14);
  --warn:          #FBBF24;
  --danger:        #FB7185;

  --shadow:        0 24px 70px -30px rgba(0, 0, 0, 0.9);
  --shadow-sm:     0 10px 26px -14px rgba(0, 0, 0, 0.75);
  --glow:          0 0 0 1px rgba(168, 85, 247, 0.28), 0 18px 48px -20px rgba(168, 85, 247, 0.55);
  --scrim:         rgba(5, 2, 14, 0.76);
  --nav-blur:      rgba(10, 6, 22, 0.86);

  /* Used by the new components below. */
  --nx-glass:      rgba(29, 18, 54, 0.66);
  --nx-glass-edge: rgba(167, 139, 250, 0.20);
  --nx-ink-glow:   0 0 24px rgba(168, 85, 247, 0.45);
}

/* A faint violet wash over the whole page, fixed so it does not scroll
   away. Behind everything, and never in the way of a click. */
:root[data-theme="dark"] body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(1100px 620px at 78% -8%, rgba(124, 58, 237, 0.26), transparent 62%),
    radial-gradient(820px 520px at 6% 4%, rgba(192, 38, 211, 0.16), transparent 58%),
    radial-gradient(900px 700px at 50% 108%, rgba(88, 28, 135, 0.22), transparent 64%);
}
:root[data-theme="dark"] body > * { position: relative; z-index: 1; }

/*
 * Except anything that is meant to sit over the page.
 *
 * The rule above lifts every direct child of body above the wash, and it does
 * so with enough specificity to beat a plain class — so a dialog appended to
 * body came out at z-index 1 and rendered behind the page it was covering. It
 * was open, full height and fully opaque, and invisible. The ads studio's ask
 * modal is built the same way and would have gone the same way.
 *
 * It takes the position too, not only the z-index. "position: relative" put the
 * dialog back into the flow of the page, so it was laid out underneath
 * everything at 7900px down the document while claiming to be fixed.
 */
:root[data-theme="dark"] body > .offer-wrap { position: fixed; inset: 0; z-index: 300; }
:root[data-theme="dark"] body > .ask-wrap   { position: fixed; inset: 0; z-index: 260; }
:root[data-theme="dark"] body > dialog,
:root[data-theme="dark"] body > [role="dialog"] { position: fixed; z-index: 300; }

/* ---------- putting the gradient back on the main button ----------

   styles.css declares .btn-primary three times, and the last one wins:
   background: var(--text), which in a dark theme is near-white. So every
   primary button on the site — Log in, Generate, Save — rendered as a white
   slab with dark text. That was an "ink button" from a later pass and it
   fights this design. Restored here, under the dark theme only, so the light
   palette keeps whatever it had.                                            */

:root[data-theme="dark"] .btn-primary {
  background: var(--beam);
  color: var(--on-accent);
  border-color: transparent;
  box-shadow: var(--glow);
}
:root[data-theme="dark"] .btn-primary:hover {
  background: var(--beam);
  filter: brightness(1.09);
  box-shadow: var(--glow);
}
:root[data-theme="dark"] .mini-btn.primary {
  background: var(--beam);
  color: var(--on-accent);
  border-color: transparent;
}

/* ---------- the two palettes that were not the main one ----------

   The sidebar came back as #0E1526 — the old blue-grey — while every page
   around it had gone violet, because the design tokens are not all in one
   place. studio.css carries a parallel set for anything inside .sx, and the
   rail has its own block in styles.css. Neither reads from the tokens at the
   top of this file, so both are mapped onto the new palette here.          */

/* Declared at :root[data-theme="dark"] and not plain :root, because styles.css
   sets --rail in both and the dark one is the more specific selector — a plain
   :root here loses to it however late this file is loaded. */
:root[data-theme="dark"] {
  --rail:         #120A24;
  --rail-2:       #1A0F31;
  --rail-border:  rgba(167, 139, 250, .12);
  --rail-text:    rgba(244, 239, 255, .72);
  --rail-text-on: #FFFFFF;
  --rail-faint:   rgba(244, 239, 255, .38);
  --rail-hover:   rgba(168, 85, 247, .10);
  --rail-active:  rgba(168, 85, 247, .18);
}

:root[data-theme="dark"] .sx {
  --ink: #F4EFFF; --ink2: #D6CBEF; --muted: #B8A8DC; --faint: #8B7BB4;
  --paper: #0A0616; --card: #150C28; --card2: #1D1236;
  --line: rgba(167, 139, 250, .16); --line2: rgba(167, 139, 250, .10);
  --chip: #241642; --field: #1D1236;
  --brand: #A855F7; --brand2: #C026D3;
  --brand-soft: #2A1550; --brand-line: #5B21B6;
  --busy: #C084FC; --busybg: rgba(192, 132, 252, .16);
  --glow-a: rgba(168, 85, 247, .24); --glow-b: rgba(192, 38, 211, .14);
  --title-grad: linear-gradient(90deg, #A855F7, #C026D3);
}

/* Four separate rules in styles.css set a background on .sidebar — var(--surface),
   var(--nav-blur) under a 900px media query, var(--rail), and a gradient — and
   which one wins depends on the viewport. Rather than add a fifth to the argument
   at the same specificity, this one is stated for both widths and left alone.
   An opaque panel also gains nothing from blurring what is behind it. */
:root[data-theme="dark"] .sidebar {
  background: linear-gradient(180deg, var(--rail-2) 0%, var(--rail) 38%, var(--rail) 100%);
  backdrop-filter: none;
}
@media (max-width: 900px) {
  :root[data-theme="dark"] .sidebar {
    background: linear-gradient(180deg, var(--rail-2) 0%, var(--rail) 38%, var(--rail) 100%);
    backdrop-filter: none;
  }
}

/* ---------- the hero ---------- */

.nx-hero {
  position: relative;
  overflow: hidden;
  border-radius: 22px;
  border: 1px solid var(--nx-glass-edge);
  background: var(--nx-glass);
  padding: 34px 32px;
  margin-bottom: 22px;
}
.nx-hero::after {
  /* The artwork sits on the right and fades into the panel rather than
     stopping at an edge, so no image is ever cut off mid-face. */
  content: "";
  position: absolute;
  inset: 0 0 0 40%;
  background-image: var(--nx-hero-art, none);
  background-size: cover;
  background-position: center right;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 38%);
  mask-image: linear-gradient(90deg, transparent, #000 38%);
  opacity: 0.85;
  pointer-events: none;
}
.nx-hero > * { position: relative; z-index: 1; max-width: 62%; }

.nx-hero h1 {
  font-family: var(--font-display, inherit);
  font-size: clamp(30px, 4.6vw, 54px);
  line-height: 1.04;
  letter-spacing: -0.02em;
  margin: 0 0 10px;
}
.nx-hero h1 .lit {
  background: var(--beam);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.nx-hero p { color: var(--text-dim); font-size: 15.5px; margin: 0; }

/* ---------- picture tiles (Song Type) ---------- */

.nx-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}
.nx-tile {
  position: relative;
  display: block;
  border: 1.5px solid var(--border);
  border-radius: 16px;
  overflow: hidden;
  background: var(--surface-2);
  cursor: pointer;
  text-align: left;
  padding: 0;
  color: inherit;
  font: inherit;
  transition: transform .18s var(--ease, ease), border-color .18s, box-shadow .18s;
}
.nx-tile:hover { transform: translateY(-2px); border-color: var(--border-strong); }
.nx-tile[aria-pressed="true"], .nx-tile.on {
  border-color: var(--accent);
  box-shadow: var(--glow);
}
.nx-tile-art {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background:
    linear-gradient(140deg, rgba(124, 58, 237, .5), rgba(192, 38, 211, .35)),
    var(--surface-2);
}
.nx-tile-name {
  display: block;
  padding: 11px 13px 13px;
  font-weight: 650;
  font-size: 14.5px;
}
.nx-tile .nx-check {
  position: absolute;
  top: 9px; right: 9px;
  width: 22px; height: 22px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--beam);
  color: #fff;
  font-size: 12px;
  opacity: 0;
  transform: scale(.7);
  transition: opacity .18s, transform .18s var(--ease, ease);
}
.nx-tile[aria-pressed="true"] .nx-check, .nx-tile.on .nx-check { opacity: 1; transform: scale(1); }

/* ---------- small square tiles (Mood) ---------- */

.nx-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 10px;
}
.nx-cell {
  border: 1.5px solid var(--border);
  border-radius: 14px;
  background: var(--surface-2);
  padding: 14px 8px 11px;
  display: grid;
  gap: 6px;
  place-items: center;
  cursor: pointer;
  color: inherit;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  transition: transform .16s var(--ease, ease), border-color .16s, box-shadow .16s;
}
.nx-cell:hover { transform: translateY(-2px); border-color: var(--border-strong); }
.nx-cell[aria-pressed="true"], .nx-cell.on { border-color: var(--accent); box-shadow: var(--glow); }
.nx-cell .nx-ico { font-size: 20px; line-height: 1; }

/* ---------- quick-pick chips ---------- */

.nx-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.nx-chip {
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-dim);
  border-radius: 999px;
  padding: 7px 15px;
  font: inherit;
  font-size: 13.5px;
  cursor: pointer;
  transition: border-color .16s, color .16s, background .16s;
}
.nx-chip:hover { color: var(--text); border-color: var(--border-strong); }
.nx-chip[aria-pressed="true"], .nx-chip.on {
  border-color: transparent;
  background: var(--beam);
  color: #fff;
}

/* ---------- the generate bar ---------- */

.nx-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  border: 0;
  border-radius: 16px;
  padding: 16px 22px;
  background: var(--beam);
  color: #fff;
  font: inherit;
  font-size: 16.5px;
  font-weight: 700;
  letter-spacing: .01em;
  cursor: pointer;
  box-shadow: var(--glow);
  transition: transform .16s var(--ease, ease), filter .16s;
}
.nx-go:hover { transform: translateY(-1px); filter: brightness(1.08); }
.nx-go:active { transform: translateY(0) scale(.995); }
.nx-go:disabled { opacity: .55; cursor: not-allowed; transform: none; filter: none; }
.nx-go .nx-cost {
  font-size: 14px;
  font-weight: 600;
  opacity: .9;
  padding-left: 10px;
  border-left: 1px solid rgba(255, 255, 255, .3);
}

/* ---------- the credit pill and upgrade ---------- */

.nx-credits {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--gold-dim);
  background: var(--gold-dim);
  color: var(--gold);
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 13.5px;
  font-weight: 650;
}
.nx-upgrade {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid rgba(255, 197, 61, .45);
  background: linear-gradient(120deg, rgba(255, 197, 61, .16), rgba(255, 197, 61, .05));
  color: var(--gold);
  border-radius: 999px;
  padding: 8px 16px;
  font: inherit;
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  transition: filter .16s, transform .16s var(--ease, ease);
}
.nx-upgrade:hover { filter: brightness(1.12); transform: translateY(-1px); }

/* The free-music counter: three songs, spent one at a time. */
.nx-free {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 13.5px;
  font-weight: 650;
  border: 1px solid var(--border-strong);
  background: var(--accent-dim);
  color: var(--text);
}
.nx-free .nx-pips { display: inline-flex; gap: 4px; }
.nx-free .nx-pip {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--beam);
}
.nx-free .nx-pip.spent { background: var(--border-strong); }

/* ---------- panels ---------- */

.nx-panel {
  border: 1px solid var(--nx-glass-edge);
  border-radius: 18px;
  background: var(--nx-glass);
  padding: 18px;
}
.nx-panel-head {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 14px;
}
.nx-panel-head .nx-ico {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 11px;
  background: var(--accent-dim);
  color: var(--accent);
  font-size: 16px;
}
.nx-panel-head b { display: block; font-size: 15px; }
.nx-panel-head small { display: block; color: var(--text-faint); font-size: 12.5px; }

/* ---------- the studio's own top bar ---------- */

.nx-top {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  padding: 14px 0 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 18px;
}
.nx-top-id { display: flex; align-items: center; gap: 12px; }
.nx-top-id .nx-mark {
  width: 46px; height: 46px; flex: none;
  border-radius: 14px;
  display: grid; place-items: center;
  background: var(--beam);
  box-shadow: var(--glow);
  font-size: 22px;
}
.nx-top-id b { display: block; font-family: var(--font-display, inherit); font-size: 22px; line-height: 1.1; }
.nx-top-id small { display: block; color: var(--text-dim); font-size: 13px; }

.nx-tabs { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.nx-tab {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid transparent;
  background: none;
  color: var(--text-dim);
  border-radius: 999px;
  padding: 9px 16px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: color .16s, background .16s, border-color .16s;
}
.nx-tab:hover { color: var(--text); background: var(--surface-2); }
.nx-tab.on {
  background: var(--beam);
  color: #fff;
  border-color: transparent;
  box-shadow: var(--glow);
}
.nx-top-end { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* ---------- the composer: the box and the button side by side ---------- */

.nx-compose {
  display: grid;
  grid-template-columns: 1fr 280px;
  gap: 16px;
  align-items: stretch;
  border: 1px solid var(--nx-glass-edge);
  border-radius: 20px;
  background: var(--nx-glass);
  padding: 16px;
  margin-bottom: 16px;
}
.nx-compose-main { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.nx-compose textarea {
  width: 100%;
  min-height: 96px;
  resize: vertical;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  padding: 14px 15px;
}
.nx-compose-side { display: flex; flex-direction: column; justify-content: center; gap: 10px; }
.nx-count { font-size: 12.5px; color: var(--text-faint); text-align: right; }

@media (max-width: 860px) {
  .nx-compose { grid-template-columns: 1fr; }
  .nx-compose-side { flex-direction: column-reverse; }
}

/* ---------- the drop zone ----------

   A bare <input type="file"> paints its own button out of the operating
   system's parts and ignores almost everything you tell it, which is why that
   grey "Choose File" sat in the middle of a violet panel looking like it had
   wandered in from another program. The input is still there and still does
   the work — it is the label that is visible, and a label click opens the file
   picker on its own, so nothing here depends on script to be usable.        */

.nx-drop {
  display: grid;
  place-items: center;
  gap: 8px;
  padding: 26px 18px;
  border: 1.5px dashed var(--border-strong);
  border-radius: 16px;
  background: var(--surface-2);
  color: var(--text-dim);
  text-align: center;
  cursor: pointer;
  transition: border-color .18s, background .18s, transform .18s var(--ease, ease);
}
.nx-drop:hover { border-color: var(--accent); background: var(--accent-dim); }
.nx-drop.over {
  border-color: var(--accent);
  background: var(--accent-dim);
  transform: scale(1.01);
  box-shadow: var(--glow);
}
.nx-drop input[type="file"] {
  /* Reachable by keyboard and by assistive software, simply not drawn. */
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.nx-drop .nx-drop-ico {
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 14px;
  background: var(--accent-dim);
  color: var(--accent);
  font-size: 22px;
}
.nx-drop b { font-size: 14.5px; color: var(--text); font-weight: 650; }
.nx-drop small { font-size: 12.5px; color: var(--text-faint); }
.nx-drop .nx-drop-btn {
  margin-top: 4px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  border-radius: 10px;
  padding: 8px 16px;
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
}
.nx-drop:hover .nx-drop-btn { border-color: var(--accent); }

/* ---------- the free-music offer ----------

   Shown once to somebody who has not signed in, on the way past the landing
   page. It is the first thing a new visitor is asked to do, so it gets the
   artwork and the full-width button; everything else on it is one sentence. */

.offer-wrap {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  padding: 18px;
  background: rgba(5, 2, 14, .74);
  backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity .22s ease;
}
.offer-wrap.on { opacity: 1; }

.offer {
  position: relative;
  width: min(1120px, 100%);
  max-height: calc(100dvh - 36px);
  overflow: auto;
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  border-radius: 26px;
  border: 1px solid rgba(192, 38, 211, .42);
  background:
    radial-gradient(900px 500px at 88% 10%, rgba(192, 38, 211, .22), transparent 60%),
    #140A26;
  box-shadow: 0 40px 120px -40px rgba(192, 38, 211, .6), 0 0 0 1px rgba(168, 85, 247, .18);
  transform: translateY(14px) scale(.985);
  transition: transform .26s var(--ease, cubic-bezier(.2, .9, .3, 1));
}
.offer-wrap.on .offer { transform: none; }

.offer-left { padding: 34px 34px 30px; min-width: 0; }

.offer-brand { display: flex; align-items: center; gap: 11px; margin-bottom: 20px; }
.offer-brand img { width: 42px; height: 42px; border-radius: 12px; }
.offer-brand b { display: block; font-size: 17px; }
.offer-brand small { display: block; color: var(--text-dim); font-size: 13px; }

.offer-badge {
  display: inline-flex; align-items: center; gap: 9px;
  border: 1px solid rgba(255, 197, 61, .5);
  background: rgba(255, 197, 61, .10);
  color: #FFC53D;
  border-radius: 999px;
  padding: 9px 18px;
  font-size: 12.5px;
  font-weight: 750;
  letter-spacing: .09em;
  text-transform: uppercase;
  margin-bottom: 18px;
}

.offer h2 {
  font-family: var(--font-display, inherit);
  font-size: clamp(30px, 3.4vw, 46px);
  line-height: 1.07;
  letter-spacing: -.02em;
  margin: 0 0 14px;
}
.offer h2 .lit {
  background: linear-gradient(95deg, #FFC53D 0%, #F472B6 45%, #C026D3 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.offer-sub { color: var(--text-dim); font-size: 15.5px; line-height: 1.55; margin: 0 0 22px; }

.offer-points {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 24px;
}
.offer-point {
  border: 1px solid var(--nx-glass-edge);
  border-radius: 14px;
  background: rgba(29, 18, 54, .6);
  padding: 14px 10px;
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.35;
}
.offer-point .ico {
  display: grid; place-items: center;
  width: 38px; height: 38px;
  margin: 0 auto 9px;
  border-radius: 11px;
  background: var(--accent-dim);
  color: var(--accent);
  font-size: 18px;
}

.offer-go {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%;
  border: 0; border-radius: 15px;
  padding: 18px 24px;
  background: linear-gradient(95deg, #7C3AED, #C026D3 55%, #DB2777);
  color: #fff;
  font: inherit; font-size: 17px; font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 16px 40px -16px rgba(192, 38, 211, .9);
  transition: transform .16s var(--ease, ease), filter .16s;
}
.offer-go:hover { transform: translateY(-1px); filter: brightness(1.08); }
.offer-foot { margin: 12px 0 0; font-size: 12.5px; color: var(--text-faint); text-align: center; }

/* The picture, with the genres floating over it. */
.offer-art { position: relative; border-radius: 0 26px 26px 0; overflow: hidden; min-height: 420px; }
.offer-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.offer-art::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, #140A26 0%, rgba(20, 10, 38, .3) 34%, transparent 62%);
}
.offer-pill {
  position: absolute; z-index: 2;
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(20, 10, 38, .62);
  backdrop-filter: blur(6px);
  color: #fff;
  border-radius: 999px;
  padding: 8px 15px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
.offer-close {
  position: absolute; top: 16px; right: 16px; z-index: 3;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .22);
  background: rgba(20, 10, 38, .6);
  color: #fff;
  font-size: 17px;
  cursor: pointer;
}
.offer-close:hover { background: rgba(192, 38, 211, .32); }

@media (max-width: 900px) {
  .offer { grid-template-columns: 1fr; }
  .offer-art { grid-row: 1; min-height: 190px; border-radius: 26px 26px 0 0; }
  .offer-art::after { background: linear-gradient(180deg, transparent 40%, #140A26 100%); }
  /* The pills crowd a small picture; the words below carry the same meaning. */
  .offer-pill { display: none; }
  .offer-left { padding: 22px 20px 26px; }
  .offer-points { grid-template-columns: repeat(2, 1fr); }
}

/* ---------- the library pages ---------- */

.nx-tools {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 18px;
}
.nx-search, .nx-sort {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: 14px;
  padding: 11px 14px;
}
.nx-search { flex: 1; min-width: 200px; }
.nx-search:focus, .nx-sort:focus { outline: none; border-color: var(--accent); box-shadow: var(--glow); }

.nx-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
}
.nx-card {
  border: 1px solid var(--nx-glass-edge);
  border-radius: 16px;
  background: var(--nx-glass);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.nx-card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.nx-card-head b { font-size: 15.5px; }
.nx-card-body { color: var(--text-dim); font-size: 13.5px; line-height: 1.5; margin: 0; }
.nx-card audio { width: 100%; }

/* A song with no cover still needs to be a card rather than a gap. */
.rec-art {
  aspect-ratio: 1;
  border-radius: 14px;
  overflow: hidden;
  background: var(--surface-2);
  display: grid;
  place-items: center;
  margin-bottom: 12px;
}
.rec-art img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rec-art-fallback { font-size: 34px; color: var(--accent); }

/* ---------- the settings row ---------- */

.nx-row {
  display: grid;
  grid-template-columns: 1.3fr 1.2fr 1fr;
  gap: 14px;
  margin: 16px 0;
}
@media (max-width: 1080px) { .nx-row { grid-template-columns: 1fr 1fr; } }
@media (max-width: 760px)  { .nx-row { grid-template-columns: 1fr; } }

/* Each tile's own colour, handed in from the markup so a new tile needs no CSS. */
/* A photograph when one is given (set inline), the gradient when not. Sized here
   so a new tile needs nothing but its picture. */
.nx-tile-art {
  background-color: var(--surface-2);
  background-image: var(--tint, var(--beam));
  background-size: cover;
  background-position: center;
}

/* ---------- the generate row ---------- */

.nx-golaunch {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0 22px;
}
.nx-golaunch .nx-go { flex: 1; }
.nx-golaunch-aside { display: flex; gap: 8px; flex-shrink: 0; }

@media (max-width: 620px) {
  .nx-golaunch { flex-direction: column-reverse; align-items: stretch; }
  .nx-golaunch-aside { justify-content: center; }
}

/* ---------- the mobile bottom bar ---------- */

.nx-bottom { display: none; }

@media (max-width: 900px) {
  .nx-hero { padding: 24px 20px; border-radius: 18px; }
  .nx-hero > * { max-width: 100%; }
  .nx-hero::after { inset: 0; opacity: .3; -webkit-mask-image: none; mask-image: none; }

  .nx-bottom {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 90;
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    align-items: end;
    gap: 2px;
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--nav-blur);
    backdrop-filter: blur(14px);
    border-top: 1px solid var(--border);
  }
  .nx-bottom a {
    display: grid;
    justify-items: center;
    gap: 3px;
    padding: 6px 2px;
    font-size: 11px;
    color: var(--text-faint);
    text-decoration: none;
  }
  .nx-bottom a.on { color: var(--accent); }
  .nx-bottom a .nx-ico { font-size: 19px; line-height: 1; }
  /* The centre action sits proud of the bar, the way the mock has it. */
  .nx-bottom .nx-fab {
    width: 54px; height: 54px;
    margin-bottom: 6px;
    border-radius: 50%;
    display: grid; place-items: center;
    background: var(--beam);
    color: #fff;
    font-size: 24px;
    box-shadow: var(--glow);
  }
  /* Nothing is hidden behind the bar. */
  body.has-bottom-nav { padding-bottom: 86px; }
}

/* A phone keyboard must never be covered by a sticky action. */
@media (max-width: 900px) and (max-height: 460px) {
  .nx-bottom { display: none; }
  body.has-bottom-nav { padding-bottom: 0; }
}
