/* Keep the editorial title slot stable while the glyph shape changes. The
   full draft is available in the copy editor; the exported card keeps a
   compact title slot so it never pushes the subject or supporting copy. */
.canvas-board {
  --card-title-line-slot: clamp(30px, 7.4cqw, 64px);
  --card-subtitle-line-slot: clamp(12px, 2.1cqw, 22px);
  --card-title-gap: clamp(3px, .7cqw, 8px);
  --card-title-glyph-safe: clamp(2px, .35cqw, 6px);
}

.canvas-board .board-editorial-header .board-title-block {
  display: grid;
  grid-template-rows: var(--card-title-line-slot) var(--card-subtitle-line-slot);
  row-gap: var(--card-title-gap);
  height: calc(var(--card-title-line-slot) + var(--card-subtitle-line-slot) + var(--card-title-gap));
  min-height: 0 !important;
  align-content: start;
}

.canvas-board .board-editorial-header .board-title-block::after {
  display: none;
}

.canvas-board .board-editorial-header .board-title-block > strong {
  max-width: 100%;
  height: var(--card-title-line-slot);
  min-height: 0;
  /* A font outline is painted outside the CSS line box. Clipping this
     element cuts ascenders and the configurable stroke on some faces. Keep
     the line slot compact, but reserve horizontal breathing room and let the
     glyph paint outside its box. */
  padding-inline: var(--card-title-glyph-safe);
  overflow: visible;
  overflow-wrap: normal;
  text-overflow: clip;
  white-space: nowrap;
}

/* A very narrow card may still need more than the readable one-line minimum.
   Let that title wrap inside the local header instead of cutting glyphs at
   the right edge. The fit script marks this fallback after measuring the
   active display font. */
.canvas-board .board-editorial-header .board-title-block:has(> strong[data-title-fit="wrap"]) {
  grid-template-rows: auto auto;
  height: auto;
}

.canvas-board .board-editorial-header .board-title-block > strong[data-title-fit="wrap"] {
  height: auto;
  overflow: visible;
  overflow-wrap: anywhere;
  text-overflow: clip;
  white-space: normal;
}

.canvas-board .board-editorial-header .caption-description {
  height: var(--card-subtitle-line-slot);
  min-height: 0;
  margin-top: 0 !important;
  overflow: hidden !important;
  text-overflow: ellipsis;
  white-space: nowrap !important;
}

/* Direct editing should never hide the draft behind the export slot. The
   compact one-line treatment returns on blur, while focus temporarily lets
   the title block grow and wraps the complete value inside the card. */
.canvas-board .board-editorial-header .board-title-block:has(> [contenteditable="true"]:focus) {
  grid-template-rows: auto auto;
  height: auto;
  min-height: 50px !important;
}

.canvas-board .board-editorial-header .board-title-block > strong[contenteditable="true"]:focus,
.canvas-board .board-editorial-header .caption-description[contenteditable="true"]:focus {
  height: auto;
  min-height: 0;
  max-width: 100%;
  overflow: visible !important;
  overflow-wrap: anywhere;
  text-overflow: clip;
  white-space: normal !important;
  word-break: break-word;
  background: transparent;
}

/* Readability is never borrowed from the character beneath the copy. */
.canvas-board[data-style="quiet-paper"] .board-gear-tiles .board-gear-item,
.canvas-board[data-style="soft-pixel"] .board-gear-tiles .board-gear-item {
  background: rgb(250 248 244 / .985);
}

.canvas-board[data-style="blue-bitmap"] .board-gear-tiles .board-gear-item {
  background: rgb(235 247 248 / .985);
}

.canvas-board[data-style="scrapbook-pop"] .board-gear-tiles .board-gear-item {
  background: rgb(255 247 235 / .985);
}

/* The legacy card grid has a more specific display rule. Reassert the actual
   information-card contract here so copy starts on one predictable inset. */
.canvas-board .board-gear-tiles .gear-tile-copy,
.canvas-board[data-ratio="portrait"][data-cast="1"] .board-gear-tiles .gear-tile-copy {
  display: flex !important;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: start;
}

/* Card dimensions remain independent of export resolution. */
.canvas-board[data-ratio="portrait"] {
  width: min(100%, 760px);
  max-width: 760px;
}

body.canvas-focus-mode .canvas-board[data-ratio="portrait"] {
  width: min(100%, 840px);
  max-width: 840px;
}

/* Keep the complete composition and view tools inside a desktop window at
   the default view scale. User zoom remains an intentional closer view. */
@media (min-width: 921px) and (min-height: 650px) {
  .canvas-board[data-ratio="portrait"] {
    max-width: min(760px, calc((100dvh - 260px) * .8));
  }
  .canvas-board[data-ratio="square"] {
    max-width: min(760px, calc(100dvh - 260px));
  }
  .canvas-board[data-ratio="landscape"] {
    max-width: min(900px, calc((100dvh - 260px) * 1.77778));
  }
}

.canvas-board[data-ratio="portrait"][data-cast="1"] .board-gear-item {
  width: 34.2593%;
  height: 8.5926%;
}

/* Two-person cards keep each outfit attached to the character it describes.
   Wider, taller notes give the item name enough room to scan at working size. */
.canvas-board[data-cast="2"] .portrait-wrap {
  inset: 20% 22% 3% !important;
}

.canvas-board[data-cast="2"] .board-gear-list {
  inset: 0 !important;
  display: block !important;
  pointer-events: none;
}

.canvas-board[data-cast="2"] .board-gear-rail {
  position: absolute;
  top: var(--two-info-rail-top, 22.2222%);
  bottom: auto;
  display: grid;
  width: var(--two-info-rail-width, 19%);
  height: var(--two-info-rail-height, 64.2963%);
  grid-template-rows: minmax(0, 1fr);
  gap: var(--two-info-rail-gap, .5cqw);
  pointer-events: auto;
}

.canvas-board[data-cast="2"] .board-gear-rail--left {
  left: var(--two-info-rail-left, 6%);
}

.canvas-board[data-cast="2"] .board-gear-rail--right {
  right: var(--two-info-rail-right, 6%);
}

.canvas-board[data-cast="2"] .board-gear-rail-items {
  display: grid;
  height: 100%;
  min-height: 0;
  grid-template-rows: repeat(5, minmax(0, 1fr));
  gap: 5px;
}

.canvas-board[data-cast="2"] .board-gear-rail .board-gear-item {
  position: static;
  width: auto;
  height: auto;
  min-height: 0;
  align-self: stretch;
}

.canvas-board[data-cast="2"] .board-gear-rail .board-gear-item:nth-child(n) {
  grid-column: 1 !important;
  grid-row: auto !important;
  justify-self: stretch;
  width: auto !important;
}

.canvas-board[data-cast="2"] .board-gear-rail .gear-tile-copy {
  padding: 8% 9%;
}

.canvas-board[data-cast="2"] .board-gear-rail--left .gear-tile-copy {
  align-items: flex-start;
  text-align: left;
}

.canvas-board[data-cast="2"] .board-gear-rail--right .gear-tile-copy {
  align-items: flex-start;
  text-align: left;
}

.canvas-board[data-cast="2"] .board-gear-rail .gear-slot-label {
  font-size: clamp(8px, 1cqw, 12px);
}

