.brand {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  text-decoration: none;
}

.brand-wordmark {
  height: 42px;
  width: auto;
  display: block;
}

.rail-brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  margin-block-start: 4px;
  margin-block-end: 10px;
  /* Align the wordmark with the home greeting without pulling the version switch upward in flow. */
  transform: translateY(-10px);
  color: var(--rk-ink);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}

.rail-brand img {
  flex: none;
  height: 26px;
  width: auto;
}

.rail-brand-version {
  flex: none;
  align-self: flex-start;
  margin-block-start: 1px;
  color: var(--rk-emerald);
  font-size: 0.75rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
}

.rail-nav {
  display: flex;
  flex-direction: column;
  gap: 22px;
  inline-size: 100%;
  align-items: center;
  margin-block-start: 8px;
}

/* Identity-gated slot for the Help & feedback rail entry. `display: contents` keeps the button a
   direct flex child of .rail-nav, so it inherits both the desktop column and the ≤680px bottom-bar
   layout without a single extra rule. */
.rail-slot {
  display: contents;
}

.rail-item {
  width: 86px;
  min-height: 72px;
  border: 0;
  border-radius: var(--rk-radius-sm);
  background: transparent;
  color: var(--rk-ink);
  text-decoration: none;
  display: grid;
  place-items: center;
  gap: 6px;
  padding-block: 9px;
  transition: background 180ms ease-out, color 180ms ease-out;
}

.rail-item svg {
  width: 27px;
  height: 27px;
  stroke-width: 1.65;
}

.rail-item span {
  font-size: 0.9rem;
  font-weight: 700;
}

.rail-item .rail-classic-copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  line-height: 1.18;
}

.rail-item .rail-classic-brand {
  font-size: 0.82rem;
}

.rail-item .rail-classic-edition {
  font-size: 0.68rem;
  white-space: nowrap;
}

.rail-item.is-active {
  color: var(--rk-emerald);
  background: var(--rk-rail-active-bg);
}

.rail-settings {
  margin-block-start: auto;
}

.search {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 50px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.55);
  color: var(--rk-ink-soft);
  padding-inline: 18px;
}

.search svg {
  width: 20px;
  height: 20px;
}

.search input {
  min-width: 0;
  width: 100%;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--rk-ink);
  font-size: 1rem;
}

.search input::placeholder {
  color: var(--rk-ink-muted);
}

.rk-top-actions {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 14px;
}

.rk-rail-classic-switch-slot {
  inline-size: 100%;
  display: flex;
  justify-content: center;
  margin-block-end: 12px;
}

.rk-rail-classic-switch-slot:empty {
  display: none;
}

.rk-classic-switch {
  min-block-size: 30px;
  max-inline-size: 140px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  padding-inline: 4px;
  border: 1px solid var(--rk-emerald);
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  box-shadow: none;
  transition: border-color 160ms ease-out, color 160ms ease-out, background 160ms ease-out, box-shadow 160ms ease-out;
}

.rk-classic-switch .rk-switch-track {
  border-color: color-mix(in srgb, var(--rk-surface) 70%, transparent);
  background: color-mix(in srgb, var(--rk-surface) 22%, transparent);
}

.rk-classic-switch .rk-switch {
  inline-size: 30px;
  block-size: 18px;
}

.rk-classic-switch .rk-switch-knob {
  inset-block-start: 3px;
  inline-size: 12px;
  block-size: 12px;
}

.rk-classic-switch .rk-switch input:checked + .rk-switch-track .rk-switch-knob {
  transform: translateX(14px);
}

[dir="rtl"] .rk-classic-switch .rk-switch input:checked + .rk-switch-track .rk-switch-knob {
  transform: translateX(-14px);
}

.rk-classic-switch-label {
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.7rem;
}

.rk-classic-switch:hover {
  border-color: var(--rk-emerald-hover);
  background: var(--rk-emerald-hover);
  color: var(--rk-surface);
  box-shadow: 0 7px 16px -10px color-mix(in srgb, var(--rk-ink) 62%, transparent);
}

.rk-classic-switch:has(.rk-switch input:focus-visible) {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .rk-classic-switch, .rk-classic-switch .rk-switch-knob { transition: none; }
}

.balance-chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
  padding-inline: 16px;
  font-weight: 800;
  white-space: nowrap;
}

.balance-chip svg {
  width: 22px;
  height: 22px;
  stroke-width: 1.55;
}

/* New-user Trial countdown pill (topbar). Quiet chrome: hairline pill + emerald dot, ink text. */
.rk-trial-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
  padding-inline: 16px;
  font-weight: 800;
  white-space: nowrap;
  color: var(--rk-ink);
  cursor: pointer;
}
.rk-trial-badge:hover {
  border-color: var(--rk-emerald);
}
.rk-trial-dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--rk-emerald);
  flex: none;
}

/* What's New (运营 ⑦) — announcement popup + 更新日志 cards (v3 paper skin). */
.rk-whatsnew { display: flex; flex-direction: column; gap: 14px; }
.rk-whatsnew-kicker {
  font-size: 0.74rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--rk-emerald);
}
.rk-whatsnew-list { display: flex; flex-direction: column; gap: 20px; }
.rk-whatsnew-card { display: flex; flex-direction: column; gap: 8px; }
.rk-whatsnew-img {
  width: 100%; max-height: 220px; object-fit: cover;
  border-radius: var(--rk-radius); border: 1px solid var(--rk-line);
}
.rk-whatsnew-meta { display: flex; align-items: center; gap: 10px; }
.rk-whatsnew-ver {
  font-size: 0.72rem; font-weight: 800; color: var(--rk-emerald);
  background: var(--rk-emerald-soft); padding: 2px 9px; border-radius: 999px;
}
.rk-whatsnew-date { font-size: 0.8rem; color: var(--rk-ink-muted); }
.rk-whatsnew-title { margin: 0; font-size: 1.15rem; font-weight: 800; color: var(--rk-ink); }
.rk-whatsnew-body { margin: 0; color: var(--rk-ink-soft); line-height: 1.5; }
.rk-whatsnew-body > p:first-child { margin-block-start: 0; }
.rk-whatsnew-body > p:last-child { margin-block-end: 0; }
/* Announcement layouts (bullets / media / text) come from ONE server-side renderer and land on two
   reader surfaces: the first-login pop-up and the message-centre detail. Both are styled from the
   same block on purpose — an announcement that looks like a button in one place and a bare link in
   the other is the same drift the single renderer exists to prevent. */
.rk-whatsnew-body .rk-ann-list,
.rk-notify-detail-body .rk-ann-list {
  margin-block: 8px 18px;
  padding-inline-start: 1.35rem;
}
.rk-whatsnew-body .rk-ann-list li,
.rk-notify-detail-body .rk-ann-list li { margin-block: 5px; }
.rk-whatsnew-body .rk-ann-section-title,
.rk-notify-detail-body .rk-ann-section-title {
  margin: 22px 0 8px;
  font-size: 1rem;
  line-height: 1.35;
  font-weight: 800;
  color: var(--rk-ink);
}
.rk-whatsnew-body .rk-ann-media,
.rk-notify-detail-body .rk-ann-media { margin: 0 0 8px; }
/* The cover picture, shown whole (Kim, 2026-08-16).
   It used to be a cropped 220px strip, on the theory that a cover is a decorative banner. But the
   auto-layout promotes the FIRST LANDSCAPE image to cover, and what ops actually paste is a product
   screenshot — which is landscape, and which a centre-crop reduces to a meaningless middle band
   (reported with a full-page screenshot whose headline and artwork were both cut away). Same rule as
   a body picture now: its own proportions, a ceiling on height, nothing cut. */
.rk-whatsnew-body .rk-ann-media img,
.rk-notify-detail-body .rk-ann-media img {
  display: block;
  /* Fills the width (Kim, 2026-08-16). Capping the HEIGHT first made a wide screenshot occupy a
     third of the dialog with empty paper either side — on a laptop under 820px tall the ceiling was
     ~180px, so a 1600×850 screenshot came out 310px wide. The ceiling now only exists to stop a
     PORTRAIT picture from running off the screen; landscape ones never reach it. */
  inline-size: 100%;
  block-size: auto; max-block-size: 68dvh;
  object-fit: contain;
  margin-inline: auto;
  border-radius: var(--rk-radius); border: 1px solid var(--rk-line);
}
/* An image the reader's allow-list refused leaves its wrapper behind; an empty box with a border
   reads as "something failed here", so collapse it instead. */
.rk-whatsnew-body .rk-ann-media:empty,
.rk-notify-detail-body .rk-ann-media:empty,
.rk-whatsnew-body .rk-ann-figure:empty,
.rk-notify-detail-body .rk-ann-figure:empty { display: none; }
/* A picture INSIDE the body (free-arrangement announcements): shown whole, never cropped. Ops puts
   product screenshots here and half a screenshot says nothing — which is why this is a separate
   class from the header banner above rather than a variant of it. */
.rk-whatsnew-body .rk-ann-figure,
.rk-notify-detail-body .rk-ann-figure { margin: 10px 0; }
.rk-whatsnew-body .rk-ann-figure img,
.rk-notify-detail-body .rk-ann-figure img {
  display: block; width: 100%; height: auto;
  border-radius: var(--rk-radius); border: 1px solid var(--rk-line);
}
/* Grouped highlights (Kim's design 2026-08-11): the cards that answer "what changed" at a glance.

   ONE ROW, however many groups there are — two groups become two halves, three become thirds. This
   used to be `repeat(auto-fit, minmax(210px, 1fr))`, which asks the browser to work out how many
   columns fit: it gave three columns here and a single stacked column on Kim's screen, because that
   arithmetic depends on the exact available width and there are only ever two or three cards to
   place. A layout with three items does not need to be discovered; it needs to be stated. */
.rk-whatsnew-body .rk-ann-groups,
.rk-notify-detail-body .rk-ann-groups {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 1px;
  margin-block: 14px 4px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-line); /* shows through the 1px gap as the divider between cards */
  overflow: hidden;
}

/* Below this there is no room for columns of prose, so they stack — the one case where a single
   column is the right answer rather than an accident. */
@media (max-width: 720px) {
  .rk-whatsnew-body .rk-ann-groups,
  .rk-notify-detail-body .rk-ann-groups {
    grid-auto-flow: row;
    grid-auto-columns: auto;
  }
}

.rk-whatsnew-body .rk-ann-group,
.rk-notify-detail-body .rk-ann-group {
  padding: 14px 16px 16px;
  background: var(--rk-surface);
}

.rk-whatsnew-body .rk-ann-group-head,
.rk-notify-detail-body .rk-ann-group-head {
  margin: 0 0 10px;
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 800;
  font-size: 0.95rem;
  color: var(--rk-ink);
}

/* The icon is drawn here, never supplied by the announcement — see sanitize-html.js. A tone the
   stylesheet does not know simply gets no icon, which is a missing glyph rather than a broken card. */
.rk-whatsnew-body .rk-ann-group-head::before,
.rk-notify-detail-body .rk-ann-group-head::before {
  content: '';
  inline-size: 18px;
  block-size: 18px;
  flex: 0 0 18px;
  background: currentColor;
  -webkit-mask: var(--rk-ann-tone-icon, none) center / 18px 18px no-repeat;
  mask: var(--rk-ann-tone-icon, none) center / 18px 18px no-repeat;
}

.rk-whatsnew-body .rk-ann-group.is-new .rk-ann-group-head,
.rk-notify-detail-body .rk-ann-group.is-new .rk-ann-group-head {
  color: var(--rk-emerald);
  --rk-ann-tone-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9z'/%3E%3C/svg%3E");
}

.rk-whatsnew-body .rk-ann-group.is-improved .rk-ann-group-head,
.rk-notify-detail-body .rk-ann-group.is-improved .rk-ann-group-head {
  color: var(--rk-emerald);
  --rk-ann-tone-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 4l7 7h-4v9h-6v-9H5z'/%3E%3C/svg%3E");
}

.rk-whatsnew-body .rk-ann-group.is-fixed .rk-ann-group-head,
.rk-notify-detail-body .rk-ann-group.is-fixed .rk-ann-group-head {
  color: var(--rk-emerald);
  --rk-ann-tone-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 100 20 10 10 0 000-20zm-1.2 14.4l-4.2-4.2 1.7-1.7 2.5 2.5 5.9-5.9 1.7 1.7z'/%3E%3C/svg%3E");
}

.rk-whatsnew-body .rk-ann-group-items,
.rk-notify-detail-body .rk-ann-group-items {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 12px;
}

.rk-whatsnew-body .rk-ann-item,
.rk-notify-detail-body .rk-ann-item {
  display: grid;
  gap: 2px;
  padding-inline-start: 22px;
  position: relative;
  font-size: 0.9rem;
}

.rk-whatsnew-body .rk-ann-item::before,
.rk-notify-detail-body .rk-ann-item::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 3px;
  inline-size: 14px;
  block-size: 14px;
  background: var(--rk-emerald);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2L4.8 12l1.7-1.7L9 12.8l8.5-8.5 1.7 1.7z'/%3E%3C/svg%3E") center / 14px 14px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2L4.8 12l1.7-1.7L9 12.8l8.5-8.5 1.7 1.7z'/%3E%3C/svg%3E") center / 14px 14px no-repeat;
}

.rk-whatsnew-body .rk-ann-item-title,
.rk-notify-detail-body .rk-ann-item-title { font-weight: 700; color: var(--rk-ink); }

.rk-whatsnew-body .rk-ann-item-desc,
.rk-notify-detail-body .rk-ann-item-desc { color: var(--rk-ink-muted); line-height: 1.45; }

/* Nothing folds here any more (Kim, 2026-08-16). The dialog used to show two entries per group and
   offer "see all N"; the update-log list reused the same stylesheet without ever having that button,
   so entries past the second were unreachable there. The renderer stopped marking them, and these
   rules went with it — an announcement now shows everything it says, on every surface. */

.rk-whatsnew-body .rk-ann-cta-row,
.rk-notify-detail-body .rk-ann-cta-row { margin-block: 4px 0; }
.rk-whatsnew-cta,
.rk-whatsnew-body .rk-ann-cta,
.rk-notify-detail-body .rk-ann-cta {
  display: inline-flex; align-items: center; justify-content: center;
  align-self: flex-start; margin-top: 4px; padding: 8px 18px; border-radius: 999px;
  background: var(--rk-emerald); color: #fff; font-weight: 700; text-decoration: none;
}
.rk-whatsnew-cta:hover,
.rk-whatsnew-body .rk-ann-cta:hover,
.rk-notify-detail-body .rk-ann-cta:hover { background: var(--rk-emerald-hover); }
/* ── The first-login announcement dialog (Kim's design, 2026-08-11) ──────────────────────────────
   Shaped differently from the archive card on purpose: this one interrupts, so it leads with the
   headline, shows one picture, then the highlights, and keeps the two ways out pinned at the end. */
.rk-whatsnew-pop {
  display: flex;
  flex-direction: column;
  min-block-size: 0;
  block-size: 100%;
}
.rk-whatsnew-kicker-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-block-end: 10px;
}
.rk-whatsnew-badge {
  font-size: 0.7rem; font-weight: 800; letter-spacing: .06em;
  color: var(--rk-emerald); background: var(--rk-emerald-soft);
  padding: 4px 10px; border-radius: 999px;
}
.rk-whatsnew-kicker-ver {
  font-size: 0.72rem; font-weight: 700; letter-spacing: .08em;
  color: var(--rk-ink-muted); text-transform: uppercase;
}
.rk-whatsnew-headline {
  margin: 0; font-size: 1.72rem; line-height: 1.25; font-weight: 800; color: var(--rk-ink);
}
.rk-whatsnew-lead { margin: 8px 0 16px; color: var(--rk-ink-soft); line-height: 1.45; }
.rk-whatsnew-pop .rk-whatsnew-date { margin: 6px 0 0; }
.rk-whatsnew-pop .rk-whatsnew-date + .rk-ann-figure,
.rk-whatsnew-pop .rk-whatsnew-date + .rk-whatsnew-body { margin-block-start: 16px; }
/* The frame follows the picture, never the other way round (Kim, 2026-08-16).
   This used to be a fixed 5:2 letterbox. Ops paste product screenshots, and a screenshot has the
   proportions it has: a 5:1 banner sat in a half-empty box, and anything taller than 5:2 was either
   shrunk into the middle of one or cropped by it. Only the HEIGHT is capped now — so a tall image
   scales down and stays whole instead of losing its bottom, and the dialog never gets pushed off
   screen by one picture. */
.rk-whatsnew-pop .rk-ann-figure {
  flex: none;
  min-block-size: 0;
  display: flex;
  justify-content: center;
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
}
.rk-whatsnew-pop .rk-ann-figure img {
  display: block;
  inline-size: 100%;
  block-size: auto;
  max-block-size: 68dvh;
  object-fit: contain;
}
.rk-whatsnew-pop .rk-whatsnew-body {
  min-block-size: 0;
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
}

/* ~~图片吃剩下的空间~~ → **[REVISE 2026-08-16 · Kim 拍板改回]**
   曾让图片按剩余高度收缩，好让亮点永远在第一屏。Kim 看过实际观感后否掉：公告本来就是**文字在前、
   图在后**，图排在正文下方根本挡不住文字，而为了这个假想的冲突去压图，代价是每张图都被缩小一圈。
   图片回到「填满宽度 + 保持原比例 + 一个宽松的高度上限」，正文长了就让正文自己滚。 */
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-groups {
  gap: 8px;
  margin-block: 10px 0;
  padding: 8px;
  border-color: color-mix(in srgb, var(--rk-line) 72%, transparent);
  border-radius: calc(var(--rk-radius) + 2px);
  background: color-mix(in srgb, var(--rk-paper) 82%, var(--rk-surface));
  overflow: visible;
}
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group {
  padding: 12px 14px 14px;
  border: 1px solid color-mix(in srgb, var(--rk-line) 68%, transparent);
  border-radius: calc(var(--rk-radius-sm) + 2px);
  background: color-mix(in srgb, var(--rk-surface) 90%, var(--rk-paper));
  box-shadow: 0 1px 2px color-mix(in srgb, var(--rk-ink) 5%, transparent);
}
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group-head {
  margin-block-end: 10px;
  gap: 6px;
  font-size: 0.82rem;
  line-height: 1.35;
}
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group-head::before {
  inline-size: 16px;
  block-size: 16px;
  flex-basis: 16px;
  -webkit-mask-size: 16px 16px;
  mask-size: 16px 16px;
}
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group-items { gap: 9px; }
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-item {
  gap: 2px;
  padding-inline-start: 18px;
  font-size: 0.76rem;
  line-height: 1.4;
}
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-item::before {
  inset-block-start: 3px;
  inline-size: 12px;
  block-size: 12px;
  -webkit-mask-size: 12px 12px;
  mask-size: 12px 12px;
}
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-item-title { font-weight: 680; }
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-item-desc {
  color: color-mix(in srgb, var(--rk-ink-muted) 86%, transparent);
  line-height: 1.4;
}
.rk-whatsnew-actions {
  display: flex; align-items: center; justify-content: center; gap: 18px;
  margin-block-start: auto; padding-block-start: 18px;
}
.rk-whatsnew-primary {
  display: inline-flex; align-items: center; justify-content: center;
  min-inline-size: 230px; min-block-size: 42px; padding: 10px 26px; border-radius: 999px;
  background: var(--rk-emerald); color: #fff; font-weight: 700; text-decoration: none;
}
.rk-whatsnew-primary:hover { background: var(--rk-emerald-hover); }
.rk-whatsnew-actions .rk-whatsnew-dismiss {
  align-self: auto; min-block-size: 42px; margin: 0; padding: 10px 22px;
  border: 1px solid var(--rk-line); background: var(--rk-surface);
  color: var(--rk-ink-soft); font-weight: 650;
}
.rk-whatsnew-actions .rk-whatsnew-dismiss:hover {
  border-color: var(--rk-emerald); color: var(--rk-ink);
}

/* Laptop-height compaction keeps the whole announcement operable without changing its hierarchy. */
@media (min-width: 721px) and (max-height: 820px) {
  .rk-modal-panel.is-announce { padding: 26px 42px 18px; }
  .rk-whatsnew-kicker-row { margin-block-end: 7px; }
  .rk-whatsnew-headline { font-size: 1.55rem; line-height: 1.18; }
  .rk-whatsnew-lead { margin-block: 5px 10px; line-height: 1.35; }
  .rk-whatsnew-pop .rk-whatsnew-date { margin-block: 4px 0; }
  .rk-whatsnew-pop .rk-whatsnew-date + .rk-ann-figure,
  .rk-whatsnew-pop .rk-whatsnew-date + .rk-whatsnew-body { margin-block-start: 10px; }
  /* Short laptops: the picture still fills the width; the ceiling only keeps a PORTRAIT one from
     taking the whole dialog. Squeezing the height here is what made a wide screenshot render at a
     third of the width (Kim, 2026-08-16) — the body scrolls, so height is the cheap dimension. */
  .rk-whatsnew-pop .rk-ann-figure img,
  .rk-whatsnew-pop .rk-ann-media img { max-block-size: 68dvh; }
  .rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group { padding: 10px 12px 11px; }
  .rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group-head { margin-block-end: 7px; }
  .rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group-items { gap: 8px; }
  .rk-whatsnew-actions { padding-block-start: 12px; }
}

@media (min-width: 721px) and (max-height: 740px) {
  .rk-modal-panel.is-announce { padding: 20px 38px 14px; }
  .rk-whatsnew-pop .rk-ann-figure img,
  .rk-whatsnew-pop .rk-ann-media img { max-block-size: 68dvh; }
  .rk-whatsnew-pop .rk-whatsnew-body .rk-ann-group { padding-block: 8px 9px; }
  .rk-whatsnew-pop .rk-whatsnew-body .rk-ann-item-desc { line-height: 1.3; }
  .rk-whatsnew-actions { padding-block-start: 8px; }
}

@media (max-width: 560px) {
  .rk-whatsnew-headline { font-size: 1.32rem; }
  .rk-whatsnew-actions { flex-direction: column-reverse; gap: 6px; }
  .rk-whatsnew-primary { inline-size: 100%; }
}

.rk-whatsnew-dismiss {
  align-self: center; margin-top: 6px; padding: 9px 26px; border-radius: 999px;
  border: 1px solid var(--rk-line); background: var(--rk-surface); color: var(--rk-ink);
  font-weight: 700; cursor: pointer;
}
.rk-whatsnew-dismiss:hover { border-color: var(--rk-emerald); }
.rk-whatsnew-empty { color: var(--rk-ink-muted); text-align: center; padding: 20px; }

/* 身份选择 (运营 ⑤) — onboarding + editor cards (v3 paper skin). */
.rk-identity { display: flex; flex-direction: column; gap: 8px; }
.rk-identity-welcome {
  position: relative;
  min-block-size: 126px;
  margin: -10px -10px 14px;
  padding: 24px 152px 24px 26px;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 18%, var(--rk-line));
  border-radius: calc(var(--rk-radius-lg) - 4px);
  background:
    radial-gradient(circle at 88% 20%, rgba(255, 255, 255, 0.9), transparent 34%),
    linear-gradient(135deg, color-mix(in srgb, var(--rk-emerald-soft) 76%, #fff), var(--rk-paper-2));
}
.rk-identity-welcome-copy { position: relative; z-index: 1; }
.rk-identity-welcome-title {
  margin: 0 0 8px;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: clamp(1.65rem, 2.7vw, 2.1rem);
  line-height: 1.08;
}
.rk-identity-welcome-sub {
  max-inline-size: 420px;
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.94rem;
  line-height: 1.5;
}
.rk-identity-welcome-art {
  position: absolute;
  inset-inline-end: 16px;
  inset-block-end: -30px;
  inline-size: 132px;
  block-size: auto;
  filter: drop-shadow(0 10px 16px rgba(43, 42, 38, 0.12));
}
.rk-identity-kicker {
  font-size: 0.74rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--rk-emerald);
}
.rk-identity-title { margin: 0; font-size: 1.3rem; font-weight: 800; color: var(--rk-ink); }
.rk-identity-sub { margin: 0 0 8px; color: var(--rk-ink-soft); }
.rk-identity-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.rk-identity-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px; text-align: left;
  padding: 14px 16px; border: 1px solid var(--rk-line); border-radius: var(--rk-radius);
  background: var(--rk-surface); cursor: pointer;
  transition: border-color 150ms ease-out, box-shadow 150ms ease-out;
}
.rk-identity-card:hover { border-color: var(--rk-emerald); }
.rk-identity.is-onboarding .rk-identity-card { min-block-size: 82px; transition: transform 150ms ease-out, border-color 150ms ease-out, box-shadow 150ms ease-out; }
.rk-identity.is-onboarding .rk-identity-card:hover { transform: translateY(-1px); box-shadow: 0 8px 20px rgba(43, 42, 38, 0.07); }
.rk-identity-card.is-active { border-color: var(--rk-emerald); background: var(--rk-emerald-soft); }
.rk-identity-label { font-weight: 800; color: var(--rk-ink); }
.rk-identity-desc { font-size: 0.82rem; color: var(--rk-ink-soft); }
.rk-identity-skip {
  align-self: center; margin-top: 8px; padding: 8px 20px; border: none; background: none;
  color: var(--rk-ink-muted); cursor: pointer; text-decoration: underline;
}
/* Step 1 的 Skip 排在五张身份卡下面 —— 窗口一矮 (或页面缩放过) 就掉出可视区,首屏唯一的退出只剩右上角
   的 ×。让它贴住面板底部常驻,否则用户只能直接关标签页,而关标签页这条路以前什么都不落库。 */
.rk-identity.is-onboarding .rk-identity-skip {
  position: sticky; inset-block-end: 0; z-index: 1;
  align-self: stretch; text-align: center;
  margin-block-start: 4px; padding-block: 12px 14px;
  background: linear-gradient(to bottom, transparent, var(--rk-surface) 42%);
}
.rk-onboarding {
  display: flex; flex-direction: column; min-block-size: 0;
}
.rk-onboarding-progress {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin: 0 0 16px; padding-inline-end: 64px; color: var(--rk-ink-muted); font-size: 0.75rem; font-weight: 850;
  letter-spacing: 0.03em;
}
.rk-onboarding-progress-dots { display: flex; align-items: center; gap: 7px; }
.rk-onboarding-progress-dots i {
  display: block; inline-size: 34px; block-size: 5px; border-radius: 999px; background: var(--rk-line);
}
.rk-onboarding-progress-dots i.is-active { background: var(--rk-emerald); }
/* Step 2 的说明块压到最矮 —— 这一步唯一要传达的是「有哪些方向可选」,说明块吃掉三分之一可视高度
   就会把第二行卡片压到看不见标题,用户以为只有三种类型。腾空间只能从说明块拿,不能缩卡片图:
   那些图是这一步的说服力来源 (Bella 2026-07-31)。 */
.rk-onboarding-hero {
  position: relative; min-block-size: 0; margin-block-end: 12px; padding: 15px 180px 15px 20px;
  display: flex; align-items: center; overflow: hidden; border: 1px solid var(--rk-line);
  border-radius: 18px; background: var(--rk-paper-2);
}
.rk-onboarding-hero-copy { position: relative; z-index: 1; min-inline-size: 0; }
.rk-onboarding-hero .rk-identity-title { margin-block-start: 2px; font-size: clamp(1.2rem, 1.9vw, 1.46rem); }
.rk-onboarding-hero .rk-identity-sub {
  max-inline-size: none; margin-block: 4px 0; font-size: 0.86rem; line-height: 1.4;
}
.rk-onboarding-hero-art {
  position: absolute; inset-inline-end: 4px; inset-block-start: 50%; translate: 0 -50%;
  inline-size: 172px; block-size: 100px;
  object-fit: contain; object-position: center center;
}
.rk-onboarding-types {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-block: 0;
}
@media (min-width: 821px) {
  .rk-onboarding-types.is-four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.rk-onboarding-type {
  position: relative; min-inline-size: 0; min-block-size: 0; padding: 8px 8px 14px;
  display: flex; flex-direction: column; align-items: stretch; justify-content: flex-start; gap: 12px;
  border: 1px solid var(--rk-line); border-radius: 18px;
  background: var(--rk-surface);
  color: var(--rk-ink); text-align: start; cursor: pointer;
  transition: transform 150ms ease-out, border-color 150ms ease-out, box-shadow 150ms ease-out;
}
.rk-onboarding-type:hover,
.rk-onboarding-type:focus-visible {
  transform: translateY(-3px); border-color: var(--rk-emerald); box-shadow: var(--rk-shadow-card);
}
.rk-onboarding-type:focus-visible { outline: 3px solid color-mix(in srgb, var(--rk-emerald) 24%, transparent); outline-offset: 2px; }
.rk-onboarding-type-visual {
  position: relative; min-block-size: 0; aspect-ratio: 1; overflow: hidden; border-radius: 14px;
  border: 1px solid var(--rk-line); background: var(--rk-paper-2);
}
.rk-onboarding-type-preview {
  display: block; inline-size: 100%; block-size: 100%; object-fit: cover; object-position: center;
  transition: transform 180ms ease-out;
}
.rk-onboarding-type:hover .rk-onboarding-type-preview,
.rk-onboarding-type:focus-visible .rk-onboarding-type-preview { transform: scale(1.035); }
.rk-onboarding-type-icon {
  position: absolute; inset-inline-start: 9px; inset-block-end: 9px;
  inline-size: 38px; block-size: 38px; display: grid; place-items: center; border-radius: 12px;
  border: 1px solid rgba(226, 218, 206, 0.94); background: rgba(255, 255, 255, 0.94); color: var(--rk-ink-soft);
  box-shadow: 0 6px 16px rgba(43, 42, 38, 0.13);
}
.rk-onboarding-type-icon svg { inline-size: 21px; block-size: 21px; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.rk-onboarding-type-label { max-inline-size: 100%; min-block-size: 1.25em; padding-inline: 8px; font-size: 1.02rem; font-weight: 850; line-height: 1.25; overflow-wrap: anywhere; }
.rk-onboarding-recommended {
  position: absolute; z-index: 1; inset-block-start: 14px; inset-inline-end: 14px; max-inline-size: calc(100% - 28px);
  padding: 4px 8px; border: 1px solid var(--rk-emerald); border-radius: 999px;
  background: rgba(255, 255, 255, 0.94); color: var(--rk-emerald); box-shadow: var(--rk-shadow-card);
  font-size: 0.63rem; font-weight: 850; line-height: 1.2; overflow-wrap: anywhere;
}
.rk-onboarding-result {
  position: relative; min-block-size: 354px; margin-block: 14px 18px; padding: 28px 30px 30px;
  display: block; overflow: hidden;
  border: 1px solid var(--rk-line); border-radius: 24px; background: var(--rk-paper-2);
  box-shadow: var(--rk-shadow-panel);
}
.rk-onboarding-result.has-recommendation {
  border-color: var(--rk-card-hover-border);
}
.rk-onboarding-result-copy { position: relative; z-index: 1; min-inline-size: 0; inline-size: 100%; }
.rk-onboarding-result-mode {
  display: inline-flex; margin-block-end: 18px; padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--rk-line); background: var(--rk-surface); color: var(--rk-emerald); font-size: 0.75rem; font-weight: 850;
}
.rk-onboarding-result-label { display: block; color: var(--rk-emerald); font-size: 0.8rem; font-weight: 850; letter-spacing: 0.05em; text-transform: uppercase; }
.rk-onboarding-result-reason {
  margin: 8px 0 12px; max-inline-size: 620px; color: var(--rk-ink-soft); font-size: 0.9rem; line-height: 1.55;
}
.rk-onboarding-result-story {
  inline-size: calc(100% - 150px); min-block-size: 146px; margin-block-start: 22px; padding: 22px 24px;
  border: 1px solid var(--rk-line); border-radius: 18px; background: rgba(255, 255, 255, 0.76);
  box-shadow: 0 12px 26px -24px rgba(43, 42, 38, 0.55);
}
.rk-onboarding-result-idea {
  margin: 0; max-inline-size: 620px; color: var(--rk-ink); font-family: var(--rk-font-display); font-size: clamp(1.08rem, 2.25vw, 1.28rem); font-weight: 800; line-height: 1.44;
}
.rk-onboarding-result-art-wrap {
  position: absolute; z-index: 2; inset-inline-end: 20px; inset-block-end: 8px; inline-size: 178px; block-size: 218px;
  display: flex; align-items: flex-end; justify-content: center; pointer-events: none;
}
.rk-onboarding-result-art { max-inline-size: 168px; max-block-size: 210px; object-fit: contain; object-position: center bottom; filter: drop-shadow(0 14px 15px rgba(75, 55, 32, 0.15)); }
.rk-onboarding-result-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.rk-onboarding-result-actions .rk-btn-primary,
.rk-onboarding-result-actions .rk-btn-ghost { min-block-size: 48px; padding-inline: 22px; }
.rk-onboarding-footer {
  margin-block-start: 12px; padding-block-start: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
/* 第 2 步内容最高,压完说明块仍会略微溢出。footer 贴住面板底部常驻 —— 同 step 1 的 skip 按钮
   (见上方 .rk-identity.is-onboarding .rk-identity-skip),否则「返回」会掉到可视区外。 */
.rk-onboarding[data-onboarding-step="2"] .rk-onboarding-footer {
  position: sticky; inset-block-end: -16px; z-index: 2;
  margin-block-start: 6px; padding-block: 8px 14px;
  background: linear-gradient(to bottom, transparent, var(--rk-surface) 46%);
}
.rk-onboarding-footer .rk-identity-skip { align-self: auto; margin: 0; }
.rk-onboarding-back {
  border: 0; background: transparent; color: var(--rk-ink-soft); font-weight: 750; cursor: pointer;
}
.rk-onboarding-back:hover { color: var(--rk-emerald); }
.rk-modal-body[aria-busy="true"] .rk-identity { cursor: wait; }
.rk-modal-body[aria-busy="true"] .rk-identity-card,
.rk-modal-body[aria-busy="true"] .rk-identity-skip,
.rk-modal-body[aria-busy="true"] .rk-onboarding-type,
.rk-modal-body[aria-busy="true"] .rk-btn { opacity: 0.62; cursor: wait; }
@media (min-width: 601px) and (max-width: 820px) {
  .rk-onboarding-types { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .rk-onboarding-type { min-block-size: 158px; }
}
/* 两行方形卡片要 945px 以上的视口高度才放得下 —— 低于这个高度,说明块压到最矮也还是溢出,第二行
   标题会被底栏盖住。再要空间只能从卡片自己的留白与画幅比例拿:改画幅不是缩图,图仍占满卡片宽度,
   只是少露一点上下,主体大小不变 (Bella 明确要求别把图改小)。实测两档都留有余量。 */
@media (min-width: 601px) and (max-height: 940px) {
  .rk-onboarding-type { padding: 7px 7px 12px; gap: 10px; }
  .rk-onboarding-type-visual { aspect-ratio: 5 / 4; }
}
/* 笔记本高度 (1366×768 / 1280×800) 再紧一档。 */
@media (min-width: 601px) and (max-height: 850px) {
  .rk-onboarding-hero { margin-block-end: 10px; padding: 11px 150px 11px 18px; }
  .rk-onboarding-hero .rk-identity-title { font-size: 1.24rem; }
  .rk-onboarding-hero .rk-identity-sub { font-size: 0.82rem; }
  .rk-onboarding-hero-art { inline-size: 142px; block-size: 84px; }
  .rk-onboarding-types { gap: 10px; }
  .rk-onboarding-type { padding: 6px 6px 10px; gap: 9px; }
  .rk-onboarding-type-visual { aspect-ratio: 4 / 3; }
  .rk-onboarding-type-label { font-size: 0.95rem; }
}
@media (max-width: 600px) {
  .rk-identity-grid { grid-template-columns: 1fr; gap: 9px; }
  .rk-identity.is-onboarding .rk-identity-card { min-block-size: 0; padding: 12px 14px; }
  .rk-identity-welcome { min-block-size: 112px; margin-inline: -4px; padding: 20px 104px 20px 20px; }
  .rk-identity-welcome-art { inset-inline-end: 6px; inset-block-end: -20px; inline-size: 98px; }
  .rk-identity-welcome-title { font-size: 1.55rem; }
  .rk-identity-welcome-sub { font-size: 0.86rem; }
  .rk-onboarding-progress { margin-block-end: 14px; padding-inline-end: 52px; }
  .rk-onboarding-progress-dots i { inline-size: 20px; }
  .rk-onboarding-hero { min-block-size: 128px; margin-block-end: 14px; padding: 18px 104px 18px 17px; border-radius: 18px; }
  .rk-onboarding-hero .rk-identity-title { font-size: 1.26rem; }
  .rk-onboarding-hero .rk-identity-sub { margin-block-start: 5px; font-size: 0.84rem; line-height: 1.4; }
  .rk-onboarding-hero-art { inset-inline-end: -12px; inset-block-start: 5px; inline-size: 128px; block-size: 118px; object-position: center top; }
  .rk-onboarding-types { grid-template-columns: 1fr 1fr; gap: 9px; }
  .rk-onboarding-type { min-block-size: 150px; padding: 7px 7px 11px; }
  .rk-onboarding-type-visual,
  .rk-onboarding-type-preview { min-block-size: 82px; block-size: 82px; }
  .rk-onboarding-type-icon { inline-size: 36px; block-size: 36px; border-radius: 11px; }
  .rk-onboarding-type-icon svg { inline-size: 20px; block-size: 20px; }
  .rk-onboarding-type-label { font-size: 0.87rem; }
  .rk-onboarding-recommended { inset-block-start: 12px; inset-inline-end: 12px; font-size: 0.58rem; }
  .rk-onboarding-result { min-block-size: 0; padding: 22px 18px 18px; grid-template-columns: minmax(0, 1fr); gap: 12px; border-radius: 20px; }
  .rk-onboarding-result-art-wrap { min-block-size: 88px; justify-content: flex-end; }
  .rk-onboarding-result-art { max-inline-size: 84px; max-block-size: 96px; }
  .rk-onboarding-result-actions { flex-direction: column; }
  .rk-onboarding-result-actions .rk-btn-primary,
  .rk-onboarding-result-actions .rk-btn-ghost { inline-size: 100%; }
}

/* 问卷 (运营 ⑥) — v3 survey modal (list / form / thanks). */
.rk-survey { display: flex; flex-direction: column; gap: 12px; }
.rk-survey-kicker {
  font-size: 0.74rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--rk-emerald);
}
.rk-survey-title { margin: 0; font-size: 1.3rem; font-weight: 800; color: var(--rk-ink); }
.rk-survey-desc { margin: 0; color: var(--rk-ink-soft); }
.rk-survey-list { display: flex; flex-direction: column; gap: 10px; }
.rk-survey-list-item {
  text-align: left; padding: 14px 16px; border: 1px solid var(--rk-line); border-radius: var(--rk-radius);
  background: var(--rk-surface); font-weight: 700; color: var(--rk-ink); cursor: pointer;
}
.rk-survey-list-item:hover { border-color: var(--rk-emerald); }
.rk-survey-form { display: flex; flex-direction: column; gap: 18px; max-height: 55vh; overflow-y: auto; padding-right: 4px; }
.rk-survey-q { display: flex; flex-direction: column; gap: 8px; }
.rk-survey-q-label { font-weight: 700; color: var(--rk-ink); }
.rk-survey-req { color: var(--rk-danger); }
.rk-survey-opts { display: flex; flex-direction: column; gap: 8px; }
.rk-survey-opt { display: flex; align-items: center; gap: 10px; cursor: pointer; color: var(--rk-ink); }
.rk-survey-opt input { accent-color: var(--rk-emerald); width: 18px; height: 18px; flex: none; }
.rk-survey-other, .rk-survey-textarea {
  width: 100%; padding: 8px 10px; border: 1px solid var(--rk-line); border-radius: var(--rk-radius-sm);
  background: var(--rk-surface); color: var(--rk-ink); font: inherit;
}
.rk-survey-other:focus, .rk-survey-textarea:focus { outline: none; border-color: var(--rk-emerald); }
.rk-survey-err { margin: 0; color: var(--rk-danger); font-size: 0.88rem; }
.rk-survey-submit {
  align-self: flex-start; padding: 9px 26px; border-radius: 999px; border: none;
  background: var(--rk-emerald); color: #fff; font-weight: 700; cursor: pointer;
}
.rk-survey-submit:hover { background: var(--rk-emerald-hover); }
.rk-survey-submit:disabled { opacity: 0.6; cursor: default; }
.rk-survey-empty, .rk-survey-done { color: var(--rk-ink-muted); text-align: center; padding: 20px; }
.rk-survey-thanks { align-items: center; text-align: center; }

.avatar {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid var(--rk-line);
  object-fit: cover;
  background: var(--rk-paper-2);
  box-shadow: var(--rk-shadow-card);
}

.avatar.is-mascot {
  object-fit: cover;
  object-position: 50% 50%;
  padding: 0;
  background: var(--rk-paper-2);
  border-color: var(--rk-card-hover-border);
  box-shadow: var(--rk-shadow-card), inset 0 0 0 3px rgba(255, 255, 255, 0.64);
}

/* Avatar → account dropdown menu (shared chrome; on every page via the topbar) */
.rk-user {
  position: relative;
}

.rk-user-toggle {
  display: block;
  border: 0;
  padding: 0;
  background: none;
  border-radius: 50%;
  line-height: 0;
  cursor: pointer;
  transition: transform 140ms ease-out;
}

.rk-user-toggle:hover {
  transform: translateY(-1px);
}

.rk-user-toggle:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.rk-user-menu {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + 10px);
  z-index: 40;
  inline-size: 300px;
  max-inline-size: 84vw;
  display: grid;
  gap: 4px;
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
}

.rk-user-menu[hidden] {
  display: none;
}

.rk-user-head {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 10px 12px;
  border: 0;
  background: transparent;
  border-radius: var(--rk-radius-sm);
  text-align: start;
  cursor: pointer;
  transition: background 160ms ease-out;
}

.rk-user-head:hover {
  background: var(--rk-paper-2);
}

.rk-user-edit {
  margin-inline-start: auto;
  flex: none;
  display: grid;
  place-items: center;
  color: var(--rk-ink-muted);
}

.rk-user-edit svg {
  width: 18px;
  height: 18px;
  stroke-width: 1.7;
}

.rk-user-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  flex: none;
}

.rk-user-avatar.is-mascot {
  object-fit: cover;
  object-position: 50% 50%;
  padding: 0;
  background: var(--rk-paper-2);
  border-color: var(--rk-card-hover-border);
}

.rk-user-id {
  display: grid;
  min-width: 0;
}

.rk-user-name {
  font-weight: 800;
  color: var(--rk-ink);
}

.rk-user-email {
  font-size: 0.85rem;
  color: var(--rk-ink-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rk-user-plan {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 2px 4px 8px;
  padding: 10px 12px;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-emerald-soft);
}

.rk-plan-tag {
  font-weight: 900;
  color: var(--rk-emerald-hover);
}

.rk-plan-credits {
  font-weight: 800;
  color: var(--rk-ink);
}

.rk-user-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  border: 0;
  border-radius: var(--rk-radius-sm);
  background: transparent;
  color: var(--rk-ink);
  padding-inline: 12px;
  font-weight: 700;
  text-align: start;
  text-decoration: none;
  transition: background 160ms ease-out;
}

.rk-user-item svg {
  width: 20px;
  height: 20px;
  stroke-width: 1.65;
  color: var(--rk-ink-soft);
}

.rk-user-item:hover {
  background: var(--rk-paper-2);
}

.rk-user-item.is-logout {
  color: var(--rk-danger);
}

.rk-user-item.is-logout svg {
  color: var(--rk-danger);
}

/* ── Topbar identity: monogram avatar / loading skeleton / anon Sign-in (req 2/3) ── */
/* Solid-color monogram (email/name initial) when the user has no photo — never the mascot. */
.avatar.is-mono,
.rk-user-avatar.is-mono {
  display: grid;
  place-items: center;
  background: var(--rk-avatar-bg, var(--rk-emerald));
  color: #fff;
  font-weight: 800;
  line-height: 1;
  border-color: transparent;
  box-shadow: var(--rk-shadow-card);
}

.avatar.is-mono {
  font-size: 22px;
}

.rk-user-avatar.is-mono {
  font-size: 18px;
}

/* Quiet placeholder circle while /me is in flight (covered by the loading overlay). */
.avatar.is-skeleton {
  background: var(--rk-paper-2);
  border-color: var(--rk-line);
  box-shadow: none;
}

/* Anonymous → a plain "Sign in" button in place of the avatar. */
.rk-signin-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding-inline: 18px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font-weight: 800;
  cursor: pointer;
  transition: border-color 160ms ease-out, color 160ms ease-out;
}

.rk-signin-btn svg {
  width: 20px;
  height: 20px;
  stroke-width: 1.65;
}

.rk-signin-btn:hover {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
}

.rk-signin-btn:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

/* Empty balance slot (anon/loading) must not eat a flex gap in .rk-top-actions. */
.rk-balance-slot:empty {
  display: none;
}

/* ── App-loading overlay: opaque paper + Pudding while identity/first data resolve (req 3) ── */
.rk-app-loading {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: grid;
  place-items: center;
  /* Warm paper scrim, a hair warmer than --rk-paper. This used to have to match the running
     GIF's baked frame colour exactly; the GIF now carries real transparency (2026-08-03), so
     the value is a free choice and the cat sits cleanly on whatever is behind it. */
  background: #f8f5ee;
  transition: opacity 360ms ease, visibility 360ms ease;
}

.rk-app-loading.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.rk-app-loading-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  width: min(100% - 40px, 620px);
  text-align: center;
}

/* Running-Pudding loading GIF — carries its own run-cycle motion, so no CSS bob. Its frame background
   is warm near-paper so it blends into the paper scrim; the baked soft contact shadow grounds the cat. */
.rk-app-loading-cat {
  width: 105px;
  height: 105px;
}

.rk-app-loading-text {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.rk-app-loading.is-storyboard .rk-app-loading-cat {
  width: 105px;
  height: 105px;
}

.rk-app-loading-kicker {
  margin: 4px 0 0;
  color: var(--rk-emerald);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.rk-app-loading.is-storyboard .rk-app-loading-text {
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 16px;
  line-height: 1.25;
  letter-spacing: -0.02em;
}

.rk-app-loading-detail {
  max-width: 48ch;
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 15px;
  line-height: 1.65;
}

.rk-app-loading-stages {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  width: min(100%, 560px);
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}

.rk-app-loading-stages li {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 9px 10px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  color: var(--rk-ink-soft);
  background: color-mix(in srgb, var(--rk-surface) 72%, transparent);
}

.rk-app-loading-stages li > span {
  width: 9px;
  height: 9px;
  border: 1px solid currentColor;
  border-radius: 50%;
}

.rk-app-loading-stages li > b {
  overflow: hidden;
  font-size: 12px;
  font-weight: 700;
  text-align: start;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rk-app-loading-stages li.is-done {
  color: var(--rk-emerald);
  border-color: color-mix(in srgb, var(--rk-emerald) 26%, var(--rk-line));
}

.rk-app-loading-stages li.is-done > span {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  box-shadow: inset 0 0 0 2px var(--rk-surface);
}

.rk-app-loading-stages li.is-active {
  color: var(--rk-ink);
  border-color: var(--rk-emerald);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
}

.rk-app-loading-stages li.is-active > span {
  border: 3px solid color-mix(in srgb, var(--rk-emerald) 24%, var(--rk-surface));
  background: var(--rk-emerald);
}

@media (max-width: 680px) {
  .rk-app-loading-stages {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    width: min(100%, 360px);
  }
}

/* Kids MV production wait — the vertical stage card, modelled on the comic page's
   .cm-page-prepare-stages (Andy 2026-08-11: "看一下漫画页是怎么追加新的loading过场页").
   WHY a variant rather than the 4-pill row above: the animation line's labels are two words
   ("Verify" / "Plan shots"), so they fit a pill. MV's say what is actually happening
   ("Filling in every moment · part 2 of 3") — in a 4-column row those get ellipsised down to
   nothing, which is exactly the "用户不知道干什么去了" complaint this whole change exists to fix.
   One row per stage, full text, no truncation. */
/* 整页等待的标题按漫画那页的量级放大（.cm-storyboard-planning h2 用的是 clamp(20,2vw,28)）。
   16px 的标题在一整屏纸底上读起来像脚注，而这一句正是用户要的答案。 */
.rk-app-loading.is-kids-mv-prep .rk-app-loading-text {
  margin-top: 2px;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: clamp(19px, 1.9vw, 26px);
  line-height: 1.25;
  letter-spacing: -0.02em;
}

.rk-app-loading.is-kids-mv-prep .rk-app-loading-detail {
  max-width: 56ch;
  font-size: 14px;
  text-wrap: balance;
}

.rk-app-loading.is-kids-mv-prep .rk-app-loading-stages {
  box-sizing: border-box;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
  width: min(100%, 520px);
  margin-top: 18px;
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: color-mix(in srgb, var(--rk-surface) 92%, transparent);
  box-shadow: var(--rk-shadow-card);
}

.rk-app-loading.is-kids-mv-prep .rk-app-loading-stages li {
  min-height: 42px;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: 10px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--rk-radius);
  background: transparent;
  box-shadow: none;
}

.rk-app-loading.is-kids-mv-prep .rk-app-loading-stages li > b {
  font-size: 13px;
  white-space: normal; /* 说明性文案不许被截断——截断了这一格就白做了 */
}

.rk-app-loading.is-kids-mv-prep .rk-app-loading-stages li.is-active {
  background: var(--rk-emerald-soft);
}

/* 正在跑的那一格转圈，而不是静止的实心点：静止点看起来和"已完成"太像。 */
.rk-app-loading.is-kids-mv-prep .rk-app-loading-stages li.is-active > span {
  width: 14px;
  height: 14px;
  border: 2px solid color-mix(in srgb, var(--rk-emerald) 28%, var(--rk-line));
  border-top-color: var(--rk-emerald);
  background: transparent;
  animation: rk-loading-stage-spin 0.9s linear infinite;
}

.rk-app-loading.is-kids-mv-prep .rk-app-loading-stages li.is-done > span {
  width: 14px;
  height: 14px;
}

@keyframes rk-loading-stage-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .rk-app-loading.is-kids-mv-prep .rk-app-loading-stages li.is-active > span { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .rk-app-loading { transition: none; }
}

/* Generic modal overlay (subscription / spending-all / edit-profile) */
.rk-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px;
}

.rk-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(43, 42, 38, 0.42);
}

.rk-modal.is-identity-onboarding .rk-modal-backdrop {
  background: rgba(30, 29, 26, 0.68);
}

.rk-modal-panel {
  position: relative;
  z-index: 1;
  inline-size: min(520px, 100%);
  max-block-size: 88vh;
  overflow-y: auto;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  box-shadow: var(--rk-shadow-panel);
  padding: 28px 30px;
}

.rk-modal-panel.is-wide {
  inline-size: min(1040px, 100%);
}

/* Tutorials: a fixed viewport onto the LP's chrome-less embed. The panel does NOT grow with its
   content — the iframe scrolls inside it — because the embed is a whole page of films and a panel
   sized to it would be taller than the screen with no way back to the close button. Same reasoning
   as the subscription overlay's fixed height above, and the body padding is dropped so the frame
   meets the panel's own rounded edge instead of floating in a grey margin. */
.rk-modal-panel.is-tutorials {
  inline-size: min(1065px, 100%);
  block-size: min(780px, calc(100vh - 56px));
  overflow: hidden;
  padding: 0;
  border-radius: 16px;
  background: var(--rk-paper);
}
/* The operations strip is fixed above the Studio canvas. Centre the tutorial within the canvas,
   not behind that strip, matching every other piece of page content that consumes --rk-opsbar-h. */
.rk-modal.is-tutorials {
  inset-block-start: var(--rk-opsbar-h, 0px);
}
.rk-modal-panel.is-tutorials .rk-modal-body {
  padding: 0;
  block-size: 100%;
  overflow: hidden;
}
.rk-tutorials-frame {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
  background: var(--rk-paper);
}
/* On a phone the modal is effectively the screen; a fixed 860px box would overflow it. */
@media (max-width: 680px) {
  .rk-modal-panel.is-tutorials { block-size: 88vh; }
}

/* Subscription overlay keeps a fixed height so switching the [Plans | Purchase Credits] tabs never
   resizes the dialog — the credits view is shorter and without this the panel visibly shrinks
   (Bella). Scoped to this overlay via its tab bar, so the shared spending "view all" modal (same
   .rk-sub, no .rk-sub-tabs) is untouched. */
.rk-modal-panel.is-wide:has(.rk-sub-tabs) {
  block-size: 88vh;
}

.rk-modal-panel.is-onboarding {
  inline-size: min(700px, 100%);
  padding: 30px 34px 26px;
}

/* Step 2 是全流程里最高的一屏 (五张方形卡片排成两行)。除了压说明块,弹窗自己的那圈留白也让给
   内容 —— 否则第二行只露出半张图、看不到标题,用户以为只有三种创作类型。仅这一步生效。 */
.rk-modal-panel.is-onboarding:has([data-onboarding-step="2"]) {
  inline-size: min(920px, 100%);
  max-block-size: 94vh;
  padding-block: 20px 16px;
}

.rk-modal-panel.is-onboarding:has([data-onboarding-step="3"]) {
  inline-size: min(820px, 100%);
}

@media (max-width: 600px) {
  .rk-modal { padding: 12px; }
  .rk-modal-panel.is-onboarding { max-block-size: 94vh; padding: 20px 18px 18px; }
}

.rk-modal-x {
  position: absolute;
  z-index: 3;
  inset-block-start: 14px;
  inset-inline-end: 14px;
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  display: grid;
  place-items: center;
  transition: background 160ms ease-out, color 160ms ease-out;
}

.rk-modal-x:hover {
  background: var(--rk-line);
  color: var(--rk-ink);
}

.rk-modal-x svg {
  width: 20px;
  height: 20px;
}

/* Unified insufficient-credit prompt. It is intentionally small and quiet: the product decision is
   only which recovery path to take, not another pricing surface. The real plan / credit catalog opens
   after the explicit CTA. */
.rk-modal.is-credit-wall-prompt .rk-modal-panel.is-credit-wall {
  inline-size: min(500px, 100%);
  overflow: visible;
  padding: 38px 34px 30px;
}

.rk-credit-wall {
  display: grid;
  justify-items: center;
  gap: 14px;
  text-align: center;
}

.rk-credit-wall-icon {
  display: grid;
  place-items: center;
  inline-size: 48px;
  block-size: 48px;
  border-radius: 50%;
  background: var(--rk-warning-soft, var(--rk-cream));
  color: var(--rk-warning, #a56b12);
  font-family: var(--rk-font-display);
  font-size: 1.5rem;
  font-weight: 850;
}

.rk-credit-wall h2 {
  margin: 2px 42px 0;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: clamp(1.35rem, 3vw, 1.7rem);
  line-height: 1.25;
}

.rk-credit-wall-copy {
  margin: 0;
  max-inline-size: 410px;
  color: var(--rk-ink-soft);
  font-size: 0.98rem;
  line-height: 1.75;
  overflow-wrap: anywhere;
}

.rk-credit-wall-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  inline-size: 100%;
  margin-block-start: 10px;
  direction: ltr;
}

.rk-credit-wall-actions.is-single {
  grid-template-columns: minmax(0, 1fr);
}

.rk-credit-wall-actions .rk-btn {
  min-block-size: 46px;
  inline-size: 100%;
  white-space: normal;
}

[dir='rtl'] .rk-credit-wall-actions .rk-btn {
  direction: rtl;
}

@media (max-width: 520px) {
  .rk-modal.is-credit-wall-prompt .rk-modal-panel.is-credit-wall {
    padding: 34px 20px 22px;
  }
  .rk-credit-wall-actions { grid-template-columns: 1fr; }
  .rk-credit-wall h2 { margin-inline: 38px; }
}

/* 新手引导的 × 是这个流程唯一的出口（「暂时跳过」已删，Bella #272 / Andy 2026-08-01），所以它必须
   一眼看得见 —— 原来那颗 paper-2 底 + ink-soft 图标的淡灰圆按钮，在浅色面板上几乎是隐形的。
   升级为白底 + 实线描边 + 深墨图标 + 投影，hover 转翡翠绿；只在引导弹窗生效，其余弹窗的 × 不变。 */
.rk-modal.is-identity-onboarding .rk-modal-x {
  inset-block-start: 16px;
  inset-inline-end: 16px;
  width: 44px;
  height: 44px;
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
  box-shadow: 0 6px 18px -10px rgba(43, 42, 38, 0.45);
}

.rk-modal.is-identity-onboarding .rk-modal-x:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
}

.rk-modal.is-identity-onboarding .rk-modal-x:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--rk-emerald) 30%, transparent);
  outline-offset: 2px;
}

.rk-modal.is-identity-onboarding .rk-modal-x svg {
  width: 23px;
  height: 23px;
  stroke-width: 2.2;
}

/* Shared desktop media preview. The width is supplied by media-preview.js after it knows the
   media ratio and the real stage height, so portrait art does not sit inside a fixed wide slab. */
.rk-modal-panel.is-media-preview {
  --rk-media-preview-width: 960px;
  inline-size: min(var(--rk-media-preview-width), 92vw);
  block-size: min(88dvh, 1080px);
  max-inline-size: none;
  max-block-size: none;
  overflow: hidden;
  padding: 0;
}

.rk-modal-panel.is-media-preview.is-maximized {
  inline-size: calc(100vw - 48px);
  block-size: calc(100dvh - 48px);
  max-inline-size: none;
  max-block-size: none;
  border-radius: 14px;
}

.rk-modal-panel.is-media-preview .rk-modal-body {
  min-inline-size: 0;
  min-block-size: 0;
  block-size: 100%;
  overflow: hidden;
}

.rk-media-preview {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-inline-size: 0;
  min-block-size: 0;
  block-size: 100%;
}

.rk-media-preview-header {
  grid-row: 1;
  min-inline-size: 0;
  min-block-size: 64px;
  display: flex;
  align-items: center;
  padding: 12px 68px 12px 18px;
  border-block-end: 1px solid var(--rk-line);
  background: var(--rk-paper);
}

.rk-media-preview-header[hidden] {
  display: none;
}

.rk-media-preview-header > div {
  min-inline-size: 0;
}

.rk-media-preview-header span {
  display: block;
  color: var(--rk-ink-muted);
  font-size: 10px;
  font-weight: 900;
}

.rk-media-preview-header span[hidden] {
  display: none;
}

.rk-media-preview-header h2 {
  min-inline-size: 0;
  margin: 2px 0 0;
  overflow: hidden;
  color: var(--rk-ink);
  font: 800 16px/1.2 var(--rk-font-display);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rk-media-preview-stage {
  --rk-media-preview-stage-inset: 0px;
  grid-row: 2;
  position: relative;
  display: grid;
  place-items: center;
  min-inline-size: 0;
  min-block-size: 0;
  overflow: hidden;
  padding: var(--rk-media-preview-stage-inset);
  background: var(--rk-paper-2);
  cursor: default;
}

.rk-media-preview-stage[data-inset="true"] {
  background: var(--rk-paper);
}

.rk-media-preview-stage[data-media-type="image"] {
  touch-action: none;
}

.rk-media-preview-stage[data-media-type="image"][data-pannable="true"] {
  cursor: grab;
}

.rk-media-preview-stage[data-media-type="image"][data-pannable="true"]:active {
  cursor: grabbing;
}

.rk-media-preview-stage > img {
  display: block;
  max-inline-size: none;
  max-block-size: none;
  object-fit: contain;
  transform-origin: center;
  user-select: none;
  will-change: transform;
}

.rk-media-preview-video {
  inline-size: 100%;
  block-size: 100%;
  background: var(--rk-ink);
  object-fit: contain;
}

.rk-media-preview-audio {
  inline-size: min(480px, calc(100% - 48px));
  display: grid;
  justify-items: center;
  gap: 18px;
  padding: 28px;
}

.rk-media-preview-audio-cover {
  inline-size: min(260px, 60vh);
  aspect-ratio: 1;
  border-radius: var(--rk-radius);
  object-fit: cover;
  box-shadow: var(--rk-shadow-object);
}

.rk-media-preview-audio-placeholder {
  inline-size: 128px;
  block-size: 128px;
  border-radius: 50%;
  background: var(--rk-emerald-soft);
}

.rk-media-preview-audio strong {
  max-inline-size: 100%;
  overflow: hidden;
  font: 800 18px/1.3 var(--rk-font-display);
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rk-media-preview-audio audio {
  inline-size: 100%;
}

.rk-media-preview-footer {
  grid-row: 3;
  display: grid;
  grid-auto-rows: max-content;
  align-content: start;
  gap: 8px;
  min-inline-size: 0;
  min-block-size: 0;
  padding: 10px 16px;
  border-block-start: 1px solid var(--rk-line);
  background: var(--rk-paper);
}

.rk-media-preview-footer[hidden] {
  display: none;
}

.rk-media-preview-tools,
.rk-media-preview-navigation,
.rk-media-preview-actions,
.rk-media-preview-business {
  display: flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 0;
}

.rk-media-preview-tools,
.rk-media-preview-navigation,
.rk-media-preview-actions {
  gap: 8px;
}

.rk-media-preview-business {
  flex-wrap: wrap;
  gap: 10px 14px;
}

.rk-media-preview-tools {
  flex-wrap: nowrap;
}

.rk-media-preview-tools button {
  min-inline-size: 40px;
  min-block-size: 40px;
  padding: 7px 11px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
}

.rk-media-preview-tools button:hover {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
}

.rk-media-preview-tools button:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.rk-media-preview-tools button:disabled {
  cursor: wait;
  opacity: 0.6;
}

.rk-media-preview-download svg {
  display: block;
  inline-size: 20px;
  block-size: 20px;
}

.rk-media-preview-tools output {
  min-inline-size: 118px;
  color: var(--rk-ink-soft);
  font-size: 12px;
  text-align: center;
  white-space: nowrap;
}

.rk-media-preview-navigation > span {
  min-inline-size: 52px;
  color: var(--rk-ink-soft);
  text-align: center;
  white-space: nowrap;
}

.rk-media-preview-actions:empty {
  display: none;
}

.rk-media-preview-actions .is-success {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-media-preview-spinner {
  inline-size: 16px;
  block-size: 16px;
  display: inline-block;
  border: 2px solid currentColor;
  border-inline-end-color: transparent;
  border-radius: 50%;
  animation: rk-media-preview-spin 700ms linear infinite;
}

@keyframes rk-media-preview-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .rk-media-preview-spinner { animation-duration: 1400ms; }
}

/* Subscription overlay */
.rk-sub-kicker {
  font-size: 0.74rem;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--rk-emerald-hover);
}

.rk-sub-heading {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
  min-width: 0;
  margin: 6px 0 22px;
  padding-inline-end: 48px;
}

.rk-sub-title {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.9rem;
  line-height: 1.12;
}

.rk-sub-subtitle {
  margin: 0;
  color: var(--rk-ink-soft);
}

.rk-sub-note {
  margin: 20px 0;
  color: var(--rk-ink-muted);
}

.rk-plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 16px;
}

.rk-plan {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 20px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
}

/* The plan the visitor already picked on the public pricing page before being routed here
   (docs/prd-lp-pricing-v3-checkout-routing.md). Same vocabulary as .rk-credit.is-selected in this
   same overlay — accent border plus an inset ring — but WITHOUT its emerald-soft fill: a plan card
   carries far more content than a credit tile, and tinting that much surface would make the chrome
   compete with the cards next to it. The mark says "this is the one you chose", not "act now". */
.rk-plan.is-picked {
  border-color: var(--rk-emerald);
  box-shadow: inset 0 0 0 1px var(--rk-emerald);
}

.rk-plan-name {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.25rem;
}

.rk-plan-price {
  font-family: var(--rk-font-display);
  font-size: 1.9rem;
  font-weight: 900;
  line-height: 1;
}

.rk-plan-price small {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--rk-ink-muted);
  margin-inline-start: 4px;
}

.rk-plan-free {
  font-size: 1.3rem;
  color: var(--rk-emerald-hover);
}

.rk-plan-desc {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.88rem;
  min-height: 2.4em;
}

.rk-plan-hl {
  list-style: none;
  margin: 4px 0;
  padding: 0;
  display: grid;
  gap: 6px;
  font-size: 0.86rem;
  color: var(--rk-ink);
}

.rk-plan-hl li {
  position: relative;
  padding-inline-start: 20px;
}

.rk-plan-hl li::before {
  content: "";
  position: absolute;
  inset-inline-start: 2px;
  inset-block-start: 0.5em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rk-emerald);
}

.rk-plan-cta {
  /* CTA sits just below the price block (classic order), NOT auto-pushed to the card bottom where the
     long highlights/includes lists hide it. Fixed height + nowrap keep every button identical (a
     longer label must not wrap to 2 lines and grow the button — the row 2 "4px taller" bug). */
  margin-block-start: 4px;
  height: 46px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-weight: 800;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-inline: 14px;
  transition: background 160ms ease-out;
}

.rk-plan-cta:hover {
  background: var(--rk-emerald-hover);
}

/* Yearly billing block inside a plan card (plan-v3-sub-overlay-yearly): per-card toggle mirroring
   asllata-web /pricing; tiers already prepaid annually show the active pill instead. */
.rk-plan-yearly {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  font-weight: 800;
  color: var(--rk-ink-soft);
  cursor: pointer;
  user-select: none;
}

.rk-plan-yearly input {
  appearance: none;
  inline-size: 34px;
  block-size: 20px;
  margin: 0;
  border: 0;
  border-radius: 999px;
  background: var(--rk-line);
  position: relative;
  cursor: pointer;
  flex: none;
  transition: background 0.15s ease;
}

.rk-plan-yearly input::after {
  content: "";
  position: absolute;
  inset-block-start: 3px;
  inset-inline-start: 3px;
  inline-size: 14px;
  block-size: 14px;
  border-radius: 50%;
  background: var(--rk-surface);
  transition: transform 0.15s ease;
}

.rk-plan-yearly input:checked {
  background: var(--rk-emerald);
}

.rk-plan-yearly input:checked::after {
  transform: translateX(14px);
}

.rk-plan-yearly input:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 2px;
}

.rk-plan-save {
  margin-inline-start: auto;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.72rem;
  font-weight: 900;
  white-space: nowrap;
}

.rk-plan-yearly-note {
  margin: 0;
  font-size: 0.78rem;
  color: var(--rk-ink-muted);
}

.rk-plan-yearly-active {
  margin: 0;
  align-self: flex-start;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.76rem;
  font-weight: 900;
}

/* [Plans | Purchase Credits] tab bar — segmented pill under the subtitle */
.rk-sub-tabs {
  display: inline-flex;
  gap: 4px;
  margin: 0 0 20px;
  padding: 4px;
  border-radius: 999px;
  background: var(--rk-paper);
  border: 1px solid var(--rk-line);
}

.rk-sub-tab {
  border: 0;
  background: transparent;
  padding: 7px 18px;
  border-radius: 999px;
  font-weight: 800;
  font-size: 0.9rem;
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: background 140ms ease-out, color 140ms ease-out;
}

.rk-sub-tab.is-active {
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.rk-sub-tab:not(.is-active):hover {
  color: var(--rk-ink);
}

/* Personal / Team sub-tabs inside the Plans view — a lighter, centered segmented control that reads
   as subordinate to the main emerald-filled [Plans | Purchase Credits] tabs. */
.rk-plan-group {
  display: flex;
  justify-content: center;
  gap: 4px;
  width: fit-content;
  margin: 0 auto 18px;
  padding: 3px;
  border-radius: 999px;
  background: var(--rk-paper);
  border: 1px solid var(--rk-line);
}

.rk-plan-group-tab {
  border: 0;
  background: transparent;
  padding: 6px 16px;
  border-radius: 999px;
  font-weight: 800;
  font-size: 0.82rem;
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: background 140ms ease-out, color 140ms ease-out;
}

.rk-plan-group-tab.is-active {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-plan-group-tab:not(.is-active):hover {
  color: var(--rk-ink);
}

/* Multi-Seat "Custom" contact-sales card (Team tab) — reuses .rk-plan; badge + text "price" */
.rk-plan-badge {
  align-self: flex-start;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.72rem;
  font-weight: 900;
}

.rk-plan-custom-price {
  font-size: 1.25rem;
  font-weight: 900;
  color: var(--rk-ink);
}

/* Multi-seat custom plan handoff — V3 skin over the complete classic contact guide. */
.rk-contact {
  width: min(100%, 920px);
  margin: 0 auto;
  padding: 4px 0 20px;
}
.rk-contact-hero {
  display: grid;
  justify-items: center;
  gap: 8px;
  margin: 0 auto 24px;
  text-align: center;
}
.rk-contact-icon {
  display: grid;
  place-items: center;
  width: 68px;
  height: 68px;
  border-radius: 50%;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 1.7rem;
  font-weight: 900;
}
.rk-contact-hero h3 {
  margin: 0;
  color: var(--rk-ink);
  font-size: 1.55rem;
}
.rk-contact-hero p {
  margin: 0;
  color: var(--rk-ink-soft);
  line-height: 1.5;
}
.rk-contact-notice {
  margin: -10px auto 16px;
  padding: 9px 14px;
  border-radius: var(--rk-radius);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.86rem;
  font-weight: 800;
  text-align: center;
}
.rk-contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
  gap: 20px;
}
.rk-contact-primary,
.rk-contact-guide {
  display: grid;
  gap: 14px;
}
.rk-contact-email-card,
.rk-contact-panel {
  padding: 22px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
}
.rk-contact-email-card {
  text-align: center;
}
.rk-contact-email-card > span {
  display: block;
  color: var(--rk-ink-soft);
  font-size: 0.82rem;
}
.rk-contact-email-card > strong {
  display: block;
  margin: 8px 0;
  color: var(--rk-emerald-hover);
  font-size: clamp(1.15rem, 2.2vw, 1.45rem);
  overflow-wrap: anywhere;
}
.rk-contact-email-card > p {
  margin: 0 0 18px;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.5;
}
.rk-contact-actions {
  display: grid;
  gap: 10px;
  padding-top: 16px;
  border-top: 1px solid var(--rk-line);
}
.rk-contact-main,
.rk-contact-outline,
.rk-contact-back,
.rk-contact-subject button {
  min-height: 42px;
  border-radius: var(--rk-radius);
  font-weight: 800;
  cursor: pointer;
}
.rk-contact-main {
  border: 1px solid var(--rk-emerald);
  background: var(--rk-emerald);
  color: var(--rk-surface);
}
.rk-contact-outline {
  border: 1px solid var(--rk-emerald);
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
}
.rk-contact-back {
  justify-self: center;
  border: 0;
  background: transparent;
  color: var(--rk-emerald-hover);
}
.rk-contact-panel h4,
.rk-contact-subject h4 {
  margin: 0 0 14px;
  color: var(--rk-ink);
  font-size: 0.95rem;
}
.rk-contact-panel ul {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.rk-contact-panel li {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
}
.rk-contact-panel li span {
  color: var(--rk-emerald-hover);
  font-weight: 900;
}
.rk-contact-subject {
  padding: 18px;
  border-radius: var(--rk-radius);
  background: var(--rk-emerald-soft);
}
.rk-contact-subject button {
  width: 100%;
  padding: 9px 12px;
  border: 1px dashed var(--rk-emerald);
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
}
.rk-contact-reply {
  margin: 0;
  padding: 13px 16px;
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.84rem;
  line-height: 1.5;
}

@media (max-width: 780px) {
  .rk-contact-grid {
    grid-template-columns: 1fr;
  }

  .rk-contact-hero {
    margin-block-end: 18px;
  }
}

/* Studio desktop task entry (2026-08-13): the composer, filters and bookshelf are one creation
   workspace. The activity therefore leaves that document flow on PC and becomes a right-side entry.
   Mobile keeps the existing in-flow card untouched. */
.rk-activity {
  appearance: none;
  font: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
}

.rk-activity-trigger-icon,
.rk-activity-compact-badge { display: none; }

.rk-activity-dismiss { display: none; }

.rk-activity:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--rk-emerald) 32%, transparent);
  outline-offset: 3px;
}

@media (min-width: 1024px) {
  .rk-activity:hover {
    transform: translateY(-2px);
    border-color: color-mix(in srgb, var(--rk-emerald) 48%, var(--rk-line));
    box-shadow: 0 16px 34px rgba(32, 91, 72, 0.2);
  }

  .rk-activity-trigger-icon {
    display: grid;
    inline-size: 32px;
    block-size: 32px;
    place-items: center;
    border-radius: 11px;
    background: var(--rk-emerald-soft);
    color: var(--rk-emerald);
  }

  .rk-activity-trigger-icon svg {
    inline-size: 22px;
    block-size: 22px;
    stroke-width: 1.8;
  }

  .rk-activity-compact-badge {
    position: absolute;
    inset-block-start: -7px;
    inset-inline-end: -7px;
    display: block;
    min-inline-size: 25px;
    block-size: 21px;
    padding-inline: 6px;
    border: 2px solid var(--rk-surface);
    border-radius: 999px;
    background: #d89b28;
    color: #fff;
    font-size: 0.66rem;
    font-weight: 800;
    line-height: 17px;
    text-align: center;
  }
}

@media (min-width: 1780px) {
  .rk-activity-trigger-icon {
    grid-column: 1;
    grid-row: 1;
    inline-size: 42px;
    block-size: 42px;
    border-radius: 14px;
  }

  .rk-activity-trigger-icon svg {
    inline-size: 24px;
    block-size: 24px;
  }

  .rk-activity-compact-badge { display: none; }
}

.rk-activity-drawer-open { overflow: hidden; }

.rk-activity-drawer-layer {
  position: fixed;
  z-index: 180;
  inset: 0;
  display: grid;
  justify-items: end;
}

.rk-activity-drawer-layer[hidden] { display: none; }

.rk-activity-drawer-backdrop {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
  background: rgba(25, 32, 29, 0.28);
  cursor: default;
}

.rk-activity-drawer {
  position: relative;
  display: flex;
  inline-size: min(460px, calc(100vw - 32px));
  block-size: 100%;
  flex-direction: column;
  overflow: auto;
  background: var(--rk-paper);
  border-inline-start: 1px solid var(--rk-line);
  box-shadow: -24px 0 60px rgba(31, 55, 47, 0.18);
  animation: rk-activity-drawer-in 180ms ease-out both;
}

.rk-activity-drawer-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 28px 28px 0;
}

.rk-activity-drawer-kicker {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--rk-emerald);
  font-size: 0.78rem;
  font-weight: 800;
}

.rk-activity-drawer-kicker svg {
  inline-size: 16px;
  block-size: 16px;
  stroke-width: 1.8;
}

.rk-activity-drawer-head h2 {
  margin: 7px 0 0;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1.82rem;
  line-height: 1.18;
  letter-spacing: -0.025em;
}

.rk-activity-switcher {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px;
  margin: 20px 28px 0;
}

.rk-activity-choice {
  display: flex;
  min-inline-size: 0;
  min-block-size: 46px;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 13px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
}

.rk-activity-choice span {
  min-inline-size: 0;
  overflow: hidden;
  font-weight: 750;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rk-activity-choice b {
  flex: none;
  color: var(--rk-ink-muted);
  font-size: 0.76rem;
}

.rk-activity-choice:hover {
  border-color: color-mix(in srgb, var(--rk-emerald) 34%, var(--rk-line));
  background: color-mix(in srgb, var(--rk-emerald-soft) 45%, var(--rk-surface));
}

.rk-activity-choice.is-active {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rk-emerald) 16%, transparent);
}

.rk-activity-choice.is-active b { color: var(--rk-emerald); }

.rk-activity-choice:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 2px;
}

.rk-activity-drawer-close {
  display: grid;
  inline-size: 40px;
  block-size: 40px;
  flex: none;
  padding: 0;
  place-items: center;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  cursor: pointer;
}

.rk-activity-drawer-close:hover { background: var(--rk-surface-soft); }

.rk-activity-drawer-close:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 2px;
}

.rk-activity-drawer-close svg {
  inline-size: 19px;
  block-size: 19px;
  stroke-width: 1.8;
}

.rk-activity-drawer-body {
  padding: 0 28px 24px;
}

.rk-activity-drawer-summary {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr);
  align-items: center;
  gap: 17px;
  margin: 25px 0 20px;
  padding: 14px 16px;
  border: 1px solid var(--rk-line);
  border-radius: 18px;
  background: var(--rk-surface);
}

.rk-activity-drawer-art {
  inline-size: 74px;
  block-size: 78px;
  overflow: hidden;
}

.rk-activity-drawer-art img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: top;
  mix-blend-mode: multiply;
}

.rk-activity-drawer-summary-copy { min-inline-size: 0; }

.rk-activity-drawer-summary p {
  margin: 0 0 10px;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.55;
}

.rk-activity-drawer-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  color: var(--rk-ink-soft);
  font-size: 0.75rem;
  font-weight: 750;
}

.rk-activity-drawer-meta span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.rk-activity-drawer-meta svg {
  inline-size: 17px;
  block-size: 17px;
  flex: none;
  stroke-width: 1.8;
}

.rk-activity-drawer-progress { margin-block-end: 6px; }

.rk-activity-drawer-progress > div:first-child {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-block-end: 8px;
  color: var(--rk-ink);
  font-size: 0.8rem;
}

.rk-activity-drawer-progress span {
  color: var(--rk-emerald);
  font-weight: 850;
}

.rk-activity-drawer-track {
  block-size: 6px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--rk-line-soft);
}

.rk-activity-drawer-track i {
  display: block;
  block-size: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
}

.rk-activity-step-list {
  margin: 18px 0;
  padding: 0;
  list-style: none;
}

.rk-activity-step-list li {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr) auto;
  align-items: start;
  gap: 12px;
  padding: 14px 0;
  border-block-end: 1px solid var(--rk-line);
}

.rk-activity-step-mark {
  display: grid;
  inline-size: 28px;
  block-size: 28px;
  place-items: center;
  border: 1px solid color-mix(in srgb, var(--rk-ink-muted) 45%, transparent);
  border-radius: 50%;
  color: var(--rk-ink-muted);
  font-size: 0.74rem;
  font-weight: 800;
}

.rk-activity-step-mark svg {
  inline-size: 16px;
  block-size: 16px;
  stroke-width: 2.2;
}

.rk-activity-step-list li.is-done .rk-activity-step-mark {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: #fff;
}

.rk-activity-step-list li.is-current .rk-activity-step-mark {
  border: 2px solid var(--rk-emerald);
  color: var(--rk-emerald);
}

.rk-activity-step-copy {
  display: grid;
  min-inline-size: 0;
  gap: 4px;
}

.rk-activity-step-copy strong {
  color: var(--rk-ink);
  font-size: 0.86rem;
}

.rk-activity-step-copy small {
  color: var(--rk-ink-soft);
  font-size: 0.75rem;
  line-height: 1.45;
}

.rk-activity-step-reward {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--rk-emerald);
  font-size: 0.75rem;
  font-weight: 800;
}

.rk-activity-step-reward svg {
  inline-size: 15px;
  block-size: 15px;
  stroke-width: 1.8;
}

.rk-activity-step-state {
  margin-block-start: 3px;
  padding: 4px 8px;
  border-radius: 999px;
  background: var(--rk-surface-soft);
  color: var(--rk-ink-muted);
  font-size: 0.65rem;
  line-height: 1.2;
  white-space: nowrap;
}

.rk-activity-step-list li.is-done .rk-activity-step-state {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
}

.rk-activity-step-list li.is-current .rk-activity-step-state {
  background: #fff1d5;
  color: #9b680c;
}

/* Delivery tone beats step position: a milestone can be done and still be waiting, retrying, or
   parked because the reward gate is shut, and those are the states the user actually came to read.
   Same vocabulary as the task centre (lib/task-status.js) so both surfaces agree. */
.rk-activity-step-list .rk-activity-step-state.is-rewarded {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
}

.rk-activity-step-list .rk-activity-step-state.is-pending {
  background: #fff1d5;
  color: #9b680c;
}

.rk-activity-step-list .rk-activity-step-state.is-attention {
  background: var(--rk-warning-soft);
  color: var(--rk-warn);
}

.rk-activity-step-list .rk-activity-step-state.is-locked {
  background: var(--rk-surface-sunken);
  color: var(--rk-ink-faint);
}

/* A step whose prerequisites are unmet is dimmed rather than hidden: seeing what comes next is what
   makes the current step feel like progress toward something. */
.rk-activity-step-list li.is-locked .rk-activity-step-copy strong,
.rk-activity-step-list li.is-locked .rk-activity-step-copy small {
  color: var(--rk-ink-faint);
}

.rk-activity-step-list li.is-locked .rk-activity-step-reward {
  opacity: 0.55;
}

/* Amount and validity share one row. `.rk-activity-step-copy` is a grid, so without this wrapper
   each would claim a row of its own — and a seven-node workflow would push the drawer's actions off
   a phone screen. Wraps rather than clips when a long expiry date meets a narrow viewport. */
.rk-activity-step-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 6px;
  margin-block-start: 3px;
}

.rk-activity-step-validity {
  color: var(--rk-ink-muted);
  font-size: 0.7rem;
  line-height: 1.3;
}

.rk-activity-step-reward + .rk-activity-step-validity::before {
  content: '·';
  margin-inline-end: 6px;
  color: var(--rk-ink-faint);
}

/* Feedback-only milestones (no reward configured) still deserve a line — silence would read as a
   missing value rather than a deliberate "this one is a checkpoint, not a payout". */
.rk-activity-step-reward.is-none {
  color: var(--rk-ink-muted);
  font-weight: 600;
}

.rk-activity.is-link { cursor: pointer; }

.rk-activity-drawer-note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 12px 13px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--rk-emerald-soft) 72%, var(--rk-surface));
  color: color-mix(in srgb, var(--rk-emerald) 64%, var(--rk-ink));
  font-size: 0.75rem;
  line-height: 1.5;
}

.rk-activity-drawer-note svg {
  inline-size: 18px;
  block-size: 18px;
  flex: none;
  margin-block-start: 1px;
  stroke-width: 2;
}

.rk-activity-drawer-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-block-start: 20px;
}

.rk-activity-drawer-secondary,
.rk-activity-drawer-primary {
  display: inline-flex;
  min-block-size: 45px;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  font-size: 0.86rem;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
}

.rk-activity-drawer-secondary {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
}

.rk-activity-drawer-primary {
  gap: 7px;
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
  box-shadow: 0 6px 14px rgba(17, 146, 113, 0.2);
}

.rk-activity-drawer-primary svg {
  inline-size: 18px;
  block-size: 18px;
  transform: rotate(180deg);
  stroke-width: 1.8;
}

html[dir="rtl"] .rk-activity-drawer-primary svg { transform: none; }

.rk-activity-drawer-secondary:hover { background: var(--rk-surface-soft); }
.rk-activity-drawer-primary:hover { background: var(--rk-emerald-hover); }

.rk-activity-drawer-achieved {
  margin: 14px 0 0;
  color: var(--rk-emerald);
  font-size: 0.8rem;
  font-weight: 750;
}

@keyframes rk-activity-drawer-in {
  from { transform: translateX(18px); opacity: 0.72; }
  to { transform: translateX(0); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .rk-activity-drawer { animation: none; }
}

/* Shown once over the Plans grid when a free user tapped Buy (credit purchase is subscriber-only) */
.rk-sub-gate {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: var(--rk-radius);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.86rem;
  font-weight: 700;
}

/* The way out, inline with the sentence that named it (cancelled-but-in-period credit gate).
   Wraps onto its own line on narrow widths because the notice is a full sentence, not a label. */
.rk-sub-gate-act {
  display: inline-block;
  margin-inline-start: 8px;
  padding: 4px 12px;
  border: 1px solid currentColor;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.82rem;
  line-height: 1.5;
  cursor: pointer;
  vertical-align: baseline;
}

.rk-sub-gate-act:hover {
  background: var(--rk-emerald-hover);
  color: var(--rk-surface);
}

.rk-sub-gate-act:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}

/* Transient payment-return toast (in-app Stripe checkout). No toast lib in v3 — see shell.js showToast.
   Tokens carry the light/dark adaptation, so no explicit theme rules are needed. */
.rk-toast {
  position: fixed;
  /* Top, not bottom (2026-08-07 Andy): on these tall, mostly-empty pages the eye never travels to the
     floor — a pill down there said its piece and left unread.
     24px, i.e. level with the top row rather than below it. Below was tried first (88px, clearing the
     76px topbar) and is worse: it lands on the first row of actual CONTENT — on the home screen it
     covered the 绘本/动画/儿童MV tabs outright. The top row is the one band that is reliably free in
     the middle: the topbar fills only its left slot and its right actions, and the five surfaces that
     actually toast are four bare pages (book-video · anim · kids-mv ×2, thin back link only) plus the
     account page's checkout return. */
  inset-block-start: 24px;
  inset-inline: 0;
  margin-inline: auto;
  width: max-content;
  max-width: min(90vw, 420px);
  /* Above .rk-app-loading (2000): the checkout-return toast fires as the page boots, so on a page that
     is still behind the loading scrim a lower-stacked toast would live and auto-dismiss entirely unseen. */
  z-index: 2100;
  padding: 12px 18px;
  border-radius: var(--rk-radius);
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
  box-shadow: var(--rk-shadow-card);
  font-size: 0.9rem;
  font-weight: 700;
  text-align: center;
  opacity: 0;
  /* Drops in from above, matching where it now lives. */
  transform: translateY(-12px);
  transition: opacity 260ms ease-out, transform 260ms ease-out;
  pointer-events: none;
}

.rk-toast.is-in {
  opacity: 1;
  transform: translateY(0);
}

.rk-toast-success {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-toast-error {
  border-color: #e0b4ac;
  background: #fdf0ed;
  color: #8f3b2c;
}

/* Scheduled-change banner: state, not a reaction — it sits above the gate notice and stays put while
   the user moves between the plans and credits tabs (subscription.js changeNoticeHtml). */
.rk-sub-change {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0 0 14px;
  padding: 12px 16px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}
.rk-sub-change-text {
  margin: 0;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--rk-ink);
  flex: 1 1 240px;
}
.rk-sub-change-acts {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.rk-sub-change-go {
  border: 0;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  border-radius: var(--rk-radius);
  padding: 8px 14px;
  font-weight: 800;
  cursor: pointer;
}
.rk-sub-change-cancel {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
  border-radius: var(--rk-radius);
  padding: 8px 14px;
  font-weight: 700;
  cursor: pointer;
}

/* Classic Autobook conversion notice: keep the scheduled Standard-plan change visible and
   cancellable without leaving the V3 subscription overlay. */
.rk-autobook-notice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin: 0 0 14px;
  padding: 12px 16px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 28%, var(--rk-line));
  border-radius: var(--rk-radius);
  background: var(--rk-emerald-soft);
}
.rk-autobook-copy {
  display: grid;
  gap: 3px;
  flex: 1 1 320px;
  color: var(--rk-ink);
}
.rk-autobook-copy strong {
  font-size: 0.9rem;
}
.rk-autobook-copy span {
  font-size: 0.82rem;
  line-height: 1.45;
  opacity: 0.72;
}
.rk-autobook-cancel {
  border: 1px solid var(--rk-emerald);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  padding: 8px 14px;
  font-weight: 800;
  cursor: pointer;
}
.rk-autobook-cancel:hover {
  background: color-mix(in srgb, var(--rk-emerald-soft) 54%, var(--rk-surface));
}

/* Manage-subscription view (strip → Manage): plan, billing cycle, renewal date, cancel. */
/* Full content width, flush with the identity strip above it. It used to be a 460px block with
   `margin: auto` inside a 1040px panel, which left ~300px of dead space on BOTH sides and read as a
   layout bug rather than a choice (Bella, 2026-08-03). Everything in here is a table or a row of
   controls — they want the width; only the prose below gets a reading measure. */
.rk-manage {
  margin: 4px 0 0;
}
.rk-manage-line {
  margin: 0 0 14px;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--rk-ink);
  opacity: 0.72;
}
/* Prepaid annual terms that overlap (year-plan A+B) — one row each, capped so a long list scrolls
   inside the view instead of pushing the actions off the modal. */
.rk-manage-terms {
  list-style: none;
  margin: 0 0 16px;
  padding: 10px;
  max-height: 132px;
  overflow-y: auto;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
}
.rk-manage-terms li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  padding: 5px 4px;
  font-size: 0.82rem;
}
.rk-manage-term-name {
  font-weight: 800;
  color: var(--rk-ink);
}
.rk-manage-term-anchor {
  color: var(--rk-ink-muted);
}
.rk-manage-term-when {
  margin-inline-start: auto;
  color: var(--rk-ink-soft);
}

/* Manage sub-tabs: credit details | team seats. `width: fit-content` keeps the bar hugging its two
   labels — stretched across the full panel each tab would be ~500px wide and stop reading as a tab.
   max-width + wrap because the labels are 25 locales wide: German runs far longer than Chinese, and
   a bar sized to its content has to fold onto a second row rather than poke out of the panel. */
.rk-manage-tabs {
  display: flex;
  flex-wrap: wrap;
  width: fit-content;
  max-width: 100%;
  gap: 6px;
  margin: 0 0 14px;
  padding: 3px;
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}
.rk-manage-tab {
  flex: 0 0 auto;
  border: 0;
  border-radius: var(--rk-radius-sm);
  padding: 7px 20px;
  background: none;
  color: var(--rk-ink-soft);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 800;
  cursor: pointer;
}
.rk-manage-tab.is-active {
  background: var(--rk-surface);
  color: var(--rk-ink);
  box-shadow: var(--rk-shadow-card);
}

/* Credit batches: what each grant was, when it lapses, how much is left.
   The measure caps are what let .rk-manage run full width without its sentences turning into
   one-line-per-paragraph banners. */
.rk-manage-note {
  margin: 0 0 10px;
  max-width: 72ch;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--rk-ink-soft);
}
.rk-manage-empty {
  margin: 12px 0;
  max-width: 72ch;
  font-size: 0.86rem;
  color: var(--rk-ink-muted);
}
.rk-manage-retry {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
  border-radius: var(--rk-radius);
  padding: 8px 14px;
  font-weight: 700;
  cursor: pointer;
}
.rk-credit-batches {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  max-height: min(360px, 38vh);
  overflow-y: auto;
}
.rk-credit-batch {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 2px 14px;
  align-items: center;
  padding: 10px 12px;
  margin-block-end: 8px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
}
.rk-credit-batch-src {
  font-size: 0.86rem;
  font-weight: 800;
  color: var(--rk-ink);
  overflow-wrap: anywhere;
}
.rk-credit-batch-exp {
  grid-column: 1;
  font-size: 0.76rem;
  color: var(--rk-ink-muted);
}
.rk-credit-batch-amt {
  grid-column: 2;
  grid-row: 1 / span 2;
  text-align: end;
  font-size: 1.05rem;
  font-weight: 900;
  color: var(--rk-emerald-hover);
  white-space: nowrap;
}
.rk-credit-batch-amt small {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--rk-ink-muted);
}

/* Team seats: one row per member, with the manager's row pinned first and unremovable. */
/* Taller than it was: dropping the duplicated plan header freed the vertical space, and the panel
   itself is a fixed 88vh, so a short list used to leave the dialog visibly hollow. vh-bounded so a
   laptop screen never ends up with a scrollbar inside a scrollbar. */
.rk-team-rows {
  list-style: none;
  margin: 8px 0 14px;
  padding: 0;
  max-height: min(360px, 38vh);
  overflow-y: auto;
}
.rk-team-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 12px;
  margin-block-end: 8px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
}
.rk-team-row.is-editing {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
}
.rk-team-who {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1 1 160px;
}
.rk-team-id {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.rk-team-avatar {
  flex: none;
  inline-size: 30px;
  block-size: 30px;
  border-radius: 999px;
  object-fit: cover;
  border: 1px solid var(--rk-line);
}
.rk-team-avatar.is-initial {
  display: grid;
  place-items: center;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.8rem;
  font-weight: 800;
}
.rk-team-who strong {
  font-size: 0.88rem;
  font-weight: 800;
  color: var(--rk-ink);
  overflow-wrap: anywhere;
}
.rk-team-who small {
  font-size: 0.74rem;
  color: var(--rk-ink-muted);
  overflow-wrap: anywhere;
}
.rk-team-badge {
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.72rem;
  font-weight: 800;
}
/* Three numbers per member — allowance, what's left, concurrency — each labelled, because a bare row
   of digits is unreadable and the first two are easy to mistake for one another. */
.rk-team-stat {
  display: flex;
  gap: 18px;
  font-size: 0.8rem;
  color: var(--rk-ink-soft);
  white-space: nowrap;
}
.rk-team-cell {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.rk-team-cell small {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--rk-ink-muted);
}
.rk-team-cell b {
  font-size: 0.9rem;
  font-weight: 800;
  color: var(--rk-ink);
  font-variant-numeric: tabular-nums;
}
.rk-team-acts {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.rk-team-acts button {
  padding: 6px 12px;
  font-size: 0.8rem;
}
.rk-team-fields {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.rk-team-fields label,
.rk-team-invite label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--rk-ink-muted);
}
.rk-team-fields input,
.rk-team-invite input {
  width: 9rem;
  padding: 7px 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-size: 0.86rem;
}
/* ± stepper around the allowance fields (classic parity). Typing into the box still works; the
   buttons exist because 100-credit steps are what managers actually adjust in. */
.rk-team-step {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  overflow: hidden;
  background: var(--rk-surface);
}
.rk-team-step input {
  width: 6rem;
  border: 0;
  text-align: center;
}
.rk-team-step-btn {
  inline-size: 30px;
  border: 0;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 1rem;
  font-weight: 800;
  cursor: pointer;
}
.rk-team-step-btn:hover {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}
.rk-team-field-label {
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--rk-ink-muted);
}
/* update_members changes the ALLOWANCE, not the member's current balance — that lands next cycle.
   Saying so here is what stops a manager reading the unchanged balance as a failed save. */
.rk-team-hint {
  margin: 6px 0 0;
  flex-basis: 100%;
  font-size: 0.74rem;
  color: var(--rk-ink-muted);
}
/* Centred, not left-aligned: this is a short self-contained task sitting in a panel much wider than
   it needs, so flush-left stranded the fields against one edge with a long empty run beside them.
   It also replaces .rk-team-empty in the same slot, which is already centred — matching means the
   panel does not visibly jump alignment the moment a manager clicks 添加成员. */
.rk-team-invite {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 18px 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  text-align: center;
}
.rk-team-invite label {
  align-items: center;
}
/* The email label spans the panel so the field's max-width has something real to clamp against —
   left shrink-wrapped, its containing block is the field itself and max-width:100% never bites. */
.rk-team-invite > label {
  align-self: stretch;
}
.rk-team-invite .rk-team-fields,
.rk-team-invite .rk-team-acts {
  justify-content: center;
}
.rk-team-invite input[type='email'] {
  /* A definite width, not 100%: centring shrink-wraps the label, so a percentage would resolve
     against the text width and collapse the field to about half its useful size. */
  width: 22rem;
  max-width: 100%;
  text-align: center;
}
.rk-team-found {
  margin: 0;
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--rk-ink);
}
.rk-team-add {
  align-self: flex-start;
}
/* A team plan with nobody in it is the state right after purchase — the moment the panel most needs
   to explain itself, and the one a lone button explains worst. */
.rk-team-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 22px 16px;
  border: 1px dashed var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  text-align: center;
}
.rk-team-empty-title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--rk-ink);
}
.rk-team-empty-body {
  margin: 0 0 6px;
  max-inline-size: 26rem;
  font-size: 0.82rem;
  color: var(--rk-ink-soft);
}
.rk-team-empty .rk-team-add {
  align-self: center;
}
/* "Full" with no way forward is its own dead end, so the cap always ships with the exit that fits
   the tier: buy up, or talk to us. */
.rk-team-full {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.rk-team-full .rk-manage-empty {
  margin: 0;
  flex: 1 1 16rem;
}

/* Section caption above the credit-batch list and the seat list. */
.rk-manage-sec {
  display: block;
  margin: 0 0 8px;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
}

.rk-manage-acts {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  flex-wrap: wrap;
}
.rk-manage-back {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
  border-radius: var(--rk-radius);
  padding: 10px 16px;
  font-weight: 700;
  cursor: pointer;
}
/* Restore brings a cancelled-but-still-paid plan back — the one constructive action here. */
.rk-manage-restore {
  border: 0;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  border-radius: var(--rk-radius);
  padding: 10px 16px;
  font-weight: 800;
  cursor: pointer;
}

/* Destructive, so it reads as an outline — never the same weight as a purchase CTA. */
.rk-manage-cancel {
  border: 1px solid var(--rk-danger);
  background: none;
  color: var(--rk-danger);
  border-radius: var(--rk-radius);
  padding: 10px 16px;
  font-weight: 800;
  cursor: pointer;
}

/* Downgrade confirmation (a scheduled change via a $0-trial Stripe checkout) — see subscription.js. */
.rk-downgrade {
  max-width: 460px;
  margin: 12px auto 0;
}
.rk-downgrade-summary {
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--rk-ink);
  margin: 0 0 10px;
}
.rk-downgrade-note {
  color: var(--rk-ink);
  opacity: 0.72;
  font-size: 0.9rem;
  line-height: 1.5;
  margin: 0 0 16px;
}
/* "How subscriptions work" — a quiet link under the grid, and the answers it opens. */
.rk-sub-faqlink {
  margin: 18px 0 0;
  text-align: center;
}
.rk-sub-faqlink button {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--rk-ink-muted);
  text-decoration: underline;
  cursor: pointer;
}
.rk-sub-faqlink button:hover {
  color: var(--rk-ink);
}
.rk-faq {
  max-width: 640px;
  margin: 12px auto 0;
}
.rk-faq-item {
  margin-block-end: 16px;
}
.rk-faq-q {
  margin: 0 0 6px;
  font-size: 0.94rem;
  font-weight: 800;
  color: var(--rk-ink);
}
.rk-faq-a {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--rk-ink-soft);
}

/* Downgrade picker: every tier below the current one, then the billing cycle. */
.rk-dg-targets {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 16px;
}
.rk-dg-target {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.rk-dg-target.is-selected {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
}
.rk-dg-name {
  font-weight: 800;
  color: var(--rk-ink);
}
.rk-dg-price {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  font-weight: 800;
  color: var(--rk-ink);
  white-space: nowrap;
}
.rk-dg-hint {
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--rk-emerald-hover);
}
.rk-dg-cycles {
  display: flex;
  gap: 8px;
  margin: 0 0 16px;
}
.rk-dg-cycle {
  flex: 1;
  padding: 9px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.rk-dg-cycle.is-active {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}
.rk-dg-cycle:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.rk-downgrade-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
  flex-wrap: wrap;
}
.rk-downgrade-keep {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
  border-radius: var(--rk-radius);
  padding: 10px 16px;
  font-weight: 700;
  cursor: pointer;
}
.rk-downgrade-go {
  border: 0;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  border-radius: var(--rk-radius);
  padding: 10px 18px;
  font-weight: 800;
  cursor: pointer;
}
.rk-downgrade-go:hover {
  background: var(--rk-emerald-hover);
}

/* Account strip (classic PackageDiglog header re-skinned): identity + plan/validity/manage on the
   left; current subscription · credits · consumption records cells on the right. Shared by both
   overlay views, so the credits tab no longer carries its own mini header. */
.rk-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
  margin: 0 0 18px;
  padding: 14px 20px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
}

.rk-strip-id {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.rk-strip-avatar {
  inline-size: 48px;
  block-size: 48px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
}

.rk-strip-avatar.is-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-weight: 900;
  font-size: 1.2rem;
}

.rk-strip-name {
  margin: 0;
  font-weight: 900;
  font-size: 1.05rem;
}

.rk-strip-sub {
  margin: 2px 0 0;
  font-size: 0.84rem;
  color: var(--rk-ink-soft);
}

.rk-strip-valid {
  color: var(--rk-ink-muted);
}

/* Now a button (it switches the overlay to the manage view instead of navigating away), so the
   anchor look has to be re-created on top of the UA button reset. */
.rk-strip-manage {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  cursor: pointer;
  color: var(--rk-emerald-hover);
  font-weight: 800;
  text-decoration: none;
  margin-inline-start: 4px;
}

.rk-strip-cells {
  display: flex;
  align-items: center;
  gap: 26px;
  flex-wrap: wrap;
}

.rk-strip-cell {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.rk-strip-label {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
}

.rk-strip-value {
  font-weight: 900;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.rk-strip-pill {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.7rem;
  font-weight: 900;
}

.rk-strip-link {
  border: 0;
  background: none;
  padding: 0;
  color: var(--rk-emerald-hover);
  font-weight: 800;
  font-size: 0.86rem;
  cursor: pointer;
  text-decoration: none;
}

/* Classic yearly-savings banner, shown while the year-plan gate is live (plans view only). */
.rk-sub-banner {
  margin: 0 0 16px;
  padding: 12px 16px;
  border-radius: var(--rk-radius);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-weight: 800;
  text-align: center;
}

/* Plan-card parity bits: POPULAR corner badge, discount chip, struck original price, perk lines,
   includes section, disabled current-plan CTA. */
.rk-plan {
  position: relative;
}

.rk-plan-pop {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
  padding: 4px 12px;
  border-end-start-radius: var(--rk-radius);
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-size: 0.72rem;
  font-weight: 900;
  letter-spacing: 0.04em;
}

.rk-plan-disc {
  margin-inline-start: 8px;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.72rem;
  font-weight: 900;
  vertical-align: middle;
  white-space: nowrap;
}

.rk-plan-orig {
  margin-inline-start: 8px;
  color: var(--rk-ink-muted);
  font-size: 0.95rem;
  font-weight: 700;
}

.rk-plan-perk {
  margin: 0;
  font-size: 0.8rem;
  color: var(--rk-ink-muted);
}

.rk-plan-team-note {
  margin: 0;
  padding-block-start: 2px;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--rk-ink-soft);
}

/* Sits directly under the price, and reads as a qualifier on it rather than as one more perk line —
   so it takes the emerald the perks do not. */
.rk-plan-first-month {
  margin: 0 0 2px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--rk-emerald-hover);
}

.rk-plan-sec {
  margin-block-start: 4px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--rk-ink);
}

.rk-plan-inc li::before {
  content: "✓";
  background: none;
  width: auto;
  height: auto;
  border-radius: 0;
  color: var(--rk-emerald-hover);
  font-weight: 900;
  inset-block-start: 0;
}

.rk-plan-cta:disabled {
  background: var(--rk-paper);
  color: var(--rk-ink-muted);
  border: 1px solid var(--rk-line);
  cursor: default;
}

.rk-credits {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}

.rk-credit {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 22px 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
  cursor: pointer;
  text-align: center;
  transition: border-color 140ms ease-out, background 140ms ease-out, box-shadow 140ms ease-out;
}

.rk-credit:hover {
  border-color: var(--rk-emerald);
}

.rk-credit.is-selected {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  box-shadow: inset 0 0 0 1px var(--rk-emerald);
}

.rk-credit:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 2px;
}

.rk-credit-amount {
  font-family: var(--rk-font-display);
  font-size: 1.5rem;
  font-weight: 900;
  line-height: 1;
}

.rk-credit-amount small {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--rk-ink-muted);
  margin-inline-start: 4px;
}

.rk-credit-bonus {
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--rk-emerald-hover);
}

.rk-credit-price {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 0.95rem;
}

.rk-credit-orig {
  color: var(--rk-ink-muted);
  font-size: 0.8rem;
}

.rk-credit-price strong {
  font-weight: 900;
}

.rk-credit-buy {
  width: 100%;
  margin-block-start: 20px;
}

.rk-credit-reminder {
  margin: 12px 0 0;
  font-size: 0.78rem;
  color: var(--rk-ink-muted);
}

/* 价目表 view — one quiet table per product line. Reads as a reference sheet, not a sales page:
   no card chrome, no accent fills, just aligned numbers on paper. */
.rk-price {
  display: grid;
  gap: 26px;
}

.rk-price-section > h3 {
  margin: 0 0 10px;
  font-family: var(--rk-font-display);
  font-size: 1rem;
  color: var(--rk-ink);
}

/* Wide content scrolls inside its own box; the dialog body must never scroll sideways.
   `min-inline-size: 0` is what makes that true: a grid item defaults to min-width:auto, so without it
   the box grows to the table's min width instead of scrolling and the whole panel goes sideways. */
.rk-price-scroll {
  min-inline-size: 0;
  overflow-x: auto;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
}

.rk-price-table {
  inline-size: 100%;
  /* Deliberately NO min-width. A min-width here reads as "scroll the table instead of wrapping the
     names", but the ancestors are grid items with the default min-width:auto, so what actually
     happens is the whole dialog panel scrolls sideways (measured at 375px). Letting the names wrap
     to two or three lines is the lesser cost, and it keeps the promise that only the box scrolls. */
  border-collapse: collapse;
  font-size: 0.85rem;
}

.rk-price-table thead th {
  position: sticky;
  inset-block-start: 0;
  padding: 9px 14px;
  text-align: start;
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
  background: var(--rk-paper);
  border-block-end: 1px solid var(--rk-line);
  white-space: nowrap;
}

.rk-price-table thead th:nth-child(3),
.rk-price-table thead th:nth-child(4) {
  text-align: end;
}

.rk-price-table tbody th {
  padding: 9px 14px;
  text-align: start;
  font-weight: 600;
  color: var(--rk-ink);
}

.rk-price-table tbody td {
  padding: 9px 14px;
  color: var(--rk-ink);
}

.rk-price-table tbody tr + tr > * {
  border-block-start: 1px solid var(--rk-line);
}

.rk-price-unit {
  color: var(--rk-ink-soft);
  white-space: nowrap;
}

.rk-price-num {
  text-align: end;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.rk-price-num strong {
  font-weight: 800;
}

.rk-price-num strong.is-discounted {
  margin-inline-start: 7px;
  color: var(--rk-emerald-hover);
}

/* List price next to a discounted one. Muted and small so the number the viewer actually pays is
   the one the eye lands on. */
.rk-price-num s {
  color: var(--rk-ink-muted);
  font-size: 0.78rem;
  font-weight: 500;
}

.rk-price-discount-badge {
  margin-inline-start: 7px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.68rem;
  font-weight: 800;
  white-space: nowrap;
}

/* "This action cannot be paid this way" — deliberately a dash, never a zero. */
.rk-price-na {
  color: var(--rk-ink-muted);
}

.rk-price-variant {
  margin-inline-start: 6px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}

/* 会动的绘本 inside the picture-book table: a labelled break, not a second table. */
.rk-price-group > th {
  padding: 8px 14px 6px;
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--rk-ink-soft);
  background: var(--rk-paper);
}

.rk-price-table tbody tr.is-discounted > th {
  color: var(--rk-emerald-hover);
}

.rk-price-discount {
  margin: 0 0 16px;
  padding: 9px 14px;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.82rem;
  font-weight: 700;
}

.rk-price-note,
.rk-price-footnote {
  margin: 8px 0 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--rk-ink-muted);
}

.rk-price-footnote {
  margin-block-start: 18px;
}

@media (max-width: 600px) {
  .rk-price-table { font-size: 0.8rem; }
  .rk-price-table thead th,
  .rk-price-table tbody th,
  .rk-price-table tbody td { padding: 8px 10px; }
}

/* Edit-profile dialog (name + avatar) — shared by the topbar avatar menu head and the account page */
.rk-modal-panel.is-form {
  inline-size: min(440px, 100%);
}

/* The dialog is a desktop reading surface, not a form column. A fixed 840px cap still compressed
   the three release-note cards on a 1440px CSS viewport and pushed the footer below the clipped
   panel. Match the shared wide-paper tier at 1040px; 100% still shrinks inside the modal's viewport
   padding on smaller screens. The body owns any remaining vertical overflow, so the actions stay
   visible on short laptop viewports. */
.rk-modal-panel.is-announce {
  inline-size: min(1040px, 100%);
  block-size: min(736px, calc(100dvh - 48px));
  max-block-size: none;
  overflow: hidden;
  padding: 32px 44px 22px;
}

.rk-modal-panel.is-announce .rk-modal-body {
  min-block-size: 0;
  block-size: 100%;
}

/* Mobile keeps the existing scrollable fallback; this pass only redesigns desktop and tablet. */
@media (max-width: 720px) {
  .rk-modal-panel.is-announce {
    block-size: auto;
    max-block-size: 94dvh;
    overflow-y: auto;
    padding: 24px 22px 20px;
  }
  .rk-modal-panel.is-announce .rk-modal-body,
  .rk-modal-panel.is-announce .rk-whatsnew-pop { block-size: auto; }
}

.rk-pe {
  display: grid;
  gap: 18px;
}

.rk-pe-avatar-row {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-block-start: 6px;
}

.rk-pe-avatar-btn {
  position: relative;
  inline-size: 84px;
  block-size: 84px;
  flex: none;
  border: 0;
  padding: 0;
  border-radius: 50%;
  background: none;
  overflow: hidden;
  line-height: 0;
}

.rk-pe-avatar-btn:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.rk-pe-avatar,
.rk-pe-avatar-slot {
  display: block;
  inline-size: 84px;
  block-size: 84px;
  border-radius: 50%;
  object-fit: cover;
}

.rk-pe-avatar.is-initial {
  display: grid;
  place-items: center;
  font-family: var(--rk-font-display);
  font-size: 2rem;
  font-weight: 900;
  color: var(--rk-emerald-hover);
  background: var(--rk-emerald-soft);
}

.rk-pe-cam {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 26px;
  display: grid;
  place-items: center;
  background: rgba(43, 42, 38, 0.55);
  opacity: 0;
  transition: opacity 160ms ease-out;
}

.rk-pe-avatar-btn:hover .rk-pe-cam,
.rk-pe-avatar-btn:focus-visible .rk-pe-cam {
  opacity: 1;
}

.rk-pe-cam svg {
  width: 16px;
  height: 16px;
  color: #fff;
  stroke-width: 1.8;
}

.rk-pe-avatar-meta {
  display: grid;
  justify-items: start;
  gap: 6px;
}

.rk-pe-change-btn {
  min-block-size: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  padding: 0 14px;
  font: inherit;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--rk-shadow-card);
  transition: border-color 160ms ease-out, background 160ms ease-out, color 160ms ease-out;
}

.rk-pe-change-btn:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-pe-change-btn:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.rk-pe-change-btn svg {
  width: 17px;
  height: 17px;
  stroke-width: 1.8;
}

.rk-pe-hint {
  font-size: 0.8rem;
  color: var(--rk-ink-muted);
}

.rk-pe-avatar-row.is-uploading .rk-pe-avatar-btn,
.rk-pe-avatar-row.is-uploading .rk-pe-change-btn {
  opacity: 0.55;
  pointer-events: none;
}

.rk-pe-field {
  display: grid;
  gap: 6px;
}

.rk-pe-label {
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--rk-ink-soft);
}

.rk-pe-input {
  block-size: 46px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-ink);
  padding-inline: 14px;
  font-weight: 600;
}

.rk-pe-input:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 1px;
}

.rk-pe-error {
  margin: 0;
  color: var(--rk-danger);
  font-size: 0.86rem;
  font-weight: 700;
}

.rk-pe-error[hidden] {
  display: none;
}

.rk-pe-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-block-start: 2px;
}

/* Account-password dialogs (set / change). Same field metrics as the edit-profile dialog above so
   the two read as one family; global because a modal can be opened from any page. */
.rk-pwd {
  display: grid;
  gap: 16px;
}

.rk-pwd-lead {
  margin: 0;
  font-weight: 800;
}

.rk-pwd-note {
  margin: 0;
  color: var(--rk-ink-soft);
  line-height: 1.5;
}

.rk-pwd-field {
  display: grid;
  gap: 6px;
}

.rk-pwd-label {
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--rk-ink-soft);
}

.rk-pwd-input {
  inline-size: 100%;
  block-size: 46px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-ink);
  padding-inline: 14px;
  font-weight: 600;
}

.rk-pwd-input:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 1px;
}

.rk-pwd-input:disabled {
  background: rgba(43, 42, 38, 0.05);
  color: var(--rk-ink-muted);
}

.rk-pwd-code-row {
  display: flex;
  gap: 10px;
}

/* Fixed width + nowrap so the label, the countdown and the longest localized "Get" all leave the
   input the same width — the button must never resize as the seconds tick down. */
.rk-pwd-code-btn {
  flex: none;
  inline-size: 96px;
  block-size: 46px;
  border: 1px solid var(--rk-emerald);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-emerald-hover);
  font-weight: 800;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rk-pwd-code-btn:disabled {
  border-color: var(--rk-line);
  color: var(--rk-ink-muted);
  cursor: not-allowed;
}

.rk-pwd-error {
  margin: 0;
  color: var(--rk-danger);
  font-size: 0.86rem;
  font-weight: 700;
}

.rk-pwd-error[hidden] {
  display: none;
}

.rk-pwd-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-block-start: 2px;
}

/* 站内用户反馈 — same field metrics as the account dialogs above, so the three read as one family.
   Global (not a page stylesheet) because the dock opens this from every page, including the bare
   workspace shells. The panel already scrolls at 88vh, so the taller rich variant needs no extra
   height handling. */
/* 12px, not the 16px of .rk-pwd: this form has three more rows, and at 14px the plain (no
   screenshot/link) variant overflowed an 88vh panel by 17px — i.e. the common case scrolled for
   almost nothing. The rich variant still scrolls, which is expected and matches classic. */
.rk-fb {
  display: grid;
  gap: 12px;
}

.rk-fb-note {
  margin: 0;
  color: var(--rk-ink-soft);
  line-height: 1.5;
}

.rk-fb-field {
  display: grid;
  gap: 6px;
}

.rk-fb-label {
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--rk-ink-soft);
}

.rk-fb-input {
  inline-size: 100%;
  block-size: 46px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-ink);
  padding-inline: 14px;
  font: inherit;
  font-weight: 600;
}

.rk-fb-input:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 1px;
}

.rk-fb-input:disabled {
  background: rgba(43, 42, 38, 0.05);
  color: var(--rk-ink-muted);
}

/* Native select keeps its own arrow; the inline padding above would otherwise crowd it. */
.rk-fb-select {
  padding-inline-end: 8px;
  cursor: pointer;
}

.rk-fb-textarea {
  block-size: auto;
  min-block-size: 78px;
  padding-block: 12px;
  line-height: 1.5;
  resize: vertical;
}

.rk-fb-textarea.is-link {
  min-block-size: 62px;
  font-weight: 500;
}

.rk-fb-rich {
  display: grid;
  gap: 14px;
}

.rk-fb-rich[hidden] {
  display: none;
}

.rk-fb-shots {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.rk-fb-shot {
  position: relative;
  inline-size: 76px;
  block-size: 76px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  overflow: hidden;
}

.rk-fb-shot img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}

.rk-fb-shot.is-loading img {
  opacity: 0.5;
}

.rk-fb-shot-spin {
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: 20px;
  block-size: 20px;
  margin-block-start: -10px;
  margin-inline-start: -10px;
  border: 2px solid var(--rk-line);
  border-block-start-color: var(--rk-emerald);
  border-radius: 999px;
  animation: rk-fb-spin 720ms linear infinite;
}

@keyframes rk-fb-spin {
  to { transform: rotate(360deg); }
}

.rk-fb-shot-x {
  position: absolute;
  inset-block-start: 3px;
  inset-inline-end: 3px;
  inline-size: 20px;
  block-size: 20px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 999px;
  background: rgba(43, 42, 38, 0.55);
  color: #fff;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
}

.rk-fb-shot-x:hover {
  background: rgba(43, 42, 38, 0.78);
}

.rk-fb-shot-add {
  inline-size: 76px;
  block-size: 76px;
  display: grid;
  place-items: center;
  gap: 2px;
  border: 1px dashed var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-ink-soft);
  font-size: 0.66rem;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  padding: 6px;
  cursor: pointer;
}

.rk-fb-shot-add:hover {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
}

.rk-fb-shot-add span:first-child {
  font-size: 1.15rem;
  font-weight: 400;
  line-height: 1;
}

.rk-fb-error {
  margin: 0;
  color: var(--rk-danger);
  font-size: 0.86rem;
  font-weight: 700;
}

.rk-fb-error[hidden] {
  display: none;
}

.rk-fb-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-block-start: 2px;
}


@media (max-width: 600px) {
  .rk-fb-shot,
  .rk-fb-shot-add {
    inline-size: 68px;
    block-size: 68px;
  }
}

.rk-btn-ghost,
.rk-btn-primary {
  block-size: 44px;
  border-radius: 999px;
  padding-inline: 22px;
  font-weight: 800;
  border: 1px solid transparent;
  transition: background 160ms ease-out;
}

.rk-btn-ghost {
  background: transparent;
  border-color: var(--rk-line);
  color: var(--rk-ink);
}

.rk-btn-ghost:hover {
  background: var(--rk-paper-2);
}

.rk-btn-primary {
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.rk-btn-primary:hover {
  background: var(--rk-emerald-hover);
}

.rk-btn-primary:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Anchor buttons. A <button> gets centring and no underline from the UA; an <a> gets neither, so the
   same two classes render a real button next to an underlined link — visible on every error screen
   that offers a "back home" link. Scoped to a.* on purpose: putting display on the shared rule would
   change layout flow for every <button> that already relies on the UA default. */
a.rk-btn-ghost,
a.rk-btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

/* Pill switch — the shared on/off primitive. Markup (label wraps it so the text is a hit target):
     <span class="rk-switch">
       <input type="checkbox">
       <span class="rk-switch-track" aria-hidden="true"><span class="rk-switch-knob"></span></span>
     </span>
   The real checkbox stays in the DOM (keyboard + screen readers + form semantics) and is visually
   replaced by the track; emerald only in the ON state, per the one-accent rule. */
.rk-switch {
  position: relative;
  flex: none;
  display: inline-flex;
  inline-size: 34px;
  block-size: 20px;
}

.rk-switch input[type="checkbox"] {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}

.rk-switch-track {
  position: absolute;
  inset: 0;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
  transition: background-color 150ms ease-out, border-color 150ms ease-out;
}

.rk-switch-knob {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-start: 2px;
  inline-size: 14px;
  block-size: 14px;
  border-radius: 50%;
  background: var(--rk-surface);
  box-shadow: 0 1px 3px -1px rgba(43, 42, 38, 0.45);
  /* Logical inset + logical translate keep the knob travelling the correct way under RTL. */
  transition: transform 150ms ease-out;
}

.rk-switch input:checked + .rk-switch-track {
  background: var(--rk-emerald);
  border-color: var(--rk-emerald);
}

.rk-switch input:checked + .rk-switch-track .rk-switch-knob {
  transform: translateX(14px);
}

[dir="rtl"] .rk-switch input:checked + .rk-switch-track .rk-switch-knob {
  transform: translateX(-14px);
}

.rk-switch input:focus-visible + .rk-switch-track {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 2px;
}

.rk-switch input:hover:not(:checked) + .rk-switch-track {
  border-color: var(--rk-ink-muted);
}

.rk-switch input:disabled {
  cursor: default;
}

.rk-switch input:disabled + .rk-switch-track {
  opacity: 0.5;
}

/* Language selector — a card-style expandable panel (see reference), lists every locale */
.rk-lang {
  position: relative;
}

.rk-lang-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
  color: var(--rk-ink);
  padding-inline: 14px;
  font-weight: 800;
  transition: border-color 180ms ease-out, background 180ms ease-out;
}

.rk-lang-toggle:hover {
  border-color: var(--rk-card-hover-border);
}

.rk-lang-toggle svg {
  width: 20px;
  height: 20px;
  stroke-width: 1.6;
}

.rk-lang-caret {
  display: inline-flex;
}

.rk-lang-caret svg {
  width: 16px;
  height: 16px;
  color: var(--rk-ink-muted);
}

.rk-lang-menu {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + 10px);
  z-index: 40;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  inline-size: min(560px, calc(100vw - 32px));
  max-inline-size: none;
  /* 25 locales — cap the height and scroll rather than run off-screen */
  max-block-size: min(62vh, 440px);
  overflow-x: hidden;
  overflow-y: auto;
  padding: 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
}

/* [hidden] must beat the display:grid above (same trap as the intake sheet) */
.rk-lang-menu[hidden] {
  display: none;
}

.rk-lang-option {
  min-inline-size: 0;
  min-height: 42px;
  border: 1px solid transparent;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  padding-inline: 12px;
  font-weight: 700;
  white-space: nowrap;
  transition: border-color 180ms ease-out, background 180ms ease-out, color 180ms ease-out;
}

.rk-lang-option:hover {
  border-color: var(--rk-card-hover-border);
}

.rk-lang-option.is-active {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.greeting {
  max-width: 820px;
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 2.05rem;
  line-height: 1.08;
  letter-spacing: 0;
  text-align: start;
  overflow-wrap: anywhere;
}

.subline {
  display: none;
  margin: 0;
  max-width: 660px;
  color: var(--rk-ink-soft);
  font-size: 1.02rem;
}

.composer {
  width: min(830px, 100%);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  min-height: 92px;
  border: 1.5px solid color-mix(in srgb, var(--rk-ink) 78%, transparent);
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.72);
  padding: 12px 14px 10px;
  box-shadow: none;
}

.sb-composer-input {
  min-inline-size: 0;
  inline-size: 100%;
}

.composer textarea {
  display: block;
  inline-size: 100%;
  min-width: 0;
  min-height: 36px;
  resize: none;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1.3rem;
  line-height: 1.4;
  padding: 4px 2px 8px;
  overflow-y: hidden;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--rk-emerald) 34%, transparent) transparent;
}

.composer textarea::-webkit-scrollbar { inline-size: 7px; }
.composer textarea::-webkit-scrollbar-track { background: transparent; }
.composer textarea::-webkit-scrollbar-thumb { border-radius: 999px; background: color-mix(in srgb, var(--rk-emerald) 34%, transparent); }

.composer textarea::placeholder {
  color: var(--rk-ink-muted);
}

.send-button {
  width: 46px;
  height: 46px;
  border: 0;
  border-radius: 50%;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  display: grid;
  place-items: center;
  flex: none;
  box-shadow: 0 16px 28px -18px rgba(15, 164, 126, 0.8);
  transition: background 180ms ease-out, transform 180ms ease-out;
}

.send-button:hover {
  background: var(--rk-emerald-hover);
  transform: translateY(-1px);
}

.send-button svg {
  width: 24px;
  height: 24px;
  display: block;
  stroke-width: 2.15;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.08));
}

/* Composer left action — add characters (structural; picker is a later step) */
.sb-composer-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  min-block-size: 48px;
  padding-block-start: 4px;
}

.sb-cast-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.7);
  color: var(--rk-ink);
  padding-inline: 15px;
  font-family: var(--rk-font-body);
  font-size: 0.92rem;
  font-weight: 800;
  white-space: nowrap;
  transition: border-color 180ms ease-out, background 180ms ease-out, color 180ms ease-out;
}

.sb-cast-btn:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-cast-btn svg {
  width: 20px;
  height: 20px;
  stroke-width: 1.65;
}

/* Composer right actions — image upload / file upload sit before the emerald send button */
.sb-tools {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-inline-start: auto;
}

.sb-one-click-switch {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 36px;
  margin-inline-end: 6px;
  padding-inline: 10px;
  border: 1px solid transparent;
  border-radius: 999px;
  color: var(--rk-ink-soft);
  font-size: 0.82rem;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
}

.sb-one-click-switch:hover,
.sb-one-click-switch:has(input:focus-visible) {
  border-color: var(--rk-line);
  background: var(--rk-paper-2);
  color: var(--rk-ink);
}

.sb-one-click-switch[hidden] { display: none; }

.sb-one-click-dialog {
  display: grid;
  gap: 18px;
  color: var(--rk-ink);
}

.sb-one-click-dialog > header { display: grid; gap: 8px; }
.sb-one-click-dialog h2 { margin: 0; font-size: clamp(1.45rem, 2vw, 1.85rem); }
.sb-one-click-dialog p { margin: 0; color: var(--rk-ink-soft); line-height: 1.6; }
.sb-one-click-dialog > small { color: var(--rk-ink-soft); line-height: 1.5; }

.sb-one-click-dialog.is-preparing {
  justify-items: center;
  padding: 12px 8px;
  text-align: center;
}

.sb-one-click-dialog.is-preparing img { object-fit: contain; }

.sb-one-click-kicker {
  width: max-content;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.78rem;
  font-weight: 900;
  letter-spacing: 0.02em;
}

.sb-one-click-indeterminate {
  width: min(360px, 82vw);
  height: 7px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--rk-paper-2);
}

.sb-one-click-indeterminate i {
  display: block;
  width: 42%;
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
  animation: sb-one-click-wait 1.3s ease-in-out infinite;
}

@keyframes sb-one-click-wait {
  from { transform: translateX(-115%); }
  to { transform: translateX(340%); }
}

/* The named wait. The estimate's first run takes minutes (297s measured 2026-08-18), so this block
   carries the only three honest things we can say while it runs: what the server is doing, how long
   it has been doing it, and what it has already finished. No percentage and no ETA — the extraction
   is one indivisible model call, so any denominator would be invented. */
.sb-one-click-dialog.is-preparing .sb-one-click-stage {
  min-height: 1.6em;
  color: var(--rk-ink);
  font-weight: 600;
}

.sb-one-click-clock {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  margin: 0;
}

.sb-one-click-elapsed {
  /* Tabular so the seconds column does not jitter the line every tick. */
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--rk-ink-soft);
}

.sb-one-click-clock-note {
  color: var(--rk-ink-muted);
  font-size: 0.85rem;
}

.sb-one-click-rail {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  max-width: min(420px, 88vw);
}

.sb-one-click-rail:empty { display: none; }

.sb-one-click-step {
  padding: 3px 9px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-muted);
  font-size: 0.75rem;
  line-height: 1.4;
}

.sb-one-click-step::before {
  margin-inline-end: 4px;
  color: var(--rk-emerald);
  content: '✓';
}

.sb-one-click-breakdown {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  list-style: none;
}

.sb-one-click-breakdown li,
.sb-one-click-total,
.sb-one-click-balance {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 13px 16px;
}

.sb-one-click-breakdown li + li { border-top: 1px solid var(--rk-line); }
.sb-one-click-breakdown .is-reused { color: var(--rk-ink-soft); }
.sb-one-click-breakdown strong { color: var(--rk-ink); white-space: nowrap; }

.sb-one-click-total {
  border-radius: 16px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-weight: 800;
}

.sb-one-click-total strong { display: inline-flex; align-items: baseline; gap: 8px; font-size: 1.25rem; }
.sb-one-click-total del { color: var(--rk-ink-soft); font-size: 0.86rem; font-weight: 600; }

.sb-one-click-balance {
  flex-wrap: wrap;
  padding-block: 0;
}

.sb-one-click-balance small { flex-basis: 100%; color: var(--rk-danger); text-align: end; }
.sb-one-click-balance.is-short strong { color: var(--rk-danger); }

.sb-one-click-billing-note {
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--rk-paper-2);
  font-size: 0.86rem;
}

.sb-one-click-billing-note.is-error { color: var(--rk-danger); }

.sb-one-click-fallback {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  cursor: pointer;
}

.sb-one-click-fallback input { margin-block-start: 4px; accent-color: var(--rk-emerald); }
.sb-one-click-fallback span { display: grid; gap: 3px; }
.sb-one-click-fallback small { color: var(--rk-ink-soft); line-height: 1.4; }

.sb-one-click-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 10px;
}

.sb-one-click-actions button { min-width: 142px; }

/* The one-click decision intentionally shows only one number and two billing explanations. */
.rk-modal.is-storybook-one-click-quote {
  padding: 16px;
}

.rk-modal.is-storybook-one-click-quote .rk-modal-panel {
  inline-size: min(560px, 100%);
  block-size: min(470px, calc(100dvh - 32px));
  max-block-size: none;
  overflow: hidden;
  padding: 0;
}

.rk-modal.is-storybook-one-click-quote .rk-modal-body {
  min-block-size: 0;
  block-size: 100%;
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-dialog {
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 0;
  min-block-size: 0;
  block-size: 100%;
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-scroll {
  display: grid;
  align-content: start;
  grid-auto-rows: max-content;
  gap: 18px;
  min-block-size: 0;
  overflow-y: auto;
  padding: 28px 28px 22px;
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-dialog header {
  display: grid;
  gap: 6px;
  padding-inline-end: 44px;
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-dialog h2 {
  font-size: clamp(1.35rem, 2vw, 1.7rem);
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-total {
  padding: 20px;
  border-radius: 14px;
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-total span {
  font-size: 0.94rem;
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-total strong {
  font-size: 1.55rem;
}

.sb-one-click-current-credit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-inline: 4px;
  color: var(--rk-ink-soft);
  font-size: 0.9rem;
}

.sb-one-click-current-credit strong {
  color: var(--rk-ink);
  font-size: 1rem;
  white-space: nowrap;
}

.sb-one-click-current-credit.is-short strong {
  color: var(--rk-danger);
}

.sb-one-click-billing-notes {
  display: grid;
  gap: 6px;
  padding: 13px 14px;
  border-radius: 12px;
  background: var(--rk-paper-2);
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-billing-note {
  padding: 0;
  background: transparent;
  font-size: 0.82rem;
  line-height: 1.45;
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-actions {
  flex: none;
  margin: 0;
  padding: 14px 28px 18px;
  border-block-start: 1px solid var(--rk-line);
  background: var(--rk-surface);
  box-shadow: 0 -10px 24px rgba(43, 42, 38, 0.05);
}

.sb-one-click-symbol {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-danger) 12%, transparent);
  color: var(--rk-danger);
  font-size: 1.35rem;
  font-weight: 900;
}

@media (max-width: 640px) {
  .sb-one-click-breakdown li,
  .sb-one-click-total,
  .sb-one-click-balance { align-items: flex-start; gap: 8px; }
  .sb-one-click-actions { display: grid; grid-template-columns: 1fr; }
  .sb-one-click-actions button { width: 100%; }

  .rk-modal.is-storybook-one-click-quote { padding: 8px; }
  .rk-modal.is-storybook-one-click-quote .rk-modal-panel {
    block-size: min(500px, calc(100dvh - 16px));
  }
  .rk-modal.is-storybook-one-click-quote .sb-one-click-scroll {
    gap: 16px;
    padding: 22px 18px 16px;
  }
  .rk-modal.is-storybook-one-click-quote .sb-one-click-total {
    display: grid;
    justify-content: stretch;
    gap: 6px;
    padding: 16px;
  }
  .sb-one-click-current-credit {
    align-items: flex-start;
    gap: 8px;
  }
  .rk-modal.is-storybook-one-click-quote .sb-one-click-actions {
    padding: 12px 18px 16px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sb-one-click-indeterminate i { animation: none; width: 66%; }
}

.rk-task-float {
  position: fixed;
  inset-inline-end: 22px;
  inset-block-end: 22px;
  z-index: 780;
  width: min(370px, calc(100vw - 28px));
  filter: drop-shadow(0 18px 34px rgba(25, 39, 34, 0.2));
}

.rk-task-float-panel {
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 24%, var(--rk-line));
  border-radius: 20px;
  background: var(--rk-surface);
}

.rk-task-float-panel > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 15px;
  border-bottom: 1px solid var(--rk-line);
  background: var(--rk-emerald-soft);
}

.rk-task-float-panel > header > span { display: grid; gap: 2px; }
.rk-task-float-panel > header strong { color: var(--rk-ink); font-size: 0.94rem; }
.rk-task-float-panel > header small { color: var(--rk-ink-soft); font-size: 0.73rem; }
.rk-task-float-panel > header button {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  box-sizing: border-box;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-surface) 76%, transparent);
  color: var(--rk-ink);
  line-height: 0;
  cursor: pointer;
  transition: background 160ms ease, color 160ms ease, transform 160ms ease;
}

.rk-task-float-panel > header button:hover { background: var(--rk-surface); color: var(--rk-emerald-hover); }
.rk-task-float-panel > header button:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.rk-task-float-panel > header button svg {
  display: block;
  width: 16px;
  height: 16px;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2;
}

[dir="rtl"] .rk-task-float-panel > header button svg { transform: scaleX(-1); }

.rk-task-float-list {
  display: grid;
  max-height: min(66vh, 560px);
  overflow: auto;
}

.rk-task-float-run { display: grid; gap: 11px; padding: 15px; }
.rk-task-float-run + .rk-task-float-run { border-top: 1px solid var(--rk-line); }

.rk-task-float-run-head {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
}

.rk-task-float-run-head > span:nth-child(2) { display: grid; min-width: 0; gap: 2px; }
.rk-task-float-run-head strong { overflow: hidden; color: var(--rk-ink); font-size: 0.88rem; text-overflow: ellipsis; white-space: nowrap; }
.rk-task-float-run-head small { overflow: hidden; color: var(--rk-ink-soft); font-size: 0.75rem; text-overflow: ellipsis; white-space: nowrap; }
.rk-task-float-run-head > b { color: var(--rk-emerald-hover); font-size: 0.86rem; }

.rk-task-float-run-dismiss {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: pointer;
}

.rk-task-float-run-dismiss:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.rk-task-float-run-dismiss:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.rk-task-float-run-dismiss svg { width: 15px; height: 15px; stroke-width: 2; }

.rk-task-float-run-icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 12px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-task-float-run-icon svg,
.rk-task-float-peek svg { width: 20px; height: 20px; stroke-width: 1.8; }
.rk-task-float-run.is-paused .rk-task-float-run-icon { background: color-mix(in srgb, var(--rk-warning, #a56b12) 14%, transparent); color: var(--rk-warning, #a56b12); }

.rk-task-float-progress {
  height: 7px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--rk-paper-2);
}

.rk-task-float-progress i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
  transition: width 280ms ease-out;
}

.rk-task-float-stats {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  color: var(--rk-ink-soft);
  font-size: 0.72rem;
}

.rk-task-float-error {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  padding: 8px 10px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--rk-warning, #a56b12) 10%, transparent);
  color: var(--rk-ink-soft);
  font-size: 0.75rem;
  line-height: 1.45;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

.rk-task-float-actions { display: flex; justify-content: flex-end; gap: 8px; }
.rk-task-float-actions :is(button, a) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding-inline: 12px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  font: 800 0.74rem/1 var(--rk-font-body);
  text-decoration: none;
  cursor: pointer;
}

.rk-task-float-primary { border-color: var(--rk-emerald) !important; background: var(--rk-emerald); color: #fff; }
.rk-task-float-ghost { background: var(--rk-surface); color: var(--rk-ink); }
.rk-task-float-quiet { margin-inline-end: auto; border-color: transparent !important; background: transparent; color: var(--rk-ink-soft); }

.rk-task-float-peek {
  display: none;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  margin-inline-start: auto;
  padding: 7px 12px 7px 8px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 30%, var(--rk-line));
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  cursor: pointer;
}

.rk-task-float-peek > span { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--rk-emerald-soft); }
.rk-task-float-peek > i { display: grid; place-items: center; min-width: 18px; height: 18px; border-radius: 999px; background: var(--rk-emerald); color: #fff; font-size: 0.68rem; font-style: normal; }
.rk-task-float.is-collapsed { width: auto; filter: drop-shadow(0 10px 24px rgba(25, 39, 34, 0.18)); }
.rk-task-float.is-collapsed .rk-task-float-panel { display: none; }
.rk-task-float.is-collapsed .rk-task-float-peek { display: inline-flex; }

.rk-task-completion-reminder {
  position: fixed;
  inset-block-start: 88px;
  inset-inline-end: 22px;
  z-index: 790;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  width: min(370px, calc(100vw - 28px));
  overflow: hidden;
  padding: 13px 14px 15px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 34%, var(--rk-line));
  border-radius: 18px;
  background: var(--rk-surface);
  box-shadow: 0 18px 40px rgba(25, 39, 34, 0.2);
  opacity: 0;
  transform: translateX(18px);
  transition: opacity 260ms ease-out, transform 260ms ease-out;
}

.rk-task-completion-reminder.is-in { opacity: 1; transform: translateX(0); }
.rk-task-completion-reminder.is-out { opacity: 0; transform: translateX(18px); pointer-events: none; }

.rk-task-completion-reminder-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 13px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-task-completion-reminder-icon svg { width: 22px; height: 22px; stroke-width: 2; }
.rk-task-completion-reminder-copy { display: grid; min-width: 0; gap: 2px; }
.rk-task-completion-reminder-copy strong { color: var(--rk-ink); font-size: 0.9rem; }
.rk-task-completion-reminder-copy small { overflow: hidden; color: var(--rk-ink-soft); font-size: 0.73rem; text-overflow: ellipsis; white-space: nowrap; }

.rk-task-completion-reminder > a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding-inline: 12px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font: 800 0.74rem/1 var(--rk-font-body);
  text-decoration: none;
}

.rk-task-completion-reminder-countdown {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 3px;
  background: var(--rk-paper-2);
}

.rk-task-completion-reminder-countdown b {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--rk-emerald);
  transform-origin: left center;
  animation: rk-task-completion-countdown 30s linear forwards;
}

@keyframes rk-task-completion-countdown { to { transform: scaleX(0); } }

@media (max-width: 640px) {
  .rk-task-float { inset-inline: 14px; inset-block-end: 14px; width: auto; }
  .rk-task-float.is-collapsed { inset-inline-start: auto; }
  .rk-task-float-list { max-height: 58vh; }
  .rk-task-completion-reminder { inset-block-start: 76px; inset-inline: 14px; width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .rk-task-completion-reminder { transition: none; }
  .rk-task-completion-reminder-countdown b { animation: none; }
}

.sb-tool-btn {
  width: 42px;
  height: 42px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--rk-ink-soft);
  display: grid;
  place-items: center;
  transition: background 180ms ease-out, color 180ms ease-out;
}

.sb-tool-btn:hover {
  background: var(--rk-paper-2);
  color: var(--rk-ink);
}

.sb-tool-btn svg {
  width: 22px;
  height: 22px;
  stroke-width: 1.6;
}

.sb-cast-btn.is-active {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-char-chips,
.sb-attachments {
  width: min(830px, 100%);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-block-start: -4px;
}

.sb-char-chips[hidden],
.sb-attachments[hidden] {
  display: none;
}

.sb-char-chip,
.sb-char-selected-chip,
.sb-attachment {
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  border: 1px solid var(--rk-card-hover-border);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.74);
  color: var(--rk-ink);
  padding: 4px 10px 4px 5px;
  font-weight: 800;
  box-shadow: var(--rk-shadow-card);
}

.sb-char-chip img,
.sb-char-selected-chip img,
.sb-attachment img {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--rk-paper-2);
}

.sb-char-chip span {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-family: var(--rk-font-display);
}

.sb-char-chip strong,
.sb-char-selected-chip span,
.sb-attachment span {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-char-chip i,
.sb-char-selected-chip i,
.sb-attachment button {
  border: 0;
  background: transparent;
  color: var(--rk-ink-soft);
  font-style: normal;
  font-weight: 900;
  padding: 0 2px;
}

.sb-char-panel {
  width: min(830px, 100%);
  max-height: min(62vh, 620px);
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  gap: 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: rgba(255, 255, 255, 0.9);
  box-shadow: var(--rk-shadow-panel);
  padding: 16px;
  overflow: hidden;
}

.sb-char-panel[hidden] {
  display: none;
}

.sb-char-panel-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
}

.sb-char-search {
  min-width: 0;
  min-height: 46px;
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  padding-inline: 12px;
}

.sb-char-search svg {
  width: 19px;
  height: 19px;
  flex: none;
}

.sb-char-search input {
  width: 100%;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--rk-ink);
  font: inherit;
}

.sb-char-workshop,
.sb-char-done {
  min-height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rk-card-hover-border);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-weight: 900;
  padding-inline: 16px;
  text-decoration: none;
  white-space: nowrap;
}

.sb-char-selected {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sb-char-style-warning {
  flex: 1 0 100%;
  min-width: 0;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 34%, var(--rk-line));
  border-radius: var(--rk-radius-sm);
  background: color-mix(in srgb, var(--rk-warn) 8%, var(--rk-surface));
  color: var(--rk-ink-soft);
  padding: 9px 11px;
}

.sb-char-style-warning > span {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--rk-warn);
  margin-block-start: 1px;
}

.sb-char-style-warning svg {
  width: 100%;
  height: 100%;
}

.sb-char-style-warning p {
  min-width: 0;
  margin: 0;
  font-size: 0.8rem;
  font-weight: 750;
  line-height: 1.45;
}

.sb-char-grid {
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 12px;
  overflow: auto;
  padding-inline-end: 4px;
}

.sb-char-card {
  min-width: 0;
  display: grid;
  gap: 7px;
  border: 0;
  background: transparent;
  color: var(--rk-ink);
  font-weight: 900;
  text-align: center;
}

.sb-char-card:disabled {
  opacity: 0.4;
}

.sb-char-thumb {
  position: relative;
  aspect-ratio: 1;
  border: 2px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
  overflow: hidden;
  transition: border-color 160ms ease-out, box-shadow 160ms ease-out;
}

.sb-char-card:hover .sb-char-thumb,
.sb-char-card.is-selected .sb-char-thumb {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-emerald-soft);
}

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

.sb-char-thumb b {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  color: var(--rk-emerald-hover);
  font-family: var(--rk-font-display);
  font-size: 1.6rem;
}

.sb-char-check {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.sb-char-check svg {
  width: 16px;
  height: 16px;
  stroke-width: 2.4;
}

.sb-char-card strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.88rem;
}

/* B1-② casting panel: one scrollable body hosts series faces + workshop sections, so the panel's
   fixed 4-row template (top / selected / body / foot) stays intact whatever we render inside. */
.sb-char-body {
  min-height: 0;
  display: grid;
  gap: 12px;
  align-content: start;
  overflow: auto;
  padding-inline-end: 4px;
}

.sb-char-body .sb-char-grid {
  /* Inside the shared scroll body the grids must keep their content height: the standalone rule's
     min-height: 0 lets a height-constrained grid row compress below content (sections overlapped). */
  min-height: auto;
  overflow: visible;
  padding-inline-end: 0;
}

.sb-char-section {
  margin: 4px 0 0;
  color: var(--rk-ink-soft);
  font-weight: 900;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.sb-char-card.is-series-face small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--rk-ink-soft);
  font-weight: 600;
  font-size: 0.74rem;
}

.sb-char-newfaces {
  margin: 2px 0 0;
  color: var(--rk-ink-soft);
  font-weight: 600;
  font-size: 0.78rem;
}

.sb-char-panel-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border-block-start: 1px solid var(--rk-line);
  padding-block-start: 12px;
  color: var(--rk-ink-soft);
  font-weight: 900;
  font-size: 0.82rem;
}

.sb-char-state {
  margin: 0;
  min-height: 140px;
  display: grid;
  place-items: center;
  color: var(--rk-ink-soft);
  text-align: center;
}

.sb-char-state.is-error {
  color: var(--rk-danger);
}

.sb-consent {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--rk-ink-soft);
  font-weight: 700;
  line-height: 1.45;
}

.sb-consent input {
  inline-size: 18px;
  block-size: 18px;
  flex: none;
  margin-block-start: 3px;
  accent-color: var(--rk-emerald);
}

.sb-consent input:focus-visible {
  outline: var(--rk-focus-ring);
  outline-offset: 3px;
}

.sb-consent::after {
  content: '';
  position: absolute;
  inset: -7px;
  border: 2px solid var(--rk-emerald);
  border-radius: var(--rk-radius-sm);
  opacity: 0;
  pointer-events: none;
}

.sb-consent.is-attention::after {
  animation: sb-consent-attention 720ms ease-out 2;
}

.sb-consent-message {
  margin: 0;
  margin-inline-start: 28px;
  color: var(--rk-emerald-hover);
  font-size: 0.82rem;
  font-weight: 800;
  line-height: 1.4;
  text-align: start;
}

@keyframes sb-consent-attention {
  0% { opacity: 0; transform: scale(0.985); }
  30% { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.02); }
}

@media (prefers-reduced-motion: reduce) {
  .sb-consent.is-attention::after {
    animation: none;
    opacity: 1;
  }
}

.sb-composer-note {
  width: min(830px, 100%);
  margin: -6px auto 0;
  text-align: center;
  font-size: 0.92rem;
  color: var(--rk-danger);
}

.sb-composer-note[data-tone="info"] {
  color: var(--rk-ink-soft);
}

.send-button {
  position: relative;
}

.composer.is-loading textarea {
  opacity: 0.6;
}

.send-button:disabled {
  cursor: default;
}

.send-button.is-loading svg {
  visibility: hidden;
}

.send-button.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2.5px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  animation: rk-spin 0.8s linear infinite;
}

@keyframes rk-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Intake confirmation sheet — a sibling below the composer. It must stay in normal page flow so
   analysis and long result cards never resize the input border or cover the controls below. */
.sb-intake-sheet {
  position: relative;
  flex: 0 0 auto;
  width: min(830px, 100%);
  max-block-size: min(56vh, 520px);
  margin: -4px auto 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: color-mix(in srgb, var(--rk-surface) 82%, var(--rk-paper));
  box-shadow: 0 6px 18px -12px rgba(43, 42, 38, 0.18);
  padding: 16px 18px 18px;
  display: grid;
  gap: 10px;
  text-align: center;
  /* Breathing room for the scroll-into-view in revealIntakeSheet (QA Q17) — without it the card
     ends up flush against the bottom edge. */
  scroll-margin-block: 12px;
  animation: sb-intake-reveal 180ms ease-out both;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--rk-emerald) 30%, transparent) transparent;
}

.sb-intake-sheet:has(.sb-intake-analyzing) {
  max-block-size: none;
  padding-block: 10px;
  background: color-mix(in srgb, var(--rk-paper-2) 62%, var(--rk-surface));
}

.sb-intake-clear {
  position: sticky;
  float: inline-end;
  inset-block-start: 8px;
  justify-self: end;
  margin-block-end: -40px;
  z-index: 2;
  width: 40px;
  height: 40px;
  border: 1px solid transparent;
  border-radius: 999px;
  display: grid;
  place-items: center;
  padding: 0;
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: pointer;
  font: inherit;
  font-size: 1.65rem;
  line-height: 1;
  transition: color 140ms ease, background 140ms ease, border-color 140ms ease;
}

.sb-intake-clear:hover {
  border-color: var(--rk-line);
  background: var(--rk-paper-2);
  color: var(--rk-ink);
}

.sb-intake-clear:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 2px;
}

.sb-intake-sheet > .sb-sheet-title,
.sb-intake-sheet > .sb-sheet-note {
  padding-inline: 44px;
}

/* [hidden] must win over the display:grid above — otherwise the empty sheet renders as a
   blank white bar under the composer even when there's no intake content to show. */
.sb-intake-sheet[hidden] {
  display: none;
}

.sb-intake-analyzing {
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  color: var(--rk-ink-soft);
  font-weight: 800;
}

.sb-intake-analyzing-copy {
  min-inline-size: 0;
  display: grid;
  gap: 2px;
  text-align: start;
}

.sb-intake-analyzing-copy strong {
  color: var(--rk-ink);
}

.sb-intake-analyzing-copy small {
  color: var(--rk-ink-soft);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1.35;
}

@keyframes sb-intake-reveal {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.sb-sheet-title {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.15rem;
  font-weight: 800;
}

.sb-sheet-note {
  margin: -6px 0 0;
  color: var(--rk-ink-soft);
  font-size: 0.95rem;
}

.sb-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.sb-cards--two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: min(610px, 100%);
  margin-inline: auto;
}

.sb-cards--two:has(> :nth-child(3)) { width: min(830px, 100%); grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sb-cards--bible:has(> :nth-child(4)) { width: min(720px, 100%); grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* The global `body { overflow-x: hidden }` turns the body into its own scroll container — and a
   scroll container that never scrolls (its height IS its content) makes every `position: sticky`
   inside it inert. `clip` cuts the same horizontal spill without creating one, which is what the
   narrow-width action bar below needs in order to stay on screen. Scoped to this page. */
.is-chapter-series { overflow-x: clip; overflow-y: visible; }
.is-chapter-series .rk-rail, .is-chapter-series .rk-topbar { display: none; }
.is-chapter-series .rk-shell { display: block; }
.is-chapter-series .rk-main { width: 100%; padding: 0; }
.is-chapter-series .rk-content { width: 100%; max-width: none; margin: 0; }

.cs-memory-link { background: transparent; border: 0; cursor: pointer; color: inherit; text-align: left; }
.cs-book + .cs-book { border-top: 1px solid var(--rk-line); }
.cs-panel-scrim { position: fixed; inset: 0; z-index: 120; display: grid; place-items: center; padding: 24px; background: color-mix(in srgb, var(--rk-ink) 24%, transparent); }
.cs-panel { position: relative; width: min(560px, 100%); max-height: min(760px, calc(100vh - 48px)); overflow: auto; padding: 32px; border: 1px solid var(--rk-line); border-radius: 24px; background: var(--rk-paper); box-shadow: 0 24px 70px color-mix(in srgb, var(--rk-ink) 22%, transparent); }
.cs-memory-panel { width: min(840px, 100%); padding: clamp(28px, 4vw, 46px); }
.cs-memory-intro { max-width: 62ch; margin-bottom: 26px; }
.cs-memory-pending { padding: 11px 14px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-paper-2); font-weight: 750; }
.cs-memory-overview, .cs-memory-columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.cs-memory-overview > section, .cs-memory-columns > section, .cs-memory-ending { padding: 18px; border: 1px solid var(--rk-line); border-radius: 15px; background: color-mix(in srgb, var(--rk-paper-2) 68%, var(--rk-surface)); }
.cs-memory-overview h3, .cs-memory-columns h3, .cs-memory-ending h3 { margin-top: 0; }
.cs-memory-panel ul, .cs-memory-panel ol { margin: 0; padding-inline-start: 20px; }
.cs-memory-people { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.cs-memory-person { min-width: 0; padding: 14px; border: 1px solid var(--rk-line); border-radius: 13px; background: var(--rk-surface); }
.cs-memory-person > div { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.cs-memory-person small, .cs-memory-list small { color: var(--rk-ink-soft); font-size: .7rem; }
.cs-memory-person p { margin: 7px 0 0; font-size: .85rem; line-height: 1.45; }
.cs-memory-person .cs-memory-state { color: var(--rk-emerald-hover); font-weight: 750; }
.cs-memory-list { display: grid; gap: 10px; list-style: none; padding: 0 !important; }
.cs-memory-list li { display: grid; gap: 3px; }
.cs-memory-list small { color: var(--rk-emerald-hover); font-weight: 750; }
.cs-memory-episodes { display: grid; gap: 10px; }
.cs-memory-episodes p { margin: 3px 0 0; }
.cs-memory-ending h4 { margin: 18px 0 8px; font-size: .86rem; }
.cs-memory-ending li { display: flex; justify-content: space-between; gap: 14px; }
.cs-memory-empty { margin: 0; font-style: italic; }
.cs-panel h2 { margin: 2px 0 10px; font-size: clamp(1.65rem, 3vw, 2.35rem); }
.cs-panel h3 { margin: 24px 0 8px; font-size: 1rem; }
.cs-panel p, .cs-panel li { color: var(--rk-ink-soft); line-height: 1.7; }
.cs-panel-kicker { margin: 0; color: var(--rk-emerald) !important; font-weight: 800; }
.cs-panel-close { position: absolute; top: 18px; right: 18px; width: 36px; height: 36px; border: 1px solid var(--rk-line); border-radius: 50%; background: transparent; font-size: 1.4rem; cursor: pointer; }
.cs-panel label:not(.cs-conflict) { display: grid; gap: 8px; margin-top: 18px; font-weight: 750; }
.cs-panel input:not([type="checkbox"]), .cs-panel textarea, .cs-panel select { width: 100%; box-sizing: border-box; border: 1px solid var(--rk-line); border-radius: 14px; background: var(--rk-surface); color: var(--rk-ink); padding: 12px 14px; font: inherit; }
.cs-panel textarea { min-height: 104px; resize: vertical; }
.cs-panel details { margin-top: 18px; }
.cs-panel summary { cursor: pointer; font-weight: 800; }
.cs-panel-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 28px; }
.cs-panel-actions button { min-height: 46px; padding: 0 20px; border: 1px solid var(--rk-line); border-radius: 13px; background: transparent; color: var(--rk-ink); font-weight: 800; cursor: pointer; }
.cs-panel-actions .cs-primary { border-color: var(--rk-emerald); background: var(--rk-emerald); color: white; }
.cs-proposals { display: grid; gap: 10px; margin-top: 20px; }
.cs-proposals label { grid-template-columns: auto 1fr !important; align-items: start; padding: 12px; border: 1px solid var(--rk-line); border-radius: 14px; }
.cs-proposals span { display: grid; gap: 3px; }
.cs-proposals small, .cs-conflict small { color: var(--rk-ink-soft); }
.cs-proposal-item { border: 1px solid var(--rk-line); border-radius: 14px; }
.cs-proposals .cs-proposal-item > label { border: none; }
.cs-proposals .cs-retire-toggle { padding: 0 12px 10px 12px; margin: 0; color: var(--rk-ink-soft); }
.cs-proposals .cs-retire-toggle input { width: 14px; height: 14px; }
/* B1-③ "same one?" questions on the memory card + the split-apart line in Series memory */
.cs-merge-questions { display: grid; gap: 10px; margin-top: 14px; }
.cs-merge-question { display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: start; padding: 12px; border: 1px dashed var(--rk-line-strong, var(--rk-line)); border-radius: 14px; }
.cs-merge-question span { display: grid; gap: 3px; }
.cs-merge-question small { color: var(--rk-ink-soft); }
.cs-memory-merged { display: flex; align-items: center; gap: 10px; margin: 6px 0 0; color: var(--rk-ink-soft); font-size: 0.85rem; }
.cs-memory-merged button { border: 1px solid var(--rk-line); background: var(--rk-surface, #fff); border-radius: 999px; padding: 3px 12px; font-size: 0.8rem; font-weight: 700; color: var(--rk-ink); }
.cs-memory-person.is-merged { opacity: 0.75; }
.cs-conflict { display: grid; grid-template-columns: 1fr 180px; gap: 7px 14px; margin-top: 16px; padding: 14px; border: 1px solid var(--rk-line); border-radius: 14px; }
.cs-conflict input { grid-column: 1 / -1; }
.cs-memory-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.cs-memory-chips span { padding: 7px 11px; border-radius: 999px; background: color-mix(in srgb, var(--rk-emerald) 10%, var(--rk-paper)); color: var(--rk-emerald); font-weight: 800; }
@media (max-width: 720px) { .cs-panel-scrim { padding: 0; align-items: end; } .cs-panel { width: 100%; max-height: 88vh; border-radius: 24px 24px 0 0; padding: 28px 20px; } .cs-panel-actions { position: sticky; bottom: -28px; margin-inline: -20px; padding: 14px 20px 20px; background: var(--rk-paper); } }
.cs-page { box-sizing: border-box; width: min(100%, 1920px); min-height: 100vh; margin-inline: auto; padding: 24px clamp(22px, 2vw, 36px) 30px; background: var(--rk-paper-2); }
.cs-head { display: flex; justify-content: space-between; align-items: center; min-height: 56px; margin-bottom: 18px; }
.cs-head-start { display: flex; align-items: center; gap: 14px; }
.cs-brand { width: 132px; margin-inline-end: 24px; }
.cs-brand img { width: 100%; }
.cs-home { display: grid; place-items: center; width: 48px; height: 48px; border: 1px solid #dedbd4; border-radius: 9px; color: #24231f; text-decoration: none; background: #fff; }
.cs-home svg { width: 24px; }
.cs-head-start > strong { font-size: 1.18rem; }
.cs-memory-link { display: flex; align-items: center; gap: 12px; min-width: 0; max-width: 380px; justify-content: flex-end; color: var(--rk-ink); text-decoration: none; }
.cs-memory-link > svg { width: 25px; }
.cs-memory-link span { display: grid; gap: 2px; }
.cs-memory-link strong { color: #079b73; font-size: 1rem; }
.cs-memory-link small { color: var(--rk-ink-soft); font-size: .78rem; }
.cs-memory-link svg:last-child { width: 15px; }
.cs-meta, .cs-sequence-note { color: var(--rk-ink-soft); }
.cs-kicker { color: var(--rk-emerald); font-size: .78rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
/* ── Open spread (single standalone book) ─────────────────────────────────────
   No directory rail: a one-book work has nothing to navigate, so the full width goes to the book.
   Left half is the book as an object, right half is where it stands and what to do next. One
   vertical hairline is the whole divider — no card inside a card. */
.cs-workbench.is-spread { display: block; min-height: 0; }
.cs-spread { display: grid; grid-template-columns: minmax(320px, 42%) minmax(0, 1fr); align-items: start; gap: clamp(28px, 4vw, 64px); padding: clamp(28px, 3vw, 44px); border: 1px solid var(--rk-line); border-radius: var(--rk-radius-lg); background: var(--rk-surface); box-shadow: var(--rk-shadow-panel); }
.cs-spread-book { display: grid; justify-items: center; gap: 10px; padding-inline-end: clamp(28px, 4vw, 64px); border-inline-end: 1px solid var(--rk-line); text-align: center; }
.cs-spread-cover { width: clamp(190px, 20vw, 268px); aspect-ratio: 3 / 4; margin-block-end: 12px; border-radius: 3px 8px 8px 3px; box-shadow: var(--rk-shadow-object); }
.cs-spread-cover::after, .cs-spread-cover::before { width: 9px; }
.cs-spread-book h1 { margin: 0; font-size: clamp(1.3rem, 1.7vw, 1.72rem); font-weight: 800; line-height: 1.25; overflow-wrap: anywhere; }
.cs-spread-status { display: inline-flex; align-items: center; gap: 7px; margin: 4px 0 0; padding: 6px 14px; border: 1px solid var(--rk-emerald); border-radius: 999px; color: var(--rk-emerald-hover); font-size: .82rem; font-weight: 800; }
.cs-spread-status svg { width: 14px; stroke-width: 3; }
.cs-spread-saved { margin: 2px 0 0; color: var(--rk-ink-soft); font-size: .82rem; }
.cs-spread-body, .cs-spread-story { min-width: 0; }
/* In the spread the state block IS the page content, so its inner labels read as real headings
   rather than the micro-caps used when it sat inside the action panel. */
.cs-spread-body .cs-story-state > strong { padding-block-end: 10px; border-block-end: 1px solid var(--rk-line); }
.cs-spread-body .cs-story-state-line > span { margin-block-end: 5px; color: var(--rk-ink); font-size: .98rem; font-weight: 800; letter-spacing: 0; text-transform: none; }
.cs-spread-body .cs-actions { margin-block-start: 26px; padding-block-start: 22px; border-block-start: 1px solid var(--rk-line); }
.cs-spread-body .cs-actions-heading { display: none; }
.cs-spread-body .cs-action-set:first-of-type { margin-block-start: 0; }

/* Desktop uses one continuous right-hand reading pane. The story keeps its natural height and
   the actions follow it, so a non-shrinking action panel cannot collapse the story to a sliver.
   Narrow layouts keep their natural document flow because the spread stacks vertically there. */
@media (min-width: 901px) {
  .cs-page.is-single.is-spread {
    display: flex;
    flex-direction: column;
    height: 100vh;
    min-height: 0;
    overflow: hidden;
  }
  .cs-page.is-single.is-spread .cs-head { flex: none; }
  .cs-page.is-single.is-spread .cs-workbench { flex: 1; min-height: 0; }
  .cs-page.is-single.is-spread .cs-spread {
    box-sizing: border-box;
    height: 100%;
    min-height: 0;
    align-items: stretch;
    overflow: hidden;
  }
  .cs-page.is-single.is-spread .cs-spread-book {
    min-height: 0;
    align-content: start;
    overflow-y: auto;
  }
  .cs-page.is-single.is-spread .cs-spread-body {
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding-inline-end: 12px;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
  }
  .cs-page.is-single.is-spread .cs-spread-story {
    flex: none;
  }
  .cs-page.is-single.is-spread .cs-actions { flex: none; order: initial; }
}

/* Multi-book workbenches are two equal-height reader columns. Each column owns one large scrollport
   plus a non-scrolling footer; the shared measured height is applied in the desktop media block. */
.cs-workbench { display: grid; grid-template-columns: clamp(330px, 23vw, 390px) minmax(0, 1fr); gap: 18px; align-items: start; min-height: calc(100vh - 122px); background: transparent; }
.cs-rail { display: flex; flex-direction: column; align-self: start; max-height: calc(100vh - 122px); border: 1px solid var(--rk-line); border-radius: var(--rk-radius-lg); background: var(--rk-surface); box-shadow: var(--rk-shadow-panel); overflow: hidden; }
.cs-rail-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }
.cs-stage { align-self: stretch; }
.cs-series-summary { display: grid; grid-template-columns: 46px minmax(0, 1fr); gap: 14px; align-items: center; padding: 18px; border-bottom: 1px solid var(--rk-line); }
.cs-rail.is-single .cs-series-summary { border-bottom: 0; }
.cs-series-text h1 { margin: 0 0 4px; font-size: 1.06rem; font-weight: 800; line-height: 1.28; overflow-wrap: anywhere; }
.cs-series-meta { margin: 0 0 8px; color: var(--rk-ink-soft); font-size: .78rem; }
.cs-rail.is-single .cs-series-meta { margin-bottom: 0; }
.cs-series-track { height: 3px; border-radius: 999px; background: var(--rk-line); overflow: hidden; }
.cs-series-track i { display: block; height: 100%; border-radius: 999px; background: var(--rk-emerald); }
.cs-cover { position: relative; display: grid; place-items: center; overflow: hidden; flex: none; background: var(--rk-paper-2); color: var(--rk-ink-soft); }
.cs-cover img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 180ms ease-out; }
.cs-cover-fallback { display: none; width: 100%; height: 100%; place-items: center; border: 1px solid var(--rk-line); background: var(--rk-paper-2); }
.cs-cover-fallback svg { width: 38%; height: 38%; stroke-width: 1.4; }
.cs-cover.is-loading .cs-cover-fallback { display: grid; color: color-mix(in srgb, var(--rk-ink-soft) 55%, transparent); animation: cs-cover-pulse 1.15s ease-in-out infinite alternate; }
.cs-cover.is-loaded img { opacity: 1; }
.cs-cover.is-loaded .cs-cover-fallback { display: none; }
.cs-cover.is-missing img { display: none; }
.cs-cover.is-missing .cs-cover-fallback { display: grid; }
@keyframes cs-cover-pulse { from { opacity: .35; } to { opacity: .72; } }
/* A book renders as an object, not a thumbnail: cloth spine down the binding edge, a page-edge
   highlight on the fore edge, and a TIGHT contact shadow. Never a wide glow — a halo is what makes
   a mockup read as a draft. The spine tint is derived from the artwork itself, so no colour field
   has to exist for it to work. */
.cs-series-cover, .cs-book-cover, .cs-chapter-cover { border-radius: 2px 5px 5px 2px; box-shadow: 0 2px 6px -2px rgba(43, 42, 38, .42); }
.cs-series-cover::after, .cs-book-cover::after, .cs-chapter-cover::after { content: ''; position: absolute; inset: 0 auto 0 0; width: 5px; background: var(--cs-spine, linear-gradient(90deg, rgba(0,0,0,.36), rgba(0,0,0,.1))); box-shadow: inset -1px 0 0 rgba(0,0,0,.22); }
.cs-series-cover::before, .cs-book-cover::before, .cs-chapter-cover::before { content: ''; position: absolute; inset: 0 0 0 auto; width: 2px; background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.55)); z-index: 1; }
.cs-chapter-cover::after, .cs-chapter-cover::before { width: 3px; }
.cs-series-cover { width: 46px; height: 60px; }
.cs-book-cover { width: 34px; height: 44px; }

/* Book row: no card, no border — it sits directly on the panel, so the object is the only thing
   with edges. Fold control is a sibling button (never nested inside the select button). */
.cs-books { padding: 8px; }
.cs-book + .cs-book { margin-block-start: 2px; }
.cs-book-head { display: flex; align-items: center; gap: 4px; }
.cs-book-main { flex: 1 1 auto; display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 12px; align-items: center; min-width: 0; padding: 10px; border: 0; border-radius: var(--rk-radius); background: transparent; color: inherit; font: inherit; text-align: start; cursor: pointer; }
.cs-book-main:hover { background: var(--rk-paper-2); }
.cs-book-main:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: -2px; }
.cs-book-text { min-width: 0; }
.cs-book-label { display: block; margin-block-end: 2px; color: var(--rk-ink-muted); font-size: .63rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.cs-book-title { display: block; font-size: .94rem; font-weight: 700; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-book-fold { flex: 0 0 auto; display: grid; place-items: center; width: 34px; height: 34px; border: 0; border-radius: var(--rk-radius-sm); background: transparent; color: var(--rk-ink-muted); cursor: pointer; }
.cs-book-fold:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.cs-book-fold:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 1px; }
.cs-book-fold svg { width: 16px; transition: transform 180ms cubic-bezier(.22, .61, .36, 1); }
.cs-book-fold[aria-expanded="false"] svg { transform: rotate(-90deg); }

/* 1fr <-> 0fr needs no JS height measurement and survives content changes. */
.cs-fold { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 200ms cubic-bezier(.22, .61, .36, 1); }
.cs-book.is-closed .cs-fold { grid-template-rows: 0fr; }
.cs-fold > div { overflow: hidden; min-height: 0; }
/* The old dotted connector line was a file-explorer idiom and the only element still saying "admin
   panel". It is replaced by a PROGRESS SPINE: one 2px rule, emerald beside the chapters already
   written and hairline beside the ones still planned. One element now carries both the hierarchy
   and the completion, so nobody has to count rows. */
.cs-chapters { position: relative; padding: 2px 6px 10px 26px; }
.cs-chapters::before { content: ''; position: absolute; inset: 4px auto 14px 20px; width: 2px; border-radius: 999px; background: linear-gradient(var(--rk-emerald) 0 var(--cs-done, 0%), var(--rk-line) var(--cs-done, 0%) 100%); }
/* The row is a container, not a button: it holds the select button plus a real "open this chapter"
   button. A button inside a button is invalid HTML — the browser hoists the inner one out and both
   click and focus break — so the row had to stop being a <button> for the door to live here. */
/* flex-WRAP, not a 2-column grid: the door's label is a fixed ~126px and the sidebar is only
   clamp(360px,26vw,440px) wide, so a rigid second column starved the title down to 12px of a 204px
   string (measured 2026-07-21). Wrapping lets the door drop to its own line — right-aligned via the
   auto margin — whenever the title would otherwise be squeezed. */
/* The row stays a container, not a button: the door must be a real sibling button, because a button
   inside a button gets hoisted out by the browser and both click and focus break. flex-WRAP is kept
   as a safety valve for very narrow rails. */
.cs-chapter { position: relative; width: 100%; display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center; min-height: 48px; padding: 5px 8px; border-radius: var(--rk-radius); background: transparent; color: var(--rk-ink); }
.cs-chapter-main { flex: 1 1 180px; display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 12px; align-items: center; min-width: 0; border: 0; padding: 0; background: transparent; color: inherit; text-align: start; cursor: pointer; font: inherit; }
.cs-chapter.has-cover .cs-chapter-main { grid-template-columns: 26px 26px minmax(0, 1fr); }
.cs-chapter-main:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 3px; border-radius: 8px; }
.cs-chapter-cover { width: 26px; height: 34px; }

/* FOUR states, four different signals — and hover, the cheapest of them, never gets the accent.
   Previously :hover and .is-selected were the same green and .is-current set a colour the base rule
   already had, so all three collapsed into one look. */
.cs-chapter:hover { background: var(--rk-paper-2); }
.cs-chapter.is-selected { background: var(--rk-surface); box-shadow: var(--rk-shadow-card); }
.cs-chapter.is-selected::before { content: ''; position: absolute; inset: 9px auto 9px -6px; width: 3px; border-radius: 999px; background: var(--rk-line); }
.cs-chapter.is-current { background: var(--rk-surface); box-shadow: 0 2px 9px -4px rgba(43, 42, 38, .3); }
.cs-chapter.is-current::before { content: ''; position: absolute; inset: 9px auto 9px -6px; width: 3px; border-radius: 999px; background: var(--rk-emerald); }
.cs-chapter.is-current .cs-chapter-title { font-weight: 700; }

/* Status is carried by the SHAPE of the numeral chip, so a glance counts what is written. */
.cs-chip { display: grid; place-items: center; width: 26px; height: 26px; border: 1px solid var(--rk-line); border-radius: var(--rk-radius-sm); background: var(--rk-surface); color: var(--rk-ink-soft); font-size: .74rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.cs-chip svg { width: 13px; stroke-width: 3; }
.cs-chapter.is-done .cs-chip, .cs-chapter.is-current .cs-chip { border-color: var(--rk-emerald); background: var(--rk-emerald); color: #fff; }
.cs-chapter.is-review .cs-chip { border-color: var(--rk-emerald); color: var(--rk-emerald-hover); }
.cs-chapter.is-warn .cs-chip { border-color: var(--rk-amber, #c98a2e); color: var(--rk-amber-ink, #9c6a1c); }
/* Not written yet reads as an empty slot, NOT as a broken row: a dashed chip and muted type. The old
   blanket opacity dimmed the shadows and borders too, which looked like a rendering fault. */
.cs-chapter.is-locked .cs-chip { border-style: dashed; background: transparent; color: var(--rk-ink-muted); }
.cs-chapter.is-locked .cs-chapter-title { color: var(--rk-ink-muted); }

.cs-chapter-text { min-width: 0; }
.cs-chapter-title { display: block; font-size: .92rem; line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The status word is detail, not standing information: it shows on the row being read or pointed at. */
.cs-chapter-sub { display: none; margin-block-start: 2px; color: var(--rk-ink-soft); font-size: .74rem; }
.cs-chapter.is-current .cs-chapter-sub, .cs-chapter:hover .cs-chapter-sub, .cs-chapter:focus-within .cs-chapter-sub { display: block; }

/* The single ribbon on the screen, spent on the single most important row. */
.cs-ribbon { position: absolute; top: -1px; inset-inline-end: 14px; width: 12px; height: 26px; background: var(--rk-emerald); clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 74%, 0 100%); }

/* The door is taken OUT OF FLOW. Left in flow it still reserved its slot while invisible, and at the
   rail's 330px floor that pushed it onto a second line on every non-current row — rows silently grew
   from 54px to 79px around a button nobody could see. (Same collision the old layout hit; keeping
   the slot was not the fix.) Absolute + fade means the row height is a constant and the title gets
   the full width; while the pill is showing, the title simply ellipsizes earlier. */
.cs-chapter-door { position: absolute; inset-inline-end: 8px; top: 50%; transform: translateY(-50%); opacity: 0; pointer-events: none; white-space: nowrap; border: 1px solid var(--rk-emerald); border-radius: 999px; padding: 5px 12px; background: var(--rk-surface); color: var(--rk-emerald-hover); font: inherit; font-size: .72rem; font-weight: 800; cursor: pointer; transition: opacity 130ms ease-out; }
.cs-chapter:hover .cs-chapter-door, .cs-chapter:focus-within .cs-chapter-door { opacity: 1; pointer-events: auto; }
/* Guard for the long tail of 25 locales: the pill can never eat more than a third of the row, and
   the title reserves the same third while the pill is up, so neither can ever cover the other. */
.cs-chapter-door { max-width: 34%; overflow: hidden; text-overflow: ellipsis; }
.cs-chapter:hover .cs-chapter-text, .cs-chapter:focus-within .cs-chapter-text { padding-inline-end: 36%; }
.cs-chapter-door:hover { background: var(--rk-emerald-soft); }
.cs-chapter-door:focus-visible { opacity: 1; outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.cs-chapter.is-locked .cs-chapter-door { display: none; }

/* Density follows chapter count so a long serialised book cannot stretch the rail into a ribbon. */
.cs-chapters[data-density="roomy"] .cs-chapter { min-height: 54px; }
.cs-chapters[data-density="tight"] .cs-chapter { min-height: 42px; }
.cs-chapters[data-density="tight"] .cs-chapter-cover { display: none; }
.cs-chapters[data-density="tight"] .cs-chapter.has-cover .cs-chapter-main { grid-template-columns: 26px minmax(0, 1fr); }

@media (prefers-reduced-motion: reduce) {
  .cs-fold, .cs-book-fold svg, .cs-chapter-door { transition: none; }
}
.cs-future-episode { display: grid; grid-template-columns: 20px auto 1fr; gap: 10px; align-items: center; padding: 20px 22px; border-top: 1px solid rgba(207, 199, 186, .72); color: var(--rk-ink-soft); }
.cs-future-episode svg { width: 16px; }
.cs-future-episode small { text-align: end; }
.cs-stage { padding: clamp(30px, 3vw, 48px); border: 1px solid var(--rk-line); border-radius: 20px; background: var(--rk-surface); box-shadow: 0 18px 46px -42px rgba(73, 61, 42, .52); overflow: auto; }
.cs-breadcrumb { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 11px; margin-bottom: 18px; color: var(--rk-ink-soft); font-size: .86rem; }
.cs-breadcrumb span:first-child, .cs-breadcrumb strong { color: var(--rk-emerald-hover); }
.cs-breadcrumb span:first-child { display: inline-flex; align-items: center; gap: 7px; }
.cs-breadcrumb span:first-child small { padding: 3px 7px; border-radius: 999px; background: var(--rk-emerald-soft); color: var(--rk-emerald-hover); font-size: .62rem; font-weight: 850; letter-spacing: .06em; text-transform: uppercase; }
.cs-stage-head { padding-bottom: 28px; border-bottom: 1px solid var(--rk-line); }
.cs-stage h2 { max-width: 26ch; margin: 0 0 14px; font-family: var(--rk-font-body); font-size: clamp(2rem, 2.5vw, 2.7rem); line-height: 1.12; overflow-wrap: anywhere; }
.cs-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 13px; margin: 0; }
.cs-meta > span:first-child { width: 10px; height: 10px; border-radius: 50%; background: var(--rk-emerald); }
.cs-meta i { width: 1px; height: 18px; border-radius: 999px; background: #d3cec4; }
.cs-current-state { padding: 4px 8px; border-radius: 999px; background: var(--rk-paper-2); color: var(--rk-ink-soft); font-size: .78rem; font-weight: 750; cursor: help; }
.cs-capacity-note { display: inline-flex; margin: 10px 0 0; padding: 8px 12px; border-radius: 999px; background: var(--rk-emerald-soft); color: var(--rk-emerald-hover); font-size: .86rem; font-weight: 700; }
.cs-stage-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(270px, 320px); gap: clamp(36px, 4vw, 64px); align-items: start; margin-top: 32px; }
.cs-stage-body { min-width: 0; max-width: 760px; }
.cs-actions { position: sticky; top: 0; display: grid; gap: 12px; min-width: 0; padding: 20px; border: 1px solid var(--rk-line); border-radius: 16px; background: var(--rk-paper); }
.cs-actions-heading { display: flex; align-items: center; gap: 9px; margin-bottom: 2px; }
.cs-actions-heading > span { width: 9px; height: 9px; border-radius: 50%; background: var(--rk-emerald); }
.cs-actions-heading strong { font-size: .9rem; }
.cs-action-group { display: grid; gap: 8px; }
.cs-action-group + .cs-action-group { padding-top: 12px; border-top: 1px solid var(--rk-line); }
.cs-action-group small { color: var(--rk-ink-soft); font-size: .78rem; line-height: 1.45; text-align: start; }
.cs-action-error, .cs-panel-error { margin: 0; color: var(--rk-danger, #b9473f); font-size: .78rem; line-height: 1.45; }
/* #225: facts about the user's own book, stated above the two doors so the choice between growing
   this book and starting the next one rests on evidence. Replaced a dialog that asked the user to
   classify a story they had not written yet. Quiet by default — it informs, never competes. */
.cs-story-state { display: grid; gap: 4px; padding: 10px 12px; border-radius: 10px; background: var(--rk-surface); }
.cs-story-state > strong { color: var(--rk-ink-soft); font-size: .72rem; letter-spacing: .02em; text-transform: uppercase; }
.cs-story-state-line { margin: 0; color: var(--rk-ink); font-size: .8rem; line-height: 1.5; }
.cs-story-state-line > span { margin-inline-end: 6px; color: var(--rk-ink-soft); font-weight: 700; }
.cs-story-state-line.is-wrapped { color: var(--rk-ink-soft); }
/* The irreversibility warning from the retired dialog: same sentence, now under the button that
   causes it, and set apart from the button's ordinary hint. */
.cs-seal-note { padding-inline-start: 9px; border-inline-start: 2px solid var(--rk-line-strong, var(--rk-line)); font-size: .74rem; }
/* Sealing a book waits on the settlement model — the pressed button counts the seconds, and a
   failure offers the retry right where the error is read (never a dead end). */
.cs-action-retry { padding: 0; border: 0; background: none; color: var(--rk-emerald-hover); font: inherit; font-weight: 700; text-decoration: underline; cursor: pointer; }
.cs-panel-actions em { margin-inline-start: 6px; font-style: normal; opacity: .75; }
.cs-sequel-note { grid-column: 1 / -1; display: flex; gap: 10px; align-items: center; justify-content: center; margin: 8px 0 0; min-height: 48px; padding: 10px 14px; border: 1px solid #8acdbb; border-radius: 9px; background: rgba(244, 251, 247, .78); color: #5f625e; font-size: .82rem; line-height: 1.4; text-align: center; }
.cs-sequel-note b { color: #249a7e; font-size: 1.1rem; }
.cs-secondary { display: inline-flex; width: 100%; min-height: 52px; padding: 10px 16px; align-items: center; justify-content: center; border: 1px solid var(--rk-emerald); border-radius: 10px; background: var(--rk-surface); color: var(--rk-emerald-hover); font-weight: 800; font-size: .98rem; cursor: pointer; }
.cs-secondary:disabled { opacity: 1; cursor: not-allowed; }
.cs-secondary b { margin-inline-end: 10px; font-size: 1.4rem; font-weight: 400; }
/* Grow-a-chapter row (rule 丙): a quieter third action — hairline border, ink text; the sealed
   state keeps the button visible but off, with the reason underneath. */
.cs-tertiary { display: inline-flex; width: 100%; min-height: 46px; padding: 8px 16px; align-items: center; justify-content: center; border: 1px solid var(--rk-line-strong, var(--rk-line)); border-radius: 10px; background: var(--rk-surface); color: var(--rk-ink); font-weight: 700; font-size: .94rem; text-decoration: none; cursor: pointer; }
.cs-tertiary b { margin-inline-end: 10px; font-size: 1.25rem; font-weight: 400; }
.cs-tertiary:disabled { opacity: .45; cursor: not-allowed; }
.cs-action-group.is-sealed small { color: var(--rk-ink-soft); }
/* Rename pencil: rides inside the series heading, ink-soft until hovered so it never competes with
   the name it edits. Stays inline-baseline so a wrapped two-line title keeps it beside the last word. */
.cs-rename-link { display: inline-flex; margin-inline-start: 8px; padding: 2px; align-items: center; justify-content: center; border: 0; border-radius: 6px; background: transparent; color: var(--rk-ink-soft); cursor: pointer; vertical-align: baseline; }
.cs-rename-link svg { width: 15px; height: 15px; stroke-width: 1.7; }
.cs-rename-link:hover { color: var(--rk-ink); background: var(--rk-surface-sunken, transparent); }
.cs-rename-link:disabled { opacity: .4; cursor: not-allowed; }
/* Series-zone door (T10 merge): a quiet rail action, anchored at the FOOT of the directory — it
   belongs after the books it would join, not between the series name and the first book. */
.cs-merge-link { display: flex; width: calc(100% - 16px); min-height: 42px; margin: 2px 8px 10px; padding: 8px 14px; align-items: center; justify-content: center; gap: 8px; border: 1px dashed var(--rk-line-strong, var(--rk-line)); border-radius: var(--rk-radius); background: transparent; color: var(--rk-ink-soft); font: inherit; font-weight: 700; font-size: .84rem; cursor: pointer; }
.cs-rail > .cs-merge-link { flex: none; }
.cs-merge-link:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
/* Stage breadcrumb: says where in the series this chapter sits, in family words only. */
.cs-crumb { margin: 0 0 10px; color: var(--rk-ink-muted); font-size: .63rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.cs-merge-link:hover { color: var(--rk-ink); border-style: solid; }
.cs-merge-link b { font-size: 1.15rem; font-weight: 400; }
.cs-merge-option { display: flex; align-items: center; gap: 12px; padding: 12px 14px; margin-block-end: 8px; border: 1px solid var(--rk-line); border-radius: 10px; cursor: pointer; }
.cs-merge-option:has(input:checked) { border-color: var(--rk-emerald); }
.cs-merge-option span { display: flex; flex-direction: column; }
.cs-merge-option small { color: var(--rk-ink-soft); }
.cs-choice-list { display: grid; gap: 12px; margin-top: 24px; }
.cs-choice-option { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 18px; border: 1px solid var(--rk-line); border-radius: 16px; background: var(--rk-surface); color: var(--rk-ink); text-align: start; cursor: pointer; }
.cs-choice-option:hover { border-color: color-mix(in srgb, var(--rk-emerald) 58%, var(--rk-line)); transform: translateY(-1px); }
.cs-choice-option.is-recommended { border-color: color-mix(in srgb, var(--rk-emerald) 62%, var(--rk-line)); background: color-mix(in srgb, var(--rk-emerald) 7%, var(--rk-surface)); }
.cs-choice-option > span:last-child { color: var(--rk-emerald); font-size: 1.8rem; line-height: 1; }
.cs-choice-copy { min-width: 0; display: grid; gap: 5px; }
.cs-choice-copy strong { font-size: 1.05rem; }
.cs-choice-copy small { color: var(--rk-ink-soft); line-height: 1.5; }
.cs-choice-copy em { color: var(--rk-warn, #b35a2d); font-size: .82rem; font-style: normal; line-height: 1.45; }
.cs-choice-badge { width: max-content; padding: 3px 8px; border-radius: 999px; background: color-mix(in srgb, var(--rk-emerald) 14%, transparent); color: var(--rk-emerald); font-size: .72rem; font-weight: 850; }
.cs-merge-hint { color: var(--rk-ink-soft); font-size: .92rem; }
.cs-merge-working { display: flex; align-items: center; gap: 8px; color: var(--rk-emerald-hover); font-weight: 600; }
/* Memory card foreword (rule 丙): tells the author what saving means, in family words. */
.cs-memory-foreword { color: var(--rk-ink-soft); font-size: .9rem; line-height: 1.7; border-block-start: 1px solid var(--rk-line); padding-block-start: 10px; }
.cs-summary { width: 100%; margin: 0; padding-bottom: 30px; border-bottom: 1px solid var(--rk-line); }
.cs-summary h3, .cs-status h3 { margin: 0 0 22px; font-size: 1.18rem; }
.cs-summary p { max-width: 64ch; margin: 0 0 16px; color: var(--rk-ink); line-height: 1.8; font-size: 1rem; }
/* The author's pasted source, folded to two lines by default (2026-08-17). Arriving here automatically
   MEANS the paste was longer than one book holds, so printing it in full put the only forward button
   below the fold on every screen size we measured. `.has-overflow` is written by syncSourceFold after
   layout, because CSS cannot tell whether two lines already showed the whole thing — and a button
   offering to unfold nothing is a worse lie than no button at all. */
.cs-user-input p { white-space: pre-wrap; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.cs-user-input.is-expanded p { display: block; overflow: visible; }
.cs-source-toggle { display: none; margin-block-start: 12px; padding: 0; border: 0; background: none; color: var(--rk-emerald-hover); font: inherit; font-size: .84rem; font-weight: 700; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.cs-user-input.has-overflow .cs-source-toggle { display: inline-flex; }
.cs-source-toggle:hover { color: var(--rk-ink); }
.cs-source-toggle:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 3px; border-radius: 4px; }
.cs-source { margin: 26px 0 18px; padding: 20px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-paper); }
.cs-source p { margin: 0 0 8px; font-weight: 800; }
.cs-source div { display: flex; gap: 8px; align-items: center; color: var(--rk-ink-soft); }
.cs-source div svg { width: 16px; color: var(--rk-emerald-hover); }
.cs-source blockquote { margin: 12px 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5; overflow: hidden; white-space: pre-line; line-height: 1.75; }
.cs-complete { display: flex; align-items: center; gap: 10px; color: var(--rk-emerald-hover); font-size: 1.05rem; }
.cs-complete svg { width: 22px; }
.cs-primary { display: inline-flex; justify-content: center; align-items: center; gap: 10px; min-height: 54px; border: 0; border-radius: 10px; padding: 10px 24px; background: var(--rk-emerald); color: white; font-size: 1rem; font-weight: 800; text-decoration: none; box-shadow: 0 8px 18px rgba(8,161,119,.12); cursor: pointer; }
.cs-actions .cs-primary { width: 100%; }
.cs-primary:disabled { opacity: .55; }
.cs-sequence-note { margin: 0; font-size: .86rem; }
.cs-status { width: 100%; padding-top: 28px; }
.cs-heading-with-info { display: flex; align-items: center; gap: 9px; margin-bottom: 22px; }
.cs-heading-with-info h3 { margin: 0; }
.cs-info-wrap { position: relative; display: inline-flex; }
.cs-info-trigger { display: grid; place-items: center; width: 21px; height: 21px; padding: 0; border: 1px solid var(--rk-line); border-radius: 50%; background: var(--rk-paper-2); color: var(--rk-ink-soft); font-size: .78rem; font-weight: 850; cursor: help; }
.cs-info-trigger:hover, .cs-info-trigger:focus-visible, .cs-info-wrap.is-open .cs-info-trigger { border-color: var(--rk-emerald); color: var(--rk-emerald-hover); outline: none; }
.cs-info-tooltip { position: absolute; z-index: 5; left: 50%; bottom: calc(100% + 10px); width: min(320px, calc(100vw - 48px)); padding: 11px 13px; border: 1px solid var(--rk-line); border-radius: 11px; background: var(--rk-ink); color: var(--rk-surface); font-size: .76rem; font-weight: 500; line-height: 1.5; opacity: 0; pointer-events: none; transform: translate(-50%, 4px); transition: opacity 140ms ease-out, transform 140ms ease-out; box-shadow: 0 12px 30px color-mix(in srgb, var(--rk-ink) 18%, transparent); }
.cs-info-wrap:hover .cs-info-tooltip, .cs-info-wrap:focus-within .cs-info-tooltip, .cs-info-wrap.is-open .cs-info-tooltip { opacity: 1; transform: translate(-50%, 0); }
.cs-status-line { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 13px; color: var(--rk-ink-soft); }
.cs-status-line span { display: grid; place-items: center; width: 28px; height: 28px; border: 2px solid var(--rk-emerald); border-radius: 50%; color: var(--rk-emerald); }
.cs-status-line span svg { width: 16px; }
.cs-status-line strong { color: #0a9b74; }
.cs-status-line i { width: 1px; height: 20px; background: #cbc7bf; }
/* The former `.cs-rail-compact` override set is gone (2026-07-27 tree refine): it existed to claw
   density back out of an over-large default, and its `.cs-chapter-cover { display:none }` silently
   turned the whole chapter-artwork path into dead code. The rail is now compact by default and
   density is chosen per book from its chapter count (`.cs-chapters[data-density]`). */
/* Chapter-series option B: the real Hub data keeps its left directory / right content topology.
   The right stage reads as one calm column; whichever real actions the API exposes remain in
   actionButtons() and settle at the bottom instead of interrupting the chapter overview. */
.cs-stage-reading { display: flex; flex-direction: column; }
.cs-stage-reading .cs-stage-grid {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 32px;
  min-height: 0;
  margin-block-start: 0;
}
.cs-stage-reading .cs-stage-body {
  width: min(100%, 1080px);
  max-width: none;
}
.cs-stage-reading .cs-summary p { max-width: none; }
.cs-stage-reading .cs-summary {
  padding-block-end: 0;
  border-block-end: 0;
}
/* The book's ending moved OUT of the action panel and INTO the body, where it is content rather
   than a footnote: reading measure, reading size, its own heading. */
.cs-stage-body .cs-story-state { gap: 10px; padding: 0; background: transparent; }
.cs-stage-body .cs-story-state > strong { font-size: .75rem; letter-spacing: .08em; }
.cs-stage-body .cs-story-state-line { max-width: 68ch; font-size: .98rem; line-height: 1.75; }
.cs-stage-body .cs-story-state-line.is-ending { color: var(--rk-ink); }
.cs-stage-body .cs-story-state-line > span { display: block; margin-block-end: 3px; font-size: .74rem; letter-spacing: .04em; text-transform: uppercase; }
/* Nothing to show is said plainly, without a heading that promises an overview it does not have. */
.cs-body-note { max-width: 68ch; margin: 0; color: var(--rk-ink-soft); font-size: .92rem; line-height: 1.7; }
/* The action zone was a 3-column grid sized for TWO actions. Rule 丙 later added a third (the
   grow-a-chapter door) and it fell to a second row, first column — reading as stranded. It is a
   plain block now: primary and secondary share one row, the weak action owns a quiet row below,
   and every hint/warning lives under the button that causes it. Any 1/2/3 combination holds. */
.cs-stage-reading .cs-actions {
  flex: none;
  position: static;
  order: initial;
  display: block;
  width: 100%;
  margin-block-start: 20px;
  padding: 20px 0 0;
  border: 0;
  border-block-start: 1px solid var(--rk-line);
  background: transparent;
}
/* Only the footers stay fixed. Titles belong to the readable content, so each side gets one large
   scrollport that starts at the card top and ends above its footer. Keeping the title outside this
   scrollport squeezed the source to a 78px slot on a real seven-chapter page. */
@media (min-width: 901px) {
  .cs-page:not(.is-single) .cs-workbench {
    height: var(--cs-workbench-height, calc(100vh - 122px));
    min-height: 0;
    align-items: stretch;
  }
  .cs-page:not(.is-single) .cs-rail {
    display: flex;
    flex-direction: column;
    align-self: stretch;
    min-height: 0;
    max-height: none;
  }
  .cs-page:not(.is-single) .cs-rail-scroll { flex: 1; }
  .cs-stage-reading { height: 100%; min-height: 0; max-height: none; overflow: hidden; }
  .cs-stage-reading .cs-stage-grid {
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-inline-end: 8px;
    scrollbar-gutter: stable;
  }
  .cs-stage-reading .cs-stage-body { flex: none; min-height: auto; overflow: visible; padding-inline-end: 0; }
}
/* Below that the workbench is one column: the directory sits ON TOP of the stage, so bounding the
   stage to the viewport would nest a second scroller inside the page's own. Here the page scrolls and
   the actions ride along its bottom edge instead. `overflow: visible` is the price of admission —
   the stage's own `overflow: auto` would otherwise capture the sticky and pin it to a box that never
   scrolls (the same trap the desktop half had to be dug out of). */
@media (max-width: 900px) {
  .cs-stage-reading { overflow: visible; }
  .cs-stage-reading .cs-stage-grid {
    flex: none;
    overflow: visible;
    padding-inline-end: 0;
    scrollbar-gutter: auto;
  }
  .cs-stage-reading .cs-actions {
    position: sticky;
    bottom: 0;
    margin-block-start: 24px;
    padding-block-end: 14px;
    background: var(--rk-surface);
  }
}
/* Actions grouped by WHAT THEY ACT ON. Each set names itself, and within a set every button sits on
   the left with its explanation beside it — so the eye reads "button, what it does" on one line
   instead of hunting for a caption underneath. */
.cs-action-set { margin-block-start: 18px; }
.cs-action-set + .cs-action-set { margin-block-start: 20px; padding-block-start: 18px; border-block-start: 1px solid var(--rk-line); }
.cs-action-label { margin: 0 0 12px; color: var(--rk-ink-muted); font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; }
.cs-action-set .cs-action-group { display: grid; grid-template-columns: minmax(180px, 300px) minmax(0, 1fr); gap: 8px 18px; align-items: center; padding: 0; border: 0; }
.cs-action-set .cs-action-group + .cs-action-group { margin-block-start: 12px; padding: 0; border: 0; }
.cs-action-set .cs-action-group > small { align-self: center; margin: 0; }
/* Two doors into the same chapter start (one-click / step-by-step). They occupy the group's single
   button cell so the hint keeps its own column; below ~200px of cell they stack instead of shrinking
   past readability. Weight (primary vs secondary) is decided in markup, not here. */
.cs-start-doors { display: flex; flex-wrap: wrap; gap: 8px; }
.cs-start-doors > button { flex: 1 1 130px; min-width: 0; }
.cs-action-set .cs-action-error { grid-column: 1 / -1; }
.cs-panel-error { margin-block-start: 12px; padding: 10px 12px; border-radius: 9px; background: color-mix(in srgb, var(--rk-danger, #b9473f) 7%, transparent); }
/* The irreversibility warning belongs to the whole series set, not to one button's caption slot. */
.cs-action-set .cs-seal-note { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 9px; align-items: start; margin-block-start: 14px; padding: 0; border: 0; color: var(--rk-ink-soft); font-size: .78rem; line-height: 1.55; }
.cs-action-set .cs-seal-note::before { content: 'i'; display: grid; place-items: center; width: 16px; height: 16px; margin-block-start: 2px; border: 1px solid var(--rk-ink-muted); border-radius: 50%; font-size: .62rem; font-weight: 800; font-style: italic; }
.cs-next-action strong, .cs-next-action p { margin: 0; }
.cs-next-action p { margin-top: 4px; color: var(--rk-ink-soft); font-size: .86rem; }
.cs-next-action span { color: var(--rk-emerald-hover); font-size: .8rem; font-weight: 800; }
.cs-loading { min-height: calc(100vh - 40px); display: grid; place-items: center; align-content: center; gap: 10px; text-align: center; }
.cs-loading img { width: 150px; border-radius: 28px; }
.cs-loading h1 { margin: 4px 0 0; font-size: clamp(1.7rem, 3vw, 2.5rem); }
.cs-loading p { margin: 0; color: var(--rk-ink-soft); }
.cs-loading .cs-elapsed { color: var(--rk-emerald-hover); font-weight: 800; font-variant-numeric: tabular-nums; }
@media (max-width: 1320px) {
  .cs-brand { display: none; }
  .cs-workbench { grid-template-columns: 330px minmax(0, 1fr); }
  .cs-stage-grid { grid-template-columns: 1fr; gap: 28px; }
  .cs-actions { position: static; grid-template-columns: repeat(2, minmax(0, 1fr)); order: -1; }
  .cs-actions-heading, .cs-story-state { grid-column: 1 / -1; }
  .cs-actions:not(.has-secondary) .cs-action-group { grid-column: 1 / -1; }
  .cs-action-group + .cs-action-group { padding-top: 0; padding-inline-start: 12px; border-top: 0; border-inline-start: 1px solid var(--rk-line); }
  /* The reading stage keeps its own block layout at every width — it never inherits the 2-col grid. */
  .cs-stage-reading .cs-actions { display: block; order: initial; }
  .cs-stage-reading .cs-actions-row .cs-action-group + .cs-action-group { padding-inline-start: 0; border-inline-start: 0; }
}
@media (max-width: 900px) {
  /* The spread folds shut: book on top, then its state and actions. The divider becomes horizontal. */
  .cs-spread { grid-template-columns: 1fr; gap: 24px; }
  .cs-spread-book { padding-inline-end: 0; padding-block-end: 24px; border-inline-end: 0; border-block-end: 1px solid var(--rk-line); }
  .cs-spread-cover { width: clamp(150px, 42vw, 200px); }
  .cs-action-set .cs-action-group { grid-template-columns: 1fr; gap: 6px; }
  .cs-workbench { min-height: 0; grid-template-columns: 1fr; }
  /* Stacked: the rail is a lid over the stage, so it is capped rather than content-sized. */
  .cs-rail { align-self: stretch; max-height: 44vh; }
  .cs-stage { min-height: 580px; }
}
@media (max-width: 760px) {
  .sb-cards--two:has(> :nth-child(3)) { grid-template-columns: 1fr; }
  .cs-page { padding: 12px; }
  .cs-head { margin-bottom: 12px; }
  .cs-head-start > strong { display:none; }
  .cs-home { width: 44px; height: 44px; }
  .cs-memory-link { max-width: 210px; }
  .cs-memory-link small { display: none; }
  .cs-series-summary { grid-template-columns: 52px minmax(0, 1fr); padding: 16px; }
  .cs-series-cover { width: 52px; height: 68px; }
  /* Touch has no hover, so the door is always up. It goes back INTO flow here and is allowed to wrap
     onto its own line rather than overlaying the title — vertical space is the cheap axis on a phone,
     and a tap target that sits on top of the text it describes is the worse trade. */
  .cs-chapter { min-height: 52px; }
  .cs-chapter-door { position: static; transform: none; opacity: 1; pointer-events: auto; max-width: none; margin-inline-start: auto; padding: 7px 14px; }
  .cs-chapter:hover .cs-chapter-text, .cs-chapter:focus-within .cs-chapter-text { padding-inline-end: 0; }
  .cs-chapters[data-density="tight"] .cs-chapter { min-height: 48px; }
  .cs-stage { min-height: 0; padding: 24px 18px 30px; }
  .cs-stage h2 { font-size: clamp(1.75rem, 9vw, 2.25rem); }
  .cs-stage-head { padding-bottom: 22px; }
  .cs-stage-grid { margin-top: 24px; }
  .cs-actions { width: 100%; grid-template-columns: 1fr; padding: 16px; }
  .cs-actions-heading, .cs-story-state, .cs-actions:not(.has-secondary) .cs-action-group { grid-column: 1; }
  .cs-action-group + .cs-action-group { padding-top: 12px; padding-inline-start: 0; border-top: 1px solid var(--rk-line); border-inline-start: 0; }
  .cs-stage-reading .cs-actions {
    grid-template-columns: 1fr;
    padding: 16px 0 0;
  }
  .cs-stage-reading .cs-actions-heading,
  .cs-stage-reading .cs-story-state,
  .cs-stage-reading .cs-action-group,
  .cs-stage-reading .cs-actions:not(.has-secondary) .cs-action-group { grid-column: 1; }
  .cs-stage-reading .cs-action-group + .cs-action-group {
    padding-block-start: 12px;
    padding-inline-start: 0;
    border-block-start: 1px solid var(--rk-line);
    border-inline-start: 0;
  }
  .cs-primary, .cs-secondary { width: 100%; }
  .cs-meta i, .cs-status-line i { display: none; }
  .cs-memory-overview, .cs-memory-columns, .cs-memory-people { grid-template-columns: 1fr; }
  .cs-info-tooltip { inset-inline-start: 0; transform: translate(0, 4px); }
  .cs-info-wrap:hover .cs-info-tooltip, .cs-info-wrap:focus-within .cs-info-tooltip, .cs-info-wrap.is-open .cs-info-tooltip { transform: translate(0, 0); }
}

.sb-choice-card {
  min-height: 116px;
  padding-block-start: 18px;
}

.sb-choice-card.is-recommended {
  padding-block-start: 38px;
}

.sb-card {
  position: relative;
  display: grid;
  gap: 6px;
  text-align: start;
  align-content: start;
  min-height: 108px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: rgba(255, 255, 255, 0.66);
  padding: 14px;
  transition: border-color 180ms ease-out, background 180ms ease-out, transform 180ms ease-out;
}

.sb-card.is-recommended {
  border-color: var(--rk-emerald);
  background: color-mix(in srgb, var(--rk-emerald-soft) 54%, var(--rk-surface));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--rk-emerald) 12%, transparent);
}

.sb-card-recommend {
  position: absolute;
  inset-block-start: 10px;
  inset-inline-end: 10px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  padding: 3px 8px;
  font-size: 0.7rem;
  font-weight: 900;
  line-height: 1.2;
}

.sb-card-reason {
  margin-block-start: auto;
  color: var(--rk-emerald-hover);
  font-size: 0.78rem;
  font-weight: 800;
  line-height: 1.35;
}

.sb-card:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  transform: translateY(-2px);
}

.sb-card-tag {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  border-radius: 999px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding-inline: 9px;
}

.sb-card-title {
  font-size: 1rem;
  font-weight: 800;
}

.sb-card-note {
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.4;
}

.sb-sheet-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}

.sb-photo-cast-result {
  width: 100%;
  min-height: 104px;
  display: grid;
  grid-template-columns: minmax(76px, auto) minmax(0, 1fr) auto;
  align-items: center;
  gap: 18px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: rgba(255, 255, 255, 0.58);
  padding: 14px 54px 14px 16px;
  text-align: start;
}

.sb-photo-cast-previews {
  display: flex;
  align-items: center;
  padding-inline-end: 6px;
}

.sb-photo-cast-thumb {
  position: relative;
  width: 68px;
  height: 68px;
  flex: 0 0 68px;
  margin: 0;
  border: 3px solid var(--rk-surface);
  border-radius: 16px;
  overflow: hidden;
  background: var(--rk-paper-2);
  box-shadow: 0 8px 18px -12px rgba(43, 42, 38, 0.7);
}

.sb-photo-cast-result.is-multiple .sb-photo-cast-thumb + .sb-photo-cast-thumb {
  margin-inline-start: -18px;
}

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

.sb-photo-cast-thumb figcaption {
  position: absolute;
  inset-inline-end: 4px;
  inset-block-end: 4px;
  min-width: 20px;
  height: 20px;
  display: grid;
  place-items: center;
  border: 2px solid var(--rk-surface);
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-size: 0.68rem;
  font-weight: 900;
  line-height: 1;
}

.sb-image-safety-result {
  min-inline-size: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 18px;
  padding-inline-end: 36px;
  text-align: start;
}

.sb-safety-previews {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sb-safety-thumb {
  width: 82px;
  margin: 0;
  display: grid;
  gap: 5px;
}

.sb-safety-thumb img {
  width: 76px;
  height: 76px;
  display: block;
  border: 1px solid color-mix(in srgb, var(--rk-danger) 45%, var(--rk-line));
  border-radius: var(--rk-radius-sm);
  object-fit: cover;
}

.sb-safety-thumb figcaption {
  overflow-wrap: anywhere;
  color: var(--rk-danger);
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1.25;
}

.sb-safety-kept {
  margin: 4px 0 0;
  color: var(--rk-good);
  font-size: 0.8rem;
  font-weight: 800;
}

.sb-sheet-actions--safety {
  justify-content: flex-end;
  flex-wrap: nowrap;
}

.sb-sheet-actions--safety .sb-sheet-secondary {
  min-height: 48px;
  border-radius: 999px;
  padding-inline: 20px;
  white-space: nowrap;
}

.sb-image-prepare-list {
  min-inline-size: 0;
  display: grid;
  gap: 12px;
}

.sb-image-prepare-card {
  min-inline-size: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 18px;
  padding-block: 10px;
  padding-inline-end: 36px;
  border-block-end: 1px solid var(--rk-line);
  text-align: start;
}

.sb-image-prepare-card:last-child {
  border-block-end: 0;
}

.sb-image-prepare-previews {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sb-image-prepare-thumb {
  width: 82px;
  margin: 0;
  display: grid;
  gap: 5px;
}

.sb-image-prepare-thumb img {
  width: 76px;
  height: 76px;
  display: block;
  border: 1px solid color-mix(in srgb, var(--rk-line-strong) 60%, var(--rk-line));
  border-radius: var(--rk-radius-sm);
  object-fit: cover;
}

.sb-image-prepare-thumb figcaption {
  overflow-wrap: anywhere;
  color: var(--rk-ink-soft);
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1.25;
}

.sb-image-prepare-actions {
  justify-content: flex-end;
  flex-wrap: nowrap;
}

.sb-image-prepare-actions .sb-sheet-secondary {
  min-height: 48px;
  border-radius: 999px;
  padding-inline: 20px;
  white-space: nowrap;
}

.sb-photo-cast-role {
  position: absolute;
  inset-inline: 4px;
  inset-block-start: 4px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(31, 34, 31, 0.76);
  color: #fff;
  font-size: 0.58rem;
  font-weight: 800;
  line-height: 1.2;
  padding: 3px 6px;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-photo-cast-copy {
  min-width: 0;
  display: grid;
  gap: 5px;
}

.sb-photo-cast-copy .sb-sheet-title,
.sb-photo-cast-copy .sb-sheet-note {
  padding-inline: 0;
  text-align: start;
}

.sb-photo-cast-copy .sb-sheet-note {
  margin: 0;
  line-height: 1.45;
}

.sb-photo-cast-result .sb-sheet-actions {
  flex-wrap: nowrap;
}

.sb-photo-cast-result .sb-sheet-primary {
  white-space: nowrap;
}

.sb-sheet-primary {
  min-height: 48px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-weight: 800;
  padding-inline: 24px;
  cursor: pointer;
  transition: background 180ms ease-out;
}

.sb-sheet-primary:hover {
  background: var(--rk-emerald-hover);
}

[data-requires-consent].is-consent-locked {
  cursor: pointer;
  opacity: 0.68;
}

.sb-sheet-primary.is-consent-locked,
.sb-sheet-primary.is-consent-locked:hover {
  border: 1px solid var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  opacity: 1;
}

.sb-sheet-actions--choice {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  width: min(440px, 100%);
  margin-inline: auto;
}

.sb-sheet-actions--choice > button {
  width: 100%;
  min-height: 44px;
  padding: 10px 18px;
  border-radius: 999px;
  font-weight: 800;
  line-height: 1.2;
}

.sb-sheet-secondary {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
  transition: border-color 180ms ease-out, background 180ms ease-out, color 180ms ease-out;
}

.sb-sheet-secondary:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-sheet-correction {
  justify-self: center;
  min-height: 38px;
  padding: 8px 16px;
  border-radius: 999px;
  font-weight: 800;
}

@media (max-width: 560px) {
  .sb-cards--two,
  .sb-cards--bible:has(> :nth-child(4)),
  .sb-sheet-actions--choice {
    grid-template-columns: 1fr;
  }

  .sb-photo-cast-result {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 12px;
    padding: 16px;
    text-align: center;
  }

  .sb-intake-sheet {
    max-block-size: min(62vh, 520px);
    padding-inline: 14px;
  }

  .sb-image-safety-result {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 12px;
    padding: 30px 2px 0;
    text-align: center;
  }

  .sb-image-safety-result .sb-photo-cast-copy,
  .sb-image-safety-result .sb-sheet-title,
  .sb-image-safety-result .sb-sheet-note {
    text-align: center;
  }

  .sb-sheet-actions--safety {
    width: 100%;
    display: grid;
    grid-template-columns: 1fr;
  }

  .sb-sheet-actions--safety > button {
    width: 100%;
  }

  .sb-image-prepare-card {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 12px;
    padding: 30px 2px 10px;
    text-align: center;
  }

  .sb-image-prepare-card .sb-photo-cast-copy,
  .sb-image-prepare-card .sb-sheet-title,
  .sb-image-prepare-card .sb-sheet-note {
    text-align: center;
  }

  .sb-image-prepare-actions {
    width: 100%;
    display: grid;
    grid-template-columns: 1fr;
  }

  .sb-image-prepare-actions > button {
    width: 100%;
  }

  .sb-photo-cast-copy .sb-sheet-title,
  .sb-photo-cast-copy .sb-sheet-note {
    text-align: center;
  }

  .sb-photo-cast-result .sb-sheet-actions,
  .sb-photo-cast-result .sb-sheet-primary {
    width: 100%;
  }
}

.sb-escape {
  border: 0;
  background: transparent;
  color: var(--rk-ink-soft);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 6px 2px;
  transition: color 150ms ease-out;
}

.sb-escape:hover {
  color: var(--rk-ink);
}

.sb-dims {
  width: min(830px, 100%);
  display: grid;
  gap: 8px;
  margin-block-start: -4px;
}

.sb-dims[hidden],
.sb-cast-btn[hidden],
.sb-tool-btn[hidden],
.fs-home-media[hidden],
.fs-home-panel[hidden],
.rk-shelf-section[hidden] {
  display: none;
}

.fs-home-media {
  inline-size: min(830px, 100%);
}

.fs-home-media {
  margin-block-start: -2px;
  padding: 5px;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  background: var(--rk-paper-2);
}

.fs-home-media-track {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}

.fs-home-media-tab {
  min-block-size: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  border: 1px solid transparent;
  border-radius: 12px;
  background: transparent;
  color: var(--rk-ink-soft);
  font-size: .92rem;
  font-weight: 800;
  transition: border-color 160ms ease-out, background 160ms ease-out, color 160ms ease-out;
}

.fs-home-media-tab svg {
  inline-size: 20px;
  block-size: 20px;
  stroke-width: 1.7;
}

.fs-home-media-tab:hover {
  color: var(--rk-ink);
}

.fs-home-media-tab.is-active {
  border-color: var(--rk-card-hover-border);
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  box-shadow: var(--rk-shadow-card);
}

.fs-home-panel {
  inline-size: min(1000px, 100%);
  display: grid;
  gap: 18px;
  margin-block-start: -4px;
  text-align: start;
}

@media (min-width: 1450px) and (max-width: 1679px) {
  .fs-home-panel {
    inline-size: min(1080px, 100%);
  }
}

@media (min-width: 1680px) {
  .fs-home-panel {
    inline-size: min(1180px, 100%);
  }
}

html[lang="ar"] .fs-home-panel {
  direction: rtl;
}

.fs-home-capabilities {
  inline-size: min(830px, 100%);
  justify-self: center;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.fs-home-capability {
  min-inline-size: 0;
  min-block-size: 82px;
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  color: var(--rk-ink);
  padding: 13px 14px;
  text-align: start;
  box-shadow: var(--rk-shadow-card);
  transition: border-color 160ms ease-out, translate 160ms ease-out;
}

.fs-home-capability:hover {
  border-color: var(--rk-card-hover-border);
  translate: 0 -1px;
}

.fs-home-capability-icon {
  inline-size: 38px;
  block-size: 38px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.fs-home-capability-icon svg {
  inline-size: 20px;
  block-size: 20px;
}

.fs-home-capability strong,
.fs-home-capability small {
  display: block;
}

.fs-home-capability strong {
  font-size: .92rem;
}

.fs-home-capability small {
  margin-block-start: 4px;
  color: var(--rk-ink-soft);
  font-size: .76rem;
  line-height: 1.35;
}

.fs-studio {
  min-inline-size: 0;
  display: grid;
  gap: 14px;
  padding-block-start: 18px;
  border-block-start: 1px solid var(--rk-line);
}

.fs-studio-head {
  min-inline-size: 0;
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 18px;
}

.fs-studio-head > span {
  min-inline-size: 0;
}

.fs-studio-head h2,
.fs-studio-head p,
.fs-studio-gallery-head h3 {
  margin: 0;
}

.fs-studio-head h2 {
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: clamp(1.65rem, 2.7vw, 2.2rem);
  line-height: 1.08;
}

.fs-studio-head p {
  margin-block-start: 4px;
  color: var(--rk-ink-soft);
  font-size: 1rem;
  line-height: 1.45;
}

.fs-studio-all {
  min-block-size: 40px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  padding-inline: 15px;
  font-weight: 800;
  text-decoration: none;
  transition: border-color 160ms ease-out, color 160ms ease-out;
}

.fs-studio-all:hover,
.fs-studio-all:focus-visible {
  border-color: var(--rk-card-hover-border);
  color: var(--rk-emerald-hover);
}

.fs-studio-all svg {
  inline-size: 17px;
  block-size: 17px;
  transform: scaleX(-1);
}

.fs-studio-featured {
  min-inline-size: 0;
  min-block-size: 252px;
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(250px, .82fr);
  gap: 20px;
  align-items: stretch;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-surface);
  color: var(--rk-ink);
  padding: 12px;
  text-align: start;
  box-shadow: var(--rk-shadow-card);
  transition: border-color 180ms ease-out, box-shadow 180ms ease-out, translate 180ms ease-out;
}

.fs-studio-featured:hover,
.fs-studio-featured:focus-visible {
  border-color: var(--rk-card-hover-border);
  box-shadow: var(--rk-shadow-panel);
  translate: 0 -2px;
}

.fs-studio-featured:focus-visible,
.fs-studio-card:focus-visible,
.fs-studio-all:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 3px;
}

.fs-studio-featured-frame,
.fs-studio-card-frame {
  min-inline-size: 0;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  box-shadow: inset 0 0 0 8px var(--rk-surface);
}

.fs-studio-featured-frame {
  min-block-size: 226px;
  display: grid;
  place-items: center;
  border-radius: calc(var(--rk-radius-lg) - 6px);
  padding: 13px;
}

.fs-studio-featured-media,
.fs-studio-card-media {
  inline-size: 100%;
  block-size: 100%;
  min-inline-size: 0;
  display: block;
  object-fit: contain;
}

.fs-studio-featured-media.is-placeholder,
.fs-studio-card-media.is-placeholder {
  display: grid;
  place-items: center;
  color: var(--rk-emerald-hover);
}

/* The rules above set `display` on the same elements the error handler toggles `hidden` on, and an
   author `display` beats the UA sheet's `[hidden] { display: none }`. Without this the "failed"
   placeholder and the broken cover would both stay on screen. Same guard as .works-media-fallback. */
.fs-studio-featured-media[hidden],
.fs-studio-card-media[hidden] {
  display: none;
}

.fs-studio-featured-media.is-placeholder svg {
  inline-size: 58px;
  block-size: 58px;
  stroke-width: 1.35;
}

.fs-studio-featured-copy {
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  padding-block: 16px;
  padding-inline-end: 14px;
}

.fs-studio-kicker {
  margin-block-end: 8px;
  color: var(--rk-emerald-hover);
  font-size: .78rem;
  font-weight: 900;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.fs-studio-featured-copy > strong {
  max-inline-size: 100%;
  overflow: hidden;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: clamp(1.45rem, 2.5vw, 2rem);
  line-height: 1.16;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.fs-studio-featured-copy > small {
  margin-block-start: 9px;
  color: var(--rk-ink-soft);
  font-size: .9rem;
  line-height: 1.45;
}

.fs-studio-open {
  min-block-size: 44px;
  margin-block-start: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  padding-inline: 18px;
  font-weight: 900;
}

.fs-studio-open svg {
  inline-size: 18px;
  block-size: 18px;
  transform: scaleX(-1);
}

.fs-studio-gallery-head {
  min-inline-size: 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  margin-block-start: 6px;
}

.fs-studio-gallery-head h3 {
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1.2rem;
}

.fs-studio-gallery-head span {
  color: var(--rk-ink-soft);
  font-size: .82rem;
  font-weight: 800;
}

.fs-studio-gallery {
  min-inline-size: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}

.fs-studio-card {
  min-inline-size: 0;
  display: grid;
  grid-template-rows: auto minmax(72px, auto);
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  color: var(--rk-ink);
  padding: 8px;
  text-align: start;
  box-shadow: var(--rk-shadow-card);
  transition: border-color 160ms ease-out, translate 160ms ease-out;
}

.fs-studio-card:hover,
.fs-studio-card:focus-visible {
  border-color: var(--rk-card-hover-border);
  translate: 0 -2px;
}

.fs-studio-card-frame {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  border-radius: calc(var(--rk-radius) - 5px);
  padding: 9px;
}

.fs-studio-card-media.is-placeholder svg {
  inline-size: 38px;
  block-size: 38px;
  stroke-width: 1.4;
}

.fs-studio-card-copy {
  min-inline-size: 0;
  padding: 11px 7px 7px;
}

.fs-studio-card-copy strong,
.fs-studio-card-copy small {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fs-studio-card-copy strong {
  min-block-size: 2.7em;
  color: var(--rk-ink);
  font-size: .95rem;
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.fs-studio-card-copy small {
  margin-block-start: 6px;
  color: var(--rk-ink-soft);
  font-size: .8rem;
  white-space: nowrap;
}

.fs-studio-empty {
  min-block-size: 176px;
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  align-items: center;
  justify-content: center;
  gap: 24px;
  border: 1px dashed var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-surface);
  padding: 20px clamp(22px, 6vw, 72px);
}

.fs-studio-empty img {
  inline-size: 132px;
  block-size: 132px;
  object-fit: contain;
  filter: drop-shadow(0 10px 16px rgba(43, 42, 38, .12));
}

.fs-studio-empty span {
  min-inline-size: 0;
}

.fs-studio-empty strong,
.fs-studio-empty small {
  display: block;
}

.fs-studio-empty strong {
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1.35rem;
}

.fs-studio-empty small {
  margin-block-start: 7px;
  color: var(--rk-ink-soft);
  font-size: 1rem;
  line-height: 1.5;
}

.fs-studio-mascot {
  display: none;
}

/* Desktop keeps the latest work prominent without letting portrait art consume a full screen.
   Mobile is intentionally left to its existing, separate stacked treatment. */
@media (min-width: 721px) {
  .fs-studio-featured {
    position: relative;
    isolation: isolate;
    overflow: visible;
    block-size: clamp(320px, 36vh, 380px);
    min-block-size: 0;
    grid-template-columns: minmax(0, 520px) minmax(340px, 1fr);
    gap: 28px;
    border-color: var(--rk-card-hover-border);
    background: var(--rk-paper-2);
    padding: 18px 20px 20px;
    box-shadow: var(--rk-shadow-panel);
  }

  .fs-studio-featured::before {
    content: "";
    position: absolute;
    z-index: 0;
    inset: 10px;
    border: 1px dashed var(--rk-line);
    border-radius: calc(var(--rk-radius-lg) - 7px);
    pointer-events: none;
  }

  .fs-studio-featured::after {
    content: "";
    position: absolute;
    z-index: 0;
    inset-inline: 34px;
    block-size: 10px;
    inset-block-end: -7px;
    border: 1px solid var(--rk-line);
    border-radius: 0 0 8px 8px;
    background: var(--rk-paper-2);
    box-shadow: var(--rk-shadow-card);
    pointer-events: none;
  }

  .fs-studio-featured-frame {
    position: relative;
    z-index: 1;
    block-size: 100%;
    min-block-size: 0;
    overflow: visible;
    border-radius: 8px;
    background: var(--rk-surface);
    padding: 12px;
    box-shadow: var(--rk-shadow-panel);
    transform: rotate(-.55deg);
    transition: transform 360ms cubic-bezier(.2, .9, .3, 1.2), box-shadow 180ms ease-out;
  }

  .fs-studio-featured-frame::before {
    content: "";
    position: absolute;
    z-index: 3;
    inline-size: 76px;
    block-size: 20px;
    left: 50%;
    inset-block-start: -10px;
    border: 1px solid var(--rk-line);
    background: var(--rk-paper);
    opacity: .9;
    transform: translateX(-50%) rotate(1.5deg);
    pointer-events: none;
  }

  .fs-studio-featured-frame::after {
    content: "";
    position: absolute;
    z-index: 2;
    inset: 9px;
    border: 1px solid var(--rk-line);
    border-radius: 5px;
    pointer-events: none;
  }

  .fs-studio-featured-media {
    position: absolute;
    z-index: 1;
    inset: 12px;
    inline-size: calc(100% - 24px);
    block-size: calc(100% - 24px);
    border-radius: 4px;
    background: var(--rk-paper);
  }

  .fs-studio-featured-copy {
    position: relative;
    z-index: 1;
    align-self: center;
    margin-block: 12px;
    border: 1px solid var(--rk-line);
    border-radius: var(--rk-radius);
    background: var(--rk-surface);
    padding: 24px;
    box-shadow: var(--rk-shadow-card);
    transform: rotate(.35deg);
    transition: transform 360ms cubic-bezier(.2, .9, .3, 1.2), box-shadow 180ms ease-out;
  }

  .fs-studio-featured-copy::before {
    content: "";
    position: absolute;
    inline-size: 11px;
    block-size: 11px;
    inset-inline-end: 18px;
    inset-block-start: 17px;
    border: 3px solid var(--rk-emerald-soft);
    border-radius: 50%;
    background: var(--rk-emerald);
    box-shadow: var(--rk-shadow-card);
  }

  .fs-studio-featured:hover .fs-studio-featured-frame,
  .fs-studio-featured:focus-visible .fs-studio-featured-frame {
    box-shadow: var(--rk-shadow-panel);
    transform: rotate(-.1deg) translateY(-2px);
  }

  .fs-studio-featured:hover .fs-studio-featured-copy,
  .fs-studio-featured:focus-visible .fs-studio-featured-copy {
    box-shadow: var(--rk-shadow-panel);
    transform: rotate(0) translateY(-1px);
  }

  .fs-studio-open {
    margin-block-start: 16px;
  }

  .fs-studio-gallery {
    position: relative;
    isolation: isolate;
    gap: 18px;
    align-items: stretch;
    padding-block: 14px 18px;
  }

  .fs-studio-gallery::before {
    content: "";
    position: absolute;
    z-index: 0;
    inset-inline: 14px;
    inset-block-end: 8px;
    block-size: 10px;
    border: 1px solid var(--rk-line);
    border-radius: 0 0 8px 8px;
    background: var(--rk-paper-2);
    box-shadow: var(--rk-shadow-card);
    pointer-events: none;
  }

  .fs-studio-card {
    position: relative;
    z-index: 1;
    overflow: visible;
    border-radius: 8px;
    padding: 10px;
    box-shadow: var(--rk-shadow-panel);
    transform: rotate(-.35deg);
    transform-origin: 50% 100%;
    transition: border-color 180ms ease-out, box-shadow 180ms ease-out,
      transform 300ms cubic-bezier(.2, .9, .3, 1.2);
  }

  .fs-studio-card::before {
    content: "";
    position: absolute;
    z-index: 3;
    inline-size: 62px;
    block-size: 16px;
    left: 50%;
    inset-block-start: -8px;
    border: 1px solid var(--rk-line);
    background: var(--rk-paper);
    opacity: .88;
    transform: translateX(-50%) rotate(1.2deg);
    pointer-events: none;
  }

  .fs-studio-card:nth-child(3n + 2) {
    transform: rotate(.28deg);
  }

  .fs-studio-card:nth-child(3n) {
    transform: rotate(-.18deg);
  }

  .fs-studio-card:hover,
  .fs-studio-card:focus-visible {
    translate: none;
    box-shadow: var(--rk-shadow-panel);
    transform: translateY(-5px) rotate(0);
  }

  .fs-studio-card-frame {
    border-radius: 5px;
    background: var(--rk-paper-2);
    box-shadow: inset 0 0 0 7px var(--rk-surface);
  }

  .fs-studio-card-copy {
    margin-block-start: 9px;
    border-block-start: 1px solid var(--rk-line);
    padding: 11px 4px 5px;
  }
}

@media (min-width: 1180px) {
  .fs-studio-mascot {
    position: absolute;
    z-index: 3;
    display: block;
    inline-size: 112px;
    block-size: auto;
    inset-inline-end: -54px;
    inset-block-end: -7px;
    pointer-events: none;
    filter: drop-shadow(0 10px 14px rgba(43, 42, 38, .14));
    transform: rotate(-2deg);
    transform-origin: 50% 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .fs-studio-featured-frame,
  .fs-studio-featured-copy,
  .fs-studio-card {
    transition: none;
  }

  .fs-studio-featured:hover .fs-studio-featured-frame,
  .fs-studio-featured:focus-visible .fs-studio-featured-frame {
    transform: rotate(-.55deg);
  }

  .fs-studio-featured:hover .fs-studio-featured-copy,
  .fs-studio-featured:focus-visible .fs-studio-featured-copy {
    transform: rotate(.35deg);
  }

  .fs-studio-card:hover,
  .fs-studio-card:focus-visible {
    transform: none;
  }
}

[dir="rtl"] .fs-studio-all svg,
[dir="rtl"] .fs-studio-open svg,
html[lang="ar"] .fs-studio-all svg,
html[lang="ar"] .fs-studio-open svg {
  transform: none;
}

@media (max-width: 900px) {
  .fs-studio-featured {
    grid-template-columns: minmax(0, 1.2fr) minmax(220px, .8fr);
  }

  .fs-studio-gallery {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 720px) {
  .fs-studio-head {
    align-items: flex-start;
  }

  .fs-studio-featured {
    min-block-size: 0;
    grid-template-columns: 1fr;
    gap: 0;
  }

  .fs-studio-featured-frame {
    min-block-size: 0;
    aspect-ratio: 16 / 10;
  }

  .fs-studio-featured-copy {
    padding: 18px 10px 10px;
  }

  .fs-studio-open {
    align-self: stretch;
  }

  .fs-studio-gallery {
    grid-template-columns: 1fr;
  }

  .fs-studio-empty {
    grid-template-columns: 94px minmax(0, 1fr);
    gap: 16px;
    padding: 18px;
  }

  .fs-studio-empty img {
    inline-size: 94px;
    block-size: 94px;
  }
}

.sb-dim-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.sb-dim-label {
  flex: none;
  inline-size: 52px;
  padding-block-start: 7px;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  font-weight: 800;
}

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

.anim-dim-primary-row {
  flex-wrap: wrap;
}

.anim-dim-primary-row .anim-dim-inline-label {
  inline-size: auto;
  margin-inline-start: 12px;
}

#anim-dims .sb-dim-chips {
  gap: 7px;
}

#anim-dims .sb-chip {
  padding-inline: 12px;
}

.sb-chip {
  min-height: 34px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: rgba(255, 255, 255, 0.6);
  color: var(--rk-ink);
  padding-inline: 14px;
  font-size: 0.88rem;
  font-weight: 700;
  transition: border-color 180ms ease-out, background 180ms ease-out, color 180ms ease-out;
}

.sb-chip:hover {
  border-color: var(--rk-card-hover-border);
}

.sb-chip.is-active {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

/* Creation-mode tabs — segmented control above the composer (Picture Book / Animation / …) */
.sb-mode-tabs {
  display: inline-flex;
  gap: 4px;
  padding: 5px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
}

.sb-mode-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  padding-inline: 18px;
  font-family: var(--rk-font-body);
  font-size: 0.95rem;
  font-weight: 800;
  transition: background 180ms ease-out, color 180ms ease-out, box-shadow 180ms ease-out;
}

.sb-mode-tab svg {
  width: 19px;
  height: 19px;
  stroke-width: 1.65;
}

.sb-mode-tab:hover {
  color: var(--rk-ink);
}

.sb-mode-tab.is-active {
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  box-shadow: var(--rk-shadow-card);
}

.section-title {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.85rem;
  line-height: 1.2;
}

.section-note {
  margin: 0;
  color: var(--rk-ink-soft);
}

/* ── site-wide pinned ops strip (Kim 2026-08-10, replaces the quiet home strip) ────────────────
   The one place in v3 that is ALLOWED to shout. It carries a deadline and a paid offer, so it uses
   the deepest reading of the platform's single accent — NOT a second hue. The reference (即梦) runs a
   saturated blue; copying it would put two colour systems on the same screen and break the rule that
   all colour comes from the user's artwork.

   `position: sticky` rather than `fixed` on purpose: it stays visible while scrolling AND keeps its
   height in the document flow, so every page below it simply starts lower. Fixed would demand a
   manual top offset on body, the rail, two sticky page headers and three 100vh containers — five
   chances to get it wrong on pages this banner has no other business touching. */
.rk-ops-strip {
  position: sticky;
  inset-block-start: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  min-block-size: 44px;
  padding-block: 9px;
  /* Symmetric inline padding keeps the sentence optically centred even though the close button only
     sits on one side. */
  padding-inline: 56px;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--rk-emerald) 78%, #04231b) 0%,
    var(--rk-emerald) 100%
  );
  color: #fff;
}

.rk-ops-strip-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px 12px;
  inline-size: 100%;
  max-inline-size: 1360px;
  color: inherit;
  text-decoration: none;
}

.rk-ops-strip-text {
  min-inline-size: 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
}

.rk-ops-strip-clock {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex: none;
}

.rk-ops-strip-pill {
  display: inline-grid;
  place-items: center;
  min-inline-size: 26px;
  padding: 2px 5px;
  border-radius: 6px;
  background: rgb(0 0 0 / 30%);
  /* Tabular figures: without them the whole row twitches sideways every time a digit changes. */
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.3;
}

.rk-ops-strip-clock i {
  font-style: normal;
  opacity: 0.6;
}

.rk-ops-strip-cta {
  flex: none;
  font-weight: 700;
  text-underline-offset: 3px;
}

.rk-ops-strip-inner:hover .rk-ops-strip-cta {
  text-decoration: underline;
}

.rk-ops-strip-chevron {
  flex: none;
  display: inline-flex;
  margin-inline-start: -6px;
  opacity: 0.85;
}

.rk-ops-strip-chevron svg {
  inline-size: 16px;
  block-size: 16px;
}

/* The arrow means "forward", which is leftward in Arabic and Hebrew. */
[dir='rtl'] .rk-ops-strip-chevron {
  transform: scaleX(-1);
}

.rk-ops-strip-close {
  position: absolute;
  inset-inline-end: 14px;
  inset-block-start: 50%;
  transform: translateY(-50%);
  display: inline-grid;
  place-items: center;
  inline-size: 28px;
  block-size: 28px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: rgb(255 255 255 / 78%);
  cursor: pointer;
  transition: background 140ms ease-out, color 140ms ease-out;
}

.rk-ops-strip-close svg {
  inline-size: 16px;
  block-size: 16px;
}

.rk-ops-strip-close:hover {
  background: rgb(0 0 0 / 22%);
  color: #fff;
}

.rk-ops-strip-close:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 1px;
}

/* ── billing dunning strip (docs/prd-stripe-dunning-recovery.md) ──────────────
   A payment warning that still reads as page furniture: same paper surface and hairline as every
   card, warn tint at the established 34%/8% mix (see the asset-review notice above), and the only
   loud element is the thin warn edge. Emerald stays reserved — fixing a card is not a creative
   action, so the CTA borrows the warn ink instead. */
.rk-dunning-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 12px 0 0;
  padding: 10px 12px 10px 14px;
  background: color-mix(in srgb, var(--rk-warn) 8%, var(--rk-surface));
  border: 1px solid color-mix(in srgb, var(--rk-warn) 34%, var(--rk-line));
  border-inline-start: 3px solid var(--rk-warn);
  border-radius: var(--rk-radius-sm);
}

.rk-dunning-icon {
  flex: none;
  display: inline-grid;
  place-items: center;
  inline-size: 22px;
  block-size: 22px;
  color: var(--rk-warn);
}

.rk-dunning-icon svg {
  inline-size: 20px;
  block-size: 20px;
  stroke-width: 1.7;
}

.rk-dunning-text {
  min-inline-size: 0;
  color: var(--rk-ink);
  font-size: 0.92rem;
  line-height: 1.45;
}

.rk-dunning-retry {
  color: var(--rk-ink-soft);
  white-space: nowrap;
}

.rk-dunning-cta {
  flex: none;
  margin-inline-start: auto;
  padding: 6px 14px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 55%, var(--rk-line));
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-warn);
  font-weight: 600;
  font-size: 0.88rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background 140ms ease-out, color 140ms ease-out;
}

.rk-dunning-cta:hover {
  background: color-mix(in srgb, var(--rk-warn) 12%, var(--rk-surface));
}

.rk-dunning-cta:disabled {
  opacity: 0.6;
  cursor: default;
}

.rk-dunning-cta:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.rk-dunning-close {
  flex: none;
  display: inline-grid;
  place-items: center;
  inline-size: 30px;
  block-size: 30px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-muted);
  cursor: pointer;
  transition: background 140ms ease-out, color 140ms ease-out;
}

.rk-dunning-close svg {
  inline-size: 16px;
  block-size: 16px;
  stroke-width: 1.8;
}

.rk-dunning-close:hover {
  background: var(--rk-paper-2);
  color: var(--rk-ink);
}

.rk-dunning-close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

@media (max-width: 720px) {
  .rk-dunning-bar {
    flex-wrap: wrap;
  }

  .rk-dunning-cta {
    margin-inline-start: 34px;
  }
}

/* 窄屏：这条通栏挂在**每一页**的顶部，所以它在手机上的高度不是审美问题而是占地问题——
   实测原样式在 375 下高 113px（时钟一行 + 文案两行 + 按钮文字一行），吃掉近 14% 屏高。
   三处收敛：按钮文字隐藏（整条可点 + 箭头已足够表达"可进入"）、文案封顶两行、关闭键收紧。
   关闭键是绝对定位，必须与文案列留出真实间隙——原值实测重叠 2px，正是"点文字却关掉横幅"的来源。 */
@media (max-width: 680px) {
  .rk-ops-strip {
    padding-inline: 44px;
    padding-block: 8px;
  }

  .rk-ops-strip-inner {
    gap: 4px 10px;
  }

  /* 时钟独占一行、文案与箭头共处第二行。不这样写的话文案会撑满整行、把箭头挤到第三行——
     实测那样是 100px 高，这里是 ~78px。 */
  .rk-ops-strip-clock {
    flex-basis: 100%;
    justify-content: center;
  }

  /* `flex-basis: 0`，不是 auto：换行的判定用的是**基准尺寸**而不是收缩后的尺寸，basis=auto 时
     整句话的自然宽度就是基准，永远大于剩余空间 → 箭头必被挤到下一行。这一处实测差 22px 高。 */
  .rk-ops-strip-text {
    flex: 1 1 0;
    min-inline-size: 0;
    font-size: 13px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  .rk-ops-strip-pill {
    min-inline-size: 23px;
    font-size: 12px;
  }

  .rk-ops-strip-cta {
    display: none;
  }

  .rk-ops-strip-chevron {
    margin-inline-start: 0;
  }

  .rk-ops-strip-close {
    inset-inline-end: 8px;
    inline-size: 26px;
    block-size: 26px;
  }
}

.rk-shelf-section .rk-section-header {
  transition: opacity 140ms ease-out;
}

.rk-shelf-section:has(.slot.is-continuation-open .book-continuation) .rk-section-header,
.rk-shelf-section:has(.slot:focus-within .book-continuation) .rk-section-header {
  opacity: 0;
}

@media (hover: hover) {
  .rk-shelf-section:has(.slot:hover .book-continuation) .rk-section-header {
    opacity: 0;
  }
}

.shelf-wrap {
  position: relative;
  max-inline-size: 100%;
  padding-block-start: 0;
  overflow: visible;
}

.shelf-scroller {
  max-inline-size: 100%;
  overflow-x: visible;
  overflow-y: visible;
  padding-block-start: 10px;
  scrollbar-width: none;
}

.shelf-scroller::-webkit-scrollbar {
  display: none;
}

.shelf-stage {
  /* plank asset is 1493x92; sink = how deep book bottoms sit into the visible top surface */
  --plank-sink: clamp(10px, 1.1vw, 16px);
  --rk-book-scale: 1;
  position: relative;
  inline-size: 100%;
  min-inline-size: 0;
  max-inline-size: 100%;
  margin-inline: auto;
}

.shelf-row {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 24px;
  margin-block-end: calc(var(--plank-sink) * -1);
  padding-block-start: 30px;
  padding-inline: 60px 200px;
}

.shelf-row.is-empty {
  justify-content: flex-start;
  padding-inline-start: clamp(72px, 7.5vw, 142px);
}

.slot {
  position: relative;
  perspective: 900px;
  flex: none;
}

/* perspective makes every slot its own stacking context. Raise the active slot itself so its
   continuation panel can clear later sibling books; z-index on the panel alone cannot cross that
   stacking-context boundary. */
.slot.is-continuation-open,
.slot:focus-within {
  z-index: 20;
}

@media (hover: hover) {
  .slot:hover { z-index: 20; }
}

.book-continuation {
  position: absolute;
  z-index: 8;
  inset-block-end: calc(100% + 8px);
  left: 50%;
  inline-size: min(300px, calc(100vw - 32px));
  padding: 14px;
  border: 1px solid var(--rk-line);
  border-radius: 14px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  box-shadow: 0 18px 42px -24px rgba(43, 42, 38, 0.45);
  transform: translate(-50%, 8px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease-out, transform 180ms ease-out;
}

.book-continuation::after {
  content: '';
  position: absolute;
  left: 50%;
  inset-block-end: -7px;
  inline-size: 13px;
  block-size: 13px;
  border-inline-end: 1px solid var(--rk-line);
  border-block-end: 1px solid var(--rk-line);
  background: var(--rk-surface);
  transform: translateX(-50%) rotate(45deg);
}

/* Invisible hover bridge across the 8px gap between the book and this floating popover (QA #1). The
   popover sits `calc(100% + 8px)` above the slot, so moving the pointer up from the book crosses dead
   space that belongs to neither — `.slot:hover` drops, the popover fades and goes pointer-events:none
   mid-travel, and the click lands on nothing ("扩展故事 reachability unstable at laptop size"). This
   bridge is a descendant of the popover, so hovering it keeps `.slot:hover` alive and the popover
   reachable. It only ever ADDS hover-safe area — it cannot reduce reachability. */
.book-continuation::before {
  content: '';
  position: absolute;
  inset-inline: 0;
  inset-block-end: -12px;
  block-size: 12px;
}

.slot.is-continuation-open .book-continuation,
.slot:focus-within .book-continuation {
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, 0);
}

@media (hover: hover) {
  .slot:hover .book-continuation {
    opacity: 1;
    pointer-events: auto;
    transform: translate(-50%, 0);
  }
}

.book-continuation-meta,
.book-continuation-hint {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.74rem;
  line-height: 1.35;
}

.book-continuation-meta { margin-block-end: 10px; }
.book-continuation-hint { padding: 6px 5px 9px; }
.book-continuation-hint:last-child { padding-block-end: 0; }

.book-continuation-action {
  position: relative;
  z-index: 1;
  inline-size: 100%;
  min-block-size: 44px;
  padding: 9px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 9px;
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: center;
  gap: 9px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 160ms ease-out, background 160ms ease-out, color 160ms ease-out;
}

.book-continuation-action.is-primary {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.book-continuation-action.is-primary:hover { background: var(--rk-emerald-hover); }
.book-continuation-action.is-secondary:hover { border-color: var(--rk-card-hover-border); background: var(--rk-paper-2); }
.book-continuation-action:focus-visible { outline: 3px solid color-mix(in srgb, var(--rk-emerald) 28%, transparent); outline-offset: 2px; }
.book-continuation-action svg { inline-size: 17px; block-size: 17px; stroke-width: 1.7; }
.book-continuation-action.is-primary .book-continuation-icon { transform: rotate(180deg); }
.book-continuation-action strong { min-inline-size: 0; font-size: 0.86rem; line-height: 1.25; }
.book-continuation-icon { display: grid; place-items: center; }

/* Short notebook viewports still open upward: the home layout leaves useful whitespace above the
   shelf, while opening inside the slot sends the lower actions below the viewport. Only cap unusually
   long panels here; keep the default bottom anchor and arrow so ordinary panels remain fully visible. */
@media (hover: hover) and (min-width: 721px) and (max-height: 700px) {
  .book-continuation {
    max-block-size: min(480px, calc(100dvh - 24px));
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
  }
}

body.is-book-continuation-sheet-open {
  overflow: hidden;
}

.book-continuation-scrim {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 24px max(16px, env(safe-area-inset-right)) max(16px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  background: color-mix(in srgb, var(--rk-ink) 24%, transparent);
}

.book-continuation.is-touch-sheet {
  position: relative;
  inset: auto;
  inline-size: min(420px, 100%);
  max-block-size: min(560px, calc(100dvh - 48px));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px;
  border-radius: var(--rk-radius-lg);
  opacity: 1;
  pointer-events: auto;
  transform: none;
  animation: book-continuation-sheet-in 180ms ease-out both;
}

.book-continuation.is-touch-sheet::before,
.book-continuation.is-touch-sheet::after {
  display: none;
}

.book-continuation.is-touch-sheet .book-continuation-action.is-locked,
.book-continuation.is-touch-sheet .book-continuation-action.is-locked + .book-continuation-hint {
  display: none;
}

@keyframes book-continuation-sheet-in {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .book-continuation.is-touch-sheet { animation: none; }
}
.chapter-series-cover { background: color-mix(in srgb, var(--rk-emerald) 78%, #285b52); }
.continue-arrow { color: var(--rk-emerald); display: grid; place-items: center; padding: 8px; }
.continue-arrow svg { width: 20px; height: 20px; }

.slot-ground {
  position: absolute;
  inset-inline: 4% -4%;
  inset-block-end: 9px;
  height: 9px;
  border-radius: 999px;
  background: radial-gradient(ellipse at center, var(--rk-book-contact-shadow), transparent 72%);
  filter: blur(2px);
  z-index: -1;
  transition: opacity 300ms ease-out;
}

.book-object {
  position: relative;
  width: calc(var(--book-w) * var(--rk-book-scale));
  height: calc(var(--book-h) * var(--rk-book-scale));
  --book-depth: calc(var(--book-depth-base) * var(--rk-book-scale));
  transform-style: preserve-3d;
  /* The spine's projected width — and how squashed its title reads — is depth * sin(angle). At 13deg a
     24px spine showed 5.4px and the title was an unreadable smear; 28deg doubles it to 11.3px and only
     costs the cover 9% of its width. Hovering still swings the book face-on to read the art. */
  transform: rotateY(28deg) rotateX(1deg);
  transform-origin: 50% 100%;
  transition: transform 420ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
  cursor: pointer;
}

.slot.is-continuation-open .book-object {
  transform: rotateY(4deg) rotateX(0deg) translateY(-12px);
}

.slot.is-continuation-open .slot-ground {
  opacity: 0.58;
}

@media (hover: hover) {
  .slot:hover .book-object {
    transform: rotateY(4deg) rotateX(0deg) translateY(-12px);
  }

  .slot:hover .slot-ground {
    opacity: 0.58;
  }
}

.book-face,
.book-back,
.book-spine,
.book-pages {
  position: absolute;
}

.book-face {
  inset: 0;
  background-size: cover;
  /* the face carries the cover's own page ratio, so `cover` sizing crops nothing and center is exact */
  background-position: center;
  border-radius: 2px 6px 6px 2px;
  transform: translateZ(var(--book-depth));
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}

.book-face::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(112deg, rgba(255, 255, 255, 0.2), transparent 34%),
    linear-gradient(0deg, rgba(0, 0, 0, 0.12), transparent 19%);
}

.book-face::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 7px;
  width: 5px;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.22), rgba(255, 255, 255, 0.16), rgba(0, 0, 0, 0.06));
}

.book-back {
  inset: 0;
  background: var(--book-spine);
  border-radius: 6px 2px 2px 6px;
}

.book-spine {
  inset-block-start: 0;
  inset-inline-start: 0;
  width: var(--book-depth);
  height: 100%;
  background: linear-gradient(
    90deg,
    color-mix(in srgb, var(--book-spine) 82%, black),
    var(--book-spine) 45%,
    color-mix(in srgb, var(--book-spine) 88%, black)
  );
  transform-origin: 0 50%;
  transform: rotateY(-90deg);
  display: flex;
  align-items: center;
  justify-content: center;
}

.book-spine span {
  writing-mode: vertical-rl;
  max-height: 88%;
  overflow: hidden;
  color: rgba(255, 250, 240, 0.92);
  font-size: 0.68rem;
  font-weight: 900;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

.book-pages {
  inset-block-start: 1.5%;
  inset-inline-end: 0;
  width: var(--book-depth);
  height: 97%;
  border-radius: 1px;
  background: repeating-linear-gradient(90deg, var(--rk-page-edge-a) 0 2px, var(--rk-page-edge-b) 2px 3px);
  transform-origin: 100% 50%;
  transform: rotateY(90deg);
}

/* Coverless placeholder: a solid spine-color cloth cover with the title printed on it (used until a
   real cover_url exists). The ::before gloss / ::after edge from .book-face still apply for depth;
   the title sits above them. */
.book-face.is-blank {
  display: grid;
  place-items: center;
  padding: 16px 15px;
  background: var(--book-spine);
  text-align: center;
}

.book-face.is-empty-shelf-cover {
  padding: 19px;
  background:
    radial-gradient(circle at 75% 18%, rgba(255, 255, 255, 0.12), transparent 26%),
    repeating-linear-gradient(92deg, rgba(255, 255, 255, 0.025) 0 1px, rgba(0, 0, 0, 0.018) 1px 3px),
    var(--book-spine);
}

.empty-book-content {
  position: relative;
  z-index: 1;
  inline-size: 100%;
  min-block-size: 100%;
  padding: 18px 13px;
  border: 1px solid rgba(255, 250, 240, 0.38);
  border-radius: 3px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.empty-book-mark {
  display: grid;
  place-items: center;
  color: rgba(255, 250, 240, 0.94);
}

.empty-book-mark svg {
  inline-size: 30px;
  block-size: 30px;
  stroke-width: 1.8;
}

.empty-book-hint {
  color: rgba(255, 250, 240, 0.82);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.35;
}

.is-empty-book .book-object:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--rk-emerald) 52%, transparent);
  outline-offset: 8px;
  border-radius: 6px;
}

.blank-title {
  position: relative;
  z-index: 1;
  color: rgba(255, 250, 240, 0.94);
  font-size: 0.98rem;
  font-weight: 900;
  line-height: 1.28;
  letter-spacing: 0.005em;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Loading / empty / error line that sits on the shelf in place of the book row (plank + cat stay). */
.shelf-caption {
  align-self: flex-end;
  margin-block-end: 44px;
  max-inline-size: 440px;
  color: var(--rk-ink-soft);
  font-size: 0.98rem;
  line-height: 1.55;
  text-align: center;
}

.frame-object,
.character-object {
  position: relative;
  border: 1px solid var(--rk-frame-edge);
  background: var(--rk-frame-bg);
  box-shadow: var(--rk-shadow-object);
  cursor: pointer;
  transition: transform 420ms cubic-bezier(0.2, 0.9, 0.3, 1.2), box-shadow 200ms ease-out;
}

.frame-object {
  width: 166px;
  height: 118px;
  border-radius: 14px;
  padding: 9px;
  transform: rotateY(16deg) rotateX(1deg);
}

.character-object {
  width: 116px;
  height: 176px;
  border-radius: 18px;
  padding: 8px;
  transform: rotateY(12deg) rotateX(0.8deg);
}

.slot:hover .frame-object,
.slot:hover .character-object {
  transform: rotateY(4deg) translateY(-10px);
  box-shadow: 0 28px 44px -30px rgba(80, 60, 32, 0.62);
}

.frame-object img,
.character-object img {
  width: 100%;
  height: 100%;
  border-radius: 10px;
  object-fit: cover;
}

.play-badge {
  position: absolute;
  inset-inline-end: 17px;
  inset-block-end: 17px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  box-shadow: 0 8px 18px -12px rgba(15, 164, 126, 0.75);
}

.play-badge svg {
  width: 16px;
  height: 16px;
}

.shelf-plank {
  position: relative;
  /* Keep the plank itself below .shelf-row (z:2), but do not create a z:1 stacking context: the
     absolutely positioned Pudding and its idea bubble need to rise above the last book. */
  z-index: auto;
  /* mock: plank overhangs the content column — left tip pinned ~24px inside the nav-rail zone
     at any viewport (absorbs the content column's centering gap beyond 1596px) */
  margin-inline-start: calc(-60px - max(0px, (100vw - 1596px) / 2));
  margin-inline-end: calc(-32px - max(0px, (100vw - 1596px) / 4));
}

.plank-img {
  inline-size: 100%;
  block-size: auto;
  display: block;
  filter: drop-shadow(0 26px 20px rgba(110, 80, 40, 0.35));
}

.shelf-pudding {
  /* LP Pudding: paws are at 71% of the 240×452 canvas; the remaining 29% is the hanging tail. */
  --cat-h: clamp(230px, 20vw, 300px);
  position: absolute;
  z-index: 3;
  /* base lands on the plank top-surface line (74% of plank height); tail drapes over the front */
  inset-inline-end: clamp(28px, 3vw, 44px);
  inset-block-end: calc(74% - var(--cat-h) * 0.29);
  inline-size: calc(var(--cat-h) * 0.531);
  block-size: var(--cat-h);
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  color: inherit;
  background: transparent;
  cursor: pointer;
  pointer-events: auto;
}

.shelf-pudding::before {
  position: absolute;
  content: '';
  inset: 8% -12% 18%;
  border: 2px solid transparent;
  border-radius: 48% 48% 42% 42%;
  pointer-events: none;
}

.shelf-pudding:focus-visible::before {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--rk-emerald) 18%, transparent);
}

.shelf-pudding:hover .shelf-cat {
  filter: drop-shadow(0 13px 10px rgba(80, 60, 32, 0.36));
}

.shelf-cat {
  display: block;
  inline-size: auto;
  block-size: 100%;
  max-inline-size: none;
  filter: drop-shadow(0 10px 8px rgba(80, 60, 32, 0.3));
}

/* A single, silent idea beat: the bubble rises from Pudding, then the permanent Showcase card
   appears above. The dots use logical inline edges so the visual connection mirrors in RTL. */
.shelf-pudding-thought {
  position: absolute;
  z-index: 4;
  inset-block-start: 15%;
  inset-inline-start: -32%;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 36px;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-surface) 94%, transparent);
  box-shadow: var(--rk-shadow-card);
  color: var(--rk-emerald-hover);
  opacity: 0;
  transform: translateY(8px) scale(0.72);
  transform-origin: 70% 100%;
}

.shelf-pudding-thought::before,
.shelf-pudding-thought::after {
  position: absolute;
  content: '';
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
}

.shelf-pudding-thought::before {
  inset-inline-end: -7px;
  inset-block-end: -7px;
  inline-size: 9px;
  block-size: 9px;
}

.shelf-pudding-thought::after {
  inset-inline-end: -13px;
  inset-block-end: -14px;
  inline-size: 5px;
  block-size: 5px;
}

.shelf-pudding-thought svg {
  inline-size: 19px;
  block-size: 19px;
}

.shelf-pudding.is-thinking .shelf-pudding-thought {
  animation: shelfPuddingIdea 1800ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
}

.shelf-pudding-replay-hint {
  position: absolute;
  z-index: 6;
  inset-block-start: -5%;
  inset-inline-end: 70%;
  inline-size: max-content;
  max-inline-size: min(250px, 58vw);
  padding: 11px 14px;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  color: var(--rk-ink);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
  font-family: var(--rk-font-body);
  font-size: 14px;
  font-weight: 800;
  line-height: 1.45;
  text-align: start;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px) scale(0.96);
  transform-origin: bottom right;
  transition: opacity 180ms ease-out, transform 180ms ease-out, visibility 180ms ease-out;
  pointer-events: none;
}

.shelf-pudding-replay-hint::after {
  position: absolute;
  content: '';
  inset-inline-end: 18px;
  inset-block-end: -7px;
  inline-size: 12px;
  block-size: 12px;
  border-inline-end: 1px solid var(--rk-line);
  border-block-end: 1px solid var(--rk-line);
  background: var(--rk-surface);
  transform: rotate(45deg);
}

.shelf-pudding.is-replay-hint-visible .shelf-pudding-replay-hint {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
}

@keyframes shelfPuddingIdea {
  0%, 8% { opacity: 0; transform: translateY(8px) scale(0.72); }
  22%, 58% { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(-5px) scale(0.92); }
}

.continue-card {
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  block-size: 144px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: rgba(255, 255, 255, 0.66);
  box-shadow: var(--rk-shadow-card);
  padding: 10px;
  overflow: hidden;
}

.continue-card img {
  width: 116px;
  height: 116px;
  border-radius: 12px;
  object-fit: cover;
}

/* Coverless tile for a Continue card (mirrors the shelf placeholder — a solid cloth square). */
.cover-blank {
  width: 116px;
  height: 116px;
  border-radius: 12px;
  background: var(--tile-color, var(--rk-emerald));
  display: grid;
  place-items: center;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
}

.cover-blank svg {
  width: 40px;
  height: 40px;
  color: rgba(255, 250, 240, 0.9);
}

.continue-card {
  cursor: pointer;
}

.continue-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 900;
  line-height: 1.4;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.continue-meta {
  margin: 4px 0 14px;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
}

.progress {
  height: 5px;
  border-radius: 999px;
  background: var(--rk-progress-track);
  overflow: hidden;
  margin-block-end: 8px;
}

.progress i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
}

.progress-label {
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
}

.more-button {
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--rk-ink-soft);
  display: grid;
  place-items: center;
}

.more-button svg {
  width: 20px;
  height: 20px;
}

/* Short-laptop home: keep every creation mode aligned to the picture-book header and tab height.
   Book settings and shelf geometry remain scoped to the visible picture-book shelf below. */
@media (min-width: 1021px) and (max-height: 760px) {
  .rk-topbar.has-home-greeting .greeting {
    font-size: 1.8rem;
  }

  .rk-home-grid .sb-mode-tabs {
    padding-block: 3px;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .sb-dims:not([id]) {
    gap: 5px;
    margin-block-start: -2px;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .sb-dims:not([id]) .sb-dim-row {
    gap: 10px;
    min-inline-size: 0;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .sb-dims:not([id]) .sb-dim-label {
    inline-size: 48px;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .sb-dims:not([id]) .sb-dim-chips {
    min-inline-size: 0;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .sb-dims:not([id]) .sb-dim-chips::-webkit-scrollbar {
    display: none;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .sb-dims:not([id]) .sb-chip {
    flex: none;
    padding-inline: 11px;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .section-title {
    font-size: 1.65rem;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .shelf-scroller {
    padding-block-start: 4px;
  }

  .rk-home-grid:has(.rk-shelf-section:not([hidden])) .shelf-row {
    padding-block-start: 20px;
  }
}

@media (max-width: 1500px) {
  .shelf-stage {
    --rk-book-scale: 0.88;
  }

  .shelf-row {
    padding-inline: 44px 180px;
  }
}

@media (max-width: 1280px) {
  .shelf-stage {
    --rk-book-scale: 0.78;
  }

  .shelf-row {
    padding-inline: 36px 160px;
  }
}

@media (max-width: 1020px) {
  .brand-wordmark {
    height: 34px;
  }

  .rail-brand {
    gap: 2px;
  }

  .rail-brand img {
    height: 17px;
  }

  .rail-brand-version {
    margin-block-start: 0;
    font-size: 0.56rem;
  }

  .rk-classic-switch {
    min-inline-size: 32px;
    padding-inline: 3px;
    gap: 0;
  }

  .rk-classic-switch-label {
    display: none;
  }

  .rail-item {
    width: 66px;
  }

  .rail-item span {
    font-size: 0.74rem;
  }

  .greeting {
    font-size: 1.82rem;
  }

  .shelf-scroller {
    overflow-x: auto;
    scrollbar-width: none;
  }

  .shelf-stage {
    inline-size: 980px;
    min-inline-size: 980px;
  }

  .shelf-row {
    padding-inline: 40px 220px;
  }

  .shelf-plank {
    margin-inline: 0;
  }
}

@media (max-width: 680px) {
  /* The bottom rail already has a Home destination; keeping the desktop wordmark here steals one
     navigation cell and clips the sixth utility entry on 390px screens. */
  .rail-brand {
    display: none;
  }

  .rk-rail-classic-switch-slot {
    display: none;
  }

  .brand {
    flex: none;
    inline-size: auto;
  }

  .brand-wordmark {
    height: 30px;
  }

  .rk-top-actions {
    width: 100%;
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: 8px;
  }

  .rk-lang-toggle,
  .balance-chip {
    min-height: 40px;
    padding-inline: 11px;
    font-size: 0.78rem;
  }

  .rk-lang-menu {
    inset-inline-start: 0;
    inset-inline-end: auto;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    inline-size: min(420px, calc(100vw - 32px));
  }

  .balance-chip {
    max-inline-size: calc(100vw - 96px);
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .avatar {
    width: 40px;
    height: 40px;
  }

  .search {
    display: none;
  }

  .rail-nav {
    flex-direction: row;
    flex: 1;
    justify-content: space-around;
    gap: 2px;
    inline-size: auto;
    min-inline-size: 0;
    margin-block-start: 0;
  }

  .rail-item {
    width: 58px;
    min-height: 58px;
    gap: 3px;
    padding-block: 5px;
  }

  .rail-item svg {
    width: 22px;
    height: 22px;
  }

  .rail-item span {
    font-size: 0.68rem;
  }

  .rail-item .rail-classic-edition {
    max-inline-size: 58px;
    white-space: normal;
    line-height: 1.05;
  }

  .rail-settings {
    display: none;
  }

  .greeting {
    max-width: 100%;
    font-size: 1.55rem;
    line-height: 1.12;
    text-align: start;
  }

  .subline {
    text-align: start;
    font-size: 0.95rem;
  }

  .rk-hero {
    justify-items: stretch;
    gap: 14px;
  }

  .rk-hero > * {
    min-inline-size: 0;
    max-inline-size: 100%;
  }

  .sb-mode-tabs {
    inline-size: 100%;
    max-inline-size: 100%;
    display: flex;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .sb-mode-tabs::-webkit-scrollbar {
    display: none;
  }

  .sb-mode-tab {
    flex: 0 0 auto;
    min-height: 38px;
    padding-inline: 14px;
    font-size: 0.86rem;
  }

  .composer {
    inline-size: 100%;
    max-inline-size: 100%;
    min-height: 62px;
    padding-inline: 16px 10px;
    align-items: flex-start;
    flex-wrap: wrap;
  }

  .sb-cast-btn {
    height: 38px;
  }

  .composer textarea {
    order: 3;
    flex-basis: 100%;
    font-size: 1.08rem;
  }

  .sb-tools {
    margin-inline-start: auto;
  }

  .sb-char-chips,
  .sb-attachments,
  .sb-composer-note,
  .sb-intake-sheet,
  .sb-dims {
    inline-size: 100%;
    max-inline-size: 100%;
  }

  .fs-home-media,
  .fs-home-panel {
    inline-size: 100%;
    max-inline-size: 100%;
  }

  .fs-home-capabilities {
    grid-template-columns: 1fr;
  }

  .fs-home-media-tab {
    min-block-size: 42px;
  }

  .sb-char-panel {
    inline-size: 100%;
    max-inline-size: 100%;
    max-height: 68vh;
    padding: 12px;
    border-radius: var(--rk-radius);
  }

  .sb-char-panel-top {
    grid-template-columns: 1fr;
  }

  .sb-char-workshop {
    justify-self: stretch;
  }

  .sb-char-grid {
    grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
    gap: 10px;
  }

  .send-button {
    width: 48px;
    height: 48px;
  }

  .sb-cards {
    grid-template-columns: 1fr;
  }

  .sb-dim-row {
    inline-size: 100%;
    max-inline-size: 100%;
    min-inline-size: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }

  .sb-dim-label {
    inline-size: auto;
    padding-block-start: 0;
  }

  .sb-dim-chips {
    inline-size: 100%;
    max-inline-size: 100%;
    min-inline-size: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-block-end: 2px;
    scrollbar-width: none;
  }

  .sb-dim-chips::-webkit-scrollbar {
    display: none;
  }

  .sb-chip {
    flex: none;
  }

  .format-chips {
    justify-content: flex-start;
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-block-end: 4px;
    scrollbar-width: none;
  }

  .format-chips::-webkit-scrollbar {
    display: none;
  }

  .format-chip {
    flex: none;
    min-height: 40px;
    padding-inline: 16px;
  }

  .shelf-scroller {
    inline-size: 100vw;
    max-inline-size: 100vw;
    margin-inline: -16px;
    padding-inline: 16px;
    overflow-x: auto;
  }

  .shelf-stage {
    min-width: 760px;
  }

  .shelf-row {
    justify-content: flex-start;
    gap: 14px;
    padding-inline: 20px 150px;
  }

  .shelf-row.is-empty {
    padding-inline-start: 42px;
  }

  .shelf-stage {
    --rk-book-scale: 0.66;
  }

  .frame-object {
    width: 118px;
    height: 84px;
    border-radius: 12px;
    padding: 7px;
  }

  .character-object {
    width: 82px;
    height: 126px;
    border-radius: 13px;
    padding: 6px;
  }

  .play-badge {
    inset-inline-end: 12px;
    inset-block-end: 12px;
    width: 27px;
    height: 27px;
  }

  .plank-img {
    filter: drop-shadow(0 14px 12px rgba(110, 80, 40, 0.26));
  }

  .shelf-pudding {
    --cat-h: 150px;
    inset-inline-end: 16px;
  }

  .continue-card {
    grid-template-columns: 88px minmax(0, 1fr) auto;
    block-size: 120px;
  }

  .continue-card img,
  .continue-card .cover-blank {
    width: 88px;
    height: 88px;
  }
}

/* ── Storybook co-creation screen (story.html) ──────────────────────────── */

.sb-empty-state {
  display: grid;
  justify-items: center;
  gap: 10px;
  max-width: 420px;
  /* A flat 12vh lead pushed the CTA out of the step's own scroll box on a laptop: the
     mascots are 548x1200 portraits, so at width 132 the art alone eats 289px, and the
     assets step only gets `100vh - 206px` to work with. Measured: the button needed a
     ~800px viewport to stay reachable, and an empty state is centred with no hint that
     anything sits below it — so it read as missing, not as scrolled-away (2026-08-06). */
  margin: min(12vh, 96px) auto 0;
  text-align: center;
  padding: 32px;
}

.sb-empty-state img {
  width: 132px;
  height: auto;
  /* Portrait mascots yield first when vertical space runs short; object-fit keeps the
     aspect ratio intact while the box itself shrinks. */
  max-height: min(34vh, 300px);
  object-fit: contain;
  filter: drop-shadow(0 12px 18px rgba(80, 60, 32, 0.22));
}

.sb-empty-state h2 {
  margin: 6px 0 0;
  font-family: var(--rk-font-display);
  font-size: 1.6rem;
}

.sb-empty-state p {
  margin: 0;
  color: var(--rk-ink-soft);
}

.sb-empty-cta {
  margin-block-start: 10px;
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  text-decoration: none;
  font-weight: 800;
  padding-inline: 22px;
  transition: background 180ms ease-out;
}

.sb-empty-cta:hover {
  background: var(--rk-emerald-hover);
}

/* Laptop viewports (1366x768 and 1080p at 125% scaling both land here). The clamps above
   are not enough on their own at ~640px of CSS height — the whole composition has to give
   ground so the only way forward stays on screen without scrolling. */
@media (max-height: 900px) {
  .sb-empty-state {
    margin-block-start: 2vh;
    gap: 8px;
    padding: 20px 32px 24px;
  }

  .sb-empty-state img {
    max-height: 30vh;
  }

  .sb-empty-state h2 {
    font-size: 1.35rem;
  }
}

.rk-bare-main:has(> .sb-flow-page),
.rk-bare-main:has(> .sb-style-step),
.rk-bare-main:has(> .sb-vt-page) {
  min-height: 0;
  padding: 0;
}

.sb-flow-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  padding: 14px clamp(18px, 3vw, 48px) 18px;
  overflow: hidden;
  background: color-mix(in srgb, var(--rk-paper-2) 34%, var(--rk-paper));
}

.sb-flow-header {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) auto minmax(220px, 1fr);
  align-items: center;
  gap: 18px;
  width: min(100%, 1920px);
  min-height: 46px;
  margin: 0 auto;
  flex: none;
}

.sb-flow-context {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.sb-flow-divider {
  width: 1px;
  height: 18px;
  margin-inline: 3px;
  background: var(--rk-line);
}

.sb-flow-title {
  min-width: 0;
  overflow: hidden;
  color: var(--rk-ink);
  font-size: 0.92rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-flow-balance {
  display: flex;
  justify-content: flex-end;
  min-width: 0;
}

.sb-flow-header > .sb-stepper {
  justify-self: center;
}

/* "This book already existed, we reopened it." Sits between the flow header and the story grid, on the
   same width as the grid so it reads as part of the page rather than a floating alert. Informational,
   not an error: paper tint + line border, no red. */
.sb-resumed-notice {
  display: flex;
  align-items: center;
  gap: 12px;
  width: min(100%, 1920px);
  margin: 10px auto 0;
  padding: 10px 16px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  font-size: 14px;
  line-height: 1.5;
}

.sb-resumed-text { flex: 1; min-width: 0; }

.sb-resumed-dismiss {
  flex: none;
  border: 0;
  background: none;
  padding: 4px 6px;
  color: var(--rk-ink-soft);
  font-size: 14px;
  cursor: pointer;
  text-decoration: underline;
}

.sb-resumed-dismiss:hover { color: var(--rk-ink); }

.sb-story-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(380px, 34vw);
  gap: 0;
  width: min(100%, 1920px);
  min-height: 0;
  margin: 10px auto 0;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
  overflow: hidden;
  flex: 1;
}

.sb-prose-panel,
.sb-story-card {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--rk-surface);
  border: 0;
  box-shadow: none;
  overflow: hidden;
}

.sb-story-card {
  border-inline-start: 1px solid var(--rk-line);
}

.sb-panel-kicker {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: none;
  padding: 16px 22px;
  border-block-end: 1px solid var(--rk-line);
}

.sb-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 0;
  background: transparent;
  color: var(--rk-ink-soft);
  font-weight: 800;
  padding: 4px 2px;
  transition: color 150ms ease-out;
}

.sb-back span { white-space: nowrap; }

.sb-back svg {
  width: 20px;
  height: 20px;
}

.sb-back:hover {
  color: var(--rk-ink);
}

.sb-back:focus-visible,
.sb-home-icon:focus-visible,
.sb-step-link:focus-visible,
.sb-style-tab:focus-visible,
.sb-style-use:focus-visible,
.sb-continue-btn:focus-visible,
.sb-vt-stepwise:focus-visible,
.sb-vt-board-image:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 3px;
}

.sb-kicker-label {
  color: var(--rk-ink-muted);
  font-size: 0.86rem;
  font-weight: 800;
}

.sb-prose-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 28px 34px;
}

.sb-prose-title {
  margin: 0 0 18px;
  font-family: var(--rk-font-display);
  font-size: 1.9rem;
  line-height: 1.16;
}

.sb-prose-p {
  margin: 0 0 14px;
  color: var(--rk-ink);
  line-height: 1.65;
  border-radius: 8px;
  transition: background 220ms ease-out;
}

.sb-prose-p.is-refine-changed {
  background: var(--rk-emerald-soft);
}

.sb-chat-log {
  flex: none;
  max-height: 128px;
  overflow-y: auto;
  padding: 10px 22px 0;
  display: grid;
  gap: 8px;
}

.sb-chat-bubble {
  justify-self: start;
  max-width: 86%;
  border-radius: 14px 14px 14px 4px;
  padding: 9px 14px;
  font-size: 0.92rem;
  line-height: 1.4;
  background: var(--rk-bubble-ai);
  color: var(--rk-ink);
}

.sb-chat-message {
  justify-self: start;
  display: flex;
  align-items: center;
  gap: 4px;
  inline-size: fit-content;
  max-inline-size: 86%;
}

.sb-chat-message.is-user {
  justify-self: end;
  flex-direction: row-reverse;
}

.sb-chat-message .sb-chat-bubble {
  min-inline-size: 0;
  max-width: none;
}

.sb-chat-copy {
  appearance: none;
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 40px;
  block-size: 40px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 10px;
  background: transparent;
  color: var(--rk-ink-muted);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease-out, color 140ms ease-out, background 140ms ease-out, border-color 140ms ease-out;
}

.sb-chat-copy svg {
  inline-size: 18px;
  block-size: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.sb-chat-message.has-copy:hover .sb-chat-copy,
.sb-chat-message.has-copy:focus-within .sb-chat-copy,
.sb-chat-copy.is-copied {
  opacity: 1;
  pointer-events: auto;
}

.sb-chat-copy:hover,
.sb-chat-copy:focus-visible {
  border-color: var(--rk-line-strong, var(--rk-line));
  outline: none;
  background: color-mix(in srgb, var(--rk-surface) 78%, transparent);
  color: var(--rk-emerald-hover);
}

.sb-chat-copy.is-copied {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-chat-bubble.is-user {
  justify-self: end;
  border-radius: 14px 14px 4px 14px;
  background: var(--rk-bubble-user);
}

.sb-chat-bubble.is-error {
  background: color-mix(in srgb, var(--rk-danger) 12%, var(--rk-surface));
  color: var(--rk-danger);
}

.sb-chat-bubble.is-pending {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--rk-ink-soft);
}

.sb-refine-wave {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-inline-size: 28px;
}

.sb-refine-wave i {
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: var(--rk-emerald);
  animation: rk-refine-wave 1s ease-in-out infinite;
}

/* Elapsed seconds inside the pending chat bubble. Tabular figures so the line does not jitter each
   tick, and a reserved width so the bubble stops growing once it reaches two digits. */
.sb-chat-elapsed {
  font-size: 0.82rem;
  color: var(--rk-ink-muted);
  font-variant-numeric: tabular-nums;
  min-inline-size: 3ch;
}

.sb-refine-wave i:nth-child(2) { animation-delay: 120ms; }
.sb-refine-wave i:nth-child(3) { animation-delay: 240ms; }

@keyframes rk-refine-wave {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.45; }
  30% { transform: translateY(-5px); opacity: 1; }
}

.sb-chat-action {
  margin-inline-start: 10px;
  min-block-size: 30px;
  padding-inline: 10px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  font: inherit;
  font-weight: 800;
  cursor: pointer;
}

.sb-chat-action:hover,
.sb-chat-action:focus-visible {
  border-color: var(--rk-emerald);
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .sb-refine-wave i { animation: none; opacity: 0.75; }
  .sb-chat-copy { transition: none; }
  .sb-prose-p { transition: none; }
}

@media (hover: none) {
  .sb-chat-copy {
    opacity: 1;
    pointer-events: auto;
  }
}

.sb-refine-bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  border-block-start: 1px solid var(--rk-line);
}

.sb-refine-avatar {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--rk-paper-2);
  object-fit: cover;
  object-position: 50% 50%; /* cat-avatar-t.png is a square head close-up — face fills the circle */
}

.sb-refine-form {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 46px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
  padding-inline: 18px 6px;
}

.sb-refine-form input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--rk-ink);
  font-size: 0.98rem;
}

.sb-refine-form input::placeholder {
  color: var(--rk-ink-muted);
}

.sb-refine-form input:disabled {
  opacity: 0.6;
}

.sb-refine-send {
  position: relative;
  flex: none;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  display: grid;
  place-items: center;
  transition: background 180ms ease-out;
}

.sb-refine-send svg {
  width: 18px;
  height: 18px;
}

.sb-refine-send:hover {
  background: var(--rk-emerald-hover);
}

.sb-refine-send:disabled {
  cursor: default;
}

.spinner-sm {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  animation: rk-spin 0.8s linear infinite;
}

.sb-card-kicker {
  flex: none;
  display: grid;
  gap: 4px;
  padding: 16px 22px 12px;
  border-block-end: 1px solid var(--rk-line);
}

/* Title and age band on one line: the title takes what is left (minmax 0 so a long one ellipsises
   instead of shoving the band out of the card), the band never shrinks and stays pinned to the
   row's end in both writing directions. */
.sb-card-titlerow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
}

/* Two lines, then ellipsis. A title is worth wrapping for — truncating a five-word one at the first
   line would hide the book's own name — but an unbounded h2 pushes the page plan back down, which is
   the whole thing this layout exists to prevent. The full text stays on the element's title. */
.sb-card-title {
  margin: 0;
  min-width: 0;
  font-family: var(--rk-font-display);
  font-size: 1.28rem;
  line-height: 1.25;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.sb-age-tag {
  justify-self: end;
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.8rem;
  font-weight: 800;
  white-space: nowrap;
  padding-inline: 12px;
}

.sb-card-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 22px 14px;
  display: grid;
  gap: 12px;
  align-content: start;
}

.sb-card-heading {
  margin: 0 0 7px;
  color: var(--rk-ink-soft);
  font-size: 0.84rem;
  font-weight: 800;
}

/* The binding entry lives in the card header now, directly under the title — no longer a second
   item on the 「角色」 heading row. */
.sb-cast-bind-entry {
  min-block-size: 30px;
  max-inline-size: 340px;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--rk-emerald-hover);
  font-size: 0.78rem;
  font-weight: 800;
  line-height: 1.4;
  text-align: start;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: pointer;
}

.sb-cast-bind-entry:hover:not(:disabled) {
  color: var(--rk-emerald);
}

.sb-cast-bind-entry:focus-visible {
  border-radius: 4px;
  outline: 2px solid var(--rk-emerald);
  outline-offset: 3px;
}

.sb-cast-bind-entry:disabled {
  color: var(--rk-ink-muted);
  text-decoration: none;
  cursor: default;
}

.sb-cast-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sb-cast-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  max-width: 100%;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding-block: 4px;
  padding-inline: 8px 10px;
  background: rgba(255, 255, 255, 0.7);
}

.sb-cast-avatar {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.78rem;
  font-weight: 900;
  overflow: hidden;
}

.sb-cast-avatar.has-image {
  background: var(--rk-paper-2);
}

.sb-cast-avatar img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.sb-cast-copy {
  min-width: 0;
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
}

.sb-cast-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9rem;
  font-weight: 800;
}

.sb-cast-role {
  color: var(--rk-ink-muted);
  font-size: 0.78rem;
}

.rk-modal-panel.is-cast-binding {
  inline-size: min(680px, 100%);
  block-size: min(720px, calc(100dvh - 48px));
  max-block-size: none;
  overflow: hidden;
  padding: 22px;
}

.rk-modal-panel.is-cast-binding .rk-modal-body {
  min-height: 0;
  block-size: 100%;
}

.sb-cast-binding-modal {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-rows: auto auto auto minmax(160px, 1fr) auto auto;
  gap: 16px;
}

.sb-cast-bind-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
}

.sb-cast-bind-head h2 {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.24rem;
}

.sb-cast-bind-head p {
  margin: 6px 0 0;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.5;
}

.sb-cast-bind-head a {
  flex: none;
  color: var(--rk-emerald-hover);
  font-size: 0.8rem;
  font-weight: 800;
}

.sb-cast-bind-targets {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-block-end: 2px;
  scrollbar-width: thin;
}

.sb-cast-bind-target {
  flex: none;
  min-block-size: 38px;
  max-inline-size: 180px;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding-inline: 14px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-size: 0.8rem;
  font-weight: 800;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-cast-bind-target:hover,
.sb-cast-bind-target.is-active {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-cast-bind-target:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.sb-cast-bind-search {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 42px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding-inline: 14px;
  background: var(--rk-paper-2);
}

.sb-cast-bind-search:focus-within {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-emerald-soft);
}

.sb-cast-bind-search svg {
  flex: none;
  width: 17px;
  color: var(--rk-ink-muted);
}

.sb-cast-bind-search input {
  min-width: 0;
  flex: 1;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--rk-ink);
}

.sb-cast-bind-body {
  min-height: 0;
  overflow-y: auto;
  padding-inline-end: 4px;
}

.sb-cast-bind-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 12px;
}

.sb-cast-bind-card {
  min-width: 0;
  display: grid;
  gap: 7px;
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--rk-ink);
  text-align: center;
}

.sb-cast-bind-card:disabled {
  opacity: 0.42;
}

.sb-cast-bind-thumb {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  overflow: hidden;
  border: 2px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
}

.sb-cast-bind-card:hover:not(:disabled) .sb-cast-bind-thumb,
.sb-cast-bind-card:focus-visible .sb-cast-bind-thumb,
.sb-cast-bind-card.is-selected .sb-cast-bind-thumb {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-emerald-soft);
}

.sb-cast-bind-card:focus-visible {
  outline: 0;
}

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

.sb-cast-bind-thumb b {
  color: var(--rk-emerald-hover);
  font-family: var(--rk-font-display);
  font-size: 1.6rem;
}

.sb-cast-bind-thumb i {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 6px;
  width: 25px;
  height: 25px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.sb-cast-bind-thumb i svg {
  width: 15px;
}

.sb-cast-bind-card strong,
.sb-cast-bind-card small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-cast-bind-card strong {
  font-size: 0.84rem;
}

.sb-cast-bind-card small {
  color: var(--rk-ink-muted);
  font-size: 0.68rem;
}

/* Restyle warning. Amber, not the emerald accent: this is something to weigh before choosing, not an
   action or an active state, and the single accent stays reserved for those. Written as an undefined
   token + fallback exactly like .cs-chapter.is-warn — the palette gains no new entry here, and if
   --rk-amber-ink ever lands in tokens.css this picks it up for free. */
.sb-cast-bind-card small.is-restyle {
  color: var(--rk-amber-ink, #9c6a1c);
}

.sb-cast-bind-state {
  min-height: 180px;
  margin: 0;
  display: grid;
  place-items: center;
  color: var(--rk-ink-soft);
}

.sb-cast-bind-state.is-error,
.sb-cast-bind-error {
  color: var(--rk-danger);
}

.sb-cast-bind-error {
  margin: 0;
  font-size: 0.8rem;
}

.sb-cast-bind-actions {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 10px;
  align-items: center;
  border-block-start: 1px solid var(--rk-line);
  padding-block-start: 14px;
}

.sb-cast-bind-actions button {
  min-height: 40px;
  border-radius: 999px;
  padding-inline: 17px;
  font-weight: 800;
}

.sb-cast-bind-unlink,
.sb-cast-bind-cancel {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
}

.sb-cast-bind-unlink {
  justify-self: start;
  color: var(--rk-danger);
}

.sb-cast-bind-save {
  min-width: 104px;
  border: 0;
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.sb-cast-bind-actions button:disabled {
  opacity: 0.48;
  cursor: not-allowed;
}

@media (max-width: 620px) {
  .sb-cast-bind-entry {
    max-inline-size: none;
  }

  .sb-cast-pill {
    width: 100%;
  }

  .sb-cast-copy {
    flex: 1;
  }

  .rk-modal-panel.is-cast-binding {
    inline-size: 100%;
    block-size: calc(100dvh - 24px);
    padding: 17px;
  }

  .sb-cast-bind-head {
    display: grid;
    gap: 8px;
  }

  .sb-cast-bind-head a {
    justify-self: start;
  }

  /* The restyle warning wraps instead of being ellipsised here. On desktop the cut-off half is
     recoverable through the title tooltip; on a touch screen there is no hover, so an ellipsis means
     the sentence is simply unreadable. Rows in this grid size to their tallest card, so the extra
     line costs layout nothing. */
  .sb-cast-bind-card small.is-restyle {
    white-space: normal;
    line-height: 1.25;
  }

  .sb-cast-bind-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .sb-cast-bind-actions {
    grid-template-columns: 1fr 1fr;
  }

  .sb-cast-bind-actions > span,
  .sb-cast-bind-unlink {
    grid-column: 1 / -1;
  }

  .sb-cast-bind-unlink {
    justify-self: stretch;
  }
}

/* 「故事场景」 is a one-line fact, not a section: label and value share a row. The value ellipsises
   rather than wrapping — a three-scene book must not cost the page plan two extra lines — and the
   full text stays reachable through the element's title. */
.sb-settings-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}

.sb-settings-row .sb-card-heading {
  flex: none;
  margin: 0;
}

.sb-settings-line {
  flex: 1;
  min-width: 0;
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.94rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-page-plan {
  min-width: 0;
}

@media (min-width: 1021px) {
  /* Rows 1-2 (cast + settings) are `auto`, so a long cast grows them without limit while row 3 stops
     shrinking at 180px — past that the grid is taller than the card. `overflow: hidden` here meant
     that surplus was simply UNREACHABLE: no scrollbar anywhere, the settings line and the top of the
     page plan cut off mid-glyph (Andy, 2026-08-07). Measured at 1280×720: 8 characters already loses
     15px, 10 loses 59px, 12 loses 103px — and a taller cast only makes it worse. `auto` keeps the
     no-overflow case pixel-identical (no scrollbar when it fits) and gives the surplus a way out. */
  .sb-card-scroll:has(.sb-page-plan.is-expanded) {
    grid-template-rows: auto auto minmax(180px, 1fr);
    align-content: stretch;
    overflow-y: auto;
    overflow-x: hidden;
  }

  .sb-page-plan.is-expanded {
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .sb-page-plan.is-expanded .sb-page-plan-details {
    flex: 1;
    min-height: 0;
    max-height: none;
  }
}

.sb-page-plan-header {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 28px;
  color: var(--rk-ink);
  text-align: start;
}

.sb-page-plan-heading {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  font-size: 0.84rem;
  font-weight: 800;
}

/* Sits where the retry button sits on the failure state — the unconfirmed rail explains instead of
   offering an action, because the text step is already paid for and may already have produced a book. */
.sb-page-plan-note {
  margin: 8px 0 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--rk-ink-soft);
}

.sb-page-plan-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  color: var(--rk-emerald);
  font-size: 0.74rem;
  font-weight: 750;
}

.sb-page-plan-status > i {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: currentColor;
  animation: sb-page-plan-pulse 1.2s ease-in-out infinite;
}

.sb-page-plan-status > svg {
  width: 15px;
  height: 15px;
  flex: none;
}

.sb-page-plan-details {
  max-height: none;
  margin-top: 8px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.sb-page-plan-details:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.sb-page-plan.is-planning .sb-page-list {
  border-color: color-mix(in srgb, var(--rk-emerald) 28%, var(--rk-line));
}

@keyframes sb-page-plan-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.82); }
  50% { opacity: 1; transform: scale(1); }
}

.sb-page-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  overflow: hidden;
}

.sb-page-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 8px 12px;
}

.sb-page-row + .sb-page-row {
  border-block-start: 1px solid var(--rk-line);
}

.sb-page-row.is-plan-changed {
  background: var(--rk-emerald-soft);
}

/* Neutral on purpose. This row used to be tinted emerald, the same colour `.is-plan-changed` uses to
   say "this row's text just changed" — so the rail spoke green twice with two different meanings, and
   the author learned neither. A draft row is quiet paper; green belongs to change alone. */
.sb-page-row.is-provisional {
  border-inline-start: 3px solid var(--rk-line);
  background: color-mix(in srgb, var(--rk-paper-2) 55%, transparent);
  animation: sb-page-row-in 0.32s ease both;
}

/* Placeholder rows for the window where the prose is already printing but the director has not
   returned a page plan yet (buffered streaming). Purely structural — they reserve the rail's shape so
   the real list replaces them in place; they never carry numbers or text. */
.sb-page-list-skeleton {
  margin-block-start: 8px;
}

/* The streaming plan now sits in the same scrollport as the finished one, and that wrapper already
   carries the 8px gap under the heading — keeping both would double it. */
.sb-page-plan-details > .sb-page-list-skeleton {
  margin-block-start: 0;
}

.sb-page-row.is-skeleton {
  align-items: center;
  min-block-size: 44px;
}

.sb-page-row.is-skeleton .sb-page-preview {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 6px;
}

.sb-skeleton-bar {
  display: block;
  block-size: 9px;
  border-radius: 999px;
  background: var(--rk-line);
  animation: sb-skeleton-pulse 1.6s ease-in-out infinite;
}

.sb-page-no .sb-skeleton-bar { inline-size: 42px; }
.sb-page-preview .sb-skeleton-bar { inline-size: 100%; }
.sb-page-preview .sb-skeleton-bar.is-short { inline-size: 62%; }

.sb-page-row.is-skeleton:nth-child(even) .sb-skeleton-bar { animation-delay: 0.2s; }
.sb-page-row.is-skeleton:nth-child(3n) .sb-skeleton-bar { animation-delay: 0.4s; }

@keyframes sb-skeleton-pulse {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 0.9; }
}

@media (prefers-reduced-motion: reduce) {
  .sb-skeleton-bar { animation: none; }
}

/* Transient notice on the asset canvas (busy draw queue, etc.) — mirrors the comic toast. */
.sb-toasts {
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 90;
}

.sb-toast {
  background: var(--rk-ink);
  color: var(--rk-paper);
  border-radius: var(--rk-radius);
  padding: 10px 18px;
  font-size: 14px;
  box-shadow: var(--rk-shadow-panel);
  transition: opacity 0.4s;
}

.sb-toast.is-out { opacity: 0; }

/* Inline way out of a blocking notice (e.g. "not enough credits" → top up). Reads as a link on the
   dark toast rather than a second button competing with the message. */
.sb-toast-action {
  margin-left: 12px;
  background: none;
  border: 0;
  padding: 0;
  color: var(--rk-emerald-soft);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

.sb-toast-action:hover { color: var(--rk-paper); }

/* During the left-pane typewriter, each row waits off-screen until the story is written past its cut
   point, then fades in — so the right pane fills in step with the left instead of all at once. */
.sb-page-row.is-staged {
  display: none;
}

.sb-page-row.is-revealed {
  animation: sb-page-row-in 0.32s ease both;
}

@keyframes sb-page-row-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .sb-page-row.is-revealed { animation: none; }
}

.sb-page-no {
  flex: none;
  inline-size: 64px;
  color: var(--rk-ink-muted);
  font-size: 0.78rem;
  font-weight: 800;
}

.sb-page-preview {
  min-width: 0;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.5;
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  overflow-wrap: anywhere;
  word-break: normal;
  hyphens: auto;
}

.sb-card-cta {
  flex: none;
  display: grid;
  gap: 10px;
  padding: 16px 22px 20px;
  border-block-start: 1px solid var(--rk-line);
}

.sb-lint {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 0.86rem;
}

.sb-lint svg {
  flex: none;
  width: 18px;
  height: 18px;
  margin-block-start: 1px;
}

.sb-lint-ok {
  color: var(--rk-good);
}

.sb-lint-warn {
  color: var(--rk-warn);
}

.sb-lint-warn ul {
  margin: 0;
  padding-inline-start: 16px;
}

.sb-continue-btn {
  min-height: 48px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-weight: 800;
}

.sb-continue-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ── Style step (pipeline Step 2) ─────────────────────────────────────────── */
/* Decision F (2026-07-29): one mixed catalog, no tabs. The step is a viewport-filling column —
   header / hero+meta (flexible) / 5×3 pager grid pinned at the bottom — so the pager sits at the
   screen's lower edge instead of leaving the bottom half of the page empty. */
.sb-style-step {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 18px;
  min-height: calc(100dvh - 96px);
}

/* The style step's header is the shared .sb-flow-header skeleton (three columns, the stepper anchored
   to the middle one) widened to this step's own 2200px track. Before this it was a plain block, so the
   stepper simply flowed after the home/back controls and drifted left of the page's centre. */
.sb-style-top {
  width: min(100%, 2200px);
}

.sb-stepper {
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  font-weight: 800;
  font-size: 0.92rem;
}

.sb-step {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--rk-ink-muted);
  white-space: nowrap;
}

.sb-step.is-done {
  color: var(--rk-good);
}

.sb-step.is-active {
  color: var(--rk-emerald);
}

.sb-step svg {
  width: 17px;
  height: 17px;
}

/* A finished step is a button, but it must read exactly like the inert steps beside it — the only
   difference the eye earns is the pointer and a warmer plate on hover. */
.sb-step-link {
  padding: 3px 8px;
  margin: -3px -8px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-weight: inherit;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}

.sb-step-link:hover { background: rgba(30, 143, 103, 0.10); color: var(--rk-emerald); }
.sb-step-link:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }

.sb-step-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--rk-emerald);
}

/* Steps ahead of the author are grey all the way through. Without this the dot stayed emerald while
   its label went muted, which read as "this one is live too" — the exact ambiguity showing the full
   route was meant to remove. Same rule the comic header already follows (.cm-step.is-pending). */
.sb-step:not(.is-done, .is-active) .sb-step-dot {
  background: var(--rk-line);
}

.sb-step-sep {
  width: 28px;
  height: 1px;
  background: var(--rk-line);
}

.sb-style-focus {
  display: grid;
  /* The meta column keeps a real floor — with a plain 1fr the fixed-height hero (its width follows
     from the aspect ratios) can eat the whole capped row and crush the text to 1px wide, which
     wraps every glyph onto its own line and blows the page 2000px tall. Measured 2026-07-29. */
  grid-template-columns: auto minmax(300px, 1fr);
  gap: 32px;
  align-items: center;
  min-height: 0;
  /* Centered with side whitespace, but GENEROUS (Andy round 2: the exhibit felt small — scale it up,
     a page scrollbar is fine). Cap arithmetic: hero at 380px ≈ 973px wide + 32 gap + 300 meta floor
     + 24 padding = 1329, inside this cap. */
  width: min(96%, 1360px);
  justify-self: center;
  padding-inline: 12px;
}

/* Hero: the 16:9 scene image and the FULL character image side by side at one shared height.
   A style with no character showcase yet (v8.2 pending batch) renders scene-only. */
.sb-style-hero2 {
  display: flex;
  gap: 12px;
  align-items: stretch;
  /* Height budgets the whole row: scene(16:9)+char(3:4) at height H is ≈2.53·H wide, and the meta
     column needs its 300px floor inside the focus cap — 380px fits the 1360px cap, don't raise it
     without redoing that arithmetic (the 1px-meta collapse is the failure mode). */
  height: min(44vh, 380px);
  min-height: 240px;
  justify-self: start;
  max-width: 100%;
  min-width: 0;
}

.sb-style-hero2 img {
  height: 100%;
  border-radius: var(--rk-radius);
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  object-fit: cover;
  object-position: center top;
}

.sb-style-hero2 .sb-style-scene {
  aspect-ratio: 16 / 9;
  min-width: 0;
}

.sb-style-hero2 .sb-style-char {
  aspect-ratio: 3 / 4;
  min-width: 0;
}

.sb-style-badge-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-block-end: 12px;
}

/* ⓘ hover note for the model behind the focused style. Pure CSS reveal on hover/focus. */
.sb-style-info {
  position: relative;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  color: var(--rk-ink-faint);
  cursor: help;
  outline: none;
}

.sb-style-info svg {
  width: 16px;
  height: 16px;
}

.sb-style-info:hover,
.sb-style-info:focus-visible {
  color: var(--rk-emerald);
}

.sb-style-tip {
  position: absolute;
  inset-block-start: calc(100% + 8px);
  inset-inline-start: -8px;
  z-index: 30;
  width: min(320px, 60vw);
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-size: 0.82rem;
  font-weight: 500;
  line-height: 1.55;
  text-transform: none;
  letter-spacing: normal;
  box-shadow: var(--rk-shadow-panel);
  opacity: 0;
  visibility: hidden;
  transition: opacity 140ms ease-out;
}

.sb-style-info:hover .sb-style-tip,
.sb-style-info:focus-visible .sb-style-tip {
  opacity: 1;
  visibility: visible;
}

.sb-style-engine {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 32%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-emerald) 8%, var(--rk-surface));
  color: var(--rk-emerald-hover);
  font-size: 0.75rem;
  font-weight: 850;
  letter-spacing: 0.04em;
  padding-inline: 12px;
  text-transform: uppercase;
}

.sb-style-name {
  margin: 0 0 8px;
  font-family: var(--rk-font-display);
  font-size: 1.7rem;
}

.sb-style-desc {
  margin: 0 0 20px;
  color: var(--rk-ink-soft);
  line-height: 1.55;
}

.sb-style-art-note {
  margin: -8px 0 20px;
  color: var(--rk-ink-faint);
  font-size: 0.86rem;
  line-height: 1.5;
}

/* Character-first default: a quiet note that the previewed style was preselected to match the
   author's chosen characters. Shown only while that suggested style is the focused one. */
.sb-style-from-char {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: -8px 0 20px;
  padding: 7px 13px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
  font-size: 0.86rem;
  line-height: 1.4;
  font-weight: 600;
}

.sb-style-use {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 50px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-weight: 800;
  padding-inline: 26px;
  transition: background 180ms ease-out;
}

.sb-style-use:hover:not(:disabled) {
  background: var(--rk-emerald-hover);
}

.sb-style-use:disabled {
  cursor: not-allowed;
  opacity: 0.58;
}

.sb-style-use.is-locked {
  background: var(--rk-good);
}

.sb-style-use svg {
  width: 18px;
  height: 18px;
}

.sb-style-selected-state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding-inline: 14px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 26%, var(--rk-line));
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
  font-size: 0.86rem;
  font-weight: 800;
}

.sb-style-selected-state svg {
  width: 17px;
  height: 17px;
}

.sb-style-locked-note {
  margin: 12px 0 0;
  color: var(--rk-ink-soft);
  font-size: 0.9rem;
}

.sb-style-change-error {
  max-width: 38rem;
  margin: 12px 0 0;
  color: var(--rk-danger);
  font-size: 0.9rem;
  font-weight: 650;
  line-height: 1.5;
}

.sb-style-change-confirm {
  display: grid;
  justify-items: center;
  gap: 12px;
  padding: 8px 0 2px;
  text-align: center;
}

.sb-style-change-confirm h2,
.sb-style-change-confirm p {
  margin: 0;
}

.sb-style-change-confirm p {
  color: var(--rk-ink-soft);
  line-height: 1.65;
}

.sb-style-change-icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--rk-warning-soft, var(--rk-cream));
  color: var(--rk-warning, var(--rk-ink));
}

.sb-style-change-icon svg {
  width: 24px;
  height: 24px;
}

/* Bottom pager grid (decision F): 3:4 character thumbnails, 5 columns × 2 rows per page, previous/next
   arrows. Lives in the step's last grid row so it hugs the bottom of the viewport. */
.sb-style-grid-shell {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  gap: 12px;
  align-items: center;
  min-width: 0;
  align-self: end;
  /* Breathing room below the hero so the shelf never crowds the exhibit (Andy 2026-07-29). */
  margin-block-start: 22px;
}

.sb-style-grid-wrap {
  display: grid;
  gap: 6px;
  min-width: 0;
}

/* Seven across, not five (Andy 2026-07-30): portrait cards at the five-column width stood 373px tall
   and stole the hero's air. Seven columns puts each card at ~197px — measured 30% narrower, so 30%
   shorter too — which is the whole point of the change; do not widen them back without re-checking
   the hero budget in .sb-style-hero2. */
.sb-style-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 10px;
  min-width: 0;
}

.sb-style-page-count {
  margin: 0;
  text-align: center;
  color: var(--rk-ink-faint);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* Emerald pager arrows (Andy 2026-07-29): the quiet grey pair disappeared into the paper.
   Keep the controls aligned with the FIRST card row. At desktop scaling 14 cards can wrap to three
   rows; centring against the whole grid put both arrows below a 720px logical viewport. */
.sb-style-page-nav {
  appearance: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 45%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-emerald) 10%, var(--rk-surface));
  color: var(--rk-emerald);
  box-shadow: var(--rk-shadow-card);
  cursor: pointer;
  transition: border-color 180ms ease-out, color 180ms ease-out, background 180ms ease-out, opacity 180ms ease-out;
}

.sb-storybook-style-step .sb-style-page-nav {
  align-self: start;
  margin-block-start: clamp(72px, 9vw, 160px);
}

/* Match the comic style catalogue's tall edge controls on desktop. The storybook layout switches
   to its compact arrangement at 1020px, so keep the shared circular pager below that breakpoint. */
@media (min-width: 1021px) {
  .sb-storybook-style-step .sb-style-grid-shell {
    grid-template-columns: 48px minmax(0, 1fr) 48px;
  }

  .sb-storybook-style-step .sb-style-page-nav {
    align-self: center;
    width: 48px;
    height: 104px;
    margin-block-start: 0;
    border-radius: 999px;
  }

  .sb-storybook-style-step .sb-style-page-nav:disabled {
    opacity: 0.4;
  }
}

@media (min-width: 1021px) and (max-height: 980px) {
  .sb-storybook-style-step .sb-style-page-nav {
    transform: translateY(-48px);
  }
}

.sb-style-page-nav:hover:not(:disabled) {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.sb-style-page-nav:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 3px;
}

.sb-style-page-nav:disabled {
  opacity: 0.28;
  cursor: default;
  box-shadow: none;
}

.sb-style-page-nav svg {
  width: 20px;
  height: 20px;
  stroke-width: 1.8;
}

.sb-style-page-nav.is-previous svg {
  transform: rotate(90deg);
}

.sb-style-page-nav.is-next svg {
  transform: rotate(-90deg);
}

.sb-style-thumb {
  display: grid;
  width: 100%;
  border: 2px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  overflow: hidden;
  padding: 0;
  text-align: start;
  transition: border-color 180ms ease-out, transform 180ms ease-out;
}

.sb-style-thumb:hover {
  transform: translateY(-2px);
}

.sb-style-thumb.is-active {
  border-color: var(--rk-emerald);
}

/* Portrait card box (Andy 2026-07-30): the shelf shows each style's CHARACTER showcase, so the box
   takes that image's proportions instead of the old 16:9 scene crop. `center top` keeps the face
   intact on the one published style whose art is 2:3 rather than 3:4 (only the feet lose a sliver). */
.sb-style-thumb-media {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  background: var(--rk-paper-2);
  overflow: hidden;
}

.sb-style-thumb-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}

/* Caption row under the picture: the NAME alone owns the full width (Andy round 3 — a chip beside
   it crowded long names). Full name surfaces on hover via the button title. */
.sb-style-thumb-caption {
  display: block;
  padding: 7px 10px 8px;
  min-width: 0;
}

.sb-style-thumb-name {
  display: block;
  min-width: 0;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--rk-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sb-style-thumb.is-active .sb-style-thumb-name {
  color: var(--rk-emerald);
}

/* Model chip lives ON the artwork, bottom-left (Andy round 3), quiet translucent ink. The locked
   check sits top-right so the two never collide. */
.sb-style-thumb-chip {
  position: absolute;
  inset-block-end: 5px;
  inset-inline-start: 5px;
  max-width: calc(100% - 10px);
  overflow: hidden;
  text-overflow: ellipsis;
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-ink) 60%, transparent);
  color: var(--rk-paper);
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  white-space: nowrap;
  pointer-events: none;
}

.sb-style-thumb:hover {
  box-shadow: var(--rk-shadow-card);
}

/* The locked style's next-step CTA: FLOATS above the bottom of the VIEWPORT, always visible with
   zero scrolling (Andy 2026-07-29 — many users are novices; if the next step isn't on screen they
   churn). The row spans the viewport but only the button takes clicks. */
.sb-style-cta-row {
  position: fixed;
  inset-block-end: 22px;
  inset-inline: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.sb-style-cta-row .sb-style-next {
  pointer-events: auto;
  justify-self: center; /* the meta-column era gave .sb-style-next justify-self:start — beat it here */
  font-size: 1.02rem;
  padding: 14px 48px;
  box-shadow: var(--rk-shadow-panel);
}

/* Room under the grid so the floating CTA never sits on top of the pager or the last caption row. */
.sb-style-step.has-cta {
  padding-block-end: 92px;
}

/* Readkidz & Midjourney Asia Labs partnership line — shown whenever a Midjourney-family style is
   previewed (Andy 2026-07-29: the partnership is real; the line says the art is Midjourney-direct). */
.sb-style-partner {
  margin: 18px 0 0;
  padding-block-start: 12px;
  border-block-start: 1px solid var(--rk-line);
  color: var(--rk-ink-faint);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.sb-style-check {
  position: absolute;
  inset-block-start: 4px;
  inset-inline-end: 4px;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--rk-good);
  color: var(--rk-surface);
}

.sb-style-check svg {
  width: 14px;
  height: 14px;
}

.sb-style-soon {
  display: grid;
  justify-items: center;
  gap: 12px;
  text-align: center;
  padding: 8vh 20px;
  color: var(--rk-ink-soft);
}

.sb-style-soon img {
  width: 116px;
  height: auto;
}

@media (max-width: 1340px) {
  .sb-style-hero2 {
    height: min(36vh, 300px);
  }

  /* Portrait cards grow taller as they grow wider, so drop a column instead of letting them swell. */
  .sb-style-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

@media (max-width: 1140px) {
  .sb-style-hero2 {
    height: min(30vh, 250px);
  }
}

@media (max-width: 1020px) {
  .sb-style-workbench {
    grid-template-rows: auto auto;
    flex: none;
    overflow: visible;
  }

  .sb-style-focus {
    grid-template-columns: minmax(0, 1fr);
    gap: 20px;
    padding: 18px;
  }

  .sb-style-hero {
    width: min(100%, 860px);
    height: auto;
    max-height: none;
  }

  .sb-style-step {
    min-height: 0; /* small screens scroll; pinning the pager would crush the hero */
  }

  .sb-style-hero2 {
    height: auto;
    max-height: 44vh;
    justify-self: stretch;
  }

  .sb-style-hero2 .sb-style-scene {
    flex: 1 1 62%;
    height: auto;
  }

  .sb-style-hero2 .sb-style-char {
    flex: 1 1 30%;
    height: auto;
  }

  /* Four, not three: at ~1000px three portrait cards are 320px wide and 427px tall each. */
  .sb-style-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .sb-style-grid-shell {
    grid-template-columns: 36px minmax(0, 1fr) 36px;
    gap: 8px;
  }

  .sb-story-grid {
    grid-template-columns: minmax(0, 1fr);
    height: auto;
    flex: none;
  }

  .sb-prose-panel {
    min-height: 420px;
  }

  .sb-story-card {
    min-height: 420px;
    border-inline-start: 0;
    border-block-start: 1px solid var(--rk-line);
  }

  .sb-card-scroll,
  .sb-card-scroll:has(.sb-page-plan.is-expanded) {
    grid-template-rows: auto;
    align-content: start;
    overflow: visible;
  }

  .sb-page-plan.is-expanded {
    display: block;
  }

  .sb-page-plan-details {
    overflow: visible;
  }

  .sb-story-page,
  .sb-style-step {
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
  }

  .sb-flow-header,
  .sb-as-top {
    grid-template-columns: minmax(0, 1fr);
    gap: 10px;
  }

  .sb-flow-header > .sb-stepper,
  .sb-as-top > .sb-stepper {
    justify-self: stretch;
    justify-content: center;
    max-width: 100%;
    overflow-x: auto;
    padding-block: 4px;
    scrollbar-width: thin;
  }

  .sb-flow-balance:empty {
    display: none;
  }
}

@media (max-width: 600px) {
  .sb-flow-page,
  .sb-style-step {
    padding: 10px 12px 14px;
  }

  .sb-flow-header > .sb-stepper {
    justify-content: flex-start;
    overflow-x: auto;
    padding-block: 4px;
  }

  .sb-style-top {
    grid-template-columns: minmax(0, 1fr);
    gap: 8px;
  }

  .sb-style-top > .sb-stepper {
    justify-self: stretch;
    justify-content: center;
  }

  .sb-flow-title,
  .sb-flow-divider {
    display: none;
  }

  .sb-style-tabs {
    width: 100%;
  }

  .sb-style-tab {
    min-width: 0;
    flex: 1;
    padding-inline: 12px;
  }

  .sb-style-workbench {
    border-radius: var(--rk-radius-sm);
  }

  .sb-style-focus {
    gap: 16px;
    padding: 14px;
  }

  .sb-style-hero,
  .sb-style-hero.is-art {
    width: 100%;
    max-width: 100%;
    height: auto;
  }

  .sb-style-use,
  .sb-style-next {
    width: 100%;
    justify-content: center;
  }

  .sb-stepper {
    gap: 6px;
    font-size: 0.78rem;
  }

  .sb-step-sep {
    width: 14px;
  }

  .sb-style-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .sb-style-grid-shell {
    grid-template-columns: 34px minmax(0, 1fr) 34px;
    gap: 6px;
    padding: 9px 8px 10px;
  }

  .sb-style-page-nav {
    width: 34px;
    height: 34px;
  }

  .sb-storybook-style-step .sb-style-page-nav { margin-block-start: 18px; }

  .sb-style-hero2 {
    flex-wrap: wrap;
    max-height: none;
  }

  .sb-style-thumb {
    width: 78px;
    height: 78px;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ── Storybook generating landing (thinking screen) + typewriter reveal ─────────────────────────── */
.sb-thinking {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 14px;
  min-height: calc(100vh - 64px);
  padding: 40px 24px;
  /* Warm paper wash, same value as the global loading scrim (lib/loading.js). Originally required
     to match pudding-write.gif's baked frame background; the GIF is transparent since 2026-08-03,
     so this is now purely a surface choice. */
  background: #f8f5ee;
}
/* Writing-Pudding GIF (pudding-write.gif) — carries its own motion (paw/pencil scribbling), so no
   CSS float; the frame bg matches .sb-thinking above. */
.sb-think-cat {
  width: 150px;
  height: 150px;
  object-fit: contain;
}
.sb-think-line {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: clamp(1.25rem, 2.4vw, 1.7rem);
  font-weight: 700;
  color: var(--rk-ink);
  letter-spacing: 0.2px;
}
/* Sub-line under the thinking headline — used by the pipeline loading screens converted from
   .sb-empty-state to the animated .sb-thinking (Planning your cast… / Writing your story…). */
.sb-think-sub {
  margin: 0;
  max-width: 42ch;
  color: var(--rk-ink-soft);
  font-size: 1rem;
}
.sb-think-dots {
  display: inline-flex;
  gap: 7px;
}
.sb-think-dots span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--rk-emerald);
  opacity: 0.35;
  animation: sb-think-dot 1.2s ease-in-out infinite;
}
.sb-think-dots span:nth-child(2) { animation-delay: 0.18s; }
.sb-think-dots span:nth-child(3) { animation-delay: 0.36s; }
@keyframes sb-think-dot {
  0%, 100% { opacity: 0.3; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-4px); }
}

/* The editor handoff's two-step rail. It stands where the generic dots used to: one progress element,
   not two. The active node borrows the dots' own pulse so the screen still reads as alive, and a
   finished node keeps its tick — the author can see the first half really is behind them. */
.sb-prep-rail {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.sb-prep-rail-step {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--rk-ink-muted);
  font-size: 0.78rem;
  font-weight: 700;
}
/* The connector between the two nodes — drawn on the step itself so the markup stays one <li> per
   step, with nothing decorative in between for a screen reader to read out. */
.sb-prep-rail-step + .sb-prep-rail-step::before {
  content: '';
  width: 26px;
  height: 1px;
  background: var(--rk-line);
}
.sb-prep-rail-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--rk-line);
  background: transparent;
}
.sb-prep-rail-mark svg { width: 11px; height: 11px; }
.sb-prep-rail-step.is-done { color: var(--rk-ink-soft); }
.sb-prep-rail-step.is-done .sb-prep-rail-mark {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: #fff;
}
.sb-prep-rail-step.is-active { color: var(--rk-ink); }
.sb-prep-rail-step.is-active .sb-prep-rail-mark {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  animation: sb-think-dot 1.2s ease-in-out infinite;
}
.sb-prep-rail-step.is-pending .sb-prep-rail-mark { opacity: 0.55; }

@media (max-width: 520px) {
  /* Narrow screens: stack the two nodes and drop the connector, which has no room to mean anything. */
  .sb-prep-rail { flex-direction: column; align-items: flex-start; gap: 8px; }
  .sb-prep-rail-step + .sb-prep-rail-step::before { display: none; }
}
.sb-think-elapsed {
  margin: 0;
  font-size: 0.85rem;
  color: var(--rk-ink-muted);
  font-variant-numeric: tabular-nums;
  min-height: 1.1em;
}
/* Editor handoff (book-prep). It borrows the thinking screen wholesale — same paper wash, same
   mascot, same rhythm — because it IS the same kind of moment, and inventing a second waiting
   language would only make the pipeline feel like two products.
   The one addition is a way out. It sits in the corner rather than under the mascot: this wait can
   be minutes and the extraction behind it keeps running whether or not anyone watches, so leaving
   must be available — but a control in the middle of a waiting ceremony reads as something to do,
   and there is nothing to do here. Corner-left is where every other v3 step keeps its home icon. */
.sb-book-prep-page {
  position: relative;
}
.sb-book-prep-home {
  position: absolute;
  inset-block-start: 18px;
  inset-inline-start: 18px;
}
/* The failure twin. The named-entity list is the only thing this state adds over a plain empty
   state, and it must not run away down the page when a book has a large cast. */
.sb-book-prep-failed .sb-book-list {
  max-block-size: 34vh;
  text-align: start;
}
.sb-think-seed {
  margin: 6px 0 0;
  max-width: 44ch;
  font-style: italic;
  color: var(--rk-ink-soft);
  line-height: 1.5;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Blinking caret on the paragraph currently being typed */
.sb-prose-scroll.is-typing > .sb-prose-p:last-of-type::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-inline-start: 2px;
  vertical-align: -0.15em;
  background: var(--rk-emerald);
  animation: sb-caret 1s steps(1) infinite;
}
@keyframes sb-caret {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* Generation-error actions (retry + home) */
.sb-gen-actions {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: center;
  margin-top: 8px;
}
.sb-gen-home {
  color: var(--rk-ink-soft);
  text-decoration: none;
  font-weight: 600;
  padding: 9px 14px;
}
.sb-gen-home:hover { color: var(--rk-emerald); }

/* Narrower reading measure for the co-creation prose (−20%); the reclaimed width goes to the card */
.sb-prose-scroll > .sb-prose-title,
.sb-prose-scroll > .sb-prose-p {
  max-width: 660px;
  margin-inline: auto;
}

/* ── Selection quick-edit toolbar — floats over a text selection in the prose (Notion-style) ─────── */
.sb-sel-toolbar {
  position: fixed;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  box-shadow: var(--rk-shadow-panel);
  opacity: 0;
  transform: translateY(4px) scale(0.98);
  transition: opacity 120ms ease-out, transform 120ms ease-out;
}
.sb-sel-toolbar.is-in {
  opacity: 1;
  transform: none;
}
.sb-sel-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 0;
  background: transparent;
  color: var(--rk-ink);
  font-size: 0.86rem;
  font-weight: 600;
  padding: 6px 11px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 120ms ease-out, color 120ms ease-out;
}
.sb-sel-chip:hover {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}
.sb-sel-chip.is-custom { color: var(--rk-ink-soft); }
.sb-sel-chip.is-custom svg { width: 15px; height: 15px; }
.sb-sel-div {
  width: 1px;
  align-self: stretch;
  margin: 3px 2px;
  background: var(--rk-line);
}

.anim-sel-toolbar .sb-sel-chip {
  min-height: 40px;
}

.anim-stream .anim-line::selection {
  color: var(--rk-ink);
  background: var(--rk-emerald-soft);
}

/* Return-home icon — sits beside the back button in the shared flow header's left column */
.sb-home-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: var(--rk-radius-sm);
  color: var(--rk-ink-soft);
  transition: background 150ms ease-out, color 150ms ease-out;
}
.sb-home-icon svg { width: 20px; height: 20px; }
.sb-home-icon:hover { background: var(--rk-paper-2); color: var(--rk-emerald); }

/* ── Asset step (pipeline Step 3): global-asset workbench canvas ─────────────── */
/* "Continue — Create the cast" — the next-step CTA the locked style now exposes. */
.sb-style-next {
  justify-self: start;
  margin-top: 12px;
  padding: 0 24px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* The 560px floor keeps the workbench usable on normal screens, but it must never out-vote the
   viewport: at ≤565px of visible height the floor pushed the canvas past the fold and took the
   bottom-right "Make the book" CTA with it — the one control that ends this step (QA Q16). Clamping
   the floor to what the viewport actually has keeps the CTA on the first screen; the canvas itself
   pans and zooms, so it loses nothing by being shorter. */
.sb-assets {
  display: flex;
  flex-direction: column;
  gap: 14px;
  height: calc(100vh - 64px);
  min-height: min(560px, calc(100vh - 64px));
}

.sb-as-top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}

/* Compact global-assets header: Home is a distinct destination from the editor return in the canvas.
   Equal 34px edge tracks keep the page name centred independently of that left control. */
.sb-as-top.is-title-only {
  grid-template-columns: 34px minmax(0, 1fr) 34px;
  justify-items: center;
  min-height: 34px;
}

.sb-as-title {
  max-width: 100%;
  margin: 0;
  overflow: hidden;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1.06rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-ops-asset-notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
  padding: 10px 14px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 42%, var(--rk-line));
  border-radius: var(--rk-radius);
  background: color-mix(in srgb, var(--rk-emerald) 8%, var(--rk-surface));
  color: var(--rk-ink);
}

.sb-ops-asset-notice-icon {
  display: inline-flex;
  flex: none;
  color: var(--rk-emerald);
}

.sb-ops-asset-notice-icon svg { width: 20px; height: 20px; }
.sb-ops-asset-notice > div { min-width: 0; }
.sb-ops-asset-notice strong { display: block; font-size: 0.82rem; line-height: 1.3; }
.sb-ops-asset-notice p {
  margin: 2px 0 0;
  color: var(--rk-ink-soft);
  font-size: 0.76rem;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

/* Two notices, one plate: the style-alignment warning and the blocked-batch reason are the same class
   of message (something about this canvas needs saying, and neither has a control of its own), so they
   share these rules rather than growing a second near-identical copy of them. */
.sb-character-style-warning,
.sb-run-blocked {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-width: 0;
  padding: 10px 14px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 45%, var(--rk-line));
  border-radius: var(--rk-radius);
  background: color-mix(in srgb, var(--rk-warn) 8%, var(--rk-surface));
  color: var(--rk-ink);
}

.sb-character-style-warning-icon,
.sb-run-blocked-icon {
  display: inline-flex;
  flex: none;
  color: var(--rk-warn);
}

.sb-character-style-warning-icon svg,
.sb-run-blocked-icon svg {
  width: 20px;
  height: 20px;
}

.sb-character-style-warning > div,
.sb-run-blocked > div { min-width: 0; }
.sb-character-style-warning strong,
.sb-run-blocked strong { display: block; font-size: 0.82rem; line-height: 1.3; }
.sb-character-style-warning p,
.sb-run-blocked p {
  margin: 2px 0 0;
  color: var(--rk-ink-soft);
  font-size: 0.76rem;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

/* Same plate as the style-alignment note beside it — this is the same class of message (something on
   this canvas cannot proceed) — with one action on the end, because unlike that note this one has a
   fix the author can press. */
.sb-appearance-gap {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 10px 14px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 45%, var(--rk-line));
  border-radius: var(--rk-radius);
  background: color-mix(in srgb, var(--rk-warn) 8%, var(--rk-surface));
  color: var(--rk-ink);
}

.sb-appearance-gap-icon {
  display: inline-flex;
  flex: none;
  color: var(--rk-warn);
}

.sb-appearance-gap-icon svg { width: 20px; height: 20px; }
.sb-appearance-gap > div { min-width: 0; flex: 1; }
.sb-appearance-gap strong { display: block; font-size: 0.82rem; line-height: 1.3; }
.sb-appearance-gap p {
  margin: 2px 0 0;
  color: var(--rk-ink-soft);
  font-size: 0.76rem;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.sb-appearance-gap-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper);
  color: var(--rk-ink);
  padding: 7px 15px;
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 800;
  cursor: pointer;
  transition: border-color 150ms ease-out, background 150ms ease-out, color 150ms ease-out;
}

.sb-appearance-gap-action:hover:not(:disabled) {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: #fff;
}

.sb-appearance-gap-action:disabled { opacity: 0.6; cursor: default; }

.sb-identity-reviews {
  display: grid;
  grid-template-columns: minmax(220px, 0.8fr) minmax(0, 1.7fr);
  gap: 14px;
  padding: 12px 14px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 45%, var(--rk-line));
  border-radius: var(--rk-radius);
  background: color-mix(in srgb, var(--rk-warn) 8%, var(--rk-surface));
}

.sb-identity-review-head,
.sb-identity-review-card,
.sb-identity-review-actions {
  display: flex;
  align-items: center;
}

.sb-identity-review-head { gap: 10px; min-width: 0; }
.sb-identity-review-head > svg { width: 22px; height: 22px; flex: none; color: var(--rk-warn); }
.sb-identity-review-head div { min-width: 0; }
.sb-identity-review-head strong { display: block; color: var(--rk-ink); }
.sb-identity-review-head p { margin: 2px 0 0; color: var(--rk-ink-soft); font-size: 0.76rem; line-height: 1.35; }
.sb-identity-review-list { display: grid; gap: 8px; min-width: 0; max-height: 144px; overflow: auto; }
.sb-identity-review-card { justify-content: space-between; gap: 12px; min-width: 0; padding: 8px 10px; border: 1px solid var(--rk-line); border-radius: var(--rk-radius-sm); background: var(--rk-surface); }
.sb-identity-review-copy { display: grid; grid-template-columns: auto auto; align-items: baseline; gap: 2px 8px; min-width: 0; }
.sb-identity-review-copy strong { color: var(--rk-ink); }
.sb-identity-review-copy span { color: var(--rk-emerald-hover); font-weight: 800; }
.sb-identity-review-copy small { grid-column: 1 / -1; color: var(--rk-ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sb-identity-review-actions { gap: 7px; flex: none; }
.sb-identity-review-actions button { min-height: 36px; padding: 0 12px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-surface); color: var(--rk-ink); font-weight: 800; }
.sb-identity-review-actions button.is-primary { border-color: var(--rk-emerald); background: var(--rk-emerald); color: #fff; }
.sb-identity-review-actions button:disabled { opacity: 0.55; cursor: default; }

@media (max-width: 900px), (max-height: 700px) {
  .sb-identity-reviews { grid-template-columns: 1fr; gap: 8px; padding: 10px 12px; }
  .sb-identity-review-head p { display: none; }
  .sb-identity-review-list { max-height: 118px; }
}

@media (max-width: 620px) {
  .sb-character-style-warning,
  .sb-ops-asset-notice { padding: 9px 11px; }
  .sb-identity-review-card { align-items: stretch; flex-direction: column; gap: 8px; }
  .sb-identity-review-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .sb-identity-review-actions button { width: 100%; padding-inline: 8px; }
}

/* The workbench viewport — a bordered paper surface with a faint dot grid; the stage pans/zooms inside. */
.sb-as-canvas {
  position: relative;
  flex: 1;
  min-height: 0;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background-color: var(--rk-paper-2);
  background-image: radial-gradient(circle, rgba(43, 42, 38, 0.05) 1.3px, transparent 1.4px);
  background-size: 22px 22px;
  overflow: hidden;
  cursor: grab;
  touch-action: none;
}

.sb-as-canvas.is-panning {
  cursor: grabbing;
}

/* Canvas chrome is a manipulation surface, not reading copy. Keep double-clicks from creating a
   native text range that competes with the next pan; the inspector is outside these scoped nodes. */
.sb-as-stage,
.sb-as-topright,
.sb-as-bottomright,
.sb-as-help {
  -webkit-user-select: none;
  user-select: none;
}

.sb-as-stage {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
}

.sb-as-edges {
  position: absolute;
  top: 0;
  left: 0;
  overflow: visible;
  pointer-events: none;
}

.sb-as-edge {
  fill: none;
  stroke: var(--rk-line);
  stroke-width: 2;
}

.sb-as-edge.is-chain {
  stroke: var(--rk-emerald);
  stroke-opacity: 0.5;
}

.sb-as-edge.is-bind {
  stroke: var(--rk-ink-muted);
  stroke-dasharray: 4 5;
  stroke-opacity: 0.6;
}

.sb-as-nodes {
  position: absolute;
  top: 0;
  left: 0;
}

/* Card geometry is 0.8× its pre-2026-08-01 size, matched number-for-number to NODE_W / NODE_H /
   NODE_BODY_H in story.js — the layout maths reads those, this draws them, and they must not drift. */
.sb-as-node {
  position: absolute;
  width: 189px;
  height: 195px;
  display: flex;
  flex-direction: column;
  background: var(--rk-surface);
  /* darker edge + stronger shadow so a light card reads clearly on the paper-2 dotted canvas */
  border: 1px solid var(--rk-composer-border);
  border-radius: var(--rk-radius);
  box-shadow: var(--rk-shadow-panel);
  overflow: hidden;
}

.sb-as-node.is-char {
  border-color: var(--rk-card-hover-border);
}

.sb-as-node.is-gated {
  opacity: 0.85;
}

.sb-as-node-media {
  position: relative;
  height: 120px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  /* white placeholder well — must NOT match the paper-2 canvas or empty cards vanish into it */
  background: var(--rk-surface);
  border-bottom: 1px solid var(--rk-line);
}

.sb-as-node.is-char .sb-as-node-media {
  background: var(--rk-emerald-soft);
}

.sb-as-node.is-gated .sb-as-node-media {
  border-bottom-style: dashed;
}

.sb-as-node-chip {
  position: absolute;
  top: 6px;
  left: 6px;
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  padding: 2px 6px;
  border-radius: 999px;
}

.sb-as-node-initial {
  width: 51px;
  height: 51px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--rk-surface);
  color: var(--rk-emerald);
  font-family: var(--rk-font-display);
  font-size: 1.36rem;
  font-weight: 800;
}

.sb-as-node-icon {
  display: inline-flex;
}

.sb-as-node-icon svg {
  width: 34px;
  height: 34px;
  color: var(--rk-ink-muted);
}

.sb-as-node-body {
  flex: 1;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

/* per-card actions: Generate (draw from the system prompt) + Edit (open the chat) */
.sb-as-node-actions {
  margin-top: auto;
  display: flex;
  gap: 5px;
}

/* 28px keeps a comfortable tap target at 0.8× scale — the card shrank, the reachable button did not
   shrink below what a pointer or thumb can land on. */
.sb-as-node-btn {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.7rem;
  cursor: pointer;
  transition: background 140ms ease-out, border-color 140ms ease-out;
}

.sb-as-node-btn svg { width: 13px; height: 13px; }
.sb-as-node-btn .spinner-sm { width: 12px; height: 12px; }

.sb-as-node-btn.is-gen {
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
}

.sb-as-node-btn.is-gen:hover:not(:disabled) { background: var(--rk-emerald-hover); }

.sb-as-node-btn.is-edit {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
}

.sb-as-node-btn.is-edit:hover:not(:disabled) { background: var(--rk-paper-2); border-color: var(--rk-card-hover-border); }
.sb-as-node-btn:disabled { opacity: 0.45; cursor: default; }

.sb-as-node-name {
  font-weight: 800;
  font-size: 0.82rem;
  color: var(--rk-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sb-as-node-sub {
  font-size: 0.68rem;
  color: var(--rk-ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sb-as-node-status {
  margin-top: auto;
  font-size: 0.64rem;
  color: var(--rk-ink-muted);
}

.sb-as-node.is-gated .sb-as-node-status {
  color: var(--rk-warn);
}

.sb-as-help {
  position: absolute;
  z-index: 4;
  top: 14px;
  left: 14px;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  box-shadow: var(--rk-shadow-card);
  cursor: pointer;
  transition: color 150ms ease-out, border-color 150ms ease-out, transform 150ms ease-out, box-shadow 150ms ease-out;
}

.sb-as-help svg { width: 22px; height: 22px; }
.sb-as-help:hover { color: var(--rk-emerald-hover); border-color: var(--rk-emerald); transform: translateY(-1px); box-shadow: var(--rk-shadow-panel); }
.sb-as-help:focus-visible { outline: 3px solid var(--rk-focus-ring); outline-offset: 2px; }

/* top-right cluster: progress pill + "Generate all" (bottom-right stays free for the next step) */
.sb-as-topright {
  position: absolute;
  top: 14px;
  right: 14px;
  display: flex;
  align-items: center;
  gap: 12px;
}

.sb-as-pill {
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 0 18px;
  font-weight: 800;
  font-size: 0.84rem;
  color: var(--rk-ink);
  box-shadow: var(--rk-shadow-card);
  white-space: nowrap;
}

/* ── one-click "Generate all" CTA ── */
.sb-as-generate {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 46px;
  padding: 0 22px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-family: var(--rk-font-display);
  font-weight: 800;
  font-size: 0.92rem;
  box-shadow: var(--rk-shadow-panel);
  cursor: pointer;
  transition: background 160ms ease-out, transform 120ms ease-out;
}

.sb-as-generate svg { width: 18px; height: 18px; }
.sb-as-generate:hover:not(:disabled) { background: var(--rk-emerald-hover); transform: translateY(-1px); }
.sb-as-generate:disabled { opacity: 0.7; cursor: default; }

/* Persistent keyboard/touch zoom: a centred footer below the infinite canvas, so controls never
   cover asset cards or compete with the in-canvas return action. */
.sb-as-zoom-controls {
  flex: none;
  align-self: center;
  width: max-content;
  min-height: 40px;
  padding: 4px 6px;
  display: flex;
  align-items: center;
  gap: 2px;
  border: 1px solid var(--rk-line);
  border-radius: 6px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  box-shadow: 0 10px 24px -16px rgba(43, 42, 38, 0.38);
}

.sb-as-zoom-button,
.sb-as-zoom-value {
  min-width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: var(--rk-ink);
  font: inherit;
  cursor: pointer;
  transition: background 150ms ease-out, color 150ms ease-out;
}

.sb-as-zoom-button {
  font-size: 1.1rem;
  line-height: 1;
}

.sb-as-zoom-value {
  min-width: 50px;
  padding-inline: 6px;
  font-size: 0.76rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.sb-as-zoom-button:hover:not(:disabled),
.sb-as-zoom-value:hover { background: var(--rk-paper-2); }
.sb-as-zoom-button:focus-visible,
.sb-as-zoom-value:focus-visible { outline: 3px solid var(--rk-focus-ring); outline-offset: 1px; }
.sb-as-zoom-button:disabled { color: var(--rk-ink-muted); cursor: default; opacity: 0.45; }

/* ── "Make the book" CTA (bottom-right → the handoff to the editor) ── */
.sb-as-bottomright {
  position: absolute;
  bottom: 18px;
  right: 18px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.sb-as-makebook {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 50px;
  padding: 0 26px;
  border: 1px solid var(--rk-emerald);
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-family: var(--rk-font-display);
  font-weight: 800;
  font-size: 0.98rem;
  box-shadow: var(--rk-shadow-card);
  cursor: pointer;
  transition: background 160ms ease-out, transform 120ms ease-out, box-shadow 160ms ease-out;
}

.sb-as-makebook svg { width: 19px; height: 19px; }
.sb-as-makebook:hover:not(:disabled) { transform: translateY(-1px); box-shadow: var(--rk-shadow-panel); }
.sb-as-makebook:disabled { opacity: 0.6; cursor: default; }

/* ready = every drawn character confirmed + sheeted → the CTA goes solid + primary */
.sb-as-makebook.is-ready {
  background: var(--rk-emerald);
  border-color: var(--rk-emerald);
  color: #fff;
  box-shadow: var(--rk-shadow-panel);
}
.sb-as-makebook.is-ready:hover:not(:disabled) { background: var(--rk-emerald-hover); }

/* Asset-canvas tutorial — opened from the quiet help control in the canvas corner. */
.rk-modal-panel.is-asset-tutorial {
  inline-size: min(840px, 100%);
  block-size: min(820px, 88vh);
  padding: 0;
  overflow: hidden;
}

.rk-modal-panel.is-asset-tutorial .rk-modal-body {
  min-block-size: 0;
  block-size: 100%;
}

.sb-as-tutorial {
  display: flex;
  flex-direction: column;
  min-block-size: 0;
  block-size: 100%;
}

.sb-as-tutorial-scroll {
  display: flex;
  flex: 1 1 auto;
  min-block-size: 0;
  flex-direction: column;
  gap: 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  padding: 30px 32px 20px;
}

.sb-as-tutorial-head {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  align-items: start;
  gap: 16px;
  padding-inline-end: 38px;
}

.sb-as-tutorial-head-icon {
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border-radius: 16px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-as-tutorial-head-icon svg { width: 26px; height: 26px; }
.sb-as-tutorial h2 { margin: 0; color: var(--rk-ink); font-family: var(--rk-font-display); font-size: clamp(1.4rem, 2.6vw, 1.85rem); line-height: 1.2; }
.sb-as-tutorial-head p { margin: 7px 0 0; color: var(--rk-ink-soft); font-size: 0.94rem; line-height: 1.65; }

.sb-as-tutorial-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sb-as-tutorial-item {
  min-width: 0;
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr);
  align-items: start;
  gap: 11px;
  padding: 13px 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}

.sb-as-tutorial-item-icon {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  border: 1px solid var(--rk-line);
}

.sb-as-tutorial-item-icon svg { width: 19px; height: 19px; }
.sb-as-tutorial-item h3 { margin: 1px 0 4px; color: var(--rk-ink); font-size: 0.9rem; line-height: 1.25; }
.sb-as-tutorial-item p { margin: 0; color: var(--rk-ink-soft); font-size: 0.8rem; line-height: 1.5; overflow-wrap: anywhere; }

.sb-as-tutorial-tip {
  margin: 0;
  padding: 11px 14px;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 0.84rem;
  line-height: 1.5;
}

.sb-as-tutorial-actions {
  display: flex;
  flex: 0 0 auto;
  justify-content: flex-end;
  gap: 10px;
  padding: 18px 32px 22px;
  border-top: 1px solid var(--rk-line);
  background: var(--rk-surface);
}

.sb-as-tutorial-close,
.sb-as-tutorial-start {
  min-height: 44px;
  padding: 0 20px;
  border-radius: 999px;
  font-weight: 800;
  cursor: pointer;
}

.sb-as-tutorial-close { border: 1px solid var(--rk-line); background: var(--rk-surface); color: var(--rk-ink); }
.sb-as-tutorial-close:hover { background: var(--rk-paper-2); }
.sb-as-tutorial-start { border: 1px solid var(--rk-emerald); background: var(--rk-emerald); color: #fff; }
.sb-as-tutorial-start:hover { background: var(--rk-emerald-hover); }
.sb-as-tutorial-close:focus-visible,
.sb-as-tutorial-start:focus-visible { outline: 3px solid var(--rk-focus-ring); outline-offset: 2px; }

/* ── "Make the book" cost / blocked / preparing modal ── */
.sb-book-scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(24, 22, 18, 0.44);
}

.sb-book-modal {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 560px;
  max-height: calc(100vh - 48px);
  max-height: calc(100dvh - 48px);
  overflow: hidden;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 20px;
  padding: 30px 30px 26px;
  box-shadow: var(--rk-shadow-panel);
  text-align: center;
}

.sb-book-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  margin-bottom: 14px;
  border-radius: 50%;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}
.sb-book-icon svg { width: 27px; height: 27px; }
.sb-book-icon-warn { background: #fdeede; color: #b5651d; }

.sb-book-modal h2 {
  margin: 0 0 8px;
  font-family: var(--rk-font-display);
  font-size: 1.28rem;
  color: var(--rk-ink);
}

.sb-book-sub {
  margin: 0 auto;
  max-width: 340px;
  font-size: 0.94rem;
  line-height: 1.5;
  color: var(--rk-ink);
  opacity: 0.78;
}

/* [REMOVED 2026-08-01] .sb-book-cost / .sb-book-balance — the cost-preview rows of the 成书 and
   资产 cards. Both cards are gone (see story.js): one had been unreachable since C1 moved the handoff,
   the other was the layer feedback-rules-billing #343 retired. */

.sb-book-fine {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--rk-ink);
  opacity: 0.6;
}

.sb-book-list {
  min-height: 0;
  margin: 14px auto 12px;
  padding: 0;
  padding-inline-end: 6px;
  width: 100%;
  max-width: 340px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  list-style: none;
  text-align: left;
}
.sb-book-list li {
  padding: 8px 0 8px 22px;
  position: relative;
  font-size: 0.9rem;
  color: var(--rk-ink);
  border-bottom: 1px solid var(--rk-line);
}
.sb-book-list li:last-child { border-bottom: 0; }
.sb-book-list li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 15px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rk-emerald);
}

.sb-book-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 22px;
}

.sb-book-primary,
.sb-book-ghost {
  min-height: 46px;
  padding: 0 24px;
  border-radius: 999px;
  font-family: var(--rk-font-display);
  font-weight: 800;
  font-size: 0.92rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background 150ms ease-out, transform 120ms ease-out;
}
.sb-book-primary {
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
  box-shadow: var(--rk-shadow-panel);
}
.sb-book-primary:hover { background: var(--rk-emerald-hover); transform: translateY(-1px); }
.sb-book-ghost {
  border: 1px solid var(--rk-line);
  background: transparent;
  color: var(--rk-ink);
}
.sb-book-ghost:hover { background: var(--rk-paper-2, var(--rk-emerald-soft)); }

/* Prepare-the-book wait (Andy 2026-07-30): the running-Pudding GIF, larger, on the same warm wash
   .rk-app-loading uses. This was originally the GIF's own baked frame colour, needed so no box showed
   around the cat; the GIF is transparent since 2026-08-03, so the wash is now optional styling.
   The block still bleeds over the modal's padding so the whole sheet is one surface. */
.sb-book-prep {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin: -30px -30px -26px;
  padding: 28px 30px 30px;
  border-radius: 20px;
  background: #f8f5ee;
}

.sb-book-prep-cat {
  width: 210px;
  height: 210px;
  display: block;
}
.sb-book-prep .spinner-sm { width: 30px; height: 30px; }
.sb-book-prep h2 { margin: 0; }

@media (max-height: 760px) {
  .sb-book-scrim { padding-block: 12px; }

  .sb-book-modal {
    max-height: calc(100vh - 24px);
    max-height: calc(100dvh - 24px);
    padding-block: 20px 18px;
  }

  .sb-book-icon {
    width: 46px;
    height: 46px;
    margin-bottom: 10px;
  }

  .sb-book-icon svg { width: 23px; height: 23px; }
  .sb-book-list { margin-block: 10px 8px; }
  .sb-book-list li { padding-block: 6px; }
  .sb-book-actions { margin-top: 14px; }
}

/* ── node reveal states (image / spinner / gated / failed) ── */
.sb-as-node { cursor: pointer; transition: box-shadow 140ms ease-out, border-color 140ms ease-out; }
.sb-as-node:hover { border-color: var(--rk-card-hover-border); box-shadow: var(--rk-shadow-panel); }
/* Selected card (Andy 2026-07-30): orange and lifted, not a quiet emerald hairline. Arriving here from
   the editor's per-page panel means "this is the one you asked for" — on a canvas of near-identical
   cards a 1px colour change was not findable. Orange (#f97316, the same one the 就用这张 action uses)
   also stays distinct from every emerald control on the card. */
.sb-as-node.is-selected {
  z-index: 3;
  border-color: #f97316;
  box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.28), 0 18px 40px -22px rgba(43, 42, 38, 0.5);
  transform: scale(1.045);
  transition: transform 160ms ease-out, box-shadow 160ms ease-out, border-color 160ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .sb-as-node.is-selected { transform: none; }
}

.sb-as-node-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.sb-as-node.is-char .sb-as-node-img {
  object-position: center top;
}

/* Production sheets are wide technical assets (16:9 set library or 21:9 turnaround/fusion).
   Show the whole sheet in the canvas card instead of cropping its side views and detail column. */
.sb-as-node:not(.is-char) .sb-as-node-img {
  object-fit: contain;
  background: var(--rk-paper-2);
}

.sb-as-node-img.is-stale { opacity: 0.45; filter: saturate(0.7); }

.sb-as-node-zoom {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 3;
  width: 27px;
  height: 27px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.72);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.88);
  color: var(--rk-ink);
  box-shadow: var(--rk-shadow-card);
  cursor: pointer;
  transition: background 140ms ease-out, border-color 140ms ease-out, color 140ms ease-out, transform 120ms ease-out;
}

.sb-as-node-zoom svg {
  width: 14px;
  height: 14px;
}

.sb-as-node-zoom:hover,
.sb-as-node-zoom:focus-visible {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-as-node-zoom:hover {
  transform: translateY(-1px);
}

.sb-as-node-zoom:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring), var(--rk-shadow-card);
}

/* The outboard 「就用这张」 / 「同步到角色工坊」 row that used to float under a character card was
   removed on 2026-08-01. 「就用这张」 itself was dropped on 2026-08-04, taking its inspector button rule
   and the card's ✓ status-badge rules with it; workshop sync is the only action left over here. */

.sb-as-node-spin {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(250, 248, 244, 0.55);
}

.sb-as-node.is-state-rendering .sb-as-node-status { color: var(--rk-emerald); }
.sb-as-node.is-state-ready .sb-as-node-status { color: var(--rk-good); }
.sb-as-node.is-state-failed { border-color: var(--rk-danger); }
.sb-as-node.is-state-failed .sb-as-node-status { color: var(--rk-danger); }
/* the sub line carries the failure text (see sbAsNodeHtml) — a red border alone read as decoration */
.sb-as-node.is-state-failed .sb-as-node-sub { color: var(--rk-danger); }
.sb-as-node.is-state-gated-look,
.sb-as-node.is-state-gated-chain { opacity: 0.9; }
.sb-as-node.is-state-gated-look .sb-as-node-status,
.sb-as-node.is-state-gated-chain .sb-as-node-status { color: var(--rk-warn); }
.sb-as-node.is-state-unsupported { opacity: 0.55; }

.sb-image-viewer-scrim {
  position: fixed;
  inset: 0;
  z-index: 94;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(24, 22, 18, 0.5);
}

.sb-image-viewer {
  width: min(1040px, 100%);
  max-height: calc(100vh - 56px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 22px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
}

.sb-image-viewer-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
}

.sb-image-viewer-kicker {
  display: block;
  margin-bottom: 3px;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--rk-emerald);
}

.sb-image-viewer h2 {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.28rem;
  line-height: 1.15;
  color: var(--rk-ink);
}

.sb-image-viewer-close {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
}

.sb-image-viewer-close:hover {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-image-viewer-close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.sb-image-viewer-stage {
  min-height: 220px;
  max-height: min(72vh, 720px);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
}

.sb-image-viewer-stage img {
  max-width: 100%;
  max-height: min(72vh, 720px);
  width: auto;
  height: auto;
  display: block;
  object-fit: contain;
}

@media (max-width: 640px) {
  .sb-image-viewer-scrim {
    align-items: stretch;
    padding: 16px;
  }

  .sb-image-viewer {
    max-height: calc(100vh - 32px);
    padding: 18px;
  }

  .sb-image-viewer-stage {
    max-height: 68vh;
  }

  .sb-image-viewer-stage img {
    max-height: 68vh;
  }
}

/* ── node inspector card (image info + manual prompt edit + confirm-look) ── */
.sb-as-inspector {
  position: absolute;
  top: 12px;
  left: 12px;
  bottom: 12px;
  width: 350px;
  max-width: calc(100% - 24px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  overflow: hidden;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  box-shadow: var(--rk-shadow-panel);
  transform: translateX(-12px);
  opacity: 0;
  transition: transform 180ms ease-out, opacity 180ms ease-out;
  z-index: 5;
}

.sb-as-inspector.is-open { transform: translateX(0); opacity: 1; }

/* while the image (and its system prompt) is being generated, the prompt area locks with a hint */
.sb-as-insp-generating {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--rk-emerald);
}

.sb-as-insp-generate {
  flex: 1;
  min-height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-weight: 800;
  font-size: 0.86rem;
  cursor: pointer;
  transition: background 140ms ease-out;
}

.sb-as-insp-generate svg { width: 16px; height: 16px; }
.sb-as-insp-generate:hover:not(:disabled) { background: var(--rk-emerald-hover); }
.sb-as-insp-generate:disabled { opacity: 0.5; cursor: default; }

.sb-as-insp-head {
  position: sticky;
  inset-block-start: 0;
  z-index: 2;
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-inline: -16px;
  padding-inline: 16px;
  min-height: 38px;
  background: var(--rk-surface);
  box-shadow: 0 -16px 0 var(--rk-surface), 0 1px 0 var(--rk-line);
}

.sb-as-insp-tabs {
  flex: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
}

.sb-as-insp-tabs button {
  min-width: 0;
  min-height: 34px;
  padding-inline: 12px;
  overflow: hidden;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  font: 800 0.8rem/1 var(--rk-font-body);
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.sb-as-insp-tabs button.is-active {
  background: var(--rk-surface);
  color: var(--rk-emerald);
  box-shadow: 0 2px 8px rgba(35, 30, 24, 0.08);
}

.sb-as-insp-tabs button:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.sb-as-insp-scroll {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-inline-end: 3px;
  scrollbar-width: thin;
}

.sb-as-insp-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sb-as-insp-panel[hidden],
.sb-as-insp-footer > [hidden] {
  display: none !important;
}

.sb-as-insp-footer {
  flex: none;
  margin: 0 -16px -16px;
  padding: 12px 16px 16px;
  border-top: 1px solid var(--rk-line);
  background: var(--rk-surface);
  box-shadow: 0 -8px 18px rgba(35, 30, 24, 0.04);
}

.sb-as-insp-footer > div {
  display: flex;
  width: 100%;
}

.sb-as-insp-kind {
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
  background: var(--rk-paper-2);
  padding: 2px 8px;
  border-radius: 999px;
}

.sb-as-insp-name {
  flex: 1;
  font-family: var(--rk-font-display);
  font-size: 1.05rem;
  color: var(--rk-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sb-as-insp-close {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--rk-radius-sm);
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: pointer;
}

.sb-as-insp-close svg { width: 18px; height: 18px; }
.sb-as-insp-close:hover { background: var(--rk-paper-2); color: var(--rk-emerald); }

.sb-as-insp-media {
  position: relative;
  flex: 0 0 auto;
  border-radius: var(--rk-radius);
  overflow: hidden;
  background: var(--rk-paper-2);
  min-height: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.sb-as-insp-media img { width: 100%; display: block; }

.sb-as-insp-history {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sb-as-insp-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: var(--rk-ink-soft);
}

.sb-as-insp-history-head strong {
  color: var(--rk-ink);
  font-size: 0.82rem;
}

.sb-as-insp-history-head span {
  font-size: 0.7rem;
}

.sb-as-insp-history-strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 76px;
  gap: 8px;
  padding-block: 2px 6px;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: thin;
}

.sb-as-insp-version {
  position: relative;
  width: 76px;
  height: 76px;
  padding: 0;
  overflow: hidden;
  border: 2px solid transparent;
  border-radius: 12px;
  background: var(--rk-paper-2);
  cursor: pointer;
}

.sb-as-insp-version:hover,
.sb-as-insp-version:focus-visible {
  border-color: var(--rk-emerald);
  outline: none;
}

.sb-as-insp-version.is-current {
  border-color: var(--rk-emerald);
}

.sb-as-insp-version img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.sb-as-insp-version-number {
  position: absolute;
  inset: 5px auto auto 5px;
  min-width: 20px;
  height: 20px;
  display: inline-grid;
  place-items: center;
  padding-inline: 5px;
  border-radius: 999px;
  background: rgba(26, 31, 29, 0.72);
  color: #fff;
  font-size: 0.64rem;
  font-weight: 800;
}

.sb-as-insp-version em {
  position: absolute;
  inset: auto 4px 4px;
  overflow: hidden;
  padding: 3px 5px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-size: 0.58rem;
  font-style: normal;
  font-weight: 800;
  line-height: 1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-char-spec {
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}

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

.sb-char-spec-head h3 {
  margin: 0;
  font-size: 0.88rem;
  color: var(--rk-ink);
}

.sb-char-spec-head-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

.sb-char-spec-origin {
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-size: 0.64rem;
  font-weight: 700;
}

.sb-char-spec-origin.is-user { color: var(--rk-emerald); }

.sb-char-form-info {
  width: 22px;
  height: 22px;
  display: inline-grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font: 800 0.72rem/1 Georgia, serif;
  cursor: help;
}

.sb-char-form-info:hover,
.sb-char-form-info:focus-visible {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
  outline: 2px solid var(--rk-focus-ring);
  outline-offset: 1px;
}

.sb-char-form-options {
  margin: 9px 0 0;
  padding: 0;
  border: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}

.sb-char-form-options label {
  position: relative;
  min-width: 0;
  padding: 8px 4px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  text-align: center;
  cursor: pointer;
}

.sb-char-form-options label span {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-char-form-options label.is-selected {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-pale);
  color: var(--rk-emerald);
}
.sb-char-form-options label:focus-within { box-shadow: 0 0 0 2px var(--rk-focus-ring); }
.sb-char-form-options input { position: absolute; opacity: 0; pointer-events: none; }

.sb-char-form-popover {
  position: fixed;
  z-index: 1400;
  width: min(520px, calc(100vw - 24px));
  padding: 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: 0 18px 54px rgba(35, 30, 24, 0.18);
  pointer-events: none;
}

.sb-char-form-popover-head {
  margin-bottom: 9px;
  color: var(--rk-ink);
  font-size: 0.78rem;
  font-weight: 850;
}

.sb-char-form-popover-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.sb-char-form-popover article {
  min-width: 0;
  padding: 6px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
}

.sb-char-form-popover img {
  width: 100%;
  aspect-ratio: 1;
  display: block;
  object-fit: cover;
  border-radius: calc(var(--rk-radius-sm) - 3px);
}

.sb-char-form-popover strong {
  display: block;
  margin-top: 6px;
  color: var(--rk-ink);
  font-size: 0.7rem;
}

.sb-char-form-popover p {
  margin: 3px 0 0;
  color: var(--rk-ink-soft);
  font-size: 0.61rem;
  line-height: 1.35;
}

.sb-char-spec-feedback { margin: 7px 0 0; font-size: 0.68rem; line-height: 1.35; }
.sb-char-spec-feedback.is-success { color: var(--rk-good); }
.sb-char-spec-feedback.is-error { color: var(--rk-danger); }
/* A form pick that has not been drawn yet: advisory, not an error — it explains that the drawing on
   screen is still the old form and nothing was thrown away (Andy 2026-07-30). */
.sb-char-spec-feedback.is-pending { color: var(--rk-ink-soft); }

.sb-as-insp-ph {
  padding: 40px 0;
  color: var(--rk-ink-muted);
  font-size: 0.85rem;
}

/* Identity reference strip — the art a bound character (upload / library / series) is drawn FROM.
   Sits under the render slot so an empty slot still proves the upload reached this character. */
.sb-as-insp-refs {
  margin-top: 10px;
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}

.sb-as-insp-refs-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
  color: var(--rk-ink-muted);
  font-size: 0.68rem;
  font-weight: 900;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.sb-as-insp-refs-head em {
  color: var(--rk-emerald);
  font-style: normal;
  letter-spacing: 0;
  text-transform: none;
}

.sb-as-insp-refs-strip { display: flex; gap: 8px; }

.sb-as-insp-refs-strip img {
  width: 64px;
  height: 84px;
  flex: none;
  border-radius: 10px;
  background: var(--rk-paper);
  object-fit: cover;
  object-position: center top;
}

.sb-as-insp-refs .sb-as-insp-hint { margin-top: 8px; }

.sb-as-insp-spin {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(250, 248, 244, 0.5);
}

.sb-as-insp-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  font-size: 0.74rem;
  color: var(--rk-ink-soft);
}

.sb-as-insp-note { margin: 0; font-size: 0.82rem; color: var(--rk-warn); }
.sb-as-insp-err { margin: 0; font-size: 0.82rem; color: var(--rk-danger); }

/* The 「就用这张」 primary-button rule retired 2026-08-04 — see sbAsNodeHtml's header note. */

/* Only the is-sync variant survives: 「已在角色工坊」. */
.sb-as-insp-confirmed {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--rk-good);
  font-weight: 700;
  font-size: 0.86rem;
}

.sb-as-insp-confirmed svg { width: 17px; height: 17px; }

.sb-as-insp-confirmed.is-sync { color: var(--rk-ink-soft); }

/* Save to Character Studio — quiet secondary action (ink text + hairline; NOT emerald) */
.sb-as-insp-sync {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 38px;
  padding: 0 14px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font-weight: 700;
  font-size: 0.84rem;
  cursor: pointer;
}
.sb-as-insp-sync svg { width: 15px; height: 15px; }
.sb-as-insp-sync:hover:not(:disabled) { border-color: var(--rk-card-hover-border, var(--rk-ink-muted)); }
.sb-as-insp-sync:disabled { opacity: 0.5; cursor: default; }

/* "Make a sequel" — quiet secondary beside the Make-the-book CTA (emerald stays on the primary) */
.sb-as-sequel {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 50px;
  padding: 0 22px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-weight: 800;
  font-size: 0.92rem;
  cursor: pointer;
  box-shadow: 0 6px 18px -12px rgba(43, 42, 38, 0.18);
}
.sb-as-sequel svg { width: 16px; height: 16px; }
.sb-as-sequel:hover:not(:disabled) { border-color: var(--rk-card-hover-border, var(--rk-ink-muted)); }
.sb-as-sequel:disabled { opacity: 0.6; cursor: default; }

@media (max-width: 900px) {
  .sb-as-top { grid-template-columns: 1fr; }
  .sb-as-top .sb-back span { display: none; }
}

@media (max-width: 620px) {
  .sb-as-help { top: 10px; left: 10px; width: 42px; height: 42px; }
  .sb-as-topright { top: 10px; right: 10px; gap: 6px; }
  .sb-as-pill { display: none; }
  .sb-as-generate { min-height: 42px; padding: 0 16px; }
  .sb-as-bottomright {
    left: 10px;
    right: 10px;
    bottom: 10px;
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  .sb-as-sequel,
  .sb-as-makebook { width: 100%; min-height: 46px; padding: 0 12px; justify-content: center; }

  .rk-modal-panel.is-asset-tutorial { block-size: min(820px, calc(100dvh - 24px)); }
  .sb-as-tutorial-scroll { gap: 16px; padding: 24px 18px 18px; }
  .sb-as-tutorial-head { grid-template-columns: 44px minmax(0, 1fr); gap: 12px; padding-inline-end: 30px; }
  .sb-as-tutorial-head-icon { width: 44px; height: 44px; border-radius: 14px; }
  .sb-as-tutorial-list { grid-template-columns: 1fr; }
  .sb-as-tutorial-actions { padding: 12px 18px 18px; }
  .sb-as-tutorial-close,
  .sb-as-tutorial-start { flex: 1; min-width: 0; padding-inline: 12px; }
}

/* series ledger card (inside the shared .sb-book-modal) */
.sb-ledger-sum { display: flex; gap: 8px; justify-content: center; margin: 10px 0 14px; flex-wrap: wrap; }
.sb-ledger-chip {
  padding: 4px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.8rem;
  font-weight: 700;
}
.sb-ledger-label {
  display: block;
  margin: 10px 0 4px;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
  text-align: left;
}
.sb-ledger-input {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-size: 0.92rem;
}
.sb-ledger-input:focus { outline: none; border-color: var(--rk-emerald); box-shadow: var(--rk-focus-ring, 0 0 0 3px rgba(15, 164, 126, 0.18)); }
.sb-ledger-ending { resize: vertical; }
.sb-ledger-toggle {
  margin: 12px auto 0;
  display: inline-block;
  border: 0;
  background: none;
  color: var(--rk-emerald);
  font-weight: 700;
  font-size: 0.84rem;
  cursor: pointer;
}
.sb-ledger-details {
  margin-top: 10px;
  max-height: 260px;
  overflow-y: auto;
  text-align: left;
  border-top: 1px solid var(--rk-line);
  padding-top: 10px;
}
.sb-ledger-line { margin: 4px 0; font-size: 0.86rem; color: var(--rk-ink-soft); }
.sb-ledger-line strong { color: var(--rk-ink); }
.sb-ledger-rule { padding-inline-start: 10px; border-inline-start: 2px solid var(--rk-line); }
.sb-ledger-fact { display: flex; gap: 8px; align-items: flex-start; margin: 4px 0; font-size: 0.86rem; color: var(--rk-ink-soft); cursor: pointer; }
.sb-ledger-fact input { margin-top: 3px; accent-color: var(--rk-emerald); }

/* ledger coref guided card — "is X the same as Y?" (amber = the AI isn't sure; the author rules) */
.sb-ledger-coref {
  margin: 10px 0;
  padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 45%, var(--rk-line));
  border-radius: 12px;
  background: color-mix(in srgb, var(--rk-warn) 7%, var(--rk-surface));
  text-align: left;
}
.sb-ledger-coref-q { margin: 0 0 8px; font-size: 0.88rem; font-weight: 700; color: var(--rk-ink); }
.sb-ledger-coref-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.sb-ledger-coref-btn {
  padding: 6px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font-size: 0.82rem;
  font-weight: 700;
  cursor: pointer;
}
.sb-ledger-coref-btn.is-active {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
}
.sb-ledger-aka { font-style: normal; color: var(--rk-ink-muted); font-size: 0.8rem; }

/* series composer badge (home, /?series= mode) */
.sb-series-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 auto 10px;
  padding: 6px 14px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-ink);
  font-size: 0.86rem;
  font-weight: 700;
}
.sb-series-badge svg { width: 15px; height: 15px; color: var(--rk-emerald); }
.sb-series-exit {
  margin-inline-start: 4px;
  color: var(--rk-ink-muted);
  text-decoration: none;
  font-size: 1rem;
  line-height: 1;
}
.sb-series-exit:hover { color: var(--rk-ink); }

/* Native chapter writing reuses Home's input and intake behavior, but is a focused creation
   surface: the author stays visibly inside the current book and chapter rather than returning to
   the bookshelf's Home presentation. */
.rk-home-grid.is-native-chapter-composer {
  display: block;
  max-inline-size: 920px;
  margin-inline: auto;
}
.is-native-chapter-composer .rk-hero { min-block-size: 0; padding-block: clamp(26px, 6vh, 76px); }
.sb-native-chapter-head {
  display: flex;
  align-items: center;
  gap: 12px;
  max-inline-size: 760px;
  margin: 0 auto 22px;
}
.sb-native-chapter-back {
  display: grid;
  flex: none;
  place-items: center;
  inline-size: 42px;
  block-size: 42px;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  color: var(--rk-ink);
  background: var(--rk-surface);
}
.sb-native-chapter-back:hover,
.sb-native-chapter-back:focus-visible { border-color: var(--rk-emerald); color: var(--rk-emerald); outline: 0; }
.sb-native-chapter-back svg { inline-size: 20px; block-size: 20px; }
.sb-native-chapter-head p { margin: 0 0 3px; color: var(--rk-emerald); font-size: 12px; font-weight: 800; }
.sb-native-chapter-head h1 { margin: 0; font: 800 clamp(24px, 3vw, 36px)/1.1 var(--rk-font-display); }

/* returning-character chip on canvas nodes (book-1 confirmed look, zero re-render) */
.sb-as-node-chip.is-series {
  inset-inline-start: auto;
  inset-inline-end: 8px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
  border-color: var(--rk-emerald);
}

/* outfit three-state chips: reuse is a calm, settled state; a mismatch asks for a decision */
.sb-as-node-chip.is-outfit-reused,
.sb-as-node-chip.is-outfit-review {
  inset-inline-start: auto;
  inset-inline-end: 8px;
}

.sb-as-node-chip.is-outfit-reused {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
  border-color: var(--rk-emerald);
}

.sb-as-node-chip.is-outfit-review {
  background: var(--rk-surface);
  color: var(--rk-warn);
  border-color: var(--rk-warn);
}

.sb-as-outfit-review {
  display: grid;
  gap: 8px;
  margin: 10px 0 4px;
}

.sb-as-outfit-choice {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  text-align: start;
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: 12px;
  background: var(--rk-surface);
  cursor: pointer;
}

.sb-as-outfit-choice:disabled { opacity: 0.55; cursor: default; }
.sb-as-outfit-choice:not(:disabled):hover { border-color: var(--rk-ink-muted); }
.sb-as-outfit-choice.is-free { border-color: var(--rk-emerald); }
.sb-as-outfit-choice.is-quiet { background: transparent; }
.sb-as-outfit-choice svg { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 2px; }
.sb-as-outfit-choice span { display: grid; gap: 2px; min-width: 0; }
.sb-as-outfit-choice strong { font-size: 0.85rem; font-weight: 700; }
.sb-as-outfit-choice em { font-style: normal; font-size: 0.74rem; color: var(--rk-ink-muted); }

.sb-as-insp-label {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
}

.sb-as-prompt-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.sb-as-prompt-edit {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: background 140ms ease-out, border-color 140ms ease-out, color 140ms ease-out;
}

.sb-as-prompt-edit svg {
  width: 16px;
  height: 16px;
}

.sb-as-prompt-edit:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-as-prompt-edit:focus-visible {
  outline: none;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.sb-as-insp-prompt {
  box-sizing: border-box;
  flex: 0 0 auto;
  width: 100%;
  min-block-size: 160px;
  resize: vertical;
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-ink);
  font-family: var(--rk-font-body);
  font-size: 0.82rem;
  line-height: 1.5;
}

.sb-as-insp-prompt:focus { outline: none; border-color: var(--rk-emerald); box-shadow: 0 0 0 3px var(--rk-focus-ring); }

.sb-as-insp-actions {
  display: flex;
  gap: 8px;
}

.sb-as-insp-regen,
.sb-as-insp-redraw {
  flex: 1;
  min-height: 40px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.82rem;
  cursor: pointer;
  transition: background 140ms ease-out;
}

.sb-as-insp-regen {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
}

.sb-as-insp-regen:hover:not(:disabled) { background: var(--rk-paper-2); }

.sb-as-insp-redraw {
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
}

.sb-prompt-editor-scrim {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(24, 22, 18, 0.42);
}

.sb-prompt-editor {
  width: min(760px, 100%);
  max-height: min(760px, calc(100vh - 56px));
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 28px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
}

.sb-prompt-editor-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
}

.sb-prompt-editor-kicker {
  display: block;
  margin-bottom: 4px;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--rk-emerald);
}

.sb-prompt-editor h2 {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.55rem;
  color: var(--rk-ink);
}

.sb-prompt-editor-close {
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
}

.sb-prompt-editor-close:hover {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-prompt-editor-close:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.sb-prompt-editor-input {
  width: 100%;
  min-height: 360px;
  max-height: min(58vh, 520px);
  resize: vertical;
  padding: 16px 18px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
  color: var(--rk-ink);
  font-family: var(--rk-font-body);
  font-size: 1rem;
  line-height: 1.55;
}

.sb-prompt-editor-input:focus {
  outline: none;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.sb-prompt-editor-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.sb-prompt-editor-cancel,
.sb-prompt-editor-confirm {
  min-height: 44px;
  padding: 0 28px;
  border-radius: 999px;
  font-weight: 800;
  font-size: 0.92rem;
  cursor: pointer;
}

.sb-prompt-editor-cancel {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
}

.sb-prompt-editor-cancel:hover {
  background: var(--rk-paper-2);
}

.sb-prompt-editor-confirm {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
}

.sb-prompt-editor-confirm:hover {
  background: var(--rk-emerald-hover);
}

.sb-prompt-editor-confirm svg {
  width: 17px;
  height: 17px;
}

@media (max-width: 640px) {
  .sb-prompt-editor-scrim {
    align-items: stretch;
    padding: 16px;
  }

  .sb-prompt-editor {
    max-height: calc(100vh - 32px);
    padding: 22px;
  }

  .sb-prompt-editor-input {
    min-height: 300px;
  }

  .sb-prompt-editor-actions {
    flex-direction: column-reverse;
  }

  .sb-prompt-editor-cancel,
  .sb-prompt-editor-confirm {
    width: 100%;
  }
}

.sb-as-insp-redraw:hover:not(:disabled) { background: var(--rk-emerald-hover); }
.sb-as-insp-regen:disabled,
.sb-as-insp-redraw:disabled { opacity: 0.5; cursor: default; }

.sb-as-insp-hint { margin: 0; font-size: 0.74rem; color: var(--rk-ink-muted); }

/* ── art-desk chat strip (Pudding) inside the inspector ── */
.sb-as-chat {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.sb-as-chat-head {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-weight: 800;
  font-size: 0.8rem;
  color: var(--rk-ink);
}

.sb-as-chat-head svg { width: 16px; height: 16px; color: var(--rk-emerald); }

.sb-as-chat-log {
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow: visible;
}

.sb-as-chat-log:empty { display: none; }

.sb-as-chat-msg {
  max-width: 88%;
  padding: 7px 11px;
  border-radius: 14px;
  font-size: 0.82rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
}

.sb-as-chat-msg.is-user {
  align-self: flex-end;
  background: var(--rk-bubble-user);
  color: var(--rk-ink);
  border-bottom-right-radius: 4px;
}

.sb-as-chat-msg.is-ai {
  align-self: flex-start;
  background: var(--rk-bubble-ai);
  color: var(--rk-ink);
  border-bottom-left-radius: 4px;
}

.sb-as-chat-msg.is-error {
  align-self: flex-start;
  background: transparent;
  color: var(--rk-danger);
  padding-inline-start: 0;
}

.sb-as-chat-form {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
}

.sb-as-chat-input {
  flex: 1;
  min-width: 0;
  min-height: 40px;
  padding: 0 14px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper);
  color: var(--rk-ink);
  font-family: var(--rk-font-body);
  font-size: 0.84rem;
}

.sb-as-chat-input:focus { outline: none; border-color: var(--rk-emerald); box-shadow: 0 0 0 3px var(--rk-focus-ring); }
.sb-as-chat-input:disabled { opacity: 0.6; }

.sb-as-chat-send {
  width: 40px;
  height: 40px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 50%;
  background: var(--rk-emerald);
  color: #fff;
  cursor: pointer;
}

.sb-as-chat-send svg { width: 18px; height: 18px; }
.sb-as-chat-send:hover:not(:disabled) { background: var(--rk-emerald-hover); }
.sb-as-chat-send:disabled { opacity: 0.5; cursor: default; }

/* Storybook Visual Treatment — V3 paper-craft full-page proposal between style and assets. */
.sb-vt-page {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  padding: 14px clamp(18px, 3vw, 48px) 10px;
  overflow: hidden;
  /* One quiet publisher-paper fog connects Story, Style, and Concept. */
  background: color-mix(in srgb, var(--rk-paper-2) 34%, var(--rk-paper));
}

/* The site-wide ops strip already occupies normal document flow above this 100dvh workbench.
   Subtract its measured height so the footer stays inside the visible decision frame instead of
   following the page's strip-sized overflow. The narrow layout remains document-flow based below. */
@media (min-width: 981px) {
  .rk-has-opsbar .sb-vt-page {
    height: calc(100vh - var(--rk-opsbar-h, 0px));
    height: calc(100dvh - var(--rk-opsbar-h, 0px));
  }
}

html[lang="ar"] .sb-flow-title,
html[lang="ar"] .sb-prose-title,
html[lang="ar"] .sb-prose-p,
html[lang="ar"] .sb-card-title,
html[lang="ar"] .sb-settings-line,
html[lang="ar"] .sb-page-preview,
html[lang="ar"] .sb-style-meta,
html[lang="ar"] .sb-vt-moment p {
  direction: rtl;
  text-align: start;
}

.sb-vt-top {
  min-height: 46px;
  flex: none;
}

.sb-vt-stepper { justify-self: center; }

.sb-vt-workspace {
  width: min(1920px, 100%);
  height: auto;
  min-height: 0;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
  gap: 18px;
  flex: 1;
}

.sb-vt-brief,
.sb-vt-stage {
  min-width: 0;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: none;
  overflow: hidden;
}

.sb-vt-brief {
  display: flex;
  flex-direction: column;
  padding: 22px 20px 10px;
}

.sb-vt-brief-head {
  padding-bottom: 15px;
  border-bottom: 1px solid var(--rk-line);
}

.sb-vt-brief-label,
.sb-vt-moments-head,
.sb-vt-stage-label {
  color: var(--rk-ink-muted);
  font-size: 0.7rem;
  font-weight: 900;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

.sb-vt-brief-head strong {
  display: block;
  margin-top: 7px;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1.25rem;
  line-height: 1.2;
}

.sb-vt-moments-head {
  display: flex;
  justify-content: space-between;
  margin-block-start: 15px;
  padding: 0 2px 9px;
}

.sb-vt-moments {
  flex: 1;
  min-height: 0;
  margin: 0 -8px;
  padding: 0 8px 18px;
  list-style: none;
  overflow-y: auto;
}

.sb-vt-moment {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 10px;
  padding: 11px 3px;
  border-top: 1px dashed rgba(133, 112, 79, 0.16);
}

.sb-vt-moment-no {
  color: var(--rk-emerald);
  font-family: var(--rk-font-display);
  font-size: 0.73rem;
  font-weight: 900;
}

.sb-vt-moment p {
  display: -webkit-box;
  margin: 0;
  color: var(--rk-ink);
  font-size: 0.78rem;
  line-height: 1.45;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.sb-vt-stage {
  display: flex;
  flex-direction: column;
  padding: 16px;
  background: var(--rk-paper-2);
}

.sb-vt-stage.is-done {
  padding: 12px;
  background: var(--rk-paper-2);
}

.sb-vt-stage.is-done .sb-vt-stage-label {
  flex: none;
  padding: 1px 4px 10px;
  background: transparent;
}

.sb-vt-stage.is-done .sb-vt-board {
  width: 100%;
  border-radius: 0 0 24px 24px;
}

/* Caption band above the board: all-caps label · asset status · frame count. The status is the only
   sentence in here, so it takes the middle and the two captions hold the edges. */
.sb-vt-stage-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 1px 4px 12px;
}

.sb-vt-stage-label > span:first-child,
.sb-vt-stage-label > span:last-child {
  flex: none;
}

/* Trailing caption group. The free-board badge rides with the frame count instead of becoming a
   fourth flex child — space-between would otherwise scatter four items across the band. */
.sb-vt-stage-meta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}

/* 「首份提案免费」. Restored 2026-08-05: it used to sit in the page heading, which was removed on
   08-01 when this step was compacted. Like the asset status beside it, it sheds the band's
   uppercase/tracking — that treatment is for the two-word captions, not for a sentence that has to
   survive 25 languages. */
.sb-vt-free {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: none;
  padding: 5px 11px;
  border: 1px solid rgba(15, 164, 126, 0.22);
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
  font-size: 0.72rem;
  font-weight: 850;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
}

.sb-vt-free > svg { width: 14px; height: 14px; flex: none; }

.sb-vt-board {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Square along the top (Andy 2026-07-30): the rounded top corners left two dark wedges of this
     backdrop showing between the caption band and the artwork. The board butts flat against the band. */
  border-radius: 0 0 17px 17px;
  background: #171a18;
  overflow: hidden;
}

/* Same warm paper as the generating state — a revisit must not flash the dark board plate while we
   are only asking the server what the board's status is. */
.sb-vt-board.is-generating,
.sb-vt-board.is-checking {
  border: 1px solid rgba(83, 74, 58, 0.12);
  background: #f8f5ee;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.72);
}

/* Deliberately quiet: no ceremony, no progress bar. It says "checking", not "rendering". */
.sb-vt-checking {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Full ink, not muted: it is the only line on the plate, so it plays the ceremony title's role. */
  color: var(--rk-ink);
  font-size: 0.82rem;
}

.sb-vt-checking .spinner-sm {
  border-color: rgba(83, 74, 58, 0.18);
  border-top-color: var(--rk-emerald);
}

.sb-vt-board-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: var(--rk-paper-2);
  cursor: zoom-in;
}

.sb-vt-board-image img {
  width: 100%;
  height: 100%;
  display: block;
  /* Keep the decision surface visually filled; the existing lightbox carries the uncropped overview. */
  object-fit: cover;
  object-position: center top;
}

.sb-vt-board-image > span {
  position: absolute;
  inset-inline-end: 14px;
  bottom: 14px;
  padding: 7px 11px;
  border: 1px solid rgba(30, 143, 103, 0.28);
  border-radius: 999px;
  background: rgba(255, 253, 248, 0.94);
  color: var(--rk-emerald-hover);
  font-size: 0.72rem;
  font-weight: 800;
  box-shadow: var(--rk-shadow-card);
  opacity: 0;
  transform: translateY(4px);
  transition: 160ms ease;
}

.sb-vt-board-image:hover > span,
.sb-vt-board-image:focus-visible > span { opacity: 1; transform: translateY(0); }

/* A board the story has moved past: still shown (it was delivered and paid for) but visibly retired,
   with the only path to a fresh one being an explicit — and chargeable — click. */
.sb-vt-board.is-stale .sb-vt-board-image { cursor: zoom-in; }
.sb-vt-board.is-stale .sb-vt-board-image img { filter: grayscale(0.85) brightness(0.62); }

.sb-vt-stale-note {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 16px 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  background: linear-gradient(to top, rgba(23, 26, 24, 0.96), rgba(23, 26, 24, 0.72) 70%, transparent);
  color: var(--rk-paper);
}

.sb-vt-stale-note strong {
  flex: none;
  font-family: var(--rk-font-display);
  font-size: 1rem;
}

.sb-vt-stale-note p {
  flex: 1;
  min-width: 180px;
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  opacity: 0.82;
}

.sb-vt-stale-note button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: none;
  padding: 9px 15px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 800;
  cursor: pointer;
}

.sb-vt-stale-note button:hover { background: var(--rk-emerald-hover); }
.sb-vt-stale-note button svg { width: 15px; height: 15px; }

/* 「我已知晓」 ack (aligned to ebook-V2) — account-level, persisted when the author leaves via
   Continue. Andy 2026-07-30: it used to float as a paper card on the board's bottom-left, where it
   covered two frames of the panel strip. Now it is one plain line in the footer's left slot (the
   place the asset status vacated), so it never sits on the artwork. Kept as a <label> so the whole
   sentence stays clickable. */
.sb-vt-skip {
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  cursor: pointer;
  color: var(--rk-ink-soft);
  font-size: 0.74rem;
  font-weight: 600;
  line-height: 1.35;
}

.sb-vt-skip > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-vt-skip > span {
  min-width: 0;
}

.sb-vt-skip input {
  width: 15px;
  height: 15px;
  flex: none;
  accent-color: var(--rk-emerald);
  cursor: pointer;
}

.sb-vt-generating,
.sb-vt-failed {
  width: min(430px, 78%);
  text-align: center;
}

.sb-vt-generating { color: var(--rk-ink); }
.sb-vt-failed { color: #fff; }

.sb-vt-generating strong,
.sb-vt-failed strong {
  display: block;
  margin-top: 20px;
  font-family: var(--rk-font-display);
  font-size: 1.35rem;
}

.sb-vt-generating p,
.sb-vt-failed p { margin: 8px auto 18px; font-size: 0.82rem; line-height: 1.55; }
.sb-vt-generating p { color: var(--rk-ink-muted); }
.sb-vt-failed p { color: rgba(255,255,255,0.62); }

.sb-vt-orbit {
  position: relative;
  width: 84px;
  height: 84px;
  margin: 0 auto;
  border: 1px solid rgba(30, 143, 103, 0.22);
  border-radius: 50%;
  animation: sb-vt-spin 5s linear infinite;
}

.sb-vt-orbit::before {
  content: '';
  position: absolute;
  inset: 19px;
  border: 1px dashed rgba(83, 74, 58, 0.22);
  border-radius: 50%;
}

.sb-vt-orbit span { position: absolute; width: 9px; height: 9px; border-radius: 50%; background: #d89855; box-shadow: 0 0 14px rgba(216,152,85,0.34); }
.sb-vt-orbit span:nth-child(1) { left: 8px; top: 15px; }
.sb-vt-orbit span:nth-child(2) { right: 4px; top: 37px; background: #5ac89d; }
.sb-vt-orbit span:nth-child(3) { left: 37px; bottom: -4px; background: #f1dfba; }
@keyframes sb-vt-spin { to { transform: rotate(360deg); } }

.sb-vt-progress {
  height: 4px;
  border-radius: 999px;
  background: rgba(83, 74, 58, 0.10);
  overflow: hidden;
}

.sb-vt-progress span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
  transition: width 500ms ease;
}

.sb-vt-generating em { display: block; margin-top: 8px; color: var(--rk-ink-muted); font-size: 0.72rem; font-style: normal; }
.sb-vt-failed > svg { width: 40px; height: 40px; color: #eab07c; }
.sb-vt-failed button { padding: 9px 18px; border: 0; border-radius: 999px; background: #fff; color: #222; font-weight: 850; cursor: pointer; }
/* Balance failure on a charged re-render: recharge leads, retry stays as the secondary way out. */
.sb-vt-failed button + button { margin-inline-start: 10px; }
.sb-vt-failed .sb-vt-credits { background: var(--rk-emerald); color: #fff; }

.sb-vt-footer {
  width: min(1920px, 100%);
  min-height: 58px;
  margin: 10px auto 0;
  display: grid;
  /* ack tick · cost · actions (asset status moved up above the board, Andy 2026-07-30) */
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 16px;
  padding: 6px 8px 6px 14px;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  background: var(--rk-surface);
  box-shadow: none;
  flex: none;
}

@media (min-width: 981px) and (max-height: 760px) {
  .sb-vt-page { padding-block: 10px 8px; }
  .sb-vt-top { min-height: 42px; }
  .sb-vt-brief { padding: 18px 18px 8px; }
  .sb-vt-footer { min-height: 54px; margin-top: 8px; padding-block: 5px; }
}

/* Asset-extraction status. Lives in the band above the board (Andy 2026-07-30, moved out of the
   footer): ONE line, and it must shed the label row's uppercase/tracking — that treatment is for the
   two short all-caps captions beside it, and it makes a CJK sentence read as loose gibberish. */
.sb-vt-background-state {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  letter-spacing: normal;
  text-transform: none;
  font-weight: 700;
}
.sb-vt-background-state > svg { width: 16px; height: 16px; flex: none; color: var(--rk-emerald); }
.sb-vt-background-state strong { color: var(--rk-ink); font-size: 0.74rem; white-space: nowrap; }
.sb-vt-background-state small {
  color: var(--rk-ink-muted);
  font-size: 0.7rem;
  font-weight: 500;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* The third state. Only the icon changes colour — the caption keeps the ink of the two others because
   this band is a caption for the board, not an alert about it, and the retry beside it is the part that
   is supposed to draw the eye. */
.sb-vt-background-state.is-failed > svg { color: var(--rk-warn); }
/* Measured 2026-08-17: the retry pill adds ~89px that cannot shrink (flex: none) to a row whose only
   give was ellipsising the hint, so between the phone breakpoint and the desktop width the caption band
   pushed past its own bounds by ~17px. Let this row wrap while the failed state is up — the phone query
   below already does the same thing for the same reason. Scoped with :has so the two shipping states
   keep the exact single-line row they were designed with. */
.sb-vt-stage-label:has(.sb-vt-background-state.is-failed) { flex-wrap: wrap; }
.sb-vt-assets-retry {
  flex: none;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper);
  color: var(--rk-ink);
  padding: 3px 11px;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: normal;
  cursor: pointer;
  transition: border-color 150ms ease-out, background 150ms ease-out, color 150ms ease-out;
}
.sb-vt-assets-retry:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: #fff;
}
.sb-vt-cost { display: grid; gap: 2px; text-align: end; }
.sb-vt-cost span { color: var(--rk-ink-muted); font-size: 0.66rem; }
.sb-vt-cost strong { color: var(--rk-ink); font-size: 0.78rem; }
.sb-vt-next { min-width: 172px; min-height: 44px; padding-inline: 16px; font-size: 0.78rem; }
.sb-vt-next:disabled { opacity: 0.46; cursor: default; }
.sb-vt-actions { display: flex; align-items: center; gap: 10px; }
.sb-vt-upgrade { min-width: 168px; }
/* Size-and-type overrides only. The emerald plate itself comes from .sb-continue-btn, the same base
   every primary in this flow uses — this control is the normal way forward and must not read as the
   quiet alternative to the upgrade entry beside it. */
.sb-vt-stepwise {
  padding: 0 17px;
  font-family: var(--rk-font-body);
  font-size: 0.76rem;
  font-weight: 850;
  cursor: pointer;
  transition: background 150ms ease-out, border-color 150ms ease-out, box-shadow 150ms ease-out, transform 150ms ease-out;
}
.sb-vt-stepwise:hover:not(:disabled) {
  border-color: var(--rk-emerald-hover);
  background: var(--rk-emerald-hover);
  color: #fff;
  box-shadow: 0 10px 24px color-mix(in srgb, var(--rk-emerald) 28%, transparent);
  transform: translateY(-1px);
}
.sb-vt-stepwise:hover:not(:disabled) { background: var(--rk-emerald-hover); }
.sb-vt-stepwise:disabled { cursor: default; }

.sb-vt-watermark {
  position: absolute;
  inset-inline-end: 22px;
  bottom: 20px;
  color: rgba(255,255,255,0.82);
  font-family: var(--rk-font-display);
  font-size: clamp(1rem, 2vw, 1.65rem);
  font-style: normal;
  font-weight: 900;
  letter-spacing: 0.02em;
  text-shadow: 0 2px 9px rgba(0,0,0,0.7);
  pointer-events: none;
}

.sb-vt-lightbox {
  position: fixed;
  z-index: 1200;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 34px;
  background: rgba(10, 12, 11, 0.91);
}

.sb-vt-lightbox img { max-width: min(92vw, 1040px); max-height: 91vh; border-radius: 10px; box-shadow: 0 24px 80px rgba(0,0,0,0.45); }
.sb-vt-lightbox-close { position: fixed; inset-inline-end: 24px; top: 18px; width: 42px; height: 42px; border: 1px solid rgba(255,255,255,0.22); border-radius: 50%; background: rgba(0,0,0,0.28); color: #fff; font-size: 1.7rem; cursor: pointer; }

.sb-vt-upsell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 34px 30px 30px;
  text-align: center;
  background: radial-gradient(circle at 50% 0, rgba(216,152,85,0.14), transparent 42%);
}
.sb-vt-upsell-crown { width: 58px; height: 58px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid rgba(216,152,85,0.24); border-radius: 19px; background: #fff7ea; color: #c9823a; font-size: 1.75rem; box-shadow: 0 12px 30px rgba(176,112,49,0.13); }
.sb-vt-upsell h2 { margin: 2px 0 0; color: var(--rk-ink); font-family: var(--rk-font-display); font-size: 1.35rem; }
.sb-vt-upsell p { max-width: 340px; margin: 0; color: var(--rk-ink-muted); font-size: 0.84rem; line-height: 1.6; }
.sb-vt-upsell-actions { width: 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 8px; }
.sb-vt-upsell-actions > * { width: 100%; }

@media (max-width: 980px) {
  .sb-vt-page {
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    overflow: visible;
  }
  .sb-vt-top { grid-template-columns: minmax(0, 1fr); }
  .sb-vt-workspace { height: auto; min-height: 0; grid-template-columns: 1fr; }
  .sb-vt-brief { max-height: 330px; }
  .sb-vt-stage { min-height: 560px; }
  .sb-vt-footer { grid-template-columns: 1fr auto; }
  .sb-vt-cost { display: none; }
}

@media (max-width: 620px) {
  .sb-vt-page { padding-inline: 12px; }
  .sb-vt-stage { min-height: 430px; padding: 10px; }
  .sb-vt-footer { grid-template-columns: 1fr; gap: 12px; padding: 14px; }
  .sb-vt-actions, .sb-vt-next { width: 100%; }
  .sb-vt-actions { flex-direction: column; }
  .sb-vt-actions > * { width: 100%; }
  /* Phone: the caption band stacks and the ack gets the room to wrap instead of ellipsising away. */
  .sb-vt-stage-label { flex-wrap: wrap; }
  .sb-vt-background-state small { white-space: normal; }
  .sb-vt-skip > span { white-space: normal; }
}

/* Composer long-paste counter — appears once the text is clearly a paste (>=800 chars) */
.sb-premise-count {
  width: min(830px, 100%);
  margin: 2px auto 0;
  text-align: end;
  font-size: 0.8rem;
  color: var(--rk-ink-muted);
}

/* ═══ Animation home — TV hero (WP-02, concept design-v3-anim-2026-07/01-home-tv.html) ═══
   The TV is the frame-object grammar scaled up: dark wooden chassis (physical-object palette,
   same family as the mini-frame edge), warm off-white glow text, ONE emerald power dot.
   All color on the screen comes from the user's film — the chassis stays near-colorless. */
.anim-tv-stage {
  position: relative;
  margin: 54px auto 0;
  width: min(760px, 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.anim-tv {
  position: relative;
  width: min(640px, 100%);
  border-radius: 26px;
  padding: 18px 18px 20px;
  background: linear-gradient(180deg, #3a362e, #2b2a26 60%, #242320);
  box-shadow: var(--rk-shadow-object), inset 0 1px 0 rgba(255, 248, 238, 0.14);
  transition: transform 420ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
}

.anim-tv:hover {
  transform: translateY(-8px);
}

.anim-tv-screen {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  background: #171a1e;
}

/* glass sheen on top of whatever the screen shows */
.anim-tv-screen::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, rgba(255, 255, 255, 0.1) 0%, transparent 32%);
  pointer-events: none;
}

.anim-screen-cover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.anim-screen-title {
  position: absolute;
  inset-inline-start: 16px;
  inset-block-end: 14px;
  color: #fff8ee;
  font-size: 14.5px;
  font-weight: 700;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
}

.anim-screen-dur {
  position: absolute;
  inset-inline-end: 14px;
  inset-block-start: 12px;
  background: rgba(0, 0, 0, 0.42);
  color: #fff8ee;
  font-size: 11.5px;
  padding: 3px 9px;
  border-radius: 999px;
}

.anim-screen-play {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 0;
  background: rgba(250, 248, 244, 0.92);
  display: grid;
  place-items: center;
  box-shadow: 0 10px 26px -10px rgba(0, 0, 0, 0.5);
  cursor: pointer;
  transition: transform 0.18s;
}

.anim-screen-play:hover {
  transform: scale(1.06);
}

.anim-screen-play::after {
  content: '';
  margin-inline-start: 5px;
  border-inline-start: 20px solid var(--rk-emerald);
  border-top: 12px solid transparent;
  border-bottom: 12px solid transparent;
}

.anim-screen-msg {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
  color: #b9b2a4;
  font-size: 13.5px;
  line-height: 1.7;
  z-index: 2;
  padding: 0 24px;
}

.anim-screen-msg b {
  color: #fff8ee;
  font-size: 15px;
}

.anim-tv-chin {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 12px;
}

.anim-tv-brand {
  font-size: 10.5px;
  letter-spacing: 2.5px;
  color: #8d867a;
  font-weight: 700;
}

.anim-tv-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rk-emerald);
  box-shadow: 0 0 8px rgba(15, 164, 126, 0.8);
}

.anim-tv-legs {
  display: flex;
  gap: min(340px, 54%);
  margin-top: -2px;
}

.anim-tv-legs i {
  width: 12px;
  height: 34px;
  background: linear-gradient(180deg, #2b2a26, #4a443a);
  border-radius: 0 0 6px 6px;
  transform: skewX(-6deg);
}

.anim-tv-legs i:last-child {
  transform: skewX(6deg);
}

.anim-tv-ground {
  width: 74%;
  height: 16px;
  margin-top: -4px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(80, 60, 32, 0.55), transparent 68%);
  opacity: 0.5;
}

/* the shelf cat, napping on the TV top until a dedicated pose lands (asset recipe TODO) */
.anim-tv-cat {
  position: absolute;
  top: -58px;
  inset-inline-end: 64px;
  width: 118px;
  pointer-events: none;
  filter: drop-shadow(0 6px 8px rgba(80, 60, 32, 0.35));
  z-index: 2;
}

@media (max-width: 620px) {
  .anim-tv-cat { inset-inline-end: 24px; width: 92px; top: -46px; }
  .anim-tv { padding: 12px 12px 14px; border-radius: 20px; }
  .anim-tv-screen { border-radius: 10px; }
}

/* ═══ Animation home — series/episode library + compact preview TV ═══ */
.anim-home-workspace {
  width: min(1360px, 100%);
  margin: 42px auto 0;
  display: grid;
  grid-template-columns: minmax(0, 1.12fr) minmax(380px, 0.88fr);
  gap: 32px;
  align-items: start;
}

#anim-reel {
  min-width: 0;
  margin-top: 0;
}

.anim-home-workspace > #anim-tv-stage {
  min-width: 0;
  padding-block-start: 62px;
}

.anim-home-workspace > #anim-tv-stage .anim-tv-stage {
  width: 100%;
  margin: 0;
}

.anim-home-workspace > #anim-tv-stage .anim-tv {
  width: min(560px, 100%);
}

.anim-reel-head {
  margin: 0 0 16px;
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 18px;
}

.anim-reel-head h2 {
  font-size: 24px;
  font-weight: 800;
  color: var(--rk-ink);
}

.anim-reel-head p {
  margin-block-start: 4px;
  color: var(--rk-ink-soft);
  font-size: 14px;
  line-height: 1.5;
}

.anim-library-new {
  min-height: 42px;
  flex: 0 0 auto;
  padding-inline: 18px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font: 750 13px/1 var(--rk-font-body);
  cursor: pointer;
}

.anim-library-new:hover,
.anim-library-new:focus-visible {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
  outline: none;
}

.anim-series-list,
.anim-episode-list {
  display: grid;
  gap: 12px;
}

.anim-series-list {
  gap: 18px;
}

.anim-series-group {
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
  padding: 16px;
}

.anim-series-group-head {
  margin-block-end: 12px;
  padding-block-end: 11px;
  border-block-end: 1px solid var(--rk-line);
}

.anim-series-group-head > span,
.anim-episode-label {
  display: block;
  color: var(--rk-emerald-hover);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.anim-series-group-head h3 {
  margin-block-start: 3px;
  color: var(--rk-ink);
  font-size: 17px;
  line-height: 1.3;
}

.anim-episode-card {
  position: relative;
  min-width: 0;
  border: 1px solid var(--rk-line);
  border-radius: 14px;
  background: var(--rk-paper);
  overflow: hidden;
}

.anim-episode-main {
  width: 100%;
  min-width: 0;
  display: grid;
  grid-template-columns: 148px minmax(0, 1fr);
  gap: 14px;
  align-items: center;
  padding: 10px;
  padding-inline-end: 10px;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: start;
  font: inherit;
  cursor: pointer;
}

.anim-episode-card:has(.anim-episode-preview) .anim-episode-main {
  padding-inline-end: 104px;
}

.anim-episode-card:hover,
.anim-episode-card:has(.anim-episode-main:focus-visible) {
  border-color: var(--rk-emerald);
}

.anim-episode-main:focus-visible,
.anim-episode-preview:focus-visible {
  outline: 3px solid var(--rk-emerald-soft);
  outline-offset: -3px;
}

.anim-episode-poster {
  aspect-ratio: 16 / 9;
  border-radius: 10px;
  overflow: hidden;
  display: grid;
  place-items: center;
  background: var(--rk-paper-2);
  color: var(--rk-ink-muted);
}

.anim-episode-poster > span svg {
  width: 30px;
  height: 30px;
}

.anim-episode-poster img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.anim-episode-copy {
  min-width: 0;
  display: block;
}

.anim-episode-copy strong {
  display: block;
  margin-block-start: 3px;
  color: var(--rk-ink);
  font-size: 15px;
  line-height: 1.35;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.anim-episode-copy small {
  display: block;
  margin-block-start: 4px;
  color: var(--rk-ink-muted);
  font-size: 12px;
}

.anim-episode-open {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-block-start: 8px;
  color: var(--rk-emerald-hover);
  font-size: 12px;
  font-weight: 800;
}

.anim-episode-open i {
  display: grid;
  place-items: center;
}

.anim-episode-open svg {
  width: 14px;
  height: 14px;
}

.anim-episode-preview {
  position: absolute;
  inset-inline-end: 10px;
  inset-block-end: 10px;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding-inline: 12px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font: 750 12px/1 var(--rk-font-body);
  cursor: pointer;
}

.anim-episode-preview:hover {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
}

.anim-episode-preview svg {
  width: 14px;
  height: 14px;
}

@media (max-width: 1040px) {
  .anim-home-workspace {
    grid-template-columns: 1fr;
  }

  .anim-home-workspace > #anim-tv-stage {
    padding-block-start: 18px;
  }

  .anim-home-workspace > #anim-tv-stage .anim-tv-stage {
    margin-inline: auto;
  }
}

@media (max-width: 620px) {
  .anim-home-workspace { margin-block-start: 28px; }
  .anim-reel-head { align-items: start; }
  .anim-reel-head p { display: none; }
  .anim-series-group { padding: 12px; }
  .anim-episode-main {
    grid-template-columns: 112px minmax(0, 1fr);
    padding-inline-end: 10px;
  }
  .anim-episode-preview {
    position: static;
    margin: 0 10px 10px auto;
  }
}

.anim-reel-row {
  display: flex;
  gap: 22px;
  justify-content: center;
  flex-wrap: wrap;
}

.anim-reel-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

/* mini TV frame — same dark-chassis family as the hero TV (and the shelf frame-object) */
.anim-mini-frame {
  position: relative;
  width: 166px;
  height: 118px;
  border-radius: 14px;
  padding: 8px;
  background: #2e2b26;
  border: 1px solid #45403a;
  box-shadow: var(--rk-shadow-object);
  cursor: pointer;
  transition: transform 0.3s cubic-bezier(0.2, 0.9, 0.3, 1.2);
  font: inherit;
}

.anim-mini-frame:hover {
  transform: translateY(-8px);
}

.anim-mini-shot {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
  background: #171a1e;
}

.anim-mini-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.anim-mini-badge {
  position: absolute;
  inset-inline-end: 14px;
  inset-block-end: 14px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(250, 248, 244, 0.92);
  display: grid;
  place-items: center;
}

.anim-mini-badge::after {
  content: '';
  margin-inline-start: 2px;
  border-inline-start: 9px solid var(--rk-emerald);
  border-top: 5.5px solid transparent;
  border-bottom: 5.5px solid transparent;
}

.anim-reel-cap {
  font-size: 12.5px;
  color: var(--rk-ink-soft);
  max-width: 166px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.anim-mini-frame.is-rendering {
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  box-shadow: var(--rk-shadow-card);
}

.anim-mini-frame.is-rendering .anim-mini-shot {
  background: var(--rk-paper-2);
  display: grid;
  place-items: center;
}

.anim-prog {
  width: 70%;
  height: 5px;
  border-radius: 99px;
  background: #ede8dc;
  overflow: hidden;
}

.anim-prog i {
  display: block;
  width: 56%;
  height: 100%;
  background: var(--rk-emerald);
  border-radius: 99px;
  animation: anim-prog-slide 1.6s ease-in-out infinite alternate;
}

@keyframes anim-prog-slide {
  from { margin-inline-start: 0; }
  to { margin-inline-start: 44%; }
}

.anim-mini-frame.is-empty {
  background: transparent;
  border: 1.5px dashed var(--rk-line);
  box-shadow: none;
}

.anim-mini-frame.is-empty .anim-mini-shot {
  background: transparent;
  display: grid;
  place-items: center;
  color: var(--rk-ink-muted);
  font-size: 12px;
}

/* Animation home v3 — the television is the single entry object and owns the episode selector.
   Keep this structure physically left-to-right in every locale; translated text adapts inside it. */
.anim-home-workspace {
  width: min(1060px, 100%);
  margin: 28px auto 0;
  display: block;
  direction: ltr;
}

.anim-home-workspace[hidden] {
  display: none;
}

.anim-home-workspace > #anim-tv-stage {
  min-width: 0;
  padding: 0;
}

.anim-home-workspace > #anim-tv-stage .anim-tv-stage,
.anim-tv-stage {
  position: relative;
  width: min(1060px, 100%);
  margin: 0 auto;
  display: block;
}

.anim-home-workspace > #anim-tv-stage .anim-tv,
.anim-tv {
  --anim-tv-frame-pad: 14px;
  position: relative;
  width: min(940px, 100%);
  margin-inline: auto;
  padding: 14px 14px 0;
  border: 1px solid #b9ae9d;
  border-radius: 24px;
  background: #d8d0c2;
  box-shadow: 0 24px 54px -34px rgba(63, 52, 38, 0.52), inset 0 1px 0 rgba(255, 255, 255, 0.58);
  transform: none;
  transition: border-color 180ms ease-out, box-shadow 180ms ease-out, padding-block-end 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.anim-tv:hover {
  border-color: #aa9e8c;
  box-shadow: 0 28px 58px -34px rgba(63, 52, 38, 0.58), inset 0 1px 0 rgba(255, 255, 255, 0.58);
  transform: none;
}

.anim-tv-screen {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid #a79c8e;
  border-radius: 16px;
  background: #202728;
  box-shadow: inset 0 0 0 2px rgba(55, 47, 38, 0.18);
}

.anim-tv-screen::after {
  content: none;
}

.anim-tv-cat {
  position: absolute;
  z-index: 4;
  /* The sprite's chest ledge is at 78% of its square canvas. Align that ledge to
     the outer-frame top so the body rests on the frame and the paws hang over it. */
  top: -111px;
  right: 38px;
  width: 142px;
  pointer-events: none;
  filter: drop-shadow(0 7px 7px rgba(67, 53, 36, 0.2));
}

.anim-tv-chin {
  display: none;
}

.anim-tv-brand {
  color: #9b8f7f;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 3px;
}

.anim-tv-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--rk-emerald);
  box-shadow: none;
}

.anim-screen-media,
.anim-screen-shade,
.anim-screen-empty,
.anim-screen-loading {
  position: absolute;
  inset: 0;
}

.anim-screen-media {
  background: #202728;
}

button.anim-screen-media {
  width: 100%;
  padding: 0;
  border: 0;
  color: inherit;
  cursor: pointer;
}

.anim-screen-cover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.anim-screen-shade {
  z-index: 1;
  background: rgba(9, 15, 17, 0.43);
  pointer-events: none;
}

.anim-screen-shade.is-default {
  background: rgba(23, 31, 30, 0.42);
}

.anim-screen-default-art {
  object-position: center;
}

.anim-screen-poster-video {
  pointer-events: none;
}

.anim-screen-play {
  position: absolute;
  z-index: 3;
  top: 50%;
  left: 50%;
  width: 82px;
  height: 82px;
  display: grid;
  place-items: center;
  translate: -50% -50%;
  border: 4px solid var(--rk-emerald);
  border-radius: 50%;
  background: var(--rk-surface);
  box-shadow: 0 16px 38px -16px rgba(6, 12, 13, 0.86), 0 0 0 5px rgba(250, 248, 244, 0.48);
  cursor: pointer;
  transition: transform 180ms ease-out, background-color 180ms ease-out, border-color 180ms ease-out;
}

.anim-screen-play::after {
  content: '';
  display: block;
  margin-inline-start: 5px;
  border-inline-start: 21px solid var(--rk-emerald);
  border-top: 13px solid transparent;
  border-bottom: 13px solid transparent;
}

.anim-screen-play:hover,
.anim-screen-play:focus-visible {
  border-color: var(--rk-emerald-hover);
  background: var(--rk-surface);
  outline: 3px solid rgba(15, 164, 126, 0.28);
  outline-offset: 3px;
  transform: scale(1.06);
}

.anim-screen-play.is-pending {
  border-color: rgba(250, 248, 244, 0.2);
  background: rgba(250, 248, 244, 0.08);
  box-shadow: none;
  cursor: default;
  pointer-events: none;
}

.anim-screen-play.is-pending::after {
  border-inline-start-color: rgba(250, 248, 244, 0.42);
}

/* The poster shelf overlaps the bottom ~120px of the screen, so this block is centred against the
   VISIBLE part of it, not the whole screen: at 28% the 进入本集 button ended 6px above the shelf and
   read as clipped. 20% leaves it ~47px of breathing room. */
.anim-screen-copy {
  position: absolute;
  z-index: 2;
  top: 20%;
  left: 64px;
  width: min(420px, 46%);
  color: #fffaf1;
  text-align: left;
  unicode-bidi: plaintext;
}

.anim-screen-copy h2 {
  margin: 9px 0 0;
  color: inherit;
  font-size: clamp(24px, 2.2vw, 34px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.anim-screen-copy p {
  margin: 14px 0 0;
  color: rgba(255, 250, 241, 0.82);
  font-size: 14px;
  font-weight: 700;
}

.anim-screen-episode {
  color: #a4e5d1;
  font-size: 12px;
  font-weight: 850;
  letter-spacing: 0.06em;
}

.anim-screen-actions {
  margin-top: 26px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.anim-screen-primary,
.anim-screen-secondary {
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 0 26px;
  border-radius: 12px;
  font: 800 14px/1 var(--rk-font-body);
  cursor: pointer;
  transition: background-color 180ms ease-out, border-color 180ms ease-out;
}

.anim-screen-primary {
  border: 1px solid var(--rk-emerald);
  background: var(--rk-emerald);
  color: #fff;
}

.anim-screen-primary:hover,
.anim-screen-primary:focus-visible {
  border-color: var(--rk-emerald-hover);
  background: var(--rk-emerald-hover);
  outline: none;
}

.anim-screen-secondary {
  border: 1px solid rgba(255, 255, 255, 0.55);
  background: rgba(20, 28, 29, 0.55);
  color: #fffaf1;
}

.anim-screen-secondary:hover,
.anim-screen-secondary:focus-visible {
  border-color: #fffaf1;
  background: rgba(20, 28, 29, 0.72);
  outline: none;
}

.anim-screen-primary svg,
.anim-screen-secondary svg {
  width: 15px;
  height: 15px;
}

.anim-screen-forward {
  display: grid;
  transform: rotate(180deg);
}

.anim-screen-dur {
  z-index: 2;
  top: 18px;
  right: 18px;
  padding: 4px 9px;
  border-radius: 999px;
  background: rgba(15, 21, 22, 0.64);
  color: #fffaf1;
  font-size: 11px;
}

.anim-channel-drawer {
  position: relative;
  z-index: 5;
  display: grid;
  grid-template-rows: 1fr;
  width: min(1066px, 100%);
  margin: -144px auto 0;
  opacity: 1;
  transform: translateY(0);
  transform-origin: top center;
  transition: grid-template-rows 420ms cubic-bezier(0.22, 1, 0.36, 1), opacity 260ms ease-out, transform 420ms cubic-bezier(0.22, 1, 0.36, 1), margin-top 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.anim-channel-drawer-inner {
  position: relative;
  min-height: 0;
  overflow: hidden;
}

.anim-channel-bar {
  position: relative;
  isolation: isolate;
  width: calc(100% - 86px);
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  align-items: center;
  gap: 14px;
  padding: 17px 16px 15px;
  margin-inline: 43px;
  margin-bottom: 22px;
  overflow: visible;
  border: 1px solid color-mix(in srgb, var(--rk-frame-edge) 74%, var(--rk-surface));
  border-radius: 19px 19px 7px 7px;
  background: color-mix(in srgb, var(--rk-frame-bg) 86%, var(--rk-shelf-top-c));
  box-shadow:
    inset 0 3px 0 color-mix(in srgb, var(--rk-surface) 78%, transparent),
    inset 12px 0 18px -22px color-mix(in srgb, var(--rk-ink-soft) 42%, transparent),
    inset -12px 0 18px -22px color-mix(in srgb, var(--rk-ink-soft) 42%, transparent),
    0 -7px 18px -16px color-mix(in srgb, var(--rk-ink) 46%, transparent);
}

.anim-channel-board {
  position: absolute;
  z-index: 2;
  inset-inline-start: 0;
  inset-inline-end: auto;
  bottom: 0;
  width: 100%;
  height: 44px;
  display: block;
  object-fit: fill;
  pointer-events: none;
}

.anim-channel-list {
  min-width: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - 28px) / 3);
  align-items: stretch;
  /* Center a short row (1–2 films) on the shelf; safe keyword falls back to
     start-alignment once films overflow so horizontal scrolling still works. */
  justify-content: safe center;
  gap: 14px;
  overflow-x: auto;
  padding: 2px;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline mandatory;
  scrollbar-width: none;
}

.anim-channel-list::-webkit-scrollbar {
  display: none;
}

.anim-channel-card {
  position: relative;
  width: 100%;
  min-width: 0;
  display: block;
  padding: 7px 7px 12px;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--rk-ink-muted) 30%, transparent);
  border-block-end-width: 4px;
  border-block-end-color: color-mix(in srgb, var(--rk-ink-muted) 22%, var(--rk-paper-2));
  border-radius: 16px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  scroll-snap-align: start;
  box-shadow:
    0 5px 0 -1px color-mix(in srgb, var(--rk-paper-2) 76%, var(--rk-ink-muted)),
    0 14px 18px -13px color-mix(in srgb, var(--rk-ink) 42%, transparent),
    var(--rk-shadow-card);
  transform: perspective(1100px) rotateX(-1.6deg) translateY(2px);
  transform-origin: 50% 100%;
  transform-style: preserve-3d;
  transition: transform 180ms ease-out, border-color 180ms ease-out, box-shadow 180ms ease-out;
}

/* The card is a container now (it holds three buttons), so lift on :focus-within — :focus-visible
   would never match a div. */
.anim-channel-card:hover,
.anim-channel-card:focus-within {
  border-color: color-mix(in srgb, var(--rk-emerald) 55%, var(--rk-ink-muted));
  outline: none;
  transform: perspective(1100px) rotateX(-0.35deg) translateY(-4px);
  box-shadow:
    0 4px 0 -1px color-mix(in srgb, var(--rk-paper-2) 72%, var(--rk-ink-muted)),
    0 18px 22px -14px color-mix(in srgb, var(--rk-ink) 46%, transparent),
    var(--rk-shadow-object);
}

/* Card face = change channel. Fills the card so the whole surface stays one click target. */
.anim-channel-face {
  display: block;
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  border-radius: inherit;
  background: none;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.anim-channel-face:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

/* Play / open-pipeline. Hidden until the card is hovered or keyboard-focused so the shelf stays
   quiet; always visible on touch, where there is no hover to reveal them. */
.anim-channel-actions {
  position: absolute;
  z-index: 2;
  inset-block-start: 12px;
  inset-inline-end: 12px;
  display: flex;
  gap: 6px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 160ms ease-out, transform 160ms ease-out;
}

.anim-channel-card:hover .anim-channel-actions,
.anim-channel-card:focus-within .anim-channel-actions {
  opacity: 1;
  transform: none;
}

.anim-channel-action {
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--rk-paper) 34%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-ink) 78%, transparent);
  color: var(--rk-paper);
  cursor: pointer;
  transition: background 140ms ease-out, transform 140ms ease-out;
}

.anim-channel-action:hover,
.anim-channel-action:focus-visible {
  outline: none;
  background: var(--rk-emerald);
  transform: scale(1.08);
}

.anim-channel-action svg {
  width: 14px;
  height: 14px;
  stroke-width: 1.9;
}

@media (hover: none) {
  .anim-channel-actions {
    opacity: 1;
    transform: none;
  }
}

.anim-channel-card.is-active {
  border-color: var(--rk-emerald);
  border-block-end-color: color-mix(in srgb, var(--rk-emerald) 24%, var(--rk-paper-2));
  box-shadow:
    0 0 0 2px color-mix(in srgb, var(--rk-emerald) 16%, transparent),
    0 5px 0 -1px color-mix(in srgb, var(--rk-emerald-soft) 74%, var(--rk-ink-muted)),
    0 15px 19px -13px color-mix(in srgb, var(--rk-ink) 44%, transparent),
    var(--rk-shadow-card);
}

.anim-channel-thumb {
  width: 100%;
  aspect-ratio: 16 / 9;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 11px;
  background: color-mix(in srgb, var(--rk-ink-soft) 70%, var(--rk-paper-2));
  color: color-mix(in srgb, var(--rk-paper) 74%, transparent);
}

.anim-channel-thumb.is-placeholder {
  border-inline: 5px dotted color-mix(in srgb, var(--rk-paper) 32%, transparent);
}

.anim-channel-thumb.is-placeholder.is-olive {
  background: color-mix(in srgb, var(--rk-shelf-bracket-b) 82%, var(--rk-paper-2));
}

.anim-channel-thumb.is-placeholder.is-teal {
  background: color-mix(in srgb, var(--rk-emerald-hover) 72%, var(--rk-ink));
}

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

.anim-channel-thumb svg {
  width: 36px;
  height: 36px;
}

.anim-channel-copy {
  position: relative;
  min-width: 0;
  display: block;
  padding: 11px 4px 0;
}

.anim-channel-copy small,
.anim-channel-copy strong {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-channel-copy small {
  padding-inline-end: 88px;
  color: var(--rk-emerald-hover);
  font-size: 10px;
  font-weight: 850;
  letter-spacing: 0.03em;
}

.anim-channel-copy strong {
  margin-top: 5px;
  color: var(--rk-ink);
  font-size: 13px;
  line-height: 1.35;
}

.anim-channel-now {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 2px;
  max-width: 84px;
  overflow: hidden;
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 9px;
  font-weight: 850;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-channel-nav {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid color-mix(in srgb, var(--rk-ink-muted) 32%, transparent);
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: border-color 180ms ease-out, color 180ms ease-out, transform 180ms ease-out;
}

.anim-channel-nav:hover,
.anim-channel-nav:focus-visible {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
  outline: none;
  transform: scale(1.05);
}

.anim-channel-nav svg {
  width: 17px;
  height: 17px;
}

.anim-channel-nav.is-next svg {
  transform: rotate(180deg);
}

.anim-screen-loading {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  background: #eee8dd;
  color: var(--rk-ink-soft);
  font-size: 13px;
  font-weight: 750;
}

.anim-screen-loading-mark {
  width: 54px;
  height: 5px;
  overflow: hidden;
  border-radius: 999px;
  background: #d9d0c2;
}

.anim-screen-loading-mark::after {
  content: '';
  display: block;
  width: 46%;
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
  animation: anim-screen-load 1.35s ease-in-out infinite alternate;
}

.anim-screen-loading.is-error .anim-screen-loading-mark::after {
  animation: none;
  background: var(--rk-ink-muted);
}

@keyframes anim-screen-load {
  from { transform: translateX(0); }
  to { transform: translateX(118%); }
}

.anim-screen-empty {
  background: #f5efe4;
}

.anim-screen-empty-art {
  object-position: center;
}

.anim-screen-empty-copy {
  top: 25%;
  left: 5.5%;
  width: 39%;
  color: var(--rk-ink);
}

.anim-screen-empty-copy p {
  max-width: 320px;
  color: var(--rk-ink-soft);
  font-weight: 650;
  line-height: 1.55;
}

.anim-screen-empty-copy .anim-screen-primary {
  margin-top: 20px;
}

@media (max-width: 760px) {
  .anim-home-workspace { margin-top: 24px; }
  .anim-home-workspace > #anim-tv-stage .anim-tv,
  .anim-tv { --anim-tv-frame-pad: 10px; padding: 10px 10px 0; border-radius: 19px; }
  .anim-tv-screen { border-radius: 12px; }
  .anim-tv-chin { height: 26px; }
  .anim-tv-cat { top: -81px; right: 24px; width: 104px; }
  .anim-screen-copy { top: 11%; left: 24px; width: 48%; }
  .anim-screen-copy h2 { font-size: clamp(19px, 4vw, 26px); }
  .anim-screen-copy p { margin-top: 6px; font-size: 12px; }
  .anim-screen-actions { margin-top: 13px; }
  .anim-screen-play { top: 50%; width: 58px; height: 58px; }
  .anim-screen-play::after { margin-inline-start: 4px; border-inline-start-width: 17px; border-top-width: 10px; border-bottom-width: 10px; }
  .anim-screen-primary, .anim-screen-secondary { min-height: 36px; padding: 0 12px; font-size: 11px; border-radius: 9px; }
  .anim-channel-drawer { width: calc(100% - 6px); margin-top: -102px; }
  .anim-channel-bar { width: calc(100% - 40px); grid-template-columns: 38px minmax(0, 1fr) 38px; gap: 8px; padding: 13px 10px 13px; margin-inline: 20px; margin-bottom: 18px; border-radius: 16px 16px 6px 6px; }
  .anim-channel-board { inset-inline-start: 0; bottom: 0; width: 100%; height: 36px; }
  .anim-channel-list { grid-auto-columns: calc((100% - 10px) / 2); gap: 10px; }
  .anim-channel-card { padding: 6px 6px 10px; border-radius: 13px; }
  .anim-channel-actions { inset-block-start: 10px; inset-inline-end: 10px; }
  .anim-channel-nav { width: 36px; height: 36px; }
  .anim-screen-empty-copy { top: 19%; left: 5%; width: 42%; }
}

@media (max-width: 520px) {
  .anim-home-workspace { margin-top: 18px; }
  .anim-tv-cat { top: -61px; right: 16px; width: 78px; }
  .anim-tv-brand { font-size: 8px; letter-spacing: 2px; }
  .anim-screen-copy { top: 10%; left: 16px; width: 55%; }
  .anim-screen-copy h2 { margin-top: 3px; font-size: 17px; }
  .anim-screen-copy p { display: none; }
  .anim-screen-episode { font-size: 9px; }
  .anim-screen-actions { margin-top: 9px; }
  .anim-screen-play { top: 50%; width: 46px; height: 46px; }
  .anim-screen-play::after { border-inline-start-width: 14px; border-top-width: 8px; border-bottom-width: 8px; }
  .anim-screen-secondary { display: none; }
  .anim-screen-primary { min-height: 31px; padding-inline: 10px; }
  .anim-screen-dur { top: 9px; right: 9px; }
  .anim-tv-chin { height: 22px; }
  .anim-channel-drawer { margin-top: -44px; }
  .anim-channel-bar { width: calc(100% - 24px); grid-template-columns: minmax(0, 1fr); padding: 9px 8px 11px; margin-inline: 12px; margin-bottom: 15px; border-radius: 13px 13px 5px 5px; }
  .anim-channel-board { inset-inline-start: 0; bottom: 0; width: 100%; height: 30px; }
  .anim-channel-list { grid-auto-columns: 82%; gap: 9px; }
  .anim-channel-nav { display: none; }
  .anim-channel-copy small { padding-inline-end: 76px; }
  .anim-screen-empty-copy { top: 18%; left: 5%; width: 45%; }
  .anim-screen-empty-copy p { display: none; }
  .anim-screen-empty-copy .anim-screen-primary { margin-top: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .anim-screen-loading-mark::after { animation: none; }
  .anim-channel-drawer,
  .anim-channel-card,
  .anim-channel-actions,
  .anim-channel-action,
  .anim-channel-nav { transition: none; }
  .anim-channel-list { scroll-behavior: auto; }
}

/* click-to-play: the film plays inside the TV screen */
.anim-home-workspace > #anim-tv-stage .anim-tv-stage.is-playing .anim-tv,
.anim-tv-stage.is-playing .anim-tv {
  padding-block-end: var(--anim-tv-frame-pad);
}

.anim-screen-video {
  position: absolute;
  z-index: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

.anim-tv-screen.is-playing .anim-screen-media,
.anim-tv-screen.is-playing .anim-screen-shade,
.anim-tv-screen.is-playing .anim-screen-copy,
.anim-tv-screen.is-playing .anim-screen-play,
.anim-tv-screen.is-playing .anim-screen-dur {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.anim-tv-stage.is-playing .anim-channel-drawer {
  grid-template-rows: 0fr;
  margin-top: 0;
  opacity: 0;
  transform: translateY(28px);
  pointer-events: none;
}

/* animation dims — locked aspect chip (16:9, phase 1; concept .chip.is-locked) */
.sb-chip.is-locked {
  opacity: 0.75;
  cursor: default;
}

.sb-chip.is-locked small {
  font-size: 10.5px;
  color: var(--rk-ink-muted);
}

/* ═══ Animation co-creation shell (anim.html, WP-07; concept 02-script-cowrite) ═══ */
/* anim.html hosts a self-managed 100dvh workspace. The bare shell's page padding (24/40px) would
   push it past the viewport — a page scrollbar appears and the bottom CTA bar hides half below the
   fold on every step. Zero the shell padding for this workspace only. */
.rk-bare-main:has(> .anim-cw) {
  padding: 0;
  min-height: 0;
}

.anim-cw {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  min-height: 100vh;
  overflow: hidden;
}

.anim-cw-top {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 12px 22px;
  border-bottom: 1px solid var(--rk-line);
  background: rgba(250, 248, 244, 0.95);
}

.anim-cw-top.is-style {
  border-bottom-color: transparent;
}

.anim-cw-top.is-edit {
  padding-block: 9px;
}

.anim-cw-edit-toolbar-slot {
  flex: 1 1 auto;
  min-width: 0;
  margin-inline-start: 22px;
  overflow-x: auto;
  scrollbar-width: none;
}

.anim-cw-edit-toolbar-slot::-webkit-scrollbar {
  display: none;
}

.anim-cw-top.is-edit .anim-cw-actions {
  min-width: 34px;
}

.anim-cw-back {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  border-radius: 999px;
  padding: 7px 15px;
  font-size: 13px;
  color: var(--rk-ink-soft);
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

html[dir="rtl"] .anim-cw-back svg {
  transform: scaleX(-1);
}

.anim-cw-home {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  cursor: pointer;
  font-family: inherit;
  display: grid;
  place-items: center;
  margin-inline-end: -8px;
}

.anim-cw-skip {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  border-radius: 999px;
  padding: 7px 15px;
  font-size: 12.5px;
  color: var(--rk-ink-muted);
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
}

.anim-cw-actions {
  flex: 0 0 auto;
  min-width: 84px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

/* Credit balance chip inside the immersive animation top bar (Andy 2026-08-07). Same .balance-chip
   as the v3 topbar — one look for one number — sized down to sit level with .anim-cw-back and
   .anim-cw-skip, which are the 35px-tall pills it shares the row with.

   Deliberately scoped through .anim-cw-actions rather than styled on .anim-cw-balance alone: the
   notebook-width block near the end of this file (min-width:1021px … max-width:1680px) re-sizes
   .balance-chip to 42px for the REAL topbar and, being later in the sheet, silently won here —
   the chip rendered 42px tall next to 35px neighbours. Specificity settles it for good, and keeps
   these rules next to their siblings instead of exiled to the bottom of the file. */
.anim-cw-balance-slot {
  display: contents;
}

.anim-cw-actions .anim-cw-balance {
  min-height: 35px;
  padding-inline: 12px;
  gap: 7px;
  font-size: 12.5px;
  color: var(--rk-ink);
  cursor: pointer;
  font-family: inherit;
}

.anim-cw-actions .anim-cw-balance svg {
  width: 17px;
  height: 17px;
}

.anim-cw-actions .anim-cw-balance:hover,
.anim-cw-actions .anim-cw-balance:focus-visible {
  border-color: var(--rk-emerald);
}

/* The step rail is navigation, the chip is information — when the row runs out of room the chip
   gives way first, down to the bare number. Letting .anim-steps wrap instead would push the whole
   bar to two lines and shove the canvas down. */
@media (max-width: 1100px) {
  .anim-cw-actions .anim-cw-balance svg {
    display: none;
  }

  .anim-cw-actions .anim-cw-balance {
    padding-inline: 10px;
  }
}

.anim-cw-fullscreen {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 9px;
  background: transparent;
  color: var(--rk-ink-muted);
  cursor: pointer;
}

.anim-cw-fullscreen svg {
  width: 18px;
  height: 18px;
  stroke-width: 1.7;
}

.anim-cw-fullscreen:hover,
.anim-cw-fullscreen:focus-visible,
.anim-cw-fullscreen.is-on {
  border-color: var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
}

.anim-cw-fullscreen:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-steps {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0 auto;
  font-size: 12.5px;
  color: var(--rk-ink-muted);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.anim-steps::-webkit-scrollbar {
  display: none;
}

.anim-step {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  white-space: nowrap;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

/* Quieter step bar (J1: keep the seven-step nav, but drop the loud filled pill + heavy weight for a
   text-colour breadcrumb closer to the storybook .sb-stepper). */
.anim-step.is-active {
  color: var(--rk-emerald);
  font-weight: 700;
}

.anim-step.is-done {
  color: var(--rk-emerald);
}

.anim-step svg {
  width: 17px;
  height: 17px;
}

.anim-step-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--rk-emerald);
}

.anim-step:not(.is-active):not(.is-locked):hover {
  color: var(--rk-ink);
}

/* WP-26 forward gating: steps beyond the project's frontier are visibly inert */
.anim-step.is-locked {
  opacity: 0.38;
  cursor: default;
}

.anim-step-sep {
  flex: 0 0 auto;
  width: 28px;
  height: 1px;
  background: var(--rk-line);
}

.anim-cw-spacer {
  width: 84px;
}

.anim-cw-main {
  /* Every pipeline step runs edge-to-edge (Jeff + 老板 2026-07-28). The old 1200/1560 ceiling threw
     away 500px per side on a 2560 display while the shot cards it was protecting stayed cramped —
     and step 7 had already gone full-bleed, so the flow visibly jumped width at step 6→7. The
     wraps keep `max-width: var(--anim-page-max)` so this stays the single knob for page width. */
  --anim-page-max: 100%;
  /* Both desk steps fill exactly this box, so the whitespace above and below the workspace is
     identical on step 4 and step 5: viewport - top bar (65) - CTA bar (75) - this padding (26+40). */
  --anim-desk-h: max(460px, calc(100vh - 206px));
  /* One rail width for both desks — they are the same left-rail/right-canvas layout, so the chat
     column must not be 420 on one step and 336 on the next. */
  --anim-desk-rail: clamp(320px, 24vw, 380px);
  flex: 1;
  min-height: 0;
  overflow: auto;
  /* The CTA bar is an in-flow flex sibling below (not floating), so the old 120px reserve just
     read as a dead band above it — a modest breathing gap is enough. */
  padding: 26px 34px 40px;
}

.anim-cw-main.is-script {
  overflow: hidden;
  padding: 18px 22px 14px;
}

.anim-cw-main.is-style {
  padding: 18px 0 40px;
}

.anim-cw-main.is-board {
  overflow: hidden;
  padding: 10px 34px 12px;
  background: color-mix(in srgb, var(--rk-paper-2) 34%, var(--rk-paper));
}

/* Animation loading uses the compact picture-book boot-loader scale. Keep the panel as a real
   full-workspace state: video is a horizontal flex layout, so an intrinsic-width thinking panel
   otherwise collapses into a narrow column on refresh. */
.anim-cw-main:has(> .anim-thinking) {
  overflow: hidden;
  padding: 0;
}

.anim-cw-main > .anim-thinking {
  flex: 1 1 100%;
  width: 100%;
  min-width: 0;
  min-height: 100%;
  padding: 24px;
}

.anim-thinking .sb-think-cat {
  width: 105px;
  height: 105px;
}

.anim-thinking .sb-think-line {
  font-size: 16px;
}

.anim-thinking .sb-think-sub {
  font-size: 14px;
}

/* ═══ WP-26 conversation frame + flat film-script flow (Camika step 1, paper-white) ═══ */
.anim-you {
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 14px;
  padding: 13px 16px;
  margin-bottom: 18px;
  box-shadow: var(--rk-shadow-card);
}

.anim-you-label {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
  margin-bottom: 5px;
}

.anim-you-text {
  font-size: 14px;
  line-height: 1.6;
  color: var(--rk-ink);
}

.anim-you-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.anim-you-chips span {
  font-size: 11.5px;
  padding: 2px 10px;
  border-radius: 999px;
  border: 1px solid var(--rk-line);
  color: var(--rk-ink-soft);
  background: var(--rk-paper);
}

.anim-you-chips span.is-resumed {
  border-style: dashed;
  color: var(--rk-ink-muted);
}

.anim-ai-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}

.anim-ai-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--rk-emerald);
}

.anim-ai-name {
  font-size: 12.5px;
  font-weight: 800;
  color: var(--rk-ink-soft);
}

.anim-ai-live {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  color: var(--rk-emerald);
  border: 1px solid var(--rk-emerald-soft);
  border-radius: 999px;
  padding: 1px 8px;
  animation: anim-live-pulse 1.6s ease-in-out infinite;
}

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

.anim-stream {
  min-width: 0;
}

.anim-reading-story,
.anim-stream.is-typing {
  width: min(100%, 820px);
  margin-inline: auto;
}

.anim-reading-title,
.anim-line.is-reading-title {
  margin: 2px 0 28px;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: clamp(21px, 2vw, 27px);
  font-weight: 850;
  line-height: 1.3;
  letter-spacing: -0.02em;
}

.anim-reading-chapter + .anim-reading-chapter {
  margin-top: 34px;
}

.anim-reading-chapter > h3,
.anim-stream .anim-line.is-act {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  color: var(--rk-emerald-hover);
  font-size: 12px;
  font-weight: 850;
  letter-spacing: 0.08em;
}

.anim-reading-chapter > h3::after,
.anim-stream .anim-line.is-act::after {
  content: "";
  height: 1px;
  flex: 1;
  background: var(--rk-paper-2);
}

.anim-reading-scene + .anim-reading-scene {
  margin-top: 18px;
}

.anim-reading-paragraph,
.anim-line.is-reading-paragraph {
  margin: 0 0 13px;
  color: var(--rk-ink);
  font-size: 15.5px;
  line-height: 1.92;
  overflow-wrap: anywhere;
}

.anim-reading-paragraph.is-summary {
  color: var(--rk-ink-soft);
}

.anim-reading-fragment.is-dialogue {
  color: color-mix(in srgb, var(--rk-ink) 88%, var(--rk-emerald));
}

.anim-reading-fragment.is-inner,
.anim-reading-fragment.is-narration {
  color: var(--rk-ink-soft);
  font-style: italic;
}

.anim-reading-fragment::selection,
.anim-reading-paragraph::selection {
  color: var(--rk-ink);
  background: var(--rk-emerald-soft);
}

.anim-reading-paragraph.is-fresh {
  margin-inline: -12px;
  padding: 6px 12px;
  border-inline-start: 2px solid var(--rk-emerald);
  border-radius: 0 8px 8px 0;
  background: var(--rk-emerald-soft);
  animation: anim-fresh-in 0.6s ease both;
}

.anim-script-reference {
  width: min(100%, 900px);
  margin: 8px auto 18px;
}

.anim-reference-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.anim-reference-divider {
  height: 1px;
  margin-top: 16px;
  background: linear-gradient(90deg, transparent, var(--rk-line) 12%, var(--rk-line) 88%, transparent);
}

.anim-reference-tabs {
  width: fit-content;
  max-width: 100%;
  display: grid;
  grid-template-columns: repeat(3, minmax(92px, 1fr));
  gap: 4px;
  margin: 0;
  padding: 4px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper);
}

.anim-reference-toggle {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-paper);
  color: var(--rk-ink-muted);
  cursor: pointer;
}

.anim-reference-toggle svg {
  width: 16px;
  height: 16px;
  transition: transform 0.2s ease;
}

.anim-script-reference.is-expanded .anim-reference-toggle svg {
  transform: rotate(180deg);
}

.anim-reference-toggle:hover,
.anim-reference-toggle:focus-visible {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
}

.anim-reference-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-reference-content {
  max-height: min(260px, 30vh);
  margin-top: 12px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.anim-reference-content[hidden] {
  display: none;
}

.anim-reference-tabs button {
  min-height: 34px;
  padding: 6px 18px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  font: inherit;
  font-size: 12.5px;
  font-weight: 750;
  white-space: nowrap;
  cursor: pointer;
}

.anim-reference-tabs button[aria-selected="true"] {
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  box-shadow: 0 2px 8px rgba(34, 45, 41, 0.08);
}

.anim-reference-tabs button:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.anim-reference-panel {
  min-width: 0;
  padding: 20px 22px;
  border: 1px solid var(--rk-line);
  border-radius: 14px;
  background: var(--rk-paper);
}

.anim-reference-panel[hidden] {
  display: none;
}

.anim-reference-world {
  display: grid;
  gap: 14px;
}

.anim-reference-tone {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 0;
}

.anim-reference-tone strong {
  color: var(--rk-ink-muted);
  font-size: 11px;
  letter-spacing: 0.08em;
}

.anim-reference-tone span,
.anim-reference-mood {
  width: fit-content;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 12px;
  font-weight: 750;
}

.anim-reference-setting,
.anim-reference-acts p,
.anim-reference-scenes details div p {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 13.5px;
  line-height: 1.75;
  overflow-wrap: anywhere;
}

.anim-reference-acts {
  display: grid;
  gap: 10px;
}

.anim-reference-acts article {
  padding-top: 12px;
  border-top: 1px dashed var(--rk-line);
}

.anim-reference-acts h4 {
  margin: 0 0 5px;
  color: var(--rk-ink);
  font-size: 12.5px;
}

.anim-reference-scenes {
  display: grid;
  gap: 8px;
}

.anim-reference-scenes details {
  border-bottom: 1px dashed var(--rk-line);
}

.anim-reference-scenes details:last-child {
  border-bottom: 0;
}

.anim-reference-scenes summary {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  padding: 10px 2px;
  color: var(--rk-ink);
  cursor: pointer;
}

.anim-reference-scenes summary span {
  color: var(--rk-emerald-hover);
  font-size: 11.5px;
  font-weight: 800;
}

.anim-reference-scenes summary strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
}

.anim-reference-scenes details > div {
  display: grid;
  gap: 9px;
  padding: 0 2px 14px;
}

.anim-reference-script {
  max-height: 430px;
  overflow: auto;
  padding: 2px 14px 2px 18px;
  border-inline-start: 2px solid var(--rk-line);
  scrollbar-width: thin;
}

.anim-line {
  font-size: 14.5px;
  line-height: 1.75;
  margin-bottom: 9px;
  color: var(--rk-ink);
  white-space: pre-wrap;
}

.anim-line.is-act {
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 1.6px;
  color: var(--rk-ink-muted);
  margin: 18px 0 10px;
}

.anim-line.is-heading {
  font-weight: 800;
  color: var(--rk-emerald-hover);
  margin: 14px 0 8px;
}

.anim-line.is-dialogue {
  padding-inline-start: 22px;
}

/* Worldview opener: quieter than the screenplay body, so it reads as a note before the story. */
.anim-line.is-world {
  color: var(--rk-ink-soft);
  font-size: 13.5px;
  line-height: 1.7;
}

.anim-line.is-vo {
  font-style: italic;
  color: var(--rk-ink-soft);
}

.anim-stream.is-typing .anim-line:last-child::after {
  content: "▍";
  color: var(--rk-emerald);
  animation: anim-live-pulse 0.9s steps(2) infinite;
}

/* ═══ WP-09 script desk chat: fresh-patch highlight + mini bubbles + input bar ═══ */
.anim-line.is-fresh {
  border-inline-start: 2px solid var(--rk-emerald);
  background: var(--rk-emerald-soft);
  padding-inline-start: 10px;
  margin-inline-start: -12px;
  border-radius: 0 8px 8px 0;
  animation: anim-fresh-in 0.6s ease both;
}

@keyframes anim-fresh-in {
  from { opacity: 0; transform: translateX(-4px); }
  to { opacity: 1; transform: none; }
}

.anim-you.is-mini {
  margin: 16px 0 10px auto;
  max-width: 78%;
  padding: 9px 13px;
}

.anim-you.is-mini .anim-you-text {
  font-size: 13px;
}

.anim-ai.is-mini {
  margin-bottom: 10px;
}

.anim-ai.is-mini .anim-ai-head {
  margin-bottom: 5px;
}

/* AI reply as a soft left-aligned bubble (mirrors storybook .sb-as-chat-msg.is-ai), so the desk
   chats read as a back-and-forth instead of an indented note. Pairs with the right-aligned
   .anim-you.is-mini user bubble. */
.anim-chat-line {
  max-width: 88%;
  margin: 0 auto 10px 0;
  padding: 8px 12px;
  border-radius: 14px;
  border-bottom-left-radius: 4px;
  background: var(--rk-bubble-ai);
  color: var(--rk-ink);
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Thinking bubble: copy reads「布丁正在思考」and the dots type themselves out one by one —
   livelier than the old single pulsing ellipsis (Jeff 2026-07-29: 固定「收到…」太糙、文案太职场). */
.anim-chat-line.is-pending::after {
  content: " ·";
  color: var(--rk-emerald);
  animation: anim-chat-thinking-dots 1.2s steps(1, end) infinite;
}

@keyframes anim-chat-thinking-dots {
  0% { content: " ·"; }
  33% { content: " ··"; }
  66% { content: " ···"; }
}

.anim-chatbar {
  position: sticky;
  bottom: 12px;
  display: flex;
  gap: 8px;
  margin-top: 18px;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 6px 6px 6px 16px;
  box-shadow: var(--rk-shadow-card);
}

.anim-chat-context-stack {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.anim-context-slot:empty {
  display: none;
}

.anim-context-chip {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  min-height: 42px;
  padding: 4px 5px;
  border: 1px solid var(--rk-emerald);
  border-radius: 12px;
  background: var(--rk-emerald-soft);
  color: var(--rk-ink);
  box-shadow: 0 5px 16px -13px var(--rk-ink-soft);
  animation: anim-context-arrive 360ms cubic-bezier(.2, .9, .3, 1.2) both;
}

.anim-context-thumb,
.anim-context-icon {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
}

.anim-context-thumb {
  object-fit: cover;
}

.anim-context-icon {
  display: grid;
  place-items: center;
  color: var(--rk-emerald-hover);
}

.anim-context-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: var(--rk-emerald-hover);
  font-size: 12.5px;
  font-weight: 750;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-context-clear {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 9px;
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: background 150ms ease-out, color 150ms ease-out;
}

.anim-context-clear:hover,
.anim-context-clear:focus-visible {
  outline: none;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
}

@keyframes anim-context-arrive {
  from { opacity: 0; transform: translateY(4px) scale(.985); }
  to { opacity: 1; transform: none; }
}

.anim-chatbar input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 13.5px;
  color: var(--rk-ink);
  outline: none;
}

.anim-chatbar input::placeholder {
  color: var(--rk-ink-muted);
}

/* Pudding avatar on the script chat bar (mirrors storybook .sb-refine-avatar) for tonal warmth. */
.anim-chat-avatar {
  flex: 0 0 auto;
  align-self: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
}

.anim-chatbar:has(.anim-chat-avatar) {
  padding-inline-start: 8px;
}

.anim-chat-send {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
}

.anim-chat-send:disabled {
  opacity: 0.5;
  cursor: default;
}

/* ═══ WP-16 art desk: left dock + card busy marker ═══ */
.anim-ad-grid {
  position: relative;
  display: block;
  height: var(--anim-desk-h);
  width: 100%;
  max-width: none;
  margin-inline: auto;
  overflow: hidden;
}

.anim-ad-grid > .anim-as-canvas {
  width: 100%;
  height: 100%;
}

.anim-as-control-error {
  position: absolute;
  z-index: 12;
  inset-block-start: 18px;
  left: 50%;
  max-width: min(560px, calc(100% - 48px));
  margin: 0;
  padding: 10px 16px;
  transform: translateX(-50%);
  border: 1px solid #efb5aa;
  border-radius: 12px;
  background: #fff4f1;
  color: #a33a2b;
  box-shadow: 0 10px 24px rgb(87 42 29 / 12%);
  font-size: 0.82rem;
  font-weight: 750;
  line-height: 1.45;
}

/* The "these sets are in the previous style" list sits directly under the refusal banner. It is a
   route, not an alarm — same shape, quieter colours, and every entry is a link to the card that can
   be redrawn (the redraw itself stays a paid click on that card). */
.anim-as-control-error.is-hint {
  inset-block-start: 62px;
  border-color: #e3d6bd;
  background: #fdf8ee;
  color: #6b5636;
  font-weight: 650;
}

.anim-as-stale-list {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-inline-start: 8px;
}

.anim-as-stale-jump {
  padding: 2px 10px;
  border: 1px solid #e0cfae;
  border-radius: 999px;
  background: #fff;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.anim-as-stale-jump:hover {
  border-color: #c9ab74;
  background: #fffaf0;
}

/* The asset graph is a workbench: use every pixel between the pipeline header and its sticky CTA.
   Keep the shared 34px side gutter, but do not strand vertical padding above or below the canvas. */
@media (min-width: 901px) {
  .anim-cw-main.is-assets {
    padding-block: 0;
    overflow: hidden;
  }

  .anim-cw-main.is-assets .anim-ad-grid {
    height: 100%;
  }

  .anim-cw-main.is-shots {
    padding-block: 0;
    overflow: hidden;
  }
}

/* Animation assets share the storybook inspector shell so both editors keep the same paper-card
   proportions and fixed footer. Animation-specific rules only adapt its prompt actions and chat. */
.anim-as-inspector {
  z-index: 8;
  width: 280px;
}

.anim-as-insp-media img {
  max-height: 280px;
  object-fit: contain;
}

.anim-as-insp-empty {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 24px;
  color: var(--rk-ink-muted);
  font-size: 0.82rem;
  font-weight: 750;
  text-align: center;
}

.anim-as-inspector .anim-ad-card-meta {
  width: 100%;
}

.anim-as-inspector .anim-ad-log {
  margin-top: 0;
}

.sb-as-insp-footer > .anim-as-insp-prompt-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.anim-as-insp-prompt-actions .sb-as-insp-redraw {
  grid-column: 1 / -1;
}

.anim-as-insp-chatbar {
  width: 100%;
  margin: 0;
  box-shadow: none;
}

.anim-as-insp-chatbar input {
  min-width: 0;
  font-size: 14px;
}

.anim-ad-dock {
  position: absolute;
  z-index: 6;
  inset-block: 18px;
  inset-inline-start: 18px;
  width: min(var(--anim-desk-rail), calc(100% - 36px));
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 18px;
  padding: 18px;
  box-shadow: 0 22px 55px -34px rgba(48, 39, 24, 0.48), var(--rk-shadow-card);
}

.anim-ad-dock .anim-chatbar.is-dock {
  margin-top: auto;
}

/* The art desk's single scroll region — same grammar as the director desk's .anim-dd-stream
   (2026-07-28 alignment). Header stays on top, the composer stays pinned at the bottom, and
   everything in between (asset card, chat) scrolls as one conversation. */
.anim-ad-stream {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  padding-inline-end: 2px;
}

/* Every block in the stream keeps its natural height. Without this, flex children happily shrink
   and the container never scrolls — the exact failure the director desk hit from the other side
   (its shot card squashed to 2px) and the art desk hit from this side (its inspector grew to 81%
   of the dock and squashed the chat log to 2px). Scrolling is the container's job; content
   never stretches and never shrinks. */
.anim-ad-stream > * {
  flex: 0 0 auto;
}

.anim-ad-intro {
  font-size: 14px;
  line-height: 1.6;
  color: var(--rk-ink-soft);
  background: var(--rk-paper-2);
  border-radius: 12px;
  padding: 12px 14px;
  margin-top: 12px;
}

/* ── 选中态紧凑卡（2026-07-28 取代 .anim-ad-inspector 一整套）────────────────────────────────
   原来这里住着 .anim-ad-inspector / -preview / -asset-head / -prompt / -actions / -diagnostic 六组，
   合起来把「大预览 + 完整提示词框 + 重做取消」钉在面板顶部：实测占掉面板 81%、聊天只剩 2px。
   提示词已迁进卡片铅笔打开的弹窗；外框改为复用导演台的 .anim-dd-card，这里只补内部布局。 */
.anim-ad-card-body {
  display: flex;
  gap: 10px;
  padding: 10px;
}

.anim-ad-card-thumb {
  flex: 0 0 auto;
  width: 92px;
  height: 92px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
}

.anim-ad-card-thumb.is-empty {
  display: grid;
  place-items: center;
  padding: 6px;
  color: var(--rk-ink-soft);
  font-size: 11px;
  text-align: center;
}

.anim-ad-card-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.anim-ad-card-meta em {
  font-style: normal;
  font-weight: 800;
  font-size: 11.5px;
  color: var(--rk-ink-soft);
}

.anim-ad-card-meta em.is-generating { color: var(--rk-emerald); }
.anim-ad-card-meta em.is-failed,
.anim-ad-card-meta em.is-cancelled { color: var(--rk-danger); }

.anim-ad-card-meta p {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 12px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.anim-ad-card-cancel {
  align-self: flex-start;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 3px 10px;
  background: var(--rk-surface);
  color: var(--rk-danger);
  cursor: pointer;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 800;
}

.anim-ad-card-cancel:disabled { cursor: default; opacity: 0.5; }

/* 派生图（拆解 / 换装 / 融合）的说明与两个功能性入口 —— 它们不给编辑，只给「重新生成」和
   「去改原型」。（Jeff 2026-07-28） */
.anim-ad-card-derived {
  color: var(--rk-ink-3) !important;
}

.anim-ad-card-acts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.anim-ad-card-act {
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 3px 10px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  cursor: pointer;
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 800;
}

.anim-ad-card-act:hover:not(:disabled) { border-color: var(--rk-emerald); color: var(--rk-emerald); }
.anim-ad-card-act:disabled { cursor: default; opacity: 0.5; }
.anim-ad-card-act.is-link { border-color: transparent; color: var(--rk-emerald); }

.anim-as-state {
  position: absolute;
  /* 2026-07-29 挪到右下角：左上角让给常显的类型徽章（.anim-as-corner），左下角是 busy/质检位。 */
  inset-block-end: 6px;
  inset-inline-end: 6px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(250, 248, 244, 0.92);
  color: var(--rk-danger);
  font-size: 10px;
  font-weight: 800;
}

.anim-as-node.has-qa-issue,
.anim-as-node.has-ref-issue {
  border-color: color-mix(in srgb, var(--rk-ink-soft) 34%, var(--rk-line));
}

/* Quiet info dot (not an alarm): flags a card that may want a retouch; the plain-language hint
   lives in the tooltip, and the fix happens in the Pudding chat — no machine QA vocabulary. */
.anim-as-qa-badge {
  position: absolute;
  inset-inline-start: 6px;
  inset-block-end: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 999px;
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  box-shadow: 0 2px 6px rgba(60, 42, 18, 0.14);
}

.anim-ad-log {
  flex: 0 0 auto;
  min-height: 0;
  margin-top: 14px;
  padding-top: 2px;
}

/* When the conversation is empty the log collapses to nothing (no forced void); the top margin
   only applies once there is something to show. */
.anim-ad-log:empty {
  margin-top: 0;
}

/* Chat bubbles inside the art desk read a touch larger than the script desk's (this column is the
   sole workspace here, not a side rail), and never cramp the readable minimum. Scoped to the dock so
   the script/director desks keep their own sizing. */
.anim-ad-log .anim-chat-line {
  margin-bottom: 10px;
  font-size: 14px;
  line-height: 1.55;
  padding: 9px 13px;
}

.anim-ad-log .anim-you.is-mini {
  padding: 10px 14px;
}

.anim-ad-log .anim-you.is-mini .anim-you-text {
  font-size: 14px;
}

.anim-ad-dock .anim-ai-name {
  font-size: 14px;
}

.anim-ad-ctx {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  border-radius: 999px;
  padding: 5px 13px;
  margin-bottom: 10px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.anim-ad-dock > .anim-context-chip,
.anim-dd-dock > .anim-context-chip {
  width: 100%;
  margin-block: 2px 4px;
}

.anim-ad-dock > .anim-context-chip::after,
.anim-dd-dock > .anim-context-chip::after {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  height: 1px;
  background: var(--rk-emerald);
  opacity: .42;
  pointer-events: none;
}

.anim-ad-dock > .anim-context-chip::after {
  inset-inline-end: -39px;
  width: 38px;
}

.anim-dd-dock > .anim-context-chip::after {
  inset-inline-end: -30px;
  width: 29px;
}

.anim-chatbar.is-dock {
  position: static;
  margin-top: 12px;
}

.anim-ad-dock .anim-chatbar.is-dock input {
  font-size: 14.5px;
}

.anim-as-busy {
  position: absolute;
  inset-block-end: 6px;
  inset-inline-start: 6px;
  z-index: 2;
  font-size: 10.5px;
  font-weight: 800;
  color: var(--rk-emerald);
  background: rgba(250, 248, 244, 0.92);
  border-radius: 999px;
  padding: 2px 9px;
  animation: anim-live-pulse 1.4s ease-in-out infinite;
}

/* 图片可能早于正式完成状态返回。保留图片给作者确认内容，同时用整块纸白蒙层 + 居中旋转
   明确告诉他「这张卡还没有结束」；左下角 Making… 与真实等待时间继续留在蒙层上方。 */
.anim-as-busy-veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  background: rgba(250, 248, 244, 0.48);
  pointer-events: none;
}

.anim-as-busy-veil .anim-as-spin {
  width: 28px;
  height: 28px;
  border-width: 3px;
}

@media (max-width: 900px) {
  .anim-ad-grid {
    display: grid;
    height: auto;
    min-height: 0;
    gap: 12px;
    overflow: visible;
  }
  .anim-ad-dock {
    position: relative;
    inset: auto;
    width: 100%;
    height: auto;
    max-height: 440px;
  }
  .anim-ad-grid > .anim-as-canvas { height: 520px; }
}

.anim-cta-bar {
  position: sticky;
  bottom: 0;
  border-top: 1px solid var(--rk-line);
  background: rgba(250, 248, 244, 0.95);
  padding: 14px 34px;
  display: flex;
  justify-content: center;
  gap: 12px;
}

.anim-cta-bar.is-kids-mv {
  justify-content: flex-end;
  align-items: center;
  z-index: 12;
}

/* 分镜按钮左侧那句「后台还在润色」。只在返工/在途重画时出现，按钮本身不变 —— 说明与动作分开，
   用户读得到原因、也照样能点（服务端会等板子定稿再开分镜）。 */
.anim-cta-caption {
  font-size: 13px;
  line-height: 1.4;
  color: var(--rk-ink-muted);
  max-width: 460px;
  text-align: right;
}

.anim-cta-main {
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
  font-weight: 800;
  font-size: 15px;
  border-radius: 999px;
  padding: 12px 34px;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 8px 20px -10px rgba(15, 164, 126, 0.55);
}

.anim-cta-main:hover {
  background: var(--rk-emerald-hover);
}

@media (max-width: 620px) {
  .anim-cw-main { padding: 18px 14px 100px; }
  .anim-cw-spacer { display: none; }
}

/* ═══ Script workbench: viewport reader + navigable outline + persistent actions ═══ */
.anim-work-inner {
  width: 100%;
  height: 100%;
  max-width: 1560px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, 360px);
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 14px 18px;
  align-items: stretch;
}

.anim-flow-col {
  min-width: 0;
  min-height: 0;
  grid-column: 1;
  grid-row: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  padding: 22px clamp(20px, 3vw, 44px) 36px;
  box-shadow: var(--rk-shadow-card);
}

.anim-story-card {
  min-height: 0;
  grid-column: 2;
  grid-row: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  position: static;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  padding: 12px 20px 20px;
  box-shadow: var(--rk-shadow-card);
  font-size: 13px;
}

.anim-card-kicker {
  font-size: 11px;
  color: var(--rk-ink-muted);
  font-weight: 800;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  margin-bottom: 10px;
}

/* Camika cwStart choreography: modules land staggered (chars +550ms, scenes +1050ms, foot last) */
.anim-card-mod {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.45s ease, transform 0.45s ease;
  padding: 10px 0;
  border-bottom: 1px dashed var(--rk-paper-2);
}

.anim-card-mod.is-in {
  opacity: 1;
  transform: none;
}

#anim-card-title {
  padding-block-start: 6px;
}

.anim-card-mod h4 {
  font-size: 15.5px;
  font-weight: 800;
  margin: 0 0 4px;
}

.anim-card-logline {
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--rk-ink-soft);
}

.anim-card-dur {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--rk-ink-soft);
}

.anim-version {
  font-size: 10.5px;
  font-weight: 800;
  color: var(--rk-emerald);
  border: 1px solid var(--rk-emerald-soft);
  border-radius: 999px;
  padding: 0 7px;
}

.anim-card-meta {
  margin-top: 4px;
  font-size: 11.5px;
  color: var(--rk-ink-muted);
}

.anim-mod-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.anim-mod-head span {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
}

.anim-mod-head i {
  font-size: 10.5px;
  font-style: normal;
  color: var(--rk-ink-muted);
  text-align: end;
}

.anim-char-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-block-start: 4px;
}

.anim-char-tags i {
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 1px 7px;
  color: var(--rk-ink-muted);
  font: 700 9.5px/1.6 var(--rk-font-body);
  font-style: normal;
}

.anim-char {
  display: flex;
  gap: 9px;
  padding: 5px 0;
}

.anim-char-avatar {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--rk-emerald-soft);
  display: grid;
  place-items: center;
  font-size: 11px;
  color: var(--rk-emerald);
  font-weight: 800;
}

.anim-char strong {
  display: block;
  font-size: 12.5px;
}

.anim-char strong em {
  font-style: normal;
  font-weight: 700;
  font-size: 10.5px;
  color: var(--rk-emerald);
  margin-inline-start: 7px;
}

.anim-char p {
  font-size: 11.5px;
  color: var(--rk-ink-soft);
  line-height: 1.45;
}

.anim-scene-row {
  width: 100%;
  display: flex;
  gap: 9px;
  padding: 8px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: inherit;
  text-align: start;
  font: inherit;
  opacity: 0.35;
  transition: opacity 0.5s ease;
  cursor: pointer;
}

.anim-scene-row.is-lit {
  opacity: 1;
}

.anim-scene-row.is-lit:hover,
.anim-scene-row.is-lit:focus-visible {
  background: var(--rk-paper-2);
  outline: none;
}

.anim-scene-row:focus-visible {
  box-shadow: inset 0 0 0 2px var(--rk-emerald);
}

.anim-scene-num {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid var(--rk-line);
  display: grid;
  place-items: center;
  font-size: 10.5px;
  font-weight: 800;
  color: var(--rk-ink-soft);
}

.anim-scene-row.is-lit .anim-scene-num {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
}

.anim-scene-row strong {
  display: block;
  font-size: 12.5px;
}

.anim-scene-row p {
  font-size: 11.5px;
  color: var(--rk-ink-muted);
}

.anim-card-foot {
  display: grid;
  gap: 8px;
  padding-top: 12px;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.45s ease, transform 0.45s ease;
}

.anim-card-foot.is-in {
  opacity: 1;
  transform: none;
}

.anim-script-dock {
  min-width: 0;
  grid-column: 1 / -1;
  grid-row: 2;
  display: grid;
  grid-template-columns: minmax(320px, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
}

.anim-script-dock-chat {
  min-width: 0;
}

.anim-script-dock .anim-chatbar {
  position: static;
  bottom: auto;
  margin: 0;
  box-shadow: none;
  background: var(--rk-paper);
}

.anim-script-dock .anim-series-script-lock {
  margin: 0;
}

.anim-script-dock-wait {
  min-height: 46px;
  display: flex;
  align-items: center;
  gap: 11px;
  padding-inline: 16px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper);
  color: var(--rk-ink-soft);
  font-size: 13px;
  font-weight: 750;
}
/* 这一格里的三点比全屏 thinking 那处小一号，跳幅也收一半——它是常驻在页脚的，
   用全屏那套幅度会一直在余光里晃。会动就够了，别抢正文（见 anim.js 的 SCRIPT_WAIT_KEYS 注释）。 */
.anim-script-dock-wait .sb-think-dots { gap: 5px; }
.anim-script-dock-wait .sb-think-dots span { width: 6px; height: 6px; }
@keyframes anim-script-wait-dot {
  0%, 100% { opacity: 0.3; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-2px); }
}
.anim-script-dock-wait .sb-think-dots span { animation-name: anim-script-wait-dot; }

.anim-script-dock-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}

.anim-script-dock-actions.is-single-action {
  min-width: 360px;
  justify-content: center;
}

.anim-script-dock-actions.is-single-action .anim-cta-main {
  min-width: 240px;
}

.anim-script-dock-actions .anim-cta-main,
.anim-script-dock-actions .anim-cta-ghost {
  min-height: 44px;
  white-space: nowrap;
}

.anim-script-dock-actions .anim-cta-main:disabled,
.anim-script-dock-actions .anim-cta-ghost:disabled {
  opacity: 0.48;
  cursor: default;
}

.anim-rewrite-confirm {
  display: grid;
  justify-items: center;
  gap: 12px;
  padding-block-start: 2px;
  text-align: center;
}

.anim-rewrite-confirm-icon {
  inline-size: 52px;
  block-size: 52px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.anim-rewrite-confirm-icon.is-warning {
  background: #fff4d9;
  color: #a66800;
}

.anim-rewrite-confirm h2 {
  margin: 2px 0 0;
  font-family: var(--rk-font-display);
  font-size: 1.28rem;
  line-height: 1.25;
  color: var(--rk-ink);
}

.anim-rewrite-confirm p {
  max-inline-size: 340px;
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.94rem;
  line-height: 1.6;
}

.anim-safety-confirm .anim-safety-suggestion {
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  font-size: 0.88rem;
}

.anim-rewrite-confirm-actions {
  inline-size: 100%;
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-block-start: 8px;
}

.anim-rewrite-confirm-actions .rk-btn-ghost,
.anim-rewrite-confirm-actions .rk-btn-primary {
  min-inline-size: 132px;
}

/* [WP-D] step artifact lags behind the edited script — quiet amber notice, never a blocker */
.anim-stale-notice {
  margin: 0 0 12px;
  padding: 8px 12px;
  border: 1px solid color-mix(in srgb, var(--rk-ink) 18%, transparent);
  border-inline-start: 3px solid #C98A1B;
  background: color-mix(in srgb, #C98A1B 7%, var(--rk-paper));
  color: var(--rk-ink);
  font-size: 13px;
  border-radius: 6px;
}

/* [WP-E] episode settlement account card — folded chips + reviewable proposal list */
.anim-ledger-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin-block: 6px;
}

.anim-ledger-chip {
  padding: 3px 10px;
  border: 1px solid color-mix(in srgb, var(--rk-ink) 16%, transparent);
  border-radius: 999px;
  font-size: 12px;
  background: var(--rk-paper-2);
}

.anim-ledger-details {
  inline-size: 100%;
  text-align: start;
  font-size: 13px;
}

.anim-ledger-details summary {
  cursor: pointer;
  color: var(--rk-accent, #0fa47e);
  text-align: center;
  margin-block: 4px;
}

.anim-ledger-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  max-block-size: 200px;
  overflow-y: auto;
  display: grid;
  gap: 6px;
}

.anim-ledger-list em {
  font-style: normal;
  opacity: 0.65;
  margin-inline-end: 4px;
}

.anim-ledger-error {
  color: #b3403a;
  font-size: 13px;
  margin: 4px 0 0;
}

/* [WP-G] series split plan card — episode list inside the intake-family modal */
.anim-split-list {
  list-style: none;
  margin: 12px 0 4px;
  padding: 0;
  max-block-size: 240px;
  overflow-y: auto;
  display: grid;
  gap: 8px;
  text-align: start;
}

.anim-split-list b {
  display: block;
  font-size: 13px;
}

.anim-split-list span {
  display: block;
  font-size: 12px;
  opacity: 0.72;
}

/* [WP-C] intake confirmation card — quiet back link under the action row */
.anim-intake-confirm .anim-intake-back {
  margin-block-start: 10px;
  align-self: center;
  font-size: 13px;
  opacity: 0.72;
}

.anim-intake-confirm .anim-intake-back:hover {
  opacity: 1;
}

.anim-cta-main.is-block,
.anim-cta-ghost.is-block {
  width: 100%;
  padding-block: 11px;
  font-size: 14px;
}

.anim-card-quote {
  margin-top: 12px;
  padding: 9px 12px;
  background: var(--rk-paper-2);
  border-radius: 10px;
  font-size: 12.5px;
  color: var(--rk-ink-soft);
  font-style: italic;
}

.anim-cta-ghost {
  border: 1.5px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-size: 14px;
  border-radius: 999px;
  padding: 12px 22px;
  cursor: pointer;
  font-family: inherit;
}

@media (max-width: 1100px) {
  .anim-cw-main.is-script {
    overflow: auto;
    padding-block-end: 100px;
  }

  .anim-work-inner {
    height: auto;
    min-height: 100%;
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
  }

  .anim-flow-col {
    grid-column: 1;
    grid-row: 1;
    overflow: visible;
  }

  .anim-story-card {
    grid-column: 1;
    grid-row: 2;
    max-height: none;
    overflow: visible;
  }

  .anim-script-dock {
    position: fixed;
    z-index: 6;
    inset-inline: 14px;
    inset-block-end: 12px;
  }
}

@media (max-width: 720px) {
  .anim-cw-main.is-script {
    padding-inline: 12px;
    padding-block-end: 152px;
  }

  .anim-flow-col,
  .anim-story-card {
    padding: 16px;
  }

  .anim-reading-title,
  .anim-line.is-reading-title {
    margin-bottom: 22px;
    font-size: 21px;
  }

  .anim-reading-chapter + .anim-reading-chapter {
    margin-top: 28px;
  }

  .anim-reading-paragraph,
  .anim-line.is-reading-paragraph {
    font-size: 15px;
    line-height: 1.82;
  }

  .anim-script-reference {
    margin-top: 28px;
  }

  .anim-reference-tabs {
    width: 100%;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .anim-reference-tabs button {
    min-width: 0;
    padding-inline: 8px;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .anim-reference-panel {
    padding: 16px 14px;
  }

  .anim-reference-scenes summary {
    grid-template-columns: 1fr;
    gap: 3px;
  }

  .anim-reference-script {
    max-height: 360px;
    padding-inline: 12px 4px;
  }

  .anim-script-dock {
    grid-template-columns: 1fr;
    gap: 8px;
    inset-inline: 8px;
    inset-block-end: 8px;
  }

  .anim-script-dock-actions {
    display: grid;
    grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.28fr);
  }

  .anim-script-dock-actions.is-single-action {
    min-width: 0;
    grid-template-columns: 1fr;
  }

  .anim-script-dock-actions .anim-cta-main,
  .anim-script-dock-actions .anim-cta-ghost {
    width: 100%;
    padding-inline: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ═══ Animation style step — mirrors Storybook's mixed style workbench ═══ */
.anim-style-wrap {
  width: min(100%, 2200px);
  min-height: 100%;
  margin: 0 auto;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 18px;
}

.anim-style-focus {
  display: grid;
  grid-template-columns: auto minmax(300px, 1fr);
  gap: 32px;
  align-items: center;
  align-self: center;
  width: min(96%, 1360px);
  min-height: 0;
  padding-inline: 12px;
  justify-self: center;
}

.anim-style-hero {
  display: flex;
  gap: 12px;
  align-items: stretch;
  height: min(44vh, 380px);
  min-height: 240px;
  min-width: 0;
  max-width: 100%;
  justify-self: start;
}

.anim-style-hero img {
  height: 100%;
  min-width: 0;
  object-fit: cover;
  object-position: center top;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}

.anim-style-scene { aspect-ratio: 16 / 9; }
.anim-style-character { aspect-ratio: 3 / 4; }

.anim-style-badge-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-block-end: 12px;
}

.anim-style-engine {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding-inline: 12px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 32%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-emerald) 8%, var(--rk-surface));
  color: var(--rk-emerald-hover);
  font-size: 0.75rem;
  font-weight: 850;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.anim-style-model-info {
  position: relative;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  color: var(--rk-ink-faint);
  cursor: help;
  outline: none;
}

.anim-style-model-info > svg { width: 16px; height: 16px; }
.anim-style-model-info:hover,
.anim-style-model-info:focus-visible { color: var(--rk-emerald); }

.anim-style-model-tip {
  position: absolute;
  inset-block-start: calc(100% + 8px);
  inset-inline-start: -8px;
  z-index: 30;
  width: min(320px, 60vw);
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-size: 0.82rem;
  font-weight: 500;
  line-height: 1.55;
  text-transform: none;
  letter-spacing: normal;
  box-shadow: var(--rk-shadow-panel);
  opacity: 0;
  visibility: hidden;
  transition: opacity 140ms ease-out;
}

.anim-style-model-info:hover .anim-style-model-tip,
.anim-style-model-info:focus-visible .anim-style-model-tip {
  opacity: 1;
  visibility: visible;
}

.anim-style-info h2 {
  margin: 0 0 8px;
  font-family: var(--rk-font-display);
  font-size: 1.7rem;
  line-height: 1.2;
}

.anim-style-info > p:not(.anim-style-partner) {
  margin: 0 0 20px;
  color: var(--rk-ink-soft);
  line-height: 1.55;
}

.anim-style-use {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 50px;
  padding-inline: 26px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font: 800 15px/1 var(--rk-font-body);
  cursor: pointer;
  transition: background 180ms ease-out;
}

.anim-style-use:hover:not(:disabled) { background: var(--rk-emerald-hover); }
.anim-style-use:disabled { opacity: 0.58; cursor: not-allowed; }
.anim-style-use.is-locked { background: var(--rk-good); }
.anim-style-use svg { width: 18px; height: 18px; }

.anim-style-partner {
  margin: 18px 0 0;
  padding-block-start: 12px;
  border-block-start: 1px solid var(--rk-line);
  color: var(--rk-ink-faint);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.anim-style-grid-shell {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  gap: 12px;
  align-items: center;
  align-self: end;
  min-width: 0;
  margin-block-start: 22px;
}

.anim-style-grid-wrap {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.anim-style-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 10px;
  min-width: 0;
}

.anim-style-page-count {
  margin: 0;
  text-align: center;
  color: var(--rk-ink-faint);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
}

.anim-style-page-nav {
  appearance: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 45%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-emerald) 10%, var(--rk-surface));
  color: var(--rk-emerald);
  box-shadow: var(--rk-shadow-card);
  cursor: pointer;
  transition: border-color 180ms ease-out, color 180ms ease-out, background 180ms ease-out, opacity 180ms ease-out;
}

.anim-style-page-nav:hover:not(:disabled) {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.anim-style-page-nav:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 3px; }
.anim-style-page-nav:disabled { opacity: 0.28; cursor: default; box-shadow: none; }
.anim-style-page-nav svg { width: 20px; height: 20px; stroke-width: 1.8; }
.anim-style-page-nav.is-previous svg { transform: rotate(90deg); }
.anim-style-page-nav.is-next svg { transform: rotate(-90deg); }

.anim-style-thumb {
  display: grid;
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 2px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  overflow: hidden;
  text-align: start;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 180ms ease-out, transform 180ms ease-out, box-shadow 180ms ease-out;
}

.anim-style-thumb:hover { transform: translateY(-2px); box-shadow: var(--rk-shadow-card); }
.anim-style-thumb.is-active { border-color: var(--rk-emerald); }

.anim-style-thumb-media {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 3 / 4;
  background: var(--rk-paper-2);
  overflow: hidden;
}

.anim-style-thumb-media img,
.anim-style-thumb-media .anim-style-blank {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  background: var(--rk-paper-2);
}

.anim-style-thumb-caption {
  display: block;
  min-width: 0;
  padding: 7px 10px 8px;
}

.anim-style-thumb-name {
  display: block;
  min-width: 0;
  color: var(--rk-ink);
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.anim-style-thumb.is-active .anim-style-thumb-name { color: var(--rk-emerald); }

.anim-style-thumb-chip {
  position: absolute;
  inset-block-end: 5px;
  inset-inline-start: 5px;
  max-width: calc(100% - 10px);
  padding: 1px 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-ink) 60%, transparent);
  color: var(--rk-paper);
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

.anim-style-check {
  position: absolute;
  inset-block-start: 4px;
  inset-inline-end: 4px;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--rk-good);
  color: var(--rk-surface);
}

@media (max-width: 1340px) {
  .anim-style-hero { height: min(36vh, 300px); }
  .anim-style-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media (max-width: 1140px) {
  .anim-style-hero { height: min(30vh, 250px); }
}

@media (max-width: 1020px) {
  .anim-style-wrap { min-height: 0; }
  .anim-style-focus { grid-template-columns: minmax(0, 1fr); gap: 20px; padding: 18px; }
  .anim-style-hero { height: auto; max-height: 44vh; justify-self: stretch; }
  .anim-style-scene { flex: 1 1 62%; height: auto !important; }
  .anim-style-character { flex: 1 1 30%; height: auto !important; }
  .anim-style-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .anim-style-grid-shell { grid-template-columns: 36px minmax(0, 1fr) 36px; gap: 8px; }
}

@media (max-width: 600px) {
  .anim-style-focus { gap: 16px; padding: 14px; }
  .anim-style-hero { flex-wrap: wrap; max-height: none; }
  .anim-style-use { width: 100%; justify-content: center; }
  .anim-style-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .anim-style-grid-shell { grid-template-columns: 34px minmax(0, 1fr) 34px; gap: 6px; padding: 9px 8px 10px; }
  .anim-style-page-nav { width: 34px; height: 34px; }
}

.anim-cta-main:disabled {
  opacity: 0.5;
  cursor: default;
}

/* Reads as unavailable, behaves as pressable: the assets CTA uses this while the storyboard handoff
   is blocked, so the press is what surfaces the blocker list. Keep the pointer — it does answer. */
.anim-cta-main[aria-disabled='true'] {
  opacity: 0.5;
  cursor: pointer;
  box-shadow: none;
}

.anim-cta-main[aria-disabled='true']:hover {
  background: var(--rk-emerald);
}

/* ═══ Concept board step (WP-12 + WP-26: script digest column / rotating loading / lightbox /
   aha panel — Camika camika.html:377-413, paper-white) ═══ */
.anim-board-grid {
  max-width: var(--anim-page-max);
  margin: 0 auto;
  /* Fill the workspace and centre the board, like the style step — otherwise a short board
     hugs the top and leaves a dead band above the CTA on tall displays. */
  min-height: 100%;
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr);
  gap: 26px;
  align-items: stretch;
  align-content: center;
}

.anim-board-script {
  position: relative;
  align-self: stretch;
  max-height: calc(100vh - 190px);
  overflow-y: auto;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  padding: 15px;
  box-shadow: var(--rk-shadow-card);
  scrollbar-width: thin;
}

.anim-board-main {
  min-width: 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
}

.anim-board-script h3 {
  font-size: 14.5px;
  font-weight: 800;
  margin-bottom: 4px;
}

.anim-bs-logline {
  font-size: 11.5px;
  color: var(--rk-ink-soft);
  line-height: 1.5;
  margin-bottom: 10px;
}

.anim-board-script h4 {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.8px;
  color: var(--rk-emerald-hover);
  margin: 12px 0 6px;
}

.anim-bs-beat {
  display: flex;
  gap: 8px;
  padding: 4px 0;
}

.anim-bs-n {
  flex: 0 0 auto;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  border: 1px solid var(--rk-line);
  display: grid;
  place-items: center;
  font-size: 9.5px;
  font-weight: 800;
  color: var(--rk-ink-muted);
}

.anim-bs-beat p {
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--rk-ink-soft);
}

.anim-board-stage {
  position: relative;
  border-radius: 16px;
}

.anim-board-stage:not(.is-ready) {
  flex: 1 1 auto;
}

.anim-board-stage.is-ready {
  cursor: zoom-in;
}

.anim-board-loading {
  display: grid;
  place-items: center;
  gap: 10px;
  min-height: 380px;
  border: 1px dashed var(--rk-line);
  border-radius: 16px;
  /* pudding-write.gif has an opaque warm-paper matte; match its averaged edge
     color so the animated frame does not read as a separate square card. */
  background: #faf7f1;
  padding: 30px;
  text-align: center;
}

.anim-board-stage:not(.is-ready) .anim-board-loading {
  box-sizing: border-box;
  height: 100%;
}

.anim-board-loading p {
  font-size: 14.5px;
  font-weight: 700;
  color: var(--rk-ink-soft);
}

.anim-board-elapsed {
  font-size: 12px;
  color: var(--rk-ink-muted);
  font-variant-numeric: tabular-nums;
}

.anim-board-img {
  display: block;
  width: 100%;
  border-radius: 16px;
  border: 1px solid var(--rk-line);
  box-shadow: var(--rk-shadow-object);
  background: var(--rk-paper-2);
}

.anim-board-img.is-reveal {
  animation: anim-board-reveal 0.9s ease both;
}

@keyframes anim-board-reveal {
  from { opacity: 0; transform: scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* Hover-reveal zoom affordance (matches the storybook reference — the pill fades in on hover/focus
   instead of always sitting on the board). */
.anim-board-zoomhint {
  position: absolute;
  right: 12px;
  bottom: 12px;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--rk-ink-soft);
  background: rgba(250, 248, 244, 0.92);
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 4px 12px;
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 160ms ease-out, transform 160ms ease-out;
}

.anim-board-stage.is-ready:hover .anim-board-zoomhint,
.anim-board-stage.is-ready:focus-visible .anim-board-zoomhint {
  opacity: 1;
  transform: translateY(0);
}

.anim-board-cap {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 12px 4px 0;
}

.anim-board-cap h4 {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--rk-ink-muted);
}

.anim-board-cap p {
  font-size: 12px;
  line-height: 1.55;
  color: var(--rk-ink-muted);
}

/* Camika cwGoBoard: the aha panel slides in ~0.9s after the reveal lands */
.anim-board-aha {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  padding: 16px 20px;
  box-shadow: var(--rk-shadow-card);
  animation: anim-aha-in 0.5s ease 0.9s both;
}

@keyframes anim-aha-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

.anim-board-aha h3 {
  font-size: 16px;
  font-weight: 800;
}

.anim-board-aha-row {
  display: flex;
  gap: 10px;
  flex: 0 0 auto;
}

/* 与绘本的 .sb-vt-lightbox 同一套观感与同一套约束（Andy 2026-08-06：动画/MV 的放大要照绘本来）。
   ⚠️ 这里曾是 `display:grid; place-items:center` + 图片 `max-width/height:100%`，看着合理，实际
   **整条 max-height 被浏览器丢掉**：grid 行高未定（auto），百分比上限反过来又要参照行高，循环依赖。
   于是 1024×1024 的立绘在 1280×720 视口里原样铺开，底部溢出三百多像素——正是「放大后看不全」。
   flex 容器高度是确定的，加上视口单位的上限，就不存在这个参照问题。 */
.anim-board-lightbox {
  position: fixed;
  inset: 0;
  /* 要压过手搓弹框（61）——否则在弹框里点放大，大图被弹框盖住（2026-07-27 实测） */
  z-index: 70;
  background: rgba(10, 12, 11, 0.91);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 34px;
  cursor: zoom-out;
}

.anim-board-lightbox[hidden] {
  display: none;
}

.anim-board-lightbox img {
  /* 视口单位而非百分比：不依赖父级行高，任何布局下都成立。1040px 的上限同绘本 ——
     超大图在宽屏上铺满会显得廉价，留住边距才像「一件作品被端上来看」。 */
  max-width: min(92vw, 1040px);
  max-height: 91vh;
  border-radius: 10px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
}

.anim-board-lightbox-close {
  position: absolute;
  top: 18px;
  right: 22px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 0;
  background: rgba(250, 248, 244, 0.14);
  color: #fff8ee;
  font-size: 16px;
  cursor: pointer;
  font-family: inherit;
}

@media (max-width: 860px) {
  .anim-board-grid { grid-template-columns: 1fr; }
  .anim-board-script { position: static; max-height: 240px; order: 1; }
  .anim-board-aha { flex-direction: column; align-items: stretch; text-align: center; }
}

/* Animation concept proposal — Storybook's publisher-facing treatment hierarchy, while the
   Animation V3-owned 3:2 / strict 3x3 board remains the actual content object. */
.anim-concept-proposal {
  width: 100%;
  max-width: 1560px;
  height: 100%;
  min-height: 0;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
}

.anim-concept-proposal .anim-board-grid {
  width: 100%;
  max-width: none;
  min-height: 0;
  flex: 1 1 auto;
  margin: 0;
  grid-template-columns: minmax(270px, 320px) minmax(0, 1fr);
  gap: 18px;
  align-items: stretch;
  align-content: stretch;
}

.anim-concept-proposal .anim-board-script,
.anim-concept-proposal .anim-board-main {
  min-height: 0;
  height: 100%;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  background: var(--rk-surface);
  box-shadow: none;
}

.anim-concept-proposal .anim-board-script {
  max-height: none;
  padding: 18px 18px 8px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.anim-board-brief-head {
  flex: none;
  padding-block-end: 12px;
  border-block-end: 1px solid var(--rk-line);
}

.anim-board-brief-label,
.anim-board-moments-head,
.anim-board-stage-label {
  color: var(--rk-ink-muted);
  font-size: 0.67rem;
  font-weight: 800;
  letter-spacing: 0.08em;
}

.anim-board-brief-label,
.sb-vt-brief-label {
  display: flex;
  align-items: center;
  gap: 5px;
  text-transform: none;
}

.anim-board-brief-info,
.sb-vt-brief-info {
  position: relative;
  width: 17px;
  height: 17px;
  flex: none;
  display: grid;
  place-items: center;
  color: var(--rk-ink-faint);
  cursor: help;
  outline: none;
}

.anim-board-brief-info > svg,
.sb-vt-brief-info > svg {
  width: 15px;
  height: 15px;
}

.anim-board-brief-info:hover,
.anim-board-brief-info:focus-visible,
.sb-vt-brief-info:hover,
.sb-vt-brief-info:focus-visible {
  color: var(--rk-emerald);
}

.anim-board-brief-tip,
.sb-vt-brief-tip {
  position: absolute;
  inset-block-start: calc(100% + 8px);
  inset-inline-start: -4px;
  z-index: 20;
  width: min(278px, 72vw);
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-size: 0.74rem;
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: normal;
  box-shadow: var(--rk-shadow-panel);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 140ms ease-out;
}

.anim-board-brief-info:hover .anim-board-brief-tip,
.anim-board-brief-info:focus-visible .anim-board-brief-tip,
.sb-vt-brief-info:hover .sb-vt-brief-tip,
.sb-vt-brief-info:focus-visible .sb-vt-brief-tip {
  opacity: 1;
  visibility: visible;
}

.anim-board-brief-head strong {
  display: block;
  margin-block-start: 7px;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1.15rem;
  line-height: 1.25;
}

.anim-concept-proposal .anim-bs-logline {
  flex: none;
  margin: 12px 0 10px;
  color: var(--rk-ink-soft);
  font-size: 0.76rem;
  line-height: 1.62;
}

.anim-board-moments-head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 10px 8px;
  border-block-start: 1px solid var(--rk-line);
}

.anim-board-moments {
  min-height: 0;
  flex: 1 1 auto;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-y: auto;
  scrollbar-width: thin;
}

.anim-concept-proposal .anim-bs-beat {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: 10px;
  padding: 10px 2px;
  border-block-end: 1px solid var(--rk-paper-2);
}

.anim-concept-proposal .anim-bs-n {
  width: auto;
  height: auto;
  border: 0;
  place-items: start;
  color: var(--rk-emerald-hover);
  font-size: 0.69rem;
}

.anim-concept-proposal .anim-bs-beat p {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  color: var(--rk-ink-soft);
  font-size: 0.72rem;
  line-height: 1.55;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

.anim-concept-proposal .anim-board-main {
  width: min(100%, calc((100dvh - 198px) * 1.5));
  max-width: 100%;
  height: auto;
  align-self: center;
  justify-self: center;
  padding: 10px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.anim-board-stage-label {
  min-height: 28px;
  flex: none;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 0 2px 7px;
}

.anim-board-stage-label > span:first-child,
.anim-board-stage-label > span:last-child {
  white-space: nowrap;
}

.anim-board-style-state {
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  overflow: hidden;
  color: var(--rk-ink-muted);
  letter-spacing: normal;
}

.anim-board-style-state svg {
  width: 14px;
  height: 14px;
  flex: none;
  color: var(--rk-emerald);
}

.anim-board-style-state strong {
  overflow: hidden;
  font-size: 0.7rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-concept-proposal .anim-board-stage {
  width: 100%;
  aspect-ratio: 3 / 2;
  min-height: 0;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 12px;
  background: var(--rk-paper-2);
}

/* The plate the pre-image states sit on. Storybook lifts its board plate off the stage behind it
   (lighter fill + hairline + inset highlight, .sb-vt-board.is-generating); this one used to be the
   exact same paper as its own stage, so it read as a hole rather than a surface. */
.anim-concept-proposal .anim-board-loading {
  width: 100%;
  height: 100%;
  min-height: 0;
  border: 1px solid var(--rk-line);
  border-radius: 12px;
  background: var(--rk-paper);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rk-surface) 72%, transparent);
  padding: 24px;
}

.anim-board-image {
  position: relative;
  width: 100%;
  height: 100%;
  display: block;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 10px;
  background: var(--rk-paper-2);
  cursor: zoom-in;
}

.anim-concept-proposal .anim-board-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: cover;
  object-position: center;
  border: 0;
  border-radius: 10px;
  box-shadow: none;
}

.anim-board-image:hover .anim-board-zoomhint,
.anim-board-image:focus-visible .anim-board-zoomhint {
  opacity: 1;
  transform: translateY(0);
}

.anim-concept-proposal .anim-stale-notice {
  flex: none;
  margin: 7px 2px 0;
  font-size: 0.7rem;
}

.anim-board-footer {
  min-height: 58px;
  flex: none;
  margin-block-start: 8px;
  padding: 7px 10px 7px 16px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 18px;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  background: var(--rk-surface);
}

.anim-board-ack {
  padding-inline-start: 2px;
}

.anim-board-decision-copy {
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.anim-board-decision-copy strong {
  flex: none;
  color: var(--rk-ink);
  font-size: 0.83rem;
}

.anim-board-decision-copy span {
  min-width: 0;
  overflow: hidden;
  color: var(--rk-ink-muted);
  font-size: 0.7rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-concept-proposal .anim-board-aha-row {
  align-items: center;
}

.anim-concept-proposal .anim-board-aha-row > button {
  min-height: 42px;
}

/* Same emerald plate and width as storybook's upgrade entry (.sb-continue-btn + .sb-vt-upgrade).
   It used to carry only .sb-vt-stepwise, which is a size-and-type override with no background of its
   own — without the base class the button fell back to the browser's grey chrome (图1'). */
.anim-board-subscribe {
  min-width: 168px;
  padding-inline: 17px;
  font-size: 0.76rem;
  cursor: pointer;
}

/* ── Concept-board invite / failure plate (paper treatment, ported from storybook) ──────────────── */
/* Storybook's rule is "dark plate → white text, paper plate → ink text". This stage is paper until an
   image lands, so it takes the ink half: display-face title, muted body, quiet price caption, and the
   flow's standard emerald pill for the action. */
.anim-board-invite {
  width: min(430px, 78%);
  color: var(--rk-ink);
  text-align: center;
}

.anim-board-invite > svg {
  width: 40px;
  height: 40px;
  color: var(--rk-emerald);
}

.anim-board-invite.is-failed > svg {
  color: var(--rk-warn);
}

.anim-board-invite strong {
  display: block;
  margin-top: 20px;
  font-family: var(--rk-font-display);
  font-size: 1.35rem;
}

/* Storybook's metrics, but ink-SOFT rather than ink-muted: over there this line is a loading
   subtitle nobody has to read, here it is the description of what the button will do and charge for.
   Muted (#9b958a on paper) lands around 2.6:1 — fine for a caption, not for load-bearing copy. */
.anim-board-invite p {
  margin: 8px auto 0;
  color: var(--rk-ink-soft);
  font-size: 0.82rem;
  font-weight: 500;
  line-height: 1.55;
}

/* The price is a caption in storybook's register (.sb-vt-cost), not a headline — but it has to own a
   line: as an inline <small> it sat shoulder-to-shoulder with the CTA. It also has to stay readable,
   since it is the number the click is judged against. */
.anim-board-invite small {
  display: block;
  margin: 16px auto 0;
  color: var(--rk-ink-soft);
  font-size: 0.74rem;
}

.anim-board-invite .sb-continue-btn {
  min-width: 168px;
  margin-top: 18px;
  padding-inline: 18px;
  font-size: 0.78rem;
  cursor: pointer;
}

@media (max-width: 980px) {
  .anim-cw-main.is-board { overflow: auto; padding-inline: 18px; }
  .anim-concept-proposal { height: auto; min-height: 100%; }
  .anim-concept-proposal .anim-board-grid { grid-template-columns: 1fr; }
  .anim-concept-proposal .anim-board-script { height: auto; max-height: 300px; order: 0; }
  .anim-concept-proposal .anim-board-main { width: 100%; min-height: 520px; align-self: stretch; }
}

@media (max-width: 620px) {
  .anim-cw-main.is-board { padding-inline: 12px; }
  .anim-concept-proposal .anim-board-main { min-height: 390px; }
  .anim-board-stage-label { grid-template-columns: auto auto; }
  .anim-board-style-state { grid-column: 1 / -1; grid-row: 2; justify-content: flex-start; }
  .anim-board-footer { grid-template-columns: 1fr; padding: 13px; }
  .anim-board-ack > span { white-space: normal; }
  .anim-concept-proposal .anim-board-aha-row { width: 100%; }
  .anim-concept-proposal .anim-board-aha-row > button { flex: 1 1 0; }
}

/* ═══ Assets canvas (WP-13) — swimlanes + bezier edges + pan/zoom ═══ */
.anim-as-canvas {
  position: relative;
  /* Height comes from the desk box (grid stretch), not from its own viewport arithmetic. */
  height: auto;
  min-height: 0;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  background: var(--rk-paper-2);
  overflow: hidden;
  cursor: grab;
  touch-action: none;
}

.anim-as-canvas:active {
  cursor: grabbing;
}

.anim-as-stage {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  transform-origin: 0 0;
}

.anim-as-edges {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  pointer-events: none;
}

/* 连线视觉统一到分镜页那套档位（Jeff 2026-07-30 拍板：以分镜页为标准，两个画布一套语言）。
   结构线＝实线、稍重；参考线＝虚线、很轻；两者都用绿色主色与 non-scaling-stroke，
   缩放画布时线宽恒定，不会越放越粗。 */
.anim-as-edges path {
  fill: none;
  stroke: var(--rk-emerald);
  stroke-width: 2;
  /* 结构线（角色→拆解→换装）要看得见：它回答「这张拆解属于谁」。分镜页的 0.1 档能成立，
     是因为那页有几十条线形成纹理；资产页只有几条，压到那个档位在纸底上等于没有
     （Jeff 2026-07-30 实测「好像没有连线了」）。参考线仍按分镜页口径压到 0.14。 */
  stroke-opacity: 0.55;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: stroke-opacity 180ms ease-out, stroke-width 180ms ease-out;
}

/* 绑定线（换装→片场 / 道具→融合）＝参考关系，与分镜页的 .is-ref 完全同款：同色、同粗、
   同虚线节奏、同透明度。选中卡片时由 .is-active 提上来。 */
.anim-as-edges path.is-bind {
  stroke-dasharray: 7 7;
  stroke-opacity: 0.14;
}

.anim-as-edge circle {
  fill: var(--rk-surface);
  stroke: var(--rk-emerald-hover);
  stroke-width: 2.2;
  opacity: 0.9;
  transition: opacity 140ms ease-out, r 140ms ease-out;
}

/* 选中态与分镜页 .is-ref.is-active 同档（2.75 / 0.92），两个画布提亮的力度一致。 */
.anim-as-edge.is-active path {
  stroke: var(--rk-emerald);
  stroke-width: 2.75;
  stroke-opacity: 0.92;
}

.anim-as-edge.is-active circle {
  r: 5;
  fill: var(--rk-emerald-soft);
  opacity: 1;
  animation: anim-ref-endpoint-arrive 720ms ease-out both;
}

.anim-as-edge.is-muted path {
  stroke-opacity: 0.06;
}

.anim-as-edge.is-muted circle {
  opacity: 0.12;
}

.anim-as-node {
  position: absolute;
  background: var(--rk-surface);
  border: 1.5px solid var(--rk-line);
  border-radius: 14px;
  padding: 7px;
  box-shadow: var(--rk-shadow-card);
  display: flex;
  flex-direction: column;
  gap: 6px;
  cursor: pointer;
  transition: transform 170ms ease-out, border-color 170ms ease-out, box-shadow 170ms ease-out;
  transform-origin: center;
}

.anim-as-node:hover {
  z-index: 3;
  transform: translateY(-2px) scale(1.01);
  border-color: color-mix(in srgb, var(--rk-emerald) 46%, var(--rk-line));
  box-shadow: 0 12px 28px -19px var(--rk-ink-soft);
}

.anim-as-node.is-selected {
  z-index: 2;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-emerald-soft), var(--rk-shadow-card);
}

.anim-as-node.is-selected::before,
.anim-as-node.is-fresh::after {
  content: "";
  position: absolute;
  inset: -5px;
  border: 2px solid var(--rk-emerald);
  border-radius: 18px;
  opacity: 0;
  pointer-events: none;
}

.anim-as-node.is-selected::before {
  animation: anim-card-select-arrive 420ms cubic-bezier(.2, .9, .3, 1.2) both;
}

.anim-as-node.is-fresh::after {
  inset: -7px;
  animation: anim-card-fresh 1500ms ease-out both;
}

.anim-as-node.is-related:not(.is-selected) {
  border-color: var(--rk-emerald-hover);
  box-shadow: 0 0 0 2px var(--rk-emerald-soft), var(--rk-shadow-card);
}

@keyframes anim-card-select-arrive {
  0% { opacity: 0; transform: scale(.96); }
  42% { opacity: .78; }
  100% { opacity: 0; transform: scale(1.045); }
}

@keyframes anim-card-fresh {
  0% { opacity: 0; transform: scale(.97); }
  18%, 46% { opacity: .86; }
  100% { opacity: 0; transform: scale(1.055); }
}

.anim-as-media {
  flex: 1;
  min-height: 0;
  border-radius: 9px;
  overflow: hidden;
  background: var(--rk-paper);
  display: grid;
  place-items: center;
}

.anim-as-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Turnarounds, outfit sheets and prop/fusion references are wide production sheets. Keep the whole
   reference visible; cropping any side view breaks the meaning of the asset card. */
.anim-as-node.is-decomp .anim-as-media img,
.anim-as-node.is-variant .anim-as-media img,
.anim-as-node.is-prop .anim-as-media img,
.anim-as-node.is-fusion .anim-as-media img {
  object-fit: contain;
  background: var(--rk-paper-2);
}

.anim-as-wait {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--rk-ink-muted);
}

.anim-as-wait.is-failed {
  color: #a65a4a;
  font-weight: 700;
}

/* 在跑的资产卡：转圈 + 「制作中/排队中」+ 真实等待时长（或服务端给的百分比）。
   以前这里只有一个静止的「—」，用户分不出「在画」和「还没开始」——两张图要三五分钟，
   整段时间屏幕上没有任何东西在动。 */
.anim-as-wait.is-working {
  color: var(--rk-ink);
  font-weight: 600;
}

.anim-as-wait .anim-as-wait-detail {
  font-style: normal;
  font-size: 11px;
  font-weight: 500;
  color: var(--rk-ink-muted);
  font-variant-numeric: tabular-nums; /* 秒数跳动时宽度不抖 */
}

.anim-status-sub {
  display: block;
  margin: 0;
  color: var(--rk-ink-muted);
  font-size: 11px;
  font-style: normal;
  font-weight: 500;
  line-height: 1.4;
  overflow-wrap: anywhere;
  text-align: center;
  white-space: normal;
}

.anim-as-spin {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--rk-line);
  border-top-color: var(--rk-emerald);
  animation: rk-spin 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .anim-as-spin {
    animation-duration: 2.4s;
  }
}

.anim-as-label {
  flex: none;
  font-size: 12px;
  color: var(--rk-ink);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 资产卡 label 只放名字，允许两行展示完整（Jeff 2026-07-29）；分镜条(is-shot)保持原有单行结构。 */
.anim-as-node:not(.is-shot) .anim-as-label {
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.3;
  flex: 1; /* 名字吃掉剩余宽度，按钮因此稳定贴在卡片右下角（各卡对齐） */
  min-width: 0; /* 名字长了就自己省略，不要把按钮挤出卡外 */
}

/* 卡片底排：名字 + 「生成/重画」并排（Jeff 2026-08-03 截图拍板）。
   原来按钮是 absolute 压在卡片右下角，实测盖住图片 9px、还要 label 空出 92px 死宽度——
   名字被截、画面被遮。改成正常流里的一行后，按钮永远落在图**下方**，名字拿走剩下的宽度。
   行高（2 行名字 ≈ 32px）仍在 AS_CARD_CHROME 预留的 34px 之内，卡片高度算法不用动。 */
.anim-as-foot {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
}

.anim-as-kind {
  display: inline-block;
  font-size: 10px;
  font-weight: 800;
  color: var(--rk-ink-muted);
  background: var(--rk-paper-2);
  border-radius: 999px;
  padding: 1px 7px;
  margin-inline-end: 6px;
}

.anim-as-topright {
  position: absolute;
  inset-block-start: 14px;
  inset-inline-end: 14px;
  z-index: 3;
}

.anim-as-genall {
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
  font-weight: 800;
  font-size: 13.5px;
  border-radius: 999px;
  padding: 9px 20px;
  cursor: pointer;
  font-family: inherit;
  box-shadow: 0 8px 20px -10px rgba(15, 164, 126, 0.55);
}

.anim-as-genall:disabled {
  opacity: 0.6;
  cursor: default;
}

/* ═══ WP-26 第二批: canvas furniture shared by assets + shots ═══ */
.anim-as-sec {
  position: absolute;
  /* Keep the section label on one line: wrapping made it two lines tall and it ran
     under the first asset chip, whose row starts 24px down. */
  white-space: nowrap;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--rk-emerald-hover);
}

.anim-as-role {
  display: inline-block;
  font-style: normal;
  font-size: 9.5px;
  font-weight: 800;
  color: var(--rk-emerald);
  border: 1px solid var(--rk-emerald-soft);
  border-radius: 999px;
  padding: 0 6px;
  margin-inline-start: 6px;
  vertical-align: 1px;
}

.anim-as-role.is-lib {
  color: var(--rk-ink-muted);
  border-color: var(--rk-line);
}

.anim-as-media {
  position: relative;
}

.anim-as-zoom {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 6px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 0;
  background: rgba(250, 248, 244, 0.9);
  color: var(--rk-ink-soft);
  font-size: 14px;
  line-height: 1;
  cursor: zoom-in;
  font-family: inherit;
  opacity: 0;
  transition: opacity 0.15s;
}

/* 美术台弹窗里资产还没出图时的占位：撑住与图片同样的位置，避免右栏塌下来。 */
.anim-ed-stage-empty {
  display: grid;
  place-items: center;
  min-height: 220px;
  border: 1px dashed var(--rk-line);
  border-radius: 12px;
  color: var(--rk-ink-soft);
  background: var(--rk-paper-2);
}

/* 手搓入口：跟放大镜同一排，贴在这一镜的图上（Jeff 2026-07-28 把它从 chat 头部搬来这里）。 */
.anim-as-edit {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 34px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  background: rgba(250, 248, 244, 0.9);
  color: var(--rk-ink-soft);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s, color 0.15s;
}

/* （:has 顶位规则 2026-07-29 下线——动作按钮改进 .anim-as-acts flex 排，谁缺谁自动补位。） */

.anim-as-edit:hover {
  color: var(--rk-emerald);
}

/* 徽章角（Jeff 2026-07-29 三次拍板）：图左上角只放一枚主/配角定位章；
   「来自角色库」用同一容器的 is-bottom 变体贴图片**左下角**——名字行只放名字。 */
.anim-as-corner {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-start: 6px;
  pointer-events: none;
}

.anim-as-corner.is-bottom {
  inset-block-start: auto;
  inset-block-end: 6px;
}

/* 左下角已有质检 ⓘ 角标时，库章往上错一格，别叠在一起。 */
.anim-as-media:has(.anim-as-qa-badge) .anim-as-corner.is-bottom {
  inset-block-end: 28px;
}

.anim-as-corner .anim-as-role {
  margin-inline-start: 0;
  background: rgba(250, 248, 244, 0.92);
}

/* 角色定位章的独立条：图**上方**，不再压在立绘上（Andy 2026-08-06）。卡片高度已在
   animAsNodes() 里按 AS_CARD_ROLE_BAND 多买了这一条，所以图区不因此变矮；两条为止,
   再长的定位就截断——这枚章是给人扫一眼的标签,不是简介。 */
.anim-as-head {
  flex: none;
  display: flex;
  align-items: flex-start;
  min-height: 0;
}

.anim-as-head .anim-as-role {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  margin-inline-start: 0;
  padding: 1px 7px;
  line-height: 1.35;
  text-align: start;
  vertical-align: baseline;
  white-space: normal;
  background: var(--rk-emerald-soft);
}

/* 动作排（铅笔/放大镜）挪到**卡片外**右上方悬浮（Jeff 截图拍板）；padding 当 hover 桥，
   鼠标从卡片挪上来不断链。按钮仍是 node 的子元素，视觉在卡外、hover 判定仍算在卡上。 */
.anim-as-acts {
  position: absolute;
  inset-block-end: 100%;
  inset-inline-end: 4px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding-block-end: 5px;
}

.anim-as-acts .anim-as-edit,
.anim-as-acts .anim-as-zoom {
  position: static;
  box-shadow: 0 2px 8px -3px var(--rk-ink-soft);
}

/* Match Storybook's primary per-card generate action while keeping Animation's footer placement. */
.anim-as-regen {
  flex: none;
  max-width: 60%; /* 窄卡（170px）上按钮不许吃掉整排，名字总要留得下 */
  min-height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  border: 0;
  border-radius: 999px;
  padding: 0 9px;
  font-family: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  background: var(--rk-emerald);
  color: #fff;
  cursor: pointer;
  opacity: 1;
  transition: background 140ms ease-out, box-shadow 140ms ease-out;
}

.anim-as-regen span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-as-regen svg {
  width: 13px;
  height: 13px;
  flex: none;
}

.anim-as-regen:hover:not(:disabled) {
  background: var(--rk-emerald-hover);
}

/* 「去充值」只长在余额不足的失败卡上，与它旁边的「重画」并排。做成描边款是因为两颗实心绿并排
   会分不清哪颗是主动作 —— 而且这一步的顺序是先充值、后重画，两颗长得一样反而让人乱点。 */
.anim-as-regen.is-topup {
  background: transparent;
  color: var(--rk-emerald);
  box-shadow: inset 0 0 0 1px var(--rk-emerald);
}

.anim-as-regen.is-topup:hover:not(:disabled) {
  background: color-mix(in srgb, var(--rk-emerald) 12%, transparent);
}

.anim-as-regen:focus-visible {
  outline: 2px solid var(--rk-surface);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--rk-emerald);
}

/* A faded emerald pill still reads as "the button is just far away" — and this state now lasts as
   long as an upstream image is missing, not the 300ms of one submission, so it has to say "you
   cannot press this yet" on sight. Grey fill + not-allowed do that; the title names what it waits
   for. Keep this the ONLY .anim-as-regen:disabled rule — a second copy below silently wins on the
   properties it repeats, which is exactly how the cursor got lost the first time. */
.anim-as-regen:disabled {
  background: var(--rk-line);
  color: var(--rk-ink-soft);
  box-shadow: none;
  opacity: 0.7;
  cursor: not-allowed;
}

.anim-as-node:hover .anim-as-zoom,
.anim-as-node:hover .anim-as-edit,
.anim-as-node.is-selected .anim-as-edit,
.anim-sh-chip:hover .anim-as-zoom {
  opacity: 1;
}

.anim-ready-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 800;
  color: var(--rk-ink-soft);
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 7px 14px;
  margin-inline-end: 10px;
  box-shadow: var(--rk-shadow-card);
}

.anim-ready-pill i {
  width: 54px;
  height: 4px;
  border-radius: 2px;
  background: var(--rk-paper-2);
  overflow: hidden;
}

.anim-ready-pill b {
  display: block;
  height: 100%;
  background: var(--rk-emerald);
  border-radius: 2px;
}

/* 画布控件（2026-08-03，worklist #299 ④）。资产台与分镜台同一套。
   **2026-08-11 从左下角移到左上角**（Andy：「这个画布的放大缩小放到画布左上角……当前按钮功能失效」）。
   失效根因就是那个位置：分镜步的画布底部压着一整条胶片条（.anim-strip 所在的第二行），
   控件按 inset-block-end:8px 钉在画布左下角，正好落到胶片条底下 —— 按钮画得出来、点不着。
   从前给 .anim-sh-workbench 打过一个 inset-block-end:130px 的补丁把它顶上去，但那是**另一个**
   布局类；分镜步用的是 .anim-sh-workspace，补丁根本没生效。左上角没有任何东西压着，
   两个画布、所有布局一致，这类「被别的层吃掉点击」的问题从结构上就不会再有。 */
.anim-canvas-ctl {
  position: absolute;
  z-index: 6;
  inset-block-start: 12px;
  inset-inline-start: 12px;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.86);
  box-shadow: 0 4px 14px -10px var(--rk-ink-soft);
}

.anim-canvas-ctl button {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: background 140ms ease-out, color 140ms ease-out;
}

.anim-canvas-ctl button:hover {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
}

.anim-canvas-ctl button:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 1px;
}

.anim-canvas-hint {
  position: absolute;
  inset-block-end: 10px;
  inset-inline-start: 12px; /* 控件 2026-08-11 移到左上角后，这里不必再让位 */
  font-size: 11px;
  color: var(--rk-ink-muted);
  pointer-events: none;
}

/* ═══ Shots canvas (WP-17/18 grid → WP-26 拍板 F: chips row + ref edges + shot nodes) ═══ */
.anim-sh-wrap {
  display: flex;
  height: var(--anim-desk-h);
  width: 100%;
  max-width: var(--anim-page-max);
  margin-inline: auto;
  flex-direction: column;
  gap: 12px;
}

.anim-sh-workbench {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 0;
  overflow: hidden;
}

.anim-sh-workbench > .anim-as-canvas.is-shots {
  width: 100%;
  height: 100%;
}

.anim-sh-filmstrip-float {
  position: absolute;
  inset-inline: 18px;
  inset-block-end: 16px;
  z-index: 4;
  min-width: 0;
  padding: 7px 10px 3px;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: 14px;
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
  transition: inset-inline-start 180ms ease-out;
}

.anim-sh-workbench.has-inspector .anim-sh-filmstrip-float {
  inset-inline-start: 310px;
}

/* 分镜工作台底部还压着一条胶片条，控件与提示一起抬到它上面。 */
.anim-sh-workbench .anim-canvas-hint {
  inset-block-end: 132px;
}

/* ~~.anim-sh-workbench .anim-canvas-ctl { inset-block-end: 130px }~~ —— 2026-08-11 删除。
   它是「把控件从胶片条底下顶上去」的补丁，而控件现在钉在左上角，没有可顶的东西了。
   （它本来也没救到分镜步：那一屏是 .anim-sh-workspace，不是 .anim-sh-workbench。） */

.anim-sh-workspace {
  display: grid;
  flex: 1 1 auto;
  min-height: 0;
  grid-template-columns: var(--anim-desk-rail) minmax(0, 1fr);
  /* Two rows: canvas on top, filmstrip below in the canvas column only — the director desk spans
     both rows so it runs the full workspace height (拉到底). */
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 12px;
  min-width: 0;
}

.anim-sh-workspace > .anim-dd-dock {
  grid-row: 1 / -1;
  height: auto;
  min-height: 0;
}

.anim-sh-striprow {
  grid-column: 2;
  min-width: 0;
}

.anim-dd-dock {
  height: calc(100vh - 340px);
  min-height: 420px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  padding: 17px;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
}

.anim-dd-dock .anim-ad-log {
  flex: 1;
  min-height: 72px;
  overflow-y: auto;
}

.anim-dd-dock .anim-chatbar {
  margin-top: auto;
}

.anim-ref-diagnostic {
  display: grid;
  gap: 7px;
  max-height: 168px;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 45%, var(--rk-line));
  border-radius: 10px;
  background: color-mix(in srgb, var(--rk-warn) 7%, var(--rk-surface));
  font-size: 10.5px;
}

.anim-ref-diagnostic > strong { color: var(--rk-warn); }
.anim-ref-diagnostic ul { display: grid; gap: 5px; margin: 0; padding: 0; list-style: none; }
.anim-ref-diagnostic li { display: grid; grid-template-columns: 60px minmax(0, 1fr); gap: 6px; }
.anim-ref-diagnostic li b { color: var(--rk-ink-soft); }
.anim-ref-diagnostic li span { color: var(--rk-ink-muted); overflow-wrap: anywhere; }
.anim-ref-diagnostic button,
.anim-ref-warning {
  border: 1px solid color-mix(in srgb, var(--rk-warn) 60%, var(--rk-line));
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-warn);
  cursor: pointer;
  font: 800 10.5px/1 var(--rk-font-body);
}

.anim-ref-diagnostic button { justify-self: start; min-height: 28px; padding: 0 11px; }

.anim-ref-warning {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-start: 6px;
  z-index: 2;
  min-height: 25px;
  padding: 0 9px;
  background: color-mix(in srgb, var(--rk-surface) 92%, transparent);
  box-shadow: 0 3px 10px rgba(60, 42, 18, 0.14);
}

/* Selected shot = one card: the "Directing: S1" header and that shot's frames are a single
   object, not a floating chip above a loose strip. */
.anim-dd-card {
  display: flex;
  flex: 0 1 auto;
  flex-direction: column;
  /* 卡片现在活在会话流里，跟着一起滚，不再需要夹高度给聊天让位（2026-07-27 会话流改造）。 */
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 42%, var(--rk-line));
  border-radius: 12px;
  background: var(--rk-surface);
}

.anim-dd-card-head { flex: 0 0 auto; }

.anim-dd-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 7px 7px 11px;
  background: color-mix(in srgb, var(--rk-emerald) 12%, var(--rk-surface));
}

.anim-dd-card-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: var(--rk-emerald-hover);
  font: 800 11.5px/1.4 var(--rk-font-body);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.anim-dd-card-clear {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: 6px;
  padding: 0;
  background: transparent;
  color: var(--rk-emerald-hover);
  cursor: pointer;
}

.anim-dd-card-clear:hover { background: color-mix(in srgb, var(--rk-emerald) 20%, transparent); }

/* Frame picker: you choose the cell you can see (Camika parity) rather than a bare F-number.
   Two per row so a 4-grid reads as the 2x2 it actually is. */
.anim-dd-frames {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  min-height: 0;
  padding: 8px;
  overflow-y: auto;
}

/* Drill-in: one cell at full width with its own version history under it. */
.anim-dd-drill {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 7px;
  min-height: 0;
  padding: 8px;
  overflow-y: auto;
}

.anim-dd-drill-stage {
  position: relative; /* 「旧图」角标定位在这张图上，不加就飞到页面角落去了 */
  display: grid;
  place-items: center;
  border-radius: 8px;
  background: var(--rk-paper);
}

.anim-dd-drill-stage img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 8px;
}

.anim-dd-drill-label {
  margin: 0;
  color: var(--rk-ink-muted);
  font: 750 10px/1 var(--rk-font-body);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.anim-dd-drill-versions {
  display: flex;
  gap: 6px;
  padding-block-end: 2px;
  overflow-x: auto;
}

.anim-dd-drill-version {
  position: relative;
  flex: 0 0 auto;
  width: 62px;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: 7px;
  padding: 0;
  background: var(--rk-surface);
  cursor: pointer;
}

.anim-dd-drill-version img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.anim-dd-drill-version > span {
  position: absolute;
  inset-block-end: 2px;
  inset-inline-start: 3px;
  border-radius: 4px;
  padding: 0 4px;
  background: rgba(23, 24, 21, 0.66);
  color: #fff;
  font: 800 9px/1.6 var(--rk-font-body);
}

.anim-dd-drill-version:hover:not(:disabled),
.anim-dd-drill-version.is-active {
  border-color: var(--rk-emerald);
  box-shadow: inset 0 0 0 2px var(--rk-emerald);
}

.anim-dd-drill-version:disabled { cursor: default; opacity: 0.55; }

.anim-dd-drill-version.is-pending {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 9;
  border-style: dashed;
  color: var(--rk-ink-muted);
  font: 750 9.5px/1 var(--rk-font-body);
}

.anim-dd-card-back {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: 6px;
  padding: 0;
  background: transparent;
  color: var(--rk-emerald-hover);
  cursor: pointer;
}

.anim-dd-card-back:hover { background: color-mix(in srgb, var(--rk-emerald) 20%, transparent); }

.anim-dd-card.is-drilled { max-height: 74%; }

.anim-dd-frames-wait {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--rk-ink-muted);
  font-size: 11px;
  text-align: center;
}

.anim-dd-frame {
  position: relative;
  display: block;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: 8px;
  padding: 0;
  background: var(--rk-surface);
  cursor: pointer;
}

.anim-dd-frame img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.anim-dd-frame > span {
  position: absolute;
  inset-block-start: 3px;
  inset-inline-start: 4px;
  border-radius: 5px;
  padding: 1px 5px;
  background: rgba(23, 24, 21, 0.66);
  color: #fff;
  font: 800 9.5px/1.5 var(--rk-font-body);
}

.anim-dd-frame.is-full {
  grid-column: 1 / -1;
}

.anim-dd-frame:hover,
.anim-dd-frame.is-active {
  border-color: var(--rk-emerald);
  box-shadow: inset 0 0 0 2px var(--rk-emerald);
}

.anim-dd-frame-actions {
  display: flex;
  padding: 0 8px 8px;
}

.anim-dd-frame-merge {
  flex: 1;
  border: 1px solid var(--rk-line);
  border-radius: 8px;
  padding: 7px 0;
  background: var(--rk-paper);
  color: var(--rk-ink-soft);
  font: 750 11px/1 var(--rk-font-body);
  cursor: pointer;
}

.anim-dd-frame-merge:hover:not(:disabled) {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
}

.anim-dd-frame-merge:disabled {
  opacity: 0.45;
  cursor: default;
}

.anim-as-canvas.is-shots {
  height: auto;
}

.anim-sh-inspector {
  z-index: 8;
  width: 280px;
}

.anim-sh-insp-scroll {
  overscroll-behavior: contain;
}

.anim-sh-prompt-panel,
.anim-sh-assistant-panel {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.anim-sh-prompt-media {
  display: block;
  width: 100%;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  background: var(--rk-paper-2);
  cursor: zoom-in;
}

.anim-sh-prompt-media img {
  display: block;
  width: 100%;
  max-height: 240px;
  object-fit: contain;
}

.anim-sh-prompt-text {
  min-height: 190px;
  resize: vertical;
}

.sb-as-insp-footer > .anim-sh-prompt-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
}

.anim-sh-prompt-actions .sb-as-insp-redraw {
  grid-column: auto;
}

.anim-sh-prompt-actions button {
  min-width: 0;
  min-height: 44px;
  padding: 8px 9px;
  line-height: 1.2;
  white-space: normal;
}

.anim-sh-assistant-footer {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.anim-sh-assistant-panel .anim-ad-log {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* 参考线的存在感（2026-08-03 下调，worklist #299 ④）。单条线 0.14 不算重，但 15~24 个镜头
   × 每镜数个资产 ≈ 上百条，叠在一起就是一层铺满画布的绿雾——需求说的「镜头一多就显得杂乱」
   指的正是这个。单条降到快看不见的程度，关系照样看得出来（走向还在），画布回到「纸上的卡片」。 */
.anim-as-edges path.is-ref {
  stroke: var(--rk-emerald);
  stroke-width: 2;
  stroke-opacity: 0.09;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  transition: stroke-opacity 180ms ease-out, stroke-width 180ms ease-out;
}

.anim-as-edges path.is-ref.is-scene {
  stroke-dasharray: 7 7;
  stroke-opacity: 0.07;
}

.anim-as-edges path.is-ref.is-entity {
  stroke-opacity: 0.1;
}

.anim-as-edges path.is-ref.is-fusion {
  stroke-width: 2.5;
  stroke-opacity: 0.13;
}

/* 选中一个镜头 = 提问「这一格用了哪些资产」。此时无关的线让到底，答案才立得出来。 */
.anim-as-edges.has-focus path.is-ref {
  stroke-opacity: 0.035;
}

.anim-as-edges path.is-ref.is-active,
.anim-as-edges.has-focus path.is-ref.is-active {
  stroke-width: 2.75;
  stroke-opacity: 0.92;
}

.anim-sh-ref circle {
  fill: var(--rk-surface);
  stroke: var(--rk-emerald);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box;
  transform-origin: center;
}

.anim-sh-ref.is-active circle {
  animation: anim-ref-endpoint-arrive 720ms ease-out both;
}

@keyframes anim-ref-endpoint-arrive {
  0% { opacity: 0; transform: scale(.55); }
  38% { opacity: 1; transform: scale(1.45); }
  100% { opacity: 1; transform: scale(1); }
}

.anim-sh-chip {
  position: absolute;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  padding: 4px;
  box-shadow: var(--rk-shadow-card);
  transition: transform 170ms ease-out, border-color 170ms ease-out, box-shadow 170ms ease-out;
}

.anim-sh-chip:hover {
  z-index: 2;
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--rk-emerald) 46%, var(--rk-line));
  box-shadow: 0 10px 24px -18px var(--rk-ink-soft);
}

.anim-sh-chip.is-related {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-emerald-soft), var(--rk-shadow-card);
}

.anim-sh-chip img {
  display: block;
  width: 100%;
  height: 64px;
  object-fit: cover;
  border-radius: 7px;
  background: var(--rk-paper-2);
}

/* 两行（2026-08-03）。单行 + 省略号在真实数据上失效：动画项目的片场名是一整句
   （「Open desert dunes under a rising moon」），换装标签也是描述式的
   （「Base look — open desert journey」），10 张卡里 5 张被截在同一个位置、肉眼分不出谁是谁。
   截断本身不是问题，截得只剩公共前缀才是。两行让差异出现在可见区内；完整文本仍在 title 里。 */
.anim-sh-chip span {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--rk-ink-soft);
  overflow: hidden;
}

/* 分镜四态（2026-08-03，worklist #299 ③）。一套语义两种排布：没出图时占满画面居中，
   已有图但正在重画时缩成左上角小药丸。已完成不画任何东西——画面本身就是完成的信号。 */
.anim-shot-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
  color: var(--rk-ink-muted);
}

.anim-shot-state.is-block {
  flex-direction: column;
  gap: 8px;
  font-size: 12px;
}

.anim-shot-state.is-pill {
  position: absolute;
  z-index: 2;
  inset-block-start: 6px;
  inset-inline-start: 6px;
  border-radius: 999px;
  padding: 5px 10px;
  background: rgba(250, 248, 244, 0.94);
  box-shadow: 0 2px 8px -3px var(--rk-ink-soft);
}

.anim-shot-state.is-rendering,
.anim-shot-state.is-queued { color: var(--rk-emerald); }

.anim-shot-state.is-failed { color: #a65a4a; }

.anim-shot-state .spinner-sm {
  width: 13px;
  height: 13px;
  flex: none;
}

.anim-shot-state.is-block .spinner-sm,
.anim-shot-state.is-block svg {
  width: 20px;
  height: 20px;
}

.anim-as-node.is-shot .anim-as-label b {
  display: block;
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.anim-shot-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--rk-ink-muted);
  margin-top: 2px;
}

.anim-as-node.is-excluded {
  opacity: 0.55;
}

.anim-shot-skip {
  font-style: normal;
  font-size: 10.5px;
  font-weight: 800;
  color: var(--rk-ink-muted);
  background: var(--rk-paper-2);
  border-radius: 999px;
  padding: 2px 8px;
}

.anim-shot-retry {
  margin-inline-start: auto;
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 12px;
  color: var(--rk-ink-soft);
  cursor: pointer;
  font-family: inherit;
}

.anim-shot-retry:hover {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
}

.anim-shot-generate {
  margin-inline-start: auto;
  min-height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border: 0;
  border-radius: 999px;
  padding: 4px 11px;
  background: var(--rk-emerald);
  color: #fff;
  font: 800 11px/1 var(--rk-font-body);
  cursor: pointer;
  box-shadow: 0 7px 16px -10px color-mix(in srgb, var(--rk-emerald) 70%, transparent);
  transition: background 140ms ease-out, transform 140ms ease-out;
}

.anim-shot-generate svg {
  width: 13px;
  height: 13px;
}

.anim-shot-generate:hover:not(:disabled) {
  background: var(--rk-emerald-hover);
  transform: translateY(-1px);
}

.anim-shot-generate:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-shot-generate:disabled {
  opacity: 0.58;
  cursor: wait;
  transform: none;
}

/* ═══ Narrative filmstrip (shots + video, Camika cwVdStripBuild) ═══ */
.anim-strip {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: 6px 2px 10px;
  scrollbar-width: thin;
}

.anim-strip-cell {
  position: relative;
  flex: 0 0 118px;
  background: var(--rk-surface);
  border: 1.5px solid var(--rk-line);
  border-radius: 10px;
  padding: 4px;
  cursor: pointer;
  box-shadow: var(--rk-shadow-card);
}

.anim-strip-cell.is-sel {
  border-color: var(--rk-emerald);
}

.anim-strip-cell.is-excluded {
  opacity: 0.5;
}

.anim-strip-thumb {
  height: 60px;
  border-radius: 7px;
  overflow: hidden;
  background: var(--rk-paper-2);
  display: grid;
  place-items: center;
  color: var(--rk-ink-muted);
}

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

.anim-strip-meta {
  display: flex;
  justify-content: space-between;
  padding: 4px 3px 0;
  font-size: 10.5px;
  color: var(--rk-ink-muted);
}

.anim-strip-meta b {
  color: var(--rk-ink-soft);
}

.anim-strip-state {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-start: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  z-index: 1;
  background: var(--rk-line);
}

.anim-strip-state[data-state="img"] { background: var(--rk-ink-muted); }
.anim-strip-state[data-state="gen"] { background: var(--rk-emerald); animation: anim-live-pulse 1.2s ease-in-out infinite; }
.anim-strip-state[data-state="done"] { background: var(--rk-emerald); }
/* Failure needs its own dot, and a ring so it reads even for colour-blind authors — before this the
   failed shot shared the muted grey of "not shot yet" (findings F-14). Additive rule only. */
.anim-strip-state[data-state="failed"] {
  background: var(--rk-danger, #d64545);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--rk-danger, #d64545) 28%, transparent);
}

/* ═══ Video focused stage (WP-20 grid → WP-26 拍板 G, Camika cwVdStage) ═══ */
/* Deliberately NOT capped at --anim-page-max: the player is the point of this step, so it is sized
   by the desk height and the page opens up around it. Filling the desk like the storyboard step
   does (was: min-height + centred, which left ~130px dead above and below on tall screens). */
.anim-vd-wrap {
  --anim-vd-detail-w: calc(var(--anim-desk-rail) * 0.9);
  --anim-vd-strip-h: 150px;
  width: 100%;
  height: var(--anim-desk-h);
  min-height: 0;
  display: grid;
  grid-template-columns: var(--anim-vd-detail-w) minmax(0, 1fr);
  align-items: stretch;
  gap: 20px;
}

@media (min-width: 901px) {
  .anim-cw-main.is-video {
    display: flex;
    overflow: hidden;
    padding-block: 26px 20px;
  }

  .anim-cw-main.is-video > .anim-vd-wrap {
    flex: 1;
    height: auto;
  }
}

.anim-vd-workspace {
  min-width: 0;
  min-height: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) var(--anim-vd-strip-h);
  gap: 14px;
}

.anim-vd-stage {
  position: relative;
  justify-self: center;
  width: auto;
  max-width: 100%;
  height: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  box-shadow: var(--rk-shadow-object);
  display: grid;
  place-items: center;
}

.anim-vd-stage img,
.anim-vd-stage video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: #000;
}

.anim-vd-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: #000;
  color: #fff;
  cursor: pointer;
}

.anim-vd-poster.is-static {
  cursor: default;
}

.anim-vd-poster:disabled {
  cursor: default;
}

.anim-vd-play {
  position: absolute;
  inset: 50% auto auto 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  padding-inline-start: 4px;
  border-radius: 50%;
  background: rgba(18, 25, 23, 0.72);
  box-shadow: 0 8px 28px rgba(18, 25, 23, 0.28);
  font-size: 22px;
  transition: transform 160ms ease, background 160ms ease;
}

.anim-vd-poster:hover:not(:disabled) .anim-vd-play,
.anim-vd-poster:focus-visible .anim-vd-play {
  transform: scale(1.08);
  background: var(--rk-emerald);
}

.anim-vd-poster:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: -3px;
}

/* 出片要一到三分钟。以前这里是一层 55% 的白纱 + 一行细字「拍摄中…」，压在一张同样浅色的分镜图上
   —— 字几乎看不见，也没有任何东西在动，用户分不出「在拍」和「卡住了」。
   改成居中的一块实心卡片：转圈 + 状态词 + 真实已跑时长（不编百分比）。 */
.anim-vd-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(250, 248, 244, 0.72);
  backdrop-filter: blur(2px);
}

.anim-vd-overlay-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  border-radius: 999px;
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  box-shadow: 0 8px 24px rgba(43, 42, 38, 0.12);
  font-size: 15px;
  font-weight: 800;
  color: var(--rk-ink);
}

.anim-vd-overlay-card em {
  font-style: normal;
  font-size: 13px;
  font-weight: 600;
  color: var(--rk-ink-muted);
  font-variant-numeric: tabular-nums; /* 秒数/百分比跳动时不抖宽 */
}

/* 有真实百分比时换成一条进度条（网关给的数，不是自己爬的假条）。 */
.anim-vd-overlay-card.has-bar { padding-inline: 20px; }

.anim-vd-bar {
  display: block;
  width: 140px;
  height: 6px;
  border-radius: 999px;
  background: var(--rk-line);
  overflow: hidden;
}

.anim-vd-bar i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
  transition: width 400ms ease-out;
}

/* Spans the full stage width purely to centre its pill, so everything left and right of that pill is
   transparent — but transparent still eats clicks. It lands on top of the browser's own control bar
   (measured: genbar 400-445, native bar ~414-462), which swallowed play / volume / fullscreen / menu.
   Nobody hit it mid-playback because Chrome auto-hides the bar; the moment a clip ENDS the bar stays
   up and the whole row goes dead. The strip itself must therefore be click-through — only its real
   children take the pointer. */
.anim-vd-genbar {
  position: absolute;
  inset-block-end: 16px;
  inset-inline: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 3;
  pointer-events: none;
}

.anim-vd-genbar > * {
  pointer-events: auto;
}

.anim-vd-fail {
  font-size: 12.5px;
  font-weight: 700;
  color: #a65a4a;
  background: rgba(250, 248, 244, 0.92);
  border-radius: 999px;
  padding: 4px 14px;
}

.anim-vd-pane {
  min-height: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  padding: 18px;
  box-shadow: var(--rk-shadow-card);
  overflow: hidden;
}

.anim-vd-pane-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.anim-vd-pane-head > div {
  min-width: 0;
}

.anim-vd-pane h4 {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  font-size: 14px;
  font-weight: 800;
  margin: 4px 0 0;
  line-height: 1.45;
}

.anim-vd-status {
  flex: 0 0 auto;
  border-radius: 999px;
  padding: 5px 9px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 10.5px;
  font-weight: 800;
  white-space: nowrap;
}

.anim-vd-prompt {
  min-height: 0;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  margin-block-start: 16px;
  padding-block-start: 14px;
  border-block-start: 1px solid var(--rk-line);
}

.anim-vd-prompt-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.anim-vd-prompt-head > div > span {
  display: block;
  margin-block-start: 3px;
  color: var(--rk-emerald-hover);
  font-size: 10px;
  font-weight: 800;
}

.anim-vd-prompt-edit {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  cursor: pointer;
}

.anim-vd-prompt-edit svg {
  width: 18px;
  height: 18px;
  stroke-width: 1.7;
}

.anim-vd-prompt-edit:hover:not(:disabled),
.anim-vd-prompt-edit:focus-visible {
  outline: none;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-vd-prompt-edit:disabled {
  opacity: 0.45;
  cursor: default;
}

.anim-vd-prompt-preview {
  min-height: 0;
  flex: 1 1 auto;
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 9;
  margin: 10px 0 0;
  padding: 11px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  background: var(--rk-paper);
  color: var(--rk-ink-soft);
  font-size: 11.5px;
  line-height: 1.6;
  white-space: pre-wrap;
}

.anim-vd-prompt-preview.is-loading {
  color: var(--rk-ink-muted);
}

.anim-vd-prompt-retry {
  margin-block-start: 7px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  padding: 5px 11px;
  font: inherit;
  font-size: 11px;
  font-weight: 800;
  cursor: pointer;
}
.anim-vd-prompt-retry:hover,
.anim-vd-prompt-retry:focus-visible {
  border-color: var(--rk-emerald);
  outline: none;
}
.anim-vd-prompt small {
  display: block;
  margin-block-start: 8px;
  color: var(--rk-ink-muted);
  font-size: 10.5px;
  line-height: 1.4;
}

.anim-vd-pane-actions {
  margin-block-start: 14px;
}

.anim-vd-pane-actions .anim-as-genall {
  width: 100%;
  margin: 0;
}

@media (max-width: 960px) {
  .anim-sh-workspace { grid-template-columns: 1fr; }
  .anim-dd-dock { height: auto; min-height: 280px; }
  .anim-as-canvas.is-shots { height: 520px; }
}

.anim-vd-foot {
  min-width: 0;
  height: var(--anim-vd-strip-h);
}

.anim-vd-foot .anim-strip {
  width: 100%;
  height: 100%;
  gap: 12px;
  padding: 2px 2px 8px;
  overflow-y: hidden;
}

.anim-vd-foot .anim-strip-cell {
  flex-basis: 168px;
  min-height: 126px;
}

.anim-vd-foot .anim-strip-thumb {
  height: 92px;
}

.anim-vd-foot .anim-strip-meta {
  min-height: 20px;
  align-items: center;
  line-height: 1.35;
  white-space: nowrap;
}

.anim-vd-prompt-form header {
  padding-inline-end: 44px;
}

.anim-vd-prompt-form h2 {
  margin: 4px 0 6px;
  color: var(--rk-ink);
  font-size: 22px;
  line-height: 1.25;
}

.anim-vd-prompt-form header > p:last-child {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 13px;
  line-height: 1.55;
}

/* 「改词」弹窗两栏(2026-08-06):左 = 只读上下文(分镜图 + 台词)+ 视频参数,右 = 运镜正文。
   此前只有一个文本框,台词与清晰度/秒数都无处安放 —— 用户看不到这镜要说什么,也改不了档位。 */
.anim-vd-prompt-grid {
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  gap: 20px;
  margin-block-start: 18px;
  align-items: start;
}

.anim-vd-prompt-side {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

.anim-vd-side-block > .anim-card-kicker {
  margin: 0 0 8px;
}

.anim-vd-side-shot {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
}

.anim-vd-side-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.anim-vd-voice-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-block-size: 168px;
  overflow-y: auto;
  margin: 0;
  padding: 11px 12px;
  list-style: none;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
}

.anim-vd-voice-list li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.anim-vd-voice-who {
  flex: 0 0 auto;
  border-radius: 999px;
  padding: 2px 8px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 10px;
  font-weight: 800;
  line-height: 1.6;
}

.anim-vd-voice-text {
  min-width: 0;
  color: var(--rk-ink-soft);
  font-size: 12px;
  line-height: 1.6;
}

.anim-vd-voice-note {
  margin: 7px 0 0;
  color: var(--rk-ink-muted);
  font-size: 11px;
  line-height: 1.55;
}

.anim-vd-param-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.anim-vd-param-row label {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.anim-vd-param-row label > span {
  color: var(--rk-ink-muted);
  font-size: 10.5px;
  font-weight: 700;
}

.anim-vd-param-row select {
  width: 100%;
  block-size: 38px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  padding-inline: 10px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: 13px/1.4 var(--rk-font-body);
  cursor: pointer;
}

.anim-vd-param-row select:focus-visible {
  outline: none;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-vd-param-row select:disabled {
  opacity: 0.55;
  cursor: default;
}

.anim-vd-apply-all {
  margin-block-start: 10px;
  inline-size: 100%;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 8px 12px;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}

.anim-vd-apply-all:hover:not(:disabled),
.anim-vd-apply-all:focus-visible {
  outline: none;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-vd-apply-all:disabled {
  opacity: 0.55;
  cursor: default;
}

.anim-vd-param-note {
  margin: 8px 0 0;
  color: var(--rk-ink-muted);
  font-size: 11px;
  line-height: 1.55;
}

.anim-vd-param-note.is-error {
  color: var(--rk-danger);
}

.anim-vd-prompt-main {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.anim-vd-prompt-main textarea {
  margin-block-start: 0;
}

.anim-vd-prompt-form textarea {
  width: 100%;
  min-height: min(46vh, 420px);
  margin-block-start: 18px;
  resize: vertical;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  padding: 14px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: 14px/1.65 var(--rk-font-body);
}

.anim-vd-prompt-form textarea:focus-visible {
  outline: none;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-vd-prompt-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-block-start: 16px;
}

@media (max-width: 900px) {
  .anim-vd-wrap {
    height: auto;
    grid-template-columns: 1fr;
  }
  /* 弹窗两栏在窄屏折成一栏:上下文在上、正文在下(正文最重要但需要先看到台词)。 */
  .anim-vd-prompt-grid { grid-template-columns: 1fr; }
  .anim-vd-pane {
    height: auto;
    min-height: 480px;
  }
  .anim-vd-workspace { grid-template-rows: auto auto; }
  .anim-vd-stage {
    width: 100%;
    height: auto;
  }
  .anim-vd-foot { height: auto; }
  .anim-vd-prompt-preview { min-height: 170px; }
}

@media (prefers-reduced-motion: reduce) {
  .anim-context-chip,
  .anim-as-node.is-selected::before,
  .anim-as-node.is-fresh::after,
  .anim-as-edge.is-active circle,
  .anim-sh-ref.is-active circle {
    animation: none;
  }

  .anim-as-node,
  .anim-sh-chip {
    transition: none;
  }
}

/* ═══ Animation series continuity (A0-A3): authenticated hub + sequel creation ═══ */
.anim-series-open {
  min-width: 40px;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding-inline: 13px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font: inherit;
  font-size: 12.5px;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
}

.anim-series-open:hover,
.anim-series-open:focus-visible {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
}

.anim-series-open:focus-visible,
.anim-series-close:focus-visible,
.anim-series-episode:focus-visible,
.anim-series-field input:focus-visible,
.anim-series-field textarea:focus-visible,
.anim-series-field select:focus-visible,
.anim-series-mode:has(input:focus-visible) {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-series-overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  padding: 24px;
  background: color-mix(in srgb, var(--rk-ink) 28%, transparent);
}

.anim-series-dialog {
  position: relative;
  width: min(620px, 100%);
  max-height: min(760px, calc(100vh - 48px));
  overflow-y: auto;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-paper);
  color: var(--rk-ink);
  box-shadow: var(--rk-shadow-panel);
  padding: 28px;
}

.anim-series-close {
  position: absolute;
  inset-block-start: 18px;
  inset-inline-end: 18px;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  cursor: pointer;
}

.anim-series-close:disabled {
  cursor: wait;
  opacity: 0.55;
}

.anim-series-summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
  padding-inline-end: 48px;
  margin-block-end: 18px;
}

.anim-series-summary p,
.anim-series-kicker {
  margin: 0 0 4px;
  color: var(--rk-emerald-hover);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.anim-series-summary h2,
.anim-series-action h2 {
  margin: 0;
  font-size: clamp(22px, 3vw, 30px);
  line-height: 1.2;
}

.anim-series-summary > span {
  flex: 0 0 auto;
  margin-block-start: 6px;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-size: 12px;
  font-weight: 800;
}

.anim-series-episodes {
  display: grid;
  gap: 8px;
  margin-block-end: 16px;
}

.anim-series-episode {
  position: relative;
  min-height: 64px;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 6px 12px;
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  text-align: start;
}

.anim-series-episode:not(:disabled) {
  cursor: pointer;
}

.anim-series-episode:not(:disabled):hover {
  border-color: var(--rk-emerald);
}

.anim-series-episode:disabled {
  opacity: 1;
}

.anim-series-episode.is-current {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
}

.anim-series-episode-no {
  grid-row: 1 / span 2;
  color: var(--rk-emerald-hover);
  font-size: 12px;
  font-weight: 900;
}

.anim-series-episode-title {
  min-width: 0;
  overflow: hidden;
  color: var(--rk-ink);
  font-size: 14px;
  font-weight: 800;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-series-episode-meta {
  grid-column: 2;
  color: var(--rk-ink-soft);
  font-size: 12px;
}

.anim-series-episode i {
  grid-column: 3;
  grid-row: 1 / span 2;
  color: var(--rk-emerald-hover);
  font-size: 11px;
  font-style: normal;
  font-weight: 800;
}

.anim-series-action {
  margin: 16px 0 0;
  padding: 18px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
}

.anim-series-action.is-bootstrap {
  margin: 0;
  padding: 4px 0 0;
  border: 0;
  background: transparent;
}

.anim-series-action h2,
.anim-series-action h3 {
  padding-inline-end: 42px;
}

.anim-series-action h3 {
  margin: 0;
  font-size: 18px;
}

.anim-series-action > p {
  margin: 7px 0 15px;
  color: var(--rk-ink-soft);
  font-size: 14px;
  line-height: 1.55;
}

.anim-series-field {
  display: grid;
  gap: 7px;
  margin-block: 14px;
}

.anim-series-field > span,
.anim-series-modes legend {
  color: var(--rk-ink-soft);
  font-size: 12px;
  font-weight: 800;
}

.anim-series-field input,
.anim-series-field textarea,
.anim-series-field select {
  width: 100%;
  min-height: 44px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-ink);
  font: inherit;
  font-size: 15px;
  padding: 10px 12px;
}

.anim-series-field textarea {
  min-height: 96px;
  resize: vertical;
  line-height: 1.5;
}

.anim-series-field.is-compact {
  grid-template-columns: minmax(110px, auto) minmax(0, 1fr);
  align-items: center;
}

.anim-series-modes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 16px 0;
  padding: 0;
  border: 0;
}

.anim-series-modes legend {
  grid-column: 1 / -1;
  margin-block-end: 2px;
}

.anim-series-mode {
  position: relative;
  min-height: 92px;
  display: block;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  cursor: pointer;
}

.anim-series-mode:has(input:checked) {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
}

.anim-series-mode input {
  position: absolute;
  inset-block-start: 13px;
  inset-inline-end: 13px;
  width: 17px;
  height: 17px;
  accent-color: var(--rk-emerald);
}

.anim-series-mode > span {
  display: grid;
  gap: 5px;
  padding-block: 14px;
  padding-inline-start: 14px;
  padding-inline-end: 38px;
}

.anim-series-mode strong {
  font-size: 14px;
}

.anim-series-mode small {
  color: var(--rk-ink-soft);
  font-size: 12px;
  line-height: 1.45;
}

.anim-series-error,
.anim-series-locknote,
.anim-series-script-lock,
.anim-series-card-lock {
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 13px;
  line-height: 1.5;
  padding: 10px 12px;
}

.anim-series-error {
  margin-block: 0 14px;
  margin-inline-start: 0;
  margin-inline-end: 48px;
  border-color: var(--rk-danger);
  color: var(--rk-danger);
}

.anim-series-locknote {
  margin: 0;
}

.anim-series-script-lock {
  margin: 0;
}

.anim-series-card-lock {
  margin: 0 0 9px;
  text-align: start;
}

.anim-series-loading {
  min-height: 220px;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 12px;
  color: var(--rk-ink-soft);
  text-align: center;
}

.anim-series-loading > span {
  width: 32px;
  height: 32px;
  border: 3px solid var(--rk-line);
  border-block-start-color: var(--rk-emerald);
  border-radius: 50%;
  animation: anim-series-spin 0.8s linear infinite;
}

@keyframes anim-series-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .anim-series-loading > span { animation: none; }
}

@media (max-width: 860px) {
  .anim-cw-top { gap: 10px; padding-inline: 14px; }
  .anim-series-open span { display: none; }
  .anim-series-open { padding-inline: 10px; }
}

@media (max-width: 620px) {
  .anim-series-overlay {
    align-items: end;
    padding: 0;
  }
  .anim-series-dialog {
    width: 100%;
    max-height: 90vh;
    border-radius: var(--rk-radius-lg) var(--rk-radius-lg) 0 0;
    padding: 22px 16px calc(22px + env(safe-area-inset-bottom));
  }
  .anim-series-modes { grid-template-columns: 1fr; }
  .anim-series-summary { display: block; padding-inline-end: 48px; }
  .anim-series-summary > span { display: inline-flex; margin-block-start: 8px; }
  .anim-series-episode { grid-template-columns: auto minmax(0, 1fr); }
  .anim-series-episode i { display: none; }
  .anim-series-field.is-compact { grid-template-columns: 1fr; }
}

/* Comic intake confirmation card (home composer, PRD prd-v3-comic-creation §7) */
.comic-intake-card { max-width: 440px; }
.comic-intake-card h3 { margin: 0 0 10px; font-family: var(--rk-font-display); }
.comic-intake-card p { color: var(--rk-ink-soft); margin: 0 0 16px; line-height: 1.6; }
.comic-intake-actions { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
.comic-intake-note { margin: 12px 0 0; padding: 8px 10px; font-size: 13px; line-height: 1.5; color: var(--rk-ink-soft); background: var(--rk-paper-deep, rgba(43, 42, 38, 0.05)); border-left: 2px solid var(--rk-green); }

/* ── Desktop install — appears only while Chrome exposes a live install prompt. The empty slot is
   removed from flex layout so an ineligible or already-installed app leaves no phantom topbar gap. */
.rk-pwa-install-slot:empty { display: none; }

/* Generalises the rule above to every slot in the header's action row. A zero-width flex child still
   collects the row gap on BOTH sides, so the empty Trial badge was silently doubling the space
   between the language pill and the balance chip — 28px against the row's own 14px, which is what
   made the chip row read as unevenly spaced. */
.rk-top-actions > :empty { display: none; }

/* The action row is one 48px rhythm. `.avatar` is a generic class (surveys, comments, menus) sized
   52 for those contexts, so it is corrected HERE rather than at the source — the other users of the
   class must keep their own size. */
.rk-user-toggle .avatar { width: 48px; height: 48px; }
.rk-pwa-install-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  min-height: 48px;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
  color: var(--rk-ink);
  cursor: pointer;
  transition: border-color 160ms ease-out, color 160ms ease-out, box-shadow 160ms ease-out;
}
.rk-pwa-install-btn:hover:not(:disabled) {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
}
.rk-pwa-install-btn:focus-visible {
  outline: none;
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}
.rk-pwa-install-btn:disabled {
  color: var(--rk-ink-muted);
  cursor: wait;
}
.rk-pwa-install-btn svg {
  width: 22px;
  height: 22px;
  stroke-width: 1.55;
  transition: opacity 160ms ease-out;
}
.rk-pwa-install-btn.is-pending svg { opacity: 0.48; }

/* ── 消息铃铛 — prominent entry to the existing message centre (worklist #324, lib/notifications.js).
   Same 48px pill chrome as its topbar neighbours; the unread count rides as a small emerald badge,
   which is the whole point of promoting it out of the avatar dropdown. */
.rk-bell-slot:empty { display: none; }
.rk-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  min-height: 48px;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
  color: var(--rk-ink);
  cursor: pointer;
  transition: border-color 160ms ease-out, color 160ms ease-out, box-shadow 160ms ease-out;
}
.rk-bell:hover {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
}
.rk-bell:focus-visible {
  outline: none;
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}
.rk-bell svg {
  width: 22px;
  height: 22px;
  stroke-width: 1.55;
}
.rk-bell-count {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-end: 2px;
  min-inline-size: 18px;
  padding-inline: 5px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 800;
  line-height: 18px;
  text-align: center;
}

@media (max-width: 1020px) {
  .rk-bell { width: 42px; min-height: 42px; }
  .rk-bell svg { width: 20px; height: 20px; }
}

/* ── 为你推荐 For You — topbar drawer + floating panel (运营 ②, lib/foryou.js) ── */
.rk-foryou { position: relative; }
.rk-foryou-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  min-height: 48px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.62);
  color: var(--rk-ink, #2B2A26);
  cursor: pointer;
}
.rk-foryou-btn:hover { border-color: var(--rk-accent, #0FA47E); color: var(--rk-accent, #0FA47E); }
.rk-foryou-btn svg { width: 22px; height: 22px; stroke-width: 1.55; }
.rk-foryou-dot {
  position: absolute;
  top: 9px;
  right: 10px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #D9534F;
  border: 1.5px solid var(--rk-paper, #FAF8F4);
}
.rk-foryou-panel {
  position: absolute;
  inset-inline-end: 0;
  inset-block-start: calc(100% + 10px);
  z-index: 40;
  inline-size: 380px;
  max-inline-size: 92vw;
  max-block-size: min(72vh, 560px);
  overflow-y: auto;
  background: var(--rk-paper, #FAF8F4);
  border: 1px solid var(--rk-line, rgba(43, 42, 38, 0.12));
  border-radius: 16px;
  padding: 14px;
  box-shadow: 0 12px 32px rgba(43, 42, 38, 0.14);
}
.foryou-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 2px 4px 10px;
}
.foryou-kicker {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--rk-accent, #0FA47E);
}
.foryou-regen {
  background: none;
  border: 1px solid var(--rk-line, rgba(43, 42, 38, 0.12));
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 12px;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.62));
  cursor: pointer;
}
.foryou-regen:hover { border-color: var(--rk-accent, #0FA47E); color: var(--rk-accent, #0FA47E); }
.foryou-item {
  border: 1px solid var(--rk-line, rgba(43, 42, 38, 0.10));
  border-radius: 12px;
  padding: 12px 14px;
  margin-bottom: 10px;
  background: rgba(255, 255, 255, 0.55);
}
.foryou-item:last-child { margin-bottom: 2px; }
.foryou-item-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.foryou-mode {
  font-size: 12px;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.62));
  border: 1px solid var(--rk-line, rgba(43, 42, 38, 0.12));
  border-radius: 999px;
  padding: 2px 10px;
}
.foryou-item-x {
  background: none;
  border: none;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.45));
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
}
.foryou-item-x:hover { color: var(--rk-ink, #2B2A26); }
/* Both clamp to 2 lines — the card is a glanceable teaser, not a wall of text. The reason is the
   personalized hook; the idea is a short preview of the premise (the FULL premise still flows into
   the composer on "开始创作"). Without clamping, an LLM idea can run 6+ lines and kills the card. */
.foryou-reason { margin: 0 0 4px; color: var(--rk-ink, #2B2A26); line-height: 1.45; font-weight: 600; font-size: 13px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.foryou-idea { margin: 0 0 11px; color: var(--rk-ink-soft, rgba(43, 42, 38, 0.72)); line-height: 1.45; font-size: 12.5px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.foryou-item-start { font-size: 13px; padding-block: 8px; }

/* ── two card variants: rich continuation (image+text) vs clean exploration badge ── */
/* Rich card: source work rendered as a small book object + cast portraits + synopsis. Solid white
   surface so it reads as the hero row; the badge card keeps the quieter translucent fill. */
.foryou-item-rich { background: var(--rk-surface, #fff); }

/* format badge (exploration / fallback): quiet pill + a 7px per-format metadata dot (the only place
   per-line color is allowed by the skin — never a fill). */
.foryou-badge { display: inline-flex; align-items: center; gap: 7px; padding: 3px 11px 3px 9px; border: 1px solid var(--rk-line, rgba(43, 42, 38, 0.12)); border-radius: 999px; font-size: 12px; font-weight: 700; color: var(--rk-ink, #2B2A26); background: rgba(255, 255, 255, 0.5); }
.foryou-badge-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--rk-ink-muted, #9B958A); flex: 0 0 auto; }
.foryou-badge-dot[data-mode="picture-book"] { background: #C08A3E; }
.foryou-badge-dot[data-mode="comic"] { background: #B5654A; }
.foryou-badge-dot[data-mode="animation"] { background: #5B84B1; }
.foryou-badge-dot[data-mode="kids-song"] { background: #A6788E; }
.foryou-badge-dot[data-mode="freestyle"] { background: #6E8B6A; }

/* "continue your story" kicker — emerald, sits on the card's top row with the dismiss × */
.foryou-cont-kicker { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--rk-accent, #0FA47E); }
.foryou-cont-kicker::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

/* the visual header: book object (left) + title / synopsis / cast (right) */
.foryou-cont-head { display: flex; gap: 12px; align-items: flex-start; }
.foryou-cont-meta { min-width: 0; flex: 1; }
.foryou-cont-title { margin: 0 0 4px; font-size: 14px; font-weight: 800; color: var(--rk-ink, #2B2A26); line-height: 1.25; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.foryou-cont-syn { margin: 0 0 8px; font-size: 12px; color: var(--rk-ink-soft, rgba(43, 42, 38, 0.68)); line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* Imageless continuation (kids-song / freestyle, or any line whose cover would not resolve): the
   kicker alone would promise to continue something without ever naming it, so the source title
   stands on its own line. No book object — the shared divider below it does the separating. */
.foryou-cont-title-lean { margin: 7px 0 0; }

/* source work as a physical book object (v3 signature; simplified from the shelf recipe) */
.foryou-book { flex: 0 0 auto; width: 54px; height: 72px; perspective: 460px; }
.foryou-book-inner { position: relative; width: 100%; height: 100%; border-radius: 2px 4px 4px 2px; transform: rotateY(19deg); transform-origin: 0% 50%; overflow: hidden; background: var(--rk-paper-2, #F3EFE7); box-shadow: 0 9px 16px -9px rgba(43, 42, 38, 0.5); }
.foryou-book-inner img { width: 100%; height: 100%; object-fit: cover; display: block; }
.foryou-book-inner::before { content: ""; position: absolute; left: 4px; top: 0; bottom: 0; width: 2px; background: rgba(0, 0, 0, 0.16); z-index: 2; }
.foryou-book-inner::after { content: ""; position: absolute; inset: 0; background: linear-gradient(105deg, rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0) 34%, rgba(0, 0, 0, 0.12)); pointer-events: none; }

/* cast: up to 2 character portrait thumbnails + their names */
.foryou-cast { display: flex; align-items: center; gap: 6px; min-width: 0; }
.foryou-cast-face { width: 30px; height: 30px; border-radius: 8px; overflow: hidden; flex: 0 0 auto; border: 1.5px solid var(--rk-surface, #fff); box-shadow: 0 0 0 1px var(--rk-line, rgba(43, 42, 38, 0.12)); background: var(--rk-paper-2, #F3EFE7); }
.foryou-cast-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.foryou-cast-more { font-size: 11px; color: var(--rk-ink-muted, #9B958A); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.foryou-card-divider { height: 1px; background: var(--rk-line, rgba(43, 42, 38, 0.10)); margin: 11px 0 10px; }

/* ── peek: auto slide-out single card (R5, once per new set, home page only) ── */
.rk-foryou-peek {
  inline-size: 340px;
  animation: rk-foryou-peek-in 180ms ease-out;
}
@keyframes rk-foryou-peek-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
.foryou-peek-actions { display: flex; align-items: center; gap: 10px; }
.foryou-peek-next {
  background: none;
  border: 1px solid var(--rk-line, rgba(43, 42, 38, 0.12));
  border-radius: 999px;
  padding: 7px 14px;
  font-size: 13px;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.72));
  cursor: pointer;
}
.foryou-peek-next:hover { border-color: var(--rk-accent, #0FA47E); color: var(--rk-accent, #0FA47E); }

/* "不再弹窗提醒" opt-out — quiet row under the actions, never competing with the CTA. */
.foryou-peek-mute {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-block-start: 12px;
  padding-block-start: 11px;
  border-block-start: 1px solid var(--rk-line, rgba(43, 42, 38, 0.10));
  cursor: pointer;
  user-select: none;
}
.foryou-peek-mute-label {
  font-size: 12px;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.72));
}
.foryou-peek-mute:hover .foryou-peek-mute-label { color: var(--rk-ink, #2B2A26); }
.foryou-loading, .foryou-empty {
  margin: 8px 4px;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.62));
  font-size: 13px;
}
@media (max-width: 640px) {
  .rk-foryou-panel { inline-size: min(92vw, 340px); }
}

/* A single standalone book shows ZERO series traces (tree standard P4): the rail collapses to one
   book card — no tree, no progress spine, no "Book 1" label — and the stage drops its breadcrumb.
   The series machinery still exists underneath; it is simply never spoken to a one-book author. */
.cs-page.is-single .cs-breadcrumb,
.cs-page.is-single .cs-crumb {
  display: none;
}

/* Memory card (tree standard T7): one-tap ceremony — the itemized list folds away. */
.cs-memory-card .cs-memory-details {
  margin-block: 10px 4px;
}
.cs-memory-card .cs-memory-details summary {
  cursor: pointer;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.62));
  font-size: 13px;
}
.cs-memory-card .cs-memory-details[open] summary {
  margin-block-end: 8px;
}

/* Generate-video popover action (2026-07-21 入口重排): locked = grey + ⓘ tooltip until the book is finished. */
.book-continuation-action.is-locked {
  opacity: 0.45;
  cursor: not-allowed;
}
.book-continuation-action.is-locked:hover {
  background: inherit;
}

/* Notebook chrome: keep the account controls visually lighter beside a long greeting while
   preserving a >=42px pointer target. This lives after the individual component rules so the
   responsive dimensions win the cascade. Wide desktop and mobile retain their dedicated sizing. */
@media (min-width: 1021px) and (max-width: 1680px) {
  .rk-top-actions {
    gap: 10px;
  }

  .rk-lang-toggle,
  .balance-chip,
  .rk-trial-badge {
    min-height: 42px;
    padding-inline: 12px;
    font-size: 0.9rem;
  }

  .balance-chip {
    gap: 8px;
  }

  .rk-lang-toggle svg,
  .balance-chip svg {
    width: 19px;
    height: 19px;
  }

  .rk-foryou-btn,
  .rk-pwa-install-btn {
    width: 42px;
    min-height: 42px;
  }

  .rk-foryou-btn svg,
  .rk-pwa-install-btn svg {
    width: 20px;
    height: 20px;
  }

  .avatar {
    width: 44px;
    height: 44px;
  }

  .avatar.is-mono {
    font-size: 19px;
  }
}

/* Subscription overlay · short-laptop adaptation.
   Short browser workspaces such as the screenshot's 1366×683 CSS viewport need the plan controls
   above the fold, while taller displays keep the roomier default. Reclaim vertical space from
   chrome and spacing, not from readable body copy or primary hit targets. */
@media (min-width: 901px) and (max-height: 760px) {
  .rk-modal:has(.rk-sub-tabs) {
    padding: 12px;
  }

  .rk-modal-panel.is-wide:has(.rk-sub-tabs) {
    inline-size: min(1120px, 100%);
    block-size: calc(100dvh - 24px);
    max-block-size: calc(100dvh - 24px);
    padding: 18px 20px;
  }

  .rk-sub-heading {
    gap: 4px 12px;
    margin-block: 2px 12px;
  }

  .rk-sub-title {
    font-size: 1.55rem;
  }

  .rk-strip {
    gap: 12px;
    margin-block-end: 12px;
    padding: 10px 14px;
  }

  .rk-strip-avatar {
    inline-size: 44px;
    block-size: 44px;
  }

  .rk-strip-cells {
    gap: 18px;
  }

  .rk-sub-tabs {
    margin-block-end: 12px;
  }

  .rk-sub-banner {
    margin-block-end: 10px;
    padding: 8px 12px;
  }

  .rk-plan-group {
    margin-block-end: 10px;
  }

  .rk-plans {
    gap: 12px;
  }

  .rk-plan {
    gap: 8px;
    padding: 16px;
  }

  .rk-plan-name {
    font-size: 1.15rem;
  }

  .rk-plan-price {
    font-size: 1.65rem;
  }

  .rk-plan-cta {
    height: 42px;
  }
}

/* ═══ Animation pipeline · large-display adaptation (2026-07-20) ═══
   The four workspace steps were tuned on ~1440px laptops; on 2K+ displays the capped
   wrappers left the hero content marooned in dead space. Two moves, per quiet-paper
   (chrome stays quiet, the WORK gets the room): ① viewport-height caps so each hero
   surface (concept board / video stage) always fits one screen at any size, ② a
   ≥1600px tier that widens the workspaces and lets the artwork spend the extra room. */

/* Concept board: 3:2 board never taller than the viewport budget (topbar + preview
   caption + proceed panel). Height-driven so the板图 stays whole on every display. */
.anim-board-img {
  width: auto;
  max-width: 100%;
  max-height: calc(100dvh - 300px);
  margin-inline: auto;
}

@media (min-width: 1600px) {
  /* (the page-width bump that used to live here is gone — every step is full-bleed now) */
  .anim-style-stage img,
  .anim-style-stage .anim-style-blank { max-height: min(66vh, 760px); }
  /* [REMOVED 2026-08-05] ~~.anim-style-thumb { flex-basis: 128px; width: 128px; height: 128px; }~~
     宽屏上把风格卡钉成 128 见方的方块。卡片本身是「3:4 图 + 一行风格名」，而按钮是 overflow:hidden
     —— 128px 的高度把整条名字连同引擎徽标一起裁掉了，2560px 屏上只剩一排没有任何说明的小图
     （Andy 2026-08-05 并排截图：MV 那页是大卡片带名字与徽标，动画这页什么都没有）。
     markup 一直是对的，两页本就是同一套形态，压扁它的只有这一条。
     flex-basis 在 .anim-style-grid（7 列 grid）里本来也不起作用 —— 这是更早那版 flex 布局的遗留，
     上面那行注释里「页面宽度那段已经去掉了」说的就是同一次改版，这条当时漏删了。 */

  .anim-board-grid { grid-template-columns: 300px minmax(0, 1fr); }
  /* (the video pane used to widen to 440px here; it now shares --anim-desk-rail with the other
     desks, and the width it gives back goes to the player) */
}

/* ── 导演台资产确认卡（protocol-chat-desk §5）─────────────────────────────
   chat 判不准要换哪个资产时出现：歧义列候选、缺资产给新建入口。用户动作之前不扣费。 */






.anim-dd-clarify {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
  padding: 10px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 42%, var(--rk-line));
  border-radius: 12px;
  background: color-mix(in srgb, var(--rk-emerald) 6%, var(--rk-surface));
}

.anim-dd-clarify-lead {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--rk-ink-1);
}

.anim-dd-clarify-options {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.anim-dd-clarify-opt {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 5px 10px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  color: var(--rk-ink-1);
}

.anim-dd-clarify-opt:hover:not(:disabled) {
  border-color: var(--rk-emerald);
  background: color-mix(in srgb, var(--rk-emerald) 10%, var(--rk-surface));
}

.anim-dd-clarify-opt:disabled,
.anim-dd-clarify-create:disabled,
.anim-dd-clarify-cancel:disabled {
  opacity: 0.55;
  cursor: default;
}

.anim-dd-clarify-opt-meta {
  font-size: 11px;
  color: var(--rk-ink-3);
}

.anim-dd-clarify-create {
  align-self: flex-start;
  padding: 6px 12px;
  border: 0;
  border-radius: 999px;
  background: var(--rk-emerald);
  cursor: pointer;
  font: inherit;
  font-size: 12px;
  color: var(--rk-on-emerald, #fff);
}

.anim-dd-clarify-note {
  margin: 0;
  font-size: 11px;
  color: var(--rk-ink-3);
}

.anim-dd-clarify-cancel {
  align-self: flex-start;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  color: var(--rk-ink-3);
  text-decoration: underline;
}

/* ── 导演台改动史（折叠，默认收起）───────────────────────────────────────
   留的是「这一镜被改成什么样」，不是聊天记录 —— 与 Camika V3 的取舍一致。 */
.anim-dd-hist {
  flex: 0 0 auto;
  margin-top: 6px;
}

.anim-dd-hist-head {
  cursor: pointer;
  font-size: 11px;
  color: var(--rk-ink-3);
  list-style: none;
}

.anim-dd-hist-head::-webkit-details-marker { display: none; }

.anim-dd-hist-head::before {
  content: "▸ ";
}

.anim-dd-hist[open] .anim-dd-hist-head::before {
  content: "▾ ";
}

.anim-dd-hist-list {
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.anim-dd-hist-item {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--rk-ink-2);
}

.anim-dd-hist-item.is-failed {
  color: var(--rk-ink-3);
}

.anim-dd-hist-mode {
  flex: 0 0 auto;
  padding: 1px 6px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  font-size: 10px;
  color: var(--rk-ink-3);
}

.anim-dd-hist-said {
  flex: 1 1 auto;
  overflow-wrap: anywhere;
}

/* 作用域标：一眼看出改的是整镜还是某一格 */
.anim-dd-hist-scope {
  flex: 0 0 auto;
  padding: 1px 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-emerald) 14%, transparent);
  font-size: 10px;
  color: var(--rk-ink-2);
}

.anim-dd-hist-when {
  flex: 0 0 auto;
  font-size: 10px;
  color: var(--rk-ink-3);
  font-variant-numeric: tabular-nums;
}

.anim-dd-hist-fail {
  flex: 0 0 auto;
  font-size: 10px;
  color: var(--rk-ink-3);
}

/* 绑定标签与澄清候选的垫图缩略图 —— 名字说"是谁"，图才说清"用的哪张" */




.anim-dd-clarify-opt.has-thumb {
  flex-direction: column;
  align-items: center;
  gap: 4px;
  width: 88px;
  padding: 6px;
  border-radius: 10px;
  text-align: center;
}

.anim-dd-clarify-thumb {
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 8px;
  object-fit: cover;
  background: var(--rk-surface-2, var(--rk-surface));
}

.anim-dd-clarify-opt.has-thumb .anim-dd-clarify-opt-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

/* ── 导演台会话流（2026-07-27）──────────────────────────────────────────
   镜头卡、班底、改动史、气泡、澄清卡全部内嵌成一条可滚动的会话，只有输入框钉底。
   改前镜头卡钉顶占掉约一半高度，聊得越久下面越挤。 */
.anim-dd-stream {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 8px;
  min-height: 0;          /* flex 子项默认 min-height:auto 会撑破容器，滚动条就不出现 */
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-inline-end: 2px;
}

/* 流里的每一块都保持自然高度：flex 默认允许收缩，会宁可把镜头卡压扁成一条线也不滚动
   （2026-07-27 实测压到 2px）。滚动交给容器，内容一律不缩。 */
.anim-dd-stream > * {
  flex: 0 0 auto;
}

/* 会话流里日志不再是滚动容器（滚动归 .anim-dd-stream），必须显式压掉旧的 `.anim-dd-dock .anim-ad-log`
   那条 flex:1 —— 否则日志被压成固定高度又不许滚动，气泡就溢出来盖在下面的提议卡上（2026-07-27 实测）。*/
.anim-dd-stream > .anim-ad-log {
  flex: 0 0 auto;
  overflow: visible;
  min-height: 0;
}

.anim-dd-stream .anim-dd-card {
  max-height: none;
}

/* 输入框旁的作用域标：镜头卡滚走后，用户仍看得见「正在对第几格说话」，点它回到整镜 */
.anim-dd-scope {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 3px;
  padding: 2px 7px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 45%, var(--rk-line));
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-emerald) 10%, transparent);
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  color: var(--rk-ink-1);
}

.anim-dd-scope:hover {
  background: color-mix(in srgb, var(--rk-emerald) 18%, transparent);
}

/* 背景垫图标：场景图是横构图，方圆头像会裁掉大半，用小圆角矩形保留画面 */






/* ── 用料条（镜头卡底部）+ 用料气泡 ─────────────────────────────────────
   这一镜用了谁、哪张垫图、什么背景；每一项都可点，手动改绑定零扣费。 */
.anim-dd-tray {
  display: flex;
  flex: 0 0 auto;      /* 与输入框一起钉底，永不随会话滚走 */
  flex-direction: column;
  gap: 6px;
}

.anim-dd-uses {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border: 1px solid var(--rk-line);
  border-radius: 12px;
  background: var(--rk-surface);
}

.anim-dd-uses-cast {
  display: flex;
  flex: 0 1 auto;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.anim-dd-use {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  cursor: pointer;
  font: inherit;
  color: var(--rk-ink-2);
}

.anim-dd-use:hover:not(:disabled) {
  border-color: var(--rk-emerald);
  background: color-mix(in srgb, var(--rk-emerald) 10%, transparent);
}

.anim-dd-use-thumb {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--rk-surface-2, var(--rk-surface));
}

.anim-dd-use-thumb.is-blank {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--rk-line);
  font-size: 12px;
  color: var(--rk-ink-3);
}

.anim-dd-use.is-add {
  width: 26px;
  height: 26px;
  justify-content: center;
  border: 1px dashed var(--rk-line);
  font-size: 15px;
  line-height: 1;
  color: var(--rk-ink-3);
}

.anim-dd-use.is-scene {
  flex: 0 1 auto;
  gap: 6px;
  padding: 2px 8px 2px 2px;
  border-color: var(--rk-line);
  border-radius: 999px;
  min-width: 0;
  margin-inline-start: auto;
}

.anim-dd-use-thumb.is-scene {
  width: 34px;
  height: 22px;
  border-radius: 5px;
}

.anim-dd-use-scene-name {
  text-transform: lowercase;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 10px;
  color: var(--rk-ink-3);
}

.anim-dd-pop {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 46vh;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 40%, var(--rk-line));
  border-radius: 12px;
  background: color-mix(in srgb, var(--rk-emerald) 5%, var(--rk-surface));
}

.anim-dd-pop-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  color: var(--rk-ink-1);
}

.anim-dd-pop-x {
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  font-size: 14px;
  color: var(--rk-ink-3);
}

.anim-dd-pop-label {
  margin: 0;
  font-size: 11px;
  color: var(--rk-ink-3);
}

.anim-dd-pop-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* 候选一行一张、宽度铺满：拆解图是 2.3:1 的横长条，塞进 76px 方卡只剩指甲盖大
   （2026-07-27 实测 64×27）。让卡片迁就图，而不是图迁就卡片。 */
.anim-dd-pop-grid {
  flex-direction: column;
}

.anim-dd-pop-cell {
  width: 100%;
}

.anim-dd-pop-opt {
  position: relative;
  display: block;
  width: 100%;
  padding: 4px;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  background: var(--rk-surface);
  cursor: pointer;
  font: inherit;
  font-size: 10px;
  color: var(--rk-ink-2);
  text-align: start;
}

/* 候选卡里的图必须完整展示（Jeff 2026-07-27）：拆解图是多视图长条、背景是横构图，
   cover 会把两侧或上下裁掉，用户就看不清自己在选什么。contain + 浅底把整张放进去。 */
/* 高度由图片真实比例决定，不锁高 —— 既完整又尽可能大 */
.anim-dd-pop-opt img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 7px;
  background: var(--rk-surface-2, color-mix(in srgb, var(--rk-ink-3) 8%, transparent));
}

.anim-dd-pop-opt.is-on {
  border-color: var(--rk-emerald);
  box-shadow: inset 0 0 0 1px var(--rk-emerald);
}

.anim-dd-pop-opt.is-only,
.anim-dd-pop-opt:disabled {
  cursor: default;
  opacity: 0.75;
}

.anim-dd-pop-row {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.anim-dd-pop-mini {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 3px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  color: var(--rk-ink-2);
}

.anim-dd-pop-mini img {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  object-fit: cover;
}

.anim-dd-pop-mini:hover:not(:disabled) {
  border-color: var(--rk-emerald);
}

.anim-dd-pop-note {
  margin: 0;
  font-size: 10px;
  line-height: 1.5;
  color: var(--rk-ink-3);
}

.anim-dd-pop-note.is-warn {
  color: color-mix(in srgb, var(--rk-ink-2) 80%, var(--rk-emerald));
}

.anim-dd-pop-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding-top: 4px;
  border-top: 1px solid var(--rk-line);
}

.anim-dd-pop-remove,
.anim-dd-pop-tell {
  border: 0;
  background: none;
  cursor: pointer;
  font: inherit;
  font-size: 11px;
  color: var(--rk-ink-3);
  text-decoration: underline;
}

.anim-dd-pop-tell {
  color: var(--rk-emerald);
}

/* 候选卡的放大钮：叠在卡片右上角，独立于"选中"这个动作 */
.anim-dd-pop-cell {
  position: relative;
  display: inline-flex;
}

.anim-dd-pop-zoom {
  position: absolute;
  inset-block-start: 3px;
  inset-inline-end: 3px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 0;
  border-radius: 6px;
  background: color-mix(in srgb, var(--rk-ink-1) 55%, transparent);
  cursor: pointer;
  font-size: 10px;
  line-height: 1;
  color: var(--rk-surface);
}

.anim-dd-pop-zoom:hover {
  background: color-mix(in srgb, var(--rk-ink-1) 78%, transparent);
}

/* 候选卡：名字条、选中勾、放大钮做实（原来 18px 半透明角标等于不存在） */
.anim-dd-pop-opt-name {
  display: block;
  padding: 3px 2px 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-dd-pop-tick {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-start: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--rk-emerald);
  font-size: 11px;
  color: var(--rk-surface);
}

.anim-dd-pop-zoom {
  inset-block-start: 6px;
  inset-inline-end: 6px;
  width: 26px;
  height: 26px;
  border: 1px solid var(--rk-line);
  border-radius: 8px;
  background: color-mix(in srgb, var(--rk-surface) 88%, transparent);
  font-size: 13px;
  color: var(--rk-ink-1);
}

.anim-dd-pop-zoom:hover {
  background: var(--rk-surface);
  border-color: var(--rk-emerald);
}

/* 用料条：刚改动的那一项闪一下（不弹消息、不留痕） */
.anim-dd-use.is-flash {
  border-color: var(--rk-emerald);
  background: color-mix(in srgb, var(--rk-emerald) 16%, transparent);
}

/* 「旧图」贴在那张图右下角：说的是哪张图，一眼就知道。只是状态，不可点，不催用户去按什么。
   选择器要压过 `.anim-dd-frame > span`（0,1,1）那条格号标签规则，否则会被它钉到左上角 */
.anim-dd-frame > .anim-dd-old,
.anim-dd-drill-stage > .anim-dd-old {
  position: absolute;
  inset-block-start: auto;
  inset-inline-start: auto;
  inset-block-end: 3px;
  inset-inline-end: 4px;
  border-radius: 5px;
  padding: 1px 5px;
  background: rgba(23, 24, 21, 0.72);
  color: #ffd9a8;
  font: 700 9.5px/1.5 var(--rk-font-body);
  pointer-events: none;
}

.anim-dd-drill-stage .anim-dd-old {
  inset-block-end: 8px;
  inset-inline-end: 10px;
  font-size: 11px;
}

/* ── 作用域必须先选：没选之前把整排目标图推到台前，垫图与输入框都先不放行 ──────────
   （原来这里还有一行 .anim-dd-scope-ask 的解说文案，2026-07-28 下线 —— 图块本身就是选择器） */
.anim-dd-frames.is-asking {
  border-radius: 10px;
  padding: 6px;
  background: color-mix(in srgb, var(--rk-emerald) 7%, transparent);
}

/* 作用域标签钉在垫图左边：这排垫图属于整镜还是某一格，抬眼可见 */
.anim-dd-uses-scope {
  flex: 0 0 auto;
  align-self: center;
  border-radius: 999px;
  padding: 2px 8px;
  background: color-mix(in srgb, var(--rk-emerald) 14%, transparent);
  color: var(--rk-ink-2);
  font: 700 10px/1.5 var(--rk-font-body);
  white-space: nowrap;
  cursor: default;
}

.anim-dd-uses-scope.is-cell {
  background: color-mix(in srgb, var(--rk-amber, #e8a33d) 20%, transparent);
}

/* ── 待确认的改动：改了什么 + 画出来大概是什么 + 两个出口。刻意不写价钱 ──────────── */
.anim-dd-proposal {
  margin-block-start: 6px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 30%, transparent);
  border-radius: 12px;
  padding: 10px 12px;
  background: color-mix(in srgb, var(--rk-emerald) 6%, transparent);
}

.anim-dd-prop-head {
  margin: 0 0 6px;
  color: var(--rk-ink-1);
  font: 700 12px/1.5 var(--rk-font-body);
}

.anim-dd-prop-list {
  margin: 0;
  padding-inline-start: 16px;
  color: var(--rk-ink-2);
  font: 400 11.5px/1.7 var(--rk-font-body);
}

.anim-dd-prop-list li + li {
  margin-block-start: 2px;
}

.anim-dd-prop-exp {
  margin: 8px 0 0;
  color: var(--rk-ink-1);
  font: 400 11.5px/1.65 var(--rk-font-body);
}

.anim-dd-prop-exp b {
  font-weight: 700;
}

.anim-dd-prop-acts {
  display: flex;
  gap: 8px;
  margin-block-start: 10px;
}

.anim-dd-prop-go,
.anim-dd-prop-more {
  border-radius: 999px;
  padding: 5px 16px;
  font: 700 11.5px/1.4 var(--rk-font-body);
  cursor: pointer;
}

.anim-dd-prop-go {
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
}

.anim-dd-prop-more {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink-2);
}

.anim-dd-prop-go:disabled,
.anim-dd-prop-more:disabled {
  opacity: 0.5;
  cursor: default;
}

/* ── 手搓编辑器：居中模态（大图 + 垫图 + 整镜提示词），遮罩不可点关 ─────────────── */
.anim-ed-mask {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(23, 24, 21, 0.42);
}

.anim-ed {
  position: fixed;
  z-index: 61;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  translate: -50% -50%;
  display: flex;
  flex-direction: column;
  width: min(1040px, 92vw);
  max-block-size: 88vh;
  border-radius: 16px;
  background: var(--rk-surface);
  box-shadow: 0 24px 64px rgba(23, 24, 21, 0.24);
  overflow: hidden;
}

.anim-ed-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 0 0 auto;
  border-block-end: 1px solid var(--rk-line);
  padding: 12px 16px;
  color: var(--rk-ink-1);
  font: 700 13px/1.4 var(--rk-font-body);
}

.anim-ed-x {
  border: 0;
  background: none;
  color: var(--rk-ink-3);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.anim-ed-wait {
  margin: 0;
  padding: 40px;
  color: var(--rk-ink-muted);
  font-size: 12px;
  text-align: center;
}

.anim-ed-body {
  display: grid;
  flex: 1 1 auto;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-content: start;
  gap: 16px;
  min-height: 0;
  padding: 16px;
  overflow-y: auto;
}

.anim-ed-left,
.anim-ed-right {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.anim-ed-left {
  align-self: start;
}

.anim-ed-stage {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  cursor: zoom-in;
}

.anim-ed-versions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.anim-ed-version {
  position: relative;
  border: 1px solid var(--rk-line);
  border-radius: 7px;
  padding: 0;
  overflow: hidden;
  background: var(--rk-surface);
  cursor: pointer;
}

.anim-ed-version.is-active {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--rk-emerald) 26%, transparent);
}

.anim-ed-version img {
  display: block;
  width: 62px;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.anim-ed-version > span {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-start: 3px;
  border-radius: 4px;
  padding: 0 4px;
  background: rgba(23, 24, 21, 0.66);
  color: #fff;
  font: 700 9px/1.5 var(--rk-font-body);
}

.anim-ed-version:disabled {
  opacity: 0.6;
  cursor: wait;
}

/* 无缩略图变体（视频 take）。视频没有每版自己的封面，来源分镜图几乎每版都一样，摆出来是几张
   相同的图；所以这一版只留版本号。位置从角标改回文字流，其余（边框/选中环/禁用）全部沿用上面
   那套，免得同一个动作在同一条线上长出两种手感。 */
.anim-ed-version.is-textual > span {
  position: static;
  display: block;
  padding: 3px 10px;
  background: transparent;
  color: var(--rk-ink-soft);
  font: 700 11px/1.6 var(--rk-font-body);
}

.anim-ed-version.is-textual.is-active > span {
  color: var(--rk-ink);
}

/* 贴舞台左上角，绝对定位 —— 绝不能进 .anim-vd-workspace 的网格流：那个网格只有两行
   (1fr + 胶片条 150px)，多一个子元素会顶掉胶片条那一行、把舞台压矮 164px，视频跟着 16/9
   连宽一起缩。左上角是唯一干净的角（底部中间是 Re-film CTA，播放时还有原生控制条）。
   z-index 要在 .anim-vd-poster(absolute inset:0) 与 genbar(3) 之上，否则点不到。 */
.anim-vd-versions {
  position: absolute;
  inset-block-start: 10px;
  inset-inline-start: 10px;
  z-index: 4;
}

/* 垫图这里只展示：增删改仍在聊天框上方那一条里做，不在两处各实现一套 */
.anim-ed-refs {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.anim-ed-ref {
  display: inline-flex;
  width: 34px;
  height: 34px;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  overflow: hidden;
  background: var(--rk-paper);
}

.anim-ed-ref.is-scene {
  width: 52px;
  border-radius: 7px;
}

.anim-ed-ref img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.anim-ed-ref i {
  margin: auto;
  color: var(--rk-ink-muted);
  font-style: normal;
  font-size: 12px;
}

.anim-ed-refs-note {
  color: var(--rk-ink-muted);
  font-size: 10.5px;
}

.anim-ed-author {
  margin: 0;
  color: var(--rk-ink-muted);
  font-size: 11px;
}

.anim-ed-text {
  flex: 1 1 auto;
  min-height: 42vh;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  padding: 10px 12px;
  background: var(--rk-paper);
  color: var(--rk-ink-1);
  font: 400 12.5px/1.65 var(--rk-font-body);
  resize: vertical;
}

.anim-ed-takeover {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--rk-ink-2);
  font-size: 11.5px;
  cursor: pointer;
}

.anim-ed-locks {
  max-height: 130px;
  margin: 0;
  border: 1px dashed var(--rk-line);
  border-radius: 8px;
  padding: 8px 10px;
  background: var(--rk-paper);
  color: var(--rk-ink-3);
  font: 400 10.5px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap;
  overflow-y: auto;
}

.anim-ed-warn {
  margin: 0;
  color: #b4691f;
  font-size: 11px;
}

.anim-ed-err {
  margin: 0;
  color: #c0392b;
  font-size: 11.5px;
}

.anim-ed-foot {
  margin: 0;
  color: var(--rk-ink-muted);
  font-size: 10.5px;
}

/* 底部动作条：左下还原官方提示词，右下重新生成 / 保存 / 生成 */
.anim-ed-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  border-block-start: 1px solid var(--rk-line);
  padding: 10px 16px;
}

.anim-ed-bar-gap {
  flex: 1 1 auto;
}

.anim-ed-plain {
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 6px 16px;
  background: var(--rk-surface);
  color: var(--rk-ink-2);
  font: 700 11.5px/1.4 var(--rk-font-body);
  cursor: pointer;
}

.anim-ed-go {
  border: 0;
  border-radius: 999px;
  padding: 7px 22px;
  background: var(--rk-emerald);
  color: #fff;
  font: 700 12px/1.4 var(--rk-font-body);
  cursor: pointer;
}

.anim-ed-plain:disabled,
.anim-ed-go:disabled {
  opacity: 0.5;
  cursor: default;
}

/* (.anim-dd-card-edit 已下线 —— 手搓入口 2026-07-28 移到画布卡片上的 .anim-as-edit) */

@media (max-width: 900px) {
  .anim-ed-body {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ── 弹框顶部两个 tab：编辑（整镜提示词） / 修图（单格 i2i） ─────────────────────── */
.anim-ed-tabs {
  display: flex;
  gap: 4px;
}

.anim-ed-tab {
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 4px 14px;
  background: none;
  color: var(--rk-ink-3);
  font: 700 12px/1.4 var(--rk-font-body);
  cursor: pointer;
}

.anim-ed-tab.is-on {
  border-color: color-mix(in srgb, var(--rk-emerald) 34%, transparent);
  background: color-mix(in srgb, var(--rk-emerald) 12%, transparent);
  color: var(--rk-ink-1);
}

.anim-ed-title {
  margin-inline-start: auto;
  margin-inline-end: 10px;
  color: var(--rk-ink-3);
  font: 700 12px/1.4 var(--rk-font-body);
  /* 导演台的标题是「S13」，美术台的可能是整段片场描述（实测 143 字），会把右上角的 × 挤到边上。
     单行截断即可，完整名字在卡片和会话流里都看得到。（2026-07-28） */
  min-width: 0;
  max-width: 60%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 修图 tab：格子选择条 */
.anim-ed-cells {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.anim-ed-cell {
  position: relative;
  border: 1px solid var(--rk-line);
  border-radius: 8px;
  padding: 0;
  overflow: hidden;
  background: var(--rk-surface);
  cursor: pointer;
}

.anim-ed-cell.is-on {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--rk-emerald) 26%, transparent);
}

.anim-ed-cell img {
  display: block;
  width: 74px;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.anim-ed-cell > span {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-start: 3px;
  border-radius: 4px;
  padding: 0 5px;
  background: rgba(23, 24, 21, 0.66);
  color: #fff;
  font: 700 9px/1.6 var(--rk-font-body);
}

.anim-ed-cell:disabled {
  opacity: 0.6;
  cursor: default;
}

.anim-ed-text.is-retouch {
  min-height: 22vh;
  flex: 0 0 auto;
}

.anim-ed-reply {
  margin: 0;
  border-radius: 10px;
  padding: 8px 11px;
  background: color-mix(in srgb, var(--rk-emerald) 8%, transparent);
  color: var(--rk-ink-1);
  font: 400 11.5px/1.6 var(--rk-font-body);
}

.anim-ed-rt-acts {
  display: flex;
  justify-content: flex-end;
}

/* ── Error screen (rk-errorscreen) ───────────────────────────────────────────────────────────────
   The single full-view error state, companion to .rk-app-loading. Quiet paper, one mascot, a human
   headline and a real way back in. Deliberately NOT a scrim: an error is a terminal state of the
   view, not an overlay on top of it. See v3-visual-design → components.md (Async & assistant states)
   and src/lib/error-screen.js. */
.rk-errorscreen {
  max-width: 460px;
  margin: 10vh auto;
  padding: 0 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* Fixed HEIGHT (not width): the two poses have different aspect ratios, and matching their heights
   is what makes them read as the same cat at the same distance. Contact shadow per mascot rules. */
.rk-errorscreen-cat {
  height: 132px;
  width: auto;
  margin-bottom: 18px;
  filter: drop-shadow(0 6px 10px rgba(60, 46, 32, 0.14));
}

.rk-errorscreen-title {
  margin: 0 0 8px;
  font-family: var(--rk-font-display);
  font-size: 20px;
  font-weight: 650;
  color: var(--rk-ink);
}

.rk-errorscreen-body {
  margin: 0;
  max-width: 34em;
  color: var(--rk-ink-soft);
  font-size: 14px;
  line-height: 1.65;
}

.rk-errorscreen-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 22px;
}

/* Anchor-vs-button parity lives with the .rk-btn-* base rules — see "Anchor buttons" there. */

/* The raw server text: kept for support and debugging, demoted so it never reads as the message. */
.rk-errorscreen-detail {
  margin: 20px 0 0;
  max-width: 34em;
  color: var(--rk-ink-muted);
  font-size: 11px;
  line-height: 1.5;
  word-break: break-word;
}

.rk-errorscreen-detail span {
  opacity: 0.75;
}

@media (max-width: 640px) {
  .rk-errorscreen { margin: 7vh auto; }
  .rk-errorscreen-cat { height: 108px; }
}

/* Version-switch confirmation (Andy 2026-07-30). Clicking a take in the history strip used to open a
   lightbox and nothing else; it now asks once whether to switch to it, with an opt-out. */
.sb-version-switch {
  display: grid;
  gap: 16px;
  justify-items: center;
  text-align: center;
}

.rk-modal-panel.is-version-switch {
  inline-size: min(920px, 100%);
  max-block-size: calc(100dvh - 48px);
  padding: 26px 30px 24px;
}

.rk-modal-panel.is-version-switch:has(.sb-version-switch.is-char) {
  inline-size: min(620px, 100%);
}

.sb-version-switch h2 { margin: 0; font-size: 1.12rem; font-weight: 800; color: var(--rk-ink); }
.sb-version-switch p { margin: 0; color: var(--rk-ink-soft); font-size: 0.9rem; line-height: 1.55; }

.sb-version-switch-preview {
  inline-size: 100%;
  max-block-size: min(62dvh, 560px);
  height: auto;
  object-fit: contain;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
}

.sb-version-switch.is-char .sb-version-switch-preview {
  inline-size: min(380px, 100%);
}

.sb-version-switch-ack {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--rk-ink-soft);
  font-size: 0.84rem;
  cursor: pointer;
}

.sb-version-switch-ack input { width: 15px; height: 15px; accent-color: var(--rk-emerald); cursor: pointer; }

.sb-version-switch-actions { display: flex; gap: 10px; }

.sb-version-switch-cancel,
.sb-version-switch-go {
  min-height: 40px;
  padding-inline: 20px;
  border-radius: 999px;
  font-weight: 700;
  cursor: pointer;
}

.sb-version-switch-cancel {
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  color: var(--rk-ink);
}

.sb-version-switch-cancel:hover { border-color: var(--rk-emerald); }

.sb-version-switch-go {
  border: 0;
  background: var(--rk-emerald);
  color: var(--rk-surface);
}

.sb-version-switch-go:hover { background: var(--rk-emerald-hover); }

@media (max-width: 640px) {
  .rk-modal-panel.is-version-switch {
    max-block-size: calc(100dvh - 24px);
    padding: 22px 18px 18px;
  }

  .sb-version-switch { gap: 12px; }
  .sb-version-switch-preview { max-block-size: 58dvh; }
}

/* Character-form buttons are drafts, not commands. The one-time confirmation makes the destructive
   meaning explicit without changing the compact three-option control in the inspector. */
.sb-character-form-confirm {
  display: grid;
  gap: 14px;
  text-align: start;
}

.sb-character-form-confirm h2 {
  margin: 0;
  color: var(--rk-ink);
  font-size: 1.12rem;
  font-weight: 850;
}

.sb-character-form-confirm p {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.88rem;
  line-height: 1.6;
}

.sb-character-form-confirm-ack {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  color: var(--rk-ink-soft);
  font-size: 0.84rem;
  cursor: pointer;
}

.sb-character-form-confirm-ack input {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--rk-emerald);
  cursor: pointer;
}

.sb-character-form-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.sb-character-form-confirm-actions button {
  min-height: 40px;
  padding-inline: 20px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-weight: 750;
  cursor: pointer;
}

.sb-character-form-confirm-actions button.is-primary {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: #fff;
}

.sb-character-form-confirm-actions button:hover { border-color: var(--rk-emerald); }
.sb-character-form-confirm-actions button.is-primary:hover { background: var(--rk-emerald-hover); }

/* Companion images (base sheet / outfits) sit in the same strip but are read-only — no switch cursor
   affordance, and a quieter frame so they never read as takes of the portrait. */
.sb-as-insp-version.is-companion { cursor: zoom-in; opacity: 0.92; }
.sb-as-insp-version.is-companion:hover { opacity: 1; }

/* ── 消息中心 ── Java's t_user_notify, read-only, opened from the avatar menu.
   Quiet paper: the list is chrome, so it stays colorless — the only accent is the unread dot, and it
   is emerald rather than the usual notification red because nothing here is an alarm. */
/* ── anchored dropdown panel (Kim 2026-08-10) ────────────────────────────────
   Position comes from lib/popover.js (it has to — the anchor moves); this file owns the surface.
   No backdrop and no scrim by design: the panel is for glancing, and the page behind it stays live.
   Sits above the pinned ops strip (z 60) and below the modal overlay, which still owns the screen
   when something genuinely needs to interrupt. */
.rk-pop {
  position: fixed;
  z-index: 70;
  display: flex;
  flex-direction: column;
  min-block-size: 0;
  overflow: hidden;
  background: var(--rk-paper);
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  box-shadow: var(--rk-shadow-panel);
}

.rk-pop-body {
  min-block-size: 0;
  overflow-y: auto;
  /* Stop scroll chaining. Without it, reaching the end of the message list hands the wheel to the
     page; the topbar scrolls away, the anchor leaves the viewport, and the panel closes itself while
     the reader was doing nothing but reading. */
  overscroll-behavior: contain;
  padding: 12px 14px 14px;
}

/* ── announcement detail dialog (Kim 2026-08-10) ──────────────────────────────
   Ops-authored copy: headings, lists, a banner image, a link out. It gets a real reading surface
   instead of being folded into a 380px strip. Personal notices still expand inline — see the comment
   above isAnnouncement() for why the two are treated differently. */
.rk-notify-detail {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-block-size: 0;
  block-size: 100%;
}

.rk-notify-detail-title {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.25rem;
  line-height: 1.25;
  color: var(--rk-ink);
}

.rk-notify-detail-when {
  margin: 0;
  font-size: 0.8rem;
  color: var(--rk-ink-muted);
}

.rk-notify-detail-body {
  flex: 1 1 auto;
  min-block-size: 0;
  margin-block-start: 4px;
  color: var(--rk-ink);
  line-height: 1.6;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  overflow-wrap: anywhere; /* ops paste raw campaign URLs — they must wrap, not widen the dialog */
}

.rk-notify-detail-body img {
  max-inline-size: 100%;
  block-size: auto;
  border-radius: var(--rk-radius-sm);
}

.rk-notify-detail-body a {
  color: var(--rk-emerald);
}

.rk-notify-detail-actions {
  display: flex;
  flex: none;
  justify-content: flex-end;
  gap: 10px;
  margin-block-start: 4px;
  padding-block-start: 12px;
  border-block-start: 1px solid var(--rk-line);
}

@media (max-width: 720px) {
  .rk-notify-detail { block-size: auto; }
  .rk-notify-detail-body { overflow: visible; }
}

/* The little caret that ties the panel to the bell. Drawn on the panel rather than as an extra node
   so it cannot be left behind when the panel closes; `inset-inline-end` puts it under the anchor in
   LTR and mirrors itself in RTL, where the panel hangs off the anchor's other edge. */
.rk-pop.is-notifications::before {
  content: '';
  position: absolute;
  inset-block-start: -7px;
  inset-inline-end: 22px;
  inline-size: 12px;
  block-size: 12px;
  transform: rotate(45deg);
  border-block-start: 1px solid var(--rk-line);
  border-inline-start: 1px solid var(--rk-line);
  background: var(--rk-paper);
}

/* The message centre in panel form. The modal version keeps its display-type heading; at 380px wide
   that heading plus its kicker costs ~60px of the reading area for a label the panel already carries
   as its accessible name — and the reference design shows tabs straight away. */
.rk-pop.is-notifications .rk-notify {
  min-block-size: 0;
  gap: 10px;
}

/* [REVISE 2026-08-10, Kim design] ~~The header was hidden in panel form.~~ It now carries the title
   and the mark-all action, so it stays — it just costs one compact row instead of two tall ones.
   The caret needs the panel to allow overflow, which is why the rounding lives on the body. */
.rk-pop.is-notifications {
  overflow: visible;
}

.rk-pop.is-notifications .rk-pop-body {
  border-radius: inherit;
}

.rk-notify {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-block-size: 340px;
}

/* The shared modal normally scrolls as one long sheet. Notifications need a stable reader instead:
   keep the heading and tabs in place, then give the remaining height to the message list. */
.rk-modal.is-notifications .rk-modal-panel {
  block-size: min(800px, 88dvh);
  overflow: hidden;
}

.rk-modal.is-notifications .rk-modal-body,
.rk-modal.is-notifications .rk-notify {
  min-block-size: 0;
  block-size: 100%;
}
/* [REVISE 2026-08-10, Kim design] Header is now one row: the name of the thing on the left, the one
   bulk action on the right. ~~A stacked kicker + display-type heading~~ cost ~60px of a 400px-wide
   panel to say something the panel's own accessible name already says. */
.rk-notify-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.rk-notify-heading {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.15rem;
  line-height: 1.2;
  color: var(--rk-ink);
}
/* [REVISE 2026-08-10, Kim design] ~~A segmented pill holding both tabs (and, worse, the mark-all
   action, which then read as a third tab).~~ Underline tabs: they carry no container, so nothing
   sitting near them can be mistaken for another segment, and the active one is stated by a rule under
   the label rather than by a raised chip. */
.rk-notify-tabs {
  display: flex;
  gap: 18px;
  border-block-end: 1px solid var(--rk-line);
}
.rk-notify-tab {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 0;
  border-block-end: 2px solid transparent;
  border-radius: 0;
  padding: 6px 2px 8px;
  margin-block-end: -1px; /* sit the rule ON the divider, not above it */
  background: none;
  color: var(--rk-ink-soft);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
}
.rk-notify-tab.is-active {
  border-block-end-color: var(--rk-emerald);
  color: var(--rk-emerald);
  font-weight: 800;
}
/* Says WHICH tab holds the unread — without it the bell states a total the reader cannot locate. */
.rk-notify-tab-count {
  flex: none;
  min-inline-size: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 800;
  line-height: 18px;
  text-align: center;
}
/* Quiet text action, not a button-shaped peer of the tabs: weight and size sit a step below them so
   the eye reads "two tabs, plus something you can do", never "three tabs". */
.rk-notify-mark-all {
  flex: none;
  margin-inline-start: auto;
  border: 0;
  border-radius: var(--rk-radius-sm);
  padding: 6px 8px;
  background: none;
  color: var(--rk-ink-soft);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  white-space: nowrap;
}
.rk-notify-mark-all:hover:not(:disabled) {
  color: var(--rk-emerald);
}
.rk-notify-mark-all:disabled {
  color: var(--rk-ink-muted);
  cursor: default;
}
.rk-notify-notice {
  margin: 0;
  padding: 8px 12px;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-emerald-soft);
  color: var(--rk-ink-soft);
  font-size: 0.85rem;
}
.rk-notify-pane {
  flex: 1;
  min-block-size: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}
/* [REVISE 2026-08-10, Kim design] ~~Each row a bordered card with 10px between them.~~ A list of
   cards inside a 400px panel is mostly border; hairline dividers give the same separation and let
   five messages fit where three did. */
.rk-notify-rows {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}
.rk-notify-row + .rk-notify-row {
  border-block-start: 1px solid var(--rk-line);
}
.rk-notify-row:hover {
  background: var(--rk-paper-2);
}
.rk-notify-head {
  inline-size: 100%;
  display: grid;
  grid-template-columns: 8px 34px minmax(0, 1fr) auto;
  align-items: start;
  gap: 10px;
  border: 0;
  padding: 12px 6px;
  background: none;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}
/* Round badge, one per category (announcement / personal). Emerald on its own soft tint: the only
   colour in the row, so the eye lands on the message rather than on the chrome. */
.rk-notify-icon {
  inline-size: 34px;
  block-size: 34px;
  display: inline-grid;
  place-items: center;
  border-radius: 999px;
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald);
}
.rk-notify-icon svg {
  inline-size: 18px;
  block-size: 18px;
}
.rk-notify-main {
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
/* One line, ellipsis. The preview exists to answer "does this concern me" at a glance; letting it
   wrap to three lines would turn the list back into the wall of text it replaced. */
.rk-notify-preview {
  min-inline-size: 0;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--rk-ink-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Loading placeholder — same grid as a real row, so the panel does not give up its height while a
   tab is fetched for the first time (measured: 488px → 137px → 488px, which reads as a flash). */
.rk-notify-skel {
  display: grid;
  grid-template-columns: 8px 34px minmax(0, 1fr) auto;
  align-items: start;
  gap: 10px;
  padding: 12px 6px;
}
.rk-notify-skel > * {
  border-radius: 6px;
  background: var(--rk-paper-2);
}
.rk-notify-skel-dot {
  inline-size: 8px;
  block-size: 8px;
  margin-block-start: 13px;
  border-radius: 999px;
}
.rk-notify-skel-icon {
  inline-size: 34px;
  block-size: 34px;
  border-radius: 999px;
}
.rk-notify-skel-lines {
  display: flex;
  flex-direction: column;
  gap: 3px; /* same as .rk-notify-main */
  background: none;
}
/* Stands in for the "view all" footer so it does not pop into existence when the list lands. */
.rk-notify-skel-all {
  margin-block-start: 4px;
  border-block-start: 1px solid var(--rk-line);
  block-size: 41px;
}
/* Heights are the real LINE BOXES (title .9rem × 1.4, preview .8rem × 1.4), not arbitrary bars —
   that is what makes a skeleton row the same height as the row it stands in for. */
.rk-notify-skel-lines i {
  border-radius: 6px;
  background: var(--rk-paper-2);
}
.rk-notify-skel-lines i:first-child { inline-size: 62%; block-size: 1.26rem; }
.rk-notify-skel-lines i:last-child { inline-size: 88%; block-size: 1.12rem; }
.rk-notify-skel-when {
  inline-size: 38px;
  block-size: 10px;
  margin-block-start: 3px;
}
/* A slow breathe says "working" without the eye having anything to chase. */
.rk-notify-skel-icon,
.rk-notify-skel-when,
.rk-notify-skel-lines i {
  animation: rk-notify-skel-pulse 1.4s ease-in-out infinite;
}
@keyframes rk-notify-skel-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
@media (prefers-reduced-motion: reduce) {
  .rk-notify-skel-icon,
  .rk-notify-skel-when,
  .rk-notify-skel-lines i {
    animation: none;
  }
}

/* Hands off to the full reader. Sits under the list, separated, centred — an exit, not a row. */
.rk-notify-all {
  inline-size: 100%;
  margin-block-start: 4px;
  border: 0;
  border-block-start: 1px solid var(--rk-line);
  padding: 12px 0 4px;
  background: none;
  color: var(--rk-emerald);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}
.rk-notify-all:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* [REVISE 2026-08-10, Kim design] ~~A rotating caret announced the expand/collapse state.~~ The row
   now carries a preview line and, for announcements, opens a dialog rather than expanding — a caret
   would promise in-place expansion that most rows no longer do. `aria-expanded` still states it for
   assistive tech on the rows that do expand. */

/* The dot keeps its cell whether or not it shows, so titles never shift left as they are read. */
.rk-notify-dot {
  inline-size: 8px;
  block-size: 8px;
  margin-block-start: 13px; /* aligns with the title's first line, not the top of the icon badge */
  border-radius: 999px;
  background: transparent;
}
.rk-notify-row.is-unread .rk-notify-dot {
  background: var(--rk-emerald);
}
.rk-notify-title {
  min-inline-size: 0;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--rk-ink-soft);
  overflow-wrap: anywhere;
}
.rk-notify-row.is-unread .rk-notify-title {
  font-weight: 800;
  color: var(--rk-ink);
}
.rk-notify-when {
  flex: none;
  margin-block-start: 2px; /* baseline-ish with the title, which sits a hair lower in its column */
  font-size: 0.75rem;
  color: var(--rk-ink-muted);
  white-space: nowrap;
}
.rk-notify-body {
  /* Logical, not physical: the 36px indent lines the body up under the title, past the dot column —
     in Arabic that column is on the right, so a hard `padding-left` would indent the wrong edge. */
  padding-block: 0 14px;
  padding-inline: 36px 16px;
  color: var(--rk-ink-soft);
  font-size: 0.88rem;
  line-height: 1.55;
  overflow-wrap: anywhere;
}
.rk-notify-body a {
  color: var(--rk-emerald);
}
.rk-notify-body img {
  display: block;
  max-inline-size: 100%;
  block-size: auto;
  margin-block: 12px;
  border-radius: var(--rk-radius-sm);
}
/* The message's own jump target, when it has one it can honour from inside v3 (see notifyCtaHref).
   Outlined rather than filled: it sits inside a list, and a solid emerald block per message would
   turn the drawer into a wall of buttons competing with the page's real primary action. */
.rk-notify-cta-row {
  margin-block: 12px 0;
}
.rk-notify-cta {
  display: inline-block;
  padding: 7px 16px;
  border: 1px solid var(--rk-emerald);
  border-radius: 999px;
  color: var(--rk-emerald);
  font-size: 0.85rem;
  font-weight: 700;
  text-decoration: none;
}
.rk-notify-cta:hover {
  background: var(--rk-emerald);
  color: var(--rk-paper);
}
.rk-notify-body p {
  margin: 0 0 8px;
}
.rk-notify-body p:last-child {
  margin-bottom: 0;
}
.rk-notify-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 40px 20px;
}
.rk-notify-empty {
  margin: 0;
  color: var(--rk-ink-muted);
  text-align: center;
}
.rk-notify-retry,
.rk-notify-more {
  align-self: center;
  margin-block-start: 12px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 8px 22px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.rk-notify-retry:hover,
.rk-notify-more:hover {
  border-color: var(--rk-emerald);
}
.rk-notify-more[disabled] {
  opacity: 0.6;
  cursor: default;
}
.rk-notify-more {
  display: block;
  margin-inline: auto;
}

/* Unread affordances on the avatar: a dot on the closed toggle (the only thing visible before the
   menu opens) and a count on the menu row itself. */
.rk-user-toggle {
  position: relative;
}
.rk-user-dot {
  position: absolute;
  inset-block-start: 0;
  inset-inline-end: 0;
  inline-size: 9px;
  block-size: 9px;
  border: 2px solid var(--rk-paper);
  border-radius: 999px;
  background: var(--rk-emerald);
}
.rk-user-badge {
  margin-inline-start: auto;
  min-inline-size: 20px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 800;
  text-align: center;
}

/* ── 任务型活动进度卡（首页，worklist #343）──
   与运营条同一条纪律：没有进行中的活动时整块不渲染、不占空间。一期刻意只有这一张卡，没有活动中心页
   —— 先证明规则会触发、奖会到账，再谈壳子。 */
.rk-activity-slot { display: flex; justify-content: center; margin-block: 10px 0; }
.rk-activity-slot[hidden] { display: none; }
.rk-activity {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  inline-size: min(720px, 100%); padding: 10px 18px;
  background: var(--rk-surface); border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius); box-shadow: var(--rk-shadow-card);
}
.rk-activity.is-done { border-color: var(--rk-emerald); background: var(--rk-emerald-soft); }
.rk-activity-copy { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
.rk-activity-title { font-weight: 600; color: var(--rk-ink); }
.rk-activity-desc { font-size: 0.82rem; color: var(--rk-ink-soft); }
.rk-activity-state { flex: none; display: flex; align-items: baseline; gap: 10px; }
.rk-activity-progress { font-size: 0.95rem; color: var(--rk-ink-soft); }
.rk-activity-progress b { font-size: 1.15rem; color: var(--rk-emerald); }
.rk-activity-reward, .rk-activity-done { font-size: 0.85rem; font-weight: 600; color: var(--rk-emerald); }

@media (max-width: 680px) {
  .rk-activity { inline-size: 100%; flex-wrap: wrap; gap: 8px; }
}

/* 活动卡的第三行：剩余时间 + 已完成人数。两条都是「压力」而非「信息」，所以给弱化的字号与颜色，
   不跟标题抢；点分隔符用 <i> 而不是文本里的 ·，方便任一条缺席时不留孤零零的点。 */
.rk-activity-meta { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--rk-ink-muted); }
.rk-activity-meta i { font-style: normal; opacity: 0.5; }

/* ══ 首页运营区改版（2026-08-05，Andy 提供设计稿）════════════════════════════
   把「平台在说话」的两块从两个孤立控件，改成职责分明的一组：
     ~~运营条 = 通栏浅色公告条~~（2026-08-10 Kim：已迁出首页，改为全站置顶通栏 `.rk-ops-strip`，
     样式与本段无关，见本文件上方「site-wide pinned ops strip」段）
     活动卡 = 有分量的参与卡（角标 + 标题 + 进度条 + 数字）
   稿子里的深绿与米黄没有照搬——首页只允许一套绿（--rk-emerald），否则同屏会出现两个绿色体系。
   这里用现有 token 的浅色调做等效层次。 */

/* ── 活动卡：左文右数，底部进度条 ── */
.rk-activity-slot { display: block; margin-block: 12px 0; }
.rk-activity {
  display: flex; align-items: center; justify-content: space-between; gap: 28px;
  inline-size: 100%; padding: 20px 24px;
}
.rk-activity-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rk-activity-badge {
  flex: none; padding: 3px 10px; border-radius: 999px;
  background: var(--rk-emerald-soft); color: var(--rk-emerald);
  font-size: 0.72rem; font-weight: 700;
}
.rk-activity-title { font-size: 1.35rem; font-weight: 700; line-height: 1.25; }
.rk-activity-desc { margin-block-start: 6px; }
.rk-activity-meta { margin-block-start: 8px; }

.rk-activity-state { flex: none; display: flex; flex-direction: column; align-items: stretch; gap: 12px; min-inline-size: 260px; }
.rk-activity-figures { display: flex; align-items: baseline; justify-content: center; gap: 18px; }
.rk-activity-figure { display: inline-flex; align-items: baseline; gap: 2px; }
.rk-activity-figure b { font-size: 1.9rem; font-weight: 700; color: var(--rk-emerald); line-height: 1; }
.rk-activity-of { font-size: 0.9rem; color: var(--rk-ink-soft); }
.rk-activity-sep { inline-size: 1px; align-self: stretch; background: var(--rk-line); }
/* 进度条：数字说事实，条让"还差多远"看得见。 */
.rk-activity-track { block-size: 6px; border-radius: 999px; background: var(--rk-paper-2); overflow: hidden; }
.rk-activity-track > i { display: block; block-size: 100%; background: var(--rk-emerald); transition: width 240ms ease-out; }

@media (max-width: 760px) {
  /* 窄屏：上排的「文案 | 数字」左右并排会把标题挤成两三行。改为上下堆叠，
     数字靠左与文案同起点，进度条仍横贯整卡。 */
  .rk-activity-row { flex-direction: column; align-items: stretch; gap: 12px; }
  .rk-activity-figures { justify-content: flex-start; }
  .rk-activity-state { min-inline-size: 0; }
  .rk-activity-title { font-size: 1.15rem; }
}

/* ── 活动卡三处修正（2026-08-05 目视后）──
   ① 进度条改为横贯整卡：原来它跟着右侧数字列走，只占右边一小截，0/3 时是一条孤零零的空轨道，
      看着像没加载完。稿子里它是贯穿整张卡的底边——那才读得出"整件事完成了多少"。
   ② 数字与单位留空隙：左边 "0 / 3" 是分开的，右边 "200积分" 却黏在一起，两组排版对不上。
   ③ 卡片改为纵向：上排左文右数，下排整条进度。 */
.rk-activity { flex-direction: column; align-items: stretch; gap: 14px; }
.rk-activity-row { display: flex; align-items: center; justify-content: space-between; gap: 28px; }
.rk-activity-state { flex: none; min-inline-size: 0; flex-direction: row; align-items: baseline; gap: 0; }
.rk-activity-of { margin-inline-start: 4px; }
.rk-activity-track { inline-size: 100%; }

/* ── 活动配图（可选）──
   有图时排在文案左侧，卡片不再显得空；**无图时整个 <span> 不渲染**，版式自动回到无图形态——
   这是配图敢做成可选的前提：没来得及做图的活动照样能上线，而不是显示一个占位灰块。
   图挂了（404/防盗链）时 onerror 会把它整块移除，同样退回无图形态，绝不留破图。 */
.rk-activity-art {
  flex: none; inline-size: 76px; block-size: 76px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--rk-radius-sm); overflow: hidden;
  background: var(--rk-paper-2);
}
.rk-activity-art img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.rk-activity.has-art .rk-activity-row { gap: 18px; }

@media (max-width: 760px) {
  .rk-activity-art { inline-size: 56px; block-size: 56px; }
}

/* ── 宽度与内部间距修正（2026-08-05 目视第二轮）──
   ① 太宽：之前做成了通栏 1034，而它们上面的创作输入框是 830 居中——三块宽度不一致，
      读起来像三个拼在一起的模块。改为跟随输入框同宽同轴（830），页面回到一条竖直的视觉主线。
   ② 图文之间空一大块：图在最左、文字被推到中间，是因为上排用了 space-between 且文案列会撑开。
      改为图与文案紧邻（gap 14），数字列才靠右。
   ③ 进度条贴底：加一点上边距并收窄到与文案同起点，读作"进度"而不是卡片底边的装饰线。 */
.rk-activity-slot { display: flex; justify-content: center; }
.rk-activity { inline-size: min(830px, 100%); }

.rk-activity { padding: 18px 20px; gap: 12px; }
.rk-activity-row { justify-content: flex-start; gap: 14px; }
.rk-activity-copy { flex: 1 1 auto; min-inline-size: 0; }
.rk-activity-state { margin-inline-start: auto; }
.rk-activity-figure b { font-size: 1.6rem; }
.rk-activity-title { font-size: 1.15rem; }
.rk-activity-art { inline-size: 60px; block-size: 60px; }

/* 进度条与文案同起点、与上排留出呼吸：贴着卡片底边时它读作装饰线，缩进并留白后才读作"进度"。 */
.rk-activity-track { margin-block-start: 2px; }


/* 那 78px 缩进只在「图在左、文案在右」时成立；窄屏上排已改为竖向堆叠（图在上方），
   再缩进就变成无缘无故的偏移。 */
@media (max-width: 760px) {

}

/* ── 对照设计稿的第三轮修正（2026-08-05）──
   之前每一项都比稿子"小一号"，叠起来就是整张卡没有分量。逐项拉开：
   ① 图从 60px 缩略图 → 96px 且**去掉灰底方框**，让插画自己说话（稿子里图是浮在卡上的，不是被框住的）；
   ② 标题 1.15 → 1.6rem，与说明文字拉开层次（稿子里标题是这张卡的主角）；
   ③ 数字 1.6 → 2.2rem，右侧才压得住左侧的大标题；
   ④ 卡片 padding 18 → 26，行距放开，扁平感来自留白不够；
   ⑤ 角标移到标题上方独立一行——和标题挤一行时它像个前缀，独立才像"标签"。 */
.rk-activity { padding: 26px 28px; gap: 16px; }
.rk-activity-row { gap: 20px; align-items: center; }

.rk-activity-art {
  inline-size: 96px; block-size: 96px;
  background: none; border-radius: var(--rk-radius);
}
.rk-activity-art img { object-fit: contain; }

.rk-activity-head { flex-direction: column; align-items: flex-start; gap: 8px; }
.rk-activity-badge { font-size: 0.75rem; padding: 4px 11px; }
.rk-activity-title { font-size: 1.6rem; line-height: 1.2; }
.rk-activity-desc { margin-block-start: 8px; font-size: 0.95rem; }
.rk-activity-meta { margin-block-start: 10px; font-size: 0.82rem; }

.rk-activity-figure b { font-size: 2.2rem; }
.rk-activity-of { font-size: 0.95rem; }
.rk-activity-figures { gap: 22px; }

/* 桌面：进度条与文案列同起点（图 96 + 间距 20）。窄屏归零见文件末尾媒体查询。 */


@media (max-width: 760px) {
  .rk-activity { padding: 20px; }
  .rk-activity-art { inline-size: 72px; block-size: 72px; }
  .rk-activity-title { font-size: 1.25rem; }
  .rk-activity-figure b { font-size: 1.8rem; }
}


/* 窄屏：图堆到上方，进度条不再缩进；必须放在桌面规则之后，否则被覆盖（本轮真踩到：手机上仍吃到 116px 缩进，卡片内容需要 437 却只有 341，整页横向溢出 79）。 */
@media (max-width: 760px) {

}

/* ══ 运营区精修（2026-08-05 Andy 逐条清单）════════════════════════════════
   主次结构与业务逻辑均不动，只做间距、密度、指标层级与响应式。 */

/* ② 模块间距：活动卡→我的书架 32。（原「创作选项→通知条 36 / 通知条→活动卡 22」两档随运营条
   迁出首页一并作废，2026-08-10。） */
.rk-activity-slot { margin-block: 22px 32px; }

/* ③ 压缩卡片高度：内边距与行距各收一档，缩略图 96 → 84；进度条上移贴近文案与数字。 */
.rk-activity { padding: 18px 24px; gap: 10px; }
.rk-activity-row { gap: 16px; }
.rk-activity-art { inline-size: 84px; block-size: 84px; }
.rk-activity-desc { margin-block-start: 6px; }
.rk-activity-meta { margin-block-start: 7px; }
.rk-activity-track { margin-block-start: 0; }


/* ④ 右侧指标加低强调标签：标签浅灰小字，数字保持绿色，两组之间细分隔线（沿用 .rk-activity-sep）。 */
.rk-activity-figures { align-items: stretch; gap: 20px; }
.rk-activity-figure { flex-direction: column; align-items: center; gap: 2px; }
.rk-activity-cap { font-size: 0.72rem; color: var(--rk-ink-muted); line-height: 1.2; }
.rk-activity-figure b { font-size: 1.85rem; }
.rk-activity-num { display: inline-flex; align-items: baseline; }

/* ⑦ ~~通知条保持次级~~ —— 运营条 2026-08-10 迁出首页并改为高对比置顶通栏，本条不再适用。 */

/* ⑧ 窄屏：缩略图与标题在上一行，进度/奖励整行落到下面；不重叠、不横向滚动。 */
@media (max-width: 760px) {
  .rk-activity-row { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .rk-activity-copy { flex: 1 1 200px; }
  .rk-activity-state { flex-basis: 100%; margin-inline-start: 0; margin-block-start: 4px; }
  .rk-activity-figures { justify-content: flex-start; }
}

/* 间距校准：主区（.rk-home-grid）本身有 22px 的行间距，会与插槽的 margin 相加——
   照目标值直接写 margin 会得到 36+22=58。这里按「目标值 − 22」反推，实测三处落在 36/22/34。 */
.rk-activity-slot { margin-block: 0 12px; }

/* ══ 进度条缩进：唯一权威定义，勿在别处再写同名规则 ══
   桌面：与文案列同起点。103 是**实测值**不是算出来的——84+16=100 看着对，但 flex gap 与
   inline-flex 的行为让实际起点差 3px；这一类对齐一律以量出来的为准。
   窄屏：图堆到上方，缩进必须归零——否则卡片内容宽度超出可用宽度，整页横向溢出。
   这条规则今天被前后追加覆盖了三次（78→100→114），每次都在窄屏炸出溢出。
   收敛成这一处，窄屏覆盖紧跟其后，物理上不给后来的追加留覆盖窗口。 */
/* 不再手填缩进：卡片改用两列网格（图 | 内容），进度条落在第二列，与文案列共用同一条分割线，
   永远不会差 1-3px。之前 100 / 103 / 114 三个手量值都只是接近。 */
.rk-activity.has-art { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 16px; row-gap: 10px; align-items: center; }
.rk-activity.has-art .rk-activity-art { grid-column: 1; grid-row: 1; }
.rk-activity.has-art .rk-activity-row { grid-column: 2; grid-row: 1; }
.rk-activity.has-art .rk-activity-track { grid-column: 2; grid-row: 2; margin-inline-start: 0; inline-size: 100%; }
@media (max-width: 760px) {
  .rk-activity.has-art .rk-activity-track { margin-inline-start: 0; inline-size: 100%; }
}

/* 窄屏「图 + 标题同一行」的前提是文案列的最小宽度放得下：375 − 卡片内边距 40 − 图 84 − 间距 16 = 235，
   之前写 200px 看似够，但标题与说明的最小内容宽把它顶到了下一行。改用 120px 起，让它真正与图并排。 */
@media (max-width: 760px) {
  .rk-activity-copy { flex: 1 1 120px; min-inline-size: 0; }
}

/* 窄屏：网格保留（图与标题才并排得住），只让进度条跨满两列——否则它被锁在第二列，只剩半宽。 */
@media (max-width: 760px) {
  .rk-activity.has-art .rk-activity-track { grid-column: 1 / -1; inline-size: 100%; }
}

/* ── 新用户折扣角标 ────────────────────────────────────────────────────────────────────────────
   贴在生成按钮标签后面的一枚小标记。刻意**不是**价格预览：2026-08-01 Andy 撤掉了生成前的费用卡
   （「生成入口不该卖东西」），带价格的卡片会把每次创作变成预算决策。这里只说"你现在更便宜"，
   具体金额由点击后的报价链路负责。
   用祖母绿而非警示色 —— 这是好消息，不是提醒。 */
.rk-discount-badge {
  display: inline-block;
  margin-inline-start: 6px;
  padding: 1px 6px;
  border-radius: var(--rk-radius-sm, 4px);
  background: var(--rk-emerald-soft, #e3f3ec);
  color: var(--rk-emerald, #0fa47e);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  vertical-align: middle;
}

/* 深色皮肤下浅底会发亮成一块白斑，改用描边式。 */
@media (prefers-color-scheme: dark) {
  .rk-discount-badge {
    background: transparent;
    border: 1px solid var(--rk-emerald, #0fa47e);
  }
}

:root[data-theme='dark'] .rk-discount-badge {
  background: transparent;
  border: 1px solid var(--rk-emerald, #0fa47e);
}

:root[data-theme='light'] .rk-discount-badge {
  background: var(--rk-emerald-soft, #e3f3ec);
  border: 0;
}

/* ── credit-details ledger (WALLET · Credit details) ─────────────────────────────────────────────
   Moved here from account.css on 2026-08-10: the same ledger is now the modal the subscription
   overlay's CONSUMPTION RECORD opens, and that overlay opens on EVERY page, while account.css is
   linked by account.html alone — left there, the modal rendered unstyled everywhere else. The
   .account-* names stay because the account page's inline #billing card renders the same rows. */
.account-link {
  border: 0;
  background: none;
  padding: 0;
  color: var(--rk-emerald-hover);
  font-weight: 800;
  cursor: pointer;
}

.account-link:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.account-link[disabled] {
  color: var(--rk-ink-muted);
  cursor: default;
  text-decoration: none;
}

.account-empty {
  margin: 0;
  color: var(--rk-ink-muted);
}

.account-ledger {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
}

.account-ledger-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 2px;
  border-block-start: 1px solid var(--rk-line);
}

.account-ledger-row:first-child {
  border-block-start: 0;
}

.account-ledger-details {
  min-inline-size: 0;
  display: grid;
  gap: 3px;
}

.account-ledger-scene {
  color: var(--rk-ink);
  overflow-wrap: anywhere;
}

.account-ledger-date {
  font-size: 0.84rem;
  color: var(--rk-ink-muted);
  unicode-bidi: plaintext;
}

.account-ledger-value {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
}

.account-ledger-kind {
  min-inline-size: 42px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 800;
  line-height: 1.35;
  text-align: center;
}

.account-ledger-kind.is-credits {
  color: var(--rk-emerald-hover);
  background: var(--rk-emerald-soft);
}

.account-ledger-kind.is-points {
  color: var(--rk-warn);
  background: color-mix(in srgb, var(--rk-warn) 12%, var(--rk-surface));
}

.account-ledger-amount {
  min-inline-size: 52px;
  font-weight: 800;
  color: var(--rk-ink-soft);
  text-align: end;
  white-space: nowrap;
}

.account-ledger-original {
  color: var(--rk-ink-muted);
  font-size: 0.82rem;
  font-weight: 600;
}

.account-ledger-amount.is-discounted {
  color: var(--rk-emerald-hover);
}

/* Any row that ADDS to a balance — refund, top-up, grant, invite reward. Named for the direction,
   not for one of its causes: it started life as refund-only and now also carries every 充值. */
.account-ledger-row.is-incoming .account-ledger-amount {
  color: var(--rk-good);
}

.account-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-block-start: 18px;
}

.account-pager-info {
  color: var(--rk-ink-soft);
  font-weight: 700;
}

@media (max-width: 520px) {
  .account-ledger-row {
    align-items: flex-start;
  }

  .account-ledger-value {
    gap: 8px;
  }
}

/* Final authority for the desktop task entry. Keep this after every historical activity-card
   override: the legacy in-flow card accumulated several later width/padding rules, and PC must not
   inherit any of them after the activity becomes a fixed entry. */
@media (min-width: 1024px) {
  #sb-activity.rk-activity-slot {
    position: fixed;
    z-index: 42;
    inset-block-start: 188px;
    inset-inline-end: 22px;
    display: block;
    inline-size: auto;
    margin: 0;
    pointer-events: none;
  }

  #sb-activity.rk-activity-slot[hidden] { display: none; }

  #sb-activity .rk-activity,
  #sb-activity .rk-activity.has-art {
    display: grid;
    grid-template-columns: none;
    grid-template-rows: none;
    inline-size: 56px;
    block-size: 56px;
    min-block-size: 0;
    padding: 0;
    gap: 0;
    place-items: center;
    place-content: center;
    border: 1px solid color-mix(in srgb, var(--rk-emerald) 25%, var(--rk-line));
    border-radius: 18px;
    background: var(--rk-surface);
    box-shadow: 0 12px 30px rgba(32, 91, 72, 0.16);
    pointer-events: auto;
  }

  #sb-activity .rk-activity > .rk-activity-art,
  #sb-activity .rk-activity > .rk-activity-row,
  #sb-activity .rk-activity > .rk-activity-track { display: none; }

  #sb-activity .rk-activity-dismiss {
    position: absolute;
    z-index: 2;
    inset-block-start: -9px;
    inset-inline-start: -9px;
    display: grid;
    inline-size: 22px;
    block-size: 22px;
    padding: 0;
    place-items: center;
    border: 1px solid var(--rk-line);
    border-radius: 50%;
    background: var(--rk-surface);
    box-shadow: 0 4px 12px rgba(32, 55, 47, 0.16);
    color: var(--rk-ink-muted);
    cursor: pointer;
    pointer-events: auto;
  }

  #sb-activity .rk-activity-dismiss:hover {
    border-color: color-mix(in srgb, var(--rk-ink-muted) 45%, var(--rk-line));
    background: var(--rk-surface-soft);
    color: var(--rk-ink);
  }

  #sb-activity .rk-activity-dismiss:focus-visible {
    outline: 3px solid color-mix(in srgb, var(--rk-emerald) 32%, transparent);
    outline-offset: 2px;
  }

  #sb-activity .rk-activity-dismiss svg {
    inline-size: 12px;
    block-size: 12px;
    stroke-width: 2;
  }
}

@media (min-width: 1780px) {
  #sb-activity.rk-activity-slot {
    inset-block-start: 184px;
    inset-inline-end: 30px;
  }

  #sb-activity .rk-activity,
  #sb-activity .rk-activity.has-art {
    grid-template-columns: 42px minmax(0, 1fr);
    grid-template-rows: auto auto;
    inline-size: 286px;
    block-size: auto;
    min-block-size: 104px;
    padding: 14px 15px;
    column-gap: 12px;
    row-gap: 9px;
    place-items: initial;
    place-content: normal;
    align-items: center;
    border-radius: 20px;
  }

  #sb-activity .rk-activity > .rk-activity-row {
    grid-column: 2;
    grid-row: 1;
    display: flex;
    min-inline-size: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }

  #sb-activity .rk-activity > .rk-activity-track {
    grid-column: 1 / -1;
    grid-row: 2;
    display: block;
    inline-size: 100%;
    block-size: 5px;
    margin: 0;
  }

  #sb-activity .rk-activity-copy { display: block; }

  #sb-activity .rk-activity-head {
    display: flex;
    min-inline-size: 0;
    flex-direction: row;
    align-items: center;
    gap: 7px;
    flex-wrap: nowrap;
  }

  #sb-activity .rk-activity-badge {
    padding: 2px 7px;
    font-size: 0.64rem;
    white-space: nowrap;
  }

  #sb-activity .rk-activity-title {
    min-inline-size: 0;
    overflow: hidden;
    font-size: 0.9rem;
    font-weight: 750;
    line-height: 1.25;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  #sb-activity .rk-activity-desc { display: none; }

  #sb-activity .rk-activity-meta {
    display: flex;
    margin-block-start: 5px;
    gap: 5px;
    overflow: hidden;
    font-size: 0.68rem;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  #sb-activity .rk-activity-state { margin: 0; }
  #sb-activity .rk-activity-figures { gap: 10px; }
  #sb-activity .rk-activity-sep { block-size: 24px; }
  #sb-activity .rk-activity-figure { align-items: flex-start; gap: 0; }
  #sb-activity .rk-activity-cap { font-size: 0.62rem; }
  #sb-activity .rk-activity-num { white-space: nowrap; }
  #sb-activity .rk-activity-figure b { font-size: 1rem; }
  #sb-activity .rk-activity-of { font-size: 0.68rem; }
  #sb-activity .rk-activity-done { font-size: 0.78rem; }

  #sb-activity .rk-activity-dismiss {
    inset-inline-start: auto;
    inset-inline-end: -9px;
  }

  #sb-activity .rk-activity-compact-badge.is-count {
    display: block;
    inset-block-start: 7px;
    inset-inline-start: 44px;
    inset-inline-end: auto;
  }
}

@media (min-width: 1024px) and (max-width: 1179px) {
  #sb-activity.rk-activity-slot { inset-inline-end: 8px; }

  #sb-activity .rk-activity,
  #sb-activity .rk-activity.has-art {
    inline-size: 48px;
    block-size: 48px;
    border-radius: 16px;
  }

  #sb-activity .rk-activity-trigger-icon {
    inline-size: 30px;
    block-size: 30px;
    border-radius: 10px;
  }
}

/* ── Home showcase (platform-curated sample books) ───────────────────────────────────────────────
   A compact shop-window in the bookshelf heading row. Platform samples are not user assets, so they
   must neither sit on the user's plank nor grow into a second empty shelf below it. The cover is the
   only vivid surface; the whole quiet-paper stage is now the action instead of adding another CTA. */

.rk-showcase-section[hidden] {
  display: none;
}

.rk-showcase-section {
  min-inline-size: 0;
  min-block-size: 80px;
  /* One curated book keeps this floating slot; every book after it stands ON the shelf instead
     (Andy 2026-08-19), so the slot is back to the width of a single card. */
  max-inline-size: min(164px, 34%);
  margin-inline-start: auto;
  visibility: visible;
  opacity: 1;
  transform: none;
  transform-origin: 100% 100%;
  transition: opacity 420ms 360ms ease-out, transform 480ms 360ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.rk-showcase-section.is-pending {
  visibility: hidden;
  opacity: 0;
  transform: translateY(10px) scale(0.97);
}

[dir='rtl'] .rk-showcase-section {
  transform-origin: 0 100%;
}

.rk-showcase-section.is-revealed {
  visibility: visible;
  opacity: 1;
  transform: none;
}

.rk-shelf-section .rk-section-header:has(.rk-showcase-section:not([hidden])) {
  align-items: center;
}

.rk-showcase-row {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-snap-type: inline proximity;
  scrollbar-width: none;
}

.rk-showcase-row::-webkit-scrollbar {
  display: none;
}

.rk-showcase-card {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 160px;
  block-size: 80px;
  min-block-size: 80px;
  padding: 0;
  overflow: visible;
  border: 0;
  background: transparent;
  box-shadow: none;
  color: inherit;
  text-decoration: none;
  isolation: isolate;
  cursor: pointer;
  scroll-snap-align: end;
  transition: transform 180ms ease-out;
}

.rk-showcase-card:hover {
  box-shadow: none;
}

.rk-showcase-card:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 3px;
}

.rk-showcase-card:active {
  transform: scale(0.98);
}

/* The stage tracks the enlarged card so the visible book, focus target and hit area stay aligned. */
.rk-showcase-stage {
  position: absolute;
  inset: 0;
  display: block;
  overflow: visible;
}

/* The book and the badge centre with auto margins (see below) — direction-agnostic and exact. The
   glow cannot: it is WIDER than the card it sits on, and auto margins on an over-constrained
   absolute box collapse to zero instead of centring. So it keeps the 50% + translateX trick and pays
   for it with an explicit RTL twin, because translateX is a PHYSICAL axis: in Arabic the untwinned
   rule threw the glow a full width past the logical edge (measured: 154px outside the viewport). */
.rk-showcase-glow {
  position: absolute;
  z-index: 0;
  left: 50%;
  inset-block-end: -4px;
  display: block;
  inline-size: 184px;
  block-size: auto;
  max-inline-size: none;
  opacity: 0.88;
  pointer-events: none;
  transform: translateX(-50%) scale(1);
  transform-origin: 50% 72%;
  transition: opacity 220ms ease-out, transform 380ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
}

/* The physical book is a GPT Image 2 cut-out derived from the LP reference. Its transparent page
   windows reveal live content below, while the raster shell carries the irregular arches, layered
   paper, cover rim, binding cap and contact shadow that CSS rectangles could only approximate. */
.rk-showcase-book {
  position: absolute;
  z-index: 2;
  inset-inline: 0;
  margin-inline: auto;
  inset-block-end: 0;
  display: block;
  flex: none;
  inline-size: 160px;
  block-size: 80px;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  transform-origin: 50% 72%;
  transition: transform 380ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
}

/* Each live image owns one shell window. The polygons trace the generated page arches and curved
   lower page edges; the opaque shell above hides the antialiasing seam at this tiny scale. */
.rk-showcase-page {
  position: absolute;
  z-index: 1;
  display: block;
  inset-block-start: 4%;
  inline-size: 41%;
  block-size: 86%;
  overflow: hidden;
  border: 0;
  background: var(--rk-paper-2);
}

/* PHYSICAL left/right, not logical: these two page images are pinned onto a photographed open book
   (`.rk-showcase-book-shell`), and a photograph does not mirror in Arabic. Logical insets swapped the
   pages under a shell that stayed put, which put the left page where the right one was drawn. */
.rk-showcase-page.is-left {
  left: 9%;
  clip-path: polygon(20% 7%, 65% 0, 90% 2%, 100% 10%, 100% 100%, 74% 91%, 54% 88%, 2% 96%, 10% 54%);
}

.rk-showcase-page.is-right {
  right: 9%;
  clip-path: polygon(0 10%, 10% 2%, 35% 0, 80% 7%, 90% 54%, 98% 96%, 46% 88%, 26% 91%, 0 100%);
}

.rk-showcase-page::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent 72%, rgba(38, 34, 26, 0.16));
  pointer-events: none;
}

.rk-showcase-page.is-right::after {
  background: linear-gradient(90deg, rgba(38, 34, 26, 0.16), transparent 28%);
}

.rk-showcase-page-art {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  max-inline-size: none;
}

.rk-showcase-book-shell {
  position: absolute;
  z-index: 3;
  inset: 0;
  display: block;
  inline-size: 100%;
  block-size: 100%;
  max-inline-size: none;
  object-fit: contain;
  pointer-events: none;
}

/* Physical too, and for the same reason as the pages: the sheen sweeps across a fixed photograph, and
   its `skewX` is physical already — a logical inset would have sent it the other way in Arabic while
   the skew stayed put. */
.rk-showcase-book-sheen {
  position: absolute;
  z-index: 4;
  inset-block: -22%;
  left: -36%;
  inline-size: 20%;
  block-size: 120%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.68), transparent);
  opacity: 0;
  transform: skewX(-18deg);
  pointer-events: none;
}

.rk-showcase-card:hover .rk-showcase-book {
  transform: translateY(-2px) scale(1.025);
}

.rk-showcase-card:hover .rk-showcase-book-sheen {
  animation: rkShowcaseSheen 720ms ease-out both;
}

.rk-showcase-card:hover .rk-showcase-glow {
  opacity: 1;
  transform: translateX(-50%) scale(1.08);
}

/* The RTL twins. Anything that centres the glow must mirror its X translation here — that is the
   price of centring an over-wide box with a physical transform. */
[dir='rtl'] .rk-showcase-glow {
  transform: translateX(50%) scale(1);
}

[dir='rtl'] .rk-showcase-card:hover .rk-showcase-glow {
  transform: translateX(50%) scale(1.08);
}

.rk-showcase-cover-link {
  display: block;
  inline-size: 54px;
  block-size: 68px;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: var(--rk-shadow-card);
}

.rk-showcase-cover-link:focus-visible,
.rk-showcase-format:focus-visible,
.rk-showcase-primary:focus-visible,
.rk-showcase-make:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.rk-showcase-cover {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.rk-showcase-cover.is-blank {
  display: grid;
  place-items: center;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
}

.rk-showcase-cover.is-blank svg {
  inline-size: 24px;
  block-size: 24px;
}

.rk-showcase-copy {
  min-inline-size: 0;
}

.rk-showcase-kicker {
  position: absolute;
  z-index: 4;
  inset-block-start: auto;
  inset-block-end: 2px;
  inset-inline: 0;
  margin-inline: auto;
  inline-size: fit-content;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 20px;
  padding: 3px 10px 4px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 42%, var(--rk-line));
  border-radius: 999px;
  background: var(--rk-surface);
  box-shadow: 0 5px 12px -9px rgba(43, 42, 38, 0.65);
  color: var(--rk-emerald-hover);
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 0.12em;
  line-height: 1;
  white-space: nowrap;
  transition: transform 360ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
}

.rk-showcase-card:hover .rk-showcase-kicker {
  transform: translateY(-2px);
}

@keyframes rkShowcaseSheen {
  0% { left: -36%; opacity: 0; }
  18% { opacity: 0.68; }
  100% { left: 118%; opacity: 0; }
}

.rk-showcase-title {
  margin: 0;
  overflow: hidden;
  color: var(--rk-ink);
  font-size: 15px;
  font-weight: 800;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rk-showcase-formats {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px 6px;
  margin-block-start: 4px;
  color: var(--rk-ink-muted);
  font-size: 12px;
  line-height: 1.25;
}

.rk-showcase-format {
  color: inherit;
  text-decoration: none;
  transition: color 140ms ease-out;
}

.rk-showcase-format:hover {
  color: var(--rk-emerald-hover);
}

.rk-showcase-ctas {
  display: flex;
  align-items: center;
  flex-direction: column;
  gap: 4px;
}

.rk-showcase-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 40px;
  max-inline-size: none;
  padding: 8px 15px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-size: 13px;
  font-weight: 800;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  grid-area: preview;
  align-self: center;
  transition: background-color 160ms ease-out;
}

.rk-showcase-primary:hover {
  background: var(--rk-emerald-hover);
}

.rk-showcase-primary-icon {
  display: inline-flex;
  flex: none;
  transform: rotate(-90deg);
}

.rk-showcase-primary-icon svg {
  inline-size: 14px;
  block-size: 14px;
}

[dir='rtl'] .rk-showcase-primary-icon {
  transform: rotate(90deg);
}

.rk-showcase-make {
  max-inline-size: 156px;
  overflow: hidden;
  color: var(--rk-ink-soft);
  font-size: 11px;
  line-height: 1.25;
  text-align: center;
  text-decoration: underline;
  text-overflow: ellipsis;
  text-underline-offset: 2px;
  white-space: nowrap;
  transition: color 140ms ease-out;
}

.rk-showcase-make:hover {
  color: var(--rk-emerald-hover);
}

@media (max-width: 1160px) {
  .rk-showcase-section {
    max-inline-size: min(164px, 34%);
  }

  .rk-showcase-card {
    inline-size: 160px;
  }
}

@media (max-width: 760px) {
  .rk-shelf-section .rk-section-header {
    align-items: stretch;
    flex-direction: column;
    gap: 8px;
  }

  .rk-showcase-section {
    inline-size: 100%;
    max-inline-size: none;
    margin-inline-start: 0;
  }

  .rk-showcase-card {
    inline-size: 160px;
    max-inline-size: 100%;
  }

  .rk-showcase-row {
    justify-content: flex-start;
  }
}

@media (max-width: 480px) {
  .rk-showcase-section {
    min-block-size: 73px;
  }

  .rk-showcase-card {
    inline-size: 142px;
    block-size: 73px;
    min-block-size: 73px;
  }

  .rk-showcase-book {
    inline-size: 142px;
    block-size: 71px;
    inset-block-end: 0;
  }

  .rk-showcase-glow {
    inline-size: 164px;
    inset-block-end: -3px;
  }

  .rk-showcase-kicker {
    inset-block-end: 1px;
    padding-inline: 8px;
    font-size: 7px;
  }

  .rk-showcase-cover-link {
    inline-size: 48px;
    block-size: 64px;
  }

  .rk-showcase-title {
    font-size: 14px;
  }

  .rk-showcase-formats {
    gap: 2px 5px;
    font-size: 11px;
  }

  .rk-showcase-primary {
    min-block-size: 40px;
    max-inline-size: none;
    padding-inline: 10px;
    font-size: 12px;
  }

  .rk-showcase-make {
    max-inline-size: 108px;
    font-size: 10px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rk-showcase-section {
    transition: none;
  }

  .rk-showcase-book {
    transition: none;
  }

  .rk-showcase-page {
    transition: none;
  }

  .rk-showcase-book-sheen {
    display: none;
  }

  .rk-showcase-card:hover .rk-showcase-kicker,
  .rk-showcase-card:hover .rk-showcase-book,
  .rk-showcase-card:hover .rk-showcase-glow {
    transition: none;
  }

  .shelf-pudding.is-thinking .shelf-pudding-thought {
    animation: none;
  }

  .shelf-pudding-replay-hint {
    transition: none;
    transform: none;
  }
}

/* Showcase reader modal. Modelled on .is-tutorials: a FIXED viewport onto a chrome-less embed, not a
   panel that grows with its content — the reader is a whole immersive page, and a panel sized to it
   would be taller than the screen with no way back to the close button. Larger than tutorials
   because a 3D book needs room to be a 3D book. */
.rk-modal-panel.is-showcase {
  inline-size: min(1240px, 100%);
  block-size: min(860px, calc(100vh - 48px));
  overflow: hidden;
  padding: 0;
  border-radius: 18px;
  background: var(--rk-paper);
}

/* Same reason as tutorials: the ops strip is fixed above the Studio canvas, so centre within the
   canvas rather than behind the strip. */
.rk-modal.is-showcase {
  inset-block-start: var(--rk-opsbar-h, 0px);
}

.rk-modal-panel.is-showcase .rk-modal-body {
  padding: 0;
  block-size: 100%;
  overflow: hidden;
}

.rk-showcase-frame {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
  background: var(--rk-paper);
}

/* The close button sits over the reader's own dark stage, so it needs its own ground to stay
   findable — the shared ghost treatment disappears against the 3D world. */
.rk-modal-panel.is-showcase .rk-modal-x {
  background: rgb(255 255 255 / 0.92);
  border-radius: 999px;
  box-shadow: 0 6px 18px -8px rgb(43 42 38 / 0.45);
}

@media (max-width: 680px) {
  .rk-modal-panel.is-showcase {
    block-size: 92vh;
    border-radius: 14px;
  }
}

/* Reader tabs — three ways of looking at ONE book. A segmented strip rather than three doors on the
   card: the card says "there is a sample here", and the choice of form belongs next to the thing it
   changes. Sits above the frame inside the modal's own rounded edge. */
.rk-modal-panel.is-showcase .rk-modal-body {
  display: flex;
  flex-direction: column;
}

.rk-showcase-tabs {
  display: flex;
  flex: none;
  gap: 4px;
  justify-content: center;
  padding: 10px 56px 10px 12px;
  border-block-end: 1px solid var(--rk-line);
  background: var(--rk-surface);
}

.rk-showcase-tab {
  min-block-size: 34px;
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 160ms ease-out, color 160ms ease-out;
}

.rk-showcase-tab:hover {
  color: var(--rk-ink);
  background: var(--rk-paper-2);
}

/* One emerald at a time — the tab you are on. */
.rk-showcase-tab.is-active {
  background: var(--rk-emerald);
  color: #fff;
}

.rk-showcase-tab:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

/* The silent warm-up frame (see startShowcasePreload). It has to be a REAL, laid-out frame — the
   flip reader composites pages against its own layout — but must reach nobody: clipped to nothing,
   inert to the pointer, behind the page, and out of the tab order (the element carries aria-hidden
   and tabindex="-1").

   Note it stays INSIDE the viewport rather than parked at left: -20000px. An off-screen cross-origin
   iframe gets its rendering throttled by the browser, and on the standalone prototype this frame is
   cross-origin (shell :3340, BFF :4310) — throttled, it would burn every per-page ceiling and warm
   nothing. clip-path costs nothing and keeps it honestly on-screen. */
.rk-showcase-preload {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  inline-size: 1024px;
  block-size: 720px;
  border: 0;
  clip-path: inset(50%);
  pointer-events: none;
  z-index: -1;
}

/* The frame takes whatever the tabs leave; without min-block-size:0 a flex child refuses to shrink
   and the iframe pushes the strip off the panel. */
.rk-modal-panel.is-showcase .rk-showcase-frame {
  flex: 1;
  min-block-size: 0;
}

@media (max-width: 680px) {
  .rk-showcase-tabs {
    padding: 8px 48px 8px 8px;
  }

  .rk-showcase-tab {
    min-block-size: 40px;
    padding: 0 12px;
    font-size: 12px;
  }
}

/* Final authority for the desktop task entry. Keep this after every historical activity-card
   override: the legacy in-flow card accumulated several later width/padding rules, and PC must not
   inherit any of them after the activity becomes a fixed entry. */
@media (min-width: 1024px) {
  #sb-activity.rk-activity-slot {
    position: fixed;
    z-index: 42;
    inset-block-start: 188px;
    inset-inline-end: 22px;
    display: block;
    inline-size: auto;
    margin: 0;
    pointer-events: none;
  }

  #sb-activity.rk-activity-slot[hidden] { display: none; }

  #sb-activity .rk-activity,
  #sb-activity .rk-activity.has-art {
    display: grid;
    grid-template-columns: none;
    grid-template-rows: none;
    inline-size: 56px;
    block-size: 56px;
    min-block-size: 0;
    padding: 0;
    gap: 0;
    place-items: center;
    place-content: center;
    border: 1px solid color-mix(in srgb, var(--rk-emerald) 25%, var(--rk-line));
    border-radius: 18px;
    background: var(--rk-surface);
    box-shadow: 0 12px 30px rgba(32, 91, 72, 0.16);
    pointer-events: auto;
  }

  #sb-activity .rk-activity > .rk-activity-art,
  #sb-activity .rk-activity > .rk-activity-row,
  #sb-activity .rk-activity > .rk-activity-track { display: none; }

  #sb-activity .rk-activity-dismiss {
    position: absolute;
    z-index: 2;
    inset-block-start: -9px;
    inset-inline-start: -9px;
    display: grid;
    inline-size: 22px;
    block-size: 22px;
    padding: 0;
    place-items: center;
    border: 1px solid var(--rk-line);
    border-radius: 50%;
    background: var(--rk-surface);
    box-shadow: 0 4px 12px rgba(32, 55, 47, 0.16);
    color: var(--rk-ink-muted);
    cursor: pointer;
    pointer-events: auto;
  }

  #sb-activity .rk-activity-dismiss:hover {
    border-color: color-mix(in srgb, var(--rk-ink-muted) 45%, var(--rk-line));
    background: var(--rk-surface-soft);
    color: var(--rk-ink);
  }

  #sb-activity .rk-activity-dismiss:focus-visible {
    outline: 3px solid color-mix(in srgb, var(--rk-emerald) 32%, transparent);
    outline-offset: 2px;
  }

  #sb-activity .rk-activity-dismiss svg {
    inline-size: 12px;
    block-size: 12px;
    stroke-width: 2;
  }
}

@media (min-width: 1780px) {
  #sb-activity.rk-activity-slot {
    inset-block-start: 184px;
    inset-inline-end: 30px;
  }

  #sb-activity .rk-activity,
  #sb-activity .rk-activity.has-art {
    grid-template-columns: 42px minmax(0, 1fr);
    grid-template-rows: auto auto;
    inline-size: 286px;
    block-size: auto;
    min-block-size: 104px;
    padding: 14px 15px;
    column-gap: 12px;
    row-gap: 9px;
    place-items: initial;
    place-content: normal;
    align-items: center;
    border-radius: 20px;
  }

  #sb-activity .rk-activity > .rk-activity-row {
    grid-column: 2;
    grid-row: 1;
    display: flex;
    min-inline-size: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }

  #sb-activity .rk-activity > .rk-activity-track {
    grid-column: 1 / -1;
    grid-row: 2;
    display: block;
    inline-size: 100%;
    block-size: 5px;
    margin: 0;
  }

  #sb-activity .rk-activity-copy { display: block; }

  #sb-activity .rk-activity-head {
    display: flex;
    min-inline-size: 0;
    flex-direction: row;
    align-items: center;
    gap: 7px;
    flex-wrap: nowrap;
  }

  #sb-activity .rk-activity-badge {
    padding: 2px 7px;
    font-size: 0.64rem;
    white-space: nowrap;
  }

  #sb-activity .rk-activity-title {
    min-inline-size: 0;
    overflow: hidden;
    font-size: 0.9rem;
    font-weight: 750;
    line-height: 1.25;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  #sb-activity .rk-activity-desc { display: none; }

  #sb-activity .rk-activity-meta {
    display: flex;
    margin-block-start: 5px;
    gap: 5px;
    overflow: hidden;
    font-size: 0.68rem;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  #sb-activity .rk-activity-state { margin: 0; }
  #sb-activity .rk-activity-figures { gap: 10px; }
  #sb-activity .rk-activity-sep { block-size: 24px; }
  #sb-activity .rk-activity-figure { align-items: flex-start; gap: 0; }
  #sb-activity .rk-activity-cap { font-size: 0.62rem; }
  #sb-activity .rk-activity-num { white-space: nowrap; }
  #sb-activity .rk-activity-figure b { font-size: 1rem; }
  #sb-activity .rk-activity-of { font-size: 0.68rem; }
  #sb-activity .rk-activity-done { font-size: 0.78rem; }

  #sb-activity .rk-activity-dismiss {
    inset-inline-start: auto;
    inset-inline-end: -9px;
  }

  #sb-activity .rk-activity-compact-badge.is-count {
    display: block;
    inset-block-start: 7px;
    inset-inline-start: 44px;
    inset-inline-end: auto;
  }
}

@media (min-width: 1024px) and (max-width: 1179px) {
  #sb-activity.rk-activity-slot { inset-inline-end: 8px; }

  #sb-activity .rk-activity,
  #sb-activity .rk-activity.has-art {
    inline-size: 48px;
    block-size: 48px;
    border-radius: 16px;
  }

  #sb-activity .rk-activity-trigger-icon {
    inline-size: 30px;
    block-size: 30px;
    border-radius: 10px;
  }
}

/* ── Show-case chrome (shared by all four product blocks) ─────────────────────────────────────────
   A sample sits inside a surface that otherwise shows the visitor's OWN work, so it has to declare
   itself. The badge borrows the bookshelf card's kicker DNA (emerald hairline, paper fill, tight
   caps) but is a normal flow element: the bookshelf pins its version to a 160px book spine, and
   these blocks are ordinary panels. */
.rk-sc-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 20px;
  padding: 3px 10px 4px;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 42%, var(--rk-line));
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
  line-height: 1;
  white-space: nowrap;
}

/* Bottom-right of its block, so it never competes with the block's own primary action. Ghost by
   default because a tutorial is an offer, not the next step. */
.rk-sc-tutorial {
  position: absolute;
  z-index: 5;
  inset-block-end: 12px;
  inset-inline-end: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-block-size: 32px;
  padding: 6px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-surface) 88%, transparent);
  color: var(--rk-ink-soft);
  font-size: 12px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}

.rk-sc-tutorial svg {
  inline-size: 14px;
  block-size: 14px;
  stroke-width: 1.6;
}

.rk-sc-tutorial:hover,
.rk-sc-tutorial:focus-visible {
  border-color: color-mix(in srgb, var(--rk-emerald) 45%, var(--rk-line));
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
}

/* Touch targets stay 40px on phones, where the button also has less room to sit in. */
@media (max-width: 640px) {
  .rk-sc-tutorial {
    inset-block-end: 10px;
    inset-inline-end: 10px;
    min-block-size: 40px;
    padding: 10px 14px;
  }
}

/* Animation has one optional tutorial offer. Keep it in the same lower-right position before and
   during sample playback, above the full-screen poster/layer, and use the product green so it is
   visible without competing with the centred play control. */
.anim-screen-empty.is-showcase > .rk-sc-tutorial.is-on-video-poster,
.rk-mshow-layer .rk-sc-tutorial.is-over-video {
  z-index: 26;
  inset-block-end: 16px;
  inset-inline-end: 16px;
  min-block-size: 44px;
  padding-inline: 16px;
  border-color: var(--rk-emerald);
  border-radius: 12px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  box-shadow: 0 10px 22px -14px color-mix(in srgb, var(--rk-emerald) 72%, transparent);
}

.anim-screen-empty.is-showcase > .rk-sc-tutorial.is-on-video-poster:hover,
.anim-screen-empty.is-showcase > .rk-sc-tutorial.is-on-video-poster:focus-visible,
.rk-mshow-layer .rk-sc-tutorial.is-over-video:hover,
.rk-mshow-layer .rk-sc-tutorial.is-over-video:focus-visible {
  border-color: var(--rk-emerald-hover);
  background: var(--rk-emerald-hover);
  color: var(--rk-surface);
}

/* The book reader has two equal exits. They live in a dedicated footer after the iframe rather than
   over the canvas, so switching between 3D / pop-up / read cannot move or duplicate them and the
   reader keeps every native control available. */
.rk-showcase-actions {
  position: static;
  z-index: auto;
  flex: none;
  box-sizing: border-box;
  inline-size: 100%;
  display: grid;
  grid-template-columns: repeat(2, 180px);
  justify-content: end;
  gap: 12px;
  padding: 12px 20px 14px;
  border-block-start: 1px solid var(--rk-line);
  background: var(--rk-surface);
}

.rk-showcase-reader-action,
.rk-modal-panel.is-showcase .rk-showcase-actions .rk-sc-tutorial {
  position: static;
  z-index: auto;
  display: inline-flex;
  inline-size: 180px;
  min-block-size: 44px;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 0 16px;
  border: 1px solid var(--rk-emerald);
  border-radius: 12px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  box-shadow: 0 8px 20px -12px color-mix(in srgb, var(--rk-emerald) 80%, transparent);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.35;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
}

.rk-showcase-reader-action svg,
.rk-modal-panel.is-showcase .rk-showcase-actions .rk-sc-tutorial svg {
  flex: none;
  inline-size: 16px;
  block-size: 16px;
  stroke-width: 1.8;
}

.rk-showcase-actions button span {
  display: block;
  min-inline-size: 0;
  overflow: hidden;
  padding-block: 2px;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rk-showcase-reader-action:hover,
.rk-showcase-reader-action:focus-visible,
.rk-modal-panel.is-showcase .rk-showcase-actions .rk-sc-tutorial:hover,
.rk-modal-panel.is-showcase .rk-showcase-actions .rk-sc-tutorial:focus-visible {
  border-color: var(--rk-emerald-hover);
  background: var(--rk-emerald-hover);
  color: var(--rk-surface);
  box-shadow: 0 10px 24px -12px color-mix(in srgb, var(--rk-emerald) 90%, transparent);
}

@media (max-width: 640px) {
  .rk-showcase-actions {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    padding: 10px;
  }

  .rk-showcase-reader-action,
  .rk-modal-panel.is-showcase .rk-showcase-actions .rk-sc-tutorial {
    inline-size: 100%;
    min-inline-size: 0;
    padding-inline: 10px;
    font-size: 12px;
  }
}

/* ── Media show case (animation TV + Kids Song stage) ─────────────────────────────────────────────
   The entry sits at the logical end of a section heading, so it must stay small enough not to
   compete with the heading and must never push the row taller. */
.rk-mshow-slot {
  margin-inline-start: auto;
  min-inline-size: 0;
}

.rk-mshow-entry {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  max-inline-size: 100%;
  padding: 6px 12px 6px 6px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  cursor: pointer;
  text-align: start;
  transition: border-color 160ms ease, transform 200ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
}

.rk-mshow-entry:hover,
.rk-mshow-entry:focus-visible {
  border-color: color-mix(in srgb, var(--rk-emerald) 45%, var(--rk-line));
  transform: translateY(-1px);
}

.rk-mshow-entry-art {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 56px;
  block-size: 34px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--rk-paper);
}

.rk-mshow-entry-art img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.rk-mshow-entry-play {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 22px;
  block-size: 22px;
  border-radius: 50%;
  background: rgb(255 255 255 / 0.86);
  color: var(--rk-emerald-hover);
}

.rk-mshow-entry-play svg {
  inline-size: 16px;
  block-size: 16px;
  stroke-width: 1.6;
}

.rk-mshow-entry-copy {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-inline-size: 0;
}

.rk-mshow-entry-title {
  overflow: hidden;
  color: var(--rk-ink-soft);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The sample plays as a layer over the player, so the visitor's own screen is handed straight back
   when they close it. */
.rk-mshow-layer {
  position: absolute;
  inset: 0;
  z-index: 25;
  background: #0b0b0c;
}

/* Absolutely placed rather than stretched by the layer: a grid-stretched child sized 100% overshoots
   its own track by the host screen's border width, and the video ended up 1px taller than the layer
   holding it (measured). Pinning to the layer's edges removes the arithmetic entirely. */
.rk-mshow-video {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  background: #0b0b0c;
}

.rk-mshow-layer-badge {
  position: absolute;
  z-index: 3;
  inset-block-start: 10px;
  inset-inline-start: 10px;
}

.rk-mshow-close {
  position: absolute;
  z-index: 3;
  inset-block-start: 8px;
  inset-inline-end: 8px;
  display: grid;
  place-items: center;
  inline-size: 32px;
  block-size: 32px;
  border: 0;
  border-radius: 999px;
  background: rgb(255 255 255 / 0.92);
  color: var(--rk-ink);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.rk-mshow-close:hover,
.rk-mshow-close:focus-visible {
  color: var(--rk-emerald-hover);
}

/* The Kids Song screen carries a 9px inner frame and its own glow overlay at z-index 10; the layer
   sits inside that frame and above the glow. */
.kids-mv-stage-screen .rk-mshow-layer {
  inset: 9px;
  z-index: 25;
  border-radius: 9px;
  overflow: hidden;
}

/* The hanging spotlights live in a higher stage stacking context than the screen. Raising the whole
   screen would erase the theatre framing, so centre only the badge in the clear space between the
   two lights while the sample is active. Logical insets keep the same result in RTL. */
.kids-mv-stage.is-media-showcase-active .rk-mshow-layer-badge {
  inset-inline: 0;
  inline-size: max-content;
  margin-inline: auto;
}

/* Kids MV gives its ordinary status and primary CTA explicit flex displays. Those author rules can
   override the HTML hidden state, so make the sample contract authoritative: while our film owns
   the stage, no project action survives in the apron. The shared player independently renders its
   tutorial button only when tutorials-modal.js has a real film for this product. */
.kids-mv-stage.is-media-showcase-active [data-media-showcase-project-only] {
  display: none !important;
}

.kids-mv-library-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

@media (max-width: 760px) {
  .rk-mshow-slot {
    margin-inline-start: 0;
    inline-size: 100%;
  }

  .rk-mshow-entry {
    min-block-size: 44px;
  }
}

/* ── A curated sample book standing ON the shelf ──────────────────────────────────────────────────
   It is a real book object, so the only new thing is the badge that keeps it honest about whose
   book it is. Pinned to the slot, not the book, so it does not scale with --rk-book-scale. */
.slot.is-showcase-slot {
  position: relative;
}

.shelf-showcase-badge {
  position: absolute;
  z-index: 5;
  inset-block-end: 8px;
  inset-inline: 0;
  margin-inline: auto;
  inline-size: fit-content;
  font-size: 8px;
  padding: 2px 7px 3px;
  pointer-events: none;
}

/* ── The sample as a card ON its workbench (television channel bar / Kids Song rail) ─────────────
   Same silhouette as the neighbouring cards so it sits in the row instead of floating above it;
   the badge is what separates it from the visitor's own work. */
.rk-mshow-card {
  position: relative;
  appearance: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: none;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--rk-ink);
  cursor: pointer;
  text-align: start;
}

.rk-mshow-card-art {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: 10px;
  background: var(--rk-paper);
  box-shadow: 0 10px 20px -14px rgb(43 42 38 / 0.6);
}

.rk-mshow-card-art img {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.rk-mshow-card-play {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 30px;
  block-size: 30px;
  border-radius: 50%;
  background: rgb(255 255 255 / 0.9);
  color: var(--rk-emerald-hover);
}

.rk-mshow-card-play svg {
  inline-size: 18px;
  block-size: 18px;
  stroke-width: 1.6;
}

.rk-mshow-card-badge {
  position: absolute;
  z-index: 3;
  inset-block-start: 6px;
  inset-inline-start: 6px;
  font-size: 8px;
  padding: 2px 6px 3px;
  pointer-events: none;
}

.rk-mshow-card-title {
  overflow: hidden;
  color: var(--rk-ink-soft);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Both hosts size their own cards — the television's channel bar is a grid with fixed tracks, the
   Kids Song rail a flex row of fixed-width cards — so the sample card fills the cell it is given
   rather than carrying sizes of its own. Hard-coded thumb sizes left it a small picture floating in
   a full-size cell (measured: 104×60 art inside a 257×208 track). */
.anim-channel-showcase,
.kids-mv-showcase-card {
  inline-size: 100%;
}

/* The poster is a video still, so 16:9 is its real shape — deriving the height from the width lets
   the card size itself in BOTH hosts. `block-size: 100%` here instead collapsed the card to 0×0 in
   the Kids Song rail, whose row has no definite height to inherit (measured). */
.anim-channel-showcase .rk-mshow-card-art,
.kids-mv-showcase-card .rk-mshow-card-art {
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 16 / 9;
}

.anim-channel-showcase .rk-mshow-card-title,
.kids-mv-showcase-card .rk-mshow-card-title {
  max-inline-size: 100%;
}

/* No visitor work means the sample becomes the workbench's primary screen, not a card below the
   fold. It remains a button (so playback still starts from an explicit user gesture) while its
   poster uses the full television / theatre screen. */
.anim-empty-showcase,
.kids-mv-empty-showcase {
  position: absolute;
  z-index: 20;
  display: block;
  box-sizing: border-box;
  overflow: hidden;
  background: #0b0b0c;
  color: white;
}

.anim-empty-showcase {
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
}

.kids-mv-empty-showcase {
  inset: 9px;
  inline-size: auto;
  block-size: auto;
  border-radius: 9px;
}

/* Keep both primary-screen badges centred. On the MV stage this also puts the badge in the clear
   space between the two spotlights instead of inheriting the generic card corner. */
.anim-empty-showcase .rk-mshow-card-badge,
.kids-mv-empty-showcase .rk-mshow-card-badge {
  inset-inline: 0;
  inline-size: max-content;
  margin-inline: auto;
}

.anim-empty-showcase .rk-mshow-card-art,
.kids-mv-empty-showcase .rk-mshow-card-art {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  border-radius: inherit;
}

.anim-empty-showcase .rk-mshow-card-play,
.kids-mv-empty-showcase .rk-mshow-card-play {
  inline-size: 64px;
  block-size: 64px;
  box-shadow: 0 10px 24px rgb(0 0 0 / 0.28);
}

.anim-empty-showcase .rk-mshow-card-play svg,
.kids-mv-empty-showcase .rk-mshow-card-play svg {
  inline-size: 30px;
  block-size: 30px;
}

.anim-empty-showcase .rk-mshow-card-title,
.kids-mv-empty-showcase .rk-mshow-card-title {
  position: absolute;
  z-index: 3;
  inset-block-start: 11px;
  inset-inline-start: 122px;
  max-inline-size: calc(100% - 190px);
  overflow: hidden;
  color: rgb(255 255 255 / 0.92);
  font-size: 13px;
  font-weight: 650;
  text-overflow: ellipsis;
  text-shadow: 0 1px 6px rgb(0 0 0 / 0.55);
  white-space: nowrap;
}

.rk-mshow-card:hover .rk-mshow-card-art,
.rk-mshow-card:focus-visible .rk-mshow-card-art {
  box-shadow: 0 12px 22px -12px rgb(43 42 38 / 0.7);
  outline: 2px solid color-mix(in srgb, var(--rk-emerald) 55%, transparent);
  outline-offset: 2px;
}

/* The film's name, for players whose own title sits under the show-case layer (the television).
   Paired with the badge on the same line so the pair reads as one label: what this is, and which
   film it is. */
.rk-mshow-layer-title {
  position: absolute;
  z-index: 3;
  inset-block-start: 12px;
  inset-inline-start: calc(10px + 108px);
  max-inline-size: calc(100% - 190px);
  overflow: hidden;
  color: rgb(255 255 255 / 0.92);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-shadow: 0 1px 6px rgb(0 0 0 / 0.55);
}

@media (max-width: 640px) {
  .rk-mshow-layer-title {
    inset-inline-start: 10px;
    inset-block-start: 38px;
    max-inline-size: calc(100% - 60px);
  }
}
