@import './subscription.css';

.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);
}

/* Laptop-height rails need a denser reading rhythm so every destination remains visible without
   turning the desktop rail into the mobile bottom bar. Hit targets stay comfortably above 44px. */
@media (min-width: 681px) and (max-height: 900px) {
  .rail-nav {
    gap: clamp(12px, 1.8vh, 16px);
    margin-block-start: 6px;
  }

  .rail-item {
    min-height: 68px;
    gap: 5px;
    padding-block: 7px;
  }
}

.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);
}
/* Rich announcements: the same semantic classes used by the admin preview and Classic/H5. */
:is(.rk-whatsnew-body, .rk-notify-detail-body) :is(.rk-ann-title-classic, .rk-ann-title-accent, .rk-ann-title-editorial) { margin: 28px 0 10px; font-size: 1.45rem; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-title-accent { color: var(--rk-emerald); border-inline-start: 3px solid currentColor; padding-inline-start: 12px; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-title-editorial { font-size: clamp(1.6rem, 4vw, 2rem); font-weight: 900; letter-spacing: -.035em; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-accent { color: var(--rk-emerald); font-weight: 700; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-highlight { color: inherit; background: var(--rk-emerald-soft); padding: .06em .16em; border-radius: 3px; box-decoration-break: clone; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-callout { margin-block: 20px; padding: 14px 18px; border-inline-start: 3px solid var(--rk-emerald); border-radius: 0 12px 12px 0; background: var(--rk-emerald-soft); overflow-wrap: anywhere; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-callout p { margin: 0; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-callout p + p { margin-block-start: 10px; }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-video { margin-block: 22px; overflow: hidden; border-radius: 14px; border: 1px solid var(--rk-line); }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-video video { display: block; width: 100%; max-height: 65vh; min-height: 160px; aspect-ratio: 16 / 9; object-fit: contain; background: var(--rk-ink); }
:is(.rk-whatsnew-body, .rk-notify-detail-body) .rk-ann-caption { margin: 0; padding: 10px 14px; font-size: .85rem; color: var(--rk-ink-muted); overflow-wrap: anywhere; }
.rk-whatsnew-body .rk-ann-media,
.rk-notify-detail-body .rk-ann-media { margin: 0 0 8px; }
.rk-whatsnew-body .rk-ann-media,
.rk-notify-detail-body .rk-ann-media,
.rk-whatsnew-body .rk-ann-figure,
.rk-notify-detail-body .rk-ann-figure,
.rk-ann-watermark-frame {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: var(--rk-radius);
}
.rk-whatsnew-body .rk-ann-media:has(img)::after,
.rk-notify-detail-body .rk-ann-media:has(img)::after,
.rk-whatsnew-body .rk-ann-figure:has(img)::after,
.rk-notify-detail-body .rk-ann-figure:has(img)::after,
.rk-ann-watermark-frame:has(img)::after,
.rk-showcase-watermark-overlay {
  content: 'ReadKidz';
  position: absolute;
  z-index: 2;
  inset-block-start: 50%;
  left: 50%;
  max-inline-size: 70%;
  color: #fff;
  font-size: 34px;
  font-weight: 700;
  line-height: 1.2;
  opacity: 0.24;
  pointer-events: none;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  white-space: nowrap;
  transform: translate(-50%, -50%) rotate(-24deg);
  transform-origin: center;
}
/* 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-whatsnew-body .rk-ann-figure {
  margin-block: 12px;
}
.rk-whatsnew-pop .rk-whatsnew-body .rk-ann-figure + .rk-ann-figure {
  margin-block-start: 20px;
}
.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-ann-figure img,
.rk-whatsnew-pop .rk-ann-media img {
  cursor: zoom-in;
}
.rk-whatsnew-pop .rk-ann-figure img:focus-visible,
.rk-whatsnew-pop .rk-ann-media img:focus-visible {
  outline: 3px solid var(--rk-emerald);
  outline-offset: 3px;
}
.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); }
/* Picker: titled header, one card per survey, reassurance line. Rows alternate emerald / amber via
   --sv-tone so a short list reads as distinct choices; amber is --rk-warn (the warm semantic token),
   NOT a second brand colour — everything below derives from those two so no literal hex appears. */
.rk-survey-pick { gap: 18px; }
.rk-survey-head { display: flex; align-items: center; gap: 14px; }
.rk-survey-head-icon {
  flex: none; display: grid; place-items: center; inline-size: 52px; block-size: 52px;
  border-radius: var(--rk-radius); background: var(--rk-emerald-soft); color: var(--rk-emerald);
}
.rk-survey-head-icon svg { inline-size: 26px; block-size: 26px; }
.rk-survey-head-copy { min-inline-size: 0; }
.rk-survey-head-title { margin: 0; font-size: 1.32rem; font-weight: 800; color: var(--rk-ink); }
.rk-survey-head-sub { margin: 4px 0 0; color: var(--rk-ink-soft); font-size: 0.95rem; }

.rk-survey-list { display: flex; flex-direction: column; gap: 12px; }
.rk-survey-list-item {
  --sv-tone: var(--rk-emerald);
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 16px;
  text-align: start; padding: 16px 18px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--sv-tone) 18%, var(--rk-line));
  border-radius: var(--rk-radius);
  background: color-mix(in srgb, var(--sv-tone) 5%, var(--rk-surface));
  transition: border-color 0.15s ease, background-color 0.15s ease, transform 0.15s ease;
}
.rk-survey-list-item.is-amber { --sv-tone: var(--rk-warn); }
.rk-survey-list-item:hover {
  border-color: color-mix(in srgb, var(--sv-tone) 45%, var(--rk-line));
  background: color-mix(in srgb, var(--sv-tone) 9%, var(--rk-surface));
}
.rk-survey-list-item:focus-visible { outline: 2px solid var(--sv-tone); outline-offset: 2px; }
.rk-survey-item-icon {
  flex: none; display: grid; place-items: center; inline-size: 52px; block-size: 52px;
  border-radius: var(--rk-radius); color: var(--sv-tone);
  background: color-mix(in srgb, var(--sv-tone) 14%, var(--rk-surface));
}
.rk-survey-item-icon svg { inline-size: 26px; block-size: 26px; }
.rk-survey-item-copy { display: flex; flex-direction: column; gap: 4px; min-inline-size: 0; }
.rk-survey-item-title { font-size: 1.02rem; font-weight: 700; color: var(--rk-ink); line-height: 1.35; }
/* Descriptions are authored for the survey's own intro screen and run long; one line here keeps the
   rows scannable, and the full text is the first thing the reader sees after picking. */
.rk-survey-item-desc {
  color: var(--rk-ink-soft); font-size: 0.88rem; line-height: 1.4;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1; overflow: hidden;
}
.rk-survey-item-badge {
  flex: none; padding: 5px 12px; border-radius: 999px; font-size: 0.8rem; font-weight: 700;
  color: color-mix(in srgb, var(--sv-tone) 78%, var(--rk-ink));
  background: color-mix(in srgb, var(--sv-tone) 14%, var(--rk-surface));
}
.rk-survey-item-badge.is-done {
  color: var(--rk-ink-muted); background: var(--rk-paper-2);
}
.rk-survey-item-go { flex: none; display: grid; place-items: center; color: var(--rk-ink-muted); }
.rk-survey-item-go svg { inline-size: 20px; block-size: 20px; }
.rk-survey-list-item:hover .rk-survey-item-go { color: var(--sv-tone); }
/* "Forward" is leftward in Arabic/Hebrew — the grid mirrors itself, the glyph does not. */
[dir="rtl"] .rk-survey-item-go svg { transform: scaleX(-1); }

.rk-survey-foot {
  display: flex; align-items: center; justify-content: center; gap: 7px; margin: 2px 0 0;
  color: var(--rk-ink-muted); font-size: 0.85rem;
}
.rk-survey-foot svg { flex: none; inline-size: 15px; block-size: 15px; }

@media (max-width: 560px) {
  .rk-survey-list-item { grid-template-columns: auto minmax(0, 1fr) auto; row-gap: 10px; padding: 14px; }
  /* The chevron is decorative once the whole card is the tap target — dropping it at this width
     buys the badge the room it needs to stay on the title's row. */
  .rk-survey-item-go { display: none; }
}
.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-opt-row { display: flex; align-items: center; gap: 10px; min-width: 0; }
/* Question illustration: a reference picture under the question text, never wider than the column. */
.rk-survey-q-img { display: block; max-width: 100%; max-height: 260px; border-radius: var(--rk-radius-sm); border: 1px solid var(--rk-line); object-fit: contain; background: var(--rk-surface); }
/* Illustrated options become picture cards laid out in a grid ("A style / B style"): the picture is
   the tap target, the radio underneath is the state. Selection is shown on the card's border so the
   reader sees which picture they picked even when the radio is scrolled under a thumb. */
.rk-survey-opts.has-img { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; align-items: start; }
.rk-survey-opts.has-img .rk-survey-other { grid-column: 1 / -1; }
.rk-survey-opt.is-pictured { flex-direction: column; align-items: stretch; gap: 8px; padding: 8px; border: 1.5px solid var(--rk-line); border-radius: var(--rk-radius-sm); background: var(--rk-surface); transition: border-color .15s ease, box-shadow .15s ease; }
/* Hover is a hint, selection is a statement: a hovered card must never look picked (screenshots and
   trackpad users both read the border as state), so hover only warms the line halfway. */
.rk-survey-opt.is-pictured:hover { border-color: color-mix(in srgb, var(--rk-emerald) 45%, var(--rk-line)); }
.rk-survey-opt.is-pictured:has(input:checked) { border-color: var(--rk-emerald); box-shadow: 0 0 0 2px color-mix(in srgb, var(--rk-emerald) 25%, transparent); }
.rk-survey-opt-card { display: block; position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: calc(var(--rk-radius-sm) - 2px); background: var(--rk-paper); }
/* "Look closer" control on a card: a separate button so zooming never counts as choosing. */
.rk-survey-opt-zoom {
  position: absolute; top: 6px; right: 6px; width: 28px; height: 28px; border-radius: 999px; border: none;
  background: rgba(255, 255, 255, 0.92); color: var(--rk-ink); display: grid; place-items: center;
  cursor: zoom-in; opacity: 0.85; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}
.rk-survey-opt-zoom:hover { opacity: 1; }
.rk-survey-opt-zoom svg { width: 15px; height: 15px; }
.rk-survey-q-img-btn { display: block; padding: 0; border: none; background: none; cursor: zoom-in; max-width: 100%; text-align: left; }
.rk-survey-lightbox {
  position: fixed; inset: 0; z-index: 130; display: grid; place-items: center; padding: 24px;
  background: rgba(30, 29, 26, 0.86); cursor: zoom-out;
}
.rk-survey-lightbox img { max-width: min(96vw, 1400px); max-height: 92vh; object-fit: contain; border-radius: var(--rk-radius-sm); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45); background: var(--rk-surface); }
.rk-survey-lightbox-close {
  position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border-radius: 999px; border: none;
  background: rgba(255, 255, 255, 0.14); color: #fff; display: grid; place-items: center; cursor: pointer;
}
.rk-survey-lightbox-close:hover { background: rgba(255, 255, 255, 0.26); }
.rk-survey-lightbox-close svg { width: 20px; height: 20px; }
.rk-survey-opt-card img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rk-survey-opt-noimg { display: block; width: 100%; height: 100%; background: repeating-linear-gradient(45deg, transparent 0 8px, var(--rk-line) 8px 9px); opacity: .5; }
.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;
  overflow: hidden;
  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;
  flex-wrap: wrap;
  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);
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.rk-plan-credits {
  font-weight: 800;
  color: var(--rk-ink);
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.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;
}

/* Modal/content loading keeps Pudding inside the surface instead of stacking a second full-screen
   scrim over it. The stable minimum height prevents the subscription and ledger dialogs from
   collapsing to a one-line ellipsis while their data resolves. */
.rk-pudding-loading {
  min-block-size: 210px;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 10px;
  padding: 24px;
  color: var(--rk-ink-soft);
  text-align: center;
}

.rk-pudding-loading-cat {
  inline-size: 105px;
  block-size: 105px;
  object-fit: contain;
}

.rk-pudding-loading-text {
  margin: 0;
  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-eta {
  margin: -2px 0 0;
  color: var(--rk-ink-muted);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.45;
}

.rk-app-loading-progress {
  width: min(100%, 520px);
  height: 6px;
  margin-top: 8px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--rk-paper-2);
}

.rk-app-loading-progress > i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
  transition: width 600ms ease-out;
}

.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);
}

/* Animation storyboard direction is a multi-minute production step. Use full-width rows so the
   five user-facing stages remain readable in every locale instead of becoming clipped pills. */
.rk-app-loading.is-storyboard .rk-app-loading-stages {
  box-sizing: border-box;
  grid-template-columns: minmax(0, 1fr);
  gap: 6px;
  width: min(100%, 520px);
  margin-top: 10px;
  padding: 8px;
  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-storyboard .rk-app-loading-stages li {
  min-height: 40px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--rk-radius);
  background: transparent;
}

.rk-app-loading.is-storyboard .rk-app-loading-stages li > b {
  font-size: 13px;
  text-overflow: clip;
  white-space: normal;
}

.rk-app-loading.is-storyboard .rk-app-loading-stages li.is-active {
  background: var(--rk-emerald-soft);
  box-shadow: none;
}

.rk-app-loading.is-storyboard .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;
}

@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,
  .rk-app-loading.is-storyboard .rk-app-loading-stages li.is-active > span { animation: none; }
  .rk-app-loading-progress > i { transition: 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%);
}

/* The survey dialog. Narrower than is-wide: the picker is a short column of cards and the form is a
   single column of questions — at 1040 both strand their content against a wall of padding. */
.rk-modal-panel.is-survey {
  inline-size: min(940px, 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;
}

/* While a subscription tab is resolving, let its Pudding state own all space below the persistent
   heading/account strip/tabs. This centres the mascot in the AVAILABLE content area rather than in
   a short 210px island directly under the tabs; ready content keeps the existing scrolling layout. */
.rk-modal-panel.is-wide:has(.rk-sub-tabs) .rk-modal-body:has(.rk-pudding-loading),
.rk-modal-panel.is-wide:has(.rk-sub-tabs) .rk-sub:has(> .rk-pudding-loading) {
  min-block-size: 0;
  block-size: 100%;
}

.rk-modal-panel.is-wide:has(.rk-sub-tabs) .rk-sub:has(> .rk-pudding-loading) {
  display: flex;
  flex-direction: column;
}

.rk-modal-panel.is-wide:has(.rk-sub-tabs) .rk-sub > .rk-pudding-loading {
  flex: 1 1 210px;
}

.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;
}

.rk-modal.is-storybook-trash-confirm .rk-modal-panel {
  inline-size: min(500px, 100%);
  padding: 38px 34px 30px;
  overflow: visible;
}

.storybook-trash-dialog {
  display: grid;
  justify-items: center;
  gap: 14px;
  text-align: center;
}

.storybook-trash-dialog h2,
.storybook-trash-dialog p { margin: 0; }
.storybook-trash-dialog h2 { padding-inline: 34px; font-size: clamp(1.35rem, 3vw, 1.75rem); }
.storybook-trash-dialog > p { max-inline-size: 38ch; color: var(--rk-ink-soft); line-height: 1.65; }

.storybook-trash-dialog-icon {
  display: grid;
  place-items: center;
  inline-size: 48px;
  block-size: 48px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-danger) 10%, var(--rk-surface));
  color: var(--rk-danger);
}

.storybook-trash-dialog-icon::before {
  content: '';
  inline-size: 15px;
  block-size: 18px;
  border: 2px solid currentColor;
  border-block-start: 0;
  border-radius: 0 0 3px 3px;
  transform: translateY(2px);
}

.storybook-trash-dialog-error:not([hidden]) {
  display: block;
  color: var(--rk-danger);
  font-weight: 700;
}

.storybook-trash-dialog-actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-block-start: 8px;
}

.storybook-trash-dialog-button {
  min-block-size: 44px;
  min-inline-size: 120px;
  padding-inline: 22px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font-weight: 800;
  cursor: pointer;
}

.storybook-trash-dialog-button.is-confirm {
  border-color: var(--rk-danger);
  background: var(--rk-danger);
  color: var(--rk-surface);
}
.storybook-trash-dialog-button:hover:not(:disabled) { transform: translateY(-1px); }
.storybook-trash-dialog-button:focus-visible { outline: 3px solid color-mix(in srgb, var(--rk-emerald) 28%, transparent); outline-offset: 2px; }
.storybook-trash-dialog-button:disabled { opacity: 0.56; cursor: wait; }

@media (max-width: 520px) {
  .rk-modal.is-storybook-trash-confirm .rk-modal-panel { padding: 34px 20px 22px; }
  .storybook-trash-dialog-actions { inline-size: 100%; }
  .storybook-trash-dialog-button { flex: 1 1 130px; }
}

@media (prefers-reduced-motion: reduce) {
  .storybook-trash-dialog-button:hover:not(:disabled) { transform: none; }
}

/* 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 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;
}

/* The "estimated credits" line on the animation / Kids MV subscription walls (2026-10-10). It is
   information, not a pitch: paper inset + hairline, no accent colour — emerald on this dialog belongs
   to the subscribe button alone. Tabular digits keep both ends of the range from jittering. */
.rk-credit-wall-estimate {
  margin: 0;
  max-inline-size: 410px;
  padding: 8px 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.6;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* The $3.99 single-work offer (docs/prd-pc-399-storybook-work-recovery.md). Same dialog as the
   credit wall; the 48-hour terms sit in the estimate's paper inset because they are information the
   author must read before paying, not a pitch — emerald stays on the buy button alone. */
.rk-wr-eyebrow {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.rk-wr-terms {
  display: grid;
  gap: 4px;
  max-inline-size: 410px;
  padding: 10px 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.6;
  text-align: start;
  overflow-wrap: anywhere;
}

.rk-wr-terms p {
  margin: 0;
}

.rk-wr-terms .rk-wr-terms-title {
  color: var(--rk-ink);
  font-weight: 600;
}

/* #683 copy test, arm 'b': what one book includes. Ink ticks, not emerald — the accent stays on the
   buy button alone; the list reads as facts, the terms inset below is unchanged. */
.rk-wr-pitch {
  display: grid;
  gap: 10px;
  max-inline-size: 410px;
  inline-size: 100%;
}

.rk-wr-pitch .rk-credit-wall-copy {
  margin: 0;
}

.rk-wr-points {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: start;
}

.rk-wr-points li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--rk-ink);
  font-size: 0.94rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.rk-wr-points svg {
  flex: 0 0 auto;
  inline-size: 16px;
  block-size: 16px;
  margin-block-start: 0.2em;
  color: var(--rk-ink-soft);
}

.rk-modal.is-credit-wall-prompt.is-animation-first-offer .rk-modal-panel.is-credit-wall {
  inline-size: min(560px, 100%);
  max-block-size: calc(100dvh - 48px);
  overflow-y: auto;
  padding: 32px 28px 24px;
}
.rk-afo select {
  display: block;
  width: 100%;
  min-height: 44px;
  margin: 0;
  background: var(--rk-surface);
  color: var(--rk-ink);
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  padding: 8px;
  font: inherit;
}
.rk-afo p { margin: 0; line-height: 1.6; font-size: .95rem; overflow-wrap: anywhere; }
.rk-afo [data-afo-terms] {
  font-weight: 500;
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  border-radius: var(--rk-radius-sm);
  color: var(--rk-ink);
  text-align: start;
}
.rk-afo .rk-afo-gets { inline-size: 100%; }
.rk-afo .rk-afo-gets li[hidden] { display: none; }
.rk-afo .rk-afo-gets svg { color: var(--rk-accent, currentColor); }
.rk-afo .rk-afo-gets strong { display: block; font-weight: 600; }
.rk-afo .rk-afo-gets strong + span { display: block; color: var(--rk-ink-soft); font-size: .88rem; }
.rk-afo .rk-afo-fine { font-size: .8rem; line-height: 1.5; color: var(--rk-ink-soft); text-align: center; }
.rk-afo .rk-credit-wall-actions { inline-size: 100%; }
/* Long localized pay labels wrap inside the pill instead of spilling past its edge. */
.rk-afo .rk-credit-wall-actions .rk-btn { block-size: auto; min-block-size: 44px; white-space: normal; padding-block: 8px; line-height: 1.3; }
.rk-afo-status {
  position: relative;
  max-width: 1120px;
  margin: 20px auto;
  padding: 16px;
  background: var(--rk-paper);
  color: var(--rk-ink);
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  box-shadow: var(--rk-shadow-card);
  font-size: 14px;
}
.rk-afo-status p { line-height: 1.55; margin: 0 0 8px; overflow-wrap: anywhere; }
.rk-afo-status .rk-btn { block-size: auto; min-block-size: 44px; white-space: normal; margin: 4px; }
.rk-afo-status[hidden] { display: none; }
[data-animation-offer-slot]:empty { display: none; }
.rk-afo-status[data-delivery="true"] { padding: 24px; margin-inline: auto; font-size: 16px; }
.rk-afo-status h2 { margin: 0 0 12px; font-size: 26px; }
.rk-afo-status [data-afo-heading] { margin-block-end: 20px; }
.rk-afo-status [data-afo-media] video { display: block; inline-size: 100%; max-block-size: 56dvh; background: var(--rk-ink); border-radius: var(--rk-radius-sm); }
.rk-afo-status [data-afo-production] ul { list-style: none; margin: 0; padding: 0; }
.rk-afo-status [data-afo-production] li { display: flex; justify-content: space-between; gap: 16px; padding-block: 12px; border-block-end: 1px solid var(--rk-line); }
.rk-afo-status .rk-afo-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-block: 20px 12px; }
.rk-afo-status [data-afo-controls] > p { text-align: center; color: var(--rk-ink-soft); }
.rk-afo-status [data-afo-action-error]:not([hidden]) { color: var(--rk-danger); }
.rk-afo-status [data-afo-billing] { border-block-start: 1px solid var(--rk-line); padding-block-start: 16px; margin-block-start: 16px; }
.rk-afo-pack { display: grid; gap: 16px; padding-block: 16px; }
.rk-afo-pack fieldset { border: 1px solid var(--rk-line); padding: 12px; min-inline-size: 0; }
.rk-afo-pack label { display: flex; align-items: center; gap: 8px; overflow-wrap: anywhere; }
.rk-afo-pack input { flex: none; min-inline-size: 20px; min-block-size: 20px; }
.rk-afo-pack-items { display: grid; grid-template-columns: repeat(auto-fit,minmax(min(220px,100%),1fr)); gap: 8px; max-block-size: 220px; overflow: auto; margin-block-start: 12px; }
.anim-cw:has(.rk-afo-status[data-delivery="true"]:not([hidden])) { height: auto; min-height: 100dvh; overflow: visible; }
.anim-cw:has(.rk-afo-status[data-delivery="true"]:not([hidden])) > .anim-cw-main,
.anim-cw:has(.rk-afo-status[data-delivery="true"]:not([hidden])) > .anim-cta-bar,
.anim-cw:has(.rk-afo-status[data-delivery="true"]:not([hidden])) .anim-steps { display: none; }
body:has(.rk-afo-status[data-delivery="true"]:not([hidden])) .rk-task-float { display: none; }
@media (max-width: 640px) {
  .rk-afo-status[data-delivery="true"] { margin: 12px; padding: 16px; }
  .rk-afo-status .rk-afo-actions { flex-direction: column; }
}

.rk-wr-error {
  margin: 0;
  max-inline-size: 410px;
  color: var(--rk-danger);
  font-size: 0.88rem;
  line-height: 1.5;
}

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

/* The buy label is a full sentence in most locales and wraps. The shared button height is fixed
   (block-size: 44px), which clipped the second line in Arabic and squeezed it in Chinese (self-test
   2026-10-15) — let this card's buttons grow with their label. */
.rk-wr-offer .rk-credit-wall-actions .rk-btn {
  block-size: auto;
  min-block-size: 46px;
  padding-block: 8px;
  line-height: 1.35;
}

/* A one-character last line (「品」 at phone width) reads like a typo; balance the title instead. */
.rk-wr-offer h2 {
  text-wrap: balance;
}

/* The paid $3.99 order's status on the story page (lib/work-recovery-follow.js): checking the payment,
   preparing the book, or why it is waiting. A quiet paper strip that never blocks the page — the
   author may read the board while the order starts the book. Below modals (z-index 100). */
.rk-wr-status {
  position: fixed;
  inset-block-start: 16px;
  inset-inline: 0;
  z-index: 95;
  display: flex;
  align-items: center;
  gap: 12px;
  inline-size: min(560px, calc(100vw - 32px));
  margin-inline: auto;
  padding: 12px 14px 12px 16px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
  color: var(--rk-ink);
  font-size: 0.9rem;
  line-height: 1.55;
}

.rk-wr-status-copy {
  display: grid;
  flex: 1;
  gap: 2px;
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

.rk-wr-status-copy span {
  color: var(--rk-ink-soft);
}

.rk-wr-status-spinner {
  flex: none;
  inline-size: 18px;
  block-size: 18px;
  border: 2px solid var(--rk-line);
  border-block-start-color: var(--rk-emerald);
  border-radius: 50%;
  animation: rk-spin 0.8s linear infinite;
}

.rk-wr-status-x {
  display: grid;
  flex: none;
  place-items: center;
  inline-size: 32px;
  block-size: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: pointer;
}

.rk-wr-status-x:hover {
  background: var(--rk-paper-2);
  color: var(--rk-ink);
}

.rk-wr-status-x svg {
  inline-size: 18px;
  block-size: 18px;
  stroke-width: 2;
}

@media (prefers-reduced-motion: reduce) {
  .rk-wr-status-spinner {
    animation: none;
  }
}

.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,
.rk-media-preview-image-frame {
  display: block;
  max-inline-size: none;
  max-block-size: none;
  transform-origin: center;
  user-select: none;
  will-change: transform;
}

.rk-media-preview-image-frame {
  position: relative;
  overflow: hidden;
}

.rk-media-preview-image-frame > img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  user-select: none;
}

.rk-media-preview-stage > img {
  object-fit: contain;
}

.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;
}

/* Footer with a note (credit-park film preview): note at the start edge, tools at the end edge. */
.rk-media-preview-footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-inline-size: 0;
}

.rk-media-preview-footer-end {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  min-inline-size: 0;
}

.rk-media-preview-note {
  min-inline-size: 0;
  overflow: hidden;
  color: var(--rk-ink-soft);
  font-size: 0.82rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Note + one wrapped line of explanation (credit-park preview). The actions keep their end edge. */
.rk-media-preview-note-block {
  display: grid;
  flex: 1 1 auto;
  gap: 3px;
  min-inline-size: 0;
}

.rk-media-preview-note-detail {
  color: var(--rk-ink-muted);
  font-size: 0.76rem;
  line-height: 1.45;
}

.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;
}

/* A phone cannot hold six preview controls on one row. Wrap them inside the footer instead of
   clipping the 1:1/maximize controls outside the modal; the stage simply gives the second row the
   small amount of height it needs. */
@media (max-width: 520px) {
  .rk-media-preview-footer { padding: 8px; }
  .rk-media-preview-tools { flex-wrap: wrap; }
  .rk-media-preview-tools output { min-inline-size: 100px; }
  .rk-media-preview-tools button {
    min-block-size: 38px;
    padding-inline: 9px;
    font-size: 13px;
  }
}

.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 recommended plan (Pro on an ordinary V3 open, or an explicit pick from public pricing). Same
   vocabulary as .rk-credit.is-selected in this overlay — accent border plus a soft outer 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. */
.rk-plan.is-picked {
  border-width: 2px;
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 4px var(--rk-emerald-soft), inset 0 0 0 1px var(--rk-emerald);
}

.rk-plan.is-picked .rk-plan-name {
  color: var(--rk-emerald-hover);
}

.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 — the custom group owns one compact, centered card.
   Keep the ordinary plan grid fluid; only this presentation-only sales card gets a readable cap. */
.rk-plan-custom {
  inline-size: min(100%, 760px);
  justify-self: center;
}

.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: var(--rk-amber);
    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; }
}

/* Inline status and action warnings in the subscription dialog. */
.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;
}

.rk-sub-gate[role="alert"] {
  --rk-sub-warning-ink: color-mix(in srgb, var(--rk-warn) 48%, var(--rk-ink));
  background: color-mix(in srgb, var(--rk-warn) 12%, var(--rk-surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rk-warn) 38%, var(--rk-surface));
  color: var(--rk-sub-warning-ink);
}

/* 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[role="alert"] .rk-sub-gate-act:hover {
  background: var(--rk-sub-warning-ink);
}

.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));
}
/* The $3.99 offer's 48-hour clock inside the same notice: tabular digits so it never jitters. */
.rk-autobook-copy .rk-wr-countdown {
  font-size: 1.05rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  opacity: 1;
}

/* 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);
}

/* 赠送行被提到价格下方时用的样式（2026-09-08）。和权益列表里那一行同一个暖色，
   但那边的选择器是 .rk-plan-hl li，这里是 <p>，匹配不到 —— 必须单列一条，
   否则提上来的那行会静默地变成和其它权益一样的灰色。 */
.rk-plan-perk.rk-plan-bonus-points {
  color: var(--rk-warn);
  font-weight: 900;
}

.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 spells out both the introductory and renewal prices. The warm
   value accent matches bonus points and keeps the limited first-month offer visually distinct. */
.rk-plan-first-month {
  margin: 0 0 2px;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--rk-warn);
}

.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-gap {
  margin-block-end: 16px;
  padding: 14px 16px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 48%, var(--rk-line));
  border-radius: var(--rk-radius-sm);
  background: color-mix(in srgb, var(--rk-warn) 9%, var(--rk-paper));
  color: var(--rk-ink);
}

.rk-credit-gap > strong {
  display: block;
  margin-block-end: 5px;
  font-family: var(--rk-font-display);
  font-size: 1rem;
}

.rk-credit-gap p {
  margin: 3px 0 0;
  font-size: 0.84rem;
  line-height: 1.45;
}

.rk-credit-gap-note {
  color: var(--rk-ink-muted);
}

.rk-credit-gap-warning {
  color: var(--rk-danger);
  font-weight: 800;
}

.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);
}

/* iOS Safari zooms the page into a focused field under 16px; touch screens get 16px. */
@media (hover: none) and (pointer: coarse) {
  .rk-pwd-input { font-size: 16px; }
}

.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 {
  position: relative;
  min-inline-size: 0;
  inline-size: 100%;
}

/* Textareas do not reliably paint text-overflow ellipses for native placeholders. This visual
   layer does, without participating in layout; the real placeholder remains on the textarea for
   accessibility and scroll-height measurement. */
.sb-composer-input::before {
  content: attr(data-placeholder);
  position: absolute;
  z-index: 1;
  inset-block-start: 4px;
  inset-inline: 2px;
  overflow: hidden;
  color: var(--rk-ink-muted);
  font-family: var(--rk-font-display);
  font-size: 1.3rem;
  line-height: 1.4;
  text-align: start;
  white-space: nowrap;
  text-overflow: ellipsis;
  pointer-events: none;
}

.sb-composer-input:has(textarea:not(:placeholder-shown))::before {
  content: none;
}

.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;
}

/* Keep an empty composer at the same one-line height across creation lanes and locales.
   The real textarea value switches back to wrapping immediately after the user starts typing,
   so authored prompts still grow normally up to the six-line cap in autoGrow(). */
.composer textarea:placeholder-shown {
  white-space: nowrap;
  overflow-x: hidden;
  text-overflow: ellipsis;
}

.composer textarea:not(:placeholder-shown) {
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.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: transparent;
  opacity: 1;
}

.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-cover-title { display: grid; gap: 8px; min-width: 0; font-weight: 700; }
.sb-one-click-cover-title input {
  width: 100%; min-width: 0; box-sizing: border-box; min-height: 44px;
  padding: 10px 12px; border: 1px solid var(--rk-line); border-radius: var(--rk-radius-sm);
  background: var(--rk-surface); color: var(--rk-ink); font: inherit; outline: none;
}
.sb-one-click-cover-title input:focus { border-color: var(--rk-emerald); }
.sb-one-click-dialog .sb-one-click-cover-title-hint { display: flex; align-items: center; gap: 6px; font-size: 0.875rem; }
.sb-one-click-cover-example { position: relative; display: inline-flex; flex: 0 0 auto; }
.sb-one-click-cover-example-trigger {
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px;
  padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--rk-ink-soft); cursor: help;
}
.sb-one-click-cover-example-trigger:hover,
.sb-one-click-cover-example-trigger:focus-visible { color: var(--rk-emerald); background: var(--rk-paper-2); }
.sb-one-click-cover-example-trigger:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.sb-one-click-cover-example-preview {
  position: absolute; z-index: 5; inset-inline-end: 0; bottom: 100%; padding-bottom: 8px;
  width: min(224px, 60vw, 32vh); visibility: hidden; opacity: 0; pointer-events: none;
}
.sb-one-click-cover-example-preview img {
  display: block; width: 100%; height: auto; aspect-ratio: 1; object-fit: contain;
  padding: 6px; box-sizing: border-box; border: 1px solid var(--rk-line); border-radius: var(--rk-radius-sm);
  background: var(--rk-surface); box-shadow: 0 8px 28px rgb(0 0 0 / 16%);
}
.sb-one-click-cover-example:hover .sb-one-click-cover-example-preview,
.sb-one-click-cover-example:focus-within .sb-one-click-cover-example-preview { visibility: visible; opacity: 1; pointer-events: auto; }

.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;
}

/* Waiting card stage list. The one-click estimate can sit behind a minutes-long free planning pass,
   and an anonymous bar for that long reads as a frozen page — these three rows say which pass is
   running and, once planning lands, what it actually found. */
.sb-one-click-steps {
  display: grid;
  gap: 10px;
  width: min(360px, 82vw);
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: start;
}

.sb-one-click-steps li {
  display: grid;
  grid-template-columns: 22px 1fr;
  align-items: start;
  gap: 10px;
  color: var(--rk-ink-soft);
  font-size: 0.92rem;
  line-height: 1.45;
}

.sb-one-click-step-mark {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
  font-size: 0.72rem;
  font-weight: 900;
}

.sb-one-click-steps li.is-done { color: var(--rk-ink); }

.sb-one-click-steps li.is-done .sb-one-click-step-mark {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.sb-one-click-steps li.is-active { color: var(--rk-ink); font-weight: 700; }

.sb-one-click-steps li.is-active .sb-one-click-step-mark {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
  color: var(--rk-paper);
}

.sb-one-click-steps li.is-todo { opacity: 0.62; }

.sb-one-click-step-text { display: grid; gap: 2px; }

.sb-one-click-step-text em {
  color: var(--rk-ink-soft);
  font-size: 0.82rem;
  font-style: normal;
  font-weight: 600;
}

.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 can take minutes, so the phase copy carries the precise
   state while this milestone bar provides calm visual movement. It never prints a made-up ETA or
   percentage: optional phases can be skipped, and only the server's named stages advance the fill. */
.sb-one-click-dialog.is-preparing .sb-one-click-stage {
  min-height: 1.6em;
  color: var(--rk-ink);
  font-weight: 600;
}

.sb-one-click-progress {
  width: min(420px, 86vw);
  height: 8px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--rk-progress-track, var(--rk-paper-2));
}

.sb-one-click-progress i {
  display: block;
  width: var(--sb-one-click-progress, 4%);
  height: 100%;
  border-radius: inherit;
  background: var(--rk-emerald);
  animation: sb-one-click-progress-pulse 1.3s ease-in-out infinite alternate;
  transition: width 420ms ease;
}

@keyframes sb-one-click-progress-pulse {
  from { opacity: 0.72; }
  to { opacity: 1; }
}

.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-breakdown .is-total {
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
  font-weight: 800;
}

.sb-one-click-funding {
  display: grid;
  gap: 12px;
  padding: 16px;
  border: 1px solid color-mix(in srgb, var(--rk-danger) 42%, var(--rk-line));
  border-radius: var(--rk-radius);
  background: color-mix(in srgb, var(--rk-danger) 7%, var(--rk-paper));
}

.sb-one-click-funding-lead {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  color: var(--rk-danger);
  font-weight: 800;
}

.sb-one-click-funding-lead strong {
  font-family: var(--rk-font-display);
  font-size: clamp(1.35rem, 3vw, 1.85rem);
  white-space: nowrap;
}

.sb-one-click-funding dl {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
}

.sb-one-click-funding dl > div {
  display: grid;
  gap: 3px;
  padding: 9px 11px;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
}

.sb-one-click-funding dt { color: var(--rk-ink-soft); font-size: 0.78rem; }
.sb-one-click-funding dd { margin: 0; color: var(--rk-ink); font-weight: 900; }
.sb-one-click-dialog .sb-one-click-funding p { color: var(--rk-danger); font-size: 0.84rem; font-weight: 700; }

.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-requote-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 16px;
  border: 1px solid color-mix(in srgb, var(--rk-warning, #a56b12) 28%, var(--rk-line));
  border-radius: 16px;
  background: color-mix(in srgb, var(--rk-warning, #a56b12) 9%, var(--rk-surface));
  color: var(--rk-ink);
  font-weight: 800;
}

.sb-one-click-requote-total strong {
  color: var(--rk-warning, #a56b12);
  font-size: 1.35rem;
  white-space: nowrap;
}

.sb-one-click-requote-toggle {
  justify-self: start;
  min-block-size: 40px;
}

.sb-one-click-requote-details {
  display: grid;
  gap: 10px;
}

.sb-one-click-requote-items {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 12px;
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  font-size: 0.86rem;
  line-height: 1.5;
  list-style: none;
}

.sb-one-click-requote-items li {
  display: grid;
  grid-template-columns: minmax(92px, auto) minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  min-block-size: 52px;
  padding-block: 10px;
  padding-inline: 12px 14px;
}

.sb-one-click-requote-items li + li { border-block-start: 1px solid var(--rk-line); }
.sb-one-click-requote-items li[hidden] { display: none; }

.sb-one-click-requote-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--rk-ink-soft);
  font-size: 0.78rem;
  font-weight: 800;
  white-space: nowrap;
}

.sb-one-click-requote-state > span,
.sb-one-click-requote-state > svg {
  inline-size: 16px;
  block-size: 16px;
  flex: 0 0 16px;
  border: 1.5px solid currentColor;
  border-radius: 50%;
}

.sb-one-click-requote-state > svg {
  fill: none;
  stroke: currentColor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 2;
}

.sb-one-click-requote-state.is-ready { color: var(--rk-emerald-hover); }
.sb-one-click-requote-state.is-in_flight { color: var(--rk-warn); }
.sb-one-click-requote-state.is-in_flight > span { border-inline-end-color: transparent; }

.sb-one-click-requote-item-copy { display: grid; gap: 2px; min-inline-size: 0; }
.sb-one-click-requote-item-copy strong { overflow-wrap: anywhere; }
.sb-one-click-requote-item-copy small { color: var(--rk-ink-soft); }

.sb-one-click-requote-unavailable,
.sb-one-click-requote-checking {
  margin: 0;
  padding-block: 11px;
  padding-inline: 13px;
  border-radius: 12px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
}

.sb-one-click-requote-unavailable.is-error,
.sb-one-click-requote-checking.is-error { color: var(--rk-danger); }

.sb-one-click-requote-checking.is-warning { color: var(--rk-warn); }

.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; }

.rk-modal.is-storybook-one-click-choice .sb-one-click-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.rk-modal.is-storybook-one-click-choice .sb-one-click-actions button {
  min-width: 0;
  width: 100%;
  block-size: auto;
  min-block-size: 44px;
  padding: 10px 12px;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* 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 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  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);
}

.rk-modal.is-storybook-one-click-quote .sb-one-click-actions button {
  inline-size: 100%;
}

@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%; }
  .sb-one-click-funding-lead { align-items: flex-start; flex-direction: column; gap: 4px; }
  .sb-one-click-requote-total { display: grid; gap: 6px; }
  .sb-one-click-requote-toggle { width: 100%; }
  .sb-one-click-requote-items li { grid-template-columns: 1fr; gap: 5px; }

  .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%; }
  .sb-one-click-progress i { animation: none; transition: none; }
}

.rk-modal.is-task-stop-confirm .rk-modal-panel.is-form {
  box-sizing: border-box;
  inline-size: min(500px, 100%);
  overflow: visible;
  padding: 38px 34px 30px;
}

.rk-task-stop-dialog {
  display: grid;
  justify-items: center;
  gap: 14px;
  text-align: center;
}

.rk-task-stop-dialog h2,
.rk-task-stop-dialog p { margin: 0; }

.rk-task-stop-dialog h2 {
  padding-inline: 34px;
  color: var(--rk-ink);
  font-size: clamp(1.35rem, 3vw, 1.75rem);
  line-height: 1.2;
}

.rk-task-stop-dialog > p:not(.rk-task-stop-dialog-progress, .rk-task-stop-dialog-error) {
  max-inline-size: 40ch;
  color: var(--rk-ink-soft);
  font-size: 1rem;
  line-height: 1.65;
}

.rk-task-stop-dialog-icon {
  display: grid;
  place-items: center;
  inline-size: 48px;
  block-size: 48px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-danger) 10%, var(--rk-surface));
  color: var(--rk-danger);
}

.rk-task-stop-dialog-icon svg {
  inline-size: 24px;
  block-size: 24px;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.7;
}

.rk-task-stop-dialog-progress {
  padding: 6px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.78rem;
  font-weight: 800;
  line-height: 1.2;
}

.rk-task-stop-dialog-error:not([hidden]) {
  display: block;
  max-inline-size: 40ch;
  padding: 9px 12px;
  border-radius: var(--rk-radius-sm);
  background: color-mix(in srgb, var(--rk-danger) 9%, var(--rk-surface));
  color: var(--rk-danger);
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1.45;
}

.rk-task-stop-dialog-actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  inline-size: 100%;
  margin-block-start: 8px;
}

.rk-task-stop-dialog-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-block-size: 44px;
  min-inline-size: 132px;
  padding-inline: 22px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: 800 0.88rem/1 var(--rk-font-body);
  cursor: pointer;
  transition: transform 160ms ease-out, background 160ms ease-out, border-color 160ms ease-out;
}

.rk-task-stop-dialog-button.is-keep:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--rk-emerald) 45%, var(--rk-line));
  background: var(--rk-emerald-soft);
}

.rk-task-stop-dialog-button.is-confirm {
  border-color: var(--rk-danger);
  background: var(--rk-danger);
  color: var(--rk-surface);
}

.rk-task-stop-dialog-button:hover:not(:disabled) { transform: translateY(-1px); }
.rk-task-stop-dialog-button:focus-visible { outline: 3px solid color-mix(in srgb, var(--rk-emerald) 28%, transparent); outline-offset: 2px; }
.rk-task-stop-dialog-button:disabled { opacity: 0.58; cursor: wait; }

.rk-modal.is-task-stop-confirm.is-submitting .rk-task-stop-dialog-button.is-confirm::before {
  content: '';
  inline-size: 14px;
  block-size: 14px;
  border: 2px solid color-mix(in srgb, var(--rk-surface) 45%, transparent);
  border-block-start-color: var(--rk-surface);
  border-radius: 50%;
  animation: rk-task-stop-spin 700ms linear infinite;
}

@keyframes rk-task-stop-spin { to { transform: rotate(1turn); } }

@media (max-width: 520px) {
  .rk-modal.is-task-stop-confirm .rk-modal-panel.is-form { padding: 34px 20px 22px; }
  .rk-task-stop-dialog h2 { padding-inline: 26px; }
  .rk-task-stop-dialog-actions { flex-direction: column; }
  .rk-task-stop-dialog-button { inline-size: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .rk-task-stop-dialog-button { transition: none; }
  .rk-task-stop-dialog-button:hover:not(:disabled) { transform: none; }
  .rk-modal.is-task-stop-confirm.is-submitting .rk-task-stop-dialog-button.is-confirm::before { animation: none; }
}

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

/* A one-click run belongs to the whole app, including the Director's full-screen preparation view.
   Keep its live card above that view so creators can see progress, leave the page, or act on a
   pause without waiting for the preparation overlay to disappear. Empty/stale docks stay behind. */
body:has(.rk-app-loading:not(.is-hidden)) .rk-task-float:has(.rk-task-float-run) {
  z-index: 2010;
}

/* A modal the float itself opened (its 「继续」 short of credits opens the plans wall) must not be
   covered by the float: it hid the fourth plan card (10-17 real run). Modals are removed on close,
   so the float is back on top the moment the modal goes. */
body:has(> .rk-modal) .rk-task-float {
  z-index: 90;
}

/* The same for an open editor card (asset / storyboard / video): its footer's main button sits in the bottom-right
   corner, right under the collapsed card — at 1024×768 「重画」 was entirely covered and a click landed on the float
   (Kids MV roadshow 1252, 10-18). The card is rendered only while open, so the float is back on top when it closes;
   19 is under every editor layer (in the canvas 20, phone 30, full-screen 80). */
body:has(.anim-ec-layer) .rk-task-float {
  z-index: 19;
}

.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-more {
  margin: 0;
  padding: 10px 15px;
  border-block-start: 1px solid var(--rk-line);
  color: var(--rk-ink-soft);
  font-size: 0.75rem;
  line-height: 1.4;
  text-align: center;
}

.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; flex-wrap: wrap; 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-actions [data-one-click-requote] { min-block-size: 40px; }
.rk-task-float-actions button:disabled { opacity: 0.58; cursor: wait; }

/* The pressed preview button keeps full strength and shows the spinner; the rest of the card greys. */
.rk-task-float-actions button.is-busy:disabled {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  opacity: 1;
}

.rk-task-float-busy-spinner {
  flex: none;
  inline-size: 12px;
  block-size: 12px;
  border: 2px solid var(--rk-line);
  border-top-color: var(--rk-emerald);
  border-radius: 50%;
  animation: rk-spin 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .rk-task-float-busy-spinner { animation-duration: 1600ms; }
}

.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-cancel-confirm-overlay {
  position: fixed;
  inset: 0;
  z-index: 1180;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgb(15 24 21 / 46%);
}

.rk-task-cancel-confirm {
  display: grid;
  gap: 14px;
  width: min(420px, calc(100vw - 32px));
  padding: 22px;
  border: 1px solid var(--rk-line);
  border-radius: 18px;
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
}

.rk-task-cancel-confirm h2 {
  margin: 0;
  color: var(--rk-ink);
  font: 800 1.05rem/1.3 var(--rk-font-body);
}

.rk-task-cancel-confirm p {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.55;
}

.rk-task-cancel-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-block-start: 4px;
}

.rk-task-cancel-confirm-actions button {
  min-height: 38px;
  padding-inline: 16px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  font: 800 0.8rem/1 var(--rk-font-body);
  cursor: pointer;
}

.rk-task-cancel-confirm-dismiss { background: var(--rk-surface); color: var(--rk-ink); }
.rk-task-cancel-confirm-submit { border-color: var(--rk-danger, #b4493d) !important; background: var(--rk-danger, #b4493d); color: #fff; }
.rk-task-cancel-confirm-actions button:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }

.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; }

@media (min-width: 641px) {
  .rk-task-float [data-one-click-drag] {
    cursor: move;
    touch-action: none;
    user-select: none;
  }

  .rk-task-float-panel > header [data-one-click-collapse] { cursor: pointer; }
}

.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; }
  .rk-task-cancel-confirm-overlay { align-items: end; padding: 14px; }
  .rk-task-cancel-confirm { width: 100%; }
}

@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;
  /* Shelf continuation slots rise to 20 on hover. A new intake choice must remain clickable
     when revealing this sheet moves a book or its hover bridge under the pointer. */
  z-index: 21;
  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); }
/* Chapter-series panels are modal work. Keep them above the global task float (780) and its
   completion reminder (790), while leaving the app-loading layer (2000) authoritative. */
.cs-panel-scrim { position: fixed; inset: 0; z-index: 800; 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-story-panel { width: min(900px, 100%); }
.cs-story-panel-body { margin-block-start: 24px; }
.cs-story-panel-body .cs-summary { padding-block-end: 22px; }
.cs-story-panel-body .cs-user-input p { display: block; overflow: visible; }
.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; inset-block-start: 18px; inset-inline-end: 18px; width: 40px; height: 40px; border: 1px solid var(--rk-line); border-radius: 50%; background: transparent; color: var(--rk-ink); 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-continuation-plan { width: min(680px, 100%); }
.cs-continuation-plan h2 { padding-inline-end: 44px; }
.cs-capacity-summary { margin-block: 16px; padding: 14px 16px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-surface); }
.cs-capacity-summary p, .cs-capacity-choice p { line-height: 1.65; overflow-wrap: anywhere; }
.cs-capacity-options { display: grid; gap: 10px; margin-block: 18px; }
.cs-capacity-option { display: grid; gap: 5px; width: 100%; padding: 14px 16px; text-align: start; color: var(--rk-ink); background: var(--rk-surface); border: 1px solid var(--rk-line); border-radius: 12px; cursor: pointer; }
.cs-capacity-option span, .cs-capacity-note { color: var(--rk-ink-soft); font-size: 13px; }
.cs-capacity-option:hover, .cs-capacity-option:focus-visible { border-color: var(--rk-emerald); outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.cs-capacity-option:disabled { opacity: .6; cursor: wait; }
.cs-capacity-reset { border: 0; background: transparent; color: var(--rk-emerald); padding: 8px 0 0; text-decoration: underline; cursor: pointer; }
.cs-capacity-option-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cs-capacity-option-head strong { color: var(--rk-ink); font-size: 16px; }
.cs-capacity-option.is-recommended { border-color: var(--rk-emerald); }
.cs-capacity-option .cs-capacity-badge { flex-shrink: 0; padding: 3px 9px; border-radius: 999px; color: var(--rk-emerald-hover); background: var(--rk-emerald-soft); font-size: 12px; font-weight: 700; }
.cs-capacity-outcome { margin-block-start: 4px; font-size: 18px; }
.cs-capacity-other { margin-block: 16px; }
.cs-capacity-other summary { width: fit-content; color: var(--rk-ink-soft); font-size: 14px; cursor: pointer; }
.cs-capacity-choice .cs-capacity-advice, .cs-capacity-choice .cs-capacity-footnote { padding: 0; border: 0; background: none; color: var(--rk-ink-soft); font-size: 12px; font-weight: 400; line-height: 1.55; }
/* "Group this poem into verses" card (worklist #548) — shared by the home sheet and the series panels
   (src/lib/stanza-format-card.js). Quiet paper: hairline frame, ink type; emerald only on the
   page's own primary button. */
.rk-stanza { display: grid; gap: 10px; width: min(640px, 100%); margin-inline: auto; text-align: start; }
.rk-stanza-title { margin: 0; }
.rk-stanza-compare { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.rk-stanza-compare li { display: flex; align-items: baseline; gap: 10px; padding: 10px 14px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-surface); color: var(--rk-ink-soft); line-height: 1.55; overflow-wrap: anywhere; }
.rk-stanza-compare li.is-after { border-color: var(--rk-emerald); background: var(--rk-emerald-soft); color: var(--rk-ink); }
.rk-stanza-tag { flex-shrink: 0; min-width: 4.5em; font-size: 12px; font-weight: 800; letter-spacing: .02em; color: var(--rk-ink); }
.rk-stanza-promise { margin: 0; color: var(--rk-ink-soft); font-size: 13px; line-height: 1.55; }
.rk-stanza-preview { display: grid; gap: 10px; margin: 0; padding: 12px 16px; max-height: 150px; overflow-y: auto; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-paper-2); }
.rk-stanza-preview figcaption { color: var(--rk-ink-soft); font-size: 12px; font-weight: 800; }
.rk-stanza-verse { margin: 0; white-space: pre-line; line-height: 1.6; overflow-wrap: anywhere; }
.rk-stanza-more { margin: 0; color: var(--rk-ink-muted); }
.rk-stanza-actions { justify-content: flex-start; }
.cs-panel .rk-stanza-actions { display: flex; flex-wrap: wrap; gap: 12px; }
/* The home sheet caps at 448px, so its preview stays short enough to keep both buttons in view;
   the series dialog has the room for a longer look. */
.cs-panel .rk-stanza-preview { max-height: 260px; }
@media (max-width: 720px) { .rk-stanza-compare li { flex-direction: column; gap: 2px; } .rk-stanza-actions button { flex: 1 1 150px; } }
.cs-continuation-input-hint { max-width: 56ch; margin-block: 4px 20px; }
.cs-continuation-mode { margin-block: 14px 0; padding: 11px 14px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-paper-2); font-weight: 750; }
.cs-continuation-plan-list { display: grid; gap: 10px; max-height: min(45vh, 420px); margin-block: 20px 0; padding: 0; overflow-y: auto; list-style: none; }
.cs-continuation-plan-row { display: grid; gap: 4px; min-width: 0; padding: 13px 15px; border: 1px solid var(--rk-line); border-radius: 13px; background: var(--rk-surface); }
.cs-continuation-plan-row > span { color: var(--rk-ink); font-weight: 800; overflow-wrap: anywhere; }
.cs-continuation-plan-row > small { color: var(--rk-ink-soft); line-height: 1.5; overflow-wrap: anywhere; }
.cs-continuation-correction { margin-block-start: 14px; }
.cs-continuation-correction button { min-height: 40px; padding-inline: 0; border: 0; background: transparent; color: var(--rk-emerald); font: inherit; font-weight: 800; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.cs-panel button:focus-visible, .cs-panel input:focus-visible, .cs-panel textarea:focus-visible, .cs-panel summary:focus-visible { outline: 3px solid color-mix(in srgb, var(--rk-emerald) 42%, transparent); outline-offset: 3px; }
.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; inset-block-end: -28px; flex-wrap: wrap; margin-inline: -20px; padding: 14px 20px 20px; background: var(--rk-paper); } .cs-panel-actions button { flex: 1 1 150px; } .cs-continuation-plan-list { max-height: 34vh; } }
.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; }
.cs-story-preview { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 18px; align-items: center; min-height: 0; padding-block: 10px 16px; }
.cs-story-preview p { min-width: 0; margin: 0; color: var(--rk-ink); font-size: .98rem; line-height: 1.65; white-space: pre-wrap; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.cs-story-full-trigger { display: inline-flex; align-items: center; justify-content: center; min-height: 40px; padding: 8px 14px; border: 1px solid var(--rk-line); border-radius: 10px; background: var(--rk-surface); color: var(--rk-emerald-hover); font: inherit; font-size: .86rem; font-weight: 800; cursor: pointer; }
.cs-story-full-trigger:hover { border-color: var(--rk-emerald); color: var(--rk-ink); }
.cs-story-full-trigger:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 3px; }
/* 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 { display: block; margin-block-start: 14px; padding: 14px 16px; 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; }
.cs-spread-body .cs-action-set + .cs-action-set { margin-block-start: 10px; padding-block-start: 10px; }
.cs-spread-body .cs-action-label { margin-block-end: 8px; }

/* Desktop splits the right-hand page into a compact story preview plus a non-scrolling action footer.
   Full prose belongs to the dialog: turning the shallow remainder into a nested scrollport made the
   story technically present but practically unreadable. 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: hidden;
  }
  .cs-page.is-single.is-spread .cs-spread-story {
    flex: 1 0 66px;
    min-block-size: 66px;
    overflow: hidden;
  }
  .cs-page.is-single.is-spread .cs-actions { flex: none; order: initial; display: block; }
}

/* 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); }
  /* Reading panes keep their own block layout at every width — neither footer may inherit the
     generic two-column action grid. In the standalone spread each action set contains its own
     button/hint columns, so splitting the SETS again leaves the hint column at zero pixels. */
  .cs-stage-reading .cs-actions { display: block; order: initial; }
  .cs-spread-body .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; }
  .cs-spread-body .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;
  }
}
@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-story-preview { grid-template-columns: 1fr; gap: 12px; }
  .cs-story-full-trigger { width: 100%; }
  .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-pro-dims .sb-dim-label:not(.anim-dim-inline-label) { inline-size: 76px; }
#anim-pro-dims .anim-quality-label { display: inline-flex; align-items: center; gap: 4px; }
.anim-quality-info {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  inline-size: 18px;
  block-size: 18px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: help;
}
.anim-quality-info:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-quality-info .sb-lane-tip {
  left: auto;
  right: auto;
  inset-inline-start: -8px;
  transform: none;
}
.anim-quality-info:hover .sb-lane-tip,
.anim-quality-info:focus .sb-lane-tip { opacity: 1; visibility: visible; }

#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;
}

/* ── PC home ops popup (lib/ops-popup.js; Kim 2026-10-27, design option B) ──────────────────────
   Image on top, copy below, one full-width emerald action and a quiet "later". The picture gives
   way on short laptop screens (315px down to 200px, by flex-shrink against the panel's max height)
   so the whole dialog fits one viewport whatever the copy length; the copy and the button never
   shrink. Only a screen too short even for the 200px picture falls back to scrolling the panel. */
.rk-modal-panel.is-ops-popup {
  display: flex;
  flex-direction: column;
  inline-size: min(560px, 100%);
  max-block-size: calc(100vh - 48px);
  padding: 0;
  overflow: hidden auto;
}

.rk-modal-panel.is-ops-popup:focus {
  outline: none;
}

.rk-modal-panel.is-ops-popup .rk-modal-body,
.rk-ops-popup {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-block-size: 0;
}

.rk-modal-panel.is-ops-popup .rk-modal-x {
  inline-size: 40px;
  block-size: 40px;
  border: 1px solid var(--rk-line);
  background: rgb(255 255 255 / 94%);
  color: var(--rk-ink);
}

.rk-modal-panel.is-ops-popup .rk-modal-x:hover {
  background: #fff;
}

.rk-ops-popup-media {
  flex: 0 1 315px;
  min-block-size: 200px;
  background: var(--rk-paper-2);
}

.rk-ops-popup-media img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.rk-ops-popup-body {
  display: flex;
  flex: none;
  flex-direction: column;
  padding: 30px 36px 24px;
}

.rk-ops-popup-title {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 30px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--rk-ink);
}

.rk-ops-popup-detail {
  margin: 10px 0 0;
  font-size: 17px;
  line-height: 1.55;
  color: var(--rk-ink-soft);
}

.rk-ops-popup-clock {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-block-start: 18px;
  font-size: 14px;
  color: var(--rk-ink-muted);
}

.rk-ops-popup-hms {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.rk-ops-popup-hms i {
  font-style: normal;
}

.rk-ops-popup-pill {
  padding: 4px 8px;
  border-radius: 8px;
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  /* Tabular figures, same reason as the strip: the digits must not twitch the row every second. */
  font-variant-numeric: tabular-nums;
  font-size: 15px;
  font-weight: 700;
}

.rk-ops-popup-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  min-block-size: 52px;
  margin-block-start: 24px;
  padding: 0 24px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-size: 17px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  transition: background 140ms ease-out;
}

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

.rk-ops-popup-cta:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px var(--rk-focus-ring);
}

.rk-ops-popup-later {
  min-block-size: 44px;
  margin-block-start: 6px;
  border: 0;
  background: transparent;
  color: var(--rk-ink-soft);
  font: inherit;
  font-size: 15px;
  cursor: pointer;
}

.rk-ops-popup-later:hover {
  color: var(--rk-ink);
}

/* ── 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);
}

.rk-dunning-actions,
.rk-dunning-confirm {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-inline-start: auto;
}

.rk-dunning-actions .rk-dunning-cta {
  margin-inline-start: 0;
}

.rk-dunning-cancel {
  flex: none;
  padding: 6px 10px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  font-size: 0.88rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 140ms ease-out, color 140ms ease-out;
}

.rk-dunning-cancel:hover {
  background: color-mix(in srgb, var(--rk-warn) 12%, var(--rk-surface));
  color: var(--rk-ink);
}

.rk-dunning-confirm-text {
  color: var(--rk-danger, #b3261e);
  font-weight: 600;
  font-size: 0.88rem;
  white-space: nowrap;
}

.rk-dunning-yes,
.rk-dunning-keep {
  flex: none;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--rk-surface);
  font-weight: 600;
  font-size: 0.88rem;
  cursor: pointer;
  white-space: nowrap;
  transition: background 140ms ease-out;
}

.rk-dunning-yes {
  border: 1px solid color-mix(in srgb, var(--rk-danger, #b3261e) 55%, var(--rk-line));
  color: var(--rk-danger, #b3261e);
}

.rk-dunning-yes:hover {
  background: color-mix(in srgb, var(--rk-danger, #b3261e) 8%, var(--rk-surface));
}

.rk-dunning-yes:disabled {
  opacity: 0.6;
  cursor: default;
}

.rk-dunning-keep {
  border: 1px solid color-mix(in srgb, var(--rk-warn) 55%, var(--rk-line));
  color: var(--rk-warn);
}

.rk-dunning-keep:hover {
  background: color-mix(in srgb, var(--rk-warn) 12%, var(--rk-surface));
}

@media (max-width: 720px) {
  .rk-dunning-bar {
    flex-wrap: wrap;
  }

  .rk-dunning-cta {
    margin-inline-start: 0;
  }

  .rk-dunning-actions,
  .rk-dunning-confirm {
    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 240px;
}

.shelf-row.is-empty {
  justify-content: flex-start;
  padding-inline-start: clamp(72px, 7.5vw, 142px);
}

.slot {
  position: relative;
  perspective: 900px;
  flex: none;
}

.shelf-book-delete,
.shelf-book-publication {
  position: absolute;
  z-index: 24;
  inset-block-start: -18px;
  inset-inline-end: -18px;
  display: grid;
  place-items: center;
  inline-size: 40px;
  block-size: 40px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--rk-danger) 30%, var(--rk-line));
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-surface) 94%, transparent);
  color: var(--rk-danger);
  box-shadow: 0 8px 22px -14px color-mix(in srgb, var(--rk-ink) 48%, transparent);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateY(4px) scale(0.94);
  transition: opacity 150ms ease-out, transform 150ms ease-out, border-color 150ms ease-out, background 150ms ease-out;
}

.shelf-book-publication {
  inset-inline: -18px auto;
  border-color: color-mix(in srgb, var(--rk-emerald) 34%, var(--rk-line));
  color: var(--rk-emerald-hover);
}
.shelf-book-delete svg,
.shelf-book-publication svg { inline-size: 18px; block-size: 18px; }
.slot:hover > .shelf-book-delete,
.slot:hover > .shelf-book-publication,
.slot:focus-within > .shelf-book-delete,
.slot:focus-within > .shelf-book-publication,
.shelf-book-delete:focus-visible {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
.shelf-book-publication:focus-visible {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
.shelf-book-delete:hover { border-color: var(--rk-danger); background: var(--rk-surface); }
.shelf-book-publication:hover { border-color: var(--rk-emerald); background: var(--rk-surface); }
.shelf-book-publication.is-pending { border-color: var(--rk-line); color: var(--rk-ink-soft); }
.shelf-book-publication.is-live { border-color: color-mix(in srgb, var(--rk-emerald) 34%, var(--rk-line)); color: var(--rk-emerald-hover); }
.shelf-book-publication.is-rejected,
.shelf-book-publication.is-takenDown { border-color: color-mix(in srgb, var(--rk-danger) 38%, var(--rk-line)); color: var(--rk-danger); }
.shelf-book-delete:focus-visible { outline: 3px solid color-mix(in srgb, var(--rk-danger) 28%, transparent); outline-offset: 2px; }
.shelf-book-publication:focus-visible { outline: 3px solid color-mix(in srgb, var(--rk-emerald) 28%, transparent); outline-offset: 2px; }

/* Focusing the destructive control must not also open the book's continuation popover. */
.slot:has(> .shelf-book-delete:focus-visible) .book-continuation,
.slot:has(> .shelf-book-publication:focus-visible) .book-continuation {
  opacity: 0;
  pointer-events: none;
}

@media (hover: none) and (pointer: coarse) {
  .shelf-book-delete,
  .shelf-book-publication {
    opacity: 1;
    pointer-events: auto;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .shelf-book-delete,
  .shelf-book-publication { transition: 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);
  }
}

/* A touch surface has no stable hover/focus path for an absolutely positioned shelf popover. Keep
   that dormant copy out of layout and scroll-overflow calculations; app.js moves it into the fixed
   scrim and adds is-touch-sheet only after the author taps the book. */
@media (hover: none) {
  .book-continuation:not(.is-touch-sheet) {
    display: none;
  }
}

.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.is-print {
  border-color: color-mix(in srgb, var(--rk-print-action) 82%, var(--rk-line));
  background: var(--rk-print-action);
  color: var(--rk-surface);
}
.book-continuation-action.is-print:hover {
  border-color: color-mix(in srgb, var(--rk-print-action) 88%, var(--rk-ink));
  background: color-mix(in srgb, var(--rk-print-action) 88%, var(--rk-ink));
}
.book-continuation-action.is-print:focus-visible {
  outline-color: color-mix(in srgb, var(--rk-print-action) 30%, transparent);
}
.book-continuation-action.is-print-preview {
  border-color: var(--rk-print-action);
  background: var(--rk-surface);
  color: var(--rk-print-action);
}
.book-continuation-action.is-print-preview:hover {
  border-color: color-mix(in srgb, var(--rk-print-action) 88%, var(--rk-ink));
  background: color-mix(in srgb, var(--rk-print-action) 10%, var(--rk-surface));
}
.book-continuation-action.is-print-preview:focus-visible {
  outline-color: color-mix(in srgb, var(--rk-print-action) 30%, transparent);
}
.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 {
  display: block;
  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; }
}

/* The home shelf owns only the viewport host; the existing React print-order dialog remains the
   single form, pricing and payment implementation inside the frame. Keep the host outside #app so
   the page can be inert while Radix retains a complete focus trap inside the embedded document. */
body.is-shelf-print-order-open {
  overflow: hidden;
  overscroll-behavior: none;
}

.shelf-print-order-host {
  position: fixed;
  inset: 0;
  z-index: 220;
  overflow: hidden;
  background: transparent;
}

.shelf-print-order-frame {
  position: absolute;
  z-index: 1;
  inset: 0;
  display: block;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
  background: transparent;
}

.shelf-print-order-loading {
  position: absolute;
  z-index: 2;
  inset: 0;
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--rk-paper) 88%, transparent);
  pointer-events: none;
  transition: opacity 160ms ease-out, visibility 160ms ease-out;
}

.shelf-print-order-loading.is-error {
  pointer-events: auto;
  background: color-mix(in srgb, var(--rk-paper) 96%, transparent);
}

.shelf-print-order-error {
  display: grid;
  justify-items: center;
  inline-size: min(420px, calc(100vw - 48px));
  padding: 28px;
  border: 1px solid var(--rk-line);
  border-radius: 18px;
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
  color: var(--rk-ink);
  text-align: center;
}

.shelf-print-order-error strong {
  font-size: 18px;
  line-height: 1.35;
}

.shelf-print-order-error span {
  margin-block-start: 8px;
  color: var(--rk-ink-soft);
  font-size: 14px;
  line-height: 1.6;
}

.shelf-print-order-retry {
  min-block-size: 44px;
  margin-block-start: 18px;
  padding-inline: 22px;
  border: 1px solid var(--rk-emerald);
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.shelf-print-order-retry:hover {
  border-color: var(--rk-emerald-hover);
  background: var(--rk-emerald-hover);
}

.shelf-print-order-retry:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 3px;
}

.shelf-print-order-host.is-load-error .shelf-print-order-frame {
  visibility: hidden;
}

.shelf-print-order-spinner {
  inline-size: 38px;
  block-size: 38px;
  border: 3px solid var(--rk-emerald-soft);
  border-block-start-color: var(--rk-emerald);
  border-radius: 50%;
  animation: shelf-print-order-spin 760ms linear infinite;
}

.shelf-print-order-host-close {
  position: fixed;
  z-index: 3;
  inset-block-start: max(16px, env(safe-area-inset-top));
  inset-inline-end: max(16px, env(safe-area-inset-right));
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  box-shadow: var(--rk-shadow-panel);
  cursor: pointer;
  transition: border-color 160ms ease-out, background 160ms ease-out, color 160ms ease-out, opacity 160ms ease-out, visibility 160ms ease-out;
}

.shelf-print-order-host-close:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.shelf-print-order-host-close:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 3px;
}

.shelf-print-order-host-close svg {
  inline-size: 20px;
  block-size: 20px;
  stroke-width: 1.8;
}

.shelf-print-order-host.is-ready .shelf-print-order-loading,
.shelf-print-order-host.is-ready .shelf-print-order-host-close {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}

@keyframes shelf-print-order-spin {
  to { transform: rotate(1turn); }
}

@media (max-width: 720px) {
  .shelf-print-order-host-close {
    inset-block-start: max(12px, env(safe-area-inset-top));
    inset-inline-end: max(12px, env(safe-area-inset-right));
  }
}

@media (prefers-reduced-motion: reduce) {
  .shelf-print-order-loading,
  .shelf-print-order-host-close { transition: none; }
  .shelf-print-order-spinner { 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[hidden] {
  display: none;
}

.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,
.continue-card video {
  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 220px;
  }
}

@media (max-width: 1280px) {
  .shelf-stage {
    --rk-book-scale: 0.78;
  }

  .shelf-row {
    padding-inline: 36px 200px;
  }
}

@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 340px;
  }

  .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;
    max-inline-size: 100%;
  }

  .composer textarea {
    order: 3;
    flex-basis: 100%;
    font-size: 1.08rem;
  }

  .sb-composer-toolbar {
    inline-size: 100%;
    min-inline-size: 0;
    flex-wrap: wrap;
  }

  .sb-tools {
    inline-size: 100%;
    min-inline-size: 0;
    max-inline-size: 100%;
    flex: 1 1 100%;
    justify-content: flex-end;
    flex-wrap: wrap;
    margin-inline-start: 0;
  }

  .sb-one-click-switch {
    min-inline-size: 0;
    max-inline-size: 100%;
    white-space: normal;
  }

  .sb-one-click-switch > span:last-child {
    min-inline-size: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .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 170px;
  }

  .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;
  }

  .shelf-print-promo {
    --rk-print-promo-w: 154px;
    inset-inline-end: 0;
  }

  .rk-print-promo-title {
    font-size: 11.5px;
  }

  .rk-print-promo-copy {
    display: none;
  }

  .rk-print-promo-cta {
    min-block-size: 40px;
    font-size: 10px;
  }

  .continue-card {
    grid-template-columns: 88px minmax(0, 1fr) auto;
    block-size: 120px;
  }

  .continue-card img,
  .continue-card video,
  .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;
  justify-content: center;
  min-height: 46px;
  /* An author background is enough to stop Blink painting the native button FACE, but
     not its border: the pill still computed `1.6px outset black` and drew a dark rim
     that the ghost twin beside it does not have. Same declaration as .rk-btn-primary. */
  appearance: none;
  border: 1px solid transparent;
  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);
}

.sb-empty-cta:disabled,
.sb-empty-cta:disabled:hover {
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  color: var(--rk-ink-muted);
  box-shadow: none;
  opacity: 1;
  cursor: not-allowed;
}

/* 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;
  overflow-wrap: anywhere;
  border-radius: 8px;
  transition: background 220ms ease-out;
}

.gn-story-meta {
  display: grid;
  gap: 10px;
  margin: 0 0 24px;
  padding-block: 14px;
  border-block: 1px solid var(--rk-line);
}

.gn-story-meta-row {
  display: grid;
  grid-template-columns: minmax(72px, auto) minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}

.gn-story-meta-row dt {
  color: var(--rk-ink-muted);
  font-size: 0.82rem;
  font-weight: 800;
  line-height: 1.65;
}

.gn-story-meta-row dd {
  min-width: 0;
  margin: 0;
  color: var(--rk-ink-soft);
  line-height: 1.65;
  overflow-wrap: anywhere;
}

@media (max-width: 640px) {
  .gn-story-meta-row {
    grid-template-columns: 1fr;
    gap: 2px;
  }
}

.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;
  }
}

/* 故事定稿锁的说明卡（docs/prd-v3-story-edit-lock.md）。一个禁用的输入框旁边什么都不写，读起来
   像 bug —— 而这扇门恰恰是作者自己打不开的那种，所以解释是必需品。语气按纸感皮肤走：低对比的
   纸底 + 细线，不是警告横幅。 */
.sb-story-lock-note {
  flex: none;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 22px 10px;
  padding: 12px 14px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
  color: var(--rk-ink);
}

.sb-story-lock-icon {
  flex: none;
  display: inline-flex;
  margin-block-start: 1px;
  color: var(--rk-ink-soft);
}

.sb-story-lock-icon svg { width: 16px; height: 16px; }

.sb-story-lock-copy strong {
  display: block;
  font-size: 14px;
  line-height: 1.45;
}

.sb-story-lock-copy p {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--rk-ink-soft);
}

/* 锁上之后头像和输入框整体退到背景里：还看得见这里曾经能说话，但不再邀请点击。 */
.sb-refine-bar.is-locked { opacity: 0.65; }
.sb-refine-bar.is-locked .sb-refine-form { background: var(--rk-paper-2); }

.sb-refine-bar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  border-block-start: 1px solid var(--rk-line);
}

.sb-story-lock {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 16px 22px;
  border-block-start: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
}

.sb-story-lock p {
  margin: 0;
  color: var(--rk-ink-muted);
  font-size: 0.9rem;
  line-height: 1.55;
}

.sb-story-lock-open {
  flex: none;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 18px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-weight: 700;
  text-decoration: none;
}

.sb-story-lock-open:hover,
.sb-story-lock-open:focus-visible {
  background: var(--rk-emerald-hover);
  outline: none;
}

@media (max-width: 640px) {
  .sb-story-lock {
    align-items: stretch;
    flex-direction: column;
  }

  .sb-story-lock-open {
    align-self: flex-start;
  }
}

.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;
}

/* `display` is not decoration here. The ring is usually a FLEX ITEM — .sb-vt-checking, .sb-vt-image-state,
   .sb-as-chat-send and friends are all flex — and a flex item is blockified, so it gets its 16px box for
   free. Put the same span inside a control that is merely a block container (a <button>, whose own
   children are laid out inline) and the box is gone: width and height do not apply to a non-replaced
   inline element, and all that survives is 3.2px of border — a hairline standing exactly where the
   button's label used to be. That is what the storybook board's 「开始制作绘本」 looked like mid-handoff
   (sxy 走查 2026-09-04 图1). Owning the display here fixes every such host at once and changes nothing
   in a flex or grid parent, where the computed value is blockified regardless. */
.spinner-sm {
  display: inline-block;
  vertical-align: middle;
  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;
}

.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;
}

.sb-cast-bind-role {
  min-block-size: 40px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 0;
  padding-inline: 7px;
  background: transparent;
  color: var(--rk-emerald-hover);
  font: inherit;
  font-size: 0.75rem;
  font-weight: 800;
  line-height: 1.25;
  text-align: start;
  cursor: pointer;
}

.sb-cast-bind-role svg {
  inline-size: 15px;
  block-size: 15px;
  stroke-width: 1.8;
}

.sb-cast-bind-role:hover:not(:disabled) {
  color: var(--rk-emerald);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.sb-cast-bind-role:focus-visible,
.sb-cast-bind-lock button:focus-visible {
  border-radius: 6px;
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.sb-cast-bind-role:disabled {
  color: var(--rk-ink-muted);
  cursor: default;
}

.sb-cast-bind-lock {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 8px 10px;
  align-items: start;
  margin-block-start: 9px;
  padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--rk-amber) 32%, var(--rk-line));
  border-radius: 12px;
  background: color-mix(in srgb, var(--rk-amber) 8%, var(--rk-surface));
  color: var(--rk-ink-soft);
}

.sb-cast-bind-lock > span svg {
  inline-size: 17px;
  block-size: 17px;
  color: var(--rk-amber);
}

.sb-cast-bind-lock p {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
}

.sb-cast-bind-lock button {
  grid-column: 2;
  justify-self: start;
  min-block-size: 40px;
  border: 0;
  padding: 0;
  background: transparent;
  color: var(--rk-emerald-hover);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 850;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.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-pill {
    width: 100%;
  }

  .sb-cast-copy {
    flex: 1;
  }

  .sb-cast-bind-role {
    flex: none;
  }

  .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;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-block-end: 12px;
}

/* One prominent catalogue-size marker shared by Picture Book, Animation, Comic and Kids MV.
   It belongs to the metadata row, not the pager: paging says where you are, this says how much
   choice exists. Logical auto margin keeps it at the far edge in both LTR and RTL. */
.sb-style-count {
  display: inline-flex;
  align-items: center;
  min-block-size: 38px;
  margin-inline-start: auto;
  padding-inline: 16px;
  border: 1px solid var(--rk-emerald);
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  font-size: 1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
}

/* ⓘ 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;
}

/* ── Style shelf: one row of seven, one screen (sxy 2026-09-05; picture book first, then rolled out) ──
   Opt-in via the .sb-style-shelf-row marker on the step container — .sb-style-* is shared with Animation, Comic and
   Kids MV, which keep their own layouts.

   The exhibit row (scene 16:9 + character 3:4 + a 340px meta column) and the shelf row (seven 3:4
   cards) are ONE block with ONE width, so their left edges align on every viewport instead of by
   accident at 1920px. Everything follows the hero height H:
     hero width  = 2.528·H + 12          (16/9 + 3/4 at height H, plus the 12px gap)
     block width = hero width + 32 + 340 (gap + meta column; 340 fits "MIDJOURNEY NIJI 7" + info + count on one line)
     card width  = (block width − 6·10) / 7
     shelf       = card·4/3 + caption 36 + page count row 43 (count 22 + two 6px grid gaps + 3px track + 6px margin)
     total       = H + 22 + shelf + chrome 58 + CTA lane 24  ≈ 1.4815·H + 245
   H is the largest value that fits the viewport height, capped by 45vh, 480px and the stage width.
   The normal block stays on one screen and is centred vertically. If a product adds more metadata
   than the hero can hold, that product must let the workbench scroll instead of overlapping the
   shelf. Twelve-per-page used to wrap to 7 + 5 and the second row was cut off at laptop heights. */
@media (min-width: 1021px) {
  .sb-style-shelf-row {
    --sb-style-stage-w: 1360px;
    /* The pager pills overhang the block by 60px each side, so the block itself stays inside
       100vw − 120 — plus 20px of slack, because 100vw counts a vertical scrollbar the host may show
       and an exact fit is what makes one appear (animation, 1656px laptop, 2026-09-05). */
    --sb-style-stage: min(100vw - 140px, var(--sb-style-stage-w));
    --sb-style-caption-h: 36px;
    --sb-style-count-h: 43px;
    --sb-style-chrome-h: 58px;
    --sb-style-cta-lane: 24px;
    --sb-style-exhibit-gap: 22px;
    /* Module-specific chrome inside the step (a search row, a non-floating CTA block) adds to this. */
    --sb-style-extra-h: 0px;
    --sb-style-hero-fit: calc((100dvh - var(--rk-opsbar-h, 0px) - 245px - var(--sb-style-extra-h)) / 1.4815);
    --sb-style-hero-by-width: calc((var(--sb-style-stage) - 384px) / 2.528);
    --sb-style-hero-h: clamp(240px, min(var(--sb-style-hero-fit), 45vh, var(--sb-style-hero-by-width)), 480px);
    --sb-style-block-w: calc(var(--sb-style-hero-h) * 2.528 + 384px);
    --sb-style-card-w: calc((var(--sb-style-block-w) - 60px) / 7);
    height: calc(100dvh - var(--rk-opsbar-h, 0px));
    min-height: 0;
    gap: 12px;
    overflow: hidden;
  }

  /* The CTA floats over the shelf edge now; the old 92px reservation was what starved the exhibit. */
  .sb-style-shelf-row.has-cta {
    padding-block-end: 0;
  }

  .sb-style-shelf-row .sb-style-workbench {
    display: grid;
    grid-template-rows: auto auto;
    row-gap: var(--sb-style-exhibit-gap);
    align-content: center;
    justify-items: center;
    min-height: 0;
    height: 100%;
    padding-block-end: var(--sb-style-cta-lane);
  }

  .sb-style-shelf-row .sb-style-focus {
    width: var(--sb-style-block-w);
    grid-template-columns: auto minmax(0, 1fr);
    /* The row is exactly the hero height, so a note appearing or vanishing in the meta column can
       never change the block height and bounce the whole page. */
    grid-template-rows: var(--sb-style-hero-h);
    padding-inline: 0;
  }

  /* Picture books can show three optional rows together: character-derived style, locked-style
     guidance and the Midjourney partnership line. On a laptop that stack can be taller than the
     image-driven row. Let this product's row grow to its real content height and give the workbench
     the bounded overflow; otherwise the next shelf row paints over the final note. Other products
     keep the shared one-screen geometry until they opt into the same content shape. */
  .sb-storybook-style-step.sb-style-shelf-row .sb-style-workbench {
    /* Auto tracks can shrink the focus below its wrapped metadata even when its inner row grows. */
    grid-template-rows: max-content max-content;
    align-content: safe center;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    scrollbar-width: thin;
  }

  .sb-storybook-style-step.sb-style-shelf-row .sb-style-focus {
    grid-template-rows: minmax(var(--sb-style-hero-h), max-content);
  }

  .sb-style-shelf-row .sb-style-hero2 {
    height: var(--sb-style-hero-h);
    min-height: 240px;
  }

  .sb-style-shelf-row .sb-style-engine {
    white-space: nowrap;
  }

  /* The model-info tooltip is 320px wide and, hidden or not, still counts toward the host's
     scrollable overflow. Left-anchored at the ⓘ it ran 7px past .anim-cw-main on a 1656px laptop
     (2026-09-05), which drew a horizontal scrollbar whose height then drew a vertical one. Anchor it
     to its END so it opens over the hero instead of off the edge. */
  .sb-style-shelf-row .sb-style-tip,
  .sb-style-shelf-row .anim-style-model-tip {
    inset-inline-start: auto;
    inset-inline-end: -8px;
  }

  .sb-style-shelf-row .sb-style-meta {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 0;
  }

  /* The +120px assumes the tall 48px pager pills with a 12px gap on each side — every module that
     mounts the shelf gets the same pills, so the block arithmetic holds everywhere. */
  .sb-style-shelf-row .sb-style-grid-shell {
    width: calc(var(--sb-style-block-w) + 120px);
    grid-template-columns: 48px minmax(0, 1fr) 48px;
    gap: 12px;
    align-self: auto;
    margin-block-start: 0;
  }

  .sb-style-shelf-row .sb-style-page-nav {
    align-self: center;
    width: 48px;
    height: 104px;
    margin-block-start: 0;
    border-radius: 999px;
  }

  .sb-style-shelf-row .sb-style-grid {
    grid-template-columns: repeat(7, var(--sb-style-card-w));
    justify-content: start;
    gap: 10px;
  }

  .sb-style-shelf-row .sb-style-thumb-caption {
    box-sizing: border-box;
    height: var(--sb-style-caption-h);
  }

  .sb-style-shelf-row .sb-style-page-count {
    box-sizing: border-box;
    min-height: calc(var(--sb-style-count-h) - 6px);
  }

  /* Centre the tall pager pills on the CARD row, not on cards + page count. */
  .sb-style-shelf-row .sb-style-page-nav {
    transform: translateY(calc(var(--sb-style-count-h) / -2));
  }

  /* Page position lives at the END of the shelf — the floating CTA sits at the centre and must never
     cover it. A short track under the count shows where page N sits among the 18. */
  .sb-style-shelf-row .sb-style-page-count {
    margin: 0;
    min-height: 22px;
    line-height: 22px;
    text-align: end;
    font-size: 0.9rem;
    color: var(--rk-ink-muted);
  }

  .sb-style-shelf-row .sb-style-page-track {
    position: relative;
    justify-self: end;
    width: calc(var(--sb-style-card-w) * 2 + 10px);
    height: 3px;
    margin-block-start: 6px;
    border-radius: 999px;
    background: var(--rk-line);
    cursor: pointer;
    touch-action: none;
    outline: none;
  }

  /* The visible bar stays 3px so the row arithmetic holds, but the hit area is a 20px lane —
     click anywhere on it to jump, hold and drag to scrub (sxy 2026-09-15). */
  .sb-style-shelf-row .sb-style-page-track::before {
    content: "";
    position: absolute;
    inset-block: -9px;
    inset-inline: -6px;
  }

  .sb-style-shelf-row .sb-style-page-track:hover,
  .sb-style-shelf-row .sb-style-page-track.is-scrubbing {
    background: color-mix(in srgb, var(--rk-line) 60%, var(--rk-ink-muted));
  }

  .sb-style-shelf-row .sb-style-page-thumb {
    position: absolute;
    inset-block: 0;
    border-radius: 999px;
    background: var(--rk-emerald);
    transition: inset-inline-start 200ms ease-out;
  }

  .sb-style-shelf-row .sb-style-page-track:hover .sb-style-page-thumb,
  .sb-style-shelf-row .sb-style-page-track.is-scrubbing .sb-style-page-thumb {
    background: var(--rk-emerald-hover);
  }

  .sb-style-shelf-row .sb-style-page-track.is-scrubbing .sb-style-page-thumb {
    transition: none;
  }

  /* While scrubbing, the target page floats above the thumb — the count row itself only catches up
     once the shelf settles. */
  .sb-style-shelf-row .sb-style-page-thumb::after {
    content: attr(data-page);
    position: absolute;
    inset-block-end: 10px;
    left: 50%;
    transform: translateX(-50%) translateY(4px);
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--rk-ink);
    color: var(--rk-paper);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.04em;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 120ms ease-out, transform 120ms ease-out;
  }

  .sb-style-shelf-row .sb-style-page-track.is-scrubbing .sb-style-page-thumb::after {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
  }

  html.sb-style-scrubbing .sb-style-shelf-row,
  html.sb-style-scrubbing .sb-style-shelf-row * {
    user-select: none;
    cursor: pointer;
  }

  /* Floating CTA: 10px lower than the shared row so it hugs the caption edge. No hover fade —
     the block arithmetic keeps a clear lane under the shelf, so the button never covers a card
     (sxy 2026-09-05 dropped the fade after seeing it live). */
  .sb-style-shelf-row .sb-style-cta-row {
    inset-block-end: 12px;
  }

  /* The meta column stretches the confirm button to its full 300px; keep the label centred. */
  .sb-style-shelf-row .sb-style-use {
    justify-content: center;
  }
}

/* Laptop heights: the 300px meta column has to hold badge row + name + description + button +
   one or two notes inside a ~300px hero. Tighter type, same content. */
@media (min-width: 1021px) and (max-height: 760px) {
  .sb-style-shelf-row .sb-style-name {
    margin-block-end: 6px;
    font-size: 1.4rem;
  }

  .sb-style-shelf-row .sb-style-desc {
    margin-block-end: 14px;
    font-size: 0.92rem;
  }

  .sb-style-shelf-row .sb-style-badge-row {
    margin-block-end: 8px;
  }

  .sb-style-shelf-row .sb-style-partner {
    margin-block-start: 10px;
    padding-block-start: 8px;
  }

  .sb-style-shelf-row .sb-style-locked-note,
  .sb-style-shelf-row .sb-style-change-error {
    margin-block-start: 8px;
    font-size: 0.84rem;
  }
}

/* Tablet band: the seven cards of a page stay ONE row and slide sideways; the pager pills stay
   (they are the only way to reach the next seven). Phones (≤600) keep their existing two-column grid. */
@media (min-width: 601px) and (max-width: 1020px) {
  .sb-style-shelf-row .sb-style-grid {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: thin;
    padding-block-end: 6px;
  }

  .sb-style-shelf-row .sb-style-thumb {
    flex: 0 0 clamp(120px, 20vw, 168px);
    scroll-snap-align: start;
  }

  .sb-style-shelf-row .sb-style-page-track {
    display: none;
  }
}

@media (min-width: 1600px) {
  .sb-style-shelf-row {
    --sb-style-stage-w: 1600px;
  }
}

/* 「从所选角色」: which tile the author's characters brought with them, kept visible on the shelf so it
   can be found again from page three. Top-left is the one free corner — the model chip owns
   bottom-left and the locked check owns top-right, and all three can be on the same card at once.
   No media query: the shelf slides sideways on tablets and stacks on phones, but the badge answers a
   question ("where did my characters' style go?") that does not change with the viewport. */
.sb-storybook-style-step .sb-style-thumb-origin {
  position: absolute;
  inset-block-start: 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-emerald) 88%, transparent);
  color: var(--rk-surface);
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  white-space: nowrap;
  pointer-events: none;
}

@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;
  /* The row owns the whole lead. .sb-empty-cta carries its own 10px margin-block-start
     for the states where it stands alone, and inside this flex row that margin dropped
     the emerald pill below its sibling instead of pairing with it. */
  margin-top: 18px;
}
.sb-gen-actions > .sb-empty-cta { margin-block-start: 0; }

/* The quiet exit standing next to the emerald CTA: the design system's .rk-btn-ghost
   pill, sized to the 46px .sb-empty-cta beside it. Declared here instead of swapped
   into the markup because one class serves both <a> and <button> across six error and
   empty screens. Painting background + border is also what switches Blink's native
   button appearance OFF — without either, <button class="sb-gen-home"> fell back to
   the UA's square grey ButtonFace box, which is what shipped on the script screen
   (2026-09-06). The <a> twins rendered as a bare text link, so one affordance had two
   looks depending on the tag. */
.sb-gen-home {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: 0 22px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink);
  text-decoration: none;
  font-weight: 800;
  cursor: pointer;
  transition: background 160ms ease-out;
}
.sb-gen-home:hover { background: var(--rk-paper-2); }

/* 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; }

/* A persisted generate-all target is already owned by the server even before it has a render slot.
   Keep that wait static (history clock, no spinner) and readable rather than dimming it like an
   unavailable action. */
.sb-as-node.is-state-queued .sb-as-node-btn.is-gen {
  opacity: 1;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
}

.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;
  /* The Home composer is 830px wide inside a 1360px content rail. Keep the chapter surface on
     that same visual scale; 920px squeezed long chapter text and made a second chapter look like
     a different product. */
  max-inline-size: 1200px;
  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);
}

/* Which Midjourney upscale became the prop reference (U1-U4). */
.sb-as-node-chip.is-mj-selection {
  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 {
  direction: rtl;
  text-align: start;
}

.sb-vt-top {
  min-height: 46px;
  flex: none;
}

.sb-vt-stepper { justify-self: center; }

/* Shared character-first concept rail (Storybook V3 + Animation V3).
   One portrait is a centered image and name; multiple portraits use equal horizontal cards.
   Neutral frames preserve each source image's medium independently of the concept board style. */
.rk-priority-cast {
  box-sizing: border-box;
  min-width: 0;
  min-height: 0;
  height: 100%;
  padding: 22px 20px 16px;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 10px;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}

.rk-priority-cast-title {
  min-width: 0;
  margin: 0;
  color: var(--rk-ink-muted);
  font-family: var(--rk-font-display);
  font-size: 0.78rem;
  font-weight: 900;
  letter-spacing: 0.04em;
  line-height: 22px;
  text-align: start;
}

.rk-priority-cast-list {
  min-width: 0;
  min-height: 0;
  display: grid;
  gap: 14px;
}

.rk-priority-cast-item {
  box-sizing: border-box;
  min-width: 0;
  min-height: 0;
  margin: 0;
  display: grid;
  justify-items: center;
  gap: 7px;
}

.rk-priority-cast-art {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
}

.rk-priority-cast-art img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center center;
}

.rk-priority-cast figcaption {
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 1rem;
  font-weight: 800;
  line-height: 22px;
  text-align: center;
  text-overflow: ellipsis;
  unicode-bidi: plaintext;
  white-space: nowrap;
}

/* The single portrait and its name stay centered together, with no thumbnail controls. */
.rk-priority-cast.is-single .rk-priority-cast-list {
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
}

.rk-priority-cast.is-single .rk-priority-cast-item {
  width: min(100%, 270px);
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 14px;
}

.rk-priority-cast.is-single .rk-priority-cast-art {
  height: auto;
  max-height: calc(100% - 36px);
  aspect-ratio: 1;
  flex: 0 1 auto;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  box-shadow: var(--rk-shadow-card);
}

/* Every multi-character row has the same size. Short viewports shrink all rows together. */
.rk-priority-cast.is-equal-stack .rk-priority-cast-list {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 12px;
}

.rk-priority-cast.is-equal-stack .rk-priority-cast-item {
  width: 100%;
  flex: 0 1 190px;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
}

.rk-priority-cast.is-equal-stack figcaption {
  width: 100%;
  text-align: start;
  white-space: normal;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

.rk-priority-cast.is-loading {
  display: block;
}

/* One centred card. This used to be a two-column grid with the story brief on the left and an
   `.is-solo` override for the deferred-director lane, which had no captions to list — and the same
   book then changed shape depending on whether its breakdown had run yet (sxy 走查 2026-09-04).
   The brief is gone in both lanes now, so there is one layout and no override. */
.sb-vt-workspace {
  width: min(1280px, 100%);
  height: auto;
  min-height: 0;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
  flex: 1;
}

.sb-vt-workspace.has-priority-cast {
  width: min(1560px, 100%);
  grid-template-columns: minmax(270px, 320px) minmax(0, 1fr);
}

.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-stage-label {
  color: var(--rk-ink-muted);
  font-size: 0.7rem;
  font-weight: 900;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

.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;
  /* The whole board, always (Andy 2026-09-02 走查：「这里应该显示的是概念稿的缩略图，否则默认用户看不到
     9 格」). `cover` + top anchoring showed only the cover block of the 2:3 board inside this landscape
     stage and cut the nine moments off the bottom; the lightbox was the only place they were visible. */
  object-fit: contain;
  object-position: center center;
}

.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); }

/* The generation is done, but its CDN image can still be downloading or decoding. */
.sb-vt-board.is-image-loading .sb-vt-board-image,
.sb-vt-board.is-image-error .sb-vt-board-image { visibility: hidden; }

.sb-vt-image-state {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 24px;
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  font-size: 0.9rem;
  text-align: center;
  overflow-wrap: anywhere;
}

.sb-vt-image-state[hidden] { display: none; }
.sb-vt-image-state .spinner-sm {
  width: 24px;
  height: 24px;
  border-color: var(--rk-line);
  border-top-color: var(--rk-emerald);
}

/* 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 (max-width: 640px) {
  body:has(.sb-vt-footer) .rk-task-float {
    inset-block-end: calc(max(22px, var(--rk-task-float-clearance, 0px)) + env(safe-area-inset-bottom, 0px));
  }
}

@media (min-width: 981px) and (max-height: 760px) {
  .sb-vt-page { padding-block: 10px 8px; }
  .sb-vt-top { min-height: 42px; }
  .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-footer :is(#sb-vt-upgrade, #sb-vt-next) {
  font-family: var(--rk-font-body);
  font-size: 0.76rem;
  font-weight: 850;
}
.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; }

/* [REVISE 2026-09-04, sxy] `.sb-vt-lightbox` 已删：概念稿的放大预览改走共享的 media-preview
   （story.js openTreatmentPreview），观感与遮罩随共享弹框，不再自成一套。 */

.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; }
/* 预计信用（2026-08-22）。一行事实，不是第二段说明：inline-block + 浅底把它和上面那段散文分开，
   读起来是「价签」而不是「又一段文案」。刻意不做成强调色——它是决策依据，不是卖点，抢了
   「去订阅」那个按钮的注意力就本末倒置了。闸外作者才有这一行（见 showTreatmentUpsell）。 */
.sb-vt-upsell-estimate {
  align-self: center;
  padding: 7px 14px;
  border: 1px solid rgba(216,152,85,0.22);
  border-radius: 999px;
  background: rgba(255,247,234,0.75);
  color: var(--rk-ink) !important;
  font-size: 0.8rem !important;
  font-variant-numeric: tabular-nums;
}
/* 列数随按钮数自适应（Andy 2026-08-21）。原来写死 grid-template-columns: 1fr 1fr，于是只有一个
   按钮时它占住左半格、整体偏左——而「只有一个按钮」正是线上默认形态（enforce=true 时没有
   「暂时跳过」）。
   仍然用 grid 而不是 flex：两个按钮的左右内边距不同（主按钮 6px、「暂时跳过」17px），flex 的
   `flex:1 1 0` 分的是**内容宽**、padding 各自额外占位，量出来是 143 / 165 —— 等分这个性质就丢了。
   grid 的 1fr 按边框盒分列，与 padding 无关，双按钮严格等宽；单按钮时列铺满、按钮由 max-width
   收窄并被 justify-items 居中。 */
.sb-vt-upsell-actions { width: 100%; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; justify-items: center; gap: 10px; margin-top: 8px; }
.sb-vt-upsell-actions > * { width: 100%; max-width: 240px; }

@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; }
  .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);
}

/* Composer route forecast — one quiet line, shown only where the screener admits it is guessing
   (ambiguous length + judged a short idea). Quiet chrome: it must read as the composer telling the
   truth about itself, never as a warning or an error. */
.sb-route-hint {
  width: min(830px, 100%);
  margin: 4px auto 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: flex-end;
  gap: 4px 8px;
  font-size: 0.8rem;
  color: var(--rk-ink-muted);
}

.sb-route-hint[hidden] { display: none; }

.sb-route-hint-action {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--rk-emerald);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.sb-route-hint-action:hover { color: var(--rk-emerald-hover); }

.sb-route-hint-action:focus-visible {
  outline: 2px solid var(--rk-focus-ring);
  outline-offset: 2px;
  border-radius: var(--rk-radius-sm);
}

/* ═══ 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.62);
  pointer-events: none;
}

.anim-screen-shade.is-default {
  background: rgba(23, 31, 30, 0.62);
}

.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);
}

/* The project link fills the card so both its preview and title open the same project. */
.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;
  text-decoration: none;
  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-screen-media.is-placeholder.is-olive {
  background: color-mix(in srgb, var(--rk-shelf-bracket-b) 82%, var(--rk-paper-2));
}

.anim-screen-media.is-placeholder.is-teal {
  background: color-mix(in srgb, var(--rk-emerald-hover) 72%, var(--rk-ink));
}

.anim-channel-thumb video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  pointer-events: none;
}

.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:not(:disabled),
.anim-channel-nav:focus-visible:not(:disabled) {
  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-channel-nav:disabled {
  opacity: 0.4;
  cursor: default;
}

.anim-channel-spacer {
  pointer-events: none;
}

.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;
}
/* The site-wide ops strip sits in document flow above this full-height workbench (same as .sb-vt-page): subtract its
   measured height so the bottom action bar stays on screen (dev 3996 assets page: "Next: storyboard" half below the fold). */
.rk-has-opsbar .anim-cw {
  height: calc(100dvh - var(--rk-opsbar-h, 0px));
  min-height: calc(100vh - var(--rk-opsbar-h, 0px));
}

.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;
  /* The paper carries its own dock (sticky at its foot), so the workspace reserves nothing below. */
  padding: 18px 22px 24px;
}

/* ═══ Story paper (2026-10-10, docs/prd-anim-prewall-flow-20261010.md §6.3) ═══
   One centred manuscript with the dock pinned at its foot. Geometry borrows the storybook reading page (sb-prose-*,
   sb-story-dock, sb-story-next); the anim-paper-* hooks size the column and keep the dock's chat bar static. The card
   is a white surface on the warm paper (surface above paper, like every v3 card). */
.anim-paper-wrap {
  width: min(100%, 980px);
  height: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.anim-paper {
  flex: 1;
  min-height: 0;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  box-shadow: var(--rk-shadow-card);
}

.anim-paper-scroll {
  padding: 36px clamp(24px, 6vw, 72px) 28px;
}

.anim-paper-scroll .sb-prose-title {
  font-size: clamp(1.5rem, 2.4vw, 1.9rem);
  margin-bottom: 22px;
}

.anim-paper-p {
  font-size: 1.02rem;
  line-height: 1.75;
}

.anim-paper-p.is-refine-changed {
  border-inline-start: 3px solid var(--rk-emerald);
  padding: 6px 12px;
  background: var(--rk-emerald-soft);
}

/* a quiet caret on the paragraph being typed; it disappears with is-typing */
.anim-paper-scroll.is-typing .anim-paper-p:last-child::after {
  content: '▍';
  margin-inline-start: 2px;
  color: var(--rk-emerald);
  animation: anim-paper-caret 900ms steps(2) infinite;
}

@keyframes anim-paper-caret {
  50% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .anim-paper-scroll.is-typing .anim-paper-p:last-child::after { animation: none; }
}

.anim-paper-scroll .anim-identity-card {
  margin-block-end: 22px;
}

.anim-paper-dock {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 18px 14px;
  border-block-start: 1px solid var(--rk-line);
}

.anim-paper-dock-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
}

.anim-paper-dock-chat {
  min-width: 0;
}

.anim-paper-dock .anim-chatbar {
  position: static;
  bottom: auto;
  margin: 0;
  box-shadow: none;
  background: var(--rk-paper);
}

.anim-paper-dock .anim-series-script-lock {
  margin: 0;
}

.anim-chat-trail {
  max-height: 128px;
}

.anim-script-revision-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}

.anim-script-revision-link .sb-chat-text {
  min-width: 0;
  overflow-wrap: anywhere;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.anim-script-revision-link svg { flex: 0 0 auto; }

.anim-script-revision-link:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 4px;
  border-radius: 4px;
}

/* ═══ Pre-wall modal + concept page (2026-10-10, docs/prd-anim-prewall-flow-20261010.md §6.5 / §6.6) ═══ */
.anim-prewall {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  text-align: center;
  padding: 8px 4px 4px;
}

.anim-prewall h2 {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.35rem;
}

.anim-prewall-rail {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 22px;
}

.anim-prewall-node {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 750;
  color: var(--rk-ink-muted);
}

.anim-prewall-node.is-active,
.anim-prewall-node.is-done { color: var(--rk-ink); }

.anim-prewall-dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 999px;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper);
  font-size: 12px;
}

.anim-prewall-dot svg { width: 13px; height: 13px; }
.anim-prewall-node.is-done .anim-prewall-dot { background: var(--rk-emerald); border-color: var(--rk-emerald); color: #fff; }
.anim-prewall-node.is-active .anim-prewall-dot { border-color: var(--rk-emerald); color: var(--rk-emerald); }
.anim-prewall-node.is-failed .anim-prewall-dot,
.anim-prewall-node.is-skipped .anim-prewall-dot { background: var(--rk-paper-2); }

.anim-prewall-stage {
  min-height: 140px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.anim-prewall-portrait {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.anim-prewall-portrait img {
  width: 150px;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: 14px;
  border: 1px solid var(--rk-line);
  box-shadow: var(--rk-shadow-card);
}

.anim-prewall-portrait figcaption { font-weight: 800; font-size: 14px; }

.anim-prewall-line { margin: 0; font-size: 14.5px; font-weight: 750; color: var(--rk-ink); }
.anim-prewall-hint { margin: 0; font-size: 12.5px; color: var(--rk-ink-muted); }

.anim-concept {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.anim-concept-head {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
}

.anim-concept-title { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 1 1 auto; flex-wrap: wrap; }
.anim-concept-title h2 { margin: 0; flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; font-family: var(--rk-font-display); font-size: 1.35rem; }
.anim-concept-style { flex: none; }

.anim-concept-style {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--rk-line);
  background: var(--rk-surface);
  font-size: 12.5px;
  font-weight: 750;
  color: var(--rk-ink-soft);
}

.anim-concept-style svg { width: 13px; height: 13px; color: var(--rk-emerald); }

.anim-concept-lead {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
}

.anim-concept-lead img {
  width: 48px;
  height: 64px;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
}

.anim-concept-lead figcaption { display: flex; flex-direction: column; gap: 2px; font-size: 12px; color: var(--rk-ink-muted); }
.anim-concept-lead figcaption strong { font-size: 13.5px; color: var(--rk-ink); }
.anim-concept-lead.is-drawing { font-size: 12.5px; color: var(--rk-ink-muted); }

/* single column (10-11: the silent preview clip was withdrawn) — the board centres at its own 3:2 width */
.anim-concept-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

/* the 3:2 board is sized by whichever is tighter — the column width or the height left under the step bar, the title
   row and the footer (≈300px of chrome measured 10-11 at 1280×720, plus 20px of slack) — so it never climbs over the title or slides under
   the footer. Specificity beats the generic `.anim-concept-proposal .anim-board-main` sizing further down. */
.anim-concept-proposal.anim-concept .anim-board-main.anim-concept-board {
  min-height: 0;
  height: auto;
  align-self: flex-start;
  width: min(100%, calc((100dvh - 320px) * 1.5));
}

/* ~~Andy 10-11: the footer's main action sits in the middle of the page~~ — Bella 10-29: one action, at the footer's
   right end. The collapsed task card takes the same row's right end (data-rk-task-slot), so the action steps left of it
   by the width task-float.js publishes as --rk-task-slot-w (0 while no card is seated) */
.anim-concept .anim-board-footer .anim-board-aha-row { justify-self: end; margin-inline-end: var(--rk-task-slot-w, 0px); }

.anim-concept .anim-concept-board {
  min-height: 0;
  height: auto;
  border: 1px solid var(--rk-line);
  border-radius: 16px;
  background: var(--rk-surface);
  padding: 14px;
}


.anim-concept-generating .sb-vt-progress,
.anim-concept-generating > em { display: none; }

@media (max-width: 960px) {
  .anim-concept-head { flex-direction: column; align-items: flex-start; }
}

@media (max-width: 760px) {
  /* The page scrolls as a whole on a phone (the workspace is overflow:auto there): the paper takes its natural
     height and the dock sticks to the bottom of the viewport instead of to a clipped card. */
  .anim-paper-wrap { height: auto; min-height: 100%; }
  .anim-paper { flex: none; overflow: visible; }
  .anim-paper-scroll { overflow: visible; padding: 24px 18px 20px; }
  .anim-paper-dock { position: sticky; bottom: 0; border-end-start-radius: var(--rk-radius); border-end-end-radius: var(--rk-radius); }
  /* A sticky dock rests on the scroller's padding edge, so any bottom padding there floats it off the screen's foot
     with the story showing underneath — the ≤720 rule still reserved 152px for the fixed .anim-script-dock this paper
     replaced (10-10). The scroller reserves nothing; the dock itself clears the home indicator. */
  .anim-cw-main.is-script:has(.anim-paper-dock) { padding-block-end: 0; }
  .anim-paper-dock { padding-block-end: calc(14px + env(safe-area-inset-bottom, 0px)); }
  .anim-paper-dock-row { grid-template-columns: 1fr; }
  .anim-paper-dock .sb-story-dock-cta,
  .anim-paper-dock .sb-story-next { width: 100%; }
}

@media (max-width: 640px) {
  /* The task float's phone form takes no measured lift (task-float.js skips it there): the collapsed card waits above
     the sticky dock's chat line and main button instead of on the button (10-10 L, Andy: the card moves, the main
     button never does). Desktop lifts by [data-rk-bottom-bar] on the dock. 150px = the stacked dock (border 1 +
     padding 12/14 + chat line 46 + gap 14 + button 52 ≈ 139) + the float's usual 10px gap; a chat trail above the row
     may sit under the card, the input and the button never do. */
  body:has(#anim-script-dock) .rk-task-float.is-collapsed {
    inset-block-end: calc(150px + env(safe-area-inset-bottom, 0px));
  }
}

.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;
}

/* Andy 10-19: an author-dismissible banner (the canvas's own refusal message) carries a × at its end. */
.anim-as-control-error.is-dismissible {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding-inline-end: 8px;
}

.anim-as-control-error-close {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  margin: -1px 0 0;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  cursor: pointer;
  opacity: 0.72;
}

.anim-as-control-error-close:hover,
.anim-as-control-error-close:focus-visible {
  opacity: 1;
  background: rgb(163 58 43 / 10%);
}

.anim-as-control-error-close svg {
  width: 14px;
  height: 14px;
  stroke-width: 2.2;
}

/* 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));
}

/* A critical reference is a production gate, not another quality suggestion. Keep the treatment
   local to the affected card: the creator can retry or replace that asset without losing the page. */
.anim-as-node.has-critical-issue {
  border-color: color-mix(in srgb, var(--rk-danger) 64%, var(--rk-line));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--rk-danger) 10%, transparent), var(--rk-shadow-card);
}

.anim-as-critical-badge {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 6px;
  z-index: 2;
  max-width: calc(100% - 12px);
  padding: 3px 8px;
  overflow: hidden;
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-danger) 88%, var(--rk-surface));
  color: var(--rk-surface);
  font-size: 10px;
  font-weight: 800;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}
/* A narrow prop card also carries the info dot at its top-left (8px + 26px): keep the badge clear of it and let the
   ellipsis take the rest, instead of sliding under the dot ("ⓘequired for storyboard", dev 3996). */
.anim-as-node:has(.anim-as-info) .anim-as-critical-badge {
  max-width: calc(100% - 48px);
}

/* 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-as-info {
  position: absolute;
  inset-inline-start: 8px;
  z-index: 8;
}
.anim-as-info .anim-as-qa-badge {
  position: static;
  width: 26px;
  height: 26px;
  padding: 0;
  color: var(--rk-ink-soft);
  background: var(--rk-surface);
  border: 1px solid var(--rk-line);
  box-shadow: var(--rk-shadow-card);
  cursor: help;
}
.anim-as-info .anim-as-qa-badge:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}
.anim-as-info-tooltip {
  position: absolute;
  inset-block-start: 34px;
  inset-inline-start: 0;
  width: var(--asset-info-width);
  max-height: 180px;
  overflow: auto;
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  box-shadow: var(--rk-shadow-card);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}
.anim-as-info:hover .anim-as-info-tooltip,
.anim-as-info:focus-within .anim-as-info-tooltip {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
}
.anim-as-node:has(.anim-as-info:hover),
.anim-as-node:has(.anim-as-info:focus-within) { z-index: 9; }

.rk-app-loading.has-stage-details .rk-app-loading-inner {
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-inline: 8px;
}
.rk-app-loading.has-stage-details .rk-app-loading-stages > li.has-details {
  display: block;
  padding: 0;
}
.rk-app-loading.has-stage-details details { width: 100%; }
.rk-app-loading.has-stage-details summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 14px;
  text-align: start;
  list-style: none;
  cursor: pointer;
}
.rk-app-loading.has-stage-details summary::-webkit-details-marker { display: none; }
.rk-app-loading.has-stage-details summary b { flex: 1; font-size: 15px; line-height: 1.5; }
.rk-app-loading.has-stage-details summary:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: -2px; border-radius: var(--rk-radius-sm); }
.rk-app-loading.has-stage-details .rk-loading-stage-dot { width: 14px; height: 14px; flex: 0 0 14px; border: 1px solid var(--rk-line); border-radius: 50%; }
.rk-app-loading.has-stage-details .is-active .rk-loading-stage-dot { border-color: var(--rk-emerald); background: var(--rk-emerald-soft); }
.rk-app-loading.has-stage-details .is-done .rk-loading-stage-dot { border-color: var(--rk-emerald); background: var(--rk-emerald); }
.rk-app-loading.has-stage-details .rk-loading-stage-chevron { flex: 0 0 16px; color: var(--rk-ink-muted); }
.rk-app-loading.has-stage-details details[open] .rk-loading-stage-chevron { transform: rotate(180deg); }
.rk-app-loading.has-stage-details details ul { margin: 0; padding: 0 18px 14px 42px; text-align: start; }
.rk-app-loading.has-stage-details .rk-app-loading-stages details ul > li {
  display: list-item;
  margin: 5px 0;
  padding: 0;
  min-height: 0;
  border: 0;
  border-radius: inherit;
  background: none;
  color: var(--rk-ink-soft);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.6;
}

.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:has(.anim-cta-resume) {
  align-items: center;
  flex-wrap: wrap;
}

.anim-cta-resume {
  max-width: 100%;
  border: 1px solid var(--rk-emerald);
  border-radius: 999px;
  background: var(--rk-paper);
  color: var(--rk-emerald-hover);
  padding: 11px 22px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.35;
  cursor: pointer;
  white-space: normal;
  overflow-wrap: anywhere;
}

.anim-cta-resume:disabled {
  opacity: .55;
  cursor: wait;
}

@media (max-width: 600px) {
  .anim-cta-bar:has(.anim-cta-resume) {
    padding-inline: 12px;
  }

  /* Keep the collapsed task badge above the two-action footer so it cannot cover the resume CTA. */
  body:has(.anim-cta-bar .anim-cta-resume) .rk-task-float.is-collapsed {
    inset-block-end: calc(190px + env(safe-area-inset-bottom, 0px));
  }

  .anim-cta-bar:has(.anim-cta-resume) .anim-cta-caption {
    flex-basis: 100%;
    text-align: center;
  }

  .anim-cta-bar:has(.anim-cta-resume) .anim-cta-main,
  .anim-cta-bar:has(.anim-cta-resume) .anim-cta-resume {
    width: 100%;
  }
}

.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);
}

/* A paid continuation can spend a few seconds in credit preflight. Keep the pressed button visually
   primary while it is disabled, so the white spinner stays visible and the label does not jump. */
.anim-cta-main.is-pending {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

.anim-cta-main.is-pending:disabled {
  border: 0;
  background: var(--rk-emerald);
  color: #fff;
  cursor: wait;
}

.anim-cta-main.is-pending:disabled:hover {
  background: var(--rk-emerald);
}

@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 {
  position: fixed;
  z-index: 12;
  inset-inline: 22px;
  inset-block-end: max(12px, env(safe-area-inset-bottom));
  max-width: 1560px;
  margin-inline: auto;
  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;
}

/* Known-character popup: one named line per matched character, above the shared explanation. */
.anim-ip-wall-hits {
  max-inline-size: 340px;
  margin: 0;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  font-size: 0.92rem;
  line-height: 1.55;
  list-style: none;
  text-align: start;
}

.anim-ip-wall-hits li + li {
  margin-block-start: 4px;
}

/* Same rule as the intake card: a long label (German, Russian…) never wraps inside its 44px button — the row wraps instead. */
.anim-ip-wall .anim-rewrite-confirm-actions { flex-wrap: wrap; }
.anim-ip-wall .anim-rewrite-confirm-actions button { white-space: nowrap; padding-inline: 20px; }

.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;
}

/* Intake card (Andy 10-19): a label never wraps inside its 44px button — the row wraps instead on a narrow screen. */
.anim-intake-confirm .anim-rewrite-confirm-actions { flex-wrap: wrap; }
.anim-intake-confirm .anim-rewrite-confirm-actions button { white-space: nowrap; padding-inline: 20px; }

/* [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: calc(24px + env(safe-area-inset-bottom));
  }

  .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: 12;
    inset-inline: 14px;
    inset-block-end: max(12px, env(safe-area-inset-bottom));
  }
}

@media (max-width: 720px) {
  .anim-cw-main.is-script {
    padding-inline: 12px;
    padding-block-end: calc(152px + env(safe-area-inset-bottom));
  }

  .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: max(8px, env(safe-area-inset-bottom));
  }

  .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 ═══ */
/* Single-row shelf (sxy 2026-09-05, rolled out from the picture book): the step carries the shared
   sb-style-* geometry classes beside its own, so the .sb-style-shelf-row block lays it out. The
   rules below only restate what .anim-style-wrap / .anim-style-focus (same specificity, later in
   the sheet) would otherwise win, and describe the chrome around the step. */
@media (min-width: 1021px) {
  /* Around the step: the 60px pipeline top bar + .anim-cw-main's 18px top / 40px bottom padding
     (measured 2026-09-05) = 118, plus 4px slack so the step never fits .anim-cw-main (overflow:auto)
     to the exact pixel — an exact fit plus one rounding error is a scrollbar, and one scrollbar
     steals width and breeds the other one. Same reason the stage keeps 40px off 100vw here. The
     confirm button lives in the meta column, so no floating-CTA lane; the block's 245px covers a
     58px bar + a 24px lane, hence extra = 122 − 58 − 24 = 40. */
  .anim-style-wrap.sb-style-shelf-row {
    --anim-shelf-chrome: 122px;
    --sb-style-stage: min(100vw - 160px, var(--sb-style-stage-w));
    --sb-style-cta-lane: 0px;
    --sb-style-extra-h: 40px;
    width: auto;
    margin: 0;
    display: grid;
    grid-template-rows: minmax(0, 1fr);
    gap: 0;
    height: auto;
    min-height: 0;
    overflow: visible;
  }

  .anim-style-wrap.sb-style-shelf-row > .sb-style-workbench {
    height: auto;
    min-height: calc(100dvh - var(--rk-opsbar-h, 0px) - var(--anim-shelf-chrome));
  }

  .anim-style-wrap.sb-style-shelf-row .anim-style-focus.sb-style-focus {
    width: var(--sb-style-block-w);
    align-self: auto;
    padding-inline: 0;
  }

  .anim-style-wrap.sb-style-shelf-row .anim-style-hero.sb-style-hero2 {
    height: var(--sb-style-hero-h);
  }

  .anim-style-wrap.sb-style-shelf-row .anim-style-grid-shell.sb-style-grid-shell {
    align-self: auto;
    margin-block-start: 0;
  }

  .anim-style-wrap.sb-style-shelf-row .anim-style-grid.sb-style-grid {
    grid-template-columns: repeat(7, var(--sb-style-card-w));
  }

  .anim-style-wrap.sb-style-shelf-row .anim-style-page-nav.sb-style-page-nav {
    width: 48px;
    height: 104px;
    border-radius: 999px;
    transform: translateY(calc(var(--sb-style-count-h) / -2));
  }
}
'''.replace('\n', nl)
c = c.replace(anchor, add, 1)
io.open(p, 'w', encoding='utf-8', newline='').write(c)
print('css ok')

.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;
  flex-wrap: wrap;
  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 {
  border: 1px solid var(--rk-line);
  background: var(--rk-paper-2);
  color: var(--rk-ink-muted);
  box-shadow: none;
  opacity: 1;
  cursor: not-allowed;
}

.anim-cta-main:disabled:hover {
  background: var(--rk-paper-2);
}

.anim-cta-bar.is-one-click-locked,
.anim-cta-bar.is-one-click-checkpoint {
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.anim-cta-lock-reason {
  max-width: 680px;
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 11.5px;
  font-style: normal;
  font-weight: 600;
  line-height: 1.4;
  text-align: center;
}

/* 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;
}

/* 动画/MV 自己的放大层。[REVISE 2026-09-04] 原文写「与绘本的 .sb-vt-lightbox 同一套观感与同一套
   约束（Andy 2026-08-06：动画/MV 的放大要照绘本来）」—— 那个参照物已经不存在了：绘本 2026-09-04
   改走共享 media-preview，`.sb-vt-lightbox` 已删。本层暂未收敛过去（v3 目前还有本层与角色页
   image-zoom.js 两套独立实现），下面这条循环依赖的教训仍然有效，原样保留。
   ⚠️ 这里曾是 `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;
  /* Keep image previews above the fixed asset, storyboard and video editors (80). */
  z-index: 90;
  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 {
  display: flex;
  align-items: center;
  gap: 5px;
  text-transform: none;
}

.anim-board-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 {
  width: 15px;
  height: 15px;
}

.anim-board-brief-info:hover,
.anim-board-brief-info:focus-visible {
  color: var(--rk-emerald);
}

.anim-board-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 {
  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;
}

/* ── 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; }
  .sb-vt-workspace.has-priority-cast { grid-template-columns: minmax(0, 1fr); }
  .sb-vt-workspace.has-priority-cast .rk-priority-cast,
  .anim-concept-proposal .rk-priority-cast {
    width: 100%;
    height: clamp(380px, 56dvh, 520px);
  }
  .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; }
  .sb-vt-workspace.has-priority-cast .rk-priority-cast,
  .anim-concept-proposal .rk-priority-cast {
    height: 440px;
    padding: 16px 14px 12px;
  }
  .rk-priority-cast.is-single .rk-priority-cast-item { width: min(100%, 230px); }
  .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;
  /* Canvas coordinates and pan transforms use a physical left origin in every locale. */
  left: 0;
  transform-origin: 0 0;
}

.anim-as-edges {
  position: absolute;
  inset-block-start: 0;
  left: 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;
  /* Andy 10-19 item 25: the arrive pulse scales the dot; without its own box as the origin it scales from the svg's
     0,0 and flies in across the canvas (same two lines as .anim-sh-ref circle on the storyboard canvas) */
  transform-box: fill-box;
  transform-origin: center;
}

/* 选中态与分镜页 .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;
}

/* Andy 10-19: 「有连线关系的，目前显示不清晰，应该直接按照选中的深色显示」 — on the asset canvas every relation reads at the
   selected strength, selected or not (the dashed bind keeps its dash). */
.anim-as-edges .anim-as-edge path,
.anim-as-edges .anim-as-edge.is-muted path,
.anim-as-edges .anim-as-edge path.is-bind {
  stroke: var(--rk-emerald);
  stroke-width: 2.75;
  stroke-opacity: 0.92;
}

.anim-as-edges .anim-as-edge circle,
.anim-as-edges .anim-as-edge.is-muted circle {
  r: 5;
  fill: var(--rk-emerald-soft);
  opacity: 1;
}

.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;
}

/* A freshly drawn card's picture can take seconds to arrive (the CDN makes its first preview on demand): the frame
   pulses as a skeleton until the image loads or fails, instead of sitting as a blank paper block (10-10 #3914).
   anim.js settleAssetMedia drops .is-loading; the badges and veils after it in the frame still paint on top. */
.anim-as-media.is-loading::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--rk-paper-2);
  animation: sb-skeleton-pulse 1.6s ease-in-out infinite;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .anim-as-media.is-loading::before { animation: none; }
}

/* A forward/reverse set is one scene card and two generated image units. Keep both views inside the
   business card so the canvas card count stays stable while the billed work remains inspectable. */
.anim-as-scene-views {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px;
  background: var(--rk-line);
}

.anim-as-scene-view {
  position: relative;
  min-width: 0;
  min-height: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
  background: var(--rk-paper);
  color: inherit;
  cursor: zoom-in;
}

.anim-as-scene-view:disabled {
  opacity: 1;
  cursor: default;
}

.anim-as-scene-view > span:last-child {
  position: absolute;
  inset-inline: 5px;
  inset-block-end: 5px;
  min-width: 0;
  padding: 4px 5px;
  border-radius: 7px;
  background: color-mix(in srgb, var(--rk-ink) 76%, transparent);
  color: #fff;
  text-align: start;
}

.anim-as-scene-view > span:last-child b,
.anim-as-scene-view > span:last-child em {
  display: block;
  overflow: hidden;
  font-size: 8.5px;
  font-style: normal;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anim-as-scene-view > span:last-child em {
  opacity: 0.82;
  font-weight: 600;
}

.anim-as-scene-view-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: var(--rk-paper-2);
}

/* 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）~~ Andy 10-19 改上下结构——名字一行，超出省略（悬停 title
   看全名），按钮另起一行居中（.anim-as-actions）。分镜条(is-shot)保持原有单行结构。 */
.anim-as-node:not(.is-shot) .anim-as-label {
  display: block;
  flex: none;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 16px;
}

.anim-as-label small {
  display: block;
  margin-block-start: 2px;
  color: var(--rk-ink-muted);
  font-size: 9px;
  font-weight: 650;
}

/* 卡片底排：名字 + 「生成/重画」并排（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;
}

/* Andy 10-19: asset cards read top to bottom — the picture, the name on one line (… when longer, the full name on
   hover), the button on its own centred row. The row keeps its height while the card is busy and shows no button,
   so the picture above never grows or shrinks (AS_CARD_CHROME = 68 holds it). Storyboard strips (is-shot) keep theirs. */
.anim-as-node:not(.is-shot) .anim-as-foot {
  flex-direction: column;
  align-items: stretch;
  gap: 5px;
  min-height: 45px;
}

.anim-as-node:not(.is-shot) .anim-as-label small {
  display: inline;
  margin: 0 0 0 4px;
}

.anim-as-actions {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 6px;
  min-height: 24px;
}

/* (the button rule .anim-as-regen caps it at 60% of a row it used to share with the name; alone on its row it may use it all) */
.anim-as-actions > button {
  max-width: 100%;
}

.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;
  display: flex;
  align-items: center;
}

.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;
  /* Panning uses stage transforms; browser focus must not scroll the fixed inspector away. */
  overflow: clip;
}

.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;
}

/* Q-18 (2026-10-14): a continuation card waiting for its source shot offers the way there — the video card's
   .anim-vdc-go, card-sized. */
.anim-shot-go { min-height: 26px; padding: 0 10px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-surface); color: var(--rk-ink); font: inherit; font-size: 11px; font-weight: 800; white-space: nowrap; cursor: pointer; }
.anim-shot-go:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
/* in the editor card head the long shot title gives way, never the way to the source shot */
.anim-ec-head [data-shot-go-source] { flex: none; min-block-size: 32px; padding: 0 12px; font-size: 0.85rem; }
/* a drawn continuation waiting on its source: a strip along the bottom of the picture (the tools own the top corner) */
.anim-shot-state.is-pill-low { position: absolute; z-index: 2; inset-block-end: 6px; inset-inline: 6px; justify-content: space-between; border-radius: 999px; padding: 4px 4px 4px 10px; background: rgba(250, 248, 244, 0.94); box-shadow: 0 2px 8px -3px var(--rk-ink-soft); }
.anim-shot-state.is-pill-low b { min-inline-size: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

.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;
}

/* Plate usage stays in the shared info popover, leaving a stable seat for the single-image action. */
.anim-as-node.is-pro-plate .anim-as-label { overflow: visible; min-inline-size: 0; }
.anim-pro-plate-foot { justify-content: space-between; min-inline-size: 0; }
.anim-pro-plate-foot > .anim-shot-generate { flex: none; }
.anim-pro-plate-foot .anim-cta-info-btn { width: 26px; height: 26px; }
.anim-pro-plate-foot .anim-cta-info-btn svg { width: 17px; height: 17px; }
.anim-pro-plate-foot .anim-cta-info-tip { width: 220px; max-inline-size: min(220px, calc(100vw - 32px)); max-block-size: 160px; overflow: auto; overflow-wrap: anywhere; }
.anim-pro-plate-foot .anim-cta-info:not(.is-dismissed):is(:hover, :focus-within) .anim-cta-info-tip { visibility: visible; opacity: 1; pointer-events: auto; }
.anim-as-node.is-pro-plate:has(.anim-cta-info:hover),
.anim-as-node.is-pro-plate:has(.anim-cta-info:focus-within) { z-index: 9; }

.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);
  grid-template-rows: auto minmax(0, 1fr);
  align-items: stretch;
  gap: 20px;
}

.anim-vd-ai-voice-note {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--rk-amber-ink, #9a6a00);
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1.45;
  text-align: center;
}

@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;
  /* Anchors the restored 「全部开拍」 batch button at the top-right of the STAGE (2026-08-28),
     matching where the asset and storyboard steps put theirs. Its previous home was the bottom of
     the this-shot panel, where it was the only full-width solid button and therefore read as that
     shot's main action — one misfire there opened three clips and spent 2850 credits. */
  position: relative;
}

.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;
}

/* Absolute on purpose — this is the fix for a player whose buttons run away from the cursor.
   The stage takes its width from its height (aspect-ratio + height:100%), so anything that nudges
   the height moves every native control sideways. In flow, the media resolved `height:100%` against
   an indefinite height and fell back to its own intrinsic ratio: a 864x496 take rendered 1024px tall
   inside a 1005px stage, and those 19px fed straight back into the row. Reaching for the volume was
   enough to tip it: measured 1787x1005 -> 1897x1067, i.e. the whole control bar jumping 110px right
   and back (Jeff 2026-09-16). Out of flow, the media can no longer size its own container. */
.anim-vd-stage img,
.anim-vd-stage video {
  position: absolute;
  inset: 0;
  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-status.is-waiting_dependency,
.anim-vd-status.is-needs_attention {
  background: #f8eedb;
  color: #8a6325;
}

.anim-vd-status.is-blocked_by_predecessor {
  background: #f8e8e5;
  color: var(--rk-danger);
}

.anim-vd-dependency {
  display: grid;
  gap: 9px;
  margin-block-start: 14px;
  padding: 11px 12px;
  border: 1px solid #e4d4b8;
  border-radius: 12px;
  background: #fbf4e7;
  color: var(--rk-ink-soft);
}

.anim-vd-dependency.is-blocked_by_predecessor {
  border-color: #e9c8c2;
  background: #fcf0ee;
}

.anim-vd-dependency p {
  margin: 0;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.45;
}

.anim-vd-dependency button {
  justify-self: start;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 6px 11px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-size: 12px;
  font-weight: 800;
  cursor: pointer;
}

.anim-vd-dependency button:hover {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald-hover);
}

.anim-vd-progress {
  display: grid;
  gap: 8px;
  margin-block-start: 14px;
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 12px;
  background: var(--rk-emerald-soft);
}

.anim-vd-progress > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  color: var(--rk-ink-soft);
  font-size: 12px;
  font-weight: 700;
}

.anim-vd-progress strong {
  color: var(--rk-emerald-hover);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

.anim-vd-progress button {
  min-block-size: 40px;
  border: 1px solid var(--rk-emerald);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  font: inherit;
  font-size: 12px;
  font-weight: 800;
  cursor: pointer;
}

.anim-vd-progress button:hover:not(:disabled),
.anim-vd-progress button:focus-visible {
  outline: none;
  background: var(--rk-surface-raised);
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-vd-progress button:disabled {
  cursor: default;
  opacity: 0.55;
}

.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;
}

/* 弹窗里的四个分区小标题(来源分镜/本镜台词/运镜与画面描述/视频参数)用官方绿 + 标题字体,
   免得和灰色正文糊成一片,一眼看不出这一块是干什么的(Jeff)。 */
.anim-vd-prompt-form .anim-card-kicker {
  font-family: var(--rk-font-display);
  font-size: 13px;
  letter-spacing: 0.6px;
  color: var(--rk-emerald);
}

.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;
}

/* 说明贴在「本镜台词」标题下面,先看懂规则再改词(Jeff);所以留的是下边距不是上边距。 */
.anim-vd-voice-note {
  margin: 0 0 10px;
  color: var(--rk-ink-muted);
  font-size: 11px;
  line-height: 1.55;
}

.anim-vd-voice-note.is-error {
  color: var(--rk-danger, #b3261e);
}

/* 时长提醒单独挂在台词框下面,用提示色 —— 它说的是「会出事」(漏念/被截断),混进上面那条
   灰色说明里没人当回事;而且上面那条还要兼做保存状态行,会被「已保存」盖掉(Jeff)。 */
.anim-vd-voice-length-note {
  margin: 8px 0 0;
  padding: 7px 10px;
  border: 1px solid color-mix(in srgb, var(--rk-warn) 26%, var(--rk-line));
  border-radius: var(--rk-radius-sm);
  background: color-mix(in srgb, var(--rk-warn) 8%, var(--rk-surface));
  color: var(--rk-warn);
  font-size: 11px;
  line-height: 1.55;
}

/* 可编辑台词:每句「说话人 + 开关」一行,下面字幕框与念法框各一行。
   念法留空 = 照字幕念,所以它可以长期是空的,不能画得像“缺了东西”。 */
.anim-vd-voice-list-editable {
  max-block-size: 268px;
  gap: 12px;
}

.anim-vd-voice-list-editable li {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

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

.anim-vd-voice-switch {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--rk-ink-muted);
  font-size: 11px;
  cursor: pointer;
}

.anim-vd-voice-field {
  display: flex;
  align-items: center;
  gap: 8px;
}

.anim-vd-voice-field > span {
  flex: 0 0 auto;
  min-inline-size: 34px;
  color: var(--rk-ink-muted);
  font-size: 11px;
}

.anim-vd-voice-field input {
  flex: 1 1 auto;
  min-inline-size: 0;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  padding: 5px 8px;
  background: var(--rk-surface, #fff);
  color: var(--rk-ink);
  font: inherit;
  font-size: 12px;
  line-height: 1.5;
}

.anim-vd-voice-field input:disabled {
  background: var(--rk-paper);
  color: var(--rk-ink-muted);
}

.anim-vd-voice-row.is-off .anim-vd-voice-who {
  background: var(--rk-paper);
  color: var(--rk-ink-muted);
}

/* 字数与重置紧跟在输入框后面:字数是「还能写多少」,重置是「改坏了怎么回去」,
   两个都只在这一行里生效,所以不另起一行,免得一句台词占掉半个面板。 */
.anim-vd-voice-count {
  flex: 0 0 auto;
  min-inline-size: 42px;
  color: var(--rk-ink-muted);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  text-align: end;
}

.anim-vd-voice-count.is-near {
  color: var(--rk-amber-ink, #9a6a00);
}

.anim-vd-voice-reset {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 22px;
  block-size: 22px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  padding: 0;
  background: var(--rk-surface, #fff);
  color: var(--rk-ink-muted);
  cursor: pointer;
}

.anim-vd-voice-reset:hover {
  color: var(--rk-ink);
  border-color: var(--rk-ink-muted);
}

.anim-vd-voice-reset[hidden] {
  display: none;
}

/* 保存那一下整行按下去:框、开关、还原一起停手,免得回包落地时把刚打的字盖回去。 */
.anim-vd-voice-row.is-saving {
  opacity: 0.66;
}

.anim-vd-voice-row.is-saving .anim-vd-voice-field input,
.anim-vd-voice-row.is-saving .anim-vd-voice-reset {
  cursor: progress;
}

/* 底栏只剩「还原官方提示词」,靠右站。字数已经挪到标题行右侧。 */
.anim-vd-prompt-main-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-block-start: 8px;
  min-block-size: 30px;
}

.anim-vd-prompt-main-head .anim-vd-voice-count {
  min-inline-size: 0;
}

.anim-vd-prompt-restore[hidden] {
  display: none;
}

.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;
  /* 间距改由表头/底栏各自的 margin 控制:右栏的标题行要和左栏「来源分镜」对齐到同一条线上,
     多一层 flex gap 就会把正文框往下推(实测差 28px)。 */
  gap: 0;
  min-width: 0;
}

/* 标题行:左边是「运镜与画面描述」,右边是字数 —— 放右上角比压在框底下显眼(Jeff)。 */
.anim-vd-prompt-main-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-block-end: 8px;
}

.anim-vd-prompt-main-head .anim-card-kicker {
  margin: 0;
}

/* 选择器要比下面那条 .anim-vd-prompt-form textarea 的 18px 更具体,否则它按后来居上赢走,
   正文框比左栏「来源分镜」低 18px(Jeff 指出的那条歪线)。 */
.anim-vd-prompt-form .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;
    grid-template-rows: auto auto auto;
  }
  /* 弹窗两栏在窄屏折成一栏:上下文在上、正文在下(正文最重要但需要先看到台词)。 */
  .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;
}

/* Names the new story could not tie to its cast (anim.js identityReviewCard). Sits at the top of the
   script column; quiet paper card, one emerald action, the choice per name on one row. */
.anim-identity-card {
  display: grid;
  gap: 10px;
  margin-block: 4px 18px;
  padding: 16px 18px;
  border: 1px solid var(--rk-line);
  border-inline-start: 3px solid var(--rk-warn);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
}

.anim-identity-card h3 {
  margin: 0;
  color: var(--rk-ink);
  font-size: 15px;
  font-weight: 800;
}

.anim-identity-body {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 13px;
  line-height: 1.55;
}

.anim-identity-rows {
  display: grid;
  gap: 8px;
}

.anim-identity-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(180px, 260px);
  gap: 12px;
  align-items: center;
}

.anim-identity-name {
  display: grid;
  gap: 2px;
  min-width: 0;
  color: var(--rk-ink);
  font-weight: 700;
  overflow-wrap: anywhere;
}

.anim-identity-name small {
  color: var(--rk-ink-muted);
  font-size: 12px;
  font-weight: 500;
}

.anim-identity-row select {
  min-height: 38px;
  padding-inline: 10px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper);
  color: var(--rk-ink);
  font: inherit;
}

.anim-identity-row select:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--rk-focus-ring);
}

.anim-identity-error {
  margin: 0;
  color: var(--rk-danger);
  font-size: 13px;
}

.anim-identity-card .anim-cta-main {
  justify-self: end;
}

@media (max-width: 640px) {
  .anim-identity-row { grid-template-columns: 1fr; }
  .anim-identity-card .anim-cta-main { justify-self: stretch; }
}

.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; }

/* Book-made workshop cards in the composer picker (worklist #543): a quiet provenance line. */
.sb-char-card .sb-char-origin {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--rk-ink-muted);
  font-size: 0.7rem;
  font-weight: 700;
}

/* "Use your saved characters?" at submit (worklist #542): one row per name the story mentions, each
   row a side-scrolling strip of that name's saved versions. Reuses the picker card as-is. */
.comic-intake-card.sb-name-match-card { max-width: 560px; }
.sb-name-match-group { margin: 0 0 14px; min-width: 0; }
.sb-name-match-group h4 { margin: 0 0 8px; color: var(--rk-ink); font-size: 0.9rem; font-weight: 800; }
.sb-name-match-row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 96px;
  gap: 10px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding: 4px 4px 8px;
}
.sb-name-match-card .sb-char-card strong { font-size: 0.76rem; font-weight: 700; }
.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;
}
/* visibility rides the entrance too: a page that is not painting frames (a background tab) holds the
   animation on its first frame, so the card sat there at opacity 0 over the composer's product tabs and
   swallowed clicks on the Kids MV tab. visibility: hidden is not hit-testable and flips to visible on the
   first painted frame, so the card only takes clicks once it can actually be seen
   (release QA 2026-10-28, OBS-KMV-01). */
@keyframes rk-foryou-peek-in {
  from { opacity: 0; transform: translateY(-6px); visibility: hidden; }
  to { opacity: 1; transform: translateY(0); visibility: visible; }
}
.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); }
}

/* ── 钱包通知位 + 每日签到 (lib/wallet-notice.js + lib/checkin.js) ── */
/* The notice pins itself to the balance chip and lives on <body>, NOT inside #rk-balance-slot:
   refreshTopbarChrome() repaints that slot by assigning innerHTML, and the wallet refresh that
   follows a grant is exactly what triggers it. Position is written by JS from the chip's rect. */
.rk-wallet-notice {
  position: fixed;
  z-index: 60;
  inline-size: 300px;
  max-inline-size: calc(100vw - 16px);
  padding: 13px 14px;
  background: var(--rk-paper, #FAF8F4);
  border: 1px solid var(--rk-line, rgba(43, 42, 38, 0.12));
  border-radius: 16px;
  box-shadow: 0 12px 32px rgba(43, 42, 38, 0.14);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity 200ms ease-out, transform 200ms ease-out;
}
.rk-wallet-notice.is-in { opacity: 1; transform: translateY(0); }

/* Headline-only variant: one line, no close button, sized to its text. Anything longer belongs in
   the week dialog, which is one click away in the account menu. */
.rk-wallet-notice.is-compact {
  inline-size: auto;
  max-inline-size: min(calc(100vw - 16px), 320px);
  padding: 11px 16px;
  white-space: nowrap;
}
/* The paragraph keeps its default block margins, which is what spaces the multi-line card.
   On a one-line card they are 32px of dead air — measured 75px tall for 22px of text. */
.rk-wallet-notice.is-compact .rk-wallet-notice-title { padding-inline-end: 0; margin: 0; }

/* Caret pointing back at the balance chip. Drawn as two stacked triangles so the hairline border
   continues across the tip: one in the border colour, one in the paper colour a pixel below it.
   Its x is set by JS (--rk-notice-caret) because the card can be clamped away from the chip. */
.rk-wallet-notice::before,
.rk-wallet-notice::after {
  content: "";
  position: absolute;
  inset-block-start: -8px;
  left: var(--rk-notice-caret, calc(100% - 26px));
  margin-inline-start: -8px;
  border-inline: 8px solid transparent;
  border-block-end: 8px solid var(--rk-line, rgba(43, 42, 38, 0.12));
}
.rk-wallet-notice::after {
  inset-block-start: -7px;
  border-block-end-color: var(--rk-paper, #FAF8F4);
}
.rk-wallet-notice-close {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 10px;
  background: none;
  border: none;
  font-size: 18px;
  line-height: 1;
  color: var(--rk-ink-muted, #9B958A);
  cursor: pointer;
}
.rk-wallet-notice-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--rk-ink, #2B2A26);
  padding-inline-end: 18px;
}
.rk-wallet-notice-kicker {
  margin-block-start: 2px;
  font-size: 12px;
  color: var(--rk-accent, #0FA47E);
}
.rk-wallet-notice-note {
  margin-block-start: 7px;
  font-size: 12px;
  line-height: 1.55;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.68));
}
.rk-wallet-notice-link,
.rk-checkin-link {
  margin-block-start: 9px;
  background: none;
  border: none;
  padding: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--rk-accent, #0FA47E);
  cursor: pointer;
}
.rk-wallet-notice-link:hover,
.rk-checkin-link:hover { text-decoration: underline; }

/* The credited pulse plays on the balance chip itself — the chip is the thing being talked about,
   so a separate icon bouncing beside it would be a second subject. */
.balance-chip.is-credited { animation: rk-wallet-credited 620ms ease-out; }
@keyframes rk-wallet-credited {
  0%   { transform: scale(1); }
  28%  { transform: scale(1.12) rotate(-3deg); }
  56%  { transform: scale(0.98) rotate(1.5deg); }
  100% { transform: scale(1) rotate(0); }
}

/* Trailing meta on an account-menu row (the check-in streak). Pushed to the end so the row reads
   "icon — label ………… 3 天" like the plan line above it. */
.rk-user-item-trail {
  margin-inline-start: auto;
  font-size: 11px;
  color: var(--rk-ink-muted, #9B958A);
}

/* ── the week, opened from the account menu (Kim's 2026-08-19 mock) ── */
.rk-modal-panel.is-checkin { inline-size: min(560px, 100%); padding: 26px 26px 22px; }

.rk-checkin-head { display: flex; align-items: center; gap: 14px; padding-inline-end: 34px; }
/* Gift mark. Filled tint rather than the bare ink stroke used in chrome: this is the one place the
   feature gets to feel like a gift, and the mock leads with it. */
.rk-checkin-hero {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 16px;
  background: rgba(15, 164, 126, 0.12);
  color: var(--rk-accent, #0FA47E);
}
.rk-checkin-hero svg { width: 28px; height: 28px; stroke-width: 1.6; }
.rk-checkin-title { font-size: 21px; font-weight: 700; color: var(--rk-ink, #2B2A26); }
.rk-checkin-sub { margin-block-start: 3px; font-size: 13px; color: var(--rk-ink-soft, rgba(43, 42, 38, 0.68)); }

/* Stat band: streak and the week's ceiling, the two numbers the mock leads with. */
.rk-checkin-stats {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-block-start: 18px;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--rk-paper-2, #F3EFE7);
  font-size: 13px;
  color: var(--rk-ink, #2B2A26);
  flex-wrap: wrap;
}
.rk-checkin-stat { display: inline-flex; align-items: center; gap: 8px; }
.rk-checkin-stat-icon { display: inline-flex; color: var(--rk-ink-muted, #9B958A); }
.rk-checkin-stat-icon.is-coin { color: #C9962F; }
.rk-checkin-stat-icon svg { width: 19px; height: 19px; stroke-width: 1.5; }
.rk-checkin-stat-divider { width: 1px; height: 18px; background: var(--rk-line, rgba(43, 42, 38, 0.14)); }

/* Seven cells on one row. They stay on one row at every width because a week that wraps stops
   reading as a week. */
.rk-checkin-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
}
.rk-checkin-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 11px 2px 12px;
  border: 1.5px solid transparent;
  border-radius: 14px;
  background: var(--rk-paper-2, #F3EFE7);
  min-width: 0;
}
.rk-checkin-day-name {
  font-size: 12px;
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.62));
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* One disc per day. Collected and today both carry a tick — the difference is weight, not symbol. */
.rk-checkin-day-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--rk-surface, #fff);
  color: var(--rk-ink-muted, #9B958A);
}
.rk-checkin-day-mark svg { width: 17px; height: 17px; stroke-width: 1.7; }
.rk-checkin-day-amount { font-size: 12px; font-weight: 600; color: var(--rk-ink-soft, rgba(43, 42, 38, 0.62)); }

.rk-checkin-day.is-collected { background: rgba(15, 164, 126, 0.10); }
.rk-checkin-day.is-collected .rk-checkin-day-mark { background: #4FBF98; color: #fff; }
.rk-checkin-day.is-collected .rk-checkin-day-amount { color: var(--rk-accent, #0FA47E); }

.rk-checkin-day.is-today {
  border-color: var(--rk-accent, #0FA47E);
  background: var(--rk-surface, #fff);
}
.rk-checkin-day.is-today .rk-checkin-day-name { color: var(--rk-ink, #2B2A26); font-weight: 600; }
.rk-checkin-day.is-today .rk-checkin-day-mark { background: var(--rk-accent, #0FA47E); color: #fff; }
.rk-checkin-day.is-today .rk-checkin-day-amount { color: var(--rk-accent, #0FA47E); font-weight: 700; }

/* A day that came and went is dimmed and carries no mark at all: nothing happened, and nothing can
   now. Giving it the future's star would offer a reward that is already gone. */
.rk-checkin-day.is-missed { opacity: 0.45; }

/* What the points are FOR. This block is the reason the modal exists at all — a balance the user
   cannot spend on purpose is not a reward. */
.rk-checkin-perks {
  margin-block-start: 18px;
  padding-block-start: 16px;
  border-block-start: 1px solid var(--rk-line, rgba(43, 42, 38, 0.10));
}
.rk-checkin-perks-title { font-size: 14px; font-weight: 600; color: var(--rk-ink, #2B2A26); }
.rk-checkin-perk-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 14px;
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
}
.rk-checkin-perk { display: flex; align-items: flex-start; gap: 9px; min-width: 0; }
.rk-checkin-perk-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 9px;
  background: var(--rk-paper-2, #F3EFE7);
  color: var(--rk-ink-soft, rgba(43, 42, 38, 0.7));
}
.rk-checkin-perk-icon svg { width: 16px; height: 16px; stroke-width: 1.6; }
.rk-checkin-perk.is-spend .rk-checkin-perk-icon { background: rgba(15, 164, 126, 0.12); color: var(--rk-accent, #0FA47E); }
.rk-checkin-perk.is-first .rk-checkin-perk-icon { background: rgba(201, 150, 47, 0.14); color: #C9962F; }
.rk-checkin-perk-text { font-size: 12px; line-height: 1.5; color: var(--rk-ink-soft, rgba(43, 42, 38, 0.68)); }

/* One full-width button, carrying whatever label the state has earned. */
.rk-checkin-foot { margin-block-start: 18px; }
.rk-checkin-claimed {
  margin-block-end: 10px;
  text-align: center;
  font-size: 13px;
  color: var(--rk-accent, #0FA47E);
}
.rk-checkin-notice {
  margin-block-end: 10px;
  text-align: center;
  font-size: 13px;
  color: #B4453F;
}
.rk-checkin-cta {
  display: block;
  inline-size: 100%;
  padding: 13px 18px;
  border: none;
  border-radius: 999px;
  background: var(--rk-accent, #0FA47E);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.rk-checkin-cta:hover { filter: brightness(1.05); }
.rk-checkin-cta.is-busy, .rk-checkin-cta:disabled { opacity: 0.6; cursor: default; }

@media (max-width: 640px) {
  .rk-wallet-notice { inline-size: min(calc(100vw - 16px), 300px); }
  .rk-modal-panel.is-checkin { padding: 20px 16px 18px; }
  .rk-checkin-hero { width: 44px; height: 44px; border-radius: 13px; }
  .rk-checkin-hero svg { width: 24px; height: 24px; }
  .rk-checkin-title { font-size: 19px; }
  .rk-checkin-week { gap: 4px; }
  .rk-checkin-day { padding: 8px 1px 9px; gap: 6px; border-radius: 11px; }
  .rk-checkin-day-name { font-size: 11px; }
  .rk-checkin-day-amount { font-size: 11px; }
  /* The discs are the first thing to give up room: seven of them plus gaps is what decides
     whether the week still fits one row on a 360px phone. */
  .rk-checkin-day-mark { width: 24px; height: 24px; }
  .rk-checkin-day-mark svg { width: 14px; height: 14px; }
  /* Four perks stack to one column rather than squeezing two sentences side by side. */
  .rk-checkin-perk-list { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .balance-chip.is-credited { animation: none; }
  .rk-wallet-notice { transition: none; opacity: 1; transform: none; }
}


/* 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%;
  left: 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;
}

.anim-identity-recovery .anim-identity-reference {
  margin: 2px 0 0;
  max-width: min(520px, 86vw);
  color: var(--rk-ink-2);
  font-size: 14px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.anim-identity-candidates {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: min(620px, 90vw);
  margin-top: 4px;
}

.anim-identity-choice {
  min-height: 40px;
  max-width: min(280px, 82vw);
  white-space: normal;
  overflow-wrap: anywhere;
}

@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);
}

/* The full activity dialog follows the subscription paper palette. Account inline rows stay compact. */
.rk-modal.is-spending .rk-modal-panel {
  inline-size: min(960px, 100%);
  block-size: min(820px, calc(100dvh - 48px));
  max-block-size: calc(100dvh - 48px);
  padding: 0;
  overflow: hidden;
  background: var(--rk-paper);
}
.rk-modal.is-spending .rk-modal-body { block-size: 100%; min-block-size: 0; overflow: hidden; }
.rk-spend { display: flex; flex-direction: column; gap: 22px; padding: 32px 40px 24px; block-size: 100%; box-sizing: border-box; min-block-size: 0; color: var(--rk-ink); }
.rk-spend-heading { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; padding-inline-end: 46px; flex: none; }
.rk-spend-heading h2 { margin: 0; font-size: 28px; line-height: 1.3; font-weight: 850; }
.rk-spend button { font: inherit; cursor: pointer; }
.rk-spend button:disabled { cursor: default; opacity: .45; }
.rk-spend button:focus-visible, .rk-spend-activity:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 3px; }
.rk-spend-link { color: var(--rk-emerald-hover); border: 0; background: transparent; min-block-size: 40px; padding: 0; font-weight: 750 !important; }
.rk-spend-assets { display: flex; align-self: flex-start; background: var(--rk-paper-2); border: 1px solid var(--rk-line); border-radius: 999px; padding: 3px; flex: none; }
.rk-spend-assets button { border: 0; background: transparent; color: var(--rk-ink-soft); padding: 7px 22px; min-block-size: 40px; border-radius: 999px; font-weight: 750; }
.rk-spend-assets button[aria-pressed="true"] { background: var(--rk-emerald); color: var(--rk-surface); }
.rk-spend-summary { flex: none; min-block-size: 76px; }
.rk-spend-balances { --spend-balance-gap: 34px; display: flex; gap: var(--spend-balance-gap); padding-block: 2px 12px; }
.rk-spend-balance { flex: 1; min-inline-size: 0; display: grid; align-content: start; gap: 8px; position: relative; text-align: center; color: var(--rk-ink-soft); font-size: 14px; }
.rk-spend-balance strong { position: relative; font-size: 25px; color: var(--rk-ink); line-height: 1.25; font-weight: 800; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.rk-spend-balance.is-total strong { color: var(--rk-emerald-hover); }
.rk-spend-operator { position: absolute; inset-inline-start: calc(-1 * var(--spend-balance-gap)); inset-block: 0; inline-size: var(--spend-balance-gap); display: grid; place-items: center; color: var(--rk-ink-muted); font-size: 14px; line-height: 1; font-weight: 700; }
.rk-spend-note { margin: 0; color: var(--rk-ink-soft); font-size: 13px; line-height: 1.5; }
.rk-spend-placeholder { color: var(--rk-ink-muted); }
.rk-spend-summary-message { padding: 16px; border: 1px solid var(--rk-line); border-radius: 12px; font-size: 14px; color: var(--rk-ink-soft); }
.rk-spend-filters { flex: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; padding: 4px; border-radius: 13px; background: var(--rk-paper-2); border: 1px solid var(--rk-line); }
.rk-spend-filters button { min-block-size: 42px; border: 0; border-radius: 9px; background: transparent; color: var(--rk-ink-soft); font-weight: 700; }
.rk-spend-filters button[aria-pressed="true"] { color: var(--rk-emerald-hover); background: var(--rk-surface); box-shadow: 0 1px 3px color-mix(in srgb, var(--rk-ink) 8%, transparent); }
.rk-spend-activity { flex: 1; min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; padding-inline: 2px 8px; }
.rk-spend .account-ledger { display: block; }
.rk-spend .account-ledger-row { min-block-size: 86px; padding-block: 18px; box-sizing: border-box; border-color: var(--rk-line); }
.rk-spend .account-ledger-details { gap: 7px; }
.rk-spend .account-ledger-scene { font-size: 16px; font-weight: 650; }
.rk-spend .account-ledger-date { font-size: 13px; }
.rk-spend .account-ledger-value { flex-direction: column; align-items: flex-end; gap: 3px; }
.rk-spend .account-ledger-original { direction: ltr; }
.rk-spend[dir="rtl"] [data-spend-back] span { display: inline-block; transform: scaleX(-1); }
.rk-spend .account-ledger-kind { display: none; }
.rk-spend .account-ledger-amount { font-size: 23px; font-weight: 750; color: var(--rk-ink); direction: ltr; }
.rk-spend .account-ledger-row.is-incoming .account-ledger-amount { color: var(--rk-emerald-hover); }
.rk-spend .account-ledger-row:not(.is-incoming) .account-ledger-amount { color: var(--rk-ink); }
.rk-modal.is-spending .rk-modal-x:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 3px; }
.rk-spend-empty { min-block-size: 180px; block-size: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 10px; color: var(--rk-ink-soft); }
.rk-spend-retry, .rk-spend-pager button { padding: 8px 18px; min-block-size: 40px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-surface); color: var(--rk-emerald-hover); }
.rk-spend-pager { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 12px; border-block-start: 1px solid var(--rk-line); padding-block-start: 14px; color: var(--rk-ink-soft); font-size: 14px; }
.rk-spend-pager[hidden] { display: none; }
@media (max-width: 600px) {
  .rk-modal.is-spending { padding: 12px; }
  .rk-modal.is-spending .rk-modal-panel { block-size: calc(100dvh - 24px); border-radius: 20px; }
  .rk-spend { padding: 24px 18px 16px; gap: 16px; }
  .rk-spend-heading { gap: 6px; align-items: flex-start; flex-direction: column; }
  .rk-spend-heading h2 { font-size: 24px; }
  .rk-spend-balances { display: grid; grid-template-columns: repeat(var(--spend-source-columns, 3), minmax(0, 1fr)); gap: 16px 12px; }
  .rk-spend-balance.is-total { grid-column: 1 / -1; padding-block-end: 12px; border-block-end: 1px solid var(--rk-line); }
  .rk-spend-balance.is-total strong { font-size: 30px; }
  .rk-spend-balance strong { font-size: 20px; }
  .rk-spend-balance { font-size: 12px; text-align: start; }
  .rk-spend-operator { display: none; }
  .rk-spend .account-ledger-scene { font-size: 15px; }
  .rk-spend .account-ledger-amount { font-size: 20px; }
  .rk-spend .account-ledger-row { gap: 10px; }
}
@media (max-height: 600px) {
  .rk-modal.is-spending .rk-modal-body { overflow-y: auto; }
  .rk-spend { block-size: auto; min-block-size: 100%; }
  .rk-spend-activity { flex: none; min-block-size: 180px; max-block-size: 55dvh; }
}

.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 compact stage, widened only enough for the carousel's two arrow buttons. */
  max-inline-size: min(212px, 42%);
  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;
}

/* Once a user owns a book, the physical-book guide replaces Pudding's shelf-end slot. The compact
   paper card stands on the plank while its transparent artwork and sparkles keep the object alive. */
.shelf-print-promo[hidden] {
  display: none;
}

.shelf-print-promo {
  --rk-print-promo-w: clamp(188px, 15vw, 206px);
  position: absolute;
  z-index: 5;
  inset-inline-end: 0;
  inset-block-end: 74%;
  inline-size: var(--rk-print-promo-w);
}

.rk-print-promo-card {
  box-sizing: border-box;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  inline-size: 100%;
  min-inline-size: 0;
  margin: 0;
  padding: 9px 10px 10px;
  overflow: visible;
  border: 1px solid color-mix(in srgb, var(--rk-emerald) 20%, var(--rk-line));
  border-radius: var(--rk-radius);
  outline: 0;
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
  color: var(--rk-ink);
  font: inherit;
  text-align: center;
  isolation: isolate;
  transition: transform 220ms ease-out, border-color 180ms ease-out, box-shadow 180ms ease-out;
}

.rk-print-promo-open {
  /* It is a button that opens the explanatory card; its chrome stays intentionally link-neutral. */
  text-decoration: none;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  inline-size: 100%;
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: inherit;
  cursor: pointer;
}

.rk-print-promo-dismiss {
  position: absolute;
  z-index: 7;
  inset-block-start: 2px;
  inset-inline-end: 2px;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-surface) 88%, transparent);
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: background 160ms ease-out, color 160ms ease-out, transform 160ms ease-out;
}

.rk-print-promo-dismiss svg {
  inline-size: 17px;
  block-size: 17px;
  stroke-width: 2;
}

.rk-print-promo-dismiss:hover {
  background: var(--rk-surface);
  color: var(--rk-ink);
  transform: scale(1.04);
}

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

.rk-print-promo-card:hover {
  border-color: color-mix(in srgb, var(--rk-emerald) 42%, var(--rk-line));
  box-shadow: var(--rk-shadow-panel);
  transform: translateY(-2px);
}

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

.rk-print-promo-art {
  position: relative;
  display: block;
  inline-size: 100%;
  aspect-ratio: 4 / 3;
  overflow: visible;
}

.rk-print-promo-art::after {
  position: absolute;
  z-index: 2;
  content: '';
  inset: 8% 10%;
  border-radius: 50%;
  background: linear-gradient(110deg, transparent 38%, color-mix(in srgb, var(--rk-surface) 72%, transparent) 50%, transparent 62%);
  opacity: 0;
  transform: translateX(-75%) rotate(-10deg);
  animation: rkPrintPromoSheen 4600ms ease-in-out infinite;
  pointer-events: none;
}

.rk-print-promo-artwork {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: center 51%;
  transform: translateY(0);
  transform-origin: 50% 70%;
  animation: rkPrintPromoArtworkFloat 3600ms cubic-bezier(0.2, 0.8, 0.2, 1) infinite;
}

.rk-print-promo-effects {
  position: absolute;
  z-index: 3;
  inset: -8% -10%;
  pointer-events: none;
}

.rk-print-promo-spark {
  --rk-spark-size: 12px;
  position: absolute;
  inline-size: var(--rk-spark-size);
  block-size: var(--rk-spark-size);
  color: var(--rk-amber);
  background: currentColor;
  clip-path: polygon(50% 0, 61% 39%, 100% 50%, 61% 61%, 50% 100%, 39% 61%, 0 50%, 39% 39%);
  opacity: 0;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--rk-amber) 58%, transparent));
  animation: rkPrintPromoSpark 2400ms ease-in-out infinite;
}

.rk-print-promo-spark.is-one {
  inset-block-start: 8%;
  inset-inline-start: 5%;
}

.rk-print-promo-spark.is-two {
  --rk-spark-size: 8px;
  inset-block-start: 2%;
  inset-inline-end: 20%;
  animation-delay: 560ms;
}

.rk-print-promo-spark.is-three {
  --rk-spark-size: 15px;
  inset-block-start: 46%;
  inset-inline-end: -1%;
  animation-delay: 1120ms;
}

.rk-print-promo-spark.is-four {
  --rk-spark-size: 9px;
  inset-block-end: 6%;
  inset-inline-start: 10%;
  animation-delay: 1640ms;
}

.rk-print-promo-spark.is-five {
  --rk-spark-size: 7px;
  inset-block-end: 20%;
  inset-inline-end: 13%;
  animation-delay: 2040ms;
}

.rk-print-promo-content {
  display: flex;
  min-block-size: 0;
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
  margin-block-start: 1px;
}

.rk-print-promo-title {
  display: -webkit-box;
  overflow: hidden;
  color: var(--rk-ink);
  font-family: var(--rk-font-display);
  font-size: 13px;
  line-height: 1.18;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.rk-print-promo-copy {
  display: -webkit-box;
  overflow: hidden;
  color: var(--rk-ink-soft);
  font-size: 9.5px;
  line-height: 1.3;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.rk-print-promo-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-block-size: 40px;
  margin-block-start: 4px;
  padding-inline: 10px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-size: 11px;
  font-weight: 800;
  line-height: 1.15;
  white-space: nowrap;
  text-overflow: ellipsis;
  transition: background 180ms ease-out, box-shadow 180ms ease-out;
}

.rk-print-promo-open:hover .rk-print-promo-cta {
  background: var(--rk-emerald-hover);
  box-shadow: 0 9px 18px -13px rgba(15, 164, 126, 0.85);
}

.rk-print-promo-cta-arrow {
  flex: none;
  font-size: 14px;
  line-height: 1;
}

[dir='rtl'] .rk-print-promo-cta-arrow {
  transform: scaleX(-1);
}

/* The shelf card is a gentle invitation, not enough context to route someone away immediately.
   This dialog gives the physical object room to explain itself, then offers one clear handoff. */
body.is-print-promo-dialog-open {
  overflow: hidden;
  overscroll-behavior: none;
}

.rk-print-promo-dialog-layer {
  position: fixed;
  z-index: 230;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 24px;
}

.rk-print-promo-dialog-backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  background: color-mix(in srgb, var(--rk-ink) 42%, transparent);
}

.rk-print-promo-dialog {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1fr);
  inline-size: min(860px, 100%);
  /* This is a fixed viewport-bound canvas, not content-led chrome. A still image, its loading
     placeholder, and an error caption all occupy the same panel, so changing samples cannot make
     the dialog jump. */
  block-size: min(520px, calc(100dvh - 48px));
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
}

.rk-print-promo-dialog-art {
  position: relative;
  display: grid;
  min-block-size: 100%;
  place-items: center;
  overflow: hidden;
  background: var(--rk-paper-2);
}

.rk-print-promo-dialog-sample-loading {
  inline-size: min(68%, 260px);
  aspect-ratio: 3 / 4;
  border-radius: var(--rk-radius-sm);
  background: linear-gradient(90deg, var(--rk-paper), var(--rk-line), var(--rk-paper));
  background-size: 200% 100%;
  animation: rkPrintPromoSampleShimmer 1.4s ease-in-out infinite;
}

.rk-print-promo-dialog-sample-empty {
  max-inline-size: 24ch;
  margin: 0;
  padding: 24px;
  color: var(--rk-ink-soft);
  line-height: 1.5;
  text-align: center;
}

.rk-print-promo-dialog-sample-step {
  position: absolute;
  z-index: 2;
  inset-block-start: 50%;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  padding: 0;
  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-ink);
  cursor: pointer;
  transform: translateY(-50%);
  transition: border-color 160ms ease-out, background 160ms ease-out, color 160ms ease-out;
}

.rk-print-promo-dialog-sample-step.is-next {
  inset-inline-end: 12px;
}

.rk-print-promo-dialog-sample-step.is-previous {
  inset-inline-start: 12px;
}

.rk-print-promo-dialog-sample-step svg {
  inline-size: 20px;
  block-size: 20px;
  stroke-width: 1.8;
}

.rk-print-promo-dialog-sample-step.is-next svg {
  transform: rotate(-90deg);
}

.rk-print-promo-dialog-sample-step.is-previous svg {
  transform: rotate(90deg);
}

[dir='rtl'] .rk-print-promo-dialog-sample-step.is-next svg {
  transform: rotate(90deg);
}

[dir='rtl'] .rk-print-promo-dialog-sample-step.is-previous svg {
  transform: rotate(-90deg);
}

.rk-print-promo-dialog-sample-step:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-print-promo-dialog-sample-step:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 2px;
}

.rk-print-promo-dialog-sample-position {
  position: absolute;
  inset-block-end: 12px;
  inset-inline-end: 12px;
  padding: 4px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-ink) 68%, transparent);
  color: var(--rk-surface);
  font-size: 0.78rem;
  line-height: 1;
}

.rk-print-promo-dialog-art img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  object-position: center;
}

.rk-print-promo-dialog-content {
  display: grid;
  grid-template-rows: auto auto auto minmax(0, 1fr) auto;
  align-content: stretch;
  gap: 12px;
  min-block-size: 0;
  padding: 38px 38px 32px;
}

.rk-print-promo-dialog-content h2,
.rk-print-promo-dialog-content p {
  margin: 0;
}

.rk-print-promo-dialog-content h2 {
  font-family: var(--rk-font-display);
  font-size: clamp(1.55rem, 3vw, 2rem);
  line-height: 1.18;
}

.rk-print-promo-dialog-title {
  max-inline-size: 16ch;
}

.rk-print-promo-ratio-info {
  position: relative;
  display: inline-grid;
  place-items: center;
  flex: none;
  inline-size: 28px;
  block-size: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--rk-ink-soft);
  cursor: help;
}

.rk-print-promo-ratio-info::after {
  position: absolute;
  z-index: 4;
  inset-block-end: calc(100% + 8px);
  inset-inline-end: 0;
  inline-size: max-content;
  max-inline-size: 240px;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--rk-ink);
  color: var(--rk-surface);
  content: attr(data-tooltip);
  font-size: 0.76rem;
  font-weight: 600;
  line-height: 1.35;
  opacity: 0;
  pointer-events: none;
  transform: translateY(4px);
  transition: opacity 140ms ease-out, transform 140ms ease-out;
}

.rk-print-promo-ratio-info:hover::after,
.rk-print-promo-ratio-info:focus-visible::after {
  opacity: 1;
  transform: translateY(0);
}

.rk-print-promo-ratio-info svg {
  inline-size: 20px;
  block-size: 20px;
  stroke-width: 1.8;
}

.rk-print-promo-ratio-info:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 3px;
}

.rk-print-promo-dialog-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-block-size: 48px;
  margin-block-start: 6px;
  padding-inline: 20px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: var(--rk-surface);
  font-weight: 800;
  text-decoration: none;
  transition: background 160ms ease-out;
}

.rk-print-promo-dialog-go:hover {
  background: var(--rk-emerald-hover);
}

.rk-print-promo-dialog-go svg {
  inline-size: 18px;
  block-size: 18px;
  transform: rotate(-90deg);
}

[dir='rtl'] .rk-print-promo-dialog-go svg {
  transform: rotate(90deg);
}

.rk-print-promo-dialog-close {
  position: absolute;
  z-index: 2;
  inset-block-start: 12px;
  inset-inline-end: 12px;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-surface) 92%, transparent);
  color: var(--rk-ink-soft);
  cursor: pointer;
  transition: border-color 160ms ease-out, background 160ms ease-out, color 160ms ease-out;
}

.rk-print-promo-dialog-close:hover {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald-soft);
  color: var(--rk-emerald-hover);
}

.rk-print-promo-dialog-close svg {
  inline-size: 19px;
  block-size: 19px;
  stroke-width: 1.8;
}

.rk-print-promo-dialog-close:focus-visible,
.rk-print-promo-dialog-go:focus-visible {
  outline: 3px solid var(--rk-focus-ring);
  outline-offset: 3px;
}

/* Reference composition: a paper collage and four illustrated stages share a fixed desktop frame.
   Container-relative dimensions scale the complete composition together on shorter laptops. */
.rk-print-promo-dialog.is-story-journey {
  box-sizing: border-box;
  container-type: inline-size;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  inline-size: min(1000px, 82vw, calc((100dvh - 112px) * 1.8));
  block-size: min(556px, calc(100dvh - 112px));
  background: var(--rk-paper);
}

.rk-print-promo-dialog.is-story-journey .rk-story-journey-art {
  min-block-size: 0;
  padding: 0.8cqi;
  background: var(--rk-paper);
}

.rk-story-journey-art .rk-story-journey-collage {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: contain;
  object-position: center;
}

.rk-print-promo-dialog.is-story-journey .rk-print-promo-dialog-content {
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 1.6cqi;
  padding: 2.6cqi 2.8cqi 2cqi;
  background: var(--rk-paper);
}

.rk-print-promo-dialog.is-story-journey .rk-print-promo-dialog-title {
  max-inline-size: 100%;
  padding-inline-end: 1.4cqi;
  margin: 0;
  font-size: 3.25cqi;
  line-height: 1.1;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

/* The selected reference explicitly uses editorial serif headings; scope that choice to this
   one illustration-led modal. Other V3 surfaces retain their existing type system. */
.rk-print-promo-dialog.is-story-journey:lang(en) .rk-print-promo-dialog-title,
.rk-print-promo-dialog.is-story-journey:lang(en) .rk-story-journey-step-label {
  font-family: Georgia, 'Times New Roman', serif;
}

.rk-story-journey-steps {
  position: relative;
  display: grid;
  grid-template-rows: repeat(4, minmax(0, 1fr));
  gap: 0.45cqi;
  min-block-size: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rk-story-journey-steps::before {
  position: absolute;
  inset-block: 12%;
  inset-inline-start: 5.7cqi;
  border-inline-start: 1px dashed var(--rk-ink-muted);
  content: '';
}

.rk-story-journey-steps li {
  position: relative;
  display: grid;
  grid-template-columns: 2.5cqi 5cqi minmax(0, 1fr) 13cqi;
  align-items: center;
  gap: 0.4cqi;
  min-block-size: 0;
  color: var(--rk-ink);
  font-size: 1.48cqi;
  font-weight: 750;
}

.rk-story-journey-step-icon {
  position: relative;
  display: grid;
  place-items: center;
  inline-size: 5cqi;
  block-size: 5cqi;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-emerald) 17%, var(--rk-paper));
  color: var(--rk-ink);
}

.rk-story-journey-step-icon svg {
  inline-size: 3cqi;
  block-size: 3cqi;
  stroke-width: 2.1;
}

.rk-story-journey-steps .is-character .rk-story-journey-step-icon {
  background: color-mix(in srgb, var(--rk-amber) 22%, var(--rk-paper));
}

.rk-story-journey-steps .is-print .rk-story-journey-step-icon {
  background: color-mix(in srgb, var(--rk-danger) 17%, var(--rk-paper));
}

.rk-story-journey-step-number {
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 2.5cqi;
  block-size: 2.5cqi;
  border-radius: 50%;
  background: color-mix(in srgb, var(--rk-ink) 7%, var(--rk-paper));
  color: var(--rk-ink);
  font-size: 1.35cqi;
  font-weight: 900;
  z-index: 1;
}

.rk-story-journey-step-label {
  min-inline-size: 0;
  line-height: 1.2;
  font-weight: 750;
}

.rk-story-journey-step-copy {
  min-inline-size: 0;
}

.rk-story-journey-step-heading {
  display: flex;
  align-items: center;
  gap: 5px;
}

.rk-story-journey-step-copy p {
  margin: 0.45cqi 0 0;
  color: var(--rk-ink-soft);
  font-size: max(14px, 1.12cqi);
  font-family: var(--rk-font-body);
  font-weight: 400;
  line-height: 1.4;
}

.rk-story-journey-step-visual {
  position: relative;
  display: grid;
  place-items: center;
  align-self: center;
  inline-size: min(100%, 9.2cqi);
  aspect-ratio: 1;
  block-size: auto;
  max-block-size: 100%;
  min-block-size: 0;
  overflow: visible;
  pointer-events: none;
}

.rk-story-journey-step-visual img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  max-inline-size: 100%;
  max-block-size: 100%;
  object-fit: contain;
  object-position: center;
}

.rk-print-promo-dialog.is-story-journey .rk-print-promo-dialog-close {
  inline-size: 3.6cqi;
  block-size: 3.6cqi;
  inset-block-start: 1cqi;
  inset-inline-end: 1cqi;
  border: 0;
  background: var(--rk-paper-2);
}

.rk-print-promo-dialog.is-story-journey .rk-print-promo-ratio-info {
  flex: none;
  inline-size: 24px;
  block-size: 24px;
}

.rk-story-journey-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.rk-story-journey-actions .rk-print-promo-dialog-go {
  flex: 1 1 0;
  min-inline-size: 0;
  min-block-size: 4.8cqi;
  padding: 0.7cqi 1cqi;
  margin: 0;
  font-size: 1.6cqi;
}

.rk-story-journey-actions .rk-print-promo-dialog-go.is-secondary {
  border: 1px solid var(--rk-emerald);
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
}

.rk-story-journey-actions .rk-print-promo-dialog-go.is-secondary:hover {
  background: var(--rk-emerald-soft);
}

@media (max-width: 640px) {
  .rk-print-promo-dialog-layer {
    align-items: end;
    padding: 12px;
  }

  .rk-print-promo-dialog {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(190px, 0.8fr) minmax(0, 1fr);
    block-size: min(680px, calc(100dvh - 24px));
  }

  .rk-print-promo-dialog-art {
    min-block-size: 0;
  }

  .rk-print-promo-dialog-sample-step.is-next {
    inset-inline-end: 10px;
  }

  .rk-print-promo-dialog-sample-step.is-previous {
    inset-inline-start: 10px;
  }

  .rk-print-promo-dialog-content {
    gap: 8px;
    padding: 24px 22px 20px;
  }
}

@keyframes rkPrintPromoArtworkFloat {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}

@keyframes rkPrintPromoSheen {
  0%, 68%, 100% { opacity: 0; transform: translateX(-75%) rotate(-10deg); }
  76% { opacity: 0.72; }
  88% { opacity: 0; transform: translateX(75%) rotate(-10deg); }
}

@keyframes rkPrintPromoSpark {
  0%, 58%, 100% { opacity: 0; transform: scale(0.3); }
  68% { opacity: 1; transform: scale(1); }
  79% { opacity: 0.18; transform: scale(0.55); }
}

@keyframes rkPrintPromoSampleShimmer {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

.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-carousel {
  position: relative;
  display: grid;
  grid-template-columns: 24px 160px 24px;
  align-items: center;
  inline-size: 208px;
  block-size: 128px;
}

.rk-showcase-carousel-stage {
  position: relative;
  inline-size: 160px;
  block-size: 128px;
}

.rk-showcase-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(4px) scale(0.97);
  transition: opacity 180ms ease-out, transform 220ms ease-out;
}

.rk-showcase-slide.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
}

.rk-showcase-carousel-arrow {
  position: relative;
  z-index: 6;
  display: grid;
  place-items: center;
  inline-size: 24px;
  block-size: 32px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: color-mix(in srgb, var(--rk-surface) 88%, transparent);
  box-shadow: 0 2px 8px rgba(66, 54, 40, 0.12);
  color: var(--rk-ink-soft);
  font: 700 24px/1 Georgia, serif;
  cursor: pointer;
}

.rk-showcase-carousel-arrow:hover,
.rk-showcase-carousel-arrow:focus-visible {
  background: var(--rk-surface);
  color: var(--rk-emerald);
}

.rk-showcase-carousel-arrow:focus-visible {
  outline: 2px solid var(--rk-emerald);
  outline-offset: 2px;
}

.rk-showcase-card {
  --rk-book-scale: 1;
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  inline-size: 160px;
  block-size: 128px;
  min-block-size: 128px;
  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);
}

/* A compact version of the shelf's closed book, with its own scale independent of shelf capacity. */
.rk-showcase-book {
  position: absolute;
  z-index: 2;
  inset-inline: 0;
  margin-inline: auto;
  inset-block-end: 17px;
  display: block;
  flex: none;
  inline-size: calc(var(--book-w) * var(--rk-book-scale));
  block-size: calc(var(--book-h) * var(--rk-book-scale));
  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);
}

.rk-showcase-book::before {
  content: '';
  position: absolute;
  inset-inline: -10%;
  inset-block-end: -6px;
  block-size: 10px;
  background: radial-gradient(ellipse, rgba(43, 42, 38, 0.24), transparent 70%);
  filter: blur(2px);
}

.rk-showcase-closed-book {
  display: block;
}

.rk-showcase-cover-art {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.rk-showcase-closed-book .book-spine span {
  font-size: 5px;
}

.rk-showcase-closed-book .book-face.is-blank {
  padding: 8px;
}

.rk-showcase-closed-book .blank-title {
  font-size: 11px;
}

/* 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(212px, 42%);
  }

  .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: 112px;
  }

  .rk-showcase-card {
    --rk-book-scale: 0.85;
    inline-size: 142px;
    block-size: 112px;
    min-block-size: 112px;
  }

  .rk-showcase-carousel {
    grid-template-columns: 22px 142px 22px;
    inline-size: 186px;
    block-size: 112px;
  }

  .rk-showcase-carousel-stage {
    inline-size: 142px;
    block-size: 112px;
  }

  .rk-showcase-carousel-arrow {
    inline-size: 22px;
    block-size: 30px;
    font-size: 22px;
  }

  .rk-showcase-book {
    inset-block-end: 17px;
  }

  .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;
  }

  .rk-print-promo-artwork,
  .rk-print-promo-art::after,
  .rk-print-promo-spark,
  .rk-print-promo-dialog-sample-loading {
    animation: none;
  }

  .rk-print-promo-artwork { transform: none; }
  .rk-print-promo-art::after { display: none; }
  .rk-print-promo-spark { opacity: 0.62; transform: scale(0.7); }

  .rk-print-promo-card,
  .rk-print-promo-open,
  .rk-print-promo-dismiss,
  .rk-print-promo-cta,
  .rk-print-promo-dialog-go,
  .rk-print-promo-dialog-close,
  .rk-print-promo-dialog-sample-step {
    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 viewport takes whatever the tabs/actions leave. It owns both the iframe and the immediate
   loading state, so a slow reader never exposes a blank paper slab. */
.rk-showcase-viewport {
  position: relative;
  flex: 1;
  min-block-size: 0;
  display: grid;
  overflow: hidden;
  background: #f8f5ee;
}

.rk-showcase-viewport > .rk-showcase-frame,
.rk-showcase-viewport > .rk-showcase-loading {
  grid-area: 1 / 1;
}

.rk-showcase-viewport > .rk-showcase-frame {
  min-block-size: 0;
}

.rk-showcase-loading {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  background: #f8f5ee;
  opacity: 1;
  visibility: visible;
  transition: opacity 180ms ease-out, visibility 180ms ease-out;
}

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

.rk-showcase-loading [data-showcase-retry][hidden] {
  display: none;
}

.rk-showcase-loading .rk-app-loading-text {
  max-inline-size: 32ch;
  text-align: center;
}

@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;
  }
}

/* Per-stage breakdown inside a film task card. Replaces the single "x / y results" line, whose
   denominator was the quote's shot cap and whose unit meant nothing to the person waiting. */
.rk-task-float-stages {
  display: grid;
  margin: 0;
  padding: 0;
  gap: 2px;
  list-style: none;
}

.rk-task-float-stages li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  color: var(--rk-ink-soft);
  font-size: 0.72rem;
}

.rk-task-float-stages li b {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.rk-task-float-stages li.is-done {
  opacity: 0.55;
}

.rk-task-float-stages li.is-active {
  color: var(--rk-ink);
}

.rk-task-float-stages li.is-active b {
  color: var(--rk-emerald);
}

.rk-task-float-stages li.is-partial {
  color: var(--rk-ink);
}

.rk-task-float-stages li.is-partial b {
  color: var(--rk-amber, #b87300);
}

/* Terminal note on a film card — a delivery that is short of shots has to say so. */
.rk-task-float-note {
  margin: 0;
  padding: 8px 10px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--rk-emerald) 8%, transparent);
  color: var(--rk-ink-soft);
  font-size: 0.75rem;
  line-height: 1.45;
}

/* Standing explanation for the one-click switch — the native title tooltip it replaces was invisible
   to anyone who does not hover, and this switch commits thousands of credits. */
.sb-one-click-hint {
  margin: 8px 2px 0;
  color: var(--rk-ink-soft);
  font-size: 0.78rem;
  line-height: 1.5;
}

/* ── 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. */
/* The layer variant is shared: `is-over-{product}` comes from media-showcase.js, so publishing a
   film for a product also lights this button up over ITS layer. Kids MV joined on 2026-08-21 and
   needs the same treatment — a ghost pill on a full-bleed film is barely visible. */
.anim-screen-empty.is-showcase > .rk-sc-tutorial.is-on-video-poster,
.rk-mshow-layer .rk-sc-tutorial.is-over-video,
.rk-mshow-layer .rk-sc-tutorial.is-over-kidsmv {
  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,
.rk-mshow-layer .rk-sc-tutorial.is-over-kidsmv:hover,
.rk-mshow-layer .rk-sc-tutorial.is-over-kidsmv: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-actions.is-read-only {
  grid-template-columns: minmax(0, 180px);
}

.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);
  }
}

/* 「更新到角色工坊」— sits under the version strip in the art desk / asset inspector.
   Two-step: the bare button arms, the armed block states the consequence and confirms. Quiet by
   default because it is an occasional action, not part of the drawing loop. */
.anim-as-insp-library {
  display: flex;
  justify-content: flex-start;
  padding-block: 2px 8px;
}

.anim-as-insp-library.is-armed {
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: 12px;
  background: var(--rk-paper-2);
}

.anim-as-insp-library.is-armed .sb-as-insp-hint {
  margin: 0;
}

.anim-as-insp-library-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

/* Storybook asset inspector — the armed state of 「更新到角色工坊」. Mirrors the art desk's block so
   the same action reads the same way on both product lines. */
.sb-as-insp-push.is-armed {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--rk-line);
  border-radius: 12px;
  background: var(--rk-paper-2);
}

.sb-as-insp-push.is-armed .sb-as-insp-hint {
  margin: 0;
}

.sb-as-insp-push-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.sb-as-insp-sync.is-primary {
  border-color: var(--rk-emerald);
  color: var(--rk-emerald);
}

/* ── page-level batch: stop entry + confirm dialogs (2026-08-28) ─────────────────────────────── */

/* The stop control is deliberately quiet and sits BESIDE the batch button, never replacing it.
   A press aimed at "hurry up" must not be able to land on a destructive action — that is the same
   root cause as the 2026-08-10 misfire this whole restoration answers. */
.anim-batch-stop {
  margin-inline-start: 8px;
  border: 0;
  background: transparent;
  color: var(--rk-ink-3);
  font-size: 12.5px;
  text-decoration: underline;
  cursor: pointer;
  padding: 4px 6px;
}
.anim-batch-stop:hover { color: var(--rk-ink-1); }

.anim-batch-dialog h3 {
  margin: 0 0 12px;
  font-size: 18px;
  font-weight: 800;
  color: var(--rk-ink-1);
}
.anim-batch-total {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 2px;
}
.anim-batch-total b { font-size: 28px; font-weight: 800; color: var(--rk-ink-1); }
.anim-batch-total span { font-size: 13px; color: var(--rk-ink-3); }
.anim-batch-strike {
  margin: 0 0 10px;
  font-size: 13px;
  color: var(--rk-ink-3);
  text-decoration: line-through;
}
/* The breakdown is what makes the on-screen arithmetic add up to the board the author sees.
   Without it, "8 shots" next to a 20-cell board reads as a bug. */
.anim-batch-breakdown {
  list-style: none;
  margin: 14px 0;
  padding: 0;
  border-block-start: 1px solid var(--rk-line);
}
.anim-batch-breakdown li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  font-size: 13.5px;
  color: var(--rk-ink-3);
  border-block-end: 1px solid var(--rk-line);
}
.anim-batch-breakdown li.is-primary { color: var(--rk-ink-1); font-weight: 700; }
.anim-batch-unit, .anim-batch-balance, .anim-batch-note {
  margin: 6px 0;
  font-size: 13px;
  color: var(--rk-ink-3);
}
.anim-batch-balance.is-short { color: var(--rk-danger, #c0392b); }
.anim-batch-note { font-size: 12.5px; margin-block: 2px 0; }
/* The 「不重复收费」 aside on the already-done line — quiet, but on the line where the doubt lives. */
.anim-batch-breakdown i { font-style: normal; color: var(--rk-ink-3); font-size: 12px; margin-inline-start: 6px; }
.anim-batch-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-block-start: 18px;
}
/* Stop reads as destructive but stays SECONDARY — the safe choice keeps the primary pill. Ghost
   already gives it the quieter weight; this only recolours it so the danger is legible without
   competing with 「继续生成」 for the eye. */
.anim-batch-danger {
  color: var(--rk-danger, #c0392b);
  border-color: color-mix(in srgb, var(--rk-danger, #c0392b) 35%, transparent);
}
.anim-batch-danger:hover {
  background: color-mix(in srgb, var(--rk-danger, #c0392b) 8%, var(--rk-surface));
}

/* Picture-book publication is one compact action, shared by Home and My Works. */
.rk-modal.is-publication .rk-modal-panel.is-publication {
  inline-size: min(460px, calc(100vw - 24px));
  padding: 24px;
}

.publication-dialog { display: grid; gap: 18px; }
.publication-dialog-header { display: flex; align-items: center; gap: 8px; padding-inline-end: 32px; }
.publication-dialog-header h2 { margin: 0; font-size: 22px; line-height: 1.2; }
.publication-info-button {
  display: grid;
  place-items: center;
  inline-size: 22px;
  block-size: 22px;
  padding: 0;
  border: 1px solid var(--rk-line);
  border-radius: 50%;
  background: transparent;
  color: var(--rk-ink-soft);
  font: 800 13px/1 Georgia, serif;
  cursor: pointer;
}
.publication-info-button:hover,
.publication-info-button.is-active { border-color: var(--rk-emerald); color: var(--rk-emerald-hover); }
.publication-info-button:focus-visible { outline: 3px solid var(--rk-focus-ring); outline-offset: 2px; }
.publication-dialog-info { margin: -8px 0 0; color: var(--rk-ink-soft); font-size: 13px; line-height: 1.55; }
.publication-dialog-book { display: flex; align-items: center; gap: 14px; min-inline-size: 0; }
.publication-dialog-cover {
  inline-size: 72px;
  block-size: 92px;
  flex: 0 0 auto;
  border-radius: 8px;
  object-fit: cover;
  background: var(--rk-paper-2);
  box-shadow: 0 10px 24px -18px color-mix(in srgb, var(--rk-ink) 48%, transparent);
}
.publication-dialog-cover.is-empty { border: 1px solid var(--rk-line); }
.publication-dialog-book-copy { display: grid; gap: 8px; min-inline-size: 0; }
.publication-dialog-book-copy strong { overflow: hidden; font-size: 16px; text-overflow: ellipsis; white-space: nowrap; }
.publication-dialog-book-copy > span { color: var(--rk-ink-soft); font-size: 13px; }
.publication-status { inline-size: fit-content; border-radius: 999px; padding: 5px 10px; font-weight: 800; }
.publication-status.is-live { background: var(--rk-emerald-soft); color: var(--rk-emerald-hover); }
.publication-status.is-pending { background: var(--rk-paper-2); color: var(--rk-ink-soft); }
.publication-status.is-rejected,
.publication-status.is-takenDown { background: #fbeaea; color: #a93636; }
.publication-review-feedback { margin: -4px 0 0; border-inline-start: 3px solid var(--rk-danger); border-radius: 8px; padding: 10px 12px; background: #fff4f4; color: #8e3030; font-size: 13px; line-height: 1.5; overflow-wrap: anywhere; }
.publication-dialog-error { margin: -6px 0 0; color: var(--rk-danger); font-size: 13px; }
.publication-dialog-actions { display: flex; justify-content: flex-end; gap: 10px; }
.publication-primary,
.publication-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 42px;
  border-radius: 11px;
  padding-inline: 16px;
  font-size: 14px;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
}
.publication-primary { border: 1px solid var(--rk-emerald); background: var(--rk-emerald); color: #fff; }
.publication-primary:hover { border-color: var(--rk-emerald-hover); background: var(--rk-emerald-hover); }
.publication-secondary { border: 1px solid var(--rk-line); background: var(--rk-surface); color: var(--rk-ink); }
.publication-primary:disabled,
.publication-secondary:disabled { cursor: wait; opacity: .58; }
.publication-primary:focus-visible,
.publication-secondary:focus-visible { outline: 3px solid var(--rk-focus-ring); outline-offset: 2px; }
.publication-alert { display: grid; justify-items: center; gap: 16px; padding: 10px 4px 2px; text-align: center; }
.publication-alert h2 { max-inline-size: 330px; margin: 0; font-size: 17px; line-height: 1.5; }

/* Share dialogs (film share + contest / Discover share), Kim 2026-11-08 design — the same look as the picture-book
   "Share this book": title row, one row of brand-marked platforms (selected one ticked), the card beside its link
   and actions, a management row, then the Discover publication row. */
.rk-modal.is-film-share { padding: 12px; }
.rk-modal-panel.is-film-share {
  inline-size: min(1010px, 100%);
  max-block-size: 92dvh;
  padding: 0;
  overflow: hidden;
  border-radius: 28px;
  background: var(--rk-paper);
}
.rk-modal-panel.is-film-share .rk-modal-body { max-block-size: inherit; }
.rk-modal-panel.is-film-share .rk-modal-x { inset-block-start: 24px; inset-inline-end: 24px; background: transparent; }
.film-share-dialog { grid-template-rows: auto minmax(0, 1fr); gap: 0; max-block-size: inherit; }
.film-share-dialog svg { inline-size: 18px; block-size: 18px; flex: 0 0 auto; }
.film-share-header { display: flex; align-items: flex-start; gap: 16px; padding: 28px 32px 0; padding-inline-end: 76px; }
.film-share-dialog .film-share-header > svg { inline-size: 30px; block-size: 30px; margin-block-start: 3px; color: var(--rk-emerald-hover); }
.film-share-header h2 { margin: 0; color: var(--rk-ink); font-size: 26px; font-weight: 800; line-height: 1.2; }
.film-share-header .film-share-muted { margin-block-start: 6px; font-size: 16px; }
.film-share-content { display: grid; align-content: start; min-block-size: 0; overflow-y: auto; padding: 0 32px 28px; overscroll-behavior: contain; }
.film-share-friends { min-inline-size: 0; margin-block-start: 22px; border-block-start: 1px solid var(--rk-line); }
.film-share-sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.film-share-muted { margin: 0; color: var(--rk-ink-soft); font-size: 14px; line-height: 1.5; }
.film-share-pad { padding-block: 20px; }
.film-share-consent { display: flex; align-items: flex-start; gap: 8px; border: 1px solid var(--rk-line); border-radius: 12px; padding: 12px 14px; background: var(--rk-surface); font-size: 14px; line-height: 1.5; cursor: pointer; }
.film-share-consent input { flex: 0 0 auto; margin-block-start: 3px; accent-color: var(--rk-emerald); }
.film-share-create { display: grid; gap: 14px; padding-block: 20px; border-block-end: 1px solid var(--rk-line); }
.film-share-create .film-share-row { margin: 0; }

/* One row of platforms: brand mark over the name; the selected one is a white tile with a green tick. */
.film-share-platforms { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 6px; padding-block: 20px; border-block-end: 1px solid var(--rk-line); }
.film-share-chip {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-inline-size: 0;
  min-block-size: 84px;
  padding: 10px 4px;
  border: 1.5px solid transparent;
  border-radius: 12px;
  background: transparent;
  color: var(--rk-ink);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.film-share-chip:hover:not(:disabled) { background: color-mix(in srgb, var(--rk-surface) 70%, transparent); }
.film-share-chip[aria-pressed="true"] { border-color: var(--rk-emerald); background: var(--rk-surface); box-shadow: 0 1px 3px rgba(43, 42, 38, .08); }
.film-share-chip[aria-pressed="true"]::after {
  content: '';
  position: absolute;
  inset-block-start: -7px;
  inset-inline-end: -7px;
  inline-size: 20px;
  block-size: 20px;
  border-radius: 50%;
  background: var(--rk-emerald) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 12px no-repeat;
  box-shadow: 0 0 0 2px var(--rk-paper);
}
.film-share-chip:disabled { opacity: .45; cursor: default; }
.film-share-chip-icon { display: grid; place-items: center; inline-size: 36px; block-size: 36px; }
.film-share-dialog .film-share-chip-icon svg { inline-size: 100%; block-size: 100%; }
.film-share-chip-label { max-inline-size: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The card beside its link and actions. */
.film-share-preview-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, .92fr); align-items: center; gap: 28px; padding-block: 24px; }
.film-share-card-col { min-inline-size: 0; }
.film-share-card-frame { padding: 0; border-radius: 16px; background: none; }
.film-share-card { position: relative; isolation: isolate; display: grid; align-content: end; gap: 6px; aspect-ratio: 1200 / 630; overflow: hidden; padding: 12px; border-radius: 16px; background: var(--rk-paper-2); color: var(--rk-ink); box-shadow: 0 14px 32px -16px rgba(43, 42, 38, .55); }
.film-share-card > img { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover; }
.film-share-card > img[hidden] { display: none; }
.film-share-card > img:not(.film-share-platform-card) { opacity: .42; }
.film-share-card > img.film-share-platform-card { z-index: 2; object-fit: contain; background: var(--rk-paper-2); }
.film-share-card strong, .film-share-play { position: relative; z-index: 1; overflow-wrap: anywhere; }
.film-share-play { display: grid; place-items: center; inline-size: 30px; block-size: 30px; border-radius: 50%; background: var(--rk-surface); color: var(--rk-emerald-hover); }
.film-share-caption { margin: 10px 0 0; color: var(--rk-ink-soft); font-size: 14px; }
.film-share-details { display: grid; min-inline-size: 0; overflow-wrap: anywhere; }
.film-share-details > strong { color: var(--rk-ink); font-size: 20px; line-height: 1.35; }
.film-share-details > .film-share-muted { margin-block-start: 4px; }
.film-share-link { display: flex; min-inline-size: 0; margin-block-start: 20px; overflow: hidden; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-surface); }
.film-share-url { flex: 1 1 auto; min-inline-size: 0; min-block-size: 52px; border: 0; padding-inline: 16px; background: transparent; color: var(--rk-ink-soft); font: inherit; font-size: 15px; }
.film-share-url:focus-visible { outline: 3px solid var(--rk-focus-ring); outline-offset: -3px; }
.film-share-copy { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; padding-inline: 16px; border: 0; border-inline-start: 1px solid var(--rk-line); background: transparent; color: var(--rk-emerald-hover); font: inherit; font-size: 15px; font-weight: 700; cursor: pointer; }
.film-share-copy:hover { background: var(--rk-emerald-soft); }
.film-share-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px; margin-block-start: 16px; }
.film-share-primary { display: inline-flex; align-items: center; gap: 10px; min-block-size: 52px; padding-inline: 24px; border: 0; border-radius: 12px; background: var(--rk-emerald); color: #fff; font: inherit; font-size: 16px; font-weight: 800; cursor: pointer; box-shadow: 0 1px 2px rgba(43, 42, 38, .1); }
.film-share-primary:hover:not(:disabled) { background: var(--rk-emerald-hover); }
.film-share-primary:disabled { opacity: .55; cursor: not-allowed; }
.film-share-quiet { display: inline-flex; align-items: center; gap: 8px; min-block-size: 44px; padding: 0; border: 0; background: transparent; color: var(--rk-emerald-hover); font: inherit; font-size: 15px; font-weight: 700; text-decoration: none; cursor: pointer; }
.film-share-quiet:hover { text-decoration: underline; }
.film-share-quiet.is-danger { color: var(--rk-danger); }
.film-share-quiet:disabled { opacity: .58; cursor: wait; }
.film-share-chip:focus-visible, .film-share-quiet:focus-visible, .film-share-primary:focus-visible, .film-share-copy:focus-visible, .film-share-outline:focus-visible { outline: 3px solid var(--rk-focus-ring); outline-offset: 2px; }
.film-share-notice { margin: 0 0 16px; color: var(--rk-emerald-hover); font-size: 14px; }

/* Management: update | stop sharing. */
.film-share-manage { display: grid; gap: 6px; padding-block: 12px; border-block: 1px solid var(--rk-line); }
.film-share-manage-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 20px; }
.film-share-rule { inline-size: 1px; block-size: 24px; background: var(--rk-line); }
.publication-secondary.is-danger { color: var(--rk-danger); }

/* Publication: icon, title and line, one outlined action. */
.film-share-publish { display: grid; gap: 12px; padding-block-start: 20px; }
.film-share-publish-row { display: flex; align-items: center; flex-wrap: wrap; gap: 16px; }
.film-share-publish-icon { display: grid; place-items: center; flex: 0 0 56px; block-size: 56px; border-radius: 14px; background: var(--rk-emerald-soft); color: var(--rk-emerald-hover); }
.film-share-dialog .film-share-publish-icon svg { inline-size: 28px; block-size: 28px; }
.film-share-publish-copy { display: grid; justify-items: start; gap: 4px; flex: 1 1 260px; min-inline-size: 0; }
.film-share-publish-copy h3 { margin: 0; color: var(--rk-ink); font-size: 18px; font-weight: 800; }
.film-share-publish-copy .film-share-muted { font-size: 15px; }
.film-share-publish-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.film-share-outline { display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-block-size: 52px; padding-inline: 24px; border: 1.5px solid var(--rk-emerald); border-radius: 12px; background: var(--rk-surface); color: var(--rk-emerald-hover); font: inherit; font-size: 16px; font-weight: 800; text-decoration: none; cursor: pointer; }
.film-share-outline:hover:not(:disabled) { background: var(--rk-emerald-soft); }
.film-share-outline:disabled { opacity: .55; cursor: not-allowed; }
.film-share-outline.is-danger { border-color: color-mix(in srgb, var(--rk-danger) 55%, var(--rk-line)); color: var(--rk-danger); }
@media (max-width: 900px) {
  .film-share-platforms { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
@media (max-width: 650px) {
  .film-share-preview-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 520px) {
  .film-share-header { padding: 20px 16px 0; padding-inline-end: 60px; }
  .film-share-content { padding: 0 16px 20px; }
  .film-share-platforms { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .film-share-header h2 { font-size: 22px; }
}

@media (max-width: 520px) {
  .rk-modal.is-publication .rk-modal-panel.is-publication { padding: 22px 18px 18px; }
  .publication-dialog-actions { flex-direction: column-reverse; }
  .publication-primary,
  .publication-secondary { inline-size: 100%; }
  .film-share-dialog .publication-dialog-actions { flex-direction: row; }
  .film-share-dialog .publication-primary,
  .film-share-dialog .publication-secondary { inline-size: auto; }
}

/* ── Creator-economy shared dialog styles (application + sell-this-book dialogs; opened from the
   account AND works pages, so they live in the global sheet, not account.css) ────────────────── */

.rk-creator-form { display: grid; gap: 14px; }

.rk-creator-reqs {
  margin: 0;
  padding: 10px 12px;
  list-style: none;
  display: grid;
  gap: 6px;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
}
.rk-creator-req {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--rk-ink);
}
.rk-creator-req-mark {
  display: inline-flex;
  inline-size: 16px;
  block-size: 16px;
}
.rk-creator-req-mark svg { inline-size: 100%; block-size: 100%; }
.rk-creator-req.is-pass .rk-creator-req-mark { color: var(--rk-emerald); }
.rk-creator-req.is-fail .rk-creator-req-mark { color: var(--rk-danger); }

.rk-creator-noteligible {
  margin: -6px 0 0;
  color: var(--rk-ink-soft);
  font-size: 12px;
}

.rk-creator-mode,
.rk-creator-doctype {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  font-size: 13px;
  color: var(--rk-ink);
}
.rk-creator-mode label,
.rk-creator-doctype label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
.rk-creator-mode input,
.rk-creator-doctype input { accent-color: var(--rk-emerald); }

.rk-creator-names {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
@media (max-width: 560px) { .rk-creator-names { grid-template-columns: 1fr; } }

.rk-creator-bio { resize: vertical; }

.rk-creator-docs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
}
.rk-creator-doc {
  position: relative;
  inline-size: 96px;
  block-size: 68px;
  border: 1px solid var(--rk-line);
  border-radius: 8px;
  overflow: hidden;
}
.rk-creator-doc img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}
.rk-creator-doc-remove {
  position: absolute;
  inset-block-start: 2px;
  inset-inline-end: 2px;
  inline-size: 20px;
  block-size: 20px;
  padding: 3px;
  border: 0;
  border-radius: 6px;
  background: color-mix(in srgb, var(--rk-ink) 55%, transparent);
  color: #fff;
  cursor: pointer;
}
.rk-creator-doc-remove svg { inline-size: 100%; block-size: 100%; }

.rk-creator-links {
  display: grid;
  gap: 8px;
  margin-bottom: 8px;
}
.rk-creator-link-row {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 28px;
  align-items: center;
  gap: 8px;
}
.rk-creator-link-mark {
  display: inline-flex;
  inline-size: 22px;
  block-size: 22px;
  color: var(--rk-ink-soft);
}
.rk-creator-link-mark svg { inline-size: 100%; block-size: 100%; }
.rk-creator-link-remove {
  inline-size: 26px;
  block-size: 26px;
  padding: 5px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--rk-ink-muted);
  cursor: pointer;
}
.rk-creator-link-remove:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.rk-creator-link-remove svg { inline-size: 100%; block-size: 100%; }

.rk-creator-note {
  margin: 0 0 4px;
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: 10px;
  background: var(--rk-paper-2);
}
.rk-creator-note-label {
  display: block;
  margin-bottom: 4px;
  color: var(--rk-ink-muted);
  font-size: 12px;
  font-weight: 800;
}
.rk-creator-note p {
  margin: 0;
  color: var(--rk-ink);
  font-size: 13px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

.rk-listing-book {
  display: flex;
  align-items: center;
  gap: 12px;
}
.rk-listing-cover {
  inline-size: 56px;
  block-size: 56px;
  border-radius: 10px;
  object-fit: cover;
  border: 1px solid var(--rk-line);
}
.rk-listing-book-copy { display: flex; flex-direction: column; gap: 3px; min-inline-size: 0; }
.rk-listing-book-copy strong { font-size: 15px; color: var(--rk-ink); overflow-wrap: anywhere; }
.rk-listing-price { font-size: 13px; font-weight: 800; color: var(--rk-emerald); }

/* ── Storybook: deferred-director reading page + 导演链 3.0 dialog (2026-09-02) ──────────────────
   docs/prd-v3-storybook-deferred-director.md §3 / §5. The story page for a book whose director runs
   after the subscription wall: prose centered, one dock at the bottom carrying the refine input and
   THE primary action. Quiet paper rules: one emerald element, hairlines, transform/opacity motion. */
.sb-story-grid.is-centered {
  grid-template-columns: minmax(0, 760px);
  justify-content: center;
  width: min(100%, 760px);
}

.sb-prose-panel.is-reading .sb-prose-scroll {
  padding-inline: clamp(20px, 5vw, 56px);
}

.sb-story-dock {
  flex: none;
  position: sticky;
  bottom: 0;
  background: var(--rk-surface);
}

/* 「这个故事一本装不下」。摆在续作按钮正上方，作者锁画风、付导演费之前就能看见。
   不是报错色：故事写长了不是他做错了什么，只是这一本放不下。 */
.sb-story-toolong {
  margin: 0 0 10px;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.9rem;
  line-height: 1.5;
}

.sb-story-dock .sb-refine-bar {
  align-items: center;
  gap: 12px;
}

.sb-story-dock .sb-refine-form {
  min-width: 0;
}

.sb-story-dock-cta {
  flex: none;
  display: flex;
}

.sb-story-next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 52px;
  padding-inline: 22px 18px;
  font-size: 1rem;
  white-space: nowrap;
  box-shadow: 0 6px 18px rgba(15, 164, 126, 0.22);
  transition: transform 180ms ease-out, box-shadow 180ms ease-out, opacity 180ms ease-out;
}

.sb-story-next svg {
  width: 18px;
  height: 18px;
}

.sb-story-next:not(:disabled):hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 24px rgba(15, 164, 126, 0.28);
}

.sb-story-next:disabled {
  box-shadow: none;
}

@keyframes sb-story-next-pulse {
  0% { transform: scale(1); }
  35% { transform: scale(1.05); }
  100% { transform: scale(1); }
}

.sb-story-next.is-pulse {
  animation: sb-story-next-pulse 620ms cubic-bezier(0.2, 0.9, 0.3, 1.2) 1;
}

@media (prefers-reduced-motion: reduce) {
  .sb-story-next.is-pulse { animation: none; }
}

.sb-story-end {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  margin: 28px 0 12px;
  padding: 16px 18px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper-2);
}

.sb-story-end img {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
}

.sb-story-end-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.sb-story-end-copy strong {
  font-size: 0.98rem;
}

.sb-story-end-copy span {
  color: var(--rk-ink-soft);
  font-size: 0.86rem;
  line-height: 1.45;
}

@media (max-width: 767px) {
  .sb-story-dock .sb-refine-bar {
    flex-wrap: wrap;
    padding: 12px 14px 14px;
  }

  .sb-story-dock .sb-refine-avatar {
    order: 2;
  }

  .sb-story-dock .sb-refine-form {
    order: 3;
    flex: 1 1 calc(100% - 50px);
  }

  .sb-story-dock-cta {
    order: 1;
    flex: 1 1 100%;
  }

  .sb-story-dock-cta .sb-story-next {
    width: 100%;
    min-height: 48px;
  }

  .sb-story-end {
    grid-template-columns: 44px minmax(0, 1fr);
  }

  .sb-story-end .sb-story-next {
    grid-column: 1 / -1;
    width: 100%;
  }
}

/* 导演链 3.0 dialog */
/* Andy 2026-09-02 走查：十一行阶段清单挤成一团，「再宽一些，增加 50%」。The panel used to size to its
   content (~500px on a desktop); a bigger max-width alone changes nothing, so the width is set outright. */
.rk-modal.is-director-run .rk-modal-panel.is-form {
  width: min(750px, calc(100vw - 32px));
  max-width: none;
}

.sb-director-modal {
  display: grid;
  justify-items: center;
  gap: 12px;
  padding: 8px 4px 4px;
  text-align: center;
}

.sb-director-mascot {
  width: 120px;
  height: 120px;
  object-fit: contain;
}

.sb-director-title {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.sb-director-eta,
.sb-director-keep,
.sb-director-detail {
  margin: 0;
  color: var(--rk-ink-soft);
  font-size: 0.9rem;
  line-height: 1.5;
}

.sb-director-detail {
  color: var(--rk-ink-muted);
  font-size: 0.8rem;
  word-break: break-word;
}

.sb-director-progress {
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: var(--rk-progress-track, var(--rk-paper-2));
  overflow: hidden;
}

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

.sb-director-rows {
  display: grid;
  gap: 10px;
  width: 100%;
  margin: 6px 0 0;
  padding: 0 8px;
  list-style: none;
  text-align: start;
}

.rk-task-float-director-stages {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: start;
}
.rk-task-float-director-stages .sb-director-row {
  grid-template-columns: 14px minmax(0, 1fr);
  gap: 8px;
  font-size: 0.75rem;
}
.rk-task-float-director-stages .sb-director-row i { width: 10px; height: 10px; }

.sb-director-row {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  color: var(--rk-ink-muted);
  font-size: 0.95rem;
  line-height: 1.45;
}

.sb-director-row i {
  width: 14px;
  height: 14px;
  border: 1.5px solid var(--rk-line);
  border-radius: 50%;
  background: var(--rk-surface);
  justify-self: center;
}

.sb-director-row.is-active {
  color: var(--rk-ink);
  font-weight: 600;
}

.sb-director-row.is-active i {
  border-color: var(--rk-emerald);
  box-shadow: 0 0 0 4px rgba(15, 164, 126, 0.16);
  animation: sb-director-breathe 1.6s ease-in-out infinite;
}

.sb-director-row.is-done {
  color: var(--rk-ink-soft);
}

.sb-director-row.is-done i {
  border-color: var(--rk-emerald);
  background: var(--rk-emerald);
}

@keyframes sb-director-breathe {
  0%, 100% { box-shadow: 0 0 0 3px rgba(15, 164, 126, 0.14); }
  50% { box-shadow: 0 0 0 6px rgba(15, 164, 126, 0.08); }
}

@media (prefers-reduced-motion: reduce) {
  .sb-director-row.is-active i { animation: none; }
}

.sb-director-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  width: 100%;
  margin-top: 6px;
}

.sb-director-actions .sb-continue-btn {
  min-width: 180px;
  padding-inline: 20px;
}

.sb-director-stop {
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  font-weight: 600;
  cursor: pointer;
}

.sb-director-stop:hover:not(:disabled) {
  border-color: var(--rk-card-hover-border, var(--rk-ink-muted));
  color: var(--rk-ink);
}

.sb-director-stop:disabled {
  opacity: 0.55;
  cursor: default;
}

/* The author's Stop only appears once the wait passes the configured bound; `hidden` must win over
   the flex display the actions row otherwise has. */
.sb-director-actions[hidden] {
  display: none;
}

/* Under 1020px the story page stops being a fixed-height scroller and the grid/panel keep
   `overflow: hidden` from the desktop rules — which turns them into the dock's scrolling box and
   silently kills `position: sticky` (the dock sat at the very end of the text on a phone). Let the
   reading page overflow so the dock pins to the viewport bottom while the author reads. */
@media (max-width: 1020px) {
  .sb-story-grid.is-centered,
  .sb-prose-panel.is-reading,
  .sb-prose-panel.is-reading .sb-prose-scroll {
    overflow: visible;
  }

  .sb-story-dock {
    border-block-start: 1px solid var(--rk-line);
    box-shadow: 0 -8px 20px rgba(43, 42, 38, 0.06);
  }
}

/* ── Early-learning lane (docs/prd-early-learning-lane.md): lane tabs under the composer,
   type chips, two-thumbnail style row. Chrome stays quiet; only the style thumbnails carry colour. */
.sb-lane-tabs {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  inline-size: min(830px, 100%);
  margin-block: 2px 4px;
}
.sb-lane-tabs[hidden] { display: none; }
.sb-lane-group {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-paper-2);
}
.sb-lane-tab {
  min-height: 34px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  padding-inline: 18px;
  font-family: var(--rk-font-body);
  font-size: 0.9rem;
  font-weight: 800;
  cursor: pointer;
  transition: background 180ms ease-out, color 180ms ease-out, box-shadow 180ms ease-out;
}
.sb-lane-tab:hover { color: var(--rk-ink); }
.sb-lane-tab.is-active {
  background: var(--rk-surface);
  color: var(--rk-emerald-hover);
  box-shadow: var(--rk-shadow-card);
}
.sb-lane-tab.has-info {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.sb-lane-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 16px;
  block-size: 16px;
  color: currentColor;
  opacity: 0.7;
}
.sb-lane-info svg { inline-size: 16px; block-size: 16px; stroke-width: 1.9; }
.sb-lane-tab.has-info:hover .sb-lane-info, .sb-lane-tab.is-active .sb-lane-info { opacity: 1; }
.sb-lane-tip {
  position: absolute;
  inset-block-start: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  inline-size: max-content;
  max-inline-size: min(360px, 80vw);
  padding: 10px 12px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-surface);
  color: var(--rk-ink);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.45;
  box-shadow: var(--rk-shadow-card);
  opacity: 0;
  visibility: hidden;
  transition: opacity 160ms ease-out, visibility 160ms ease-out;
  z-index: 20;
}
.sb-lane-tab.has-info:hover .sb-lane-tip, .sb-lane-tab.has-info:focus-visible .sb-lane-tip {
  opacity: 1;
  visibility: visible;
}
.sb-lane-tip { text-align: start; white-space: normal; font-weight: 600; }
.sb-style-picks {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
.sb-style-pick {
  display: grid;
  gap: 6px;
  inline-size: 148px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--rk-ink-soft);
  font-family: var(--rk-font-body);
  font-size: 0.82rem;
  font-weight: 800;
  text-align: center;
  cursor: pointer;
}
.sb-style-pick-thumb {
  position: relative;
  aspect-ratio: 3 / 2;
  border-radius: 12px;
  border: 2px solid var(--rk-line);
  overflow: hidden;
  background: var(--rk-paper-2);
  transition: border-color 180ms ease-out, box-shadow 180ms ease-out;
}
.sb-style-pick-thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
.sb-style-pick-check {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-start: 6px;
  display: none;
  inline-size: 22px;
  block-size: 22px;
  border-radius: 999px;
  background: var(--rk-emerald);
  color: #fff;
  align-items: center;
  justify-content: center;
}
.sb-style-pick-check svg { inline-size: 14px; block-size: 14px; stroke-width: 2.4; }
.sb-style-pick:hover .sb-style-pick-thumb { border-color: var(--rk-card-hover-border); }
.sb-style-pick.is-active { color: var(--rk-emerald-hover); }
.sb-style-pick.is-active .sb-style-pick-thumb { border-color: var(--rk-emerald); box-shadow: var(--rk-shadow-card); }
.sb-style-pick.is-active .sb-style-pick-check { display: inline-flex; }
@media (max-width: 680px) {
  .sb-style-picks { gap: 10px; }
  .sb-style-pick { inline-size: calc(50% - 5px); }
  .sb-lane-tab { padding-inline: 14px; }
}
/* `.sb-dim-row` sets display:flex, which beats the UA `[hidden]` rule — the lane's style row hides via
   the attribute when 涂色书 is picked, so the attribute must win. */
.sb-dim-row[hidden] { display: none; }

/* ── 连环画长文分章的确认卡 ────────────────────────────────────────────────────────────────────
   作者贴了一篇稿子，正要被告知它是三本书。所以这张卡的重点是让他**看见切在哪儿**：每一章
   给出自己的标题和开头几句，而不是只报一个数字。列表可滚动，但主按钮永远在卡内可见——
   「主操作不许移动或藏起来」。 */
.sb-chapter-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 560px;
}
.sb-chapter-card h2 {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
}
.sb-chapter-body {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--rk-ink-muted, #6e6a61);
}
.sb-chapter-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: min(46vh, 360px);
  overflow-y: auto;
}
.sb-chapter-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 10px;
  padding: 10px 12px;
  border: 1px solid var(--rk-line, #e7e1d6);
  border-radius: 10px;
  background: var(--rk-paper, #fdfaf3);
}
.sb-chapter-n {
  grid-row: 1;
  font-size: 12px;
  font-weight: 700;
  color: var(--rk-emerald, #0fa47e);
  white-space: nowrap;
}
.sb-chapter-title {
  grid-row: 1;
  font-size: 13px;
  font-weight: 600;
}
.sb-chapter-preview {
  grid-column: 2;
  font-size: 12px;
  line-height: 1.5;
  color: var(--rk-ink-muted, #6e6a61);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.sb-chapter-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* 近期卡片上的「做下一章」。卡片本身是个链接，所以这颗按钮要自己挡住冒泡（见 app.js 的
   data-next-chapter 分支）——视觉上也必须一眼看出它是独立动作，不是卡片的一部分文字。 */
.sb-next-chapter {
  margin-top: 8px;
  padding: 4px 10px;
  border: 1px solid var(--rk-emerald, #0fa47e);
  border-radius: 999px;
  background: transparent;
  color: var(--rk-emerald, #0fa47e);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.sb-next-chapter:hover {
  background: var(--rk-emerald, #0fa47e);
  color: #fff;
}

/* ── 动画专业版 (docs/prd-anim-relay-pro-integration.md §5.1): the 专业版 / 娱乐版 switch reuses the
   early-learning lane tabs. The "What's in Pro" dialog (docs/plan-anim-pro-intro-v2.md, 10-09) has no opener on the
   home page since 10-19; its styles stay with the dialog module: the Casual / Pro comparison and the trade-off line,
   five numbered points, one film's pictures. The pictures carry the only colour; numbers are ink circles (emerald
   stays reserved for the primary action and focus). */
.anim-lane-tabs { flex-wrap: wrap; }
/* 10-19 (Andy): the "What's in Pro" link is gone; the Pro ⓘ lists its points as 1–N instead. */
.sb-lane-tip.is-list {
  inline-size: min(480px, 90vw);
  max-inline-size: min(480px, 90vw);
  padding: 14px 16px;
  font-size: 0.86rem;
  line-height: 1.55;
}
.sb-lane-tip-lead { display: block; margin-block-end: 10px; color: var(--rk-ink); font-weight: 700; }
.sb-lane-tip-list { display: grid; gap: 6px; font-weight: 600; color: var(--rk-ink); }
.sb-lane-tip-item { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 6px; }
.sb-lane-tip-no { color: var(--rk-ink-soft); font-variant-numeric: tabular-nums; }
/* Phones: a tip centred on the first or last tab runs off the screen edge, so it centres on the whole switch instead. */
@media (max-width: 720px) {
  .anim-lane-tabs .sb-lane-group { position: relative; }
  .anim-lane-tabs .sb-lane-tab.has-info { position: static; }
}

.anim-pro-intro-layer {
  position: fixed;
  z-index: 1180; /* a modal: above the task float (780), below toasts */
  inset: 0;
  display: grid;
  place-items: center;
  padding: 24px;
}
.anim-pro-intro-layer[hidden] { display: none; }
.anim-pro-intro-backdrop {
  position: absolute;
  inset: 0;
  border: 0;
  background: color-mix(in srgb, var(--rk-ink) 42%, transparent);
}
.anim-pro-intro {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  inline-size: min(1080px, 100%);
  max-block-size: calc(100dvh - 48px);
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
}
.anim-pro-intro-close {
  position: absolute;
  z-index: 2;
  inset-block-start: 14px;
  inset-inline-end: 14px;
  display: inline-grid;
  place-items: center;
  inline-size: 40px;
  block-size: 40px;
  border: 0;
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink-soft);
  cursor: pointer;
}
.anim-pro-intro-close:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.anim-pro-intro-close:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-pro-intro-close svg { inline-size: 20px; block-size: 20px; }
.anim-pro-intro-scroll { min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; padding: 32px 40px 28px; }
.anim-pro-intro-head { padding-inline-end: 48px; }
.anim-pro-intro-head h2 {
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: clamp(1.5rem, 2.6vw, 1.9rem);
  line-height: 1.2;
  color: var(--rk-ink);
}
.anim-pro-intro-head p { max-inline-size: 86ch; margin: 10px 0 0; color: var(--rk-ink-soft); font-size: 1rem; line-height: 1.6; }

/* Casual / Pro comparison */
.anim-pro-intro-compare {
  inline-size: 100%;
  margin-block-start: 22px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
  table-layout: fixed; /* the first row sets the widths: label 18%, each lane 41% */
  font-size: 1rem;
  line-height: 1.45;
}
.anim-pro-intro-compare caption { padding-block-end: 10px; text-align: start; font-family: var(--rk-font-display); font-size: 1.15rem; color: var(--rk-ink); }
.anim-pro-intro-compare th,
.anim-pro-intro-compare td { padding: 9px 14px; text-align: start; vertical-align: top; border-block-start: 1px solid var(--rk-line); }
.anim-pro-intro-compare thead th,
.anim-pro-intro-compare thead td { border-block-start: 0; background: var(--rk-paper-2); color: var(--rk-ink); font-weight: 800; }
.anim-pro-intro-compare thead td { inline-size: 18%; }
.anim-pro-intro-compare thead th { inline-size: 41%; }
.anim-pro-intro-compare tbody th { color: var(--rk-ink); font-weight: 800; }
.anim-pro-intro-compare td { color: var(--rk-ink-soft); }
.anim-pro-intro-compare td.is-pro { color: var(--rk-ink); font-weight: 600; }

.anim-pro-intro-tradeoff {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 14px 0 0;
  padding: 12px 16px;
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
  color: var(--rk-ink);
  font-size: 1rem;
  line-height: 1.55;
}
.anim-pro-intro-tradeoff svg { flex: none; inline-size: 20px; block-size: 20px; margin-block-start: 2px; color: var(--rk-ink-soft); }

/* The five points: an ink circle per number (any script), each a link to its section */
.anim-pro-num {
  display: inline-grid;
  flex: none;
  place-items: center;
  inline-size: 28px;
  block-size: 28px;
  border: 1.5px solid var(--rk-ink);
  border-radius: 50%;
  color: var(--rk-ink);
  font-family: var(--rk-font-body);
  font-size: 0.95rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.anim-pro-intro-points { margin-block-start: 20px; }
.anim-pro-intro-points h3 { margin: 0 0 8px; font-family: var(--rk-font-display); font-size: 1.15rem; color: var(--rk-ink); }
.anim-pro-intro-points ol { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 16px; margin: 0; padding: 0; list-style: none; }
.anim-pro-intro-points a {
  display: flex;
  align-items: center;
  gap: 12px;
  min-block-size: 44px;
  padding: 6px 10px;
  border-radius: var(--rk-radius-sm);
  color: var(--rk-ink);
  font-size: 1rem;
  font-weight: 700;
  text-decoration: none;
}
.anim-pro-intro-points a:hover { background: var(--rk-paper-2); }
.anim-pro-intro-points a:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }

/* The case: one original film, with a muted excerpt */
.anim-pro-intro-case {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: center;
  gap: 22px;
  margin-block-start: 28px;
  padding: 18px;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-paper);
}
.anim-pro-intro-case h3 { margin: 0; font-family: var(--rk-font-display); font-size: 1.15rem; line-height: 1.35; color: var(--rk-ink); }
.anim-pro-intro-case p { margin: 8px 0 0; color: var(--rk-ink-soft); font-size: 1rem; line-height: 1.6; }
.anim-pro-intro-case .anim-pro-intro-meta { color: var(--rk-ink); font-weight: 700; }
.anim-pro-intro-clip { margin: 0; }
.anim-pro-intro-clip figcaption,
.anim-pro-intro-figure figcaption { margin-block-start: 10px; color: var(--rk-ink-soft); font-size: 1rem; line-height: 1.55; }

/* Pictures: every one is a button that opens the enlarged view */
.anim-pro-intro-media {
  position: relative;
  display: block;
  inline-size: 100%;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-sm);
  background: var(--rk-paper-2);
  cursor: zoom-in;
}
.anim-pro-intro-media img,
.anim-pro-intro-media video { display: block; inline-size: 100%; block-size: auto; }
.anim-pro-intro-media:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-pro-intro-zoom {
  position: absolute;
  inset-block-end: 8px;
  inset-inline-end: 8px;
  display: grid;
  place-items: center;
  inline-size: 32px;
  block-size: 32px;
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink);
  box-shadow: var(--rk-shadow-card);
  opacity: 0.88;
  transition: opacity 160ms ease;
}
.anim-pro-intro-zoom svg { inline-size: 16px; block-size: 16px; }
.anim-pro-intro-media:hover .anim-pro-intro-zoom,
.anim-pro-intro-media:focus-visible .anim-pro-intro-zoom { opacity: 1; }
.anim-pro-intro-media.is-video { cursor: pointer; }
.anim-pro-intro-play {
  position: absolute;
  inset-block-end: 8px;
  inset-inline-start: 8px;
  display: grid;
  place-items: center;
  inline-size: 36px;
  block-size: 36px;
  border-radius: 50%;
  background: var(--rk-surface);
  color: var(--rk-ink);
  box-shadow: var(--rk-shadow-card);
}
.anim-pro-intro-play svg { inline-size: 16px; block-size: 16px; margin-inline-start: 2px; }
.anim-pro-intro-clip.is-still .anim-pro-intro-play { inset: 0; margin: auto; inline-size: 56px; block-size: 56px; }
.anim-pro-intro-clip.is-still .anim-pro-intro-play svg { inline-size: 22px; block-size: 22px; }

/* The five sections */
.anim-pro-intro-feature { margin-block-start: 32px; padding-block-start: 26px; border-block-start: 1px solid var(--rk-line); scroll-margin-block-start: 12px; }
.anim-pro-intro-feature:focus { outline: none; }
.anim-pro-intro-feature h3 {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  font-family: var(--rk-font-display);
  font-size: 1.25rem;
  line-height: 1.3;
  color: var(--rk-ink);
}
.anim-pro-intro-bullets { display: grid; gap: 8px; margin: 12px 0 0; padding: 0; list-style: none; }
.anim-pro-intro-bullets li { position: relative; padding-inline-start: 22px; color: var(--rk-ink-soft); font-size: 1rem; line-height: 1.6; }
.anim-pro-intro-bullets li::before {
  content: "";
  position: absolute;
  inset-inline-start: 6px;
  inset-block-start: 0.7em;
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: var(--rk-ink-soft);
}
.anim-pro-intro-note { margin: 12px 0 0; padding: 10px 14px; border-radius: var(--rk-radius-sm); background: var(--rk-paper-2); color: var(--rk-ink-soft); font-size: 1rem; line-height: 1.55; }
.anim-pro-intro-figure { margin: 18px 0 0; }
.anim-pro-intro-row { display: flex; align-items: center; gap: 10px; }
.anim-pro-intro-row > .anim-pro-intro-tile { flex: 1 1 0; min-inline-size: 0; }
.anim-pro-intro-row.is-single { max-inline-size: 62%; margin-inline: auto; }
.anim-pro-intro-tile { display: grid; gap: 8px; }
.anim-pro-intro-tag {
  justify-self: start;
  padding: 2px 10px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  color: var(--rk-ink);
  font-size: 0.9rem;
  font-weight: 700;
}
.anim-pro-intro-arrow { display: grid; flex: none; place-items: center; color: var(--rk-ink-soft); }
.anim-pro-intro-arrow svg { inline-size: 24px; block-size: 24px; }
.anim-pro-intro-arrow.is-down { margin-block: 6px; }
.anim-pro-intro-arrow.is-down svg { transform: rotate(90deg); }
[dir="rtl"] .anim-pro-intro-row .anim-pro-intro-arrow svg { transform: scaleX(-1); }

.anim-pro-intro-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 40px 18px;
  border-block-start: 1px solid var(--rk-line);
  background: var(--rk-surface);
}
.anim-pro-intro-hint { margin: 0; color: var(--rk-ink-soft); font-size: 1rem; }
/* the enlarged view sits on the shared modal layer (z 100): keep the task float from covering its controls */
body.is-anim-pro-intro-previewing .rk-task-float { visibility: hidden; }

@media (max-width: 760px) {
  .anim-pro-intro-layer { padding: 12px; }
  .anim-pro-intro { max-block-size: calc(100dvh - 24px); }
  .anim-pro-intro-scroll { padding: 22px 18px 18px; }
  .anim-pro-intro-head { padding-inline-end: 44px; }
  /* the comparison becomes one card per row: label across, then each lane named above its text */
  .anim-pro-intro-compare thead { display: none; }
  .anim-pro-intro-compare tr { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .anim-pro-intro-compare { table-layout: auto; }
  .anim-pro-intro-compare tbody th { grid-column: 1 / -1; background: var(--rk-paper-2); }
  .anim-pro-intro-compare td { border-block-start: 0; padding-block-start: 8px; }
  .anim-pro-intro-compare td::before { content: attr(data-lane); display: block; margin-block-end: 2px; color: var(--rk-ink-muted); font-size: 0.875rem; font-weight: 700; }
  .anim-pro-intro-compare tbody tr:first-child th { border-block-start: 0; }
  .anim-pro-intro-case { grid-template-columns: minmax(0, 1fr); padding: 14px; }
  .anim-pro-intro-points ol { grid-template-columns: minmax(0, 1fr); }
  .anim-pro-intro-row { flex-direction: column; align-items: stretch; }
  .anim-pro-intro-row > .anim-pro-intro-tile { flex: none; }
  .anim-pro-intro-row.is-single { max-inline-size: none; }
  .anim-pro-intro-row .anim-pro-intro-arrow svg,
  [dir="rtl"] .anim-pro-intro-row .anim-pro-intro-arrow svg { transform: rotate(90deg); }
  .anim-pro-intro-actions { flex-direction: column; align-items: stretch; gap: 10px; padding: 12px 18px 16px; }
  .anim-pro-intro-actions .rk-btn-primary { inline-size: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .anim-pro-intro-zoom { transition: none; }
}

/* ═══ CTA bar start group (docs/prd-anim-editor-big-card.md D7, Andy 10-09) ═══
   The progress words (and the 专业版 notes entry) leave the flow and sit at the bar's start edge, so the main button is
   centred whatever they say — the caption used to sit beside it and push it off centre. New class: frozen production-V3
   pages keep their own bar untouched. Back in flow where the bar wraps. */
.anim-cta-start {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 34px;
  display: flex;
  align-items: center;
  gap: 12px;
  max-inline-size: calc(50% - 220px);
}
.anim-cta-start .anim-cta-caption {
  display: -webkit-box;
  max-inline-size: none;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  color: var(--rk-ink-soft);
  font-size: 0.95rem;
  font-weight: 700;
  line-height: 1.35;
  text-align: start;
}
@media (max-width: 900px) {
  .anim-cta-start { position: static; max-inline-size: none; }
}

/* ═══ 编辑大卡片 + 资产目录 (docs/prd-anim-editor-big-card.md, Andy 10-09) ═══
   The asset list column left of the canvas and the editor card that covers the canvas once a card on it is clicked.
   New class names only — frozen production-V3 pages load this same stylesheet and none of their markup carries these. */
.anim-ad-grid.has-asset-list {
  display: grid;
  /* §8.3 F12: the shot lists' width, so the column does not change size between the steps */
  grid-template-columns: clamp(248px, 16vw, 300px) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  gap: 16px;
}
.anim-ad-grid.has-asset-list.is-list-collapsed { grid-template-columns: 48px minmax(0, 1fr); }
/* the storyboard step: the shot list takes the place of the bottom filmstrip (S10) */
.anim-sh-workbench.has-shot-list {
  display: grid;
  grid-template-columns: clamp(248px, 16vw, 300px) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  gap: 16px;
  overflow: visible;
}
.anim-sh-workbench.has-shot-list.is-list-collapsed { grid-template-columns: 48px minmax(0, 1fr); }
.anim-sh-workbench.has-shot-list .anim-canvas-hint { inset-block-end: 10px; }
.anim-as-canvas-wrap { position: relative; min-inline-size: 0; min-block-size: 0; }
.anim-as-canvas-wrap > .anim-as-canvas { inline-size: 100%; block-size: 100%; }
/* clip, not hidden: a hidden box is still scrollable by the browser, which left an invisible offset under the zoom */
.has-asset-list .anim-as-canvas, .has-shot-list .anim-as-canvas { overflow: clip; }
.anim-as-stage.is-gliding { transition: transform 0.36s cubic-bezier(0.2, 0.7, 0.2, 1); }

/* ── asset list ── */
.anim-al { position: relative; display: flex; flex-direction: column; min-block-size: 0; border: 1px solid var(--rk-line); border-radius: var(--rk-radius); background: var(--rk-surface); overflow: hidden; }
.anim-al-rail { display: none; }
.anim-al.is-collapsed .anim-al-panel { display: none; }
.anim-al.is-collapsed .anim-al-rail { display: flex; flex-direction: column; align-items: center; gap: 12px; padding-block: 8px; }
.anim-al-rail-label { writing-mode: vertical-rl; color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 800; letter-spacing: 0.2em; }
.anim-al-panel { flex: 1; display: flex; flex-direction: column; min-block-size: 0; }
.anim-al-head { display: flex; align-items: center; gap: 8px; padding-block: 10px 6px; padding-inline: 16px 6px; }
.anim-al-head h2 { margin: 0; font-family: var(--rk-font-display); font-size: 1.05rem; }
.anim-al-count { color: var(--rk-ink-soft); font-weight: 700; }
.anim-al-fold { display: inline-grid; place-items: center; inline-size: 40px; block-size: 40px; margin-inline-start: auto; border: 0; border-radius: 50%; background: transparent; color: var(--rk-ink-soft); cursor: pointer; }
.anim-al-rail .anim-al-fold { margin: 0; }
.anim-al-fold:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.anim-al-fold svg { inline-size: 20px; block-size: 20px; stroke-width: 1.8; }
[dir="rtl"] .anim-al-fold svg { transform: scaleX(-1); }
.anim-al-filter { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 12px 10px; }
.anim-al-filter button { min-block-size: 32px; padding: 0 12px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-surface); color: var(--rk-ink-soft); font: inherit; font-size: 0.875rem; font-weight: 700; cursor: pointer; }
.anim-al-filter button.is-on { border-color: var(--rk-ink); background: var(--rk-paper-2); color: var(--rk-ink); }
.anim-al-body { flex: 1; min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; padding: 0 8px 12px; }
.anim-al-group { display: flex; align-items: baseline; gap: 6px; margin: 10px 8px 6px; color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 800; letter-spacing: 0.06em; }
.anim-al-group span { color: var(--rk-ink-muted); }
.anim-al-item { position: relative; display: grid; grid-template-columns: 96px minmax(0, 1fr); align-items: center; gap: 10px; inline-size: 100%; min-block-size: 64px; padding: 8px; border: 1px solid transparent; border-radius: 14px; background: transparent; color: inherit; font: inherit; text-align: start; cursor: pointer; }
.anim-al-item:hover { background: var(--rk-paper); }
/* selected: emerald ring + soft fill + a start-edge bar, so the state does not rest on colour alone */
.anim-al-item.is-selected { border-color: var(--rk-emerald); background: var(--rk-emerald-soft); box-shadow: inset 4px 0 0 var(--rk-emerald); }
[dir="rtl"] .anim-al-item.is-selected { box-shadow: inset -4px 0 0 var(--rk-emerald); }
.anim-al-item.is-sub { padding-inline-start: 26px; }
.anim-al-item.is-sub::before { content: ""; position: absolute; inset-inline-start: 14px; inset-block: 0 50%; inline-size: 8px; border-inline-start: 1.5px solid var(--rk-line); border-block-end: 1.5px solid var(--rk-line); border-end-start-radius: 6px; }
.anim-al-thumb { display: grid; place-items: center; block-size: 72px; border-radius: 10px; background: var(--rk-paper-2); overflow: hidden; }
.anim-al-item.is-sub .anim-al-thumb { min-block-size: 56px; }
/* real proportions: the picture keeps its own shape inside a fixed-height slot — never cropped, never stretched */
.anim-al-thumb img { display: block; max-inline-size: 100%; max-block-size: 72px; inline-size: auto; block-size: auto; }
.anim-al-item.is-sub .anim-al-thumb img { max-block-size: 56px; }
.anim-al-thumb.is-pair { grid-template-columns: 1fr 1fr; gap: 3px; padding-inline: 3px; }
.anim-al-ph { display: grid; place-items: center; block-size: 100%; max-inline-size: 100%; border: 1.5px dashed var(--rk-line); border-radius: 8px; background: var(--rk-paper); color: var(--rk-ink-muted); }
.anim-al-ph svg { inline-size: 22px; block-size: 22px; stroke-width: 1.6; }
.anim-al-text { display: grid; gap: 3px; min-inline-size: 0; }
.anim-al-name { overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: 0.95rem; font-weight: 800; line-height: 1.3; overflow-wrap: anywhere; }
.anim-al-role { justify-self: start; padding: 1px 8px; border-radius: 999px; background: var(--rk-paper-2); color: var(--rk-ink-soft); font-size: 0.75rem; font-weight: 800; }
.anim-al-state { display: inline-flex; align-items: center; gap: 5px; color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; }
.anim-al-dot { flex: none; inline-size: 7px; block-size: 7px; border-radius: 50%; background: var(--rk-ink-muted); }
.is-ready > .anim-al-dot { background: var(--rk-emerald); }
.is-todo > .anim-al-dot { border: 1.5px solid var(--rk-ink-muted); background: transparent; }
.is-failed > .anim-al-dot, .is-partial > .anim-al-dot { background: var(--rk-danger); }
.anim-al-state.is-failed { color: var(--rk-danger); }
.anim-al-spin { flex: none; inline-size: 12px; block-size: 12px; border: 2px solid var(--rk-line); border-block-start-color: var(--rk-emerald); border-radius: 50%; animation: anim-al-spin 0.9s linear infinite; }
@keyframes anim-al-spin { to { transform: rotate(360deg); } }
.anim-al-none { margin: 16px; color: var(--rk-ink-soft); }
/* §6.5 A1: the asset canvas card's pencil (opens the editor card) and magnifier, the storyboard canvas's size (S15):
   32px white circles with a hairline and a shadow, bolder icons; still shown on hover / selection, above the card */
.anim-as-acts.anim-as-acts-big { gap: 6px; padding-block-end: 6px; }
.anim-as-acts.anim-as-acts-big .anim-as-edit, .anim-as-acts.anim-as-acts-big .anim-as-zoom { display: grid; place-items: center; inline-size: 32px; block-size: 32px; padding: 0; border: 1px solid var(--rk-line); border-radius: 50%; background: var(--rk-surface); color: var(--rk-ink); box-shadow: 0 2px 10px -4px rgb(0 0 0 / 40%); font-size: 0; line-height: 0; }
.anim-as-acts.anim-as-acts-big svg { inline-size: 17px; block-size: 17px; stroke-width: 1.9; }
.anim-as-acts.anim-as-acts-big .anim-as-edit:hover, .anim-as-acts.anim-as-acts-big .anim-as-zoom:hover { background: var(--rk-paper-2); color: var(--rk-emerald); }
.anim-as-acts.anim-as-acts-big > button:focus-visible { opacity: 1; outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
/* §8.3 F10: a selected card shows both tools, as on the storyboard canvas (the old rule lit only the pencil) */
.anim-as-node.is-selected .anim-as-acts.anim-as-acts-big > button { opacity: 1; }
/* §8.3 F10: the pencil on the video player belongs to the shot on screen — always shown (the storyboard canvas's
   hidden-until-hover rule used to win over it) */
.anim-sh-tools.anim-vdc-tools > button { opacity: 1; }
/* shot rows: a storyboard is a wide picture of 4–9 panels — the picture takes the full row width so the panels can still
   be told apart, the title and state sit under it */
.anim-al-item.is-shot { grid-template-columns: minmax(0, 1fr); gap: 6px; margin-block-end: 4px; }
.anim-al-thumb.is-board { block-size: auto; min-block-size: 60px; max-block-size: 170px; }
.anim-al-thumb.is-board img { inline-size: 100%; block-size: auto; max-block-size: 170px; object-fit: contain; }
.anim-al-thumb.is-board .anim-al-ph { inline-size: 100%; block-size: auto; }
.anim-al-item.is-shot .anim-al-text { grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 8px; }
.anim-al-item.is-shot .anim-al-name { grid-column: 1 / -1; -webkit-line-clamp: 1; display: block; white-space: nowrap; text-overflow: ellipsis; }
.anim-al-sub { color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; }
.anim-al-item.is-excluded .anim-al-thumb { opacity: 0.5; }
/* one panel of a card storyboard (lib/animation-panel-cut.js): the whole board moved and scaled inside a 16:9 frame */
.anim-panel-cut { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; border-radius: 7px; background: var(--rk-paper-2); }
.anim-panel-cut > img { position: absolute; display: block; max-inline-size: none; max-block-size: none; }
/* the list's panel tree (docs/plan-storyboard-cut-panels-20261019.md 第 4 步, design ①): one card per shot — the fold and the
   shot side by side, its panels one row each when open (indented under a green rail), a strip of small panels when closed,
   dashed while the storyboard is not drawn */
.anim-sl-node { margin-block-end: 8px; padding: 8px; border: 1px solid var(--rk-line); border-radius: 14px; background: var(--rk-surface, #fff); }
.anim-sl-node.is-selected { border-color: var(--rk-emerald); background: var(--rk-emerald-soft); }
.anim-sl-node.is-excluded { opacity: 0.6; }
.anim-sl-head { display: flex; align-items: flex-start; gap: 4px; }
.anim-sl-fold { flex: none; display: grid; place-items: center; inline-size: 28px; block-size: 28px; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--rk-ink-muted); cursor: pointer; }
.anim-sl-fold:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.anim-sl-fold svg { inline-size: 16px; block-size: 16px; stroke-width: 2.2; }
.anim-sl-shot { flex: 1; min-inline-size: 0; display: grid; gap: 8px; padding: 4px 6px; border: 0; border-radius: 10px; background: transparent; color: inherit; font: inherit; text-align: start; cursor: pointer; }
.anim-sl-shot:hover { background: color-mix(in srgb, var(--rk-paper-2) 70%, transparent); }
.anim-sl-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; min-inline-size: 0; }
.anim-sl-tag { font-size: 0.95rem; font-weight: 800; }
.anim-sl-meta { color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; white-space: nowrap; }
.anim-sl-row .anim-al-state { margin-inline-start: auto; flex: none; }
/* three small panels a row (a 3×3 board reads as its grid), each shrinking a little in a narrow column */
.anim-sl-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 56px)); gap: 4px; }
.anim-sl-mini { inline-size: 100%; border-radius: 5px; }
.anim-sl-mini.is-todo { display: grid; place-items: center; aspect-ratio: 16 / 9; border: 1.5px dashed var(--rk-line); background: var(--rk-paper); color: var(--rk-ink-muted); box-sizing: border-box; }
.anim-sl-ph { display: grid; place-items: center; }
.anim-sl-ph svg { inline-size: 16px; block-size: 16px; stroke-width: 1.6; }
.anim-sl-panels { display: grid; gap: 6px; margin: 8px 0 2px 14px; padding-inline-start: 12px; border-inline-start: 2px solid color-mix(in srgb, var(--rk-emerald) 30%, transparent); }
.anim-sl-panel { display: grid; grid-template-columns: 72px minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 4px; border: 1px solid transparent; border-radius: 8px; background: transparent; color: inherit; font: inherit; text-align: start; cursor: pointer; }
.anim-sl-panel:hover { background: var(--rk-paper); }
.anim-sl-panel.is-selected { border-color: var(--rk-emerald); background: color-mix(in srgb, var(--rk-emerald-soft) 80%, #fff); }
.anim-sl-panel .anim-sl-mini { inline-size: 72px; border-radius: 6px; }
.anim-sl-panel-text { display: grid; gap: 1px; min-inline-size: 0; }
.anim-sl-panel-text b { font-size: 0.85rem; font-weight: 800; }
.anim-sl-panel-text span { color: var(--rk-ink-soft); font-size: 0.75rem; overflow-wrap: anywhere; }
.anim-sl-panel.is-failed .anim-al-dot { background: var(--rk-danger); }
.anim-sl-fold:focus-visible, .anim-sl-shot:focus-visible, .anim-sl-panel:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-al-fold:focus-visible, .anim-al-filter button:focus-visible, .anim-al-item:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
/* §6.5 A2: asset rows stacked like the shot rows — the picture on top (true ratio, height-capped, centred), the text
   below across the whole row: the name on up to two lines, then the role tag on the left and the state on the right */
.anim-al-item:not(.is-shot) { grid-template-columns: minmax(0, 1fr); align-items: stretch; gap: 6px; margin-block-end: 4px; }
.anim-al-item:not(.is-shot) .anim-al-thumb { block-size: auto; min-block-size: 64px; max-block-size: 132px; padding: 4px; }
.anim-al-item:not(.is-shot) .anim-al-thumb img { max-inline-size: 100%; max-block-size: 124px; object-fit: contain; }
.anim-al-item.is-sub:not(.is-shot) .anim-al-thumb { min-block-size: 56px; max-block-size: 108px; }
.anim-al-item.is-sub:not(.is-shot) .anim-al-thumb img { max-block-size: 100px; }
.anim-al-item:not(.is-shot) .anim-al-ph { inline-size: auto; block-size: 84px; }
.anim-al-item:not(.is-shot) .anim-al-text { grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 8px; }
.anim-al-item:not(.is-shot) .anim-al-name { grid-column: 1 / -1; }
.anim-al-item:not(.is-shot) .anim-al-state { grid-column: 2; }

/* ── editor card ── */
.anim-ec-layer { position: absolute; inset: 0; z-index: 20; display: flex; padding: 14px; background: rgb(250 248 244 / 72%); cursor: default; touch-action: auto; }
/* Jeff 2026-10-13: on a cream wash the card read as part of the page, not a dialog — dim what is behind it with the
   shared modal scrim (.rk-modal-backdrop). The editor card itself keeps its paper surface. */
.anim-ec-layer:not(.is-pro) { background: rgba(43, 42, 38, 0.42); }
/* A viewport-level editor dims navigation, the asset list and the action bar together.
   Keep it below the shared payment/modal layer (100). */
.anim-ec-layer:is(.is-pro, .is-assets, .is-video) { --anim-editor-list-width: clamp(248px, 16vw, 300px); position: fixed; inset: 0; z-index: 80; align-items: center; justify-content: flex-end; padding: 24px 48px; background: rgb(43 42 38 / 42%); }
/* Keep the desktop card beside the asset list while the scrim spans the viewport. */
.anim-ec-layer:is(.is-pro, .is-assets, .is-video) > .anim-ec { z-index: 1; flex: 0 1 1440px; block-size: min(900px, calc(100dvh - 160px)); max-inline-size: calc(100% - var(--anim-editor-list-width) - 16px); max-block-size: 100%; }
:is(.anim-ad-grid, .anim-sh-workbench).is-list-collapsed .anim-ec-layer:is(.is-pro, .is-assets, .is-video) { --anim-editor-list-width: 48px; }
/* Andy 10-19: the 专业版 storyboard card may cover the shot list (「盖住左侧的列表没问题的。反正是弹窗」) — wider and centred,
   the extra width going mostly to the picture column, so the shot cards under the storyboard show more */
.anim-ec-layer.is-shots.is-pro { justify-content: center; }
.anim-ec-layer.is-shots.is-pro > .anim-ec { flex-basis: 1760px; max-inline-size: 100%; }
@container (min-width: 560px) {
  .anim-pro-inspector .anim-ec-main.has-side { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
}
@media (max-width: 1100px) {
  .anim-ec-layer:is(.is-pro, .is-assets, .is-video) { padding: 10px; }
  .anim-ec-layer:is(.is-pro, .is-assets, .is-video) > .anim-ec { block-size: calc(100dvh - 20px); max-inline-size: 100%; }
}
.anim-ec { --anim-ec-float-clear: 0px; position: relative; flex: 1; display: flex; flex-direction: column; min-inline-size: 0; border: 1px solid var(--rk-line); border-radius: var(--rk-radius-lg); background: var(--rk-surface); box-shadow: var(--rk-shadow-panel); overflow: hidden; }
.anim-ec-head { display: flex; align-items: center; gap: 12px; min-block-size: 60px; padding-block: 8px; padding-inline: 22px 12px; border-block-end: 1px solid var(--rk-line); }
.anim-ec-kind { flex: none; padding: 4px 12px; border-radius: 999px; background: var(--rk-paper-2); color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 800; }
.anim-ec-head h2 { min-inline-size: 0; margin: 0; overflow: hidden; font-family: var(--rk-font-display); font-size: 1.25rem; white-space: nowrap; text-overflow: ellipsis; }
.anim-ec-state { flex: none; display: inline-flex; align-items: center; gap: 6px; color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 800; }
.anim-ec-panes { display: none; }
.anim-ec-x { flex: none; display: inline-grid; place-items: center; inline-size: 44px; block-size: 44px; margin-inline-start: auto; border: 0; border-radius: 50%; background: transparent; color: var(--rk-ink-soft); cursor: pointer; }
.anim-ec-x:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.anim-ec-x svg { inline-size: 22px; block-size: 22px; stroke-width: 1.8; }
.anim-ec-body { flex: 1; display: grid; grid-template-columns: minmax(0, 65fr) minmax(300px, 32fr); min-block-size: 0; }
.anim-ec-left { display: flex; flex-direction: column; min-inline-size: 0; min-block-size: 0; border-inline-end: 1px solid var(--rk-line); container-type: inline-size; }
.anim-ec-tabs { display: flex; gap: 4px; padding: 10px 20px 0; overflow-x: auto; border-block-end: 1px solid var(--rk-line); }
.anim-ec-tab { position: relative; display: inline-flex; align-items: center; gap: 8px; min-block-size: 44px; padding: 0 14px; border: 0; background: none; color: var(--rk-ink-soft); font: inherit; font-size: 1rem; font-weight: 800; white-space: nowrap; cursor: pointer; }
.anim-ec-tab img { inline-size: 28px; block-size: 28px; border-radius: 6px; background: var(--rk-paper-2); object-fit: cover; }
.anim-ec-tab.is-on { color: var(--rk-ink); }
.anim-ec-tab.is-on::after { content: ""; position: absolute; inset-inline: 10px; inset-block-end: -1px; block-size: 3px; border-radius: 3px; background: var(--rk-ink); }
.anim-ec-main { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; gap: 18px; min-block-size: 0; padding: 16px 20px; overflow-y: auto; overscroll-behavior: contain; }
.anim-ec-main:not(.has-side) { align-content: stretch; }
.anim-ec-media { display: flex; flex-direction: column; gap: 12px; min-block-size: 0; }
/* the picture's box never changes height when the image arrives (Rule #411); the image sits inside at its own shape */
.anim-ec-stagebox { position: relative; flex: none; block-size: 340px; border-radius: var(--rk-radius); background: var(--rk-paper-2); overflow: hidden; }
.anim-ec-main:not(.has-side) .anim-ec-stagebox { flex: 1; block-size: auto; min-block-size: 300px; }
.anim-ec-main.has-side { grid-auto-rows: max-content; }
@container (min-width: 560px) {
  .anim-ec-main.has-side { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); grid-auto-rows: minmax(0, 1fr); align-content: stretch; overflow: hidden; }
  .anim-ec-main.has-side .anim-ec-media { overflow-y: auto; overscroll-behavior: contain; }
  .anim-ec-main.has-side .anim-ec-stagebox { flex: 1; block-size: auto; min-block-size: 240px; }
}
.anim-ec-stagebox > img { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: contain; }
.anim-ec-zoom { position: absolute; inset-block-start: 10px; inset-inline-end: 10px; display: grid; place-items: center; inline-size: 40px; block-size: 40px; border: 1px solid var(--rk-line); border-radius: 50%; background: rgb(255 255 255 / 92%); color: var(--rk-ink); cursor: zoom-in; }
.anim-ec-zoom svg { inline-size: 18px; block-size: 18px; stroke-width: 1.8; }
.anim-ec-corner { position: absolute; inset-block-end: 10px; inset-inline-start: 10px; padding: 3px 10px; border-radius: 999px; background: rgb(255 255 255 / 92%); color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; }
.anim-ec-busy { position: absolute; inset-block-start: 10px; inset-inline-start: 10px; display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; background: rgb(255 255 255 / 94%); font-size: 0.9rem; font-weight: 800; }
.anim-ec-empty { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 8px; padding: 16px; color: var(--rk-ink-soft); text-align: center; }
.anim-ec-empty b { font-size: 1rem; }
.anim-ec-empty em { font-size: 0.875rem; font-style: normal; }
.anim-ec-generating { width: auto; }
.anim-ec-generating strong { margin-top: 16px; font-size: 1.1rem; }
/* a redraw veils the old picture so it does not read as the result (Jeff 2026-10-13) */
.anim-ec-redraw-veil { position: absolute; inset: 0; z-index: 2; display: grid; place-content: center; justify-items: center; padding: 16px; background: rgb(250 248 244 / 78%); backdrop-filter: blur(2px); color: var(--rk-ink); text-align: center; }
/* the prompt box says when it is being saved or rewritten (Jeff 2026-10-13) */
.anim-ec-textwrap { position: relative; flex: 1; display: flex; flex-direction: column; min-block-size: 0; }
.anim-ec-textwrap > .anim-ec-textarea { flex: 1; }
.anim-ec-text-veil { position: absolute; inset: 0; z-index: 2; display: grid; place-content: center; justify-items: center; padding: 16px; border-radius: 14px; background: rgb(250 248 244 / 84%); color: var(--rk-ink); text-align: center; }
.anim-ec-redraw-veil .anim-ec-generating { padding: 22px 30px 18px; border-radius: var(--rk-radius-lg); background: rgb(255 255 255 / 90%); box-shadow: var(--rk-shadow-panel); }
.anim-ec-versions { display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; min-width: 0; }
/* Jeff 2026-10-13: many versions stay on one row and slide sideways — the big picture keeps its size */
.anim-ec-versions > .anim-ec-label { flex: none; }
.anim-ec-ver-track { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; padding-block: 2px 6px; }
.anim-ec-ver-track > .anim-ec-ver { flex: none; }
/* Andy 10-19: in the asset editor the version strip and a derived prop's references read top to bottom — the heading on
   its own line at the left, the pictures on the next line; what a reference is sits in the heading's ⓘ card */
.anim-ec-media.is-asset .anim-ec-versions { flex-direction: column; align-items: stretch; gap: 6px; }
.anim-ec-media.is-asset .anim-ec-versions > .anim-ec-label { align-self: flex-start; }
.anim-ec-baseref { display: flex; flex-direction: column; align-items: stretch; gap: 6px; min-width: 0; }
.anim-ec-baseref-head { display: flex; align-items: center; gap: 6px; }
.anim-ec-baseref-track { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; }
.anim-ec-baseref-track > .anim-ec-ver { flex: none; }
.anim-ec-baseref-chip span { max-inline-size: 96px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.anim-ec-baseref-empty { color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; }
.anim-ec-label { color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 800; }
.anim-ec-ver { display: grid; justify-items: center; gap: 3px; padding: 4px; border: 1.5px solid var(--rk-line); border-radius: 12px; background: var(--rk-surface); color: var(--rk-ink-soft); font: inherit; font-size: 0.75rem; font-weight: 800; cursor: pointer; }
.anim-ec-ver img { inline-size: 56px; block-size: 56px; border-radius: 8px; background: var(--rk-paper-2); object-fit: contain; }
.anim-ec-ver.is-current { border-color: var(--rk-ink); color: var(--rk-ink); cursor: default; }
.anim-ec-ver:disabled:not(.is-current) { opacity: 0.55; cursor: not-allowed; }
.anim-ec-prompt { display: flex; flex-direction: column; gap: 8px; min-block-size: 0; }
.anim-ec-prompt-head { display: flex; align-items: baseline; gap: 10px; font-size: 0.95rem; font-weight: 800; }
.anim-ec-prompt-head small { color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 700; }
.anim-ec-textarea { flex: 1; min-block-size: 220px; padding: 12px 14px; border: 1px solid var(--rk-line); border-radius: 14px; background: var(--rk-paper); color: var(--rk-ink); font: inherit; font-size: 1rem; line-height: 1.6; resize: none; }
.anim-ec-textarea:disabled { color: var(--rk-ink-soft); }
/* the description's length against its limit, sitting inside the box's bottom-right corner (Jeff 2026-10-12) */
.anim-ec-textarea.has-count { padding-bottom: 34px; }
.anim-ec-count { position: relative; align-self: flex-end; margin: -38px 14px 0 0; padding: 2px 6px; border-radius: 8px; background: var(--rk-paper); color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; font-variant-numeric: tabular-nums; pointer-events: none; }
.anim-ec-count.is-near { color: var(--rk-warning, #b7791f); }
.anim-ec-count.is-over { color: var(--rk-danger); }
.anim-ec-hint, .anim-ec-wait { margin: 0; color: var(--rk-ink-soft); font-size: 0.875rem; line-height: 1.5; }
.anim-ec-err { margin: 0; color: var(--rk-danger); font-size: 0.9rem; font-weight: 700; }
/* Jeff 2026-10-13: the card's failures sit top right, beside the close button */
.anim-ec-head-err { display: inline-flex; align-items: center; gap: 6px; min-inline-size: 0; max-inline-size: min(46%, 520px); margin: 0; margin-inline-start: auto; padding: 5px 12px 5px 6px; border-radius: 999px; background: color-mix(in srgb, var(--rk-danger) 10%, transparent); color: var(--rk-danger); font-size: 0.85rem; font-weight: 700; }
.anim-ec-head-err b { flex: none; display: inline-grid; place-items: center; inline-size: 18px; block-size: 18px; border-radius: 50%; background: var(--rk-danger); color: #fff; font-size: 0.75rem; line-height: 1; }
.anim-ec-head-err span { min-inline-size: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.anim-ec-head-err + .anim-ec-x { margin-inline-start: 0; }
.anim-ec-derived { display: grid; align-content: start; gap: 14px; padding: 16px; border: 1px dashed var(--rk-line); border-radius: 14px; background: var(--rk-paper); }
.anim-ec-derived p { margin: 0; font-size: 1rem; line-height: 1.6; }
.anim-ec-derived .anim-ec-ghost { justify-self: start; }
.anim-ec-notes { display: grid; gap: 6px; padding: 10px 20px; border-block-start: 1px solid var(--rk-line); background: var(--rk-paper); }
.anim-ec-notes p { margin: 0; color: var(--rk-ink-soft); font-size: 0.9rem; line-height: 1.5; }
.anim-ec-notes .anim-ec-ghost { justify-self: start; }
.anim-ec .anim-as-insp-library { display: grid; gap: 8px; }
/* the fixed action row: secondary on the start side, the single primary on the end side — it never moves */
.anim-ec-actions { display: flex; align-items: center; gap: 10px; min-block-size: 70px; padding: 12px 20px; border-block-start: 1px solid var(--rk-line); background: var(--rk-surface); }
.anim-ec-why { flex: 1; min-inline-size: 0; color: var(--rk-ink-soft); font-size: 0.875rem; line-height: 1.4; }
.anim-ec-ghost { min-block-size: 40px; padding: 0 16px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-surface); color: var(--rk-ink); font: inherit; font-size: 0.95rem; font-weight: 800; white-space: nowrap; cursor: pointer; }
.anim-ec-ghost:hover:not(:disabled) { background: var(--rk-paper-2); }
.anim-ec-ghost:disabled { opacity: 0.5; cursor: not-allowed; }
.anim-ec-primary { flex: none; display: inline-flex; align-items: center; gap: 8px; min-block-size: 46px; padding: 0 24px; border: 0; border-radius: 999px; background: var(--rk-emerald); color: #fff; font: inherit; font-size: 1rem; font-weight: 800; white-space: nowrap; cursor: pointer; }
.anim-ec-primary:hover:not(:disabled) { background: var(--rk-emerald-hover); }
.anim-ec-primary svg { inline-size: 18px; block-size: 18px; }
.anim-ec-primary:disabled { background: var(--rk-line); color: var(--rk-ink-muted); cursor: not-allowed; }
/* chat column */
.anim-ec-chat { display: flex; flex-direction: column; min-inline-size: 0; min-block-size: 0; padding-block-end: var(--anim-ec-float-clear, 0px); background: var(--rk-paper); }
.anim-ec-chat-head { display: flex; align-items: center; gap: 10px; padding: 12px 16px 8px; }
/* §6.5 A4: the whole transparent cat head, uncropped — the round frame cut Pudding's ears off */
.anim-ec-avatar { flex: none; inline-size: 40px; block-size: 40px; object-fit: contain; border: 0; border-radius: 0; background: transparent; }
.anim-ec-chat-head b { font-family: var(--rk-font-display); font-size: 1rem; }
.anim-ec-ctx { display: flex; align-items: center; gap: 10px; margin: 0 16px 8px; padding: 8px 10px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-surface); font-size: 0.9rem; font-weight: 700; }
.anim-ec-ctx img { inline-size: 34px; block-size: 34px; border-radius: 8px; background: var(--rk-paper-2); object-fit: contain; }
.anim-ec-log { flex: 1; display: flex; flex-direction: column; gap: 10px; min-block-size: 0; padding: 4px 16px 12px; overflow-y: auto; overscroll-behavior: contain; }
.anim-ec-ai, .anim-ec-intro { align-self: flex-start; max-inline-size: 94%; margin: 0; padding: 10px 14px; border: 1px solid var(--rk-line); border-radius: 14px; border-start-start-radius: 4px; background: var(--rk-surface); font-size: 1rem; line-height: 1.55; overflow-wrap: anywhere; }
.anim-ec-intro, .anim-ec-ai.is-pending { color: var(--rk-ink-soft); }
/* the desks' thinking turn, copied from the H5 story writer (Jeff 2026-10-13): a bare line — a ring of dots stepping
   round, a light sweeping the words, the time waited; the reply then takes a bubble and types itself in */
.anim-ec-thinking { align-self: flex-start; display: inline-flex; align-items: center; gap: 9px; max-inline-size: 94%; padding: 6px 2px; color: var(--rk-ink-soft); font-size: 0.95rem; line-height: 1.5; }
.anim-think-ring { position: relative; flex: none; inline-size: 14px; block-size: 14px; }
.anim-think-ring i { position: absolute; inset-block-start: 50%; inset-inline-start: 50%; inline-size: 3px; block-size: 3px; margin: -1.5px 0 0 -1.5px; border-radius: 50%; background: var(--rk-emerald); opacity: 0.18; animation: anim-think-dot 0.72s steps(6, end) infinite; }
.anim-think-ring i:nth-child(1) { transform: rotate(0deg) translateY(-5.5px); animation-delay: -0.72s; }
.anim-think-ring i:nth-child(2) { transform: rotate(60deg) translateY(-5.5px); animation-delay: -0.6s; }
.anim-think-ring i:nth-child(3) { transform: rotate(120deg) translateY(-5.5px); animation-delay: -0.48s; }
.anim-think-ring i:nth-child(4) { transform: rotate(180deg) translateY(-5.5px); animation-delay: -0.36s; }
.anim-think-ring i:nth-child(5) { transform: rotate(240deg) translateY(-5.5px); animation-delay: -0.24s; }
.anim-think-ring i:nth-child(6) { transform: rotate(300deg) translateY(-5.5px); animation-delay: -0.12s; }
@keyframes anim-think-dot { 0% { opacity: 1; } 100% { opacity: 0.18; } }
.anim-think-text { position: relative; overflow: hidden; min-inline-size: 0; white-space: nowrap; text-overflow: ellipsis; }
.anim-think-text::after { content: ''; position: absolute; inset-block: 0; left: -40%; inline-size: max(56px, 40%); background: linear-gradient(90deg, rgb(255 255 255 / 0%), rgb(255 255 255 / 85%), rgb(255 255 255 / 0%)); animation: anim-think-sweep 2s ease-in-out infinite; pointer-events: none; }
@keyframes anim-think-sweep { 0% { left: -40%; } 75%, 100% { left: 100%; } }
.anim-think-clock { flex: none; color: var(--rk-ink-muted); font-size: 0.875rem; font-style: normal; font-variant-numeric: tabular-nums; }
@media (prefers-reduced-motion: reduce) { .anim-think-ring i, .anim-think-text::after { animation: none; } .anim-think-ring i:nth-child(1) { opacity: 1; } }
.anim-ec-you { align-self: flex-end; max-inline-size: 88%; margin: 0; padding: 10px 14px; border-radius: 14px; border-start-end-radius: 4px; background: var(--rk-bubble-user); color: var(--rk-ink); font-size: 1rem; line-height: 1.55; overflow-wrap: anywhere; }
.anim-ec-log .anim-dd-proposal { align-self: stretch; margin: 0; }
/* §6.5 A5: the one-line composer (58px) sits centred on the left column's 71px action row: (71 − 58) / 2 ≈ 6px below.
   The example placeholder stays on one line (ellipsis): a wrapped placeholder made the empty box two lines tall. */
.anim-ec-composer textarea::placeholder { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.anim-ec-composer { display: flex; align-items: flex-end; gap: 8px; margin: 0 12px 6px; padding-block: 6px; padding-inline: 14px 6px; border: 1px solid var(--rk-composer-border); border-radius: var(--rk-radius-lg); background: var(--rk-surface); }
.anim-ec-composer:focus-within { border-color: var(--rk-ink-muted); }
.anim-ec-composer.is-off { background: var(--rk-paper-2); }
.anim-ec-composer textarea { flex: 1; min-inline-size: 0; min-block-size: 44px; max-block-size: 140px; padding-block: 10px; padding-inline: 0; border: 0; background: transparent; color: var(--rk-ink); font: inherit; font-size: 1rem; line-height: 1.5; resize: none; outline: none; }
.anim-ec-send { flex: none; display: grid; place-items: center; inline-size: 44px; block-size: 44px; border: 0; border-radius: 50%; background: var(--rk-emerald); color: #fff; cursor: pointer; }
.anim-ec-send:disabled { background: var(--rk-line); color: var(--rk-ink-muted); cursor: not-allowed; }
.anim-ec-send svg { inline-size: 20px; block-size: 20px; stroke-width: 2; }
[dir="rtl"] .anim-ec-send svg { transform: scaleX(-1); }
.anim-ec button:focus-visible, .anim-ec-textarea:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .anim-as-stage.is-gliding { transition: none; }
  .anim-al-spin { animation: none; }
}
/* narrow desktop windows and tablets: the card takes the whole work area and shows one column at a time */
@media (max-width: 1100px) {
  /* §8.3 F5: …but it stops above the action bar, which stays visible (§5.2) */
  .anim-ec-layer { position: fixed; inset: 64px 0 var(--anim-cta-h, 0px) 0; z-index: 30; padding: 10px; }
  .anim-ec-body { grid-template-columns: minmax(0, 1fr); }
  .anim-ec-left { border-inline-end: 0; }
  .anim-ec-panes { display: inline-flex; flex: none; gap: 2px; margin-inline-start: auto; padding: 3px; border: 1px solid var(--rk-line); border-radius: 999px; }
  .anim-ec-panes button { min-block-size: 36px; padding: 0 14px; border: 0; border-radius: 999px; background: transparent; color: var(--rk-ink-soft); font: inherit; font-weight: 800; cursor: pointer; }
  .anim-ec-panes button[aria-selected="true"] { background: var(--rk-ink); color: #fff; }
  .anim-ec-x { margin-inline-start: 4px; }
  .anim-ec-kind { display: none; }
  .anim-ec.is-pane-edit .anim-ec-chat, .anim-ec.is-pane-chat .anim-ec-left { display: none; }
}
@media (max-width: 900px) {
  .anim-ad-grid.has-asset-list, .anim-ad-grid.has-asset-list.is-list-collapsed,
  .anim-sh-workbench.has-shot-list, .anim-sh-workbench.has-shot-list.is-list-collapsed { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 520px; }
  .anim-al { max-block-size: 260px; }
  .anim-al.is-collapsed .anim-al-rail { flex-direction: row; padding: 4px 10px; }
  .anim-al-rail-label { writing-mode: horizontal-tb; }
}

/* ── editor card · storyboard (docs/prd-anim-editor-big-card.md §7.1) ──
   Same card as the assets page. ~~It stopped above the floating filmstrip (inset-block-end: 136px)~~ — 10-09 S11: the
   strip became the shot list beside the canvas, so the card covers the whole canvas like the assets card does. */
.anim-sh-workbench.has-editor-card .anim-canvas-hint { visibility: hidden; }
/* storyboard canvas card tools (S15): the pencil (opens the editor card straight in the edit-prompt mode) and the
   magnifier — one row in the picture's top end corner, equal circles on one centre line, shown on hover and on the
   picked card (and to keyboard focus). New class only: frozen pages keep their 24px buttons. */
.anim-sh-tools { position: absolute; inset-block-start: 8px; inset-inline-end: 8px; z-index: 2; display: flex; align-items: center; gap: 6px; }
.anim-sh-tools .anim-as-edit, .anim-sh-tools .anim-as-zoom { position: static; display: grid; place-items: center; inline-size: 32px; block-size: 32px; padding: 0; border: 1px solid var(--rk-line); border-radius: 50%; background: var(--rk-surface); color: var(--rk-ink); box-shadow: 0 2px 10px -4px rgb(0 0 0 / 40%); font-size: 0; line-height: 0; opacity: 0; transition: opacity 0.15s, color 0.15s, background-color 0.15s; }
.anim-sh-tools .anim-as-edit { cursor: pointer; }
.anim-sh-tools .anim-as-zoom { cursor: zoom-in; }
.anim-sh-tools svg { inline-size: 17px; block-size: 17px; }
.anim-sh-tools .anim-as-edit:hover, .anim-sh-tools .anim-as-zoom:hover { background: var(--rk-paper-2); color: var(--rk-emerald); }
.anim-as-node:hover .anim-sh-tools > button, .anim-as-node.is-selected .anim-sh-tools > button, .anim-sh-tools > button:focus-visible { opacity: 1; }
.anim-sh-tools > button:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
/* button text standard, layout half (S16 rule 4): a label never wraps; when a row is short of room the reason line
   gives way first, then a label is cut with an ellipsis (its full text is in the title) — the primary never leaves
   the card or drops to a second line */
.anim-ec-ghost, .anim-ec-link { max-inline-size: 100%; overflow: hidden; text-overflow: ellipsis; }
.anim-ec-actions .anim-ec-primary { flex: 0 1 auto; min-inline-size: 0; max-inline-size: 100%; }
.anim-ec-primary > span { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; }
.anim-ec-row > .anim-ec-ghost { flex: 0 1 auto; min-inline-size: 0; }
/* Keep the Pro upstream-wait explanation readable beside the three actions on a small screen. */
@media (max-width: 680px) {
  .anim-pro-inspector .anim-ec-actions { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.2fr); }
  .anim-pro-inspector .anim-ec-actions > button { min-inline-size: 0; }
  .anim-pro-inspector .anim-ec-why { grid-column: 1 / -1; grid-row: 1; }
  .anim-pro-inspector .anim-ec-why:empty { display: none; }
}
/* the asset card's magnifier carries the same icon now */
.anim-as-zoom svg { inline-size: 14px; block-size: 14px; vertical-align: middle; }
/* ~~.anim-ec-tabs.is-asking / .anim-ec.is-shots .anim-ec-tab img~~ — 10-09 S12: the storyboard's scope tabs became the
   vertical rail below. */
/* scope rail (S12): far left of the card's left column — the whole shot, then each cell, at a size that reads as a
   picture you can pick; the picked one has the emerald ring */
.anim-ec-split { flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); min-block-size: 0; }
.anim-ec-split.has-rail { grid-template-columns: 152px minmax(0, 1fr); }
.anim-ec-split-main { display: flex; flex-direction: column; min-inline-size: 0; min-block-size: 0; container-type: inline-size; }
.anim-ec-rail { display: flex; flex-direction: column; gap: 10px; min-block-size: 0; padding: 14px 12px; overflow-y: auto; overscroll-behavior: contain; border-inline-end: 1px solid var(--rk-line); background: var(--rk-paper); }
.anim-ec-rail-hint { margin: 0 2px; color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; line-height: 1.4; }
.anim-ec-rail.is-asking .anim-ec-rail-hint { color: var(--rk-ink); }
.anim-ec-cell { display: grid; gap: 6px; padding: 5px; border: 2px solid var(--rk-line); border-radius: 14px; background: var(--rk-surface); color: var(--rk-ink-soft); font: inherit; text-align: center; cursor: pointer; }
.anim-ec-cell:hover { border-color: var(--rk-ink-muted); color: var(--rk-ink); }
.anim-ec-rail.is-asking .anim-ec-cell { border-style: dashed; }
.anim-ec-cell.is-on { border-color: var(--rk-emerald); background: var(--rk-emerald-soft); color: var(--rk-ink); box-shadow: 0 0 0 2px color-mix(in srgb, var(--rk-emerald) 22%, transparent); }
.anim-ec-cell-img { position: relative; display: block; border-radius: 9px; background: var(--rk-paper-2); overflow: hidden; }
.anim-ec-cell-img img { display: block; inline-size: 100%; block-size: auto; }
.anim-ec-cell-img .anim-ec-stale { position: absolute; inset-block-start: 4px; inset-inline-start: 4px; }
.anim-ec-cell-name { font-size: 0.875rem; font-weight: 800; }
.anim-ec-rail .anim-ec-wait { display: flex; align-items: center; gap: 6px; }
/* picture and notes: stacked by default so the picture gets the full width; side by side only on a wide card */
.anim-ec-main.has-notes { grid-auto-rows: max-content; align-content: start; }
.anim-ec-main.has-notes .anim-ec-stagebox { flex: none; block-size: clamp(280px, 42vh, 440px); min-block-size: 0; }
@container (min-width: 980px) {
  .anim-ec-main.has-notes { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); grid-auto-rows: minmax(0, 1fr); align-content: stretch; overflow: hidden; }
  .anim-ec-main.has-notes .anim-ec-media, .anim-ec-main.has-notes > .anim-ec-prompt { min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; }
  .anim-ec-main.has-notes .anim-ec-stagebox { flex: 1; block-size: auto; min-block-size: 260px; }
}
/* frame notes (S13) */
.anim-ec-prompt.is-notes { gap: 12px; }
.anim-ec-prompt .anim-ec-prompt-head { align-items: center; }
.anim-ec-link { margin-inline-start: auto; display: inline-flex; align-items: center; gap: 6px; min-block-size: 36px; padding: 0 14px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-surface); color: var(--rk-ink); font: inherit; font-size: 0.875rem; font-weight: 800; white-space: nowrap; cursor: pointer; }
.anim-ec-link:hover:not(:disabled) { background: var(--rk-paper-2); }
.anim-ec-link:disabled { opacity: 0.5; cursor: not-allowed; }
.anim-ec-link svg { inline-size: 14px; block-size: 14px; }
.anim-ec-frames { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.anim-ec-frame { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; align-items: start; inline-size: 100%; padding: 10px 12px; border: 1px solid var(--rk-line); border-radius: 14px; background: var(--rk-surface); color: var(--rk-ink); font: inherit; text-align: start; }
button.anim-ec-frame { cursor: pointer; }
button.anim-ec-frame:hover { border-color: var(--rk-ink-muted); background: var(--rk-paper); }
.anim-ec-frame-n { grid-row: span 2; padding: 2px 10px; border-radius: 999px; background: var(--rk-paper-2); color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 800; white-space: nowrap; }
.anim-ec-frame-text { font-size: 0.975rem; line-height: 1.55; overflow-wrap: anywhere; }
.anim-ec-frame-cam { grid-column: 2; color: var(--rk-ink-soft); font-size: 0.8rem; line-height: 1.4; }
.anim-ec-focus { display: grid; gap: 10px; }
.anim-ec-focus-text { margin: 0; font-size: 1.05rem; font-weight: 700; line-height: 1.6; overflow-wrap: anywhere; }
.anim-ec-cam { justify-self: start; padding: 2px 10px; border-radius: 999px; background: var(--rk-paper-2); color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; }
.anim-ec-details { display: grid; gap: 6px; margin: 0; padding-inline-start: 18px; color: var(--rk-ink-soft); font-size: 0.9rem; line-height: 1.5; overflow-wrap: anywhere; }
.anim-ec-notes-edited { margin: 0; color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 700; }
.anim-ec-paras { display: grid; gap: 10px; }
.anim-ec-paras p { margin: 0; font-size: 0.975rem; line-height: 1.6; overflow-wrap: anywhere; }
.anim-ec-unsaved { margin: 0; padding: 6px 12px; border-radius: 10px; background: color-mix(in srgb, var(--rk-warn) 16%, var(--rk-surface)); font-size: 0.875rem; font-weight: 700; }
/* "used in this shot" (S18, Andy 10-09: no pill frame, no big rounding — spacing and order do the work): each item is
   the picture at its own proportions on one common height with the name under it; cast, then sets, then props */
.anim-ec-used { display: grid; gap: 10px; padding-block-start: 6px; }
.anim-ec-used-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 14px 18px; }
.anim-ec-used-item { display: grid; justify-items: start; gap: 6px; max-inline-size: 132px; padding: 0; border: 0; background: none; color: var(--rk-ink); font: inherit; font-size: 0.85rem; font-weight: 700; text-align: start; cursor: zoom-in; }
.anim-ec-used-item img { display: block; block-size: 64px; inline-size: auto; max-inline-size: 132px; border-radius: 4px; background: var(--rk-paper-2); }
.anim-ec-used-item span { max-inline-size: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.anim-ec-used-item:hover span { color: var(--rk-emerald); }
.anim-ec-used-item:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 3px; }
/* edit mode: save / restore / regenerate sit under the text they act on; the picture gives the text more room */
.anim-ec-main.has-notes.is-editing .anim-ec-stagebox { block-size: clamp(200px, 28vh, 320px); }
.anim-ec-tab .anim-ec-stale, .anim-ec-stagebox > .anim-ec-stale { padding: 1px 6px; border-radius: 999px; background: color-mix(in srgb, var(--rk-warn) 18%, var(--rk-surface)); color: var(--rk-ink); font-size: 0.75rem; font-weight: 800; }
.anim-ec-stagebox > .anim-ec-stale { position: absolute; inset-block-start: 10px; inset-inline-start: 10px; }
.anim-ec-wait { align-self: center; color: var(--rk-ink-soft); font-size: 0.875rem; }
.anim-ec-row { display: flex; flex-wrap: wrap; gap: 8px; }
.anim-ec-ver.is-pending { cursor: default; opacity: 0.7; }
.anim-ec-ver.is-pending .anim-al-spin { margin-block: 22px; }
/* Jeff 2026-10-13: the picked version chip shows it is loading (ring over its picture, Loading… label); the others stay grey */
.anim-ec-ver.is-switching { position: relative; border-color: var(--rk-emerald); color: var(--rk-ink); cursor: progress; }
.anim-ec-ver.is-switching:disabled { opacity: 1; cursor: progress; }
.anim-ec-ver.is-switching img { opacity: 0.45; }
.anim-ec-ver.is-switching .anim-al-spin { position: absolute; inset-block-start: 21px; inset-inline-start: calc(50% - 11px); inline-size: 22px; block-size: 22px; border-width: 2.5px; }
/* Jeff 2026-10-13: the Stop after a run outlived the server's own deadline — a quiet line and a plain button under the orbit */
.anim-run-stop { display: grid; justify-items: center; gap: 8px; margin-block-start: 10px; max-inline-size: 280px; text-align: center; color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 600; }
.anim-run-stop-btn { display: inline-flex; align-items: center; gap: 6px; min-block-size: 34px; padding: 0 14px; border: 1.5px solid var(--rk-danger); border-radius: 999px; background: var(--rk-surface); color: var(--rk-danger); font: inherit; font-weight: 800; cursor: pointer; }
.anim-run-stop-btn:disabled { opacity: 0.6; cursor: progress; }
.anim-as-regen.is-stop { border-color: var(--rk-danger); color: var(--rk-danger); }
.anim-ec-history { margin: 0 16px 6px; }
.anim-ec-tray { margin: 0 12px 8px; }
.anim-ec-composer .anim-ec-scope { align-self: center; flex: none; }
.anim-ec-notes .anim-ref-diagnostic, .anim-ec-notes [role="alert"] { margin: 0; }

/* ── 视频页第三轮 (docs/prd-anim-editor-big-card.md §8.1, Andy 10-09) ──
   No left pane and no banner row: the player sits in the middle of the work area at the largest 16:9 that fits, the
   shot's row (which shot, its state, edit, film) sits between the player and the strip, the strip spans the whole width.
   New class names only — frozen pages (and the old .anim-vd-wrap grid) keep their rules. */
.anim-vdc { --anim-vd-strip-h: 150px; display: flex; flex-direction: column; gap: 14px; width: 100%; height: var(--anim-desk-h); min-height: 0; }
@media (min-width: 901px) { .anim-cw-main.is-video > .anim-vdc { flex: 1; height: auto; } }
.anim-vdc-main { position: relative; flex: 1; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: 12px; }
.anim-vdc-stagebox { min-height: 0; display: grid; place-items: center; }
/* the player and its title line share one column exactly as wide as the 16:9 picture: the title is left-aligned with
   the picture's edge and never widens it (inline-size containment = it does not count towards the column width) */
.anim-vdc-player { height: 100%; max-width: 100%; min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 10px; }
.anim-vdc-player > .anim-vd-stage { height: 100%; max-height: 100%; justify-self: start; }
.anim-vdc-tools { z-index: 5; }
.anim-vd-stage:hover .anim-vdc-tools > button, .anim-vdc-tools > button:focus-visible { opacity: 1; }
.anim-vdc-tools > button { opacity: 0.92; }
.anim-vdc-row { display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; align-items: center; gap: 8px; min-height: 48px; }
.anim-vdc-head { contain: inline-size; display: flex; align-items: center; gap: 12px; min-height: 40px; min-width: 0; }
.anim-vdc-head > .anim-as-topright { position: static; flex: none; margin-inline-start: auto; gap: 8px; }
.anim-vdc-shot { flex: 1 1 auto; display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0; color: var(--rk-ink-soft); font-size: 0.95rem; font-weight: 700; }
.anim-vdc-shot > b { flex: none; padding: 2px 9px; border-radius: 999px; background: var(--rk-paper-2); color: var(--rk-ink); font-size: 0.8rem; }
.anim-vdc-title { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: var(--rk-ink); }
.anim-vdc-state { flex: none; }
.anim-vdc-shot.is-waiting_dependency .anim-vdc-state { color: var(--rk-ink); }
.anim-vdc-shot.is-blocked_by_predecessor .anim-vdc-state, .anim-vdc-shot.is-needs_attention .anim-vdc-state { color: var(--rk-danger); }
.anim-vdc-go { flex: none; min-height: 32px; padding: 0 12px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-surface); color: var(--rk-ink); font: inherit; font-size: 0.85rem; font-weight: 800; white-space: nowrap; cursor: pointer; }
.anim-vdc-acts { display: flex; align-items: center; gap: 10px; }
.anim-vdc-edit, .anim-vdc-film { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 20px; border-radius: 999px; font: inherit; font-size: 0.95rem; font-weight: 800; white-space: nowrap; cursor: pointer; }
.anim-vdc-edit { border: 1px solid var(--rk-line); background: var(--rk-surface); color: var(--rk-ink); }
.anim-vdc-edit svg { width: 16px; height: 16px; }
.anim-vdc-edit:hover:not(:disabled) { background: var(--rk-paper-2); }
/* outline, not solid: the batch (top right) and the next step (bottom bar) already carry the page's solid greens */
.anim-vdc-film { border: 1.5px solid var(--rk-emerald); background: var(--rk-surface); color: var(--rk-emerald-hover); }
.anim-vdc-film svg { width: 18px; height: 18px; }
.anim-vdc-film:hover:not(:disabled) { background: var(--rk-emerald-soft); }
.anim-vdc-edit:disabled, .anim-vdc-film:disabled { border-color: var(--rk-line); background: var(--rk-paper-2); color: var(--rk-ink-muted); cursor: not-allowed; }
.anim-vdc-edit:focus-visible, .anim-vdc-film:focus-visible, .anim-vdc-go:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-vdc-fail { justify-self: center; margin: 0; color: var(--rk-danger); font-size: 0.875rem; font-weight: 700; }
.anim-vdc-foot { flex: none; }
/* §8.2 V11: the shot list sits left of the player area (same column as the storyboard step); the editor card covers
   the whole area right of it */
/* §8.3 F12: the video step's work area uses the full height between the header and the action bar, like the asset
   and storyboard steps, so the left list keeps its place when moving between them */
@media (min-width: 901px) { .anim-cw-main.is-video:has(> .anim-vdc) { padding-block: 0; } }
.anim-vdc.has-shot-list { display: grid; grid-template-columns: clamp(248px, 16vw, 300px) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); gap: 16px; }
.anim-vdc.has-shot-list.is-list-collapsed { grid-template-columns: 48px minmax(0, 1fr); }
.anim-al-item.is-disabled { cursor: not-allowed; opacity: 0.55; }
.anim-al-item.is-disabled:hover { background: transparent; }
/* the video editor card (§8.1 V6): it covers the player area (batch, player, the shot's row); the strip stays below */
.anim-ec-ver.is-textual { min-width: 56px; min-height: 40px; padding: 6px 12px; font-size: 0.85rem; }
.anim-vdc-params { display: grid; gap: 8px; padding-top: 6px; border-top: 1px solid var(--rk-line); }
.anim-vdc-params .anim-vd-param-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 14px; }
.anim-vdc-params .anim-vd-param-row label { display: grid; gap: 4px; color: var(--rk-ink-soft); font-size: 0.85rem; font-weight: 700; }
.anim-vdc-params select { min-height: 38px; padding: 0 10px; border: 1px solid var(--rk-line); border-radius: 10px; background: var(--rk-surface); color: var(--rk-ink); font: inherit; }
.anim-vdc-params .anim-vd-param-note { margin: 0; color: var(--rk-ink-soft); font-size: 0.82rem; }
.anim-ec-chat.is-voices { padding-block-end: var(--anim-ec-float-clear, 0px); }
.anim-vdc-voices { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px 16px 18px; }
.anim-vdc-voices .anim-vd-side-block { display: grid; gap: 10px; margin: 0; }
.anim-vdc-voices .anim-ec-intro { margin: 0; }
/* the ⓘ in the bottom-left group (§8.1 V1): the sentence floats above on hover / focus, never taking a row */
.anim-cta-info { position: relative; display: inline-flex; flex: none; }
.anim-cta-info-btn { display: grid; place-items: center; width: 30px; height: 30px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--rk-ink-soft); cursor: help; }
.anim-cta-info-btn svg { width: 20px; height: 20px; }
.anim-cta-info-btn:hover, .anim-cta-info-btn:focus-visible { background: var(--rk-paper-2); color: var(--rk-ink); }
.anim-cta-info-btn:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-cta-info-tip { position: absolute; z-index: 40; inset-block-end: calc(100% + 10px); inset-inline-start: -6px; width: max-content; max-width: min(360px, 70vw); padding: 10px 12px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-surface); box-shadow: var(--rk-shadow-panel); color: var(--rk-ink); font-size: 0.85rem; font-weight: 600; line-height: 1.5; text-align: start; white-space: normal; visibility: hidden; opacity: 0; transition: opacity 0.12s; pointer-events: none; }
.anim-cta-info-btn:hover + .anim-cta-info-tip, .anim-cta-info-btn:focus + .anim-cta-info-tip { visibility: visible; opacity: 1; }
.anim-cta-start:has(.anim-cta-info) { display: flex; align-items: center; gap: 6px; }
/* §6.5 A5–A6: the action bar seats the collapsed task card at its right end (task-float.js centres it on the bar), and
   Kids MV uses the other lanes' layout (D7: progress bottom-left, main action centred) instead of a right-aligned one */
.anim-cta-bar.anim-cta-seat.is-kids-mv { justify-content: center; }
/* §8.3 F8: three columns — the main action alone in the middle one, whatever sits beside it in the right one (it wraps
   before reaching the seated task card, whose width task-float.js publishes as --rk-task-slot-w) */
.anim-cta-bar.anim-cta-seat { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; column-gap: 12px; }
.anim-cta-bar.anim-cta-seat > .anim-cta-main { grid-column: 2; grid-row: 1; }
.anim-cta-bar.anim-cta-seat > .anim-cta-side { grid-column: 3; grid-row: 1; justify-self: start; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; min-inline-size: 0; max-inline-size: calc(100% - var(--rk-task-slot-w, 0px)); }
.anim-cta-bar.anim-cta-seat > .anim-cta-side .anim-cta-lock-reason { max-inline-size: 360px; }
/* phones: one column, the progress, the main action, then the side group */
@media (max-width: 600px) {
  .anim-cta-bar.anim-cta-seat { grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .anim-cta-bar.anim-cta-seat > .anim-cta-main, .anim-cta-bar.anim-cta-seat > .anim-cta-side { grid-column: 1; grid-row: auto; justify-self: stretch; max-inline-size: none; }
  .anim-cta-bar.anim-cta-seat > .anim-cta-side { justify-content: center; }
  /* an ⓘ in the centred side group opens centred on itself, never past either screen edge */
  .anim-cta-bar.anim-cta-seat > .anim-cta-side .anim-cta-info-tip { inset-inline: auto; left: 50%; max-width: calc(100vw - 32px); transform: translateX(-50%); }
}
.anim-cta-bar.anim-cta-seat.is-kids-mv .anim-cta-caption { text-align: start; }
/* §8.3 F4: dismissed with Esc while hovered — hidden until the pointer leaves the ⓘ */
.anim-cta-info.is-dismissed .anim-cta-info-tip { visibility: hidden; opacity: 0; }
/* an ⓘ that carries a warning (e.g. the author's own prompt is behind the system's) */
.anim-cta-info.is-alert .anim-cta-info-btn { color: var(--rk-amber-ink, #9a5b00); }
/* §8.3 F14: inside an editor card only the fixed action row's primary is solid green — a proposal's "draw it like this"
   and the "save to the character workshop" confirm are outlined emerald (they still mean "go") */
.anim-ec .anim-dd-prop-go, .anim-ec .sb-as-insp-redraw { border: 1.5px solid var(--rk-emerald); background: var(--rk-surface); color: var(--rk-emerald-hover); box-shadow: none; }
.anim-ec .anim-dd-prop-go:hover:not(:disabled), .anim-ec .sb-as-insp-redraw:hover:not(:disabled) { background: var(--rk-emerald-soft); }
/* the type's placeholder above the state words when a card has no picture yet */
.anim-ec-empty-ph { display: grid; place-items: center; inline-size: 64px; block-size: 64px; margin-block-end: 6px; border: 1.5px dashed var(--rk-line); border-radius: 14px; color: var(--rk-ink-muted); }
.anim-ec-empty-ph svg { inline-size: 30px; block-size: 30px; stroke-width: 1.6; }
/* §8.3 F15: the lightbox's version steps and "2 / 3" */
.anim-lb-step { position: absolute; inset-block-start: 50%; z-index: 2; display: grid; place-items: center; inline-size: 48px; block-size: 48px; margin-block-start: -24px; border: 1px solid var(--rk-line); border-radius: 50%; background: rgb(255 255 255 / 92%); color: var(--rk-ink); cursor: pointer; }
.anim-lb-step[hidden] { display: none; }
.anim-lb-step svg { inline-size: 24px; block-size: 24px; stroke-width: 2; }
.anim-lb-step.is-prev { inset-inline-start: 24px; }
.anim-lb-step.is-next { inset-inline-end: 24px; }
.anim-lb-step:hover { background: #fff; color: var(--rk-emerald); }
.anim-lb-step:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
[dir="rtl"] .anim-lb-step svg { transform: scaleX(-1); }
.anim-lb-count { position: absolute; inset-block-end: 20px; inset-inline-start: 50%; z-index: 2; padding: 4px 12px; border-radius: 999px; background: rgb(0 0 0 / 55%); color: #fff; font-weight: 800; font-size: 0.85rem; transform: translateX(-50%); }
.anim-cta-info.is-down .anim-cta-info-tip { inset-block-end: auto; inset-block-start: calc(100% + 8px); }
.anim-cta-info.is-end .anim-cta-info-tip { inset-inline-start: auto; inset-inline-end: -6px; }
.anim-cta-info-tip > span { display: block; }
.anim-cta-info-tip > span + span { margin-block-start: 8px; }
/* §8.2 V14–V15: in the video card the prompt fills its column (its explanation is an ⓘ); the settings live in the
   footer's left end, the film button in its right end */
/* review 10-10: inside a card column the sentence is anchored to the whole heading row and never wider than it — the
   column scrolls (overflow), so a tip running past its edge was cut off */
.anim-ec-prompt-head, .anim-ec-derived .anim-ec-row { position: relative; }
.anim-ec-prompt-head > .anim-cta-info, .anim-ec-derived .anim-ec-row > .anim-cta-info { position: static; }
.anim-ec-prompt-head .anim-cta-info-tip, .anim-ec-derived .anim-ec-row .anim-cta-info-tip { inset-inline: 0 auto; max-width: min(360px, 100%); }
.anim-ec-prompt-head .anim-cta-info-btn { width: 26px; height: 26px; }
.anim-ec-prompt-head .anim-cta-info-btn svg { width: 18px; height: 18px; }
.anim-ec-main.is-video-main > .anim-ec-prompt { overflow: visible; }
.anim-ec-main.is-video-main > .anim-ec-prompt > .anim-ec-textarea { flex: 1 1 auto; min-block-size: 260px; }
/* The video editor uses the viewport scrim above; only the card has an opaque paper surface. */
/* Give the storyboard more of the desktop card while keeping a readable prompt and reference rail. */
@media (min-width: 1101px) {
  .anim-ec.is-video .anim-ec-body { grid-template-columns: minmax(0, 3fr) minmax(240px, 1fr); }
}
/* Keep the storyboard and prompt side by side when the card has enough room. */
@container (min-width: 540px) {
  .anim-ec-main.has-notes.is-video-main { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); grid-auto-rows: minmax(0, 1fr); align-content: stretch; overflow: hidden; }
  .anim-ec-main.is-video-main .anim-ec-media { min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; }
  .anim-ec-main.is-video-main > .anim-ec-prompt { min-block-size: 0; }
  .anim-ec-main.is-video-main > .anim-ec-prompt > .anim-ec-textarea { min-block-size: 0; }
}
/* Let the image set its own height at the top of the media column, without a stretched background frame. */
.anim-ec-main.has-notes.is-video-main .anim-ec-stagebox:has(> img) { flex: none; block-size: auto; min-block-size: 0; aspect-ratio: auto; background: transparent; }
.anim-ec-main.is-video-main .anim-ec-stagebox > img { position: static; display: block; inline-size: 100%; block-size: auto; }
.anim-ec-actions.is-video { flex-wrap: nowrap; }
.anim-ec-actions.is-video > .anim-vdc-params { flex: 0 1 auto; min-inline-size: 0; }
.anim-ec-actions.is-video > .anim-ec-primary { flex: none; margin-inline-start: auto; }
.anim-ec-actions.is-video .anim-ec-why { text-align: end; }
.anim-ec-actions.is-video .anim-vdc-params { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 0; border: 0; }
.anim-ec-actions.is-video .anim-vdc-params label { display: inline-flex; align-items: center; gap: 6px; color: var(--rk-ink-soft); font-size: 0.85rem; font-weight: 700; }
.anim-ec-actions.is-video .anim-vd-param-note { color: var(--rk-ink-soft); font-size: 0.82rem; font-weight: 700; }
.anim-ec-actions.is-video .anim-vd-param-note.is-error { color: var(--rk-danger); }
.anim-ec-actions.is-video .anim-vd-param-note:empty, .anim-vd-side-block.is-compact .anim-vd-voice-note:empty { display: none; }
.anim-vdc-voices-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.anim-vdc-voices-head > .anim-card-kicker { margin: 0; }
/* §6.5 A7: "say this line" is the shared pill switch (emerald when on), its words at the card's type size */
.anim-vdc-voices .anim-vd-voice-switch.is-pill { gap: 8px; color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 700; }
.anim-vdc-voices .anim-vd-voice-row.is-off .anim-vd-voice-switch.is-pill { color: var(--rk-ink-muted); }
/* in the card the subtitle / spoken-line boxes use the pane's width and the card's type size (the old modal kept them
   at 12px in a narrow column) */
.anim-vdc-voices .anim-vd-voice-row { align-items: stretch; }
.anim-vdc-voices .anim-vd-voice-field { align-self: stretch; }
.anim-vdc-voices .anim-vd-voice-field { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 4px 8px; }
.anim-vdc-voices .anim-vd-voice-field > span:first-child { grid-column: 1 / -1; min-inline-size: 0; font-size: 0.8rem; }
.anim-vdc-voices .anim-vd-voice-field input { min-block-size: 36px; font-size: 0.9rem; }
/* §8.3 F13: the wrapping line boxes (same look as the inputs they replace) */
.anim-vdc-voices .anim-vd-voice-field textarea { flex: 1 1 auto; min-inline-size: 0; min-block-size: 36px; padding: 7px 10px; border: 1px solid var(--rk-line); border-radius: var(--rk-radius-sm); background: var(--rk-surface, #fff); color: var(--rk-ink); font: inherit; font-size: 0.9rem; line-height: 1.45; resize: none; overflow: hidden; }
.anim-vdc-voices .anim-vd-voice-field textarea:disabled { background: var(--rk-paper); color: var(--rk-ink-muted); }
.anim-vdc-voices .anim-vd-voice-field textarea:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 1px; }
/* 专业版 video card (step 7): length / resolution are read-only in its footer (each shot is timed by its plan), the
   right pane lists the numbered references at a readable size */
.anim-ec-actions.is-video .anim-vdc-params.is-readonly { gap: 6px 8px; color: var(--rk-ink-soft); font-size: 0.85rem; font-weight: 700; }
.anim-vdc-params.is-readonly > b { margin-inline-end: 10px; color: var(--rk-ink); font-weight: 800; }
/* Keep the next-take duration explanation inside the mobile editor, including RTL. */
@media (max-width: 680px) {
  .anim-pro-video .anim-ec-actions.is-video { position: relative; }
  .anim-pro-video .anim-vdc-params > .anim-cta-info { position: static; }
  .anim-pro-video .anim-vdc-params .anim-cta-info-tip {
    inset-inline: 10px auto;
    inset-block-end: calc(100% + 8px);
    max-width: calc(100% - 20px);
  }
}
.anim-ec-chat.is-refs .anim-vd-refs { margin: 0; padding: 0; border: 0; }
.anim-ec-chat.is-refs .anim-vd-refs .anim-card-kicker { margin: 0 0 10px; }
.anim-ec-chat.is-refs .anim-pro-refs { gap: 8px; }
.anim-ec-chat.is-refs .anim-pro-ref { grid-template-columns: 96px minmax(0, 1fr); gap: 12px; padding: 6px; border-radius: 12px; }
.anim-ec-chat.is-refs .anim-pro-ref-thumb { inline-size: 96px; block-size: 64px; border-radius: 8px; }
.anim-ec-chat.is-refs .anim-pro-ref-thumb i { padding: 4px; font-size: 0.72rem; line-height: 1.25; text-align: center; }
.anim-ec-chat.is-refs .anim-pro-ref-text { font-size: 0.875rem; line-height: 1.4; }
.anim-vdc-row > .anim-pro-note { margin: 0; justify-self: center; }
@media (max-width: 900px) {
  .anim-vdc.has-shot-list, .anim-vdc.has-shot-list.is-list-collapsed { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto; height: auto; }
  .anim-vdc-main { grid-template-rows: auto auto; }
  .anim-vdc-player { width: 100%; height: auto; }
  .anim-vdc-player > .anim-vd-stage { width: 100%; height: auto; }
  .anim-vdc-foot { height: auto; }
}

/* ── 动画专业版 导演手记 (docs/prd-anim-pro-director-notes.md, 10-09): a column beside the director wait (its own layer:
   the wait overlay replaces its DOM on every progress change), a drawer under 1100px, a side panel on the later steps.
   Ink text on paper; emerald only on the live dot, the spinner of the step being worked on. */
.anim-pro-wait-home {
  position: absolute;
  inset-block-start: max(12px, env(safe-area-inset-top));
  inset-inline-start: max(22px, env(safe-area-inset-left));
  inline-size: 40px;
  block-size: 40px;
  margin: 0;
  text-decoration: none;
}
.anim-pro-wait-home svg { inline-size: 18px; block-size: 18px; }
.anim-pro-wait-home:hover { color: var(--rk-ink); background: var(--rk-paper-2); }
.anim-pro-wait-home:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
/* The director page after a failed run (#3936): it stays up — the step it stopped in marked, the bar no longer
   reading as moving, the retry under the steps. It waits for the author, so it sits under the modal layer
   (.rk-modal 100): a wall the retry runs into (credits, subscription) opens on top of it instead of behind it. */
.rk-app-loading.is-pro-director-failed { z-index: 90; }
/* the sorry pose is a tall still, not the square running loop */
.rk-app-loading.is-pro-director-failed .rk-app-loading-cat { object-fit: contain; }
.rk-app-loading.is-pro-director-failed .rk-app-loading-progress > i { background: var(--rk-ink-muted); }
.rk-app-loading.is-pro-director-failed .rk-app-loading-stages li.is-failed { color: var(--rk-danger); background: color-mix(in srgb, var(--rk-danger) 7%, var(--rk-surface)); }
.rk-app-loading.is-pro-director-failed .rk-app-loading-stages li.is-failed > span,
.rk-app-loading.is-pro-director-failed .rk-app-loading-stages li.is-failed .rk-loading-stage-dot { border-color: var(--rk-danger); background: var(--rk-danger); box-shadow: inset 0 0 0 2px var(--rk-surface); }
.anim-pro-wait-actions { margin-top: 20px; }
.anim-pro-notes.is-wait.is-failed { z-index: 91; }
.anim-pro-notes {
  position: fixed;
  z-index: 2005; /* above the wait overlay (2000), under the lifted task float (2010) */
  inset-block-start: 16px;
  inset-inline-end: 24px;
  display: flex;
  flex-direction: column;
  inline-size: clamp(360px, 30vw, 460px);
  max-block-size: calc(100dvh - 32px - var(--anim-pro-notes-foot, 0px));
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-panel);
  color: var(--rk-ink);
  font-family: var(--rk-font-body);
}
.anim-pro-notes.is-panel { z-index: 1170; inset-block-start: 80px; max-block-size: calc(100dvh - 104px - var(--anim-pro-notes-foot, 0px)); }
body.has-anim-pro-notes .rk-app-loading { padding-inline-end: calc(clamp(360px, 30vw, 460px) + 40px); }
.anim-pro-notes-head { display: flex; align-items: center; gap: 10px; min-block-size: 54px; padding: 10px 14px 10px 18px; border-block-end: 1px solid var(--rk-line); }
.anim-pro-notes-head h2 { margin: 0; font-family: var(--rk-font-display); font-size: 1rem; line-height: 1.3; }
.anim-pro-notes-live { flex: none; inline-size: 8px; block-size: 8px; border-radius: 50%; background: var(--rk-emerald); animation: anim-pro-notes-pulse 1.6s ease-in-out infinite; }
.anim-pro-notes.is-panel .anim-pro-notes-live,
.anim-pro-notes.is-failed .anim-pro-notes-live { animation: none; background: var(--rk-ink-muted); }
.anim-pro-notes-meta { display: none; color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 700; }
.anim-pro-notes-elapsed { margin-inline-start: auto; color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 700; white-space: nowrap; }
.anim-pro-notes-close { display: inline-grid; place-items: center; margin-inline-start: auto; inline-size: 40px; block-size: 40px; border: 0; border-radius: 50%; background: transparent; color: var(--rk-ink-soft); cursor: pointer; }
.anim-pro-notes-close:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.anim-pro-notes-close:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-pro-notes-close svg { inline-size: 18px; block-size: 18px; stroke-width: 1.8; }
.anim-pro-notes-failed { margin: 0; padding: 10px 18px; border-block-end: 1px solid var(--rk-line); background: var(--rk-paper-2); color: var(--rk-ink); font-size: 0.95rem; line-height: 1.5; }
.anim-pro-notes-body { position: relative; flex: 1 1 auto; min-block-size: 0; overflow-y: auto; overscroll-behavior: contain; padding: 4px 18px 14px; }
.anim-pro-notes-body:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: -2px; }
.anim-pro-notes-sec { padding-block: 8px; }
.anim-pro-notes-sec + .anim-pro-notes-sec { border-block-start: 1px solid var(--rk-line); }
.anim-pro-notes-sec-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  inline-size: 100%;
  min-block-size: 40px;
  padding: 6px 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.anim-pro-notes-sec-head:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; border-radius: 8px; }
.anim-pro-notes-state { flex: none; inline-size: 16px; block-size: 16px; margin-block-start: 3px; border: 1.5px solid var(--rk-ink-muted); border-radius: 50%; }
.anim-pro-notes-sec.is-done .anim-pro-notes-state { position: relative; border-color: var(--rk-ink); }
.anim-pro-notes-sec.is-done .anim-pro-notes-state::after {
  content: "";
  position: absolute;
  inset-inline-start: 4px;
  inset-block-start: 2px;
  inline-size: 4px;
  block-size: 7px;
  border: solid var(--rk-ink);
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg);
}
.anim-pro-notes-sec.is-active .anim-pro-notes-state { border-color: var(--rk-emerald); }
.anim-pro-notes-sec-text { display: grid; gap: 2px; min-inline-size: 0; }
.anim-pro-notes-sec-title { font-family: var(--rk-font-display); font-size: 1rem; font-weight: 700; color: var(--rk-ink); }
.anim-pro-notes-sec-sum { color: var(--rk-ink-soft); font-size: 0.875rem; font-weight: 600; line-height: 1.5; }
.anim-pro-notes-sec-sum:empty { display: none; }
.anim-pro-notes-chev { margin-inline-start: auto; color: var(--rk-ink-soft); transition: transform 0.2s ease; }
.anim-pro-notes-chev svg { inline-size: 18px; block-size: 18px; stroke-width: 1.8; }
.anim-pro-notes-sec.is-open .anim-pro-notes-chev { transform: rotate(180deg); }
.anim-pro-notes-items { display: none; padding-inline-start: 26px; padding-block: 2px 4px; }
.anim-pro-notes-sec.is-open .anim-pro-notes-items { display: block; }
.anim-pro-notes-sub { margin: 12px 0 6px; color: var(--rk-ink); font-size: 0.875rem; font-weight: 800; }
.anim-pro-notes-item { margin: 0 0 12px; color: var(--rk-ink-soft); font-size: 1rem; line-height: 1.6; overflow-wrap: anywhere; }
.anim-pro-notes-lbl { display: block; color: var(--rk-ink); font-size: 0.875rem; font-weight: 800; }
.anim-pro-notes-item.is-closing { color: var(--rk-ink); font-weight: 600; }
.anim-pro-notes-item:has(> .anim-pro-notes-txt.is-queued) { display: none; }
.anim-pro-notes-txt.is-typing::after { content: ""; display: inline-block; inline-size: 2px; block-size: 1em; margin-inline-start: 2px; vertical-align: -2px; background: var(--rk-ink); animation: anim-pro-notes-blink 1s steps(1) infinite; }
.anim-pro-notes-item.is-new { box-shadow: inset 3px 0 0 var(--rk-line); padding-inline-start: 10px; }
[dir="rtl"] .anim-pro-notes-item.is-new { box-shadow: inset -3px 0 0 var(--rk-line); }
.anim-pro-notes-divider { display: flex; align-items: center; gap: 10px; margin: 14px 0 10px; color: var(--rk-ink); font-size: 0.875rem; font-weight: 800; }
.anim-pro-notes-divider::before,
.anim-pro-notes-divider::after { content: ""; flex: 1; block-size: 1px; background: var(--rk-ink-muted); }
.anim-pro-notes-thinking { display: flex; align-items: center; gap: 8px; margin: 2px 0 4px; color: var(--rk-ink-soft); font-size: 0.95rem; font-weight: 700; }
.anim-pro-notes-spin { flex: none; inline-size: 16px; block-size: 16px; border: 2px solid var(--rk-line); border-block-start-color: var(--rk-emerald); border-radius: 50%; animation: anim-pro-notes-spin 0.9s linear infinite; }
.anim-pro-notes-latest {
  position: sticky;
  inset-block-end: 6px;
  display: block;
  margin-inline-start: auto;
  min-block-size: 40px;
  padding: 8px 14px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  box-shadow: var(--rk-shadow-card);
  color: var(--rk-ink);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 800;
  cursor: pointer;
}
.anim-pro-notes-latest[hidden] { display: none; }
.anim-pro-notes-sr { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* the entry on the later steps' action bar — it rides in the bar's start-edge group (.anim-cta-start), so the bar's main
   button stays centred (Rule #411 — the primary action never moves) */
.anim-pro-notes-open {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 8px;
  min-block-size: 40px;
  padding: 8px 14px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  background: var(--rk-surface);
  color: var(--rk-ink);
  font: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
}
.anim-pro-notes-open:hover { background: var(--rk-paper-2); }
.anim-pro-notes-open:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-pro-notes-open svg { inline-size: 18px; block-size: 18px; stroke-width: 1.8; }
@keyframes anim-pro-notes-pulse { 50% { opacity: 0.35; } }
@keyframes anim-pro-notes-blink { 50% { opacity: 0; } }
@keyframes anim-pro-notes-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .anim-pro-notes-live, .anim-pro-notes-spin, .anim-pro-notes-txt.is-typing::after { animation: none; }
  .anim-pro-notes-chev { transition: none; }
}
/* narrow: a bottom drawer; the handle shows the count and the step being worked on */
@media (max-width: 1099px) {
  body.has-anim-pro-notes .rk-app-loading { padding-inline-end: 0; padding-block-end: 72px; }
  .anim-pro-notes,
  .anim-pro-notes.is-panel {
    inset-inline: 0;
    inset-block-start: auto;
    inset-block-end: 0;
    inline-size: auto;
    max-block-size: 72dvh;
    border-end-start-radius: 0;
    border-end-end-radius: 0;
    transform: translateY(calc(100% - 56px - env(safe-area-inset-bottom, 0px)));
    transition: transform 0.25s ease;
  }
  .anim-pro-notes.is-open,
  .anim-pro-notes.is-panel { transform: none; }
  .anim-pro-notes-head { cursor: pointer; padding-block-end: calc(10px + env(safe-area-inset-bottom, 0px)); }
  .anim-pro-notes.is-open .anim-pro-notes-head { padding-block-end: 10px; }
  .anim-pro-notes-meta { display: inline; }
  .anim-pro-notes-elapsed { display: none; }
  @media (prefers-reduced-motion: reduce) { .anim-pro-notes { transition: none; } }
}

/* ── 动画专业版 创作页 (docs/prd-anim-relay-pro-integration.md §5.4): shot cards with their three layers, the clips
   and the light film page. Quiet paper chrome; the pictures carry the colour, shown at their own 16:9 ratio. */
.anim-pro-film, .anim-pro-cut {
  inline-size: min(1240px, 100%);
  margin-inline: auto;
  padding: 20px 24px 120px;
}
.anim-pro-film-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-block-end: 16px; }
.anim-pro-film-head h2 { margin: 0; font-family: var(--rk-font-display); font-size: 1.35rem; }
.anim-pro-film-head p { margin: 0; color: var(--rk-ink-soft); font-size: 0.9rem; font-weight: 600; }
.anim-pro-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
}
.anim-pro-card {
  display: grid;
  grid-template-rows: auto auto auto;
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius);
  background: var(--rk-surface);
}
.anim-pro-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 10px 12px 8px; }
.anim-pro-card-head strong { font-size: 0.92rem; font-weight: 800; }
.anim-pro-card-head span { color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 600; }
.anim-pro-card-media { aspect-ratio: 16 / 9; background: var(--rk-paper-2); }
.anim-pro-card-media img, .anim-pro-card-media video { display: block; inline-size: 100%; block-size: 100%; object-fit: contain; }
.anim-pro-cut-stage > .anim-pro-card-empty { max-block-size: min(58vh, 640px); inline-size: 100%; }
.anim-pro-card-empty {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 9;
  color: var(--rk-ink-soft);
  font-size: 0.85rem;
  font-weight: 600;
}
.anim-pro-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-block-size: 48px; padding: 8px 12px; }
.anim-pro-layers { display: inline-flex; gap: 4px; padding: 3px; border: 1px solid var(--rk-line); border-radius: 999px; background: var(--rk-paper-2); }
.anim-pro-layer {
  min-block-size: 28px;
  padding-inline: 12px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--rk-ink-soft);
  font-family: var(--rk-font-body);
  font-size: 0.8rem;
  font-weight: 800;
  cursor: pointer;
}
.anim-pro-layer.is-active { background: var(--rk-surface); color: var(--rk-emerald-hover); box-shadow: var(--rk-shadow-card); }
.anim-pro-chip {
  display: inline-flex;
  align-items: center;
  min-block-size: 26px;
  padding-inline: 10px;
  border-radius: 999px;
  background: var(--rk-paper-2);
  color: var(--rk-ink-soft);
  font-size: 0.78rem;
  font-weight: 700;
}
.anim-pro-chip.is-busy { color: var(--rk-emerald-hover); }
.anim-pro-chip.is-bad { color: var(--rk-ink); background: color-mix(in srgb, var(--rk-ink) 8%, var(--rk-paper-2)); }
.anim-pro-retry { block-size: 32px; padding-inline: 14px; font-size: 0.82rem; }
.anim-pro-card-foot .rk-btn { block-size: 34px; padding-inline: 16px; font-size: 0.85rem; }
.anim-pro-cut-stage {
  overflow: hidden;
  border: 1px solid var(--rk-line);
  border-radius: var(--rk-radius-lg);
  background: var(--rk-paper-2);
}
.anim-pro-cut-stage video { display: block; inline-size: 100%; block-size: auto; max-block-size: min(58vh, 640px); object-fit: contain; background: #000; }
.anim-pro-cut-note { margin: 0; padding: 10px 14px; color: var(--rk-ink-soft); font-size: 0.88rem; font-weight: 700; background: var(--rk-surface); }
.anim-pro-cut-error { margin: 0; padding: 10px 14px; color: var(--rk-ink); font-weight: 700; background: var(--rk-surface); }
.anim-pro-cut-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; margin-block-start: 16px; }
.anim-pro-cut-actions .rk-btn { display: inline-flex; align-items: center; justify-content: center; text-decoration: none; }
@media (max-width: 680px) {
  .anim-pro-film, .anim-pro-cut { padding: 14px 16px 120px; }
  .anim-pro-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ── 专业版 storyboard canvas (docs/prd-anim-relay-pro-ux-parity.md §3.3): the entertainment canvas with the plates row,
   the action preview badge, picture numbers on the references of the selected item, and the left panel's extras. ── */
.anim-pro-workbench .anim-as-media { position: relative; }
.anim-pro-refno {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-end: 6px;
  z-index: 3;
  padding: 2px 7px;
  border-radius: 999px;
  color: #fff;
  background: var(--rk-emerald);
  font-size: 11px;
  font-weight: 800;
  line-height: 1.5;
  white-space: nowrap;
  box-shadow: 0 2px 8px -4px var(--rk-ink-soft);
  pointer-events: none;
}
.anim-sh-chip .anim-pro-refno { inset-block-start: -8px; inset-inline-end: -6px; }
.anim-pro-stick .anim-pro-refno { inset-block-start: -10px; inset-inline-end: -8px; font-size: 10px; }
.anim-pro-badges {
  position: absolute;
  inset-block-start: 6px;
  inset-inline-start: 6px;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-inline-size: calc(100% - 70px);
  pointer-events: none;
}
.anim-pro-badge {
  padding: 1px 7px;
  border: 1px solid var(--rk-line);
  border-radius: 999px;
  color: var(--rk-ink);
  background: color-mix(in srgb, var(--rk-surface) 92%, transparent);
  font-size: 10.5px;
  font-weight: 800;
  line-height: 1.6;
  white-space: nowrap;
}
.anim-pro-badge.is-stale { border-color: #c9935a; color: #8a5a28; }
.anim-as-node.is-stale { border-color: color-mix(in srgb, #c9935a 60%, var(--rk-line)); }
.anim-pro-stick {
  position: absolute;
  z-index: 2;
  display: block;
  padding: 0;
  overflow: visible;
  border: 1.5px solid var(--rk-surface);
  border-radius: 7px;
  background: var(--rk-paper-2);
  box-shadow: 0 4px 12px -6px var(--rk-ink-soft);
  cursor: pointer;
}
.anim-pro-stick img { display: block; inline-size: 100%; block-size: 100%; object-fit: cover; border-radius: 6px; }
.anim-pro-stick.is-selected { border-color: var(--rk-emerald); box-shadow: 0 0 0 3px var(--rk-emerald-soft); }
.anim-pro-stick.is-stale { border-color: #c9935a; }
.anim-pro-stick-tag {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 1px 4px;
  border-radius: 0 0 6px 6px;
  color: #fff;
  background: color-mix(in srgb, var(--rk-ink) 62%, transparent);
  font-size: 10px;
  font-weight: 800;
  line-height: 1.5;
}
.anim-pro-stick.is-none .anim-pro-stick-tag,
.anim-pro-stick.is-failed .anim-pro-stick-tag { inset-block: 0; border-radius: 6px; color: var(--rk-ink-soft); background: var(--rk-paper-2); }
.anim-pro-stick.is-failed .anim-pro-stick-tag { color: #a65a4a; }
.anim-pro-stick .spinner-sm { inline-size: 9px; block-size: 9px; }
.anim-as-edges path.is-ref.is-style { stroke-dasharray: 2 6; stroke-opacity: 0.06; }
.anim-as-edges path.is-ref.is-out { stroke-dasharray: 6 5; }
.anim-as-edges.has-focus path.is-ref.is-out { stroke-opacity: 0.55; }

.anim-pro-inspector .anim-pro-insp-media { position: relative; }
.anim-pro-inspector .anim-pro-insp-media .anim-shot-state.is-pill { position: absolute; inset-block-start: 8px; inset-inline-start: 8px; }
.anim-pro-inspector .anim-pro-insp-media .anim-shot-state.is-block {
  display: flex;
  min-block-size: 120px;
  justify-content: center;
  border: 1px dashed var(--rk-line);
  border-radius: 10px;
  background: var(--rk-paper-2);
}
.anim-pro-note { margin: 0; color: var(--rk-ink-soft); font-size: 12px; font-weight: 600; line-height: 1.5; }
/* Kids MV relay asset step: the cast, outfits, props and sets drawn for the film, read only, each at its own ratio */
.kmv-relay-assets-group { margin-block-start: 18px; }
.kmv-relay-assets-group h3 { margin: 0 0 10px; color: var(--rk-ink-soft); font-size: 0.95rem; font-weight: 700; }
.kmv-relay-assets-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); align-items: start; gap: 12px; }
.kmv-relay-asset { margin: 0; overflow: hidden; background: var(--rk-surface); border: 1px solid var(--rk-line); border-radius: var(--rk-radius-sm); }
.kmv-relay-asset img { display: block; inline-size: 100%; block-size: auto; background: var(--rk-paper-2); }
.kmv-relay-asset figcaption { padding: 8px 10px; color: var(--rk-ink); font-size: 0.85rem; font-weight: 600; line-height: 1.35; }
.anim-pro-note.is-stale { padding: 7px 9px; border: 1px solid color-mix(in srgb, #c9935a 55%, var(--rk-line)); border-radius: 9px; color: #8a5a28; background: color-mix(in srgb, #c9935a 8%, var(--rk-surface)); }
.anim-pro-src { color: var(--rk-ink-soft); font-weight: 700; }
.anim-pro-link {
  padding: 0;
  border: 0;
  color: var(--rk-emerald);
  background: none;
  font: inherit;
  font-size: 12px;
  font-weight: 800;
  cursor: pointer;
}
.anim-pro-link:disabled { color: var(--rk-ink-soft); cursor: default; }
.anim-pro-viewing { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 12px; font-weight: 700; color: var(--rk-ink-soft); }
.anim-pro-versions .anim-ed-version.is-current { border-color: var(--rk-emerald); }
.anim-pro-cells { display: grid; gap: 4px; }
.anim-pro-cells.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.anim-pro-cells.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.anim-pro-cell {
  position: relative;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--rk-line);
  border-radius: 6px;
  background-color: var(--rk-paper-2);
  background-repeat: no-repeat;
}
.anim-pro-cell b {
  position: absolute;
  inset-block-start: 3px;
  inset-inline-start: 3px;
  padding: 0 5px;
  border-radius: 999px;
  color: #fff;
  background: color-mix(in srgb, var(--rk-ink) 60%, transparent);
  font-size: 10px;
  line-height: 1.5;
}
/* a card storyboard's panel that can be changed on its own (animation-relay/pro-cells) */
.anim-pro-cell.is-pick { padding: 0; cursor: pointer; font: inherit; }
.anim-pro-cell.is-pick:hover:not(:disabled) { border-color: var(--rk-emerald); }
.anim-pro-cell.is-pick:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 1px; }
.anim-pro-cell.is-pick.is-active { border-color: var(--rk-emerald); box-shadow: 0 0 0 2px var(--rk-emerald); }
.anim-pro-cell.is-pick.is-failed { border-color: var(--rk-coral, #d9534f); }
.anim-pro-cell.is-pick:disabled { cursor: default; opacity: 0.7; }
.anim-pro-cell.is-pick .anim-al-spin { position: absolute; inset-block-start: 4px; inset-inline-end: 4px; }
.anim-pro-refs { display: flex; flex-direction: column; gap: 6px; }
.anim-pro-ref {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  padding: 4px;
  border: 1px solid var(--rk-line);
  border-radius: 9px;
  color: inherit;
  background: var(--rk-surface);
  font: inherit;
  text-align: start;
}
button.anim-pro-ref { cursor: pointer; }
button.anim-pro-ref:hover { border-color: color-mix(in srgb, var(--rk-emerald) 46%, var(--rk-line)); }
.anim-pro-ref-thumb { display: flex; align-items: center; justify-content: center; inline-size: 52px; block-size: 38px; overflow: hidden; border-radius: 6px; background: var(--rk-paper-2); }
.anim-pro-ref-thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; }
.anim-pro-ref-thumb > .anim-panel-cut { inline-size: 100%; flex: none; }
.anim-pro-ref-thumb .anim-panel-cut > img { object-fit: fill; }
.anim-pro-ref-thumb i { color: var(--rk-ink-soft); font-size: 10px; font-style: normal; font-weight: 700; }
.anim-pro-ref-text { display: flex; flex-direction: column; min-inline-size: 0; font-size: 11.5px; line-height: 1.35; }
.anim-pro-ref-text b { color: var(--rk-emerald); font-weight: 800; }
.anim-pro-ref-text span { color: var(--rk-ink-soft); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.anim-pro-edit { display: flex; flex-direction: column; gap: 7px; padding-block-start: 10px; border-block-start: 1px solid var(--rk-line); }
.anim-pro-edit .anim-ed-text { min-block-size: 70px; }
.anim-pro-inspector .anim-pro-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.anim-pro-inspector .anim-pro-actions .sb-as-insp-redraw { grid-column: 1 / -1; }

/* 专业版 video step (PRD ux-parity §3.4): the entertainment left pane plus the references and length/quality rows. The
   pane scrolls as one column instead of squeezing the prompt to nothing on a short window, and the shot's main action
   stays pinned to the bottom of the pane (it never moves or hides). */
.anim-pro-video .anim-vd-pane { overflow-y: auto; overscroll-behavior: contain; }
.anim-pro-video .anim-vd-pane > * { flex-shrink: 0; }
.anim-pro-video .anim-vd-prompt { flex: 0 0 auto; }
.anim-pro-video .anim-vd-prompt-preview { flex: 0 0 auto; max-block-size: 15.5em; }
.anim-pro-video .anim-vd-refs { margin-block-start: 14px; padding-block-start: 12px; border-block-start: 1px solid var(--rk-line); }
.anim-pro-video .anim-vd-refs .anim-card-kicker { margin: 0 0 8px; }
.anim-pro-video .anim-pro-ref-thumb i { padding: 2px; font-size: 9px; line-height: 1.15; text-align: center; }
.anim-pro-video-meta { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 14px 0 0; font-size: 12px; }
.anim-pro-video-meta > div { display: flex; gap: 6px; }
.anim-pro-video-meta dt { color: var(--rk-ink-soft); font-weight: 700; }
.anim-pro-video-meta dd { margin: 0; color: var(--rk-ink); font-weight: 800; }
.anim-pro-video .anim-vd-pane-actions {
  position: sticky;
  inset-block-end: -18px;
  z-index: 1;
  margin-block-start: auto;
  padding-block: 12px 0;
  background: var(--rk-surface);
}
.anim-pro-video-text { min-block-size: 200px; margin-block-start: 10px; resize: vertical; }
.anim-pro-video-edit-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; margin-block-start: 10px; }
.anim-pro-video-edit-actions .sb-as-insp-redraw { grid-column: 1 / -1; }
.anim-pro-video-edit-actions button { min-block-size: 40px; }

/* 专业版 direct mode (docs/plan-anim-pro-direct-mode.md 第 9 步): the clip's shot list in the keyframe card
   (lib/animation-pro-direct.js) — one card per 镜头: number, seconds, size, the action the author may change, the lines read only */
.anim-pro-shotlist { display: grid; gap: 8px; margin-block-start: 12px; }
.anim-pro-sl-rows { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.anim-pro-sl-row { display: grid; gap: 6px; padding: 10px 12px; border: 1px solid var(--rk-line); border-radius: 12px; background: var(--rk-surface); }
.anim-pro-sl-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.anim-pro-sl-no { display: inline-grid; place-items: center; min-inline-size: 22px; block-size: 22px; padding: 0 6px; border-radius: 999px; background: var(--rk-paper-2); color: var(--rk-ink); font-size: 0.75rem; font-weight: 800; }
.anim-pro-sl-t { color: var(--rk-ink-soft); font-size: 0.8125rem; font-variant-numeric: tabular-nums; }
.anim-pro-sl-size { display: inline-flex; align-items: center; gap: 6px; margin-inline-start: auto; color: var(--rk-ink-soft); font-size: 0.8125rem; }
.anim-pro-sl-size select { padding: 3px 8px; border: 1px solid var(--rk-line); border-radius: 8px; background: var(--rk-paper); color: var(--rk-ink); font: inherit; }
.anim-pro-sl-action { display: grid; gap: 4px; color: var(--rk-ink-soft); font-size: 0.8125rem; }
.anim-pro-sl-action textarea { box-sizing: border-box; inline-size: 100%; min-block-size: 76px; padding: 8px 10px; border: 1px solid var(--rk-line); border-radius: 10px; background: var(--rk-paper); color: var(--rk-ink); font: inherit; font-size: 0.9375rem; line-height: 1.55; resize: vertical; }
.anim-pro-sl-action textarea[aria-invalid="true"] { border-color: #b42318; }
.anim-pro-sl-lines { display: grid; gap: 2px; color: var(--rk-ink-soft); font-size: 0.8125rem; }
.anim-pro-sl-lines ul { margin: 0; padding-inline-start: 18px; color: var(--rk-ink); }
.anim-pro-sl-actions { display: flex; justify-content: flex-end; gap: 8px; }
/* 专业版 card method: a card's four picks in a row (two on a narrow card), its words as one-line boxes and one text box */
.anim-pro-card-picks { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 6px 10px; }
.anim-pro-card-pick { display: grid; gap: 3px; min-inline-size: 0; color: var(--rk-ink-soft); font-size: 0.8125rem; }
.anim-pro-card-pick select { box-sizing: border-box; inline-size: 100%; min-inline-size: 0; padding: 4px 8px; border: 1px solid var(--rk-line); border-radius: 8px; background: var(--rk-paper); color: var(--rk-ink); font: inherit; text-overflow: ellipsis; }
.anim-pro-card-row .anim-pro-sl-action textarea { min-block-size: 56px; }
.anim-pro-sl-action input[type="text"] { box-sizing: border-box; inline-size: 100%; padding: 7px 10px; border: 1px solid var(--rk-line); border-radius: 10px; background: var(--rk-paper); color: var(--rk-ink); font: inherit; font-size: 0.9375rem; }
.anim-pro-sl-action input[aria-invalid="true"] { border-color: #b42318; }

/* the canvas panel tree of a card shot (docs/plan-storyboard-cut-panels-20261019.md 第 5 步, design ①): a block holding the
   slim head card, the tree line and one card per panel; the line is outside the edges svg, so a selection never dims it */
.anim-pro-block { position: absolute; border-radius: 16px; background: color-mix(in srgb, var(--rk-surface) 55%, transparent); outline: 1px solid var(--rk-line); cursor: pointer; }
.anim-pro-block.is-selected { background: color-mix(in srgb, var(--rk-emerald) 7%, transparent); outline: 2px solid var(--rk-emerald); }
.anim-pro-block.is-related:not(.is-selected) { outline: 2px solid var(--rk-emerald-soft); }
.anim-pro-block.is-stale { outline-style: dashed; }
.anim-as-node.is-pro-head { flex-direction: row; align-items: center; gap: 6px; padding: 6px 8px 6px 10px; border-radius: 12px; }
.anim-as-node.is-pro-head:hover { transform: none; }
.anim-pro-head-tag { flex: none; padding: 2px 8px; border-radius: 8px; background: var(--rk-paper-2); font-size: 0.85rem; font-weight: 800; }
.anim-pro-head-meta { flex: 1; min-inline-size: 0; overflow: hidden; color: var(--rk-ink-soft); font-size: 0.78rem; font-weight: 700; white-space: nowrap; text-overflow: ellipsis; }
.anim-as-node.is-pro-head .anim-al-state { flex: none; font-size: 0.75rem; }
.anim-as-node.is-pro-head .anim-pro-badges, .anim-as-node.is-pro-head .anim-pro-refno { position: static; }
.anim-as-node.is-pro-head .anim-as-zoom { position: static; flex: none; display: grid; place-items: center; inline-size: 28px; block-size: 28px; padding: 0; border: 1px solid var(--rk-line); border-radius: 50%; background: var(--rk-surface); color: var(--rk-ink-soft); }
.anim-as-node.is-pro-head .anim-as-zoom svg { inline-size: 15px; block-size: 15px; }
.anim-as-node.is-pro-head .anim-shot-generate { flex: none; margin-inline-start: 0; }
.anim-pro-tree { position: absolute; box-sizing: border-box; border-inline-start: 2px solid color-mix(in srgb, var(--rk-emerald) 35%, transparent); border-block-end: 2px solid color-mix(in srgb, var(--rk-emerald) 35%, transparent); border-end-start-radius: 8px; pointer-events: none; }
.anim-as-node.is-pro-panel { gap: 4px; padding: 5px; border-radius: 10px; }
.anim-as-node.is-pro-panel .anim-panel-cut { inline-size: 100%; }
.anim-pro-panel-ph { display: grid; place-items: center; inline-size: 100%; aspect-ratio: 16 / 9; border: 1.5px dashed var(--rk-line); border-radius: 7px; background: var(--rk-paper); color: var(--rk-ink-muted); box-sizing: border-box; }
.anim-pro-panel-ph svg { inline-size: 22px; block-size: 22px; stroke-width: 1.6; }
.anim-pro-panel-label { position: relative; display: grid; gap: 1px; min-inline-size: 0; font-size: 0.72rem; line-height: 1.25; }
.anim-pro-panel-label b { flex: none; font-weight: 800; }
.anim-pro-panel-label span { overflow: hidden; color: var(--rk-ink-soft); white-space: nowrap; text-overflow: ellipsis; }
.anim-pro-panel-label .spinner-sm { position: absolute; inset-inline-end: 0; inset-block-start: 0; }
.anim-as-node.is-pro-panel.is-failed { border-color: color-mix(in srgb, var(--rk-danger) 55%, var(--rk-line)); }

/* the dialog's panel tree (docs/plan-storyboard-cut-panels-20261019.md 第 6 步, design ②): 整镜 / 格 N first, then the picked
   panel cut from the storyboard (or the used panels side by side), its badge, the versions and the edit context cut the
   same way; the lightbox shows the same cut. A panel picture's own <img> is placed by its inline box — the general img
   rules of the stage, the version chips and the lightbox never size it */
/* Compact thumbnails stay in one scrollable row, leaving room for the selected panel's preview. */
.anim-pro-pick { display: flex; flex: none; gap: 8px; align-items: stretch; min-inline-size: 0; max-inline-size: 100%; padding: 2px 2px 6px; overflow-x: auto; overscroll-behavior-inline: contain; }
.anim-pro-pick > button { display: flex; box-sizing: border-box; align-items: center; gap: 6px; padding: 5px; border: 1px solid var(--rk-line); border-radius: 10px; background: var(--rk-surface); color: inherit; font: inherit; text-align: start; cursor: pointer; }
.anim-pro-pick > button:hover:not(:disabled) { border-color: color-mix(in srgb, var(--rk-emerald) 46%, var(--rk-line)); }
.anim-pro-pick > button[aria-checked="true"] { border: 2px solid var(--rk-emerald); background: var(--rk-emerald-soft); padding: 4px; }
.anim-pro-pick > button:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
.anim-pro-pick-whole { flex: none; flex-direction: column; justify-content: center; inline-size: 56px; color: var(--rk-ink-soft); font-size: 0.8rem; font-weight: 800; }
.anim-pro-pick-whole span { max-inline-size: 100%; overflow-wrap: anywhere; text-align: center; font-size: 0.75rem; line-height: 1.3; }
.anim-pro-pick-whole svg { inline-size: 20px; block-size: 20px; }
.anim-pro-pick > .anim-pro-pick-panel { flex: 0 0 96px; min-inline-size: 0; position: relative; flex-direction: column; align-items: stretch; gap: 4px; text-align: start; }
.anim-pro-pick-panel .anim-panel-cut, .anim-pro-pick-panel .anim-pro-panel-ph { flex: none; inline-size: 100%; }
.anim-pro-pick-text { display: grid; gap: 2px; min-inline-size: 0; }
.anim-pro-pick-text b { overflow: hidden; font-size: 0.75rem; font-weight: 800; white-space: nowrap; text-overflow: ellipsis; }
.anim-pro-pick-text { padding-inline: 2px; }
.anim-pro-pick-panel .anim-al-spin { position: absolute; inset-block-start: 6px; inset-inline-end: 6px; }
/* one panel: as large as the stage allows at 16:9 (the stage is a size container); the used panels: the stage grows with them */
.anim-ec-stagebox.is-panels { display: grid; place-items: center; container-type: size; }
.anim-ec-stagebox.is-panels .anim-pro-stage-cut { inline-size: min(100cqw, calc(100cqh * 16 / 9)); aspect-ratio: 16 / 9; border-radius: 0; }
.anim-ec-stagebox.is-panels:has(.anim-pro-stage-mosaic) { container-type: normal; block-size: auto; min-block-size: 0; flex: none; }
.anim-pro-stage-badge { position: absolute; inset-block-start: 12px; inset-inline-start: 12px; padding: 3px 10px; border-radius: 10px; background: color-mix(in srgb, var(--rk-surface) 92%, transparent); font-size: 0.82rem; font-weight: 800; }
.anim-pro-mosaic { display: grid; gap: 6px; inline-size: 100%; }
.anim-pro-mosaic.is-1 { grid-template-columns: minmax(0, 1fr); }
.anim-pro-mosaic.is-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.anim-pro-mosaic.is-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.anim-pro-mosaic > .anim-panel-cut { inline-size: 100%; }
.anim-pro-stage-mosaic { align-self: center; padding: 8px; box-sizing: border-box; }
/* the panel thumbnail is a span too: undo the corner-badge rule (.anim-ed-version > span) or both spans float and the button
   collapses to its border (release QA 2026-10-28, BUG-PRO-06) */
.anim-ed-version .anim-pro-vthumb { position: static; padding: 0; border-radius: 0; background: none; gap: 2px; inline-size: 62px; }
.anim-ed-version .anim-pro-vthumb .anim-panel-cut { border-radius: 2px; }
.anim-pro-vthumb .anim-panel-cut > img, .anim-ec-ctx .anim-panel-cut > img, .anim-lb-cut .anim-panel-cut > img { width: auto; max-inline-size: none; max-block-size: none; aspect-ratio: auto; border-radius: 0; box-shadow: none; object-fit: fill; }
.anim-ec-ctx .anim-pro-ctx-cut { inline-size: 64px; flex: none; }
.anim-ec-ctx .anim-pro-ctx-mosaic { inline-size: 96px; flex: none; gap: 2px; }
.anim-ec-head .anim-pro-head-meta { color: var(--rk-ink-soft); font-size: 0.85rem; font-weight: 700; white-space: nowrap; }
.anim-lb-cut { display: block; inline-size: min(92vw, 1040px, calc(91vh * 16 / 9)); cursor: default; }
.anim-lb-cut[hidden] { display: none; }
.anim-lb-cut .anim-pro-mosaic { gap: 10px; }
.anim-lb-cut .anim-panel-cut { border-radius: 10px; box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45); }
/* "Continue contest entry" (lib/contest-continuation.js): the link plus a dismiss button. */
.rk-contest-return { display: flex; align-items: center; gap: 8px; margin: 0 0 16px; }
.rk-banner-close { display: grid; place-items: center; width: 32px; height: 32px; border: 0; border-radius: 8px; background: transparent; color: var(--rk-ink-muted); cursor: pointer; }
.rk-banner-close:hover { background: var(--rk-paper-2); color: var(--rk-ink); }
.rk-banner-close:focus-visible { outline: 2px solid var(--rk-emerald); outline-offset: 2px; }
