/* Duo web — a dark, glassy surface warmed by a violet→rose signature. */

:root {
  /* Neutrals carry a faint violet so the dark never reads as dead grey. */
  --bg: #0b0a0e;
  --bg-raise: #16141c;
  --glass: rgba(255, 255, 255, 0.035);
  --glass-strong: rgba(255, 255, 255, 0.065);
  --edge: rgba(255, 255, 255, 0.08);
  --edge-strong: rgba(255, 255, 255, 0.16);
  --text: #f5f4f7;
  --text-dim: #a09ead;
  --text-faint: #625f6e;
  --danger: #f0798a;
  --ok: #8fe3b0;
  --warn: #e6b45c;

  /* The one brand gesture, used sparingly: active states, primary action,
     the wordmark, focus rings. */
  --accent: #8b6cff;
  --accent-2: #ff6b9d;
  --accent-grad: linear-gradient(135deg, #8b6cff 0%, #b45cff 45%, #ff6b9d 100%);
  --accent-soft: rgba(139, 108, 255, 0.16);
  --accent-ring: rgba(139, 108, 255, 0.45);
  /* Text on an accent-filled surface. White for every coloured accent;
     mono flips it so black-on-white / white-on-black stays readable. */
  --on-accent: #fff;

  --ring-speaking: #57c78a;
  --ring-width: 3px;

  --glow-1: rgba(139, 108, 255, 0.18);
  --glow-2: rgba(255, 107, 157, 0.12);
  --font-body:
    ui-sans-serif, -apple-system, "Segoe UI", Inter, Roboto, sans-serif;

  --radius: 14px;
  --radius-lg: 20px;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.28);
  --shadow-lift:
    0 2px 4px rgba(0, 0, 0, 0.45), 0 16px 40px rgba(0, 0, 0, 0.42),
    0 0 0 1px var(--accent-ring);
}

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

html {
  height: 100%;
}

/* ── Appearance variants ─────────────────────────────────────────────
   Three data attributes on <html>, set before first paint. Everything a
   theme changes is a custom property; components never branch. */

:root[data-theme="light"] {
  /* True neutrals. Dark mode's faint violet is what keeps it from reading
     as dead grey; carried into light it reads as a purple wash over the
     whole page. In light, only the accent gets to be a color. */
  --bg: #f5f5f6;
  --bg-raise: #ffffff;
  --glass: rgba(12, 12, 14, 0.03);
  --glass-strong: rgba(12, 12, 14, 0.055);
  --edge: rgba(12, 12, 14, 0.1);
  --edge-strong: rgba(12, 12, 14, 0.2);
  --text: #1b1b1f;
  --text-dim: #55555c;
  --text-faint: #8e8e94;
  --danger: #d4425a;
  --ok: #1f9a5e;
  --warn: #b7801f;
  --glow-1: rgba(139, 108, 255, 0.14);
  --glow-2: rgba(255, 107, 157, 0.1);
  --shadow-card:
    0 1px 2px rgba(28, 20, 60, 0.08), 0 8px 24px rgba(28, 20, 60, 0.08);
  --shadow-lift:
    0 2px 4px rgba(28, 20, 60, 0.1), 0 16px 40px rgba(28, 20, 60, 0.14),
    0 0 0 1px var(--accent-ring);
}

:root[data-accent="ember"] {
  --accent: #ff8a5c;
  --accent-2: #ff5c7a;
  --accent-grad: linear-gradient(135deg, #ff8a5c 0%, #ff6b62 45%, #ff5c7a 100%);
  --accent-soft: rgba(255, 138, 92, 0.16);
  --accent-ring: rgba(255, 138, 92, 0.45);
  --glow-1: rgba(255, 138, 92, 0.16);
  --glow-2: rgba(255, 92, 122, 0.12);
}
:root[data-accent="ocean"] {
  --accent: #5cb8ff;
  --accent-2: #7a5cff;
  --accent-grad: linear-gradient(135deg, #5cb8ff 0%, #6b8aff 45%, #7a5cff 100%);
  --accent-soft: rgba(92, 184, 255, 0.16);
  --accent-ring: rgba(92, 184, 255, 0.45);
  --glow-1: rgba(92, 184, 255, 0.16);
  --glow-2: rgba(122, 92, 255, 0.12);
}
:root[data-accent="meadow"] {
  --accent: #4ed99a;
  --accent-2: #5cb8ff;
  --accent-grad: linear-gradient(135deg, #4ed99a 0%, #4ecbc0 45%, #5cb8ff 100%);
  --accent-soft: rgba(78, 217, 154, 0.16);
  --accent-ring: rgba(78, 217, 154, 0.45);
  --glow-1: rgba(78, 217, 154, 0.14);
  --glow-2: rgba(92, 184, 255, 0.12);
}
:root[data-accent="mono"] {
  /* Ultimate sleek: the accent is simply the opposite of the page.
     Flat fills, no gradient, no ambient glow. */
  --accent: #f5f4f7;
  --accent-2: #f5f4f7;
  --accent-grad: linear-gradient(#f5f4f7, #f5f4f7);
  --accent-soft: rgba(255, 255, 255, 0.1);
  --accent-ring: rgba(255, 255, 255, 0.38);
  --on-accent: #101014;
  --glow-1: transparent;
  --glow-2: transparent;
}
:root[data-theme="light"][data-accent="mono"] {
  --accent: #17171b;
  --accent-2: #17171b;
  --accent-grad: linear-gradient(#17171b, #17171b);
  --accent-soft: rgba(12, 12, 14, 0.08);
  --accent-ring: rgba(12, 12, 14, 0.4);
  --on-accent: #fff;
  --glow-1: transparent;
  --glow-2: transparent;
}

/* Light mode's ambient glow, restated after the accent blocks so it wins:
   keyed to the chosen accent and kept faint. The hard-coded violet pair it
   replaces washed every light page purple no matter the accent — which is
   why panes with a flat white surface looked "whiter" than the page. */
:root[data-theme="light"]:not([data-accent="mono"]) {
  --glow-1: color-mix(in oklab, var(--accent) 7%, transparent);
  --glow-2: color-mix(in oklab, var(--accent-2) 5%, transparent);
}

:root[data-font="rounded"] {
  --font-body:
    ui-rounded, "SF Pro Rounded", "Hiragino Maru Gothic ProN", Quicksand,
    Comfortaa, ui-sans-serif, sans-serif;
}
:root[data-font="serif"] {
  --font-body:
    "New York", ui-serif, Georgia, "Iowan Old Style", "Times New Roman", serif;
}

body,
.app {
  height: 100%;
}

body {
  background:
    radial-gradient(1200px 560px at 88% -12%, var(--glow-1), transparent 60%),
    radial-gradient(1000px 620px at -12% 112%, var(--glow-2), transparent 55%),
    var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

input,
textarea,
select {
  font: inherit;
  color: var(--text);
  background: var(--glass);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  padding: 11px 14px;
  width: 100%;
  outline: none;
  transition:
    border-color 140ms ease,
    box-shadow 140ms ease;
}

input:focus,
textarea:focus,
select:focus {
  border-color: var(--accent-ring);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

input::placeholder,
textarea::placeholder {
  color: var(--text-faint);
}

textarea {
  resize: vertical;
  min-height: 84px;
}

label {
  display: block;
  font-size: 13px;
  color: var(--text-dim);
  margin: 14px 0 6px;
}

.glass {
  background: var(--glass);
  border: 1px solid var(--edge);
  border-radius: var(--radius-lg);
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  box-shadow: var(--shadow-card);
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--edge-strong);
  background: var(--glass-strong);
  color: var(--text);
  font-weight: 550;
  transition:
    background 120ms ease,
    transform 60ms ease;
}

.button:hover {
  background: rgba(255, 255, 255, 0.12);
}

.button:active {
  transform: translateY(1px);
}

.button.primary {
  background: var(--accent-grad);
  background-size: 140% 140%;
  color: var(--on-accent, #fff);
  border-color: transparent;
  box-shadow: 0 4px 16px color-mix(in oklab, var(--accent) 32%, transparent);
}

.button.primary:hover {
  background-position: 100% 0;
  box-shadow: 0 6px 22px color-mix(in oklab, var(--accent) 42%, transparent);
}

.button.primary:disabled {
  box-shadow: none;
}

.button.ghost {
  border-color: transparent;
  background: transparent;
  color: var(--text-dim);
}

.button.ghost:hover {
  color: var(--text);
  background: var(--glass);
}

.button:disabled {
  opacity: 0.45;
  cursor: default;
  transform: none;
}

/* ── Auth ─────────────────────────────────────────────────────────── */

.auth {
  height: 100%;
  display: grid;
  place-items: center;
  padding: 24px;
}

.auth-card {
  width: min(400px, 100%);
  padding: 36px 32px 30px;
}

.auth-card h1 {
  font-size: 30px;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
}

.auth-card .tagline {
  color: var(--text-dim);
  margin-bottom: 22px;
}

.auth-card .button {
  width: 100%;
  margin-top: 20px;
}

.auth-swap {
  margin-top: 16px;
  text-align: center;
  font-size: 13.5px;
  color: var(--text-faint);
}

.auth-swap button {
  color: var(--text-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.form-error {
  margin-top: 14px;
  color: var(--danger);
  font-size: 13.5px;
  min-height: 1.2em;
}

.form-note {
  margin: 4px 0 6px;
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1.5;
}

/* ── Shell ────────────────────────────────────────────────────────── */

.shell {
  height: 100%;
  display: grid;
  grid-template-columns: 264px 1fr;
  gap: 14px;
  padding: 14px;
}

.sidebar {
  display: flex;
  flex-direction: column;
  padding: 18px 14px 14px;
  min-height: 0;
  overflow-y: auto;
}

.brand {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.02em;
  padding: 4px 10px 18px;
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.brand b {
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 700;
}

.brand span {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 2px 8px;
  align-self: center;
}

.nav-section {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-faint);
  padding: 14px 10px 6px;
}

.nav-list {
  overflow-y: auto;
  min-height: 0;
  flex: 1;
}

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  padding: 9px 11px;
  border-radius: 11px;
  color: var(--text-dim);
  font-weight: 500;
  transition:
    background 130ms ease,
    color 130ms ease;
}

.nav-item:hover {
  background: var(--glass);
  color: var(--text);
}

.nav-item.active {
  background: var(--accent-soft);
  color: var(--text);
}

.nav-item.active::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 17px;
  border-radius: 999px;
  background: var(--accent-grad);
}

.nav-item .avatar {
  flex: none;
}

.nav-item .label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.nav-icon {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--text-faint);
}

.nav-item:hover .nav-icon,
.nav-item.active .nav-icon {
  color: var(--accent);
}

.nav-empty {
  padding: 6px 12px 10px;
  font-size: 12.5px;
  color: var(--text-faint);
  line-height: 1.5;
}

/* The one icon primitive: block-level, never shrinks, inherits colour. */
.icon {
  display: block;
  flex: none;
}

.button.with-icon {
  gap: 7px;
}

.sidebar-footer {
  border-top: 1px solid var(--edge);
  margin-top: 10px;
  padding-top: 10px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.sidebar-footer .who {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: 11px;
  text-align: left;
  color: inherit;
  transition: background 130ms ease;
}

.sidebar-footer .who:hover {
  background: var(--glass);
}

.sidebar-footer .who-text {
  min-width: 0;
}

.icon-button {
  flex: none;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  color: var(--text-faint);
  font-size: 15px;
  transition:
    background 130ms ease,
    color 130ms ease;
}

.icon-button:hover {
  background: var(--glass);
  color: var(--text);
}

.sidebar-footer .who .name {
  font-size: 13.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-transform: capitalize;
}

.sidebar-footer .who .plan {
  font-size: 11.5px;
  color: var(--text-faint);
  text-transform: capitalize;
}

.sidebar-footer .who .plan.paid {
  color: var(--accent);
  font-weight: 600;
}

.main {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ── Avatars ──────────────────────────────────────────────────────── */

.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 14px;
  font-weight: 650;
  color: var(--on-accent, #fff);
  background: var(--accent-grad);
  flex: none;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.avatar.lg {
  width: 54px;
  height: 54px;
  font-size: 21px;
}

/* ── Gallery ──────────────────────────────────────────────────────── */

.screen {
  padding: 26px 30px;
  overflow-y: auto;
  min-height: 0;
  flex: 1;
}

.screen-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 22px;
}

.screen-head h2 {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.025em;
}

.screen-head .meta {
  color: var(--text-faint);
  font-size: 13px;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: 16px;
}

.character-card {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: left;
  transition:
    transform 150ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 150ms ease,
    border-color 150ms ease;
}

.character-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-ring);
  box-shadow: var(--shadow-lift);
}

.character-card .row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.character-card .row > div {
  min-width: 0;
}

.character-card .name {
  font-weight: 650;
  font-size: 16px;
  letter-spacing: -0.01em;
}

.character-card .tagline {
  color: var(--text-dim);
  font-size: 13.5px;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.character-card .badge {
  align-self: flex-start;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-faint);
  border: 1px solid var(--edge);
  border-radius: 999px;
  padding: 2px 9px;
  margin-top: 3px;
}

.character-card .badge.public,
.character-card .badge.unlisted,
.character-card .badge.yours {
  color: var(--accent);
  border-color: var(--accent-ring);
  background: var(--accent-soft);
}

.card-new {
  border-style: dashed;
  border-color: var(--edge-strong);
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 9px;
  color: var(--text-dim);
  min-height: 138px;
  font-weight: 550;
  box-shadow: none;
}

.card-new .icon {
  color: var(--text-faint);
}

.card-new:hover .icon {
  color: var(--accent);
}

.card-new:hover {
  color: var(--accent);
  border-color: var(--accent-ring);
  background: var(--accent-soft);
  transform: translateY(-3px);
}

.empty-state {
  text-align: center;
  color: var(--text-dim);
  padding: 70px 20px;
}

.empty-state .big {
  font-size: 19px;
  color: var(--text);
  margin-bottom: 6px;
}

/* ── Editor ───────────────────────────────────────────────────────── */

.editor {
  /* Width comes from the editor-layout grid; a fossil cap from the
     single-column era left a gulf of dead air beside the preview. */
  max-width: none;
}

.editor .actions {
  display: flex;
  gap: 10px;
  margin-top: 24px;
}

.seg {
  display: inline-flex;
  /* A flex-column parent stretches children across its full width, which
     left two buttons rattling around a yard of empty pill. The pill is
     its buttons, nothing more. */
  width: fit-content;
  align-self: flex-start;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--edge);
  border-radius: 999px;
  background: var(--glass);
}

.seg button,
.seg-item {
  padding: 7px 16px;
  border-radius: 999px;
  color: var(--text-dim);
  font-weight: 550;
  font-size: 13.5px;
  transition:
    background 130ms ease,
    color 130ms ease;
}

.seg button:hover,
.seg-item:hover {
  color: var(--text);
}

.seg button.active,
.seg-item.active {
  background: var(--accent-grad);
  color: var(--on-accent, #fff);
  box-shadow: 0 2px 10px var(--accent-soft);
}

/* ── Chat ─────────────────────────────────────────────────────────── */

.chat {
  flex: 1;
  min-height: 0;
  display: flex;
  position: relative;
  padding: 0;
}

.chat-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.chat-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--edge);
}

.chat-head .name {
  font-weight: 650;
  letter-spacing: -0.01em;
}

.chat-head .sub {
  font-size: 12.5px;
  color: var(--text-faint);
}

.chat-head .button.ghost {
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 10px;
  color: var(--text-dim);
}

.chat-head .button.ghost:hover {
  color: var(--text);
}

/* Buttons that carry an icon AND a word are sized by their content. */
.chat-head .button.ghost.with-icon {
  width: auto;
  gap: 7px;
  padding: 0 13px 0 11px;
}

.thread {
  flex: 1;
  overflow-y: auto;
  padding: 22px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 0;
}

.msg {
  max-width: 74%;
  padding: 11px 15px;
  border-radius: 18px;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

/* Roleplay text. Actions read as stage directions: italic, tinted toward
   the accent, slightly quieter than speech so the spoken words stay the
   foreground. */
.rp-action {
  font-style: italic;
  color: color-mix(in oklab, var(--accent) 42%, var(--text-dim));
}
.msg.user .rp-action {
  /* On the accent-filled bubble the readable ink is whatever reads on
     that accent — white for the coloured ones, near-black for Mono. A
     hardcoded white was white-on-white under Mono in dark mode. */
  color: color-mix(in oklab, var(--on-accent, #fff) 75%, var(--accent));
}
.msg-text strong {
  font-weight: 700;
}

.msg.user {
  align-self: flex-end;
  background: var(--accent-grad);
  color: var(--on-accent, #fff);
  border-bottom-right-radius: 6px;
  box-shadow: 0 2px 12px color-mix(in oklab, var(--accent) 28%, transparent);
}

.msg.assistant {
  align-self: flex-start;
  background: var(--glass-strong);
  border: 1px solid var(--edge);
  border-bottom-left-radius: 6px;
}

.msg.assistant.streaming::after {
  content: "▍";
  animation: blink 1s steps(2) infinite;
  color: var(--accent);
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

.composer {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 14px 20px 18px;
  border-top: 1px solid var(--edge);
}

.composer textarea {
  min-height: 46px;
  max-height: 160px;
  border-radius: 22px;
  padding: 12px 16px;
}

.composer .button.attach {
  width: 42px;
  height: 46px;
  flex: none;
  padding: 0;
  font-size: 20px;
  border-radius: 50%;
  color: var(--text-dim);
}

.composer .button.attach:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

.composer .button.primary {
  height: 46px;
  border-radius: 22px;
}

.chat-error {
  color: var(--danger);
  font-size: 13px;
  padding: 0 22px 10px;
}

/* ── Memory panel ─────────────────────────────────────────────────── */

.memory-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 18px;
  gap: 12px;
  overflow-y: auto;
}

.memory-panel h3 {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-faint);
}

.memory-map {
  width: 100%;
  aspect-ratio: 1;
  border-radius: var(--radius);
  background: var(--glass);
  border: 1px solid var(--edge);
}

.memory-map text {
  fill: var(--text-dim);
  font-size: 8px;
}

.memory-entry {
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  padding: 10px 12px;
  font-size: 13px;
}

.memory-entry .kind {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-faint);
  margin-bottom: 3px;
}

.memory-entry .tools {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.memory-entry .tools button {
  font-size: 12px;
  color: var(--text-faint);
}

.memory-entry .tools button:hover {
  color: var(--text);
}

.memory-entry.pinned {
  border-color: var(--edge-strong);
  background: var(--glass);
}

.memory-empty {
  color: var(--text-faint);
  font-size: 13px;
  text-align: center;
  padding: 18px 6px;
}

/* ── Bits ─────────────────────────────────────────────────────────── */

.spinner {
  color: var(--text-faint);
  padding: 40px;
  text-align: center;
}

.toast {
  position: fixed;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--bg-raise);
  border: 1px solid var(--edge-strong);
  border-radius: var(--radius);
  padding: 10px 18px;
  font-size: 13.5px;
  box-shadow: var(--shadow-lift);
  /* Above the modal backdrop (60), dropdowns (80) and the call pill
     (240): a toast that fires while a modal is open must still show. */
  z-index: 300;
}

/* ── Memory drawer ────────────────────────────────────────────────── */

.chat-main {
  flex: 1;
}

.memory-drawer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 320px;
  transform: translateX(105%);
  transition: transform 180ms ease;
  background: var(--bg-raise);
  border-left: 1px solid var(--edge);
  border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
  overflow-y: auto;
  z-index: 5;
}

.memory-drawer.open {
  transform: translateX(0);
}

.memory-drawer .memory-panel {
  padding: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* ── Settings ─────────────────────────────────────────────────────── */

.settings-card {
  max-width: 620px;
  padding: 22px 24px;
  margin-bottom: 16px;
}

.settings-card h3 {
  font-size: 15px;
  margin-bottom: 8px;
}

.settings-card .dim {
  color: var(--text-dim);
  font-size: 13.5px;
}

.settings-card p.dim {
  margin-bottom: 12px;
}

.settings-row {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--edge);
  font-size: 14px;
}

.settings-row:last-child {
  border-bottom: none;
}

.terms-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  color: var(--text);
  font-size: 13.5px;
  margin-top: 14px;
}

.terms-row input {
  width: auto;
  margin-top: 3px;
}

.settings-card .actions {
  margin-top: 16px;
}

.settings-card .memory-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 14px;
}

.settings-card select {
  margin-top: 4px;
}

.avatar.has-image {
  background: none;
  padding: 0;
  overflow: hidden;
}

.avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  display: block;
}

/* ── Portrait section (editor) ────────────────────────────────────── */

.portrait-row {
  display: flex;
  gap: 16px;
  align-items: center;
  margin: 6px 0 4px;
}

.portrait-row .avatar.large {
  width: 72px;
  height: 72px;
  font-size: 26px;
}

.portrait-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* ── Chat image attachments ───────────────────────────────────────── */

.attachment-tray {
  display: flex;
  gap: 8px;
  padding: 0 4px;
}

.attachment-tray:empty {
  display: none;
}

.attach-chip {
  position: relative;
  display: inline-flex;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--edge);
  background: var(--bg-raise);
}

.attach-thumb {
  display: block;
  width: 64px;
  height: 64px;
  object-fit: cover;
}

.chip-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}