.canvas-board[data-cast="2"] .board-gear-rail .gear-tile-copy strong {
  font-size: clamp(9px, 1.35cqw, 17px);
  line-height: 1.16;
}

.canvas-board[data-cast="2"] .board-gear-rail .gear-item-secondary {
  font-size: clamp(7px, .84cqw, 10px);
}

/* Full-frame screenshots have uncontrolled local contrast. Protect only the
   overlaid item copy with a soft paper halo; there is no opaque panel and the
   photograph remains the dominant surface. Mixed source cards use the same
   treatment so a single cutout cannot make the lineup visually inconsistent. */
.canvas-board[data-source-mode="original"][data-info="true"] .multi-info-column,
.canvas-board[data-source-mode="mixed"][data-info="true"] .multi-info-column {
  position: relative;
  isolation: isolate;
}

.canvas-board[data-source-mode="original"][data-info="true"] .multi-info-column::before,
.canvas-board[data-source-mode="mixed"][data-info="true"] .multi-info-column::before {
  position: absolute;
  inset: 18% 4% 16%;
  z-index: -1;
  border-radius: 999px;
  background: radial-gradient(
    ellipse,
    color-mix(in srgb, var(--recipe-panel, rgb(255 255 255 / .86)) 74%, transparent) 0%,
    color-mix(in srgb, var(--recipe-panel, rgb(255 255 255 / .86)) 42%, transparent) 46%,
    transparent 76%
  );
  content: "";
  filter: blur(8px);
  opacity: .76;
  pointer-events: none;
}

.portrait-wrap {
  cursor: grab;
  touch-action: none;
}

/* The preview is an editing surface, not just a passive output. Keep the
   empty state centered and place its photo actions beside the selected
   figure, while keeping them out of placement-mode drag interactions. */
.portrait-wrap .character-slot {
  position: relative;
  display: flex;
  min-width: 0;
  height: 100%;
  flex: 1 1 0;
  align-items: stretch;
  justify-content: center;
}

.portrait-wrap .character-slot .character-figure {
  width: 100%;
  flex: 1 1 auto;
  align-items: center;
}

.character-image-actions {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 30;
  display: flex;
  gap: 6px;
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease, transform 140ms ease;
}

.character-slot.is-selected .character-image-actions,
.character-slot:hover .character-image-actions,
.character-slot:focus-within .character-image-actions {
  opacity: 1;
  pointer-events: auto;
}

.character-image-action {
  min-height: 34px;
  padding: 0 12px;
  border: 1px solid color-mix(in oklch, var(--recipe-ink, var(--foreground)) 28%, transparent);
  border-radius: 999px;
  color: var(--recipe-ink, var(--foreground));
  background: color-mix(in oklch, var(--recipe-panel, var(--card)) 94%, transparent);
  box-shadow: 0 8px 18px color-mix(in oklch, var(--recipe-shadow, rgb(0 0 0 / .12)) 90%, transparent);
  font: 700 10px/1 var(--sans);
  white-space: nowrap;
}

.character-image-action:hover {
  border-color: var(--primary);
  background: var(--recipe-panel, var(--card));
  transform: translateY(-1px);
}

.character-image-action:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

