/* ===================================
   Cyberpunk Builder and Sheet
   @layer builder (20.1): every rule here is loaded after and wins over the
   site layer for normal declarations, and holds no !important. The unlayered
   print block in view.html is the deliberate exception.
   =================================== */

@layer builder {

/* --- Site chrome the components replace ----------------------------------
   The builder layer wins these properties over `site`, but only where it
   states them: these resets remove the site's element styling (heading
   margins, borders and padding, the table shadow, the input hover/focus
   background and glow) for the builder's own document root. Every selector
   still names a .cpr- class, so loading builder.css cannot restyle chrome. */
.cpr-root h1,
.cpr-root h2,
.cpr-root h3,
.cpr-root h4,
.cpr-root h5,
.cpr-root h6 {
  margin: 0;
  padding: 0;
  border: 0;
}

.cpr-root .cpr-table {
  box-shadow: none;
  overflow: visible;
}

.cpr-root input:hover,
.cpr-root select:hover,
.cpr-root textarea:hover {
  border-color: var(--border-strong);
  background-color: var(--bg-primary);
}

.cpr-root input:focus,
.cpr-root select:focus,
.cpr-root textarea:focus {
  border-color: var(--border-strong);
  box-shadow: 0 0 0 2px var(--focus);
  background-color: var(--bg-primary);
}

/* 20.1: the site's .button is untouched; every builder control is .cpr-btn*. */
.cpr-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--sp-5);
  padding: var(--sp-2) var(--sp-4);
  border: 0;
  border-radius: 999px;
  background: var(--btn-primary);
  color: var(--btn-text);
  font-family: var(--font-heading);
  font-size: var(--text-base);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.cpr-btn--secondary {
  border: 1px solid var(--border-strong);
  background: transparent;
  color: var(--text-primary);
}

.cpr-btn--small {
  min-height: var(--sp-5);
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--accent-fill);
  background: transparent;
  color: var(--accent-fill);
  font-size: var(--text-sm);
}

/* The builder's inputs keep the ground colour and take the accent focus ring
   (18.3b): the site's olive glow and the --bg-tertiary switch are chrome, not
   the builder (F.5). */
.cpr-step-block input:focus,
.cpr-step-block select:focus,
.cpr-step-block textarea:focus {
  border-color: var(--border-strong);
  box-shadow: 0 0 0 2px var(--focus);
  background-color: var(--bg-primary);
}

  /* 18.3b: the global 500px minimum must not apply to the builder's tables --
     a phone clips them inside main otherwise. The skills tables were already
     lifted; a wide builder table scrolls inside its own box instead (L5). */
  .cpr-table {
    min-width: 0;
  }

  .cpr-skill-table {
    min-width: 0;
  }

/* ===================================
   Cyberpunk Builder and Sheet
   One spacing scale: --sp-1..--sp-5.
   =================================== */

.cpr-form {
  display: grid;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
  padding: 0;
}

.cpr-fieldset {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-3) var(--sp-4) var(--sp-4);
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
}

/* The choice heading is a row inside its panel, above the caption and the
   fields (19.3): no <legend> straddling the border. */
.cpr-choice-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  background: var(--bg-secondary);
}

.cpr-choice-head .cpr-subhead { margin: 0; padding: 0; }

.cpr-required {
  margin: 0;
  padding: 0 var(--sp-2);
  background: var(--accent-fill);
  color: var(--accent-text);
  border-radius: var(--border-radius);
  font-size: var(--text-xs);
  font-weight: 600;
}

.cpr-caption {
  margin: 0;
  padding: 0;
  font-size: var(--text-base);
  color: var(--text-primary);
}

/* The verbatim rule line under a caption: one step down and muted, so the
   sentence that explains the numbers stays the loudest text (19.3/aa3 O8). */
.cpr-quote {
  margin: 0;
  padding: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.cpr-choice {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-1) 0;
  cursor: pointer;
}

.cpr-choice > input {
  margin: 0;
}

.cpr-choice input[type="number"] {
  width: 4em;
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--text-base);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--border-radius);
  font-family: var(--font-mono);
}

.cpr-choice .rule-source {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.cpr-field {
  display: grid;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  align-items: center;
}

.cpr-field > label,
.cpr-field-label {
  font-weight: 600;
}

.cpr-field select,
.cpr-field input[type="text"],
.cpr-field input[type="number"],
.cpr-field textarea {
  width: 100%;
  padding: var(--sp-1) var(--sp-2);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--border-radius);
  font: inherit;
}

