/* ============================================================================
   KANATA — roleplay studio · shared interface stylesheet
   Visual contract: the active "kami (紙 / 纸)" design system.
   The :root block below is that system's tokens.css, pasted verbatim.
   Everything after it composes those tokens.
   Discipline held throughout: one accent (ink blue), serif at weight 500,
   hairline + whisper elevation only, no italic, no blur, no gradient fills.
   ========================================================================= */

/* design-systems/kami/tokens.css — DO NOT EDIT */
:root {
  /* Surface (3 levels) */
  --bg: #f5f4ed;
  --surface: #faf9f5;
  --surface-warm: #e8e6dc;

  /* Foreground ramp (4 levels) */
  --fg: #141413;
  --fg-2: #3d3d3a;
  --muted: #504e49;
  --meta: #6b6a64;

  /* Border (2 levels) */
  --border: #e8e6dc;
  --border-soft: #e5e3d8;

  /* Accent */
  --accent: #1b365d;
  --accent-on: #faf9f5;
  --accent-light: #2d5a8a;

  /* Accent states */
  --accent-hover: var(--accent);
  --accent-active: #142a48;

  /* Semantic */
  --success: #4a6b3a;
  --warn: #8a6b1f;
  --danger: #8a3a30;

  /* Typography */
  --font-display:
    Charter, Georgia, Palatino, "Times New Roman", "Hiragino Mincho ProN",
    "YuMincho", "Source Han Serif SC", serif;
  --font-body:
    Charter, Georgia, Palatino, "Times New Roman", "Hiragino Mincho ProN",
    "YuMincho", "Source Han Serif SC", serif;
  --font-mono:
    "JetBrains Mono", "SF Mono", "Fira Code", Consolas, Monaco,
    "TsangerJinKai02", "Source Han Serif SC", monospace;

  /* Type scale */
  --text-xs: 11px;
  --text-sm: 12px;
  --text-base: 14px;
  --text-md: 15px;
  --text-lg: 17px;
  --text-xl: 22px;
  --text-2xl: 32px;
  --text-3xl: 48px;
  --text-4xl: 96px;

  /* Line height */
  --leading-display: 1.1;
  --leading-tight: 1.25;
  --leading-body: 1.55;
  --leading-dense: 1.4;

  /* Tracking */
  --tracking-display: -1.2px;
  --tracking-eyebrow: 1.2px;
  --tracking-label: 0.4px;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 28px;
  --space-8: 32px;
  --space-12: 48px;
  --space-18: 72px;
  --space-22: 88px;

  /* Web page geometry */
  --section-y-desktop: 72px;
  --section-y-tablet: 48px;
  --section-y-phone: 32px;

  /* Radius */
  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-pill: 9999px;

  /* Elevation (3 levels) */
  --elev-flat: none;
  --elev-ring: 0 0 0 1px var(--border);
  --elev-ring-accent: 0 0 0 1px var(--accent);
  --elev-raised: 0 4px 24px rgba(0, 0, 0, 0.05);

  /* Focus ring */
  --focus-ring: 0 0 0 2px var(--accent-active);

  /* Motion */
  --motion-fast: 150ms;
  --motion-base: 200ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);

  /* Layout */
  --container-max: 1120px;
  --container-gutter-desktop: 64px;
  --container-gutter-tablet: 32px;
  --container-gutter-phone: 16px;

  /* Brand-specific: tag tint scale (solid hex, never rgba) */
  --tag-bg-faint: #eef2f7;
  --tag-bg-soft: #e4ecf5;
  --tag-bg-base: #d6e1ee;
  --tag-bg-strong: #d0dce9;
}

/* ---------------------------------------------------------------------------
   Ink ground. The same system read as dark paper.
   Every value below re-binds a token that already exists — no token is
   invented and no value leaves the palette. Parchment becomes kami's Deep
   Dark, cards lift to its Dark Surface, and the single accent inverts from
   ink on paper (#1b365d) to lit ink (#93aecb), which is the luminance dark
   ground needs. Measured on --bg (#141413): fg 15.9:1 · fg-2 12.2:1 ·
   muted 7.6:1 · meta 5.2:1 · accent 8.0:1 · accent-on 7.4:1 · the dimmest
   caption, --meta on a seal plate, 4.5:1. The hairline sits at 1.43 against
   the page (1.13 on paper), so edges read without a second shadow.
   ------------------------------------------------------------------------ */