.msg img.chat-image {
  display: block;
  max-width: min(280px, 100%);
  max-height: 280px;
  border-radius: 12px;
  margin-bottom: 6px;
}

/* The CSP forbids inline style attributes, so utility classes carry the
   few one-liners screens need. */
.file-input {
  display: none;
}
.spacer {
  flex: 1;
}

.danger-zone {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--edge);
}
.button.danger {
  color: var(--danger);
  border-color: rgba(255, 125, 125, 0.35);
}

/* ── Gallery tabs & discovery ─────────────────────────────────────── */
.discover-search {
  width: 100%;
  margin: 4px 0 14px;
}

/* Genre filter chips: quiet pills, the active one wears the gradient. */
.tag-row {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  min-width: 0;
}
.tag-row::-webkit-scrollbar {
  display: none;
}
.tag-chip {
  border: 1px solid var(--edge);
  background: var(--glass);
  color: var(--text-dim);
  border-radius: 999px;
  padding: 4px 11px;
  font-size: 12px;
  white-space: nowrap;
  flex-shrink: 0;
  cursor: pointer;
  transition:
    color 0.15s ease,
    border-color 0.15s ease,
    background 0.15s ease;
}
.tag-chip:hover {
  color: var(--text);
  border-color: var(--edge-strong);
}
.tag-chip.active {
  background: var(--accent-grad);
  border-color: transparent;
  color: var(--on-accent, #fff);
}

/* Shelves: one horizontal row per genre, scrolls on its own. */
.shelf-title {
  margin: 22px 2px 10px;
  font-size: 15px;
  font-weight: 650;
  color: var(--text);
}
.shelf {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(240px, 280px);
  gap: 14px;
  overflow-x: auto;
  padding: 2px 2px 12px;
  scrollbar-width: thin;
}

/* Tags on a card: whisper-quiet, information not decoration. */
.card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.card-tag {
  font-size: 11px;
  color: var(--text-faint);
  border: 1px solid var(--edge);
  border-radius: 999px;
  padding: 2px 8px;
}

/* ── Settings modal ───────────────────────────────────────────────── */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(6, 6, 10, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 60;
  animation: modal-in 140ms ease-out;
}

@keyframes modal-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.settings-modal {
  /* A real surface, not a pane of glass: the backdrop behind it is a dark
     scrim in both themes, and a translucent modal would read as dark even
     in light mode. */
  background: var(--bg-raise);
  width: min(860px, calc(100vw - 32px));
  height: min(620px, calc(100vh - 48px));
  display: flex;
  flex-direction: column;
  border-radius: 22px;
  overflow: hidden;
  outline: none;
  box-shadow:
    0 24px 70px rgba(0, 0, 0, 0.55),
    0 0 0 1px var(--edge);
}

.settings-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 22px 10px;
}

.settings-modal-body {
  display: flex;
  flex: 1;
  min-height: 0;
}

.settings-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px 16px 14px;
  min-width: 168px;
  border-right: 1px solid var(--edge);
}

.settings-nav-item {
  text-align: left;
  padding: 8px 12px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 13.5px;
  font-weight: 500;
  transition:
    background 120ms ease,
    color 120ms ease;
}

.settings-nav-item:hover {
  background: var(--glass);
  color: var(--text);
}

.settings-nav-item.active {
  background: var(--accent-soft);
  color: var(--text);
  font-weight: 600;
}

.settings-pane {
  flex: 1;
  overflow-y: auto;
  padding: 8px 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.plan-card {
  padding: 16px 18px;
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 6px 0;
}

.plan-name {
  font-weight: 650;
  font-size: 16px;
}

.plan-price {
  color: var(--text-dim);
}

.allowance-bar {
  height: 8px;
  border-radius: 999px;
  background: var(--bg-raise);
  overflow: hidden;
}

.allowance-fill.sized {
  height: 100%;
  width: var(--fill, 0%);
  border-radius: 999px;
  background: var(--accent-grad);
}

.usage-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 120px;
  padding: 8px 0;
}

.usage-bar {
  flex: 1;
  min-width: 4px;
  height: var(--height, 4%);
  border-radius: 4px 4px 0 0;
  background: linear-gradient(180deg, #7c5cff, rgba(124, 92, 255, 0.35));
}

.legal-text {
  white-space: pre-wrap;
  font-family: inherit;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-dim);
  max-height: 100%;
  overflow-y: auto;
}

/* ── Call view ────────────────────────────────────────────────────── */
/* Shaped like a voice channel with a friend: one big tile for them, a
   small one for you, rings that follow real audio, one control bar. */