.cpr-field input[type="number"] {
  /* Six digits plus the browser's number spinner (Eurobucks, IP, reserve
     ammo; g21r2/g21r3 Opus M1: 8ch clipped "12345" in Chrome). */
  width: 12ch;
  min-width: 4em;
  font-size: var(--text-base);
  font-family: var(--font-mono);
}

/* The Streetrat row select lists STAT values: numbers in the mono face
   (18.3c/N11). The name is unique to that picker; the lifepath selects keep
   the body face. */
.cpr-field select[name="value"] {
  font-family: var(--font-mono);
}

/* The accent focus ring, in place of the browser's default outline. */
.cpr-field select:focus-visible,
.cpr-field input:focus-visible,
.cpr-field textarea:focus-visible,
.cpr-table input:focus-visible,
.cpr-choice input:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  box-shadow: none;
}

.cpr-help {
  display: block;
  margin: 0;
  padding: 0;
  font-weight: 400;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.cpr-random {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
}

.cpr-lifepath-table {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--border-default);
}

.cpr-lifepath-table h3 {
  margin: 0;
}

/* The STAT way choice (15.2): only the chosen way renders, the other is a link. */
.cpr-stat-ways {
  display: grid;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
  padding: 0;
}

.cpr-stat-way {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
}

.cpr-stat-other {
  margin: 0;
  font-size: var(--text-sm);
}

.cpr-instance {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-2);
}

.cpr-modules {
  margin: 0 0 var(--sp-4);
  padding-left: var(--sp-5);
}

.cpr-value {
  margin: 0;
  padding: 0;
}

.cpr-inline {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
}

.cpr-steps-wrap {
  margin: 0 0 var(--sp-3);
  padding: 0;
  border-left: 0;
  background: none;
  box-shadow: none;
}

.cpr-steps {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cpr-step {
  margin: 0;
  padding: var(--sp-1) var(--sp-2);
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
}

.cpr-step a {
  color: var(--text-muted);
  border-bottom: none;
}

.cpr-step.done a {
  color: var(--text-primary);
}

/* The current step is the accent-filled pill; its label is the ink that sits
   on that fill. */
.cpr-step.current {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
}

.cpr-step.current a,
.cpr-step.current .cpr-done {
  color: var(--accent-text);
  font-weight: 600;
}

.cpr-notice,
.cpr-bookmark,
.cpr-confirm,
.cpr-errors,
.cpr-warnings {
  margin: 0 0 var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
}

.cpr-errors,
.cpr-warnings {
  padding-left: var(--sp-5);
}

/* Warnings are warm (warn), refusals are hot (danger); the message text is a
   <strong>, so it needs the colour named on itself, not only inherited. */
.cpr-errors {
  color: var(--danger);
  border-left: 3px solid var(--danger);
}

.cpr-warnings {
  color: var(--warning);
  border-left: 3px solid var(--warning);
}

.cpr-error strong {
  color: var(--danger);
}

.cpr-warning strong {
  color: var(--warning);
}

.cpr-warnings-head {
  color: var(--warning);
}

.cpr-error-summary {
  margin: 0;
  padding: 0;
  color: var(--danger);
}

.cpr-notice-summary {
  margin: 0;
  padding: 0;
  color: var(--danger);
}

.cpr-continue-wrap {
  margin: 0;
  padding: 0;
}

.cpr-continue {
  display: inline-block;
  margin: var(--sp-3) 0;
  padding: var(--sp-2) var(--sp-3);
}

/* The Save row closes a step: a ruled row with the button and its refusal
   summary side by side. */
.cpr-save-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-2) 0 0;
  border-top: 1px solid var(--border-default);
}

.cpr-state p {
  font-size: var(--text-base);
  color: var(--text-primary);
  margin: 0;
}

.cpr-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

.cpr-toolbar,
.cpr-sheet-head,
.cpr-section {
  margin: 0 0 var(--sp-3);
  padding: var(--sp-2) 0;
}

.cpr-table {
  width: 100%;
  margin: 0 0 var(--sp-3);
  padding: 0;
  /* The site's ``table`` rule hides overflow; a builder table with nowrap
     cells must never clip (aa3 DeepSeek B). */
  overflow: visible;
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
  border-collapse: separate;
  border-spacing: 0;
}