:root[data-theme="ink"] {
  /* Surface */
  --bg: #141413;            /* deep dark — olive-tinted, never #000000 */
  --surface: #1c1c1a;       /* card lift, a half-shade above the page */
  --surface-warm: #30302e;  /* dark surface — secondary buttons, veil, slips */

  /* Foreground ramp — the warmth survives the inversion */
  --fg: #f0eee6;
  --fg-2: #d5d2c8;
  --muted: #a9a69c;
  --meta: #8b887f;

  /* Border */
  --border: #32322e;
  --border-soft: #262623;

  /* Accent — still the only chromatic move, raised to reading luminance */
  --accent: #93aecb;
  --accent-on: #121c2e;
  --accent-light: #b3c9de;
  --accent-hover: var(--accent);
  --accent-active: #6e8fb4;   /* pressed: darker, still 5.1:1 under --accent-on */
  --focus-ring: 0 0 0 2px var(--accent);

  /* Semantic — lifted off the dark ground so the status dot still reads */
  --success: #8fae7c;
  --warn: #cfa459;
  --danger: #d98c7f;

  /* Tag fills — solid hex pre-blends, never rgba */
  --tag-bg-faint: #1a222e;
  --tag-bg-soft: #22334a;
  --tag-bg-base: #26374f;
  --tag-bg-strong: #2a3d57;

  /* Elevation — the whisper stays a whisper; only its ground changed */
  --elev-raised: 0 4px 24px rgba(0, 0, 0, 0.45);

  /* Tells the browser itself which ground it is on, so scrollbars and the
     native <select> popup are dark too instead of flashing a white sheet. */
  color-scheme: dark;
}

/* The browser's own selection blue belongs to neither palette. */
:root[data-theme="ink"] ::selection {
  background: var(--tag-bg-base);
  color: var(--fg);
}

/* Nothing else is overridden. Every remaining pairing in the stylesheet is a
   token against a token, so the whole interface inverts together and no
   component needs a private dark rule. */

/* ---------------------------------------------------------------------------
   Application layer. Only aliases and geometry — no new colours.
   --hair      every divider in the studio is the same 1px hairline
   --ok        the only status colour a room ever needs (open / idle)
   ------------------------------------------------------------------------ */
:root {
  --hair: 1px solid var(--border);
  --hair-soft: 1px solid var(--border-soft);
  --shell-max: 1320px;
  --ink: var(--accent);
  color-scheme: light;
}

/* --- reset ---------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 400;
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img,
svg {
  display: block;
  max-width: 100%;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  background: none;
  border: 0;
}
input,
textarea,
select {
  font: inherit;
  color: inherit;
}
p {
  margin: 0;
  text-wrap: pretty;
}
h1,
h2,
h3,
h4 {
  margin: 0;
  text-wrap: balance;
  font-family: var(--font-display);
  font-weight: 500;
}
strong,
b {
  font-weight: 500;
}
ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}
figure {
  margin: 0;
}
[hidden] {
  display: none !important;
}

/* Body links inside panels and footers: underlined, and darker on hover —
   never lighter, so contrast only ever increases. */
.link-quiet {
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--fg-2);
  text-decoration: underline;
  text-decoration-color: var(--border);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition:
    color var(--motion-fast) var(--ease-standard),
    text-decoration-color var(--motion-fast) var(--ease-standard);
}
.link-quiet:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-sm);
}

/* --- type ----------------------------------------------------------------- */
h1,
.h1 {
  font-size: clamp(29px, 3.4vw, 40px);
  line-height: 1.14;
  letter-spacing: -0.4px;
  color: var(--fg);
}
h2,
.h2 {
  font-size: var(--text-xl);
  line-height: var(--leading-tight);
  letter-spacing: 0.2px;
}
h3,
.h3 {
  font-size: var(--text-lg);
  line-height: 1.32;
  letter-spacing: 0;
}
.label {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--meta);
  margin: 0;
}
.label-accent {
  color: var(--accent);
}
.lede {
  font-size: var(--text-lg);
  line-height: 1.55;
  color: var(--muted);
  max-width: 60ch;
}
.small {
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--muted);
}
.tiny {
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--meta);
}
.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.jp {
  font-family: var(--font-display);
  letter-spacing: 0.08em;
}
.rule {
  border: 0;
  border-top: var(--hair);
  margin: 0;
}
.rule-strong {
  border: 0;
  border-top: 1px solid var(--fg);
  margin: 0;
}
.credit {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.5;
  color: var(--meta);
  letter-spacing: 0.04em;
}
.credit a {
  text-decoration: underline;
  text-underline-offset: 2px;
  color: var(--fg-2);
}
.credit a:hover {
  color: var(--accent);
}
a:not(.btn):not(.rail-item):not(.card):not(.brand):hover {
  color: var(--accent);
}

/* --- app shell ------------------------------------------------------------ */
.shell {
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: var(--container-gutter-desktop);
  display: grid;
  grid-template-columns: 236px minmax(0, 1fr);
  gap: var(--space-8);
  align-items: start;
}
.shell-wide {
  grid-template-columns: 236px minmax(0, 1fr);
}
/* Conversation screens carry two side panels plus a script column, so they get
   a wider shell than the browsing pages. */