.call {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 22px 26px;
  border-radius: 20px;
  min-height: 100%;
  background:
    radial-gradient(
      900px 420px at 50% -10%,
      var(--accent-soft),
      transparent 60%
    ),
    var(--glass);
}

.call-statusline {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--text-dim);
  min-height: 20px;
  align-self: stretch;
  justify-content: center;
}
.call-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
  flex: none;
}
.call-dot.live {
  background: var(--ok);
  box-shadow: 0 0 8px color-mix(in oklab, var(--ok) 60%, transparent);
}
.call-dot.reconnecting {
  background: var(--warn);
  animation: call-dot-blink 1s ease-in-out infinite;
}
@keyframes call-dot-blink {
  50% {
    opacity: 0.35;
  }
}
.call-timer {
  font-variant-numeric: tabular-nums;
  color: var(--text-faint);
  margin-left: 4px;
}

.call-tiles {
  position: relative;
  flex: 1;
  align-self: stretch;
  display: grid;
  place-items: center;
  min-height: 0;
}
.tile {
  border-radius: var(--radius-lg);
  background: var(--glass-strong);
  border: 1px solid var(--edge);
  display: grid;
  place-items: center;
  transition:
    box-shadow 80ms ease-out,
    filter 120ms ease-out;
}
.tile-ai {
  width: min(560px, 82vw);
  height: min(56vh, 480px);
  position: relative;
  overflow: hidden;
}
.tile-ai .avatar.lg {
  width: min(240px, 36vh);
  height: min(240px, 36vh);
  font-size: 72px;
  border-radius: 50%;
}
.tile-plate {
  position: absolute;
  left: 14px;
  bottom: 12px;
  font-size: 13.5px;
  font-weight: 650;
  padding: 5px 12px;
  border-radius: 999px;
  background: rgba(10, 8, 16, 0.55);
  color: #fff;
  backdrop-filter: blur(6px);
}
.tile-user {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 136px;
  height: 92px;
  font-size: 13px;
  color: var(--text-dim);
  background: var(--bg-raise);
}
.tile-you {
  font-weight: 650;
}
.tile.is-speaking {
  box-shadow:
    0 0 0 var(--ring-width, 3px) var(--ring-speaking),
    0 0 14px color-mix(in oklab, var(--ring-speaking) 55%, transparent);
  filter: brightness(1.04);
}

.mic-meter {
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 10px;
  height: 4px;
  border-radius: 999px;
  background: var(--glass-strong);
  overflow: hidden;
}
.mic-meter-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: var(--ring-speaking);
  transition: width 90ms linear;
}
.mic-meter.muted .mic-meter-fill {
  background: var(--text-faint);
  opacity: 0.5;
}

/* A field that just refused to be skipped. */
.needs-answer .dropdown-button {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--danger) 25%, transparent);
}

.mic-slash {
  position: absolute;
  right: 8px;
  bottom: 8px;
  font-size: 12px;
  filter: grayscale(1) brightness(1.6);
}

.call-captions {
  max-width: 620px;
  min-height: 64px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: center;
}
.caption {
  font-size: 14px;
  line-height: 1.5;
}
.caption.you {
  color: var(--text-faint);
  font-size: 12.5px;
}
.call-notice {
  color: var(--warn);
  font-size: 13px;
  min-height: 18px;
}

.call-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 999px;
  background: var(--bg-raise);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-card);
}
.call-button {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border-radius: 999px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text);
  font-size: 13.5px;
  cursor: pointer;
}
.call-button:hover {
  background: var(--glass-strong);
}
.call-button.active {
  background: var(--accent-grad);
  color: var(--on-accent, #fff);
}
.call-button.end {
  margin-left: 8px;
  background: var(--danger);
  color: #fff;
}
.call-button.end:hover {
  filter: brightness(1.1);
}
.call-button.end svg {
  transform: rotate(135deg);
}
.pill-button.danger svg {
  transform: rotate(135deg);
}
.call-watch {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--text-dim);
  padding: 0 6px;
  cursor: pointer;
}
.call-volume {
  width: 220px;
}
.call-debug {
  display: flex;
  gap: 8px;
}
/* ── Call record: a finished call, folded to a line in the thread ──── */
.call-record {
  /* A flex item with overflow:hidden has an automatic minimum size of
     zero, so a long transcript crushed this card to its own borders —
     a thin grey line where a call used to be. Never shrink. */
  flex: none;
  align-self: center;
  width: min(480px, 92%);
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background: var(--glass);
  overflow: hidden;
  margin: 4px 0;
}
.call-record-head {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 14px;
  border: none;
  background: transparent;
  color: var(--text);
  font-size: 13px;
  cursor: pointer;
  text-align: left;
}
.call-record-head:hover {
  background: var(--glass-strong);
}
.call-record-title {
  font-weight: 650;
}
.call-record-meta {
  color: var(--text-faint);
  font-size: 12.5px;
  margin-left: auto;
}
.call-record-chevron {
  color: var(--text-faint);
  font-size: 11px;
}
.call-record-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 4px 12px 12px;
  border-top: 1px solid var(--edge);
  max-height: 320px;
  overflow-y: auto;
}
.call-record-body.hidden {
  display: none;
}
.call-record-body .msg.compact {
  font-size: 13px;
  padding: 7px 11px;
  max-width: 88%;
}
.call-record-glance {
  font-size: 11px;
  opacity: 0.6;
  margin-left: 6px;
}

.actions-spacer {
  flex: 1;
  order: 1;
}
/* "Keep this face" is the decision; "Repaint" is the second thought.
   Pushed to the far side and dressed down, they can't be mistaken for
   each other or fat-fingered together. */
.prompt-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
}
.prompt-actions .button:not(.primary) {
  border-color: var(--edge);
  background: transparent;
}

.call-debug button {
  font-size: 12px;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px dashed var(--edge-strong);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
}

/* ── Call pill: the two circles in the corner ──────────────────────── */
.call-pill {
  position: fixed;
  z-index: 240;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: 999px;
  background: var(--bg-raise);
  border: 1px solid var(--edge-strong);
  box-shadow: var(--shadow-lift);
  cursor: grab;
  user-select: none;
}
.call-pill.br {
  right: 18px;
  bottom: 18px;
}
.call-pill.bl {
  left: 18px;
  bottom: 18px;
}
.call-pill.tr {
  right: 18px;
  top: 18px;
}
.call-pill.tl {
  left: 18px;
  top: 18px;
}
.call-pill.hidden {
  display: none;
}
.pill-circle {
  position: relative;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: none;
  padding: 0;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--glass-strong);
  cursor: pointer;
  transition: box-shadow 80ms ease-out;
}
.pill-circle .avatar {
  width: 100%;
  height: 100%;
  border-radius: 50%;
}
.pill-circle.is-speaking {
  box-shadow:
    0 0 0 3px var(--ring-speaking),
    0 0 10px color-mix(in oklab, var(--ring-speaking) 55%, transparent);
}
.pill-you-dot {
  font-size: 12px;
  font-weight: 650;
  color: var(--text-dim);
}
.pill-actions {
  display: flex;
  gap: 6px;
}
.pill-button {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--edge);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  display: grid;
  place-items: center;
  font-size: 14px;
}
.pill-button.active {
  background: var(--accent-grad);
  color: var(--on-accent, #fff);
}
.pill-button.danger {
  color: var(--danger);
  border-color: color-mix(in oklab, var(--danger) 45%, transparent);
}
.pill-hide {
  position: absolute;
  top: -7px;
  right: 4px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--edge);
  background: var(--bg-raise);
  color: var(--text-faint);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
}

/* The pop-out window is presence, not controls: two circles, nothing
   clickable, no chrome of our own. (The window's own title bar is the
   browser's and cannot be removed.) */
.pip-body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
}
.pip-body .call-pill {
  position: static;
  box-shadow: none;
  background: transparent;
  border: none;
  padding: 0;
  gap: 16px;
  cursor: default;
  pointer-events: none;
}
.pip-body .pill-circle {
  width: 68px;
  height: 68px;
}
.pip-body .pill-hide,
.pip-body .pill-actions {
  display: none;
}

.speak-button {
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 13px;
  margin-left: 6px;
  opacity: 0.6;
}

.speak-button.busy {
  opacity: 0.55;
  cursor: progress;
}
.speak-button.playing {
  color: var(--accent);
  opacity: 1;
}

.speak-button:hover {
  opacity: 1;
}

/* ── Group chats ──────────────────────────────────────────────────── */
.group-faces {
  display: flex;
}
.group-faces .avatar {
  margin-right: -10px;
  border: 2px solid var(--bg);
}
.group-msg {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.group-speaker {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim);
}
.group-speaker .avatar {
  width: 20px;
  height: 20px;
  font-size: 10px;
}
.picker-modal {
  background: var(--bg-raise);
  width: min(440px, calc(100vw - 32px));
  height: auto;
  max-height: calc(100vh - 48px);
  width: min(420px, calc(100vw - 32px));
  height: auto;
  max-height: min(560px, calc(100vh - 48px));
}
.picker-body {
  padding: 8px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
}
.picker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 10px;
  cursor: pointer;
}
.picker-row:hover {
  background: var(--bg-raise);
}

/* ── Games (poster shelf) ─────────────────────────────────────────── */
.game-section {
  font-size: 12px;
  font-weight: 650;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text-faint);
  margin: 20px 0 12px;
}

.game-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(184px, 1fr));
  gap: 16px;
}

/* Poster proportions, like a store shelf. Art fills the tile; everything
   else floats over it. */
.game-card {
  position: relative;
  aspect-ratio: 3 / 4;
  /* A poster should never balloon: on a narrow pane the grid drops to one
     column, and without a cap a single cover would fill the screen. */
  max-width: 240px;
  width: 100%;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--edge);
  background: var(--bg-raise);
  box-shadow: var(--shadow-card);
  transition:
    transform 170ms cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 170ms ease,
    border-color 170ms ease;
}

.game-art,
.game-tile {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

.game-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  text-align: center;
  background:
    radial-gradient(
      120% 120% at 18% 0%,
      rgba(139, 108, 255, 0.4),
      transparent 55%
    ),
    radial-gradient(
      120% 120% at 100% 100%,
      rgba(255, 107, 157, 0.32),
      transparent 55%
    ),
    var(--bg-raise);
  font-weight: 700;
  font-size: 17px;
  color: #fff;
}

/* The wash: a grey veil plus a bottom scrim so the name always reads, and
   so five unrelated cover styles feel like one shelf. It lifts on hover. */
.game-wash {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      to top,
      rgba(8, 7, 12, 0.92) 0%,
      rgba(8, 7, 12, 0.55) 32%,
      rgba(8, 7, 12, 0.12) 62%,
      rgba(8, 7, 12, 0.05) 100%
    ),
    rgba(20, 18, 26, 0.34);
  transition: opacity 170ms ease;
}

/* Unreleased games sit in grayscale; hovering restores the color, and the
   promise sits quietly in the middle. Transitions on the art itself so the
   whole cover breathes back to life rather than snapping. */
.game-card.status-available .game-wash {
  background: linear-gradient(
    to top,
    rgba(8, 6, 14, 0.85) 0%,
    rgba(8, 6, 14, 0.25) 30%,
    transparent 55%
  );
}
.game-card:not(.status-available) .game-art {
  filter: grayscale(0.92) brightness(0.72);
  transition: filter 0.35s ease;
}
.game-card:not(.status-available):hover .game-art {
  filter: grayscale(0.08) brightness(0.94);
}
.coming-soon-veil {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 650;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.8);
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.35s ease;
}
.game-card:not(.status-available):hover .coming-soon-veil {
  opacity: 0;
}

.game-card:hover .game-wash {
  opacity: 0.82;
}

/* Non-playable entries read as quieter, without hiding what they are. */
.game-card.status-coming-soon .game-art,
.game-card.status-planned .game-art {
  filter: saturate(0.72) brightness(0.9);
}

.game-card.status-available:hover {
  transform: translateY(-4px);
  border-color: var(--accent-ring);
  box-shadow: var(--shadow-lift);
}

.game-body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 12px 13px 13px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.game-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.game-title {
  font-weight: 650;
  font-size: 14.5px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: #fff;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.6);
}

.game-status {
  flex: none;
  font-size: 10px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(10, 9, 14, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: rgba(255, 255, 255, 0.82);
  white-space: nowrap;
}

.game-status.available {
  color: var(--ok);
  border-color: rgba(138, 255, 192, 0.4);
  background: rgba(16, 60, 40, 0.6);
}

/* The blurb is the payoff, not the headline: hidden until hover. */
.game-blurb {
  font-size: 12px;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.82);
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition:
    max-height 200ms ease,
    opacity 160ms ease;
}

.game-card:hover .game-blurb {
  max-height: 84px;
  opacity: 1;
}

.game-credit {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.5);
}

.game-disclaimer {
  font-size: 11.5px;
  color: var(--text-faint);
  line-height: 1.5;
  border-top: 1px solid var(--edge);
  padding-top: 14px;
  margin-top: 22px;
}