.character-image-action--remove {
  color: color-mix(in oklch, var(--recipe-ink, var(--foreground)) 82%, #8a3f48);
}

body.image-placement-mode .character-image-actions {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .character-image-actions,
  .character-image-action { transition: none; }
}

.character-empty-placeholder {
  position: relative;
  display: grid;
  width: max-content;
  max-width: 100%;
  min-height: 0;
  align-content: center;
  justify-items: center;
  gap: 7px;
  padding: 0;
  border: 0;
  border-radius: 0;
  color: var(--recipe-ink, var(--foreground));
  background: transparent;
  box-shadow: none;
  text-align: center;
  transition: color 160ms ease, transform 160ms ease;
}

.character-empty-placeholder::before,
.character-empty-placeholder::after {
  display: none;
  content: none;
}

.character-empty-mark {
  display: grid;
  width: 32px;
  height: 32px;
  place-items: center;
  border: 1px solid color-mix(in oklch, var(--recipe-ink, var(--foreground)) 46%, transparent);
  border-radius: 50%;
  color: var(--recipe-ink, var(--foreground));
  font-size: 17px;
  line-height: 1;
}

.character-empty-kicker {
  color: color-mix(in oklch, var(--recipe-ink, var(--foreground)) 56%, transparent);
  font-family: var(--mono);
  font-size: 8px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.character-empty-placeholder strong {
  font-family: var(--sans);
  font-size: clamp(12px, 1.6cqw, 17px);
  font-weight: 700;
}

.character-empty-placeholder small {
  color: var(--recipe-muted, var(--muted-foreground));
  font-family: var(--sans);
  font-size: clamp(9px, 1.1cqw, 12px);
}

.character-figure.is-empty {
  align-items: center !important;
  cursor: pointer;
}

.character-figure.is-empty:hover .character-empty-placeholder,
.character-figure.is-empty:focus-visible .character-empty-placeholder {
  color: color-mix(in oklch, var(--recipe-ink, var(--foreground)) 78%, var(--primary));
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .character-empty-placeholder { transition: none; }
  .character-figure.is-empty:hover .character-empty-placeholder,
  .character-figure.is-empty:focus-visible .character-empty-placeholder { transform: none; }
}

@media (max-width: 560px) {
  .canvas-board[data-cast="3"] .character-empty-placeholder,
  .canvas-board[data-cast="4"] .character-empty-placeholder,
  .canvas-board[data-cast="5"] .character-empty-placeholder {
    gap: 5px;
  }

  .canvas-board[data-cast="3"] .character-empty-placeholder > small:not(.character-empty-kicker),
  .canvas-board[data-cast="4"] .character-empty-placeholder > small:not(.character-empty-kicker),
  .canvas-board[data-cast="5"] .character-empty-placeholder > small:not(.character-empty-kicker) {
    display: none;
  }

  .canvas-board[data-cast="3"] .character-empty-placeholder strong,
  .canvas-board[data-cast="4"] .character-empty-placeholder strong,
  .canvas-board[data-cast="5"] .character-empty-placeholder strong {
    font-size: 0;
    white-space: nowrap;
  }

  .canvas-board[data-cast="3"] .character-empty-placeholder strong::after,
  .canvas-board[data-cast="4"] .character-empty-placeholder strong::after,
  .canvas-board[data-cast="5"] .character-empty-placeholder strong::after {
    content: "슬롯";
    font-size: 10px;
  }

  .canvas-board[data-cast="3"] .character-empty-mark,
  .canvas-board[data-cast="4"] .character-empty-mark,
  .canvas-board[data-cast="5"] .character-empty-mark {
    width: 26px;
    height: 26px;
    font-size: 15px;
  }
}

.portrait-wrap.is-dragging {
  cursor: grabbing;
}

/* Common output grammar. Recipe changes are deliberately token-level only. */
.canvas-board[data-style="quiet-paper"],
.canvas-board[data-style="custom"] {
  --recipe-ink: #263238;
  --recipe-muted: rgb(38 50 56 / .58);
  --recipe-panel: rgb(255 252 247 / .94);
  --recipe-edge: rgb(38 50 56 / .18);
  --recipe-shadow: rgb(38 50 56 / .1);
}

.canvas-board[data-style="blue-bitmap"] {
  --recipe-ink: #214854;
  --recipe-muted: rgb(33 72 84 / .58);
  --recipe-panel: rgb(239 249 249 / .94);
  --recipe-edge: rgb(33 72 84 / .22);
  --recipe-shadow: rgb(33 72 84 / .11);
}

.canvas-board[data-style="soft-pixel"] {
  --recipe-ink: #5c465d;
  --recipe-muted: rgb(92 70 93 / .58);
  --recipe-panel: rgb(255 250 252 / .94);
  --recipe-edge: rgb(92 70 93 / .18);
  --recipe-shadow: rgb(92 70 93 / .1);
}

.canvas-board[data-style="scrapbook-pop"] {
  --recipe-ink: #6b3943;
  --recipe-muted: rgb(107 57 67 / .58);
  --recipe-panel: rgb(255 248 238 / .95);
  --recipe-edge: rgb(107 57 67 / .2);
  --recipe-shadow: rgb(107 57 67 / .11);
}

.canvas-board[data-background-tone="dark"][data-background-pattern="none"] {
  --recipe-ink: #f7f3ed;
  --recipe-muted: rgb(247 243 237 / .62);
  --recipe-panel: rgb(29 34 40 / .94);
  --recipe-edge: rgb(247 243 237 / .22);
  --recipe-shadow: rgb(9 12 16 / .28);
}

.canvas-board[data-style] .board-editorial-header {
  color: var(--recipe-ink);
}

.canvas-board[data-style] .board-editorial-header::after {
  display: none !important;
}

/* Title contrast belongs to the glyph itself. The removed full-header halo
   painted a white gradient over the artwork and made the export feel cropped. */
.canvas-board[data-style] .board-editorial-header {
  height: auto;
  min-height: 0 !important;
  pointer-events: none;
}

.canvas-board[data-style] .board-editorial-header::before {
  display: none !important;
}

.canvas-board[data-style] .board-editorial-header .board-title-block::before {
  display: none !important;
}

.canvas-board[data-style] .board-editorial-header .board-title-block {
  pointer-events: auto;
}

.canvas-board[data-style] .board-editorial-header .board-title-block {
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  transform: none !important;
}

.canvas-board[data-style] .board-editorial-header .board-title-block > strong {
  text-shadow: none !important;
  -webkit-text-stroke: var(--title-outline-width, 0px) var(--title-outline-color, transparent);
  paint-order: stroke fill;
}

.canvas-board[data-style] .board-gear-tiles .board-gear-item {
  border-color: var(--recipe-edge) !important;
  border-radius: 12px !important;
  background: var(--recipe-panel) !important;
  box-shadow: 0 10px 24px var(--recipe-shadow) !important;
}

.canvas-board[data-style] .board-gear-tiles .gear-tile-copy,
.canvas-board[data-style] .board-gear-tiles .gear-tile-copy strong {
  color: var(--recipe-ink) !important;
}

.canvas-board[data-style] .board-gear-tiles .gear-tile-copy span,
.canvas-board[data-style] .board-gear-tiles .gear-item-secondary {
  color: var(--recipe-muted) !important;
}

/* Solid dark boards need an explicit inverse information surface. Keep the
   contract keyed to the rendered tone rather than a particular preset so
   ink, charcoal, and a dark custom color cannot fall back to dark copy. */
.canvas-board[data-background-tone="dark"][data-background-pattern="none"] .board-gear-tiles .board-gear-item {
  border-color: var(--recipe-edge) !important;
  background: var(--recipe-panel) !important;
  box-shadow: 0 10px 24px var(--recipe-shadow) !important;
}

.canvas-board[data-background-tone="dark"][data-background-pattern="none"] .board-gear-tiles .gear-tile-copy,
.canvas-board[data-background-tone="dark"][data-background-pattern="none"] .board-gear-tiles .gear-tile-copy strong {
  color: var(--recipe-ink) !important;
}

.canvas-board[data-background-tone="dark"][data-background-pattern="none"] .board-gear-tiles .gear-tile-copy span,
.canvas-board[data-background-tone="dark"][data-background-pattern="none"] .board-gear-tiles .gear-item-secondary {
  color: var(--recipe-muted) !important;
}

.canvas-board[data-style] .multi-info-column {
  color: var(--recipe-ink);
}

/* Silhouette copy follows the card surface: neutral black on light surfaces,
   white on dark surfaces. The restrained inverse halo keeps either choice
   readable when the text crosses the dark cutout itself. */
.canvas-board[data-style][data-info="true"][data-info-mode="silhouette"] .multi-info-column {
  color: var(--silhouette-info-color, var(--recipe-ink));
  text-shadow: 0 1px 8px var(--silhouette-info-halo, rgb(255 255 255 / .9));
}
.canvas-board[data-style][data-info="true"][data-info-mode="silhouette"] .multi-info-items small {
  color: var(--silhouette-info-muted, currentColor);
}

/* The card copy is a single high-resolution graphic layer shared with PNG
   export. Keep the semantic contenteditable nodes in the accessibility tree
   and preserve their measured color; only their browser-painted glyphs are
   made transparent while the shared layer is ready. Direct editing reveals
   the native text temporarily so the caret and draft remain understandable. */
.canvas-board .board-copy-canvas {
  position: absolute;
  z-index: 17;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.canvas-board[data-copy-rendered="true"] .board-title-block > strong,
.canvas-board[data-copy-rendered="true"] .board-title-block > .caption-description,
.canvas-board[data-copy-rendered="true"] .board-copyright {
  filter: opacity(0) !important;
}

.canvas-board[data-copy-editing="true"] .board-copy-canvas {
  visibility: hidden;
}

.canvas-board[data-copy-editing="true"] .board-title-block > strong,
.canvas-board[data-copy-editing="true"] .board-title-block > .caption-description,
.canvas-board[data-copy-editing="true"] .board-copyright {
  filter: none !important;
}

/* A newly selected display face may arrive after the synchronous style pass.
   Keep the semantic copy visible while it loads instead of freezing a canvas
   painted with the old or fallback face. The shared canvas is redrawn as soon
   as the font-ready boundary clears. */
.canvas-board[data-copy-font-pending="true"] .board-copy-canvas {
  visibility: hidden;
}

.canvas-board[data-copy-font-pending="true"] .board-title-block > strong,
.canvas-board[data-copy-font-pending="true"] .board-title-block > .caption-description,
.canvas-board[data-copy-font-pending="true"] .board-copyright {
  filter: none !important;
}

/* Every saved card carries the same unobtrusive rights notice. It is a
   measured member of the shared copy layer, so its position and typography
   stay identical in the live preview and PNG export. */
.canvas-board .board-copyright {
  position: absolute;
  right: 5%;
  bottom: 1.6%;
  left: 5%;
  z-index: 18;
  display: block;
  overflow: hidden;
  color: var(--recipe-muted, var(--recipe-ink, currentColor));
  font-family: var(--mono, var(--sans));
  font-size: clamp(7px, 1.05cqw, 10px);
  font-weight: 650;
  letter-spacing: .04em;
  line-height: 1.2;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
  pointer-events: none;
}

/* Material 3 state treatment, kept in the app's neutral visual language. */
.compact-segments {
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--muted);
}

.compact-segments button {
  min-height: 28px;
  border-radius: 999px;
  transition: color 140ms ease, background-color 140ms ease, box-shadow 140ms ease;
}

.compact-segments button:hover:not(:disabled) {
  color: var(--foreground);
  background: color-mix(in oklch, var(--background) 68%, var(--muted));
}

.compact-segments button.is-selected {
  color: var(--foreground);
  background: var(--background);
  box-shadow: 0 1px 3px rgb(20 24 28 / .12);
}

.cast-count-control {
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: 999px;
}

.cast-count-control button {
  border-radius: 999px;
  transition: color 140ms ease, background-color 140ms ease, box-shadow 140ms ease;
}

.cast-count-control button.is-selected {
  color: var(--foreground);
  background: var(--background);
  box-shadow: 0 1px 3px rgb(20 24 28 / .12);
}

.rail-mode-button,
.rail-site-nav-toggle {
  box-shadow: none !important;
}

.rail-mode-button .tool-key,
.rail-site-nav-toggle .rail-site-nav-mark {
  display: inline-grid;
  width: 30px;
  height: 23px;
  min-width: 30px;
  min-height: 23px;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 999px;
  color: var(--muted-foreground);
  background: transparent;
  font-family: var(--sans);
  font-size: 10px;
  font-style: normal;
  font-weight: 700;
  line-height: 1;
  letter-spacing: .06em;
  text-align: center;
  transition: color 140ms ease, background-color 140ms ease;
}

.rail-mode-button.is-active,
.rail-site-nav[open] > .rail-site-nav-toggle {
  color: var(--sidebar-foreground);
  background: var(--sidebar-accent);
  box-shadow: none !important;
}

.rail-mode-button.is-active .tool-key,
.rail-site-nav[open] > .rail-site-nav-toggle .rail-site-nav-mark {
  color: var(--primary);
  background: color-mix(in oklch, var(--primary) 10%, transparent);
}

.toolbar-button:focus-visible,
.toolbar-icon:focus-visible,
.background-art-choice:focus-visible,
.compact-segments button:focus-visible,
.cast-count-control button:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--primary) 16%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .compact-segments button,
  .cast-count-control button,
  .rail-mode-button .tool-key,
  .rail-site-nav-toggle .rail-site-nav-mark {
    transition: none;
  }
}