.shell-room {
  max-width: 1560px;
}
@media (max-width: 1180px) {
  .shell {
    padding-inline: var(--container-gutter-tablet);
    gap: var(--space-6);
    grid-template-columns: 208px minmax(0, 1fr);
  }
}
@media (max-width: 860px) {
  .shell {
    grid-template-columns: minmax(0, 1fr);
    padding-inline: var(--container-gutter-phone);
    gap: 0;
  }
}

/* --- top bar — solid parchment, hairline below, no blur ------------------ */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--bg);
  border-bottom: var(--hair);
}
.topbar-inner {
  max-width: var(--shell-max);
  margin-inline: auto;
  padding: 14px var(--container-gutter-desktop);
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
@media (max-width: 1180px) {
  .topbar-inner {
    padding-inline: var(--container-gutter-tablet);
  }
}
@media (max-width: 860px) {
  .topbar-inner {
    padding-inline: var(--container-gutter-phone);
    gap: var(--space-3);
  }
}
.brand {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}
.brand-name {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-lg);
  letter-spacing: 0.14em;
}
.brand-kanji {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  color: var(--accent);
  letter-spacing: 0.2em;
}
.topbar .search {
  flex: 1;
  max-width: 420px;
}
.topbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-left: auto;
}
@media (max-width: 860px) {
  .topbar .search {
    display: none;
  }
}
@media (max-width: 620px) {
  .topbar-actions .tag {
    display: none;
  }
}

/* --- theme picker — two hairline segments, one remembered choice ---------- */
.themepick {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border-radius: var(--radius-sm);
  box-shadow: 0 0 0 1px var(--border);
}
.themepick button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 30px;
  padding: 0 9px;
  border-radius: var(--radius-xs);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  color: var(--meta);
  transition:
    color var(--motion-fast) var(--ease-standard),
    background var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-fast) var(--ease-standard);
}
.themepick button:hover {
  color: var(--fg);
  background: var(--surface);
}
.themepick button[aria-pressed="true"] {
  color: var(--accent);
  background: var(--tag-bg-soft);
  box-shadow: 0 0 0 1px var(--tag-bg-base);
}
.themepick svg {
  width: 15px;
  height: 15px;
  flex: none;
}
@media (max-width: 620px) {
  /* On a phone the two marks carry it and the words stay for assistive tech,
     so the control keeps its 44px targets instead of a 30px row. */
  .themepick button {
    min-height: 44px;
    min-width: 44px;
    padding: 0 11px;
  }
  .themepick button span {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
@media (max-width: 560px) {
  /* A room's phone header belongs to back-navigation: the studio name goes and
     the room's own name is the h1 directly below the header. Without this the
     room header would need 400px for brand + back + switch + seal. */
  body.is-room .topbar .brand {
    display: none;
  }
}

/* --- left rail ------------------------------------------------------------ */
.rail {
  position: sticky;
  top: 68px;
  padding-block: var(--space-8) var(--space-12);
}
.rail-group + .rail-group {
  margin-top: var(--space-8);
}
.rail-group > .label {
  padding-inline: var(--space-4);
  margin-bottom: var(--space-3);
}
.rail-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: 9px var(--space-4);
  border-radius: var(--radius-md);
  font-size: var(--text-md);
  color: var(--muted);
  transition:
    color var(--motion-fast) var(--ease-standard),
    background var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-base) var(--ease-standard);
}
.rail-item svg {
  width: 17px;
  height: 17px;
  flex: none;
}
.rail-item:hover {
  color: var(--fg);
  background: var(--surface);
}
.rail-item[aria-current="page"] {
  color: var(--fg);
  background: var(--surface);
  box-shadow: var(--elev-ring);
}
.rail-item[aria-current="page"] svg {
  color: var(--accent);
}
.rail-count {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--meta);
}
.rail-note {
  margin-top: var(--space-8);
  padding: var(--space-5);
}
@media (max-width: 860px) {
  .rail {
    position: fixed;
    inset: auto 0 0 0;
    top: auto;
    z-index: 50;
    display: flex;
    gap: var(--space-2);
    justify-content: space-between;
    padding: var(--space-2) var(--space-3)
      calc(var(--space-2) + env(safe-area-inset-bottom, 6px));
    background: var(--surface);
    border-top: var(--hair);
    overflow-x: auto;
  }
  .rail-group {
    display: contents;
  }
  .rail-group > .label,
  .rail-note {
    display: none;
  }
  .rail-item {
    flex-direction: column;
    gap: 4px;
    padding: var(--space-2) var(--space-3);
    min-width: 68px;
    min-height: 52px;
    justify-content: center;
    font-size: var(--text-xs);
    text-align: center;
    border-radius: var(--radius-md);
  }
  .rail-item[aria-current="page"] {
    background: var(--tag-bg-soft);
    box-shadow: none;
    color: var(--accent);
  }
  .rail-count {
    display: none;
  }
  body {
    padding-bottom: 74px;
  }
}