.game-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.game-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 13px;
}

.game-chip.on {
  border-color: rgba(139, 108, 255, 0.6);
  background: rgba(139, 108, 255, 0.15);
  color: var(--text);
}

.game-chip .chip-tag {
  font-size: 10px;
  opacity: 0.7;
}

.game-modal-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--edge);
}

.game-modal-row:last-child {
  border-bottom: none;
}

.handoff {
  max-width: 300px;
  text-align: right;
}

/* ── Memory: header, composer ─────────────────────────────────────── */
.memory-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.memory-composer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: var(--glass);
}

.memory-composer .memory-input {
  min-height: 52px;
  font-size: 13.5px;
  padding: 9px 12px;
}

.memory-composer-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

.memory-composer-row .memory-kind {
  flex: 1;
  padding: 8px 10px;
  font-size: 12.5px;
}

.memory-composer-row .button {
  flex: none;
  padding: 8px 16px;
  font-size: 13px;
}

.memory-entry.pinned {
  border-color: var(--accent-ring);
  background: var(--accent-soft);
}

/* ── Profile hero ──────────────────────────────────────────────────── */
.profile-hero {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--edge);
  margin-bottom: 14px;
}
.profile-hero-text {
  flex: 1;
  min-width: 0;
}
.profile-hero-name {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.profile-hero-email {
  font-size: 12px;
  color: var(--text-faint);
  margin-top: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.plan-chip {
  display: inline-block;
  margin-top: 6px;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 999px;
  padding: 3px 10px;
  border: 1px solid var(--edge-strong);
  color: var(--text-dim);
}
.plan-chip.paid {
  background: var(--accent-grad);
  border-color: transparent;
  color: var(--on-accent, #fff);
}

/* ── Plan comparison ───────────────────────────────────────────────── */
.cadence {
  margin: 6px 0 16px;
}
.plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  align-items: stretch;
}
.plan-option {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--edge);
}
.plan-option.featured {
  border-color: var(--accent-ring);
  box-shadow: 0 0 0 1px var(--accent-ring);
}
.plan-option.current {
  background: var(--glass-strong);
}
.plan-option-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.plan-option .plan-name {
  font-weight: 700;
  font-size: 15px;
}
.plan-option .plan-price {
  font-size: 24px;
  font-weight: 750;
  letter-spacing: -0.02em;
}
.plan-features {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
  flex: 1;
}
.plan-features li {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  font-size: 13px;
  color: var(--text-dim);
}
.plan-features li svg {
  color: var(--accent);
  flex-shrink: 0;
  margin-top: 2px;
}

/* ── Usage tiles ───────────────────────────────────────────────────── */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin: 14px 0 6px;
}
.stat-tile {
  padding: 14px 16px;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
}
.stat-value {
  font-size: 22px;
  font-weight: 750;
  letter-spacing: -0.02em;
}
.stat-label {
  font-size: 13px;
  font-weight: 600;
  margin-top: 2px;
}
.stat-caption {
  font-size: 11.5px;
  color: var(--text-faint);
  margin-top: 2px;
}
.stat-tile .allowance-bar {
  margin-top: 10px;
}

/* ── Appearance ────────────────────────────────────────────────────── */
.accent-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
}
.accent-swatch {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background: var(--glass);
  color: var(--text-dim);
  cursor: pointer;
}
.accent-swatch.active {
  border-color: var(--accent-ring);
  box-shadow: 0 0 0 1px var(--accent-ring);
  color: var(--text);
}
.accent-dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  flex-shrink: 0;
}
.accent-swatch.accent-violet .accent-dot {
  background: linear-gradient(135deg, #8b6cff, #ff6b9d);
}
.accent-swatch.accent-ember .accent-dot {
  background: linear-gradient(135deg, #ff8a5c, #ff5c7a);
}
.accent-swatch.accent-ocean .accent-dot {
  background: linear-gradient(135deg, #5cb8ff, #7a5cff);
}
.accent-swatch.accent-meadow .accent-dot {
  background: linear-gradient(135deg, #4ed99a, #5cb8ff);
}
.accent-swatch.accent-mono .accent-dot {
  background: linear-gradient(135deg, #f5f4f7 50%, #17171b 50%);
  border: 1px solid var(--edge-strong);
}
.accent-name {
  font-size: 13px;
}

/* ── Data controls ─────────────────────────────────────────────────── */
.data-controls {
  padding: 16px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--edge);
  display: grid;
  gap: 14px;
}
.data-promise {
  font-size: 13.5px;
  line-height: 1.5;
}
.toggle-row {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  cursor: pointer;
  font-size: 13.5px;
}
.toggle-row input {
  margin-top: 3px;
  accent-color: var(--accent);
}

/* ── Legal, readable ───────────────────────────────────────────────── */
.legal-text {
  max-height: 46vh;
  overflow-y: auto;
  padding-right: 8px;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--text-dim);
}
.legal-heading {
  color: var(--text);
  margin: 18px 0 6px;
}
.legal-paragraph {
  margin: 0 0 10px;
}

/* ── Character posters ─────────────────────────────────────────────── */
.char-art {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.char-art-initial {
  font-size: 64px;
  font-weight: 750;
  color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.35);
}
.char-art-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 360ms ease;
}
.char-art.has-image .char-art-img {
  opacity: 1;
}
.char-art.has-image .char-art-initial {
  opacity: 0;
  transition: opacity 200ms ease;
}
/* While a portrait is on its way the tile breathes: a soft light sweeps
   across the tone so the wait reads as loading, not as a missing face. */
.char-art.loading::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    110deg,
    transparent 30%,
    rgba(255, 255, 255, 0.16) 50%,
    transparent 70%
  );
  background-size: 220% 100%;
  animation: artShimmer 1.4s ease-in-out infinite;
  pointer-events: none;
}
@keyframes artShimmer {
  from {
    background-position: 120% 0;
  }
  to {
    background-position: -120% 0;
  }
}

.poster-card {
  position: relative;
  aspect-ratio: 3 / 4;
  width: 100%;
  max-width: 240px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--edge);
  cursor: pointer;
  padding: 0;
  background: var(--glass);
  text-align: left;
  transition:
    transform 0.22s ease,
    box-shadow 0.22s ease,
    border-color 0.22s ease;
}
.poster-card:hover {
  transform: translateY(-4px) scale(1.015);
  border-color: var(--accent-ring);
  box-shadow: var(--shadow-lift);
}
.poster-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(8, 6, 14, 0.92) 0%,
    rgba(8, 6, 14, 0.45) 34%,
    transparent 62%
  );
  pointer-events: none;
}
.poster-body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 12px 14px;
  color: #fff;
}
.poster-name {
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.01em;
}
.poster-tagline {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.72);
  margin-top: 2px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.poster-body .card-tag {
  border-color: rgba(255, 255, 255, 0.25);
  color: rgba(255, 255, 255, 0.65);
}
.poster-owner {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--accent-grad);
  color: var(--on-accent, #fff);
  border-radius: 999px;
  padding: 3px 9px;
}
.poster-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 14px;
}
.shelf .poster-card {
  max-width: none;
}
.shelf {
  grid-auto-columns: minmax(170px, 200px);
}

/* ── Featured carousel ─────────────────────────────────────────────── */
.feature-carousel {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-bottom: 22px;
  border: 1px solid var(--edge);
}
.feature-stage {
  display: grid;
  grid-template-columns: minmax(180px, 240px) 1fr;
  min-height: 250px;
}
.feature-stage .char-art {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: 0;
}
.feature-text {
  padding: 22px 26px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  justify-content: center;
  align-items: flex-start;
}
.feature-kicker {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.feature-name {
  font-size: 26px;
  font-weight: 750;
  letter-spacing: -0.02em;
}
.feature-tagline {
  color: var(--text-dim);
  font-size: 14px;
  max-width: 46ch;
}
.feature-text .button {
  margin-top: 8px;
}
.feature-dots {
  position: absolute;
  right: 6px;
  bottom: 4px;
  display: flex;
  gap: 0;
}
/* The button is the target (28px, a thumb can hit it); the dot is drawn
   inside it. Eight-pixel buttons at a fourteen-pixel pitch were the
   smallest control in the app. */
.feature-dot {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border: none;
  background: transparent;
  cursor: pointer;
  padding: 0;
}
.feature-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--edge-strong);
  transition:
    background 140ms ease,
    transform 140ms ease;
}
.feature-dot.active::before {
  background: var(--accent);
  transform: scale(1.25);
}
@media (max-width: 640px) {
  .feature-stage {
    grid-template-columns: 1fr;
  }
  .feature-stage .char-art {
    aspect-ratio: 16 / 9;
  }
}

/* ── Editor as a character sheet ───────────────────────────────────── */
.editor-layout {
  display: grid;
  /* The form owns every pixel up to the preview: a fixed cap left a
     gulf of dead air in the middle on wide screens. */
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: 28px;
  align-items: start;
}
@media (max-width: 900px) {
  .editor-layout {
    grid-template-columns: 1fr;
  }
  .editor-preview {
    display: none;
  }
}
.editor {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.editor-section {
  padding: 20px 22px 22px;
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.editor-section-title {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -0.01em;
  padding-bottom: 10px;
  margin-bottom: 2px;
  border-bottom: 1px solid var(--edge);
}
/* Field labels inside the editor step back into quiet uppercase — the
   form reads as fields with captions, not alternating rows of text. */
.editor-section label {
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 12px 0 6px;
}
.editor-section label.toggle-row {
  text-transform: none;
  letter-spacing: normal;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-dim);
}
.editor-preview {
  position: sticky;
  top: 18px;
}
.editor-preview-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 10px;
}
.preview-poster {
  cursor: default;
  max-width: none;
}
.preview-poster:hover {
  transform: none;
  box-shadow: var(--shadow-card);
  border-color: var(--edge);
}

/* ── First words: the greeting, rendered as chat will render it ────── */
.editor-vignette {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.vignette-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.vignette-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  overflow: hidden;
  flex: none;
  background: var(--glass-strong);
  border: 1px solid var(--edge);
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-faint);
}
.vignette-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.vignette-name {
  font-size: 13px;
  font-weight: 650;
}
/* .msg.assistant supplies the real chat fill, border, and radii — the
   vignette only narrows the type and caps runaway greetings. */
.vignette-bubble {
  max-width: 100%;
  font-size: 13px;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-line-clamp: 6;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.vignette-bubble.empty {
  cursor: pointer;
}
.vignette-dots {
  display: inline-flex;
  gap: 5px;
  padding: 3px 0;
}
.vignette-dots span {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--text-faint);
  animation: vignette-dot 1.3s ease-in-out infinite;
}
.vignette-dots span:nth-child(2) {
  animation-delay: 0.18s;
}
.vignette-dots span:nth-child(3) {
  animation-delay: 0.36s;
}
@keyframes vignette-dot {
  0%,
  100% {
    opacity: 0.25;
  }
  40% {
    opacity: 0.85;
  }
}
.vignette-caption {
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-faint);
  min-height: 16px;
}
@media (prefers-reduced-motion: reduce) {
  .vignette-dots span {
    animation: none;
    opacity: 0.5;
  }
}

/* ── Billing hero ──────────────────────────────────────────────────── */
.billing-hero {
  padding: 18px;
  border-radius: var(--radius-lg);
  display: grid;
  gap: 12px;
  margin-bottom: 8px;
  background:
    radial-gradient(
      420px 200px at 100% 0%,
      var(--accent-soft),
      transparent 70%
    ),
    var(--glass);
}
.billing-hero-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.billing-hero-plan {
  font-size: 20px;
  font-weight: 750;
  letter-spacing: -0.01em;
}
.billing-hero-price {
  color: var(--text-dim);
  font-size: 13px;
  margin-top: 2px;
}
.billing-store-title {
  margin: 18px 0 4px;
  font-size: 14px;
}