/* A wide builder table scrolls inside its box instead of clipping inside
   main on a phone (L5). The wrapper is a block so the table keeps its own
   rounded panel. */
.cpr-table-scroll {
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Artboard A: header rows are unfilled muted labels at the xs step, and the
   row text is the sheet's ink rather than the site's muted body copy. */
.cpr-table th {
  padding: var(--sp-1) var(--sp-2);
  border-bottom: 1px solid var(--border-default);
  text-align: left;
  background: none;
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 600;
}

.cpr-table td {
  padding: var(--sp-1) var(--sp-2);
  border-bottom: 1px solid var(--border-default);
  text-align: left;
  color: var(--text-primary);
}

.cpr-table tr:last-child td {
  border-bottom: none;
}

/* A number typed into a table row (a STAT, a Role choice) is a number too; the
   4em box and the scale padding match the skills inputs (M6). */
.cpr-table input[type="number"] {
  width: 4em;
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--text-base);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--border-radius);
  font-family: var(--font-mono);
}

/* The live bounds flag sits as a block under its input inside the same cell
   (never beside it, where it ran over the Cost and Page cells), and a flagged
   input takes the warn border while typing -- :has() on the live flag, no
   script (18.3c/N2/N9). The wrapper is a div inside the cell, so the table
   keeps its table-cell layout. */
.cpr-num-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1);
}

.cpr-num-cell input[type="number"] {
  flex: 0 0 auto;
}

.cpr-num-cell:has(.cpr-live-flag:not(:empty)) input {
  border-color: var(--warning);
}

.cpr-handle {
  margin: 0;
  padding: 0;
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  color: var(--display-color);
  font-size: calc(var(--text-4xl) * var(--heading-size-multiplier, 1));
  letter-spacing: 0;
  text-transform: none;
}

/* 20.3: the page title is the second and last display-face rule. */
.cpr-title {
  margin: 0;
  padding: 0;
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  color: var(--text-heading);
  font-size: calc(var(--text-3xl) * var(--heading-size-multiplier, 1));
  letter-spacing: 0;
  text-transform: none;
}

.cpr-step-block,
.cpr-sheet { font-size: var(--text-base); }

.cpr-section-head {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: calc(var(--text-xs) * var(--heading-size-multiplier, 1));
  color: var(--accent-fill);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  border: none;
}
.cpr-section-head::after {
  content: "";
  flex: 1 1 auto;
  border-top: 1px solid var(--border-default);
}
.cpr-subhead {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: calc(var(--text-base) * var(--heading-size-multiplier, 1));
  color: var(--text-heading);
  text-transform: none;
  letter-spacing: 0;
  margin: 0;
  padding: 0;
}

/* Every numeric cell carries the mono face; the class is the hook for a plain
   <td> or <span> the box classes do not cover (M7). */
.cpr-num {
  font-family: var(--font-mono);
  white-space: nowrap;
}

/* The page reference is the page number in the muted small step; the book
   name is printed by the template only when it is not the core book (N1). A
   page reference never wraps: "p.82" is one token. */
.cpr-page {
  white-space: nowrap;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* The page cell must win its colour over ``.cpr-table td`` (aa3 DeepSeek A).
   It carries the same specificity (0,1,1) and sits after that rule, so source
   order decides; the element-matching test resolves the cascade by element and
   catches a later ``td.cpr-page`` or ``.cpr-table td`` override written either
   way (18.3d / aa3 Opus O4). */
td.cpr-page {
  color: var(--text-muted);
}

/* A <summary> takes the accent focus ring, not the UA default (L6). */
.cpr-step-block summary:focus-visible,
.cpr-sheet summary:focus-visible {
  outline: 2px solid var(--focus);
}

.cpr-sheet-sub {
  margin: var(--sp-1) 0 0;
  padding: 0;
}

.cpr-stat-strip,
.cpr-derived-strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.cpr-stat-box {
  display: grid;
  justify-items: center;
  min-width: 3.5em;
  margin: 0;
  padding: var(--sp-1) var(--sp-2);
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
}

.cpr-stat-label {
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.cpr-fashion-spent {
  margin: 0;
  padding: 0;
  font-size: var(--text-xs);
  font-family: var(--font-mono);
  color: var(--text-muted);
}

.cpr-stat-value {
  font-weight: 600;
  font-family: var(--font-mono);
}

.cpr-source,
.cpr-stat-footnote {
  flex-basis: 100%;
  margin: 0;
  padding: 0;
}

.cpr-skills-cols {
  columns: 1;
  column-gap: var(--sp-4);
}

.cpr-skill-category {
  break-inside: avoid;
  margin: 0 0 var(--sp-2);
  padding: 0;
}

.cpr-skill-category h3 {
  margin: 0;
}

.cpr-skill-row {
  display: flex;
  align-items: baseline;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
}

.cpr-skill-name {
  flex: 1;
}

.cpr-level-box {
  min-width: 2em;
  margin: 0;
  padding: 0 var(--sp-1);
  text-align: center;
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
  font-family: var(--font-mono);
}

.cpr-cyber-group {
  margin: 0 0 var(--sp-2);
  padding: 0;
}

.cpr-cyber-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  margin: 0;
  padding: 0 0 0 var(--sp-3);
}

.cpr-gear-list {
  columns: 2;
  column-gap: var(--sp-4);
  margin: 0;
  padding: 0;
}

.cpr-gear-row {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-2);
  break-inside: avoid;
  margin: 0;
  padding: 0;
}