/* --- surfaces ------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: var(--hair);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  transition: box-shadow var(--motion-base) var(--ease-standard);
}
a.card:hover,
button.card:hover,
.card-interactive:hover {
  box-shadow: var(--elev-raised);
}
.card-flat {
  background: transparent;
  border: var(--hair);
}
.card-tight {
  padding: var(--space-5);
}
.card-lead {
  border-radius: var(--radius-lg);
}
.sunk {
  background: var(--surface);
  border: var(--hair);
  border-radius: var(--radius-md);
}
.stack {
  display: flex;
  flex-direction: column;
}
.row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.row-top {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
}
.between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}
.wrap {
  flex-wrap: wrap;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
}
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-5);
}
.grid-auto {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(238px, 1fr));
  gap: var(--space-5);
}
@media (max-width: 620px) {
  .grid-2,
  .grid-3 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --- buttons — one ink fill per view -------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 42px;
  padding: 9px 16px;
  border-radius: var(--radius-md);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  transition:
    background var(--motion-fast) var(--ease-standard),
    color var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-base) var(--ease-standard),
    border-color var(--motion-fast) var(--ease-standard);
}
.btn svg {
  width: 16px;
  height: 16px;
  flex: none;
}
.btn-primary {
  background: var(--accent);
  color: var(--accent-on);
  box-shadow: var(--elev-ring-accent);
}
.btn-primary:hover {
  background: var(--accent-active);
  box-shadow: var(--elev-ring-accent), var(--elev-raised);
}
.btn-primary:active {
  background: var(--accent-active);
}
.btn-secondary {
  background: var(--surface-warm);
  color: var(--fg-2);
  box-shadow: 0 0 0 1px var(--border);
}
.btn-secondary:hover {
  background: var(--surface-warm);
  color: var(--fg);
  box-shadow: 0 0 0 1px var(--fg-2);
}
.btn-raised {
  background: var(--surface-warm);
  color: var(--fg-2);
  box-shadow: 0 0 0 1px var(--border);
}
.btn-raised:hover {
  color: var(--fg);
  box-shadow: 0 0 0 1px var(--fg-2);
}
.btn-quiet {
  background: transparent;
  color: var(--fg-2);
  box-shadow: 0 0 0 1px var(--border);
}
.btn-quiet:hover {
  color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.btn-ghost {
  background: transparent;
  color: var(--accent);
  box-shadow: var(--elev-ring-accent);
}
.btn-ghost:hover {
  color: var(--accent-on);
  background: var(--accent);
}
.btn-icon {
  min-height: 40px;
  width: 40px;
  padding: 0;
  background: transparent;
  color: var(--fg-2);
  box-shadow: 0 0 0 1px var(--border);
}
.btn-icon:hover {
  color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.btn-block {
  width: 100%;
}
.btn-sm {
  min-height: 34px;
  padding: 6px 12px;
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
}
.btn[aria-pressed="true"] {
  background: var(--tag-bg-base);
  color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

/* --- chips / tags --------------------------------------------------------- */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  padding: 6px 12px;
  border-radius: var(--radius-sm);
  background: transparent;
  box-shadow: 0 0 0 1px var(--border);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  color: var(--fg-2);
  transition:
    color var(--motion-fast) var(--ease-standard),
    background var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-fast) var(--ease-standard);
}
.chip:hover {
  color: var(--fg);
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--fg-2);
}
.chip[aria-pressed="true"] {
  background: var(--tag-bg-base);
  color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 7px;
  border-radius: var(--radius-xs);
  background: var(--tag-bg-soft);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: var(--tracking-label);
  color: var(--accent);
}
.tag-quiet {
  background: transparent;
  box-shadow: 0 0 0 1px var(--border);
  color: var(--fg-2);
}
.tag-plain {
  background: var(--surface-warm);
  color: var(--fg-2);
}
.dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--success);
  flex: none;
}
.dot-idle {
  background: var(--meta);
}