/* ── Switch ────────────────────────────────────────────────────────── */
.toggle-row input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 40px;
  height: 24px;
  border-radius: 999px;
  background: var(--glass-strong);
  border: 1px solid var(--edge-strong);
  position: relative;
  cursor: pointer;
  flex-shrink: 0;
  transition:
    background 0.18s ease,
    border-color 0.18s ease;
  margin-top: 0;
}
.toggle-row input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--text-dim);
  transition:
    transform 0.18s ease,
    background 0.18s ease;
}
.toggle-row input[type="checkbox"]:checked {
  background: var(--accent-grad);
  border-color: transparent;
}
.toggle-row input[type="checkbox"]:checked::after {
  transform: translateX(16px);
  background: var(--on-accent, #fff);
}
.toggle-row {
  align-items: center;
}

/* ── Duo Ultra, dressed for the part ───────────────────────────────── */
.plan-option.ultra {
  position: relative;
  border-color: transparent;
  background:
    linear-gradient(var(--bg-raise), var(--bg-raise)) padding-box,
    linear-gradient(135deg, #f0c46c 0%, #b45cff 55%, #ff6b9d 100%) border-box;
  border: 1.5px solid transparent;
}
.plan-option.ultra::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    360px 160px at 85% -10%,
    rgba(240, 196, 108, 0.12),
    transparent 70%
  );
  pointer-events: none;
}
.plan-option.ultra .plan-name {
  background: linear-gradient(135deg, #f0c46c, #ff6b9d);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.plan-option.ultra .plan-features li svg {
  color: #f0c46c;
}
.plan-option.ultra .button {
  background: linear-gradient(135deg, #f0c46c 0%, #e08cff 60%, #ff6b9d 100%);
  border: none;
  color: #211539;
  font-weight: 700;
}

/* ── Editor face actions, sized like they matter ───────────────────── */
.portrait-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.portrait-actions .button {
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--edge-strong);
}

/* ── Discover filter bar ───────────────────────────────────────────── */
.discover-filterbar {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 10px 0 16px;
}
.discover-toolbar {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-shrink: 0;
  margin-left: auto;
}
.discover-toolbar select {
  min-width: 0;
  max-width: 150px;
  padding: 5px 26px 5px 10px;
  font-size: 12.5px;
  height: 30px;
  border-radius: 999px;
}
@media (max-width: 760px) {
  .discover-filterbar {
    flex-wrap: wrap;
  }
  .discover-toolbar {
    margin-left: 0;
  }
}

/* Edit affordance on your own posters. */
.poster-edit {
  position: absolute;
  top: 10px;
  left: 10px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: none;
  background: rgba(8, 6, 14, 0.55);
  color: #fff;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.18s ease;
}
.poster-card:hover .poster-edit,
.poster-card:focus-within .poster-edit {
  opacity: 1;
}

/* The trash sits opposite the pencil and must be pressed twice. */
.poster-delete {
  position: absolute;
  top: 10px;
  left: 46px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: none;
  background: rgba(8, 6, 14, 0.55);
  color: #fff;
  cursor: pointer;
  opacity: 0;
  transition:
    opacity 0.18s ease,
    background 0.18s ease;
}
.poster-card:hover .poster-delete,
.poster-card:focus-within .poster-delete {
  opacity: 1;
}
.poster-delete.armed {
  background: var(--danger);
  opacity: 1;
}
/* Saved-shelf cards have no pencil; the trash takes its spot. */
.shelf .poster-delete {
  left: 10px;
}

/* Light mode carries no ambient glow. The radial bloom is what keeps the
   dark from reading as dead grey; on a light page the same trick reads as
   a purple stain, whatever the accent. Last in the file on purpose — it
   must outrank the accent variants at equal specificity. */
:root[data-theme="light"] {
  --glow-1: transparent;
  --glow-2: transparent;
}

/* New-character / new-group as posters: dashed invitations, same shape. */
.poster-card.card-new {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border-style: dashed;
  border-color: var(--edge-strong);
  background: var(--glass);
  color: var(--text-dim);
  font-weight: 600;
}
.poster-card.card-new:hover {
  color: var(--text);
  transform: none;
  box-shadow: none;
  border-color: var(--accent-ring);
}

/* Ownership badges by visibility: public earns the gradient, the rest
   stay quiet. */
.poster-owner.vis-private,
.poster-owner.vis-unlisted {
  background: rgba(8, 6, 14, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.25);
}

.voice-row {
  display: flex;
  gap: 10px;
  align-items: center;
}
.voice-row .dropdown {
  flex: 1;
}

/* Duo Ultra card CTA in the plan grid gets its class from drawBilling. */

/* The preview poster before any face exists: the accent gradient, so the
   mirror never looks broken — it looks waiting. */
.preview-art:not(.has-image) {
  background: linear-gradient(160deg, var(--accent) 0%, var(--accent-2) 100%);
}

/* ── Character profile ─────────────────────────────────────────────── */
.character-profile {
  display: grid;
  /* A definite height, not a max: a grid row will not shrink below its
     content on its own, so with max-height the info column silently grew
     taller than the panel and overflow:hidden ate the actions. With a
     definite height the row is constrained, the column scrolls, and the
     sticky footer has a scrollport to stick to. */
  grid-template-columns: minmax(200px, 280px) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  width: min(760px, calc(100vw - 32px));
  height: min(600px, calc(100vh - 48px));
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-raise);
}
.profile-art-side {
  position: relative;
  min-height: 320px;
}
.profile-art-side .poster-scrim {
  background: linear-gradient(to right, transparent 55%, var(--bg-raise) 100%);
}
.profile-info {
  position: relative;
  padding: 24px 26px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.profile-close {
  position: absolute;
  top: 14px;
  right: 14px;
}
.profile-name {
  font-size: 24px;
  font-weight: 750;
  letter-spacing: -0.02em;
  margin-right: 36px;
}
.profile-tagline {
  color: var(--text-dim);
  font-size: 14px;
}
.profile-section-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-top: 8px;
}
.profile-summary {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-dim);
}
.profile-greeting {
  font-size: 13.5px;
  line-height: 1.6;
  border-left: 2px solid var(--accent);
  padding: 6px 12px;
  background: var(--glass);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.profile-actions {
  /* Pinned inside the scrolling column: the decision is always on screen,
     however long the biography above it runs. Solid, with a hairline —
     prose scrolls up to it and stops, never dissolves underneath it. */
  position: sticky;
  bottom: -24px;
  margin: auto -26px -24px;
  padding: 12px 26px 18px;
  background: var(--bg-raise);
  border-top: 1px solid var(--edge);
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
@media (max-width: 640px) {
  .character-profile {
    grid-template-columns: 1fr;
    max-height: calc(100vh - 32px);
  }
  .profile-art-side {
    min-height: 200px;
  }
  .profile-art-side .poster-scrim {
    background: linear-gradient(to bottom, transparent 55%, var(--bg-raise));
  }
}

/* Settings nav items carry their glyphs. */
.settings-nav-item {
  display: flex;
  align-items: center;
  gap: 9px;
}
.settings-nav-item svg {
  flex-shrink: 0;
  opacity: 0.75;
}

/* Gallery header actions: creation is a verb in the toolbar, not a ghost
   on the shelf. */
.screen-head .head-actions {
  display: flex;
  gap: 10px;
  align-items: center;
}

/* Remix banner: one quiet sentence about whose work this is. */
.remix-banner {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 12px 16px;
  border-radius: var(--radius);
  margin-bottom: 14px;
  font-size: 13px;
  color: var(--text-dim);
}
.remix-banner svg {
  color: var(--accent);
  flex-shrink: 0;
  margin-top: 1px;
}

/* Account exit row: leaving is quiet, deleting has to be asked twice. */
.account-actions {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}
.button.danger-ghost {
  border: 1px solid color-mix(in oklab, var(--danger) 45%, transparent);
  color: var(--danger);
  background: transparent;
}
.button.danger-ghost.armed {
  background: var(--danger);
  color: #fff;
  border-color: transparent;
}

/* The memory pane gets the room it was being denied: the panel fills the
   pane's height and scrolls itself, instead of crushing the graph into
   whatever sliver the picker left. */
.settings-pane .memory-panel {
  max-height: 44vh;
  overflow-y: auto;
  padding: 4px 2px;
}
/* Room is for content: before a character is chosen the viewer is empty,
   and an empty box holding 300px open is just a hole in the page. */
.settings-pane .memory-panel:not(:empty) {
  min-height: 300px;
}
.settings-pane .memory-panel h3 {
  margin-top: 10px;
}

/* ── Group picker, humanised ───────────────────────────────────────── */
.picker-list {
  display: grid;
  gap: 8px;
  max-height: 40vh;
  overflow-y: auto;
  padding: 2px;
  margin-bottom: 14px;
}
.picker-person {
  display: flex;
  gap: 10px;
  align-items: center;
  text-align: left;
  /* A grid item's min-width defaults to its content, so a no-wrap tagline
     was forcing every row wider than the modal — the whole list side-
     scrolled. Zero it: the tagline's ellipsis needs permission to shrink. */
  min-width: 0;
  width: 100%;
  padding: 8px 10px;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background: var(--glass);
  cursor: pointer;
  transition:
    border-color 0.15s ease,
    background 0.15s ease;
}
.picker-person:hover {
  border-color: var(--edge-strong);
}
.picker-person.chosen {
  border-color: var(--accent-ring);
  background: var(--accent-soft);
}
.picker-person-text {
  flex: 1;
  min-width: 0;
}
.picker-person-text .name {
  font-weight: 650;
  font-size: 14px;
}
.picker-person-tagline {
  font-size: 11.5px;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.picker-check {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  border: 1px solid var(--edge-strong);
  color: var(--text-faint);
  transform: rotate(0deg);
  transition: all 0.18s ease;
  flex-shrink: 0;
}
.picker-person.chosen .picker-check {
  background: var(--accent-grad);
  border-color: transparent;
  color: var(--on-accent, #fff);
  transform: rotate(45deg);
}
.picker-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
}
.picker-count {
  color: var(--text-faint);
  font-size: 13px;
}
.picker-body {
  padding: 4px 22px 20px;
  overflow-y: auto;
}
.scene-line {
  max-width: 52ch;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── No visible scrollbars ─────────────────────────────────────────────
   Scrolling everywhere, bars nowhere: the modern-app look the rest of the
   chrome already speaks. Applied at the end so it wins over the per-pane
   scrollbar-width rules above. */
* {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
*::-webkit-scrollbar {
  display: none;
}

.tag-block.hidden {
  display: none;
}

/* ── Prompt studio ─────────────────────────────────────────────────── */
.prompt-modal {
  width: min(680px, calc(100vw - 32px));
}
.prompt-body {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
@media (max-width: 620px) {
  .prompt-body {
    grid-template-columns: 1fr;
  }
}
.prompt-shot {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--edge);
  background: var(--glass);
  display: grid;
  place-items: center;
}
.prompt-shot-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.prompt-shot-empty {
  font-size: 12px;
  color: var(--text-faint);
}
/* Painting: a slow sweep, so a ten-second wait looks like work rather
   than a frozen dialog. */
.prompt-shot.painting::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    110deg,
    transparent 20%,
    var(--accent-soft) 50%,
    transparent 80%
  );
  background-size: 220% 100%;
  animation: painting-sweep 1.4s ease-in-out infinite;
}
@keyframes painting-sweep {
  from {
    background-position: 180% 0;
  }
  to {
    background-position: -60% 0;
  }
}
.style-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 6px;
}
.voice-preview.playing {
  color: var(--accent);
}

/* A control that does not apply right now is absent, not disabled. */
.hidden {
  display: none !important;
}

/* The end of the list, while there is more of it. */
.load-more {
  padding: 22px 0 8px;
  text-align: center;
  font-size: 12.5px;
  color: var(--text-faint);
}

/* ── Dropdowns that belong to the app ─────────────────────────────────
   The OS popup ignores the design system and, on Windows, painted our
   white control text onto its own white menu. The popup is ours now. */
.dropdown {
  position: relative;
  width: fit-content;
  min-width: 180px;
}
.dropdown.compact {
  min-width: 140px;
}
.dropdown-button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 9px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background: var(--glass);
  color: var(--text);
  font-size: 13.5px;
  cursor: pointer;
  text-align: left;
}
.dropdown.compact .dropdown-button {
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 12.5px;
}
.dropdown-button:hover {
  border-color: var(--edge-strong);
}
.dropdown.open .dropdown-button {
  border-color: var(--accent-ring);
}
.dropdown-caption {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dropdown-chevron {
  color: var(--text-faint);
  font-size: 10px;
  transition: transform 0.15s ease;
}
.dropdown.open .dropdown-chevron {
  transform: rotate(180deg);
}
.dropdown-list {
  display: none;
  position: absolute;
  z-index: 80;
  top: calc(100% + 6px);
  left: 0;
  min-width: 100%;
  max-height: 290px;
  overflow-y: auto;
  padding: 5px;
  border-radius: var(--radius);
  border: 1px solid var(--edge-strong);
  background: var(--bg-raise);
  box-shadow: var(--shadow-card);
}
.dropdown.open .dropdown-list {
  display: block;
}
.dropdown-option {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 8px 11px;
  border: none;
  border-radius: calc(var(--radius) - 5px);
  background: transparent;
  color: var(--text);
  font-size: 13px;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
}
.dropdown-option:hover,
.dropdown-option.highlighted {
  background: var(--glass-strong);
}
.dropdown-option.selected {
  color: var(--accent);
  font-weight: 650;
}
.dropdown-option-hint {
  color: var(--text-faint);
  font-size: 11.5px;
}

/* ── Chess by Duo ──────────────────────────────────────────────────── */
/* The park lives in WebGL; everything here is the glass furniture
   floating over it — tokens only, no hue assumptions, Mono-safe. */
/* A quiet vignette pulls the eye to the table; costs nothing to render. */
.chess-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse at 50% 42%,
    transparent 55%,
    rgba(8, 20, 24, 0.38) 100%
  );
}