.cpr-lifepath-list {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--sp-1) var(--sp-3);
  margin: 0;
  padding: 0;
}

.cpr-lifepath-list dt {
  font-weight: 600;
}

.cpr-lifepath-list dd {
  margin: 0;
  padding: 0;
}

.cpr-notes {
  border-top: 1px solid var(--border-default);
}

.cpr-skills {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
}

.cpr-skills table {
  table-layout: fixed;
  width: 100%;
}

/* Artboard A's fixed column geometry (N1): the name column takes the rest. */
.cpr-col-name {
  width: auto;
}

.cpr-col-level {
  width: 88px;
}

.cpr-col-cost {
  width: 64px;
}

.cpr-col-page {
  width: 72px;
}

/* The name column takes the rest and must break a long slash-joined name:
   without a break opportunity "Electronics/Security Tech (x2)" paints under
   the level input at 390 px on the terminal themes (aa3 Opus O2). */
.cpr-skill-table td:first-child {
  overflow-wrap: anywhere;
}

.cpr-skill-table td:nth-child(2) {
  padding: var(--sp-2) var(--sp-1);
}

/* The level input keeps the base 4em / --sp-1 --sp-2 rule: this rule must
   never re-declare width or padding, or an equal-specificity later rule wins
   the cascade and the box shrinks to 56 px (N2). */
.cpr-skill-table input[type="number"] {
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--border-radius);
  /* An explicit size, never ``font: inherit``: inheriting let a cell's
     font-size shrink the box back to 56 px (aa5 Opus M1). */
  font-size: var(--text-base);
  font-family: var(--font-mono);
}

/* A flagged bounds input takes the warn border. The selectors carry the same
   specificity as the base input rules and sit after them, so the border
   shorthand cannot win (L6). */
.cpr-table input.cpr-over,
.cpr-skill-table input.cpr-over,
.cpr-num-cell input.cpr-over,
.cpr-field input.cpr-over,
.cpr-choice input.cpr-over {
  border-color: var(--warning);
}

.cpr-skill-table input[type="text"] {
  width: 100%;
  padding: var(--sp-1) var(--sp-2);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  border-radius: var(--border-radius);
  font: inherit;
}

.cpr-skill-table .cpr-live-cost {
  display: inline-block;
  min-width: 2em;
  font-family: var(--font-mono);
}

.cpr-tag {
  margin: 0 0 0 var(--sp-1);
  padding: 0 var(--sp-1);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
}

.cpr-lead {
  margin: 0 0 var(--sp-3);
  padding: 0;
}

.cpr-money-bar {
  margin: 0 0 var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
  font-family: var(--font-body);
}

.cpr-money-bar p {
  margin: 0;
  padding: 0;
}

/* Eurobucks and the gear page's Humanity total are numbers too. */
.cpr-money-bar strong,
.cpr-humanity strong {
  font-family: var(--font-mono);
}

.cpr-kit,
.cpr-cart,
.cpr-shop {
  margin: 0 0 var(--sp-3);
  padding: 0;
}

.cpr-item-list,
.cpr-item-options {
  margin: 0;
  padding: 0;
  list-style: none;
}

.cpr-item-options {
  padding-left: var(--sp-4);
  flex-basis: 100%;
}