/* --- form ----------------------------------------------------------------- */
.search {
  position: relative;
  display: flex;
  align-items: center;
}
.search svg {
  position: absolute;
  left: 13px;
  width: 16px;
  height: 16px;
  color: var(--meta);
}
.field {
  width: 100%;
  min-height: 42px;
  padding: 10px 14px 10px 38px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: var(--hair);
  font-size: var(--text-md);
  transition:
    border-color var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-fast) var(--ease-standard);
}
.field::placeholder {
  color: var(--meta);
  opacity: 1;
}
.field:hover {
  border-color: var(--fg-2);
}
.field:focus {
  background: var(--surface);
  border-color: var(--accent);
  box-shadow: var(--focus-ring);
  outline: none;
}
.field-flat {
  padding-left: 14px;
}
.select {
  min-height: 38px;
  padding: 7px 12px;
  border-radius: var(--radius-sm);
  background: transparent;
  border: var(--hair);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  color: var(--fg-2);
}
.select:hover {
  color: var(--fg);
  border-color: var(--fg-2);
}
.switch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-base);
  color: var(--muted);
}
.switch input {
  width: 34px;
  height: 20px;
  appearance: none;
  margin: 0;
  border-radius: var(--radius-pill);
  background: var(--surface-warm);
  box-shadow: 0 0 0 1px var(--border);
  position: relative;
  transition: background var(--motion-fast) var(--ease-standard);
}
.switch input::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 14px;
  height: 14px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--border);
  transition: transform var(--motion-base) var(--ease-standard);
}
.switch input:checked {
  background: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.switch input:checked::after {
  transform: translateX(14px);
}
textarea.field {
  border-radius: var(--radius-md);
  padding: var(--space-4);
  resize: none;
  line-height: var(--leading-body);
}
textarea.field:focus {
  box-shadow: var(--focus-ring);
}

/* --- character plate — a printed seal, not a portrait -------------------- */
.plate {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border: var(--hair);
  border-radius: var(--radius-md);
  background: var(--tag-bg-faint);
  display: grid;
  place-items: center;
  container-type: inline-size;
}
.plate::after {
  content: "";
  position: absolute;
  inset: 9px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--tag-bg-base);
  pointer-events: none;
}
.plate-sigil {
  position: absolute;
  width: 70%;
  height: 70%;
  color: var(--accent);
  opacity: 0.16;
  z-index: 0;
}
.plate-mark {
  position: relative;
  z-index: 1;
  writing-mode: vertical-rl;
  text-orientation: upright;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(32px, 25cqw, 58px);
  letter-spacing: 0.1em;
  color: var(--accent);
  line-height: 1;
}
.plate-code {
  position: absolute;
  left: 16px;
  bottom: 14px;
  z-index: 1;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--meta);
}
.plate-size-lg {
  aspect-ratio: 4 / 5;
}
.avatar {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-sm);
  flex: none;
  display: grid;
  place-items: center;
  background: var(--surface);
  border: var(--hair);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-base);
  color: var(--accent);
}
.avatar-sm {
  width: 30px;
  height: 30px;
  font-size: var(--text-sm);
}
.avatar-tint {
  background: var(--tag-bg-faint);
  border-color: var(--tag-bg-base);
}
.av-stack {
  display: flex;
}
.av-stack .avatar {
  margin-left: -9px;
  box-shadow: 0 0 0 2px var(--surface);
}
.av-stack .avatar:first-child {
  margin-left: 0;
}

/* --- media ---------------------------------------------------------------- */
.media {
  position: relative;
  overflow: hidden;
  border: var(--hair);
  border-radius: var(--radius-md);
  background: var(--surface-warm);
}
.media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.media-16-9 {
  aspect-ratio: 16 / 9;
}
.media-3-2 {
  aspect-ratio: 3 / 2;
}
.media-4-3 {
  aspect-ratio: 4 / 3;
}
.media-banner {
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
}
@media (max-width: 620px) {
  .media-banner {
    aspect-ratio: 4 / 3;
  }
}
.overlay-chip {
  position: absolute;
  left: 14px;
  bottom: 14px;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: calc(100% - 28px);
  padding: 7px 12px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  border: var(--hair);
  box-shadow: var(--elev-raised);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--fg);
}
.overlay-chip .label {
  color: var(--meta);
  letter-spacing: var(--tracking-label);
}

/* --- conversation — set as a printed script, never as chat bubbles -------
   One voice, one colour. Your voice is ink (accent text + a mouth-rule), the
   cast is near-black, the room's stage directions are olive behind a
   hairline. Nothing reverses or floats: every turn shares the same 30px seal
   gutter and the same cue line, the way a screenplay does. No bubble, no
   box, no second surface — the script sits directly on parchment.
   ------------------------------------------------------------------------ */
.thread {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}
.turn {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: var(--space-4);
  align-items: start;
}
/* Consecutive lines from the same speaker drop the repeated seal and keep
   the gutter, so a run of dialogue reads as one voice talking. */