@media (max-width: 920px) and (min-height: 600px) {
  body:not(.image-placement-mode):not(.canvas-focus-mode) .canvas-board[data-ratio="portrait"] {
    width: min(100%, 22svh); margin-inline: auto; min-height: 0;
  }
  body:not(.image-placement-mode):not(.canvas-focus-mode) .canvas-board[data-ratio="landscape"] {
    width: 100%; min-height: 0;
  }
}

/* Direct pattern selection controls the live preview opacity. */
.canvas-board[data-style] .scene-pattern {
  opacity: var(--pattern-opacity, 0) !important;
}

.canvas-board .scene-pattern[data-pattern="none"],
.canvas-board .scene-pattern[data-pattern="gradient"],
.canvas-board .scene-pattern[data-pattern="grain"] {
  display: none !important;
}

.canvas-board .scene-pattern[data-pattern="stars"]::before,
.canvas-board .scene-pattern[data-pattern="stars"]::after {
  display: none;
}

.canvas-board .scene-pattern[data-pattern="collage"] {
  display: none !important;
}

.canvas-board .scene-pattern[data-pattern="scrapbook"] {
  display: none !important;
}

.toolbar-button:focus-visible,
.toolbar-icon:focus-visible,
.background-art-choice:focus-visible,
.backdrop-swatch:focus-visible,
.compact-segments button:focus-visible,
.cast-count-control button:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--primary) 16%, transparent);
}

/* The selected figure is the edit surface. Dim the other figures so the
   cursor, focus ring, and keyboard target all point to the same object. */
body.image-placement-mode .canvas-board {
  outline: 2px solid var(--primary);
  outline-offset: 8px;
  box-shadow: 0 18px 44px color-mix(in oklch, var(--primary) 12%, transparent), 16px 18px 0 color-mix(in oklch, var(--primary) 16%, transparent);
}

body.image-placement-mode .canvas-board .character-figure {
  transition: opacity 180ms ease, filter 180ms ease, box-shadow 180ms ease;
}

body.image-placement-mode .canvas-board .portrait-wrap {
  z-index: 20 !important;
}

body.image-placement-mode .canvas-board .board-editorial-header,
body.image-placement-mode .canvas-board .multi-info-layer,
body.image-placement-mode .canvas-board .board-gear-list {
  opacity: .2;
  pointer-events: none !important;
}

body.image-placement-mode .canvas-board .character-figure:not(.is-selected) {
  opacity: .24;
  filter: saturate(.45);
  pointer-events: none;
}

body.image-placement-mode .canvas-board .character-figure.is-selected {
  z-index: 16;
  opacity: 1;
  outline: 2px solid var(--primary);
  outline-offset: 5px;
  box-shadow: 0 0 0 8px color-mix(in oklch, var(--primary) 12%, transparent);
}

body.image-placement-mode .canvas-board .character-figure.is-selected img {
  filter: none !important;
}

body.image-placement-mode .canvas-board .character-figure.is-selected:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 8px;
  box-shadow: 0 0 0 12px color-mix(in oklch, var(--primary) 20%, transparent);
}

body.image-placement-mode .canvas-board .portrait-wrap {
  cursor: grab;
}

body.image-placement-mode .canvas-board .portrait-wrap.is-dragging,
body.image-placement-mode .canvas-board .portrait-wrap.is-dragging .character-figure.is-selected {
  cursor: grabbing;
}

@media (prefers-reduced-motion: reduce) {
  body.image-placement-mode .canvas-board .character-figure {
    transition: none;
  }
}

/* Copy controls belong to the rendered card layer, not the textareas. The
   title owns alignment and color; the optional subtitle follows the title's
   alignment while keeping its quiet, theme-derived treatment. */
.canvas-board .board-editorial-header .board-title-block {
  width: 100%;
  text-align: left;
}

.canvas-board .board-editorial-header .board-title-block > strong {
  color: var(--card-title-color, var(--recipe-ink, currentColor)) !important;
  text-align: var(--card-title-align, left);
}

.canvas-board .board-editorial-header .caption-description {
  color: var(--recipe-ink, currentColor) !important;
  opacity: .68;
  text-align: var(--card-title-align, left) !important;
}

/* Keep the active copy target visible while the inspector is being used. This
   is editor-only chrome: the PNG renderer receives the same copy values and
   never receives this outline. */
.canvas-board[data-copy-target="title"] .board-editorial-header .board-title-block > strong,
.canvas-board[data-copy-target="subtitle"] .board-editorial-header .board-title-block > .caption-description {
  outline: 1px dashed color-mix(in oklch, var(--primary) 72%, transparent);
  outline-offset: clamp(3px, .5cqw, 7px);
}

/* Give the title block a real local width so left/center/right changes are
   visible even when the current title is short. Both preview and PNG use
   this same layer. */