.cpr-kit-row,
.cpr-cart-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-1) 0;
}

.cpr-item-slots,
.cpr-item-qty,
.cpr-item-paid,
.cpr-shop-stat,
.cpr-shop-cost,
.cpr-shop-count {
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
}

.cpr-gear-qty {
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
}

.cpr-shop-section,
.cpr-shop-category,
.cpr-over-budget,
.cpr-needs {
  margin: 0 0 var(--sp-2);
  padding: 0;
}

.cpr-shop-section > summary,
.cpr-shop-category > summary {
  font-weight: 600;
}

.cpr-over-budget > summary,
.cpr-needs > summary {
  color: var(--text-muted);
}

.cpr-shop-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-2);
  margin: 0;
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-3);
}

.cpr-shop-row .cpr-shop-row {
  padding-left: var(--sp-4);
}

/* Nested rows, Needs/Over-budget groups and option lists are blocks under
   their foundation row, never flex siblings beside it. */
.cpr-shop-children {
  flex-basis: 100%;
}

/* y4: a nested list with no rows is kept in the DOM (its body is swapped on
   every action) and hidden until one lands in it; nothing removes the element.
   The Needs groups and the rows' own Over lists are hoisted out of the swapped
   bodies and sit one step in from their section's or category's own list.
   y6: a Needs group whose foundation needs a missing foundation carries one
   plain note instead of its rows, so the note keeps the group visible. */
details.cpr-over-budget:not(:has(.cpr-shop-row)),
details.cpr-needs:not(:has(.cpr-shop-row)):not(:has(.cpr-shop-hint)) {
  display: none;
}

.cpr-shop-section > .cpr-row-group,
.cpr-shop-category > .cpr-row-group {
  padding-left: var(--sp-4);
}

/* Label above the control on narrow screens, beside it from 40em. */
@media (min-width: 40em) {
  .cpr-field {
    grid-template-columns: 12em minmax(0, 1fr);
    gap: var(--sp-1) var(--sp-2);
  }

  .cpr-field > label,
  .cpr-field-label {
    text-align: right;
  }

  /* The help sentence sits between its label and its control (15.3): in the
     control column from 40em, with the control on the row under it. */
  .cpr-field > .cpr-help,
  .cpr-field > .cpr-caption {
    grid-column: 2;
  }

  .cpr-field > .cpr-caption ~ input,
  .cpr-field > .cpr-caption ~ select,
  .cpr-field > .cpr-caption ~ textarea,
  .cpr-field > .cpr-help ~ input,
  .cpr-field > .cpr-help ~ select,
  .cpr-field > .cpr-help ~ textarea {
    grid-column: 2;
  }

  .cpr-random {
    grid-column: 2;
  }

  /* A saved answer's Change link sits under its value, not under the label. */
  .cpr-field > .cpr-change {
    grid-column: 2;
  }


}

/* The skills categories flow in two columns from 60em, but only when the form
   column itself has room for two tables (the book-first panel takes a third of
   the width beside it): each category needs about 26rem, so a narrow form keeps
   one column instead of breaking names mid-word. */
@media (min-width: 60em) {
  .cpr-skills {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
  }


}

/* 17.2: live totals. The flag sits beside its control; the pool counter and
   the category subtotals carry the stable ids the live fragment swaps. */
.cpr-live-total {
  margin: 0 0 var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
  font-family: var(--font-body);
}

/* The live flag is a block under its control: in a .cpr-num-cell it takes a
   full flex row under the input, so it can never run into the neighbouring
   Cost/Page cells (N2). Elsewhere (the pool counter) it reads as its own
   line. */
.cpr-live-flag {
  display: block;
  flex-basis: 100%;
  margin: 0;
  padding: 0 var(--sp-1);
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  color: var(--warning);
  white-space: nowrap;
}

.cpr-cat-subtotal {
  margin: 0 0 0 var(--sp-2);
  padding: 0;
  font-size: var(--text-sm);
  font-family: var(--font-mono);
  font-weight: 400;
  color: var(--text-muted);
}

/* The Role list spans the form; its preview sits below it (2026-10-10). */
.cpr-role-layout {
  display: grid;
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
}

.cpr-role-preview {
  margin: 0;
  padding: var(--sp-3);
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: var(--border-radius);
}

.cpr-role-preview h3,
.cpr-role-preview h4 {
  margin: 0 0 var(--sp-2);
}