.turn.turn-cont .turn-avatar {
  visibility: hidden;
}
.turn-body {
  min-width: 0;
}
/* Cue line: NAME ————————————— 03:14 */
.turn-head {
  display: grid;
  grid-template-columns: auto minmax(16px, 1fr) auto;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.cue-rule {
  height: 1px;
  background: var(--border);
}
.speaker {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--fg-2);
}
.turn-user .speaker {
  color: var(--accent);
}
.turn-head .label {
  color: var(--meta);
  letter-spacing: var(--tracking-label);
  white-space: nowrap;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Narrow phones: the cue line tightens rather than overflowing its column. */
@media (max-width: 620px) {
  .turn-head {
    gap: var(--space-2);
  }
  .speaker {
    letter-spacing: 0.8px;
  }
  .turn-head .label {
    font-size: var(--text-xs);
    letter-spacing: 0.2px;
  }
}
.speech {
  font-size: var(--text-md);
  line-height: 1.62;
  color: var(--fg);
}
.speech p + p {
  margin-top: var(--space-3);
}
.speech em,
.speech i,
.speech cite {
  font-style: normal;
  color: var(--accent);
}
/* Your line — ink on parchment behind a single 2px mouth-rule. */
.turn-user .speech {
  color: var(--accent);
  border-left: 2px solid var(--accent);
  padding-left: var(--space-4);
}
.narration {
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--muted);
  border-left: 1px solid var(--border);
  padding: 1px 0 1px var(--space-4);
  max-width: 62ch;
}
.narration + .speech {
  margin-top: var(--space-4);
}
.narration p + p {
  margin-top: var(--space-2);
}
.beat {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--meta);
}
.beat::before,
.beat::after {
  content: "";
  height: 1px;
  flex: 1;
  background: var(--border);
}
.typing {
  display: inline-flex;
  gap: 5px;
  align-items: center;
  padding: var(--space-2) 0;
}
.typing span {
  width: 5px;
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--accent);
  opacity: 0.5;
  animation: pulse 1.15s var(--ease-standard) infinite;
}
.typing span:nth-child(2) {
  animation-delay: 0.16s;
}
.typing span:nth-child(3) {
  animation-delay: 0.32s;
}
@keyframes pulse {
  0%,
  100% {
    opacity: 0.25;
    transform: translateY(0);
  }
  50% {
    opacity: 0.95;
    transform: translateY(-2px);
  }
}
.msg-actions {
  display: flex;
  gap: var(--space-1);
  margin-top: var(--space-2);
  margin-left: -7px;
  opacity: 0;
  transition: opacity var(--motion-fast) var(--ease-standard);
}
.turn:hover .msg-actions,
.turn:focus-within .msg-actions {
  opacity: 1;
}
.msg-actions button {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
  color: var(--muted);
  padding: 3px 7px;
  border-radius: var(--radius-xs);
}
.msg-actions button:hover {
  color: var(--accent);
  background: var(--tag-bg-faint);
}
/* Touch: the actions are the only affordance, so they stay visible against a
   44px target instead of waiting for a hover that will never arrive. */
@media (hover: none) {
  .msg-actions {
    opacity: 1;
  }
  .msg-actions button {
    min-height: 44px;
    padding: 10px 12px 10px 0;
    color: var(--fg-2);
  }
}

/* --- composer — one field, one Send, docked to the foot of the room ------ */
.composer {
  background: var(--surface);
  border: var(--hair);
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-raised);
  transition: box-shadow var(--motion-base) var(--ease-standard);
}
.composer:focus-within {
  box-shadow: var(--elev-raised), 0 0 0 1px var(--tag-bg-base);
}
.composer textarea {
  display: block;
  width: 100%;
  border: 0;
  background: none;
  outline: none;
  resize: none;
  padding: var(--space-4) var(--space-4) var(--space-2);
  font-size: var(--text-md);
  line-height: var(--leading-body);
}
.composer textarea::placeholder {
  color: var(--meta);
}
.composer-foot {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3) var(--space-3);
}
.composer-foot .spacer {
  flex: 1;
}
.composer-hint {
  display: none;
  color: var(--meta);
  padding-right: var(--space-2);
}
.composer .btn-primary {
  min-height: 44px;
  padding-inline: var(--space-5);
}
@media (hover: none) {
  .composer .chip {
    min-height: 44px;
    padding-inline: var(--space-4);
  }
}
@media (min-width: 861px) and (hover: hover) {
  .composer textarea {
    padding-inline: var(--space-5);
  }
  .composer-foot {
    padding: var(--space-3) var(--space-4) var(--space-4);
  }
  .composer-hint {
    display: inline;
  }
}

/* The dock. The page is the transcript — it scrolls as one document — and the
   composer stays stuck to its foot. Sticky keeps its flow space, so there is
   never a second scroll container and never a last line hidden behind it. */
.dock {
  position: sticky;
  bottom: 0;
  z-index: 30;
  margin-top: var(--space-2);
  padding-block: var(--space-3)
    calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
  background: var(--bg);
  border-top: var(--hair);
}
@media (max-width: 860px) {
  /* In a room the bottom edge belongs to the composer, not the studio rail. */
  body.is-room {
    padding-bottom: 0;
  }
  body.is-room .rail {
    display: none;
  }
  .dock {
    margin-inline: calc(var(--container-gutter-phone) * -1);
    padding-inline: var(--container-gutter-phone);
  }
  .dock .composer {
    border-radius: var(--radius-md);
  }
}