.chess-stage {
  position: relative;
  height: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.chess-board {
  position: absolute;
  inset: 0;
}
.chess-board canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.chess-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  /* The pregame room: its own surface, not a veil over an empty stage —
     and built from theme variables, so a light theme gets a light room
     and the accent colours the air, whatever the accent is. */
  background:
    radial-gradient(
      120% 90% at 50% 0%,
      color-mix(in oklab, var(--accent) 10%, transparent),
      transparent 62%
    ),
    linear-gradient(
      180deg,
      color-mix(in oklab, var(--text) 5%, var(--bg)),
      var(--bg)
    );
  z-index: 5;
}
/* A full-bleed checkerboard, tilted and slowly drifting — the room you
   wait in is already a chessboard. Oversized so the tilt never shows an
   edge; faint so the card stays the subject. */
.chess-overlay::before {
  content: "";
  position: absolute;
  inset: -60%;
  z-index: 0;
  /* Checker tint comes from the theme's text colour: pale squares on a
     dark theme, ink squares on a light one. */
  background: repeating-conic-gradient(
    color-mix(in oklab, var(--text) 7%, transparent) 0% 25%,
    transparent 0% 50%
  );
  background-size: 110px 110px;
  transform: rotate(-7deg);
  animation: chessRoomDrift 80s linear infinite;
  -webkit-mask-image: radial-gradient(
    75% 75% at 50% 45%,
    rgba(0, 0, 0, 0.9),
    transparent 100%
  );
  mask-image: radial-gradient(
    75% 75% at 50% 45%,
    rgba(0, 0, 0, 0.9),
    transparent 100%
  );
}
/* A slow pool of candle-gold light wandering the board. */
.chess-overlay::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: radial-gradient(
    42% 34% at 30% 30%,
    color-mix(in oklab, var(--accent) 12%, transparent),
    transparent 70%
  );
  animation: chessRoomGlow 26s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes chessRoomDrift {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 220px 110px;
  }
}
@keyframes chessRoomGlow {
  from {
    transform: translate(0, 0);
  }
  to {
    transform: translate(38%, 26%);
  }
}
@media (prefers-reduced-motion: reduce) {
  .chess-overlay::before,
  .chess-overlay::after {
    animation: none;
  }
}
.chess-overlay > * {
  position: relative;
  z-index: 1;
}
.chess-overlay.hidden {
  display: none;
}
.chess-setup {
  width: min(420px, 92%);
  max-height: calc(100% - 32px);
  overflow-y: auto;
  padding: 22px 24px;
  border-radius: var(--radius-lg);
  background: var(--bg-raise);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-lift);
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
  overflow-x: hidden;
}
/* The ROOM is the chessboard now; the card is the object resting on
   it. No checker inside — a clean raised surface, an accent hairline
   along the top edge, and a faint accent ring so it reads as lifted
   off the pattern rather than cut out of it. */
.chess-setup {
  box-shadow:
    var(--shadow-lift),
    0 0 0 1px color-mix(in oklab, var(--accent) 22%, transparent),
    0 18px 60px color-mix(in oklab, var(--accent) 12%, transparent);
}
.chess-setup::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--accent-grad);
  opacity: 0.85;
  pointer-events: none;
}

/* ── Loading surface: held until the valley's first painted frame ── */
.chess-loading {
  position: absolute;
  inset: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background:
    radial-gradient(
      120% 90% at 50% 6%,
      rgba(84, 116, 143, 0.32),
      transparent 62%
    ),
    linear-gradient(180deg, #11161f, #0b0e13);
  transition: opacity 460ms ease;
}
.chess-loading.fading {
  opacity: 0;
  pointer-events: none;
}
.chess-loading.hidden {
  display: none;
}
.chess-loading-motif {
  width: 96px;
  height: 96px;
  display: grid;
  place-items: center;
  color: #e8c56c;
  border-radius: 22px;
  border: 1px solid rgba(232, 197, 108, 0.22);
  background: repeating-conic-gradient(
    rgba(232, 197, 108, 0.1) 0% 25%,
    rgba(255, 255, 255, 0.03) 0% 50%
  );
  background-size: 32px 32px;
  animation: chessCheckerDrift 7s linear infinite;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
}
@keyframes chessCheckerDrift {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 64px 32px;
  }
}
.chess-loading-title {
  font-weight: 750;
  font-size: 20px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #e9e5da;
}
.chess-loading-status {
  font-size: 14px;
  color: rgba(233, 229, 218, 0.62);
  min-height: 1.3em;
}
.chess-loading-dots {
  display: flex;
  gap: 7px;
}
.chess-loading-dots span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(232, 197, 108, 0.75);
  animation: chessLoadingDot 1.3s ease-in-out infinite;
}
.chess-loading-dots span:nth-child(2) {
  animation-delay: 0.18s;
}
.chess-loading-dots span:nth-child(3) {
  animation-delay: 0.36s;
}
@keyframes chessLoadingDot {
  0%,
  100% {
    opacity: 0.25;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-4px);
  }
}
.chess-setup-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 4px;
}
.chess-setup-head .avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
}
.chess-setup-title {
  font-weight: 750;
  font-size: 17px;
  letter-spacing: -0.01em;
}
.chess-setup-sub {
  font-size: 13px;
  color: var(--text-dim);
}
.chess-elo-row {
  display: flex;
  align-items: center;
  gap: 14px;
}
.chess-elo-slider {
  flex: 1;
  accent-color: var(--accent);
}
.chess-elo-read {
  min-width: 96px;
  text-align: right;
}
.chess-elo-value {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.chess-elo-band {
  display: block;
  font-size: 11.5px;
  color: var(--text-faint);
}
.chess-seat {
  margin-top: 8px;
}
.chess-credits {
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 2px;
}
.chess-credits a {
  color: var(--text-faint);
}

.chess-plate {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px 8px 8px;
  border-radius: 999px;
  background: var(--bg-raise);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-card);
  z-index: 4;
  transition: box-shadow 80ms ease-out;
}
.chess-plate.hidden {
  display: none;
}
.chess-plate.is-speaking {
  box-shadow:
    0 0 0 var(--ring-width, 3px) var(--ring-speaking),
    0 0 12px color-mix(in oklab, var(--ring-speaking) 55%, transparent);
}
.chess-plate-avatar .avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
}
.chess-plate-name {
  font-weight: 650;
  font-size: 14px;
}
.chess-plate-state {
  font-size: 12.5px;
  color: var(--text-faint);
  min-width: 0;
}
.chess-plate.thinking .chess-plate-state::after {
  content: "thinking…";
  animation: chess-think 1.4s ease-in-out infinite;
}
@keyframes chess-think {
  50% {
    opacity: 0.35;
  }
}

.chess-caption {
  position: absolute;
  top: 72px;
  left: 50%;
  transform: translateX(-50%);
  max-width: min(480px, 86%);
  padding: 10px 16px;
  border-radius: var(--radius);
  background: var(--bg-raise);
  border: 1px solid var(--edge);
  font-size: 13.5px;
  line-height: 1.5;
  z-index: 4;
  box-shadow: var(--shadow-card);
}
.chess-caption.hidden {
  display: none;
}

/* Errors float over the park, not under it. */
.chess-stage .call-notice {
  position: absolute;
  top: 128px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 7;
  padding: 0 14px;
  text-align: center;
}

.chess-bar {
  position: absolute;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  /* Phones: the row wraps instead of clipping Resign and Leave off
     the edge of the world. */
  max-width: calc(100% - 24px);
  flex-wrap: wrap;
  justify-content: center;
  row-gap: 6px;
}
@media (max-width: 700px) {
  .chess-bar .call-button {
    padding: 0 10px;
    min-height: 38px;
    font-size: 12.5px;
  }
}
.chess-bar.hidden {
  display: none;
}
.call-button.armed {
  background: var(--danger);
  color: #fff;
}

.chess-promotion {
  position: absolute;
  bottom: 88px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 999px;
  background: var(--bg-raise);
  border: 1px solid var(--edge-strong);
  box-shadow: var(--shadow-lift);
  z-index: 6;
}
.chess-promotion.hidden {
  display: none;
}
.chess-promotion-choice {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--edge);
  background: var(--glass-strong);
  color: var(--text);
  font-size: 26px;
  cursor: pointer;
}
.chess-promotion-choice:hover {
  background: var(--accent-grad);
  color: var(--on-accent, #fff);
}

.chess-end {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(360px, 90%);
  height: fit-content;
  padding: 22px 24px;
  border-radius: var(--radius-lg);
  background: var(--bg-raise);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-lift);
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 6;
}
.chess-end.hidden {
  display: none;
}
.chess-end-result {
  font-size: 17px;
  font-weight: 700;
}
.chess-end-meta {
  font-size: 13px;
  color: var(--text-dim);
}
.chess-end-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 6px;
}

.chess-moves {
  position: absolute;
  right: 14px;
  top: 148px;
  bottom: 104px;
  width: 148px;
  overflow-y: auto;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: color-mix(in oklab, var(--bg-raise) 82%, transparent);
  border: 1px solid var(--edge);
  z-index: 4;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
.chess-moves.hidden {
  display: none;
}
.chess-move-row {
  display: grid;
  grid-template-columns: 28px 1fr 1fr;
  gap: 4px;
  padding: 1px 0;
}
.chess-move-number {
  color: var(--text-faint);
}
/* Every move is a way back to the position it produced. */
.chess-move-cell {
  appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  padding: 1px 5px;
  border-radius: 5px;
  cursor: pointer;
}
.chess-move-cell:hover {
  background: color-mix(in oklab, var(--text) 10%, transparent);
}
.chess-move-cell.active {
  background: color-mix(in oklab, #e8c56c 26%, transparent);
  color: var(--text);
  font-weight: 650;
}
.chess-move-cell.empty {
  cursor: default;
}

/* ── Reviewing an earlier position ── */
.chess-review {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* Clear of the control bar, which wraps to two rows at this width. */
  bottom: 150px;
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px 8px 12px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--bg-raise) 88%, transparent);
  border: 1px solid color-mix(in oklab, #e8c56c 35%, var(--edge));
  box-shadow: var(--shadow-lift);
  font-size: 13px;
}
.chess-review.hidden {
  display: none;
}
.chess-review-label {
  color: var(--text-dim);
  min-width: 132px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.chess-review-step {
  appearance: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 1px solid var(--edge);
  background: transparent;
  color: var(--text);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.chess-review-step:hover {
  background: color-mix(in oklab, var(--text) 12%, transparent);
}
.chess-review-live {
  appearance: none;
  border: 0;
  border-radius: 999px;
  padding: 6px 12px;
  background: #e8c56c;
  color: #241c08;
  font-weight: 650;
  font-size: 12.5px;
  cursor: pointer;
}
/* A board being reviewed is not a board you can play on; the tint says
   so before you try to drag a piece. */
.chess-stage.is-reviewing .chess-board::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 2px color-mix(in oklab, #e8c56c 45%, transparent);
  border-radius: var(--radius-lg);
}

.chess-picker {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
}
.chess-picker .picker-person {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* The chat header's play button wears a dot while a game is saved. */
.button.has-saved-game {
  position: relative;
}
.button.has-saved-game::after {
  content: "";
  position: absolute;
  top: 6px;
  right: 6px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

.game-card.playable {
  cursor: pointer;
}
.game-card.playable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── The launcher: hitting Play opens a room, not a list ───────────── */
.launcher-modal {
  width: min(1120px, 74vw);
  max-width: none;
  height: min(780px, 86vh);
  display: flex;
  flex-direction: column;
  position: relative;
  padding: 0;
  overflow: hidden;
  /* A launcher is a place, not a pane of glass: solid raise surface so
     the chat behind never bleeds through the shelves. */
  background: var(--bg-raise);
}
@media (max-width: 900px) {
  .launcher-modal {
    width: 94vw;
    height: 92vh;
  }
}
.launcher-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 3;
}
.launcher-shell {
  flex: 1;
  display: grid;
  grid-template-columns: 216px 1fr;
  min-height: 0;
}
@media (max-width: 760px) {
  .launcher-shell {
    grid-template-columns: 1fr;
  }
  .launcher-side {
    display: none;
  }
}

/* ── Sidebar: the launcher's spine ── */
.launcher-side {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px 14px 16px;
  border-right: 1px solid var(--edge);
  background: var(--glass);
}
.launcher-side-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 8px 16px;
}
.launcher-side-head .avatar {
  width: 38px;
  height: 38px;
  border-radius: 50%;
}
.launcher-side-kicker {
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.launcher-side-name {
  font-weight: 700;
  font-size: 14.5px;
}
.launcher-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.launcher-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-dim);
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}
.launcher-nav-item:hover {
  background: var(--glass-strong);
  color: var(--text);
}
.launcher-nav-item.active {
  background: var(--accent-soft);
  color: var(--text);
}
.launcher-side-spacer {
  flex: 1;
}
.launcher-desktop-cta {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: var(--radius);
  border: 1px solid var(--edge-strong);
  background: var(--glass-strong);
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.launcher-desktop-cta:hover {
  border-color: var(--accent-ring);
}
.launcher-desktop-cta.glow {
  background: var(--accent-grad);
  color: var(--on-accent, #fff);
  border-color: transparent;
  box-shadow:
    0 4px 18px color-mix(in oklab, var(--accent) 45%, transparent),
    0 0 0 1px color-mix(in oklab, var(--accent) 30%, transparent);
  transition:
    box-shadow 0.2s ease,
    transform 0.15s ease;
}
.launcher-desktop-cta.glow:hover {
  transform: translateY(-1px);
  box-shadow:
    0 6px 26px color-mix(in oklab, var(--accent) 60%, transparent),
    0 0 0 1px color-mix(in oklab, var(--accent) 40%, transparent);
}
.launcher-desktop-cta.glow .launcher-desktop-cta-sub {
  color: color-mix(in oklab, var(--on-accent, #fff) 75%, transparent);
}
.launcher-desktop-cta-title {
  font-weight: 700;
  font-size: 13px;
}
.launcher-desktop-cta-sub {
  font-size: 10.5px;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.launcher-desktop-note {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  padding: 8px 16px;
  border-radius: 999px;
  background: var(--bg-raise);
  border: 1px solid var(--edge-strong);
  box-shadow: var(--shadow-lift);
  font-size: 12.5px;
  color: var(--text-dim);
  z-index: 4;
}
.launcher-desktop-note.hidden {
  display: none;
}

/* ── Content pane: room to breathe ── */
.launcher-content {
  overflow-y: auto;
  padding: 26px 30px 22px;
  display: flex;
  flex-direction: column;
  gap: 28px;
  min-height: 0;
}

.launcher-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.launcher-section-head {
  display: flex;
  align-items: center;
  gap: 12px;
}
.launcher-section-head h3 {
  font-size: 16px;
  font-weight: 750;
  letter-spacing: -0.01em;
}
.launcher-kicker {
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--accent-soft);
}
.launcher-install {
  margin-left: auto;
}
.launcher-install-note {
  font-size: 12.5px;
  color: var(--text-dim);
  margin: -4px 0 2px;
}

.launcher-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
  gap: 14px;
}
.launcher-card {
  border-radius: var(--radius-lg);
  border: 1px solid var(--edge);
  background: var(--glass);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition:
    transform 0.15s ease,
    box-shadow 0.15s ease;
}
.launcher-card:not(.unreleased):not(.locked):hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card);
}
.launcher-art {
  position: relative;
  aspect-ratio: 16 / 9;
  background:
    radial-gradient(120% 140% at 20% 0%, var(--accent-soft), transparent 60%),
    var(--glass-strong);
}
.launcher-art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.launcher-art-name {
  position: absolute;
  left: 12px;
  bottom: 10px;
  font-weight: 750;
  font-size: 15px;
  color: #fff;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.75);
}
.launcher-card-body {
  padding: 12px 14px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.launcher-card-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 14.5px;
}
.launcher-card-blurb {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-dim);
}
.launcher-play {
  margin-top: 4px;
  align-self: flex-start;
  display: flex;
  align-items: center;
  gap: 8px;
}
.launcher-lock {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-faint);
  border: 1px solid var(--edge);
  border-radius: 999px;
  padding: 3px 9px;
}
.launcher-card.locked .launcher-art img {
  filter: saturate(0.55) brightness(0.85);
}
.launcher-card.unreleased .launcher-art img {
  filter: saturate(0.25) brightness(0.7);
}
.launcher-card.unreleased {
  opacity: 0.85;
}
.launcher-disclaimer {
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--text-faint);
  margin-top: 2px;
}