.cpr-role-preview p {
  margin: 0 0 var(--sp-2);
}

.cpr-role-skills {
  display: grid;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cpr-role-skills li {
  display: flex;
  align-items: baseline;
  gap: var(--sp-2);
}

.cpr-role-skills .cpr-skill-name {
  flex: 1;
}

.cpr-role-skills .cpr-skill-level {
  min-width: 2em;
  text-align: center;
  font-family: var(--font-mono);
}

/* 17.3: the regions the lifepath reveals swap whole. */
.cpr-lifepath-tables,
.cpr-lifepath-instances {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
}

.cpr-role-layout > .cpr-fieldset {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
  column-gap: var(--sp-4);
  align-items: baseline;
}
.cpr-role-layout > .cpr-fieldset > :not(label) { grid-column: 1 / -1; }

.cpr-preview-empty {
  margin: 0;
  padding: 0;
  color: var(--text-muted);
}

/* Builder documents use the canvas frame on ground, outside the site card. */
.cpr-document {
  max-width: none;
  padding: var(--sp-4);
}
.cpr-main {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0;
  background-color: var(--bg-primary);
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

/* Component vocabulary: the canvas structure, semantic tokens and scale. */
.cpr-root {
  min-width: 0;
  font-family: var(--font-body);
  color: var(--text-primary);
  display: grid;
  gap: var(--sp-4);
}
.cpr-root *, .cpr-root *::before, .cpr-root *::after { box-sizing: border-box; }
.cpr-panel {
  min-width: 0;
  background: var(--bg-secondary);
  border: 1px solid var(--border-default);
  border-radius: 6px;
  padding: var(--sp-4) var(--sp-5);
  box-shadow: none;
}
.cpr-sheet { display: grid; gap: var(--sp-4); min-width: 0; }
.cpr-sheet-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--border-default);
  box-shadow: none;
}
.cpr-sheet-head .cpr-handle { flex-basis: 100%; line-height: 1.05; }
.cpr-sheet-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* One shrinkable track: an auto track grew to the weapons table's min-width, so its
   .cpr-table-scroll never scrolled and the sheet ran off a phone (2026-10-19). */