/* --- panels --------------------------------------------------------------- */
.panel {
  padding: var(--space-5);
}
.panel + .panel {
  margin-top: var(--space-5);
}
.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.kv {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: var(--space-2) var(--space-4);
  font-size: var(--text-base);
}
.kv dt {
  color: var(--meta);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  padding-top: 2px;
}
.kv dd {
  margin: 0;
  color: var(--fg-2);
}
.meter {
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--surface-warm);
  border: var(--hair-soft);
  overflow: hidden;
}
.meter span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--accent);
}
.list-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-sm);
  width: 100%;
  text-align: left;
  transition:
    background var(--motion-fast) var(--ease-standard),
    color var(--motion-fast) var(--ease-standard);
}
.list-row:hover {
  background: var(--surface);
}
.list-row[aria-current="true"] {
  background: var(--surface);
  box-shadow: inset 2px 0 0 var(--accent);
}
.list-row .label {
  letter-spacing: var(--tracking-label);
}
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.clamp-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --- layout helpers ------------------------------------------------------- */
.cols {
  display: grid;
  gap: var(--space-8);
  align-items: start;
}
.cols-main {
  grid-template-columns: minmax(0, 1fr) 288px;
}
.cols-chat {
  grid-template-columns: 212px minmax(0, 1fr) 252px;
}
.cols-story {
  grid-template-columns: 204px minmax(0, 1fr) 248px;
}
.cols-launch {
  grid-template-columns: minmax(0, 1fr);
}
/* The two reference columns sit in a wrapper so a phone can hoist BOTH of them
   into one sheet. On wide screens the wrapper dissolves (display: contents)
   and the asides are ordinary grid columns again. */
.cols-chat .room-side,
.cols-story .room-side {
  display: contents;
}
/* Placement is explicit and scoped to the room grids: with display: contents
   the asides are hoisted here, so auto-placement would order them wrong. */
.cols-chat .col-left,
.cols-story .col-left {
  grid-column: 1;
  grid-row: 1;
}
.cols-chat .col-center,
.cols-story .col-center {
  grid-column: 2;
  grid-row: 1;
}
.cols-chat .col-right,
.cols-story .col-right {
  grid-column: 3;
  grid-row: 1;
}
.drawer-head,
.drawer-scrim {
  display: none;
}
@media (max-width: 1400px) {
  .cols-chat {
    grid-template-columns: 206px minmax(0, 1fr);
  }
  .cols-story {
    grid-template-columns: 198px minmax(0, 1fr);
  }
  .cols-chat .col-right,
  .cols-story .col-right {
    grid-column: 2;
    grid-row: 2;
  }
  .cols-chat .col-right.sticky-col,
  .cols-story .col-right.sticky-col {
    position: static;
  }
}
@media (max-width: 1080px) {
  .cols-main {
    grid-template-columns: minmax(0, 1fr);
  }
  .cols-chat,
  .cols-story {
    grid-template-columns: minmax(0, 1fr);
  }
  .cols-chat .col-left,
  .cols-story .col-left,
  .cols-chat .col-right,
  .cols-story .col-right {
    grid-column: 1;
    grid-row: auto;
  }
  .cols-chat .col-center,
  .cols-story .col-center {
    grid-column: 1;
    grid-row: 1;
  }
  /* Record + memory become one full-height sheet, opened from the room head. */
  .cols-chat .room-side,
  .cols-story .room-side {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 60;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-3) var(--container-gutter-phone) var(--space-12);
    background: var(--bg);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity var(--motion-base) var(--ease-standard),
      visibility var(--motion-base) var(--ease-standard);
  }
  .cols-chat .room-side.drawer-open,
  .cols-story .room-side.drawer-open {
    opacity: 1;
    visibility: visible;
  }
  .cols-chat .room-side .col-left,
  .cols-chat .room-side .col-right,
  .cols-chat .room-side .sticky-col,
  .cols-story .room-side .col-left,
  .cols-story .room-side .col-right,
  .cols-story .room-side .sticky-col {
    position: static;
    margin-top: var(--space-5);
  }
  .drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    position: sticky;
    top: calc(var(--space-3) * -1);
    z-index: 2;
    margin: calc(var(--space-3) * -1)
      calc(var(--container-gutter-phone) * -1) 0;
    padding: var(--space-3) var(--container-gutter-phone);
    background: var(--bg);
    border-bottom: var(--hair);
  }
  .drawer-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: var(--surface-warm);
    border: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-base) var(--ease-standard);
  }
  .cols-chat .room-side.drawer-open ~ .drawer-scrim,
  .cols-story .room-side.drawer-open ~ .drawer-scrim {
    opacity: 0.94;
    pointer-events: auto;
  }
}
.sticky-col {
  position: sticky;
  top: 84px;
}
.page-head {
  padding-block: var(--space-8) var(--space-6);
}
.section {
  padding-block: var(--space-8);
}
.section + .section {
  border-top: var(--hair);
}
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 10px 14px;
  background: var(--surface);
  border: var(--hair);
  border-radius: var(--radius-md);
  z-index: 100;
}
.skip:focus {
  left: var(--space-4);
  top: var(--space-4);
}