/* First flight: a hero spread, not a floating column. */
.launcher-hero {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 34px;
  align-items: center;
  padding: 8px 6px;
}
@media (max-width: 860px) {
  .launcher-hero {
    grid-template-columns: 1fr;
  }
  .launcher-hero-art {
    display: none;
  }
}
.launcher-hero-copy {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.launcher-hero-copy h3 {
  font-size: 26px;
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: -0.02em;
  white-space: pre-line;
  margin-bottom: 4px;
}
.launcher-hero-art {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-lift);
  transform: rotate(1.5deg);
}
.launcher-hero-art img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.launcher-hero-art-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 24px 16px 12px;
  font-size: 12.5px;
  font-weight: 650;
  color: #fff;
  background: linear-gradient(transparent, rgba(8, 6, 12, 0.8));
}
.launcher-intro-point {
  display: flex;
  gap: 14px;
  align-items: flex-start;
}
.launcher-intro-glyph {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: var(--accent-soft);
  color: var(--accent);
}
.launcher-intro-title {
  font-weight: 700;
  font-size: 14.5px;
  margin-bottom: 2px;
}
.launcher-intro-text {
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-dim);
}
.launcher-intro-go {
  align-self: flex-start;
  margin-top: 8px;
  min-height: 46px;
  padding: 0 28px;
}
.launcher-weekly {
  align-self: flex-start;
  font-size: 10px;
  padding: 3px 8px;
  letter-spacing: 0.05em;
}
.launcher-hero-deck {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.launcher-deck {
  position: relative;
  width: min(340px, 100%);
  aspect-ratio: 4 / 5;
}
.launcher-deck-card {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-lift);
  opacity: 0;
  transform: translateX(26px) rotate(2.5deg) scale(0.96);
  transition:
    opacity 0.45s ease,
    transform 0.45s ease;
  pointer-events: none;
}
.launcher-deck-card.current {
  opacity: 1;
  transform: translateX(0) rotate(0deg) scale(1);
}
.launcher-deck-card.leaving {
  opacity: 0;
  transform: translateX(-26px) rotate(-2.5deg) scale(0.96);
}
.launcher-deck-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.launcher-deck-name {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 30px 16px 14px;
  font-size: 15px;
  font-weight: 750;
  color: #fff;
  background: linear-gradient(transparent, rgba(8, 6, 12, 0.85));
}
.launcher-deck-dots {
  display: flex;
  gap: 6px;
}
.launcher-deck-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--edge-strong);
  transition:
    background 0.3s ease,
    transform 0.3s ease;
}
.launcher-deck-dot.current {
  background: var(--accent);
  transform: scale(1.25);
}

/* Settings: the game picker, then the game's own room. */
.launcher-settings-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.launcher-settings-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 14px 10px 10px;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: var(--glass);
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.launcher-settings-row:hover:not(.dim) {
  background: var(--glass-strong);
  border-color: var(--edge-strong);
}
.launcher-settings-row.dim {
  opacity: 0.55;
  cursor: default;
}
.launcher-settings-thumb {
  width: 72px;
  height: 44px;
  border-radius: 8px;
  object-fit: cover;
  background: var(--glass-strong);
  flex: none;
}
.launcher-settings-row-body {
  flex: 1;
}
.launcher-chevron {
  font-size: 20px;
  color: var(--text-faint);
}
.launcher-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  border: none;
  background: transparent;
  color: var(--text-dim);
  font-size: 13px;
  cursor: pointer;
  padding: 4px 0;
}
.launcher-back:hover {
  color: var(--text);
}
.launcher-settings-banner {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--edge);
  aspect-ratio: 5 / 1.4;
}
.launcher-settings-banner img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.launcher-settings-banner-name {
  position: absolute;
  left: 16px;
  bottom: 12px;
  font-size: 17px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.8);
}
.launcher-replay-intro {
  align-self: flex-start;
  margin-top: 8px;
}

/* Settings rows inside the launcher. */
.launcher-setting {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 14px 16px;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: var(--glass);
}
.launcher-setting-title {
  font-weight: 650;
  font-size: 14px;
}
.launcher-setting-sub {
  font-size: 12.5px;
  color: var(--text-dim);
  margin-top: 2px;
}
.launcher-setting-elo {
  flex-direction: column;
  gap: 12px;
}
.launcher-elo-row {
  width: 100%;
}

/* ── One shelf language: locks, pickers, and the big tab's CTA ─────── */
.game-lock {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(10, 8, 16, 0.65);
  color: #fff;
  backdrop-filter: blur(4px);
  z-index: 2;
}
.game-card.locked .game-art {
  filter: saturate(0.6) brightness(0.85);
}

/* The launcher's shelves use the same posters, sized for a modal. */
.launcher-posters {
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
}
.launcher-posters .game-card {
  max-width: 210px;
}

.games-section-head {
  margin-top: 10px;
}
.games-section-head .game-section {
  margin: 0;
}
.games-desktop-cta {
  margin-left: auto;
  margin-right: 12px;
}

/* ── The opponent picker: glass, air, search, two worlds ───────────── */
.opponent-picker {
  width: min(440px, 92vw);
  padding: 24px 24px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--bg-raise);
  border: 1px solid var(--edge-strong);
  box-shadow: var(--shadow-lift);
  border-radius: var(--radius-lg);
}
.opponent-picker h2 {
  font-size: 18px;
  font-weight: 750;
  letter-spacing: -0.01em;
}
.opponent-sub {
  font-size: 12.5px;
  color: var(--text-dim);
  margin-top: -8px;
}
.opponent-search {
  width: 100%;
  padding: 10px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background: var(--glass);
  color: var(--text);
  font-size: 13.5px;
}
.opponent-search:focus {
  outline: none;
  border-color: var(--accent-ring);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.opponent-tabs {
  align-self: flex-start;
}
.opponent-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
  margin: 0 -6px;
  padding: 0 6px;
}
.opponent-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 12px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.opponent-row:hover {
  background: var(--glass-strong);
  border-color: var(--edge);
}
.opponent-row .avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  flex: none;
}
.opponent-row-body {
  flex: 1;
  min-width: 0;
}
.opponent-row-name {
  font-weight: 650;
  font-size: 14px;
}
.opponent-row-tagline {
  font-size: 12px;
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.opponent-row-go {
  color: var(--text-faint);
  opacity: 0;
  transition: opacity 0.12s ease;
}
.opponent-row:hover .opponent-row-go {
  opacity: 1;
  color: var(--accent);
}
.opponent-empty {
  padding: 18px 6px;
  text-align: center;
}

/* ── The Games tab as a full launcher ──────────────────────────────── */
.games-launcher {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 0;
}
.games-topbar {
  display: flex;
  align-items: center;
  gap: 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--edge);
}
.games-topbar h2 {
  margin: 0;
}
.games-tabs {
  display: flex;
  gap: 4px;
  margin-left: auto;
}
.games-tab {
  padding: 8px 16px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--text-dim);
  font-size: 13.5px;
  font-weight: 650;
  cursor: pointer;
}
.games-tab:hover {
  background: var(--glass-strong);
  color: var(--text);
}
.games-tab.active {
  background: var(--accent-soft);
  color: var(--text);
}
.games-pane {
  flex: 1;
  overflow-y: auto;
  padding: 24px 2px 18px;
  display: flex;
  flex-direction: column;
  gap: 34px;
  min-height: 0;
}
.games-shelf {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.games-help {
  max-width: 560px;
  gap: 18px;
}
.games-settings-note {
  margin-top: 2px;
}
.games-footer {
  display: flex;
  align-items: center;
  gap: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--edge);
}
.games-footer-cta {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
}
/* In the footer the CTA sits beside fine print: same visual weight
   class, one size down, so the row reads as one quiet line. */
.games-footer .launcher-desktop-cta {
  padding: 5px 12px;
  gap: 8px;
  border-radius: 10px;
}
.games-footer .launcher-desktop-cta-title {
  font-size: 12px;
}
.games-footer .launcher-desktop-cta-sub {
  font-size: 9.5px;
}
.games-footer .launcher-desktop-cta svg {
  width: 13px;
  height: 13px;
}
.games-fineprint {
  margin: 0;
  flex: 1;
}

/* Poster cards that open popups show a hand, like everything honest. */
.game-card.openable {
  cursor: pointer;
}
.game-card.openable:focus-visible,
.game-card.playable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* The glassy per-game popup. */
.game-info-popup {
  width: min(400px, 92vw);
  padding: 0;
  overflow: hidden;
  background: var(--bg-raise);
  border: 1px solid var(--edge-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
}
.game-info-art {
  position: relative;
  aspect-ratio: 16 / 7;
  background: var(--glass-strong);
}
.game-info-art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.game-info-name {
  position: absolute;
  left: 18px;
  bottom: 12px;
  font-size: 19px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.85);
}
.game-info-body {
  padding: 16px 20px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.game-info-blurb {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-dim);
}
.game-info-soon {
  font-size: 12.5px;
  color: var(--text-faint);
}
.game-info-cta {
  align-self: flex-start;
}
.game-info-close {
  align-self: flex-end;
  margin-top: -6px;
}