.canvas-board .board-editorial-header .board-title-block {
  align-items: stretch;
}

.canvas-board .board-editorial-header .board-title-block > strong {
  display: block;
  width: 100%;
  max-width: 100%;
}

/* An empty optional subtitle should not leave either placeholder copy or a
   phantom second row in the card. During direct editing it becomes visible
   again so the user can intentionally start typing into it. */
.canvas-board .board-editorial-header .board-title-block:has(> .caption-description[data-empty="true"]) {
  grid-template-rows: var(--card-title-line-slot);
  row-gap: 0;
  height: var(--card-title-line-slot);
}

.canvas-board .board-editorial-header .caption-description[data-empty="true"] {
  display: block !important;
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  margin: -1px !important;
  padding: 0 !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
  border: 0 !important;
  pointer-events: none;
}

.canvas-board .board-editorial-header .board-title-block:has(> .caption-description[data-empty="true"]:focus) {
  grid-template-rows: auto;
  height: auto;
}

.canvas-board .board-editorial-header .board-title-block:has(> .caption-description[data-empty="true"]:focus) .caption-description {
  display: block !important;
  position: static !important;
  width: 100% !important;
  height: auto !important;
  margin: 0 !important;
  overflow: visible !important;
  clip: auto !important;
  clip-path: none !important;
  white-space: normal !important;
  pointer-events: auto;
}

/* Solo layer contract: equipment cards are information surfaces, so they
   must sit above the photo in every supported ratio and image mode. Keep
   title copy above both; the shared copy canvas and copyright remain higher
   still. The same contract is intentionally used by preview and PNG export. */
.canvas-board[data-ratio="portrait"][data-cast="1"] .board-editorial-header,
.canvas-board[data-ratio="landscape"][data-cast="1"] .board-editorial-header {
  z-index: 16 !important;
}

.canvas-board[data-ratio="portrait"][data-cast="1"] .portrait-wrap,
.canvas-board[data-ratio="landscape"][data-cast="1"] .portrait-wrap {
  z-index: 14 !important;
}

.canvas-board[data-ratio="portrait"][data-cast="1"] .board-gear-list,
.canvas-board[data-ratio="landscape"][data-cast="1"] .board-gear-list {
  z-index: 15 !important;
}

/* Preview/export parity contract. CardLayout supplies the absolute frame
   inset; these final rules remove legacy flex margins and make each live
   image use exactly the same frame that CardPng receives. */
.canvas-board .portrait-wrap {
  display: flex;
  align-items: stretch;
  justify-content: stretch;
}

.canvas-board .portrait-wrap .character-slot {
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
}

.canvas-board .portrait-wrap .character-slot .character-figure {
  width: 100%;
  min-width: 0;
  margin-inline: 0 !important;
  flex: 1 1 auto;
  align-items: stretch;
}

.canvas-board .portrait-wrap .character-slot .character-figure[data-cutout="false"] {
  overflow: hidden !important;
}

.canvas-board .portrait-wrap .character-slot .character-figure[data-cutout="true"] {
  overflow: visible !important;
}

.canvas-board .portrait-wrap .character-slot .character-figure img {
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
}

/* Keep the preview frame identical to CardPng's canvas frame. These legacy
   borders were part of layout, so every image became smaller than its export
   counterpart. Paint the same affordances without consuming image pixels. */
.canvas-board {
  border: 0;
}

.canvas-board[data-cutout="false"][data-cast="3"] .portrait-wrap .character-figure,
.canvas-board[data-cutout="false"][data-cast="4"] .portrait-wrap .character-figure,
.canvas-board[data-cutout="false"][data-cast="5"] .portrait-wrap .character-figure {
  border-right: 0;
  box-shadow: inset -1px 0 0 rgba(242, 244, 239, 0.42);
}

.canvas-board[data-cutout="false"][data-cast="3"] .portrait-wrap .character-figure:last-child,
.canvas-board[data-cutout="false"][data-cast="4"] .portrait-wrap .character-figure:last-child,
.canvas-board[data-cutout="false"][data-cast="5"] .portrait-wrap .character-figure:last-child {
  box-shadow: none;
}

/* Paper collage theme ----------------------------------------------------
   The visual treatment is reserved for meaningful information surfaces:
   each note is a paper scrap, its top tab identifies the equipment slot, and
   one small tape strip explains why the note is attached to the collage.
   The tape stays flat and deterministic so the PNG renderer can reproduce it
   without a second layout pass or expensive filters. */
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item {
  position: relative;
  overflow: visible;
  border: 1px solid rgb(65 52 40 / .2) !important;
  border-radius: 4px !important;
  background: #fffaf1 !important;
  box-shadow: 4px 5px 0 rgb(65 52 40 / .13), 0 12px 18px rgb(65 52 40 / .09) !important;
}

/* The portrait composition uses alternating absolute notes. Keep that layout
   contract when the material skin is active; two-person rails remain normal
   grid items and therefore keep their existing flow geometry. */
.canvas-board[data-background-pattern="collage"][data-ratio="portrait"][data-cast="1"] .board-gear-tiles .board-gear-item {
  position: absolute;
}

.canvas-board[data-background-pattern="collage"][data-ratio="landscape"][data-cast="1"] .board-gear-tiles .board-gear-item {
  position: absolute;
}