.cpr-sheet-columns, .cpr-sheet-equipment {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-4);
  min-width: 0;
}
.cpr-sheet .cpr-section { margin: 0; }
.cpr-section.cpr-panel { padding: var(--sp-4) var(--sp-5); }
.cpr-section-head { margin-bottom: var(--sp-2); }
.cpr-root h2.cpr-section-head { margin: 0; }
.cpr-stat-strip, .cpr-derived-strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-2);
  margin-top: var(--sp-2);
}
.cpr-derived-strip { grid-template-columns: minmax(0, 1fr); }
.cpr-derived-strip .cpr-stat-box { justify-items: start; }
.cpr-derived-strip .cpr-stat-label { text-transform: none; }
@media (min-width: 40em) {
  .cpr-stat-strip { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .cpr-derived-strip { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.cpr-stat-box { background: var(--bg-primary); padding: var(--sp-2); }
.cpr-stat-value { font-size: var(--text-xl); font-weight: 500; }
.cpr-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-1) var(--sp-2);
  border-top: 1px solid var(--border-default);
  padding: var(--sp-2) 0;
  min-width: 0;
}
.cpr-item-name { font-family: var(--font-body); font-weight: 600; color: var(--text-heading); }
.cpr-meta { font-size: var(--text-sm); color: var(--text-muted); }
.cpr-item--child {
  margin-left: var(--sp-5);
  padding-left: var(--sp-3);
  border-top: none;
  border-left: 1px solid var(--border-strong);
}
.cpr-pill {
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 0 var(--sp-2);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--text-xs);
  color: var(--text-primary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
}
.cpr-num { font-weight: 500; }
/* One line per skill at every width (g20r2 Opus N1): the row never wraps,
   the name takes the room left and breaks at its slashes, and every number
   keeps its own width. */
.cpr-skill-row { flex-wrap: nowrap; }
/* The name cell holds the name and its pills; the pills wrap under the name
   (as on the canvas) instead of squeezing it, so the name breaks only at its
   slashes and spaces (g20r3 Opus N2). */
.cpr-skill-name { overflow-wrap: anywhere; }
.cpr-skill-row > .cpr-skill-name {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-1) var(--sp-2);
}
.cpr-skill-row > .cpr-num { flex: none; }
.cpr-handle { overflow-wrap: anywhere; }
.cpr-weapons .cpr-table { min-width: 24em; }
.cpr-weapons .cpr-table th { white-space: nowrap; }
.cpr-skill-base { color: var(--text-heading); font-size: var(--text-lg); }
.cpr-skills-cols { columns: 17rem; }
.cpr-skills-cols > .cpr-section-head { column-span: all; }
.cpr-gear-list { columns: auto; }
.cpr-gear-row { justify-content: flex-start; }
.cpr-gear .cpr-gear-name { font-weight: 400; }
.cpr-gear .cpr-gear-qty, .cpr-armor .cpr-pill { margin-left: auto; }
.cpr-skill-level { font-family: var(--font-mono); min-width: 2em; text-align: right; border: 0; background: none; }
.cpr-source, .cpr-stat-footnote, .cpr-stat-strip > .cpr-section-head, .cpr-derived-strip > .cpr-section-head { grid-column: 1 / -1; }
.cpr-refusal {
  border: 1px solid var(--danger);
  border-radius: 6px;
  background: var(--bg-primary);
  padding: var(--sp-3);
  margin-bottom: var(--sp-2);
}
.cpr-refusal ul { margin: 0; padding-left: var(--sp-4); }
.cpr-errors { border-left: none; padding: 0; }
.cpr-flag { display: block; color: var(--warning); font-size: var(--text-sm); font-weight: 600; }
.cpr-live-total .cpr-flag { white-space: normal; }
.cpr-money-summary { display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-4); }
.cpr-money-summary > span { display: flex; align-items: baseline; gap: var(--sp-2); }
.cpr-money-summary .cpr-num { font-size: var(--text-xl); color: var(--text-heading); }
.cpr-money-summary > .cpr-primary-figure .cpr-num { font-size: var(--text-2xl); }
.cpr-live-total .cpr-money-summary > .cpr-primary-figure .cpr-num { color: var(--accent-fill); }
.cpr-label {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.cpr-cart-row .cpr-item-paid { margin-left: auto; color: var(--text-heading); }
.cpr-cart-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.cpr-cart-footer .cpr-cart-total { margin: 0; }
.cpr-cart-footer .cpr-btn { width: auto; }
.cpr-step { border-radius: 999px; padding: var(--sp-2) var(--sp-3); }
.cpr-kit.cpr-panel, .cpr-cart.cpr-panel { padding: var(--sp-4) var(--sp-5); }
.cpr-panel .cpr-table { margin: var(--sp-2) 0 0; border: 0; border-radius: 0; }
.cpr-panel .cpr-table th { border-bottom: 1px solid var(--border-strong); }
.cpr-shop-section { padding: var(--sp-3); border: 1px solid var(--border-default); border-radius: 6px; }
.cpr-shop-row.cpr-item { padding: var(--sp-2) 0; }
.cpr-root .cpr-role-preview { padding: var(--sp-4); border-radius: 6px; }
@media (min-width: 60em) {
  /* Balanced columns, not a grid: cards fill both columns instead of leaving an empty
     row cell beside a long one (one card taller than the rest still sets the height). */
  .cpr-sheet-columns { display: block; columns: 2; column-gap: var(--sp-4); }
  .cpr-sheet-equipment { display: contents; }
  .cpr-sheet-columns > .cpr-section,
  .cpr-sheet-equipment > .cpr-section { break-inside: avoid; margin: 0 0 var(--sp-4); }
}
@media (max-width: 40em) {
  .cpr-panel, .cpr-section.cpr-panel, .cpr-kit.cpr-panel, .cpr-cart.cpr-panel { padding: var(--sp-3); }
  .cpr-lifepath-list { grid-template-columns: minmax(0, 1fr); }
}
/* Canvas header chips and the Gear's Kit/Cart beside Shop. */
.cpr-sheet-head { align-items: flex-end; justify-content: space-between; }
.cpr-sheet-identity { min-width: 0; display: grid; gap: var(--sp-1); }
.cpr-sheet-sub { color: var(--text-muted); font-style: normal; }
.cpr-chip {
  display: inline-flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-2) var(--sp-3);
  background: var(--bg-tertiary);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
}
.cpr-chip .cpr-num { color: var(--text-heading); font-size: var(--text-lg); }
.cpr-chip-label {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}
.cpr-gear-layout, .cpr-gear-layout #gear-kit-cart-body {
  display: grid;
  min-width: 0;
  gap: var(--sp-4);
  align-items: start;
}
.cpr-gear-layout .cpr-kit, .cpr-gear-layout .cpr-cart, .cpr-gear-layout .cpr-shop { margin: 0; }
.cpr-gear-layout .cpr-shop { padding: var(--sp-4) var(--sp-5); }
.cpr-gear-layout .cpr-shop-section { background: var(--bg-primary); margin-top: var(--sp-2); }
.cpr-field .cpr-caption { font-size: var(--text-base); color: var(--text-primary); }
.cpr-title { line-height: 1.1; }
.cpr-skills-cols .cpr-skill-category { margin-top: var(--sp-3); }
.cpr-skill-row .cpr-meta { width: 4em; text-align: right; }
.cpr-skill-base { min-width: 2em; text-align: right; }
@media (min-width: 60em) {
  .cpr-gear-layout { grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr)); }
}
@media (max-width: 40em) {
  .cpr-gear-layout .cpr-shop { padding: var(--sp-3); }
}