/* ── The flat board: same session, no valley ── */
.board2d {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background:
    radial-gradient(
      110% 80% at 50% 0%,
      color-mix(in oklab, #54748f 24%, transparent),
      transparent 60%
    ),
    linear-gradient(180deg, #171d27, #10141b);
  padding: 18px 12px 96px;
}
.board2d.inert .board2d-square {
  cursor: default;
}
.board2d-frame {
  /* The board is a square sized by whichever direction is tighter;
     the 96px keeps it clear of the control bar. */
  width: min(78vh, 92%, 720px);
  max-height: calc(100% - 120px);
  aspect-ratio: 1;
  padding: 10px;
  border-radius: 12px;
  background: linear-gradient(160deg, #6b4f37, #4e3826);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5);
}
.board2d-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);
  width: 100%;
  height: 100%;
  border-radius: 6px;
  overflow: hidden;
}
.board2d-square {
  appearance: none;
  border: 0;
  padding: 0;
  position: relative;
  cursor: pointer;
  font: inherit;
}
.board2d-square.light {
  background: #e7e2d2;
}
.board2d-square.dark {
  background: #4a5568;
}
.board2d-square.moved.light {
  background: color-mix(in oklab, #e8c56c 55%, #e7e2d2);
}
.board2d-square.moved.dark {
  background: color-mix(in oklab, #e8c56c 42%, #4a5568);
}
/* Legal moves: a dot on empty squares, a ring around capturable prey. */
.board2d-square.legal::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 22%;
  height: 22%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: color-mix(in oklab, #e8c56c 85%, transparent);
  pointer-events: none;
}
.board2d-square.legal-capture::after {
  content: "";
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  border: 3px solid color-mix(in oklab, #e8c56c 85%, transparent);
  pointer-events: none;
}
.board2d-coord {
  position: absolute;
  font-size: clamp(8px, 1.3vh, 12px);
  font-weight: 650;
  opacity: 0.55;
  pointer-events: none;
  color: #1d2430;
}
.board2d-square.dark .board2d-coord {
  color: #dfe4ec;
}
.board2d-coord.rank {
  top: 3px;
  left: 4px;
}
.board2d-coord.file {
  right: 4px;
  bottom: 2px;
}
.board2d-piece {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: clamp(20px, 7.2vh, 58px);
  line-height: 1;
  pointer-events: none;
  will-change: transform;
  user-select: none;
}
.board2d-piece.white {
  color: #f4efe2;
  text-shadow:
    0 2px 3px rgba(0, 0, 0, 0.45),
    0 0 1px #6b6455;
}
.board2d-piece.black {
  color: #23262e;
  text-shadow:
    0 2px 3px rgba(0, 0, 0, 0.35),
    0 0 1px #6a7690;
}
.board2d-piece.taken {
  transition:
    opacity 200ms ease,
    transform 200ms ease;
  opacity: 0;
  transform: scale(0.6);
}
.board2d-piece.tipped {
  transition: transform 550ms ease;
  transform: rotate(78deg) translateY(8%);
}
.board2d-piece.arriving {
  opacity: 0;
  transform: scale(0.7);
}
.board2d-tray {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 2px;
  min-height: 22px;
  max-width: min(78vh, 92%, 720px);
  font-size: 19px;
  line-height: 1;
}
.board2d-lost {
  opacity: 0.85;
}
.board2d-lost.white {
  color: #ece6d6;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.board2d-lost.black {
  color: #2b2f38;
  text-shadow: 0 1px 2px rgba(90, 105, 130, 0.6);
}

/* ── The A+C setup card: marquee, living preview, ticket stub ── */
.chess-setup {
  animation: chessCardIn 380ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
@keyframes chessCardIn {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.985);
  }
}
@media (prefers-reduced-motion: reduce) {
  .chess-setup {
    animation: none;
  }
}
.chess-kicker {
  text-align: center;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.chess-versus {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 18px;
  margin: 2px 0 4px;
}
.chess-versus-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 84px;
}
.chess-versus-side .avatar {
  width: 52px;
  height: 52px;
  border-radius: 50%;
}
.chess-versus-name {
  font-size: 13px;
  font-weight: 650;
  max-width: 110px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chess-versus-elo {
  font-size: 11.5px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.chess-versus-vs {
  align-self: center;
  font-size: 12px;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  padding: 3px 9px;
  border: 1px solid var(--edge);
  border-radius: 999px;
}
.chess-preview-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.chess-preview-thumb {
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 10px;
  border: 1px solid var(--edge);
  transition: background 200ms ease;
}
.chess-preview-thumb.\33 d {
  background-image: url("games/chess-by-duo.jpeg");
  background-size: cover;
  background-position: center;
}
.chess-preview-thumb.\32 d {
  background: repeating-conic-gradient(#4a5568 0% 25%, #e7e2d2 0% 50%);
  background-size: 32px 32px;
  background-position: center;
}
.chess-preview-pick {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.chess-preview-hint {
  font-size: 12px;
  color: var(--text-dim);
}
.chess-elo-ticks {
  display: flex;
  justify-content: space-between;
  font-size: 10.5px;
  color: var(--text-faint);
  margin-top: -4px;
  padding: 0 2px;
}
.chess-quote {
  min-height: 1.4em;
  text-align: center;
  font-style: italic;
  font-size: 13.5px;
  color: color-mix(in oklab, var(--accent) 55%, var(--text-dim));
  margin: 2px 0;
}
/* The stub: tear along the dashed line to sit down. */
.chess-cta-stub {
  margin: 8px -24px -22px;
  padding: 16px 24px 16px;
  border-top: 1px dashed color-mix(in oklab, var(--text) 25%, transparent);
  background: color-mix(in oklab, var(--text) 3%, transparent);
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
}
/* Perforation notches where the dashed line meets the card edges. */
.chess-cta-stub::before,
.chess-cta-stub::after {
  content: "";
  position: absolute;
  top: -7px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--bg);
}
.chess-cta-stub::before {
  left: -7px;
}
.chess-cta-stub::after {
  right: -7px;
}
.chess-cta-stub .chess-credits {
  margin: 0;
  text-align: center;
}

.chess-elo-lane {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.chess-elo-lane .chess-elo-slider {
  width: 100%;
}

/* ── Accessibility floor: applies everywhere, overridden nowhere ── */
/* Keyboard focus is visible on every interactive element. Text fields
   keep their own ring (border + glow on :focus); everything else gets
   the accent outline, offset so it never clips a rounded control. */
:where(
  button,
  a[href],
  summary,
  [role="button"],
  [tabindex]:not([tabindex="-1"])
):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* Motion is a preference, not a requirement: with reduced motion on,
   every decorative animation and transition collapses to an instant.
   Anything the app relies on for sequencing uses timers, not
   transitionend, so nothing waits on an animation that never plays. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Sign in: the first thing anyone sees ── */
.auth {
  position: relative;
  overflow: hidden;
}
.auth::before {
  content: "";
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(
      40% 34% at 30% 28%,
      color-mix(in oklab, var(--accent) 22%, transparent),
      transparent 70%
    ),
    radial-gradient(
      36% 30% at 72% 70%,
      color-mix(in oklab, var(--accent-2) 16%, transparent),
      transparent 70%
    );
  pointer-events: none;
  animation: authGlow 18s ease-in-out infinite alternate;
}
@keyframes authGlow {
  to {
    transform: translate(4%, -3%) scale(1.06);
  }
}
.auth-card {
  position: relative;
  padding: 34px 32px 28px;
  animation: chessCardIn 420ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.auth-brand {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-bottom: 8px;
}
.auth-brand b {
  font-size: 40px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.auth-brand span {
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 3px 8px;
}
.auth-card .tagline {
  font-size: 15px;
  line-height: 1.45;
  color: var(--text-dim);
  margin-bottom: 14px;
  max-width: 30ch;
}
.auth-beats {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 22px;
}
.auth-beat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-dim);
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: var(--glass);
}
.auth-beat svg {
  color: var(--accent);
}

/* ── The welcome ── */
.onboard {
  position: fixed;
  inset: 0;
  z-index: 260;
  display: grid;
  place-items: center;
  padding: 20px;
  background: color-mix(in oklab, var(--bg) 72%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  animation: onboardIn 320ms ease;
}
.onboard.closing {
  animation: onboardOut 240ms ease forwards;
}
@keyframes onboardIn {
  from {
    opacity: 0;
  }
}
@keyframes onboardOut {
  to {
    opacity: 0;
  }
}
.onboard-card {
  width: min(560px, 100%);
  max-height: calc(100% - 24px);
  overflow-y: auto;
  padding: 30px 32px 22px;
  border-radius: var(--radius-lg);
  background: var(--bg-raise);
  border: 1px solid var(--edge);
  box-shadow:
    var(--shadow-lift),
    0 0 0 1px color-mix(in oklab, var(--accent) 22%, transparent);
  display: flex;
  flex-direction: column;
  gap: 12px;
  animation: chessCardIn 380ms cubic-bezier(0.2, 0.7, 0.3, 1);
}
.onboard-brand {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.onboard-brand b {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.02em;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.onboard-brand span {
  font-size: 10.5px;
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: 999px;
  padding: 3px 8px;
}
.onboard-title {
  font-size: 24px;
  font-weight: 750;
  letter-spacing: -0.015em;
  margin: 0;
}
.onboard-lede {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--text-dim);
  margin: 0;
}
.onboard-beats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
  margin-top: 6px;
}
.onboard-beat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px;
  border-radius: var(--radius);
  border: 1px solid var(--edge);
  background: var(--glass);
  animation: beatIn 480ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
@keyframes beatIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}
.onboard-beat-icon {
  color: var(--accent);
}
.onboard-beat-title {
  font-weight: 650;
  font-size: 14px;
}
.onboard-beat-blurb {
  font-size: 12.5px;
  color: var(--text-dim);
}
.onboard-card label {
  font-size: 12.5px;
  color: var(--text-dim);
  margin-top: 4px;
}
.onboard-bubble {
  margin-top: 6px;
  padding: 12px 14px;
  border-radius: 16px 16px 16px 4px;
  background: var(--glass-strong);
  border: 1px solid var(--edge);
  font-size: 14px;
}
.onboard-bubble-who {
  display: block;
  font-size: 11px;
  color: var(--text-faint);
  margin-bottom: 3px;
}
.onboard-chips,
.onboard-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}
.onboard-chip {
  appearance: none;
  font: inherit;
  font-size: 13px;
  padding: 8px 13px;
  border-radius: 999px;
  border: 1px solid var(--edge-strong);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  transition:
    background 140ms ease,
    border-color 140ms ease,
    transform 140ms ease;
}
.onboard-chip:hover {
  border-color: var(--accent-ring);
}
.onboard-chip.on {
  background: var(--accent-grad);
  border-color: transparent;
  color: var(--on-accent);
  font-weight: 650;
}
.onboard-chip.static {
  cursor: default;
}
.onboard-count {
  font-size: 12.5px;
  color: var(--text-faint);
}
.onboard-options {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-top: 4px;
}
.onboard-option {
  appearance: none;
  font: inherit;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--edge-strong);
  background: var(--glass);
  color: var(--text);
  cursor: pointer;
  transition:
    border-color 140ms ease,
    transform 140ms ease,
    box-shadow 140ms ease;
}
.onboard-option:hover {
  transform: translateY(-1px);
}
.onboard-option.on {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.onboard-option-icon {
  color: var(--accent);
}
.onboard-option-title {
  font-weight: 700;
  font-size: 15px;
}
.onboard-option-blurb {
  font-size: 12.5px;
  color: var(--text-dim);
}
.onboard-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
  padding-top: 14px;
  border-top: 1px solid var(--edge);
}
.onboard-dots {
  display: flex;
  gap: 6px;
}
.onboard-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--edge-strong);
  transition:
    background 160ms ease,
    transform 160ms ease;
}
.onboard-dot.on {
  background: var(--accent);
  transform: scale(1.25);
}
.onboard-actions {
  display: flex;
  gap: 8px;
}
.onboard-actions .hidden {
  display: none;
}
.onboard-skip {
  align-self: center;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-faint);
  font: inherit;
  font-size: 12.5px;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.onboard-skip.hidden {
  display: none;
}

/* ── The sign-in page wears the site's hero ── */
.auth {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 48px;
  align-items: center;
  place-items: stretch;
  max-width: 1080px;
  margin: 0 auto;
  padding: 48px 32px;
  min-height: 100%;
}
.auth-hero {
  position: relative;
  align-self: center;
}
.auth-hero .auth-brand {
  margin-bottom: 22px;
}
.auth-hero .auth-brand b {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.02em;
}
.auth-title {
  font-size: clamp(42px, 6vw, 76px);
  line-height: 0.98;
  letter-spacing: -0.035em;
  font-weight: 600;
  margin-bottom: 18px;
  text-wrap: balance;
}
.auth-title::after {
  content: ".";
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.auth-hero .tagline {
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.5;
  color: var(--text-dim);
  max-width: 44ch;
  margin-bottom: 18px;
}
.auth-hero .auth-beats {
  margin-bottom: 0;
}
.auth-card {
  position: relative;
  width: min(420px, 100%);
  justify-self: end;
  align-self: center;
  padding: 30px 30px 26px;
}
@media (max-width: 860px) {
  .auth {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 32px 20px;
  }
  .auth-card {
    justify-self: stretch;
    width: 100%;
  }
}