.canvas-board[data-background-pattern="collage"][data-cast="2"] .board-gear-rail .board-gear-item {
  position: relative;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item::before {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: max(4px, .45cqw);
  background: var(--collage-slot-color, #82909a);
  content: "";
  pointer-events: none;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item::after {
  position: absolute;
  top: -3%;
  left: 37%;
  z-index: 2;
  width: 25%;
  height: 10%;
  border: 1px solid rgb(92 74 54 / .08);
  background: rgb(215 196 164 / .72);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .32);
  content: "";
  pointer-events: none;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item[data-card-slot="head"] { --collage-slot-color: #7d96a5; }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item[data-card-slot="body"] { --collage-slot-color: #a97778; }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item[data-card-slot="hands"] { --collage-slot-color: #8b9b86; }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item[data-card-slot="legs"] { --collage-slot-color: #b29467; }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item[data-card-slot="feet"] { --collage-slot-color: #817b98; }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item[data-card-slot="weapon"],
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item[data-card-slot="offhand"] { --collage-slot-color: #646b70; }

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-tile-copy,
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-tile-copy strong {
  color: #2f302e !important;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-tile-copy span,
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-item-secondary {
  color: rgb(47 48 46 / .62) !important;
}

.canvas-board[data-background-pattern="collage"] .scene-background {
  z-index: 0;
}

/* Vintage scrapbook is an editorial material skin: the source image remains
   the subject while cool paper, archive scraps, tape, and fine ink marks sit
   behind it. Notes are intentionally paper-like rather than rounded UI cards.
   The PNG renderer repeats these same surfaces without changing geometry. */
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item {
  position: relative;
  overflow: visible;
  border: 0 !important;
  border-radius: 2px !important;
  clip-path: none;
  background: transparent !important;
  box-shadow: none !important;
}

/* The solo note rail is an absolute editorial composition. The relative
   positioning above is only the containing block for the pseudo-elements;
   never let the material skin turn the five fixed notes into normal flow. */
.canvas-board[data-background-pattern="scrapbook"][data-cast="1"] .board-gear-tiles .board-gear-item {
  position: absolute;
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-surface {
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 0;
  box-sizing: border-box;
  border: 1px solid rgb(48 69 75 / .25);
  clip-path: polygon(0 3%, 7% 1%, 15% 2%, 24% 0, 34% 2%, 44% 1%, 55% 2%, 65% 0, 76% 2%, 87% 1%, 100% 3%, 99% 22%, 100% 44%, 98% 65%, 100% 82%, 98% 100%, 87% 98%, 77% 100%, 67% 98%, 56% 100%, 45% 98%, 35% 100%, 24% 98%, 14% 100%, 4% 98%, 0 100%, 1% 80%, 0 61%, 2% 41%, 0 20%);
  background:
    linear-gradient(90deg, var(--scrapbook-slot-color, #6f8790) 0 var(--scrapbook-stripe-width), transparent var(--scrapbook-stripe-width) 100%),
    linear-gradient(180deg, rgb(255 252 244 / .48), transparent 28%),
    #f7f0e3;
  filter: drop-shadow(6px 7px 0 rgb(48 69 75 / .14)) drop-shadow(0 14px 22px rgb(48 69 75 / .11));
  content: "";
  pointer-events: none;
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item:nth-child(2n) .gear-note-surface {
  background:
    linear-gradient(90deg, var(--scrapbook-slot-color, #6f8790) 0 var(--scrapbook-stripe-width), transparent var(--scrapbook-stripe-width) 100%),
    linear-gradient(180deg, rgb(255 255 255 / .38), transparent 30%),
    #eef1ed;
  filter: drop-shadow(3px 8px 0 rgb(48 69 75 / .13)) drop-shadow(0 14px 22px rgb(48 69 75 / .09));
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item:nth-child(3n) .gear-note-surface {
  background:
    linear-gradient(90deg, var(--scrapbook-slot-color, #6f8790) 0 var(--scrapbook-stripe-width), transparent var(--scrapbook-stripe-width) 100%),
    linear-gradient(180deg, rgb(255 250 240 / .42), transparent 30%),
    #f2e5d7;
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item[data-card-slot="head"] { --scrapbook-slot-color: #6f8790; }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item[data-card-slot="body"] { --scrapbook-slot-color: #9c6e63; }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item[data-card-slot="hands"] { --scrapbook-slot-color: #7f8d78; }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item[data-card-slot="legs"] { --scrapbook-slot-color: #b18457; }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item[data-card-slot="feet"] { --scrapbook-slot-color: #766b80; }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item[data-card-slot="weapon"],
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item[data-card-slot="offhand"] { --scrapbook-slot-color: #4d5b5d; }

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-tile-copy,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-tile-copy strong {
  color: #3b4040 !important;
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-tile-copy span,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-item-secondary {
  color: rgb(59 64 64 / .68) !important;
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-tile-copy {
  position: relative;
  z-index: 1;
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles {
  --scrapbook-stripe-width: max(5px, .6cqw);
}

.canvas-board[data-background-pattern="scrapbook"] .board-editorial-header {
  color: #294650;
}

.canvas-board[data-background-pattern="scrapbook"] .board-editorial-header .board-title-block {
  background: transparent !important;
  box-shadow: none !important;
  transform: none !important;
}

.canvas-board[data-background-pattern="scrapbook"] .scene-background,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-list {
  z-index: 0;
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-list {
  z-index: 9;
}

/* Generated material kit -------------------------------------------------
   The two public presets use different material grammars. These overrides
   consume the generated paper boards as real surfaces instead of simulating
   them with flat fills. The DOM remains a semantic information layer; the
   material is decorative and never replaces the item text or source photo. */
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item {
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item::before,
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item::after {
  display: none !important;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-note-surface,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-surface {
  display: block;
  position: absolute;
  inset: 0;
  z-index: 0;
  box-sizing: border-box;
  border: 1px solid color-mix(in srgb, var(--material-ink) 25%, transparent);
  background-color: var(--material-note-tint, #f7f0e3);
  background-image:
    linear-gradient(180deg, rgb(255 255 255 / .2), transparent 34%),
    var(--material-surface);
  background-position: 0 0, var(--material-position, 50% 50%);
  background-size: 100% 100%, 180% 180%;
  background-blend-mode: soft-light, multiply;
  pointer-events: none;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-note-surface {
  clip-path: polygon(0 4%, 8% 1%, 18% 3%, 29% 0, 40% 3%, 50% 1%, 61% 3%, 72% 0, 84% 3%, 100% 2%, 98% 20%, 100% 38%, 97% 55%, 100% 74%, 98% 98%, 86% 97%, 74% 100%, 62% 97%, 50% 100%, 38% 97%, 25% 100%, 12% 97%, 1% 100%, 3% 82%, 0 64%, 2% 45%, 0 24%);
  filter: drop-shadow(5px 7px 0 rgb(67 55 43 / .16)) drop-shadow(0 13px 18px rgb(67 55 43 / .1));
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-surface {
  clip-path: polygon(0 3%, 7% 1%, 15% 2%, 24% 0, 34% 2%, 44% 1%, 55% 2%, 65% 0, 76% 2%, 87% 1%, 100% 3%, 99% 22%, 100% 44%, 98% 65%, 100% 82%, 98% 100%, 87% 98%, 77% 100%, 67% 98%, 56% 100%, 45% 98%, 35% 100%, 24% 98%, 14% 100%, 4% 98%, 0 100%, 1% 80%, 0 61%, 2% 41%, 0 20%);
  filter: drop-shadow(4px 7px 0 rgb(48 69 75 / .13)) drop-shadow(0 12px 18px rgb(48 69 75 / .08));
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item:nth-child(1) { --material-note-tint: #f4e8d7; --material-position: 12% 12%; --material-tape-left: 37%; --material-tape-width: 25%; --material-tape-height: 10%; --material-tape-rotation: -1deg; --material-tape-color: rgb(211 181 137 / .76); }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item:nth-child(2) { --material-note-tint: #e7ddd0; --material-position: 82% 18%; --material-tape-left: 64%; --material-tape-width: 21%; --material-tape-height: 12%; --material-tape-rotation: 1deg; --material-tape-color: rgb(165 184 181 / .72); }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item:nth-child(3) { --material-note-tint: #e9d7d0; --material-position: 20% 82%; --material-tape-left: 52%; --material-tape-width: 27%; --material-tape-height: 12%; --material-tape-rotation: -1.4deg; --material-tape-color: rgb(220 193 157 / .74); }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item:nth-child(4) { --material-note-tint: #e0e5d9; --material-position: 75% 76%; --material-tape-left: 64%; --material-tape-width: 21%; --material-tape-height: 12%; --material-tape-rotation: 1deg; --material-tape-color: rgb(165 184 181 / .72); }
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .board-gear-item:nth-child(5) { --material-note-tint: #f1e2ca; --material-position: 50% 50%; --material-tape-left: 37%; --material-tape-width: 25%; --material-tape-height: 10%; --material-tape-rotation: -1deg; --material-tape-color: rgb(211 181 137 / .76); }

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item:nth-child(1) { --material-note-tint: #f7f0e3; --material-position: 50% 12%; --material-tape-left: 16%; --material-tape-width: 24%; --material-tape-height: 12%; --material-tape-rotation: -1deg; --material-tape-color: rgb(198 213 217 / .66); }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item:nth-child(2) { --material-note-tint: #e7eef0; --material-position: 84% 22%; --material-tape-left: 64%; --material-tape-width: 21%; --material-tape-height: 12%; --material-tape-rotation: 1deg; --material-tape-color: rgb(190 205 193 / .72); }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item:nth-child(3) { --material-note-tint: #edf0e7; --material-position: 18% 78%; --material-tape-left: 52%; --material-tape-width: 27%; --material-tape-height: 12%; --material-tape-rotation: -1.4deg; --material-tape-color: rgb(219 196 164 / .66); }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item:nth-child(4) { --material-note-tint: #eef2f3; --material-position: 76% 74%; --material-tape-left: 64%; --material-tape-width: 21%; --material-tape-height: 12%; --material-tape-rotation: 1deg; --material-tape-color: rgb(190 205 193 / .72); }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .board-gear-item:nth-child(5) { --material-note-tint: #f4eee4; --material-position: 50% 52%; --material-tape-left: 16%; --material-tape-width: 24%; --material-tape-height: 12%; --material-tape-rotation: -1deg; --material-tape-color: rgb(198 213 217 / .66); }

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-tile-tape,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-tile-tape {
  display: block;
  position: absolute;
  top: -7%;
  right: auto;
  left: var(--material-tape-left, 16%);
  width: var(--material-tape-width, 24%);
  height: var(--material-tape-height, 12%);
  clip-path: polygon(1% 8%, 98% 0, 100% 91%, 3% 100%);
  z-index: 2;
  border: 1px solid rgb(82 70 56 / .1);
  background-image:
    linear-gradient(90deg, rgb(255 255 255 / .28), transparent 42%, rgb(79 69 58 / .08)),
    var(--material-surface);
  background-position: 0 0, center;
  background-size: 100% 100%, 260% 260%;
  background-blend-mode: soft-light, multiply;
  background-color: var(--material-tape-color, rgb(198 213 217 / .66));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .32);
  transform: rotate(var(--material-tape-rotation, -1deg));
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-note-stamp,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-stamp {
  position: absolute;
  top: 13%;
  right: 8%;
  z-index: 2;
  display: block;
  width: 16%;
  aspect-ratio: 1;
  opacity: .66;
  pointer-events: none;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-note-stamp {
  border: 1px dashed var(--material-ink);
  border-radius: 50%;
  background:
    radial-gradient(circle, transparent 0 38%, color-mix(in srgb, var(--material-ink) 58%, transparent) 40% 43%, transparent 45%),
    repeating-linear-gradient(0deg, transparent 0 4px, color-mix(in srgb, var(--material-ink) 34%, transparent) 5px 6px);
  transform: rotate(9deg);
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-stamp {
  top: 18%;
  right: 10%;
  width: 18%;
  border-top: 1px solid var(--material-ink);
  border-bottom: 1px solid var(--material-ink);
  opacity: .46;
  transform: rotate(-4deg);
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-stamp::before,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-stamp::after {
  position: absolute;
  top: 50%;
  width: 35%;
  height: 1px;
  background: var(--material-ink);
  content: "";
}

.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-stamp::before { left: -42%; }
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-stamp::after { right: -42%; }

/* Material stamps are decorative residue rather than item information. They
   compete with the copy in the solo portrait notes, and their lines become
   especially noisy at mobile/export scale. Tape remains the attachment cue. */
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-note-stamp,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-note-stamp {
  display: none;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-tile-copy,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-tile-copy {
  position: relative;
  z-index: 3;
  color: var(--material-ink) !important;
}

.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-tile-copy span,
.canvas-board[data-background-pattern="collage"] .board-gear-tiles .gear-item-secondary,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-tile-copy span,
.canvas-board[data-background-pattern="scrapbook"] .board-gear-tiles .gear-item-secondary {
  color: var(--material-muted-ink) !important;
}

/* Floating text toolbar values are applied at the final card seam so the
   preview canvas, direct-edit layer, and PNG renderer share the same title
   treatment. Layout-specific title sizing lives in card-composer.css so its
   portrait and lineup rules keep their intended cascade priority. */
.canvas-board .board-editorial-header .board-title-block > strong {
  font-style: var(--card-title-font-style, normal);
  text-decoration-line: var(--card-title-text-decoration, none);
  text-transform: var(--card-title-text-transform, none);
}

.canvas-board .board-editorial-header .caption-description {
  font-family: var(--card-subtitle-font, var(--sans)) !important;
  font-size: clamp(8px, var(--card-subtitle-font-size-scale, 1.5cqw), 36px) !important;
  font-weight: var(--card-subtitle-weight, 400) !important;
  font-style: var(--card-subtitle-font-style, normal);
  text-decoration-line: var(--card-subtitle-text-decoration, none);
  text-transform: var(--card-subtitle-text-transform, none);
  color: var(--card-subtitle-color, var(--recipe-ink, currentColor)) !important;
  opacity: var(--card-subtitle-opacity, .68);
}

/* Item identity must survive the card's responsive width. The old one-line
   rule made a valid item look like a different item once its tail was hidden.
   Keep the complete name in the note and let the renderer choose a smaller
   line box when a narrow rail needs it; tape remains the only decorative
   element competing with the copy. */
.canvas-board .board-gear-tiles .gear-tile-copy {
  overflow: visible;
}

.canvas-board .board-gear-tiles .gear-tile-copy > .gear-slot-label,
.canvas-board .board-gear-tiles .gear-tile-copy > strong,
.canvas-board .board-gear-tiles .gear-tile-copy > .gear-item-secondary,
.canvas-board .multi-info-item > span,
.canvas-board .multi-info-item > small {
  max-width: 100% !important;
  overflow: visible !important;
  overflow-wrap: break-word;
  text-overflow: clip !important;
  white-space: normal !important;
  word-break: keep-all;
}

.canvas-board .board-gear-tiles .gear-tile-copy > strong {
  line-height: 1.14;
}

.canvas-board .multi-info-item > span,
.canvas-board .multi-info-item > small {
  line-height: 1.14;
}

/* Official translations form separate lines under the selected language. */
.canvas-board .gear-name-translation {
  display: block;
  font: inherit;
  color: inherit;
  overflow-wrap: anywhere;
  word-break: normal;
}

.canvas-board .gear-name-translation + .gear-name-translation {
  margin-top: .18em;
}

.canvas-board .multi-info-item > small:has(.gear-name-translation) {
  opacity: .8;
  letter-spacing: 0;
}

/* Protected copy is always an opaque, theme-aware plane. This is the same
   surface painted by CardPng when a person sits above the note material. */
.canvas-board {
  --card-copy-protected-surface: #fffaf4;
  --card-copy-protected-ink: #263238;
  --card-copy-protected-muted: rgb(38 50 56 / .68);
  --card-copy-protected-edge: rgb(38 50 56 / .18);
}

.canvas-board[data-background-tone="dark"] {
  --card-copy-protected-surface: #1d2228;
  --card-copy-protected-ink: #f7f3ed;
  --card-copy-protected-muted: rgb(247 243 237 / .68);
  --card-copy-protected-edge: rgb(247 243 237 / .24);
}

.canvas-board[data-background-pattern="collage"] {
  --card-copy-protected-surface: #f4e8d7;
  --card-copy-protected-ink: #3f3933;
  --card-copy-protected-muted: rgb(63 57 51 / .64);
  --card-copy-protected-edge: rgb(63 57 51 / .2);
}

.canvas-board[data-background-pattern="scrapbook"] {
  --card-copy-protected-surface: #f7f0e3;
  --card-copy-protected-ink: #294650;
  --card-copy-protected-muted: rgb(41 70 80 / .62);
  --card-copy-protected-edge: rgb(41 70 80 / .22);
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy {
  outline: none;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--card-copy-protected-ink);
  align-content: start;
  justify-items: start;
  text-align: left;
}

.canvas-board[data-composition-custom="true"][data-copy-protection="false"] #boardGearList .gear-tile-copy {
  background: transparent;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy > .gear-slot-label {
  color: var(--card-copy-protected-muted);
  font-family: var(--sans);
  font-weight: 600;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy > strong {
  color: var(--card-copy-protected-ink);
  font-family: var(--sans);
  font-weight: 700;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy > .gear-item-secondary {
  color: var(--card-copy-protected-muted);
  font-family: var(--sans);
  font-weight: 500;
}

.canvas-board[data-gear-copy-rendered="true"][data-composition-custom="true"] #boardGearList .gear-tile-copy {
  filter: opacity(0);
}

/* Custom plans use one quiet rounded surface per note. The button itself is
   only the hit target; its note surface owns the sole perimeter. */
.canvas-board[data-composition-custom="true"] #boardGearList .board-gear-item,
.canvas-board[data-composition-custom="true"] #boardGearSurfaceLayer .board-gear-surface-item {
  border: 0 !important;
  border-radius: 0 !important;
  outline: none;
  background: transparent !important;
  box-shadow: none !important;
}

.canvas-board[data-composition-custom="true"] #boardGearList .board-gear-item:focus-visible {
  outline: 2px solid var(--primary) !important;
  outline-offset: 2px;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-note-surface,
.canvas-board[data-composition-custom="true"] #boardGearSurfaceLayer .gear-note-surface {
  display: block !important;
  position: absolute;
  inset: 0;
  z-index: 0;
  box-sizing: border-box;
  border: var(--card-plan-unit-scale, 1px) solid var(--card-copy-protected-edge);
  border-radius: calc(var(--plan-note-radius, 8) * var(--card-plan-unit-scale, 1px)) !important;
  clip-path: none !important;
  filter: none !important;
  background-color: var(--material-note-tint, var(--card-copy-protected-surface));
  background-image: none !important;
  box-shadow: none !important;
  pointer-events: none;
}

.canvas-board[data-composition-custom="true"][data-composition-layer="person-front"] #boardGearList .gear-note-surface {
  display: none !important;
}

.canvas-board[data-composition-custom="true"][data-composition-layer="person-front"] #boardGearSurfaceLayer .gear-note-surface {
  display: block !important;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-tape,
.canvas-board[data-composition-custom="true"] #boardGearList .gear-note-stamp,
.canvas-board[data-composition-custom="true"] #boardGearSurfaceLayer .gear-tile-tape,
.canvas-board[data-composition-custom="true"] #boardGearSurfaceLayer .gear-note-stamp {
  display: none !important;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-note-protection {
  display: none;
  position: absolute;
  left: var(--plan-protection-left, 0%);
  top: var(--plan-protection-top, 0%);
  width: var(--plan-protection-width, 100%);
  height: var(--plan-protection-height, 100%);
  z-index: 1;
  box-sizing: border-box;
  border: 0;
  border-radius: calc(var(--plan-note-radius, 8) * var(--card-plan-unit-scale, 1px));
  background-color: var(--material-note-tint, var(--card-copy-protected-surface));
  pointer-events: none;
}

.canvas-board[data-composition-custom="true"][data-composition-layer="person-front"][data-copy-protection="true"] #boardGearList .gear-note-protection {
  display: block;
}

.canvas-board[data-gear-copy-rendered="true"][data-composition-custom="true"] #boardGearList .gear-note-protection {
  display: none !important;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy {
  position: absolute;
  z-index: 2;
  padding: 0;
  text-align: left;
}

.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy > .gear-slot-label,
.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy > strong,
.canvas-board[data-composition-custom="true"] #boardGearList .gear-tile-copy > .gear-item-secondary {
  text-align: left;
}

/* When the preview card itself is small, fixed title/subtitle minima consume
   the space above the first information row. Scale the header to the card's
   width, keep both copy fields in normal flow, and let long values wrap. */
@container (max-width: 480px) {
  .canvas-board[data-ratio][data-cast] .board-editorial-header {
    padding: .8cqw 3cqw 0 !important;
  }

  .canvas-board[data-ratio][data-cast] .board-editorial-header .board-title-block {
    --card-title-line-slot: clamp(7px, 5.7cqw, 12px);
    --card-subtitle-line-slot: clamp(4px, 3.2cqw, 7px);
    --card-title-gap: clamp(.5px, .6cqw, 1.5px);
    --card-title-glyph-safe: clamp(.25px, .2cqw, .75px);
    grid-template-rows: auto auto;
    row-gap: var(--card-title-gap);
    height: auto;
  }

  .canvas-board[data-ratio][data-cast] .board-editorial-header .board-title-block > strong {
    height: auto;
    padding-inline: var(--card-title-glyph-safe);
    font-size: clamp(6px, 5.2cqw, 11px);
    line-height: 1;
  }

  .canvas-board[data-ratio][data-cast] .board-editorial-header .caption-description {
    display: block !important;
    height: auto !important;
    min-height: 0;
    max-width: 100%;
    margin: 0 !important;
    overflow: visible !important;
    font-size: clamp(3px, 2.7cqw, 6px) !important;
    line-height: 1.1;
    text-overflow: clip;
    white-space: normal !important;
    overflow-wrap: anywhere;
  }

  .canvas-board[data-ratio][data-cast] .board-copyright {
    font-size: clamp(4px, 3.2cqw, 8px);
  }

  /* Solo portrait cards have a taller gap before their first note row, so
     retain a slightly larger title and subtitle there. */
  .canvas-board[data-ratio="portrait"][data-cast="1"] .board-editorial-header {
    padding: 2cqw 5cqw 0 !important;
  }

  .canvas-board[data-ratio="portrait"][data-cast="1"] .board-editorial-header .board-title-block {
    --card-title-line-slot: clamp(10px, 9cqw, 18px);
    --card-subtitle-line-slot: clamp(6px, 5cqw, 10px);
    --card-title-gap: clamp(1px, .8cqw, 2px);
    --card-title-glyph-safe: clamp(.5px, .25cqw, 1px);
  }

  .canvas-board[data-ratio="portrait"][data-cast="1"] .board-editorial-header .board-title-block > strong {
    font-size: clamp(8px, 7cqw, 14px);
  }

  .canvas-board[data-ratio="portrait"][data-cast="1"] .board-editorial-header .caption-description {
    font-size: clamp(4px, 4cqw, 8px) !important;
  }
}