/* Admin sheet rows stack so Review stays reachable on a phone. */
@media (max-width: 40em) {
  .cpr-admin-table, .cpr-admin-table tbody, .cpr-admin-table tr, .cpr-admin-table td {
    display: block;
    width: 100%;
    min-width: 0;
  }
  .cpr-admin-table thead { display: none; }
  .cpr-admin-table td[data-label]::before { content: attr(data-label) ": "; }
  .cpr-admin-table tr { margin-bottom: var(--sp-4); }
  .cpr-admin-table td { border: 0; padding: var(--sp-2) 0; }
}

.cpr-admin-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: center;
}
.cpr-admin-actions .cpr-inline { align-items: center; }


/* Book-first decisions: reading leads in document order and on small screens. */
.cpr-root .cpr-decision-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-4);
  align-items: start;
}
.cpr-root .cpr-decision-form { min-width: 0; }
.cpr-root .cpr-book-first { border-top: 2px solid var(--link-default); }
.cpr-root .cpr-book-icon {
  width: 1.25em;
  height: 1.25em;
  vertical-align: middle;
  color: var(--link-default);
}
.cpr-root .cpr-reading-list { list-style: none; padding: 0; }
.cpr-root .cpr-reading-list li { margin-block: var(--sp-3); }
.cpr-root .cpr-reading-list p { margin-block: var(--sp-1); }
.cpr-root .cpr-reading-ref {
  font-family: var(--font-mono);
  color: var(--link-default);
}
.cpr-root .cpr-in-short {
  border: 1px dashed var(--border-strong);
  padding: var(--sp-3);
  margin-block: var(--sp-3);
}
.cpr-root .cpr-ask {
  background: var(--bg-tertiary);
  border: 1px solid var(--border-default);
  padding: var(--sp-3);
}
.cpr-root .cpr-book-cost {
  font-family: var(--font-mono);
  border: 1px solid var(--border-strong);
  background: var(--bg-secondary);
  padding: var(--sp-3);
  margin-bottom: var(--sp-3);
}
@media (min-width: 48rem) {
  .cpr-root .cpr-decision-layout { grid-template-columns: minmax(0, 2fr) minmax(15rem, 1fr); }
  .cpr-root .cpr-book-first { grid-column: 2; grid-row: 1; }
  .cpr-root .cpr-decision-form { grid-column: 1; grid-row: 1; }
}


/* Navigation stays available above the swapped step area. */
.cpr-steps-wrap { min-width: 0; position: sticky; top: 0; z-index: 10; background: var(--bg-primary); }
.cpr-step small { display: block; }
.cpr-root #cpr-step-area { scroll-margin-top: 6rem; }
#cpr-root.cpr-root.htmx-request .cpr-steps,
#cpr-root.cpr-root.htmx-request #cpr-step-area button,
#cpr-root.cpr-root.htmx-request .cpr-refusal a {
    pointer-events: none;
    opacity: 0.5;
}
.cpr-root #cpr-step-area :disabled { opacity: 0.5; }
@media (max-width: 600px) {
    .cpr-main { overflow: visible; }
    .cpr-steps { flex-wrap: nowrap; overflow-x: auto; }
    .cpr-step { flex: 0 0 auto; white-space: nowrap; }
}

}