/* --- overview / spec page ------------------------------------------------- */
.cover {
  position: relative;
  border: var(--hair);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 16 / 9;
}
.cover-plate {
  position: absolute;
  inset: auto var(--space-6) var(--space-6) var(--space-6);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-md);
  background: var(--surface);
  border: var(--hair);
  box-shadow: var(--elev-raised);
}
@media (max-width: 720px) {
  .cover-plate {
    position: static;
    margin: 0;
    border: 0;
    border-top: var(--hair);
    border-radius: 0;
    box-shadow: none;
    padding: var(--space-5) var(--space-5) 0;
  }
  .cover img {
    aspect-ratio: 4 / 3;
  }
}
.screen-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.screen-card .media {
  box-shadow: none;
}
.thumb-ui {
  aspect-ratio: 16 / 10;
  border: var(--hair);
  border-radius: var(--radius-md);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: var(--space-4);
  overflow: hidden;
}
.thumb-ui i {
  display: block;
  height: 5px;
  border-radius: var(--radius-pill);
  background: var(--border);
}
.thumb-ui i.short {
  width: 46%;
}
.thumb-ui i.mid {
  width: 72%;
}
.thumb-ui i.acc {
  background: var(--tag-bg-base);
  width: 34%;
}
.tok {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-top: var(--hair);
}
.tok .hex {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--meta);
  letter-spacing: 0.04em;
}
/* The token table prints both values of every pair, so the number beside a
   swatch is always the value that swatch is actually showing. */
.hex-ink {
  display: none;
}
:root[data-theme="ink"] .hex-paper {
  display: none;
}
:root[data-theme="ink"] .hex-ink {
  display: inline;
}
.swatch {
  width: 46px;
  height: 46px;
  border-radius: var(--radius-sm);
  border: var(--hair);
  flex: none;
}
.footer {
  border-top: var(--hair);
  padding-block: var(--space-8) var(--space-12);
  margin-top: var(--space-12);
}

/* --- resume list (chats.html) --------------------------------------------- */
.session {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr) auto;
  gap: var(--space-5);
  align-items: center;
}
.session-media {
  aspect-ratio: 4 / 3;
}
@media (max-width: 720px) {
  .session {
    grid-template-columns: minmax(0, 1fr);
  }
  .session-media {
    aspect-ratio: 16 / 9;
  }
}

/* --- room chrome ----------------------------------------------------------
   The transcript has no scroller of its own any more: a room is one document,
   the page owns the scroll, and the composer is docked (see .dock).
   ------------------------------------------------------------------------ */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.room-head {
  padding-block: var(--space-6) var(--space-5);
}
.room-head-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
@media (max-width: 620px) {
  .room-head {
    padding-block: var(--space-4) var(--space-3);
  }
  .room-head h1 {
    font-size: var(--text-xl);
    letter-spacing: 0;
  }
  .room-head .avatar {
    width: 32px;
    height: 32px;
    font-size: var(--text-sm);
  }
}
.meter-block {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 6px var(--space-4);
  align-items: center;
}
.meter-block .meter {
  grid-column: 1 / -1;
}

/* --- character seal picker ----------------------------------------------- */
.seal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(68px, 1fr));
  gap: var(--space-3);
}
.seal {
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  border: var(--hair);
  border-radius: var(--radius-sm);
  background: var(--tag-bg-faint);
  color: var(--accent);
  transition:
    background var(--motion-fast) var(--ease-standard),
    box-shadow var(--motion-base) var(--ease-standard);
}
.seal svg {
  width: 62%;
  height: 62%;
  opacity: 0.5;
}
.seal:hover {
  box-shadow: var(--elev-raised);
}
.seal[aria-pressed="true"] {
  background: var(--tag-bg-soft);
  box-shadow: 0 0 0 1px var(--accent);
}
.seal[aria-pressed="true"] svg {
  opacity: 1;
}

/* --- forms ---------------------------------------------------------------- */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5) var(--space-6);
}
@media (max-width: 720px) {
  .form-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
.field-block {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
}
.field-block > .label {
  color: var(--meta);
}
.field-note {
  font-size: var(--text-sm);
  line-height: 1.45;
  color: var(--meta);
}
.field-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding-block: var(--space-3);
  border-top: var(--hair-soft);
}
.field-row:first-of-type {
  border-top: 0;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}
