/* ==========================================================================
   GB Custom Leather Craft — Commission Configurator
   Scoped under .cmsn to avoid collisions with base.css
   ========================================================================== */

.cmsn { --cmsn-gap: 1.25rem; --cmsn-radius: 3px; --cmsn-line: rgba(0,0,0,0.14); }
.cmsn *, .cmsn *::before, .cmsn *::after { box-sizing: border-box; }

/* ------------------------------------------------------------ Availability */
.cmsn-availability {
  background: var(--color-leather-dark);
  color: #fff;
  text-align: center;
  padding: 0.85rem 1.25rem;
}
.cmsn-availability__label {
  display: block;
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.75;
  margin-bottom: 0.2em;
}
.cmsn-availability__msg { font-size: 1rem; margin: 0; }

/* ----------------------------------------------------------------- Layout */
.cmsn-head { text-align: center; padding: 3rem 0 1.5rem; }
.cmsn-head__title { font-size: clamp(1.8rem, 5vw, 2.75rem); margin-bottom: 0.35em; }
.cmsn-head__sub { max-width: 46ch; margin: 0 auto; opacity: 0.85; }

.cmsn-layout { display: grid; grid-template-columns: 1fr; gap: 2rem; padding-bottom: 6rem; }
@media (min-width: 1024px) {
  .cmsn-layout { grid-template-columns: minmax(0,1.55fr) minmax(320px,1fr); gap: 3rem; align-items: start; }
}

/* --------------------------------------------------------------- Progress */
.cmsn-progress { margin: 0 0 2rem; }
.cmsn-progress__list { display: none; }
@media (min-width: 768px) {
  .cmsn-progress__list {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 0.5rem;
    list-style: none; margin: 0; padding: 0;
  }
}
.cmsn-progress__btn {
  width: 100%;
  background: none;
  border: none;
  border-top: 3px solid var(--cmsn-line);
  padding: 0.7rem 0.25rem 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  opacity: 0.5;
  transition: opacity 0.15s ease, border-color 0.15s ease;
}
.cmsn-progress__btn:disabled { cursor: not-allowed; }
.cmsn-progress__btn[aria-current="step"] { opacity: 1; border-top-color: var(--color-leather); }
.cmsn-progress__btn[data-complete="true"] { opacity: 0.9; border-top-color: var(--color-brass); }
.cmsn-progress__num { display: block; font-size: 0.7rem; letter-spacing: 0.1em; opacity: 0.7; }
.cmsn-progress__name { display: block; font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }

.cmsn-progress__mobile { display: block; }
@media (min-width: 768px) { .cmsn-progress__mobile { display: none; } }
.cmsn-progress__bar { height: 4px; background: var(--cmsn-line); border-radius: 2px; overflow: hidden; }
.cmsn-progress__fill { display: block; height: 100%; background: var(--color-leather); transition: width 0.25s ease; }
.cmsn-progress__meta { display: flex; justify-content: space-between; font-size: 0.8rem; margin-top: 0.5rem; }
.cmsn-progress__meta strong { text-transform: uppercase; letter-spacing: 0.05em; }

/* ------------------------------------------------------------------ Steps */
.cmsn-step[hidden] { display: none; }
.cmsn-step__title { font-size: clamp(1.35rem, 3.5vw, 1.9rem); margin-bottom: 0.4em; }
.cmsn-step__intro { opacity: 0.85; margin-bottom: 2rem; max-width: 60ch; }

.cmsn-field { margin-bottom: 1.75rem; }

/* ON A PHONE, THE FORM SHOULD BE ON THE SCREEN.
   Measured at 375x812 before this rule: 645 of the 812 available pixels went
   to chrome before the first control — site header 103, availability banner
   73, title block 166 (48px of it padding-top alone), progress bar plus 32px
   of margin, and 64px more from the generic `section { padding: 4rem 0 }` in
   base.css that .cmsn-step inherits because it is a <section>. The customer
   arrived at the order form and could see 167px of it.

   Nothing is removed and nothing moves: the title, the subhead, the
   availability notice and the progress bar all stay exactly where they were.
   The space between them is tightened, on phones only. Desktop is untouched,
   where the budget is not scarce. */
@media (max-width: 560px) {
  .cmsn-head { padding: 1.5rem 0 1rem; }
  .cmsn-head__title { font-size: 1.65rem; }
  .cmsn-progress { margin-bottom: 1rem; }
  .cmsn-step { padding-top: 1.5rem; }
  .cmsn-step__intro { margin-bottom: 1.25rem; }
}


.cmsn-field__label { display: block; font-weight: 600; margin-bottom: 0.35em; }
.cmsn-field__hint { display: block; font-size: 0.85rem; opacity: 0.7; margin-bottom: 0.6em; }
/* A hint the markup hides has to stay hidden: `display: block` on the class
   outranks `[hidden]` from the browser. The generate-concept message is one
   of these, and with that button switched on it showed as an empty paragraph
   with a margin. */
.cmsn-field__hint[hidden] { display: none; }
.cmsn-req { color: var(--color-leather); }

.cmsn-input, .cmsn-textarea, .cmsn-select {
  width: 100%;
  padding: 0.75em 0.85em;
  border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
  font: inherit;
  color: inherit;
  min-height: 48px;
}
.cmsn-textarea { min-height: 130px; resize: vertical; line-height: 1.55; }
.cmsn-input:focus-visible, .cmsn-textarea:focus-visible, .cmsn-select:focus-visible {
  outline: 3px solid var(--color-brass); outline-offset: 1px;
}
.cmsn-input[aria-invalid="true"], .cmsn-textarea[aria-invalid="true"] { border-color: #B3261E; }

.cmsn-error { display: none; color: #B3261E; font-size: 0.85rem; margin-top: 0.4em; font-weight: 600; }
.cmsn-error[data-visible="true"] { display: block; }
/* Sits under the Continue button, so a step that will not advance says so
   where the customer just clicked as well as at the field that needs fixing. */
.cmsn-error--nav { margin-top: .6rem; }

.cmsn-counter { font-size: 0.78rem; opacity: 0.6; text-align: right; margin-top: 0.25em; }

/* ------------------------------------------------------------- Option grid */
.cmsn-options { display: grid; grid-template-columns: 1fr; gap: 0.65rem; }
@media (min-width: 560px) { .cmsn-options--2 { grid-template-columns: repeat(2,1fr); } }
@media (min-width: 560px) { .cmsn-options--3 { grid-template-columns: repeat(3,1fr); } }

.cmsn-opt { position: relative; display: block; }
/* HIDDEN HAS TO WIN. `display: block` above is a class selector, so it
   out-specifies the user agent's `[hidden] { display: none }` and an option
   marked hidden went on being drawn — a belt-only customer was shown the two
   COLLAR lettering tiles, checkboxes and all. Every other component in this
   sheet already carries its own [hidden] guard for exactly this reason;
   .cmsn-opt was the one that was missed. */
.cmsn-opt[hidden] { display: none; }
.cmsn-opt input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.cmsn-opt__box {
  display: flex; align-items: center; gap: 0.75rem;
  min-height: 56px;
  padding: 0.85rem 1rem;
  border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.cmsn-opt input:checked + .cmsn-opt__box {
  border-color: var(--color-leather);
  box-shadow: inset 0 0 0 1px var(--color-leather);
}
.cmsn-opt input:focus-visible + .cmsn-opt__box { outline: 3px solid var(--color-brass); outline-offset: 2px; }
.cmsn-opt__text { flex: 1; }
.cmsn-opt__name { display: block; font-weight: 600; }
.cmsn-opt__note { display: block; font-size: 0.8rem; opacity: 0.7; }

.cmsn-swatch { width: 30px; height: 30px; border-radius: 50%; border: 1px solid rgba(0,0,0,0.25); flex: none; }

/* Selected-state must not rely on color alone (a11y) */
.cmsn-opt input:checked + .cmsn-opt__box::after {
  content: "✓";
  font-weight: 700;
  color: var(--color-leather);
  margin-left: auto;
}

/* ---------------------------------------------------- STORY TILES, LARGER
   The lettering and font tiles in 02 Story carry more reading than the
   compact option rows elsewhere — two of them hold a live font sample — and
   at the shared 56px box they were cramped. Scaled to roughly 1.5x their
   rendered height (80px -> ~120px) by growing the BOX, not the grid: the
   column count and the tile WIDTH are untouched, so nothing can overflow a
   narrow viewport. Scoped to the Story step so the fit, design and materials
   tiles keep the density they were designed at. */
[data-step="story"] .cmsn-opt__box {
  /* 120px, not 84px. The shared box is 56px MIN but renders at 80px because
     its content is taller than the minimum — so scaling the minimum by 1.5
     moved nothing until the content grew past it. The rendered height is the
     number that matters, and 80px x 1.5 is 120px, so that is the floor set
     here. Padding and type are scaled with it so the tile grows as a whole
     rather than becoming a tall box around small text. */
  min-height: 120px;
  padding: 1.275rem 1.5rem;
  gap: 1.125rem;
}
[data-step="story"] .cmsn-opt__name { font-size: 1.125rem; }
[data-step="story"] .cmsn-opt__note { font-size: 0.9rem; }
[data-step="story"] .cmsn-swatch { width: 40px; height: 40px; }

/* ------------------------------------------------------------------ Info  */
.cmsn-info-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; min-width: 24px;
  border-radius: 50%;
  border: 1px solid var(--color-leather);
  background: none; color: var(--color-leather);
  font-size: 0.75rem; font-weight: 700; cursor: pointer;
  margin-left: 0.4em; vertical-align: middle;
}
.cmsn-info-btn:hover { background: var(--color-leather); color: #fff; }

.cmsn-link-btn {
  position: relative;
  background: none; border: none; padding: 0;
  font: inherit; color: var(--color-leather);
  text-decoration: underline; cursor: pointer;
}

/* A link button sitting INSIDE a sentence, as step 03's instruction does.
   It carries the paragraph's weight rather than shrinking inside it. */
.cmsn-link-btn--lead { font-weight: 600; }

/* Expand the touch target to >=44px without changing the visual size */
.cmsn-info-btn::before,
.cmsn-link-btn::before {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 100%; height: 100%;
  min-width: 44px; min-height: 44px;
}

/* ----------------------------------------------------------------- Modal  */
.cmsn-modal[hidden] { display: none; }
.cmsn-modal {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
  background: rgba(0,0,0,0.6);
}
.cmsn-modal__panel {
  background: var(--color-background);
  border-radius: 4px;
  max-width: 720px; width: 100%;
  max-height: 88vh; overflow-y: auto;
  padding: 1.75rem;
  position: relative;
}
.cmsn-modal__close {
  position: absolute; top: 0.6rem; right: 0.6rem;
  width: 44px; height: 44px;
  background: none; border: none; font-size: 1.5rem; cursor: pointer; line-height: 1;
}
.cmsn-modal__title { margin-bottom: 0.75em; padding-right: 2.5rem; }
.cmsn-modal img { width: 100%; height: auto; border: 1px solid var(--cmsn-line); background: #fff; margin-bottom: 1rem; }
.cmsn-modal__placeholder {
  border: 1px dashed var(--color-leather);
  color: var(--color-leather);
  padding: 2rem 1rem; text-align: center; font-size: 0.85rem;
  text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 1rem;
}

/* ---------------------------------------------------------------- Uploads */
.cmsn-drop {
  border: 2px dashed var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  padding: 2rem 1.25rem;
  text-align: center;
  background: var(--color-surface);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.cmsn-drop[data-drag="true"] { border-color: var(--color-leather); background: rgba(107,58,32,0.04); }
.cmsn-drop__title { font-weight: 600; margin-bottom: 0.35em; }
.cmsn-drop__hint { font-size: 0.85rem; opacity: 0.7; margin-bottom: 1rem; }

.cmsn-refs { display: grid; grid-template-columns: 1fr; gap: 1rem; margin-top: 1.25rem; }
@media (min-width: 640px) { .cmsn-refs { grid-template-columns: repeat(2,1fr); } }
.cmsn-ref {
  border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
  padding: 0.85rem;
}
.cmsn-ref__top { display: flex; gap: 0.75rem; align-items: flex-start; margin-bottom: 0.65rem; }
.cmsn-ref__thumb {
  width: 68px; height: 68px; flex: none;
  object-fit: cover; border-radius: 2px; background: #ddd;
  border: 1px solid var(--cmsn-line);
}
.cmsn-ref__meta { flex: 1; min-width: 0; }
.cmsn-ref__name {
  font-size: 0.82rem; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmsn-ref__size { font-size: 0.75rem; opacity: 0.6; }
.cmsn-ref__remove {
  background: none; border: 1px solid var(--cmsn-line);
  border-radius: 2px; cursor: pointer;
  min-width: 44px; min-height: 32px; font-size: 0.78rem;
}
.cmsn-ref__remove:hover { border-color: #B3261E; color: #B3261E; }
.cmsn-ref .cmsn-select, .cmsn-ref .cmsn-textarea { font-size: 0.85rem; min-height: 44px; }
.cmsn-ref .cmsn-textarea { min-height: 66px; margin-top: 0.5rem; }

/* ---------------------------------------------------------------- Preview */
.cmsn-aside { position: static; }
@media (min-width: 1024px) { .cmsn-aside { position: sticky; top: 96px; } }

.cmsn-preview {
  border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
  padding: 1.1rem;
  margin-bottom: 1rem;
}
.cmsn-preview__label {
  font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase;
  opacity: 0.6; margin-bottom: 0.6rem;
}
/* Superseded: .cmsn-preview__scroll is the scroll container now. Leaving
   overflow-x here made the stage a second, nested scroller that swallowed the
   zoom width instead of overflowing its parent. */
.cmsn-preview__stage { width: 100%; }
.cmsn-preview__svg { width: 100%; height: auto; display: block; min-width: 260px; }
.cmsn-preview__note { font-size: 0.72rem; opacity: 0.65; margin: 0.75rem 0 0; line-height: 1.45; }
.cmsn-legend { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; margin-top: 0.7rem; font-size: 0.7rem; opacity: 0.75; }
.cmsn-legend span { display: inline-flex; align-items: center; gap: 0.3rem; }
.cmsn-legend i { width: 12px; height: 12px; border-radius: 2px; display: inline-block; }

/* ----------------------------------------------------------------- Price  */
.cmsn-price {
  border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
  padding: 1.1rem;
}
.cmsn-price__head {
  width: 100%; display: flex; justify-content: space-between; align-items: center;
  background: none; border: none; padding: 0; font: inherit; color: inherit; cursor: pointer;
  text-align: left;
}
.cmsn-price__title { font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; opacity: 0.6; }
.cmsn-price__total { font-size: 1.35rem; font-family: var(--font-heading-family); }
.cmsn-price__body { margin-top: 0.9rem; }
.cmsn-price__body[hidden] { display: none; }
.cmsn-price__row { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.88rem; padding: 0.3rem 0; }
.cmsn-price__row span:last-child { white-space: nowrap; }
.cmsn-price__row--sub { opacity: 0.7; font-size: 0.78rem; padding-left: 0.8rem; }
.cmsn-price__rule { border: 0; border-top: 1px solid var(--cmsn-line); margin: 0.7rem 0; }
.cmsn-price__deposit { background: var(--color-leather-dark); color: #fff; border-radius: 2px; padding: 0.85rem; margin-top: 0.9rem; }
.cmsn-price__deposit-row { display: flex; justify-content: space-between; font-weight: 700; }
.cmsn-price__balance { display: flex; justify-content: space-between; font-size: 0.85rem; opacity: 0.85; margin-top: 0.35rem; }
.cmsn-price__disclaimer { font-size: 0.7rem; opacity: 0.65; line-height: 1.45; margin: 0.8rem 0 0; }

/* ------------------------------------------------------------------- Nav  */
.cmsn-nav { display: flex; gap: 0.75rem; margin-top: 2.25rem; }
.cmsn-nav .btn { flex: 1; }
@media (min-width: 560px) { .cmsn-nav { justify-content: flex-start; } .cmsn-nav .btn { flex: 0 0 auto; min-width: 170px; } }

/* Mobile sticky summary */
.cmsn-sticky {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
  background: var(--color-background);
  border-top: 1px solid var(--cmsn-line);
  padding: 0.7rem 1rem calc(0.7rem + env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: 0.75rem;
  box-shadow: 0 -6px 20px rgba(0,0,0,0.08);
}
@media (min-width: 1024px) { .cmsn-sticky { display: none; } }
/* `display: flex` outranks the `[hidden]` attribute, the same trap recorded
   further up this file for .cmsn-field__hint. Without this the bar stayed
   across the bottom of the confirmation screen, still quoting an estimate,
   after the form it belonged to had been replaced. */
.cmsn-sticky[hidden] { display: none; }
/* AND THE BUTTONS INSIDE IT. `.btn` is display:inline-flex, which outranks
   `[hidden]` exactly as the bar itself did. Measured at 375x812 the moment
   Back and Submit were added: both were correctly marked hidden on step 01
   and both still reserved a row, so the bar stood 168px tall — a fifth of a
   phone screen — holding two buttons nobody could see. */
.cmsn-sticky .btn[hidden] { display: none; }
.cmsn-sticky__info { flex: 1; min-width: 0; line-height: 1.25; }
.cmsn-sticky__label { display: block; font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.6; }
.cmsn-sticky__val { display: block; font-size: 1rem; font-weight: 700; }
.cmsn-sticky .btn { min-width: 130px; }
@media (min-width: 1024px) { .cmsn-layout { padding-bottom: 3rem; } }

/* NARROW PHONES: the bar is two buttons and a price, and on a 375px screen
   those add up to more than the screen. Left alone the page gains a sideways
   scroll, which on a phone reads as the layout being broken. The buttons are
   allowed to shrink and the row to wrap, so the bar gets taller instead of
   wider — the one direction a phone has to spare. */
@media (max-width: 460px) {
  .cmsn-sticky { flex-wrap: wrap; gap: 0.5rem 0.6rem; padding-left: 0.75rem; padding-right: 0.75rem; }
  .cmsn-sticky .btn { min-width: 0; flex: 1 1 auto; }
  .cmsn-sticky__info { flex: 1 0 100%; }
  /* The expand control carries a full sentence of label. It has to be allowed
     to give that up before it pushes the page sideways — wherever it sits, not
     only in the bar. */
  .cmsn-preview__expand { max-width: 100%; flex: 0 1 auto; min-width: 0; }
  .cmsn-preview__expandtxt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* The label and the control share one row and neither will give. Let the row
     wrap instead: taller is free on a phone, wider is not. */
  .cmsn-preview__bar { flex-wrap: wrap; }
}

/* The uploaded file's own name, above its size. Truncated rather than wrapped:
   a long camera filename would otherwise push the row taller than the
   thumbnail beside it. */
.cmsn-ref__name {
  display: block; font-weight: 600; font-size: 0.85rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 100%;
}

/* ---------------------------------------------------------------- Review  */
.cmsn-review__group { border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius); background: var(--color-surface); padding: 1.15rem; margin-bottom: 1rem; }
.cmsn-review__head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; margin-bottom: 0.85rem; }
.cmsn-review__title { font-size: 0.75rem; letter-spacing: 0.11em; text-transform: uppercase; opacity: 0.65; }

/* "all four required" beside the agreements heading — the rule the submit
   button already enforces, said before it is enforced. */
.cmsn-review__req {
  display: inline-block; margin-left: 0.6em;
  font-size: 0.9em; letter-spacing: 0.06em;
  color: var(--color-leather); opacity: 0.95;
}
.cmsn-review__dl { display: grid; grid-template-columns: 1fr; gap: 0.5rem 1rem; margin: 0; }
@media (min-width: 560px) { .cmsn-review__dl { grid-template-columns: 11rem 1fr; } }
.cmsn-review__dl dt { font-size: 0.85rem; opacity: 0.65; }
.cmsn-review__dl dd { margin: 0; font-size: 0.92rem; white-space: pre-wrap; overflow-wrap: anywhere; }
.cmsn-review__refs { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.cmsn-review__refs img { width: 58px; height: 58px; object-fit: cover; border-radius: 2px; border: 1px solid var(--cmsn-line); }

/* ------------------------------------------------------------------ Terms */
.cmsn-term { display: flex; gap: 0.8rem; padding: 1rem; border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius); background: var(--color-surface); margin-bottom: 0.85rem; }
.cmsn-term input { width: 22px; height: 22px; margin: 0.15rem 0 0; flex: none; accent-color: var(--color-leather); }
.cmsn-term__body { flex: 1; }
.cmsn-term__title { display: block; font-weight: 700; font-size: 0.8rem; letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: 0.35em; }
.cmsn-term__text { font-size: 0.85rem; opacity: 0.85; line-height: 1.55; }
.cmsn-term[data-invalid="true"] { border-color: #B3261E; }

/* ------------------------------------------------------------- Feedback   */
.cmsn-alert { border-radius: var(--cmsn-radius); padding: 0.9rem 1rem; font-size: 0.9rem; margin-bottom: 1.25rem; }
.cmsn-alert--error { background: #FDECEA; color: #8C1D18; border: 1px solid #F2B8B5; }
.cmsn-alert--info { background: rgba(169,121,60,0.12); border: 1px solid rgba(169,121,60,0.4); }
.cmsn-alert[hidden] { display: none; }
/* THE CONFIRMATION'S OWN NOTICES, which sit in a centered column of their own
   under a centered heading. Two of them carried the same three declarations as
   a `style=` attribute, which the build's style-src budget counts one by one:
   the rule is that style-src still allows unsafe-inline and the number of
   inline styles must not creep, and a third copy is exactly the creep it is
   there to catch. */
.cmsn-done__notice { max-width: 52ch; margin: 0 auto 1.5rem; text-align: left; }
.cmsn-done__notice p { margin: 0 0 0.75rem; }
.cmsn-done__notice p:last-child { margin: 0; }

.cmsn-saved { font-size: 0.75rem; opacity: 0.6; margin-top: 1rem; }
.cmsn-saved[hidden] { display: none; }

.cmsn-done { text-align: center; padding: 3rem 1rem; }
.cmsn-done__title { font-size: clamp(1.5rem,4vw,2.2rem); margin-bottom: 0.5em; }
.cmsn-done__id { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9rem; opacity: 0.7; margin-bottom: 1.5rem; }

.cmsn-spinner { display: inline-block; width: 16px; height: 16px; border: 2px solid rgba(255,255,255,0.4); border-top-color: #fff; border-radius: 50%; animation: cmsn-spin 0.7s linear infinite; margin-right: 0.5em; vertical-align: -3px; }
@keyframes cmsn-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .cmsn *, .cmsn *::before, .cmsn *::after { transition: none !important; animation: none !important; }
}

/* ================= v2: commission-request additions ===================== */

.cmsn-opt-tag {
  font-size: .7rem; font-weight: 400; text-transform: uppercase;
  letter-spacing: .07em; opacity: .55; margin-left: .4em;
}
.btn--small { min-height: 44px; padding: .6em 1.1em; font-size: .82rem; }

/* --- Method callouts (measure a belt vs measure a buckle) --- */
.cmsn-method {
  border: 1px solid var(--cmsn-line);
  border-left: 4px solid var(--color-leather);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
  padding: 1.1rem 1.15rem;
  margin: 0 0 1rem;
}
.cmsn-method--alt { border-left-color: var(--color-brass); }
.cmsn-method__tag {
  display: inline-block; font-size: .66rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--color-leather); margin-bottom: .45em;
}
.cmsn-method--alt .cmsn-method__tag { color: var(--color-brass); }
.cmsn-method__title { display: block; font-size: 1rem; margin-bottom: .35em; }
.cmsn-method__text { font-size: .9rem; opacity: .85; margin: 0 0 .85em; line-height: 1.6; }
.cmsn-measure-cta { width: 100%; }
@media (min-width: 560px) { .cmsn-measure-cta { width: auto; } }

/* --- Warning callout --- */
.cmsn-callout {
  background: rgba(169,121,60,.14);
  border: 1px solid rgba(169,121,60,.45);
  border-radius: var(--cmsn-radius);
  padding: .9rem 1rem; font-size: .88rem; line-height: 1.6; margin: 0 0 1rem;
}

/* --- Progressive-disclosure wrapper --- */
.cmsn-reveal {
  margin-top: 1.25rem; padding: 1.15rem;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: color-mix(in srgb, var(--color-surface) 70%, transparent);
}
.cmsn-reveal[hidden] { display: none; }

/* --- Three buckle cards --- */
.cmsn-buckle-cards { display: grid; grid-template-columns: 1fr; gap: .85rem; }
@media (min-width: 780px) { .cmsn-buckle-cards { grid-template-columns: repeat(3, 1fr); } }
.cmsn-bcard { position: relative; display: block; }
.cmsn-bcard input {
  position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer;
}
.cmsn-bcard__box {
  display: flex; flex-direction: column; height: 100%;
  min-height: 128px; padding: 1.15rem;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-surface);
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease;
}
.cmsn-bcard input:checked + .cmsn-bcard__box {
  border-color: var(--color-leather);
  box-shadow: inset 0 0 0 2px var(--color-leather);
}
.cmsn-bcard input:focus-visible + .cmsn-bcard__box { outline: 3px solid var(--color-brass); outline-offset: 2px; }
.cmsn-bcard__title {
  font-family: var(--font-heading-family); font-size: 1.05rem; line-height: 1.2; margin-bottom: .3em;
}
.cmsn-bcard__desc { font-size: .85rem; opacity: .78; line-height: 1.5; }
.cmsn-bcard input:checked + .cmsn-bcard__box::after {
  content: "✓ Selected"; margin-top: auto; padding-top: .7em;
  font-size: .75rem; font-weight: 700; color: var(--color-leather);
}

/* --- Option thumbnails / out of stock --- */
.cmsn-opt__thumb {
  width: 48px; height: 48px; flex: none; object-fit: cover;
  border-radius: 2px; border: 1px solid var(--cmsn-line);
}
.cmsn-opt--oos .cmsn-opt__box { opacity: .5; }
.cmsn-opt--oos .cmsn-opt__note { color: #8C1D18; font-weight: 600; }

/* --- Font samples --- */
.cmsn-fontsample { display: block; font-size: 1.5rem; line-height: 1.15; margin-bottom: .15em; color: var(--color-heading); }
.cmsn-fontsample--western {
  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 900; letter-spacing: .04em; text-transform: uppercase; font-size: 1.15rem;
}
.cmsn-fontsample--script {
  font-family: "Snell Roundhand", "Brush Script MT", "Segoe Script", cursive;
  font-style: italic; font-size: 1.6rem;
}
.cmsn-fontsample--custom {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .95rem; opacity: .65; border: 1px dashed var(--cmsn-line);
  padding: .3em .5em; border-radius: 2px;
}

/* --- Sub-upload blocks --- */
.cmsn-subupload {
  margin-top: 1rem; padding-top: 1rem; border-top: 1px dashed var(--cmsn-line);
}

/* --- Previous design gallery --- */
.cmsn-prev-gallery figure { margin: 0; }
.cmsn-prev[hidden] { display: none; }
.cmsn-prev img { width: 100%; height: auto; border-radius: var(--cmsn-radius); border: 1px solid var(--cmsn-line); }
.cmsn-prev figcaption { font-size: .82rem; opacity: .7; margin-top: .5em; }

/* --- Success: what happens next --- */
.cmsn-next {
  text-align: left; max-width: 30rem; margin: 1.5rem auto 0;
  background: var(--color-surface); border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius); padding: 1.25rem 1.5rem;
}
.cmsn-next__title { font-size: .78rem; letter-spacing: .1em; text-transform: uppercase; opacity: .65; margin-bottom: .85em; }
.cmsn-next__list { counter-reset: nx; }
.cmsn-next__list li {
  counter-increment: nx; position: relative;
  padding-left: 2rem; margin-bottom: .6em; font-size: .92rem;
}
.cmsn-next__list li::before {
  content: counter(nx); position: absolute; left: 0; top: 0;
  width: 1.35rem; height: 1.35rem; border-radius: 50%;
  background: var(--color-leather); color: #fff;
  font-size: .72rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* --- Video embed in modals --- */
.cmsn-video {
  position: relative; width: 100%; padding-bottom: 56.25%;
  height: 0; overflow: hidden; border-radius: var(--cmsn-radius);
  background: #000; margin-bottom: 1rem;
}
.cmsn-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.cmsn-ref__thumb--file {
  display: flex; align-items: center; justify-content: center;
  font-size: .6rem; font-weight: 700; letter-spacing: .06em;
  color: var(--color-leather); background: rgba(107,58,32,.08);
}
.cmsn-construction { margin-top: .9rem; border-top: 1px solid var(--cmsn-line); padding-top: .8rem; }
.cmsn-construction summary {
  cursor: pointer; font-size: .78rem; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--color-leather);
  padding: .35rem 0; min-height: 30px;
}
.cmsn-construction summary:focus-visible { outline: 3px solid var(--color-brass); outline-offset: 2px; }
.cmsn-construction img { width: 100%; height: auto; margin: .75rem 0 .5rem; background: #fff;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius); }
.cmsn-construction p { font-size: .82rem; opacity: .78; line-height: 1.55; margin: 0; }

/* Shown when a request saved successfully but the workshop notification
   could not be confirmed. Deliberately reassuring, not alarming. */
.cmsn-alert--warn {
  background: rgba(169,121,60,.15);
  border: 1px solid rgba(169,121,60,.55);
  color: #4A2815;
  line-height: 1.6;
}
.cmsn-alert--warn a { color: #6B3A20; font-weight: 700; }

/* Per-file upload failure: recoverable, and explicitly reassuring about the rest. */
.cmsn-ref__fail {
  margin-top: .6rem; padding: .7rem .8rem;
  background: #FDECEA; border: 1px solid #F2B8B5; border-radius: var(--cmsn-radius);
}
.cmsn-ref__failmsg { margin: 0 0 .25em; font-size: .82rem; color: #8C1D18; line-height: 1.5; }
.cmsn-ref__failsafe { margin: 0 0 .6em; font-size: .78rem; color: #6B5A48; }
.cmsn-ref__failbtns { display: flex; gap: .5rem; flex-wrap: wrap; }
.cmsn-done__estimatenote {
  max-width: 46rem; margin: .75rem auto 0;
  font-size: .85rem; line-height: 1.6; opacity: .8;
}
.cmsn-next__list li strong { font-weight: 700; }

/* Consolidated "referencing a previous belt?" block */
.cmsn-refbelt__row {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; margin-top: .85rem;
}
.cmsn-refbelt code {
  background: rgba(0,0,0,.06); padding: .1em .4em; border-radius: 2px;
  font-size: .85em; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* Method 1 / Method 2 workflows — deliberately distinct so they can't be confused */
.cmsn-methodhead { font-size: 1.05rem; margin: 0 0 .35em; }
.cmsn-method1 { border-left: 4px solid var(--color-leather); }
.cmsn-method2 { border-left: 4px solid var(--color-brass); }
/* Step A and Step B are two halves of one measuring process, so they get one
   container treatment rather than each being styled where it happens to sit.
   Previously Step A sat in .cmsn-substep and Step B in a bare .cmsn-field, so
   they read as two unrelated blocks. */
.cmsn-substep {
  margin-top: 1.15rem;
  padding: 1.15rem;
  border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
}
.cmsn-substep + .cmsn-substep { margin-top: 1rem; }
.cmsn-substep__tag {
  display: inline-block; background: var(--color-leather); color: #fff;
  font-size: .68rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  padding: .25em .6em; border-radius: 2px; margin-bottom: .5em;
}
.cmsn-method2 .cmsn-substep__tag { background: var(--color-brass); }
.cmsn-substep__title { display: block; font-size: 1rem; margin-bottom: .35em; }
.cmsn-diagram {
  width: 100%; height: auto; margin: .85rem 0; background: #fff;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
}
.cmsn-diagram-missing {
  border: 1px dashed var(--color-leather); color: var(--color-leather);
  padding: 1.5rem 1rem; text-align: center; font-size: .8rem; margin: .85rem 0;
  text-transform: uppercase; letter-spacing: .04em; border-radius: var(--cmsn-radius);
}
.cmsn-videosoon {
  font-size: .85rem; opacity: .7; font-style: italic;
  padding: .5rem 0; margin: 0;
}

/* Preview view toggle — with buckle / strap only (Phase 2 concept preview) */
.cmsn-viewtoggle { display: flex; gap: .4rem; margin: .6rem 0 .2rem; }
.cmsn-viewtoggle button {
  flex: 0 0 auto; font: inherit; font-size: .72rem; letter-spacing: .06em;
  text-transform: uppercase; padding: .4em .85em; cursor: pointer;
  background: transparent; color: var(--cmsn-ink, #231A14);
  border: 1px solid var(--cmsn-line, #E4DACC); border-radius: 999px;
}
.cmsn-viewtoggle button[aria-pressed="true"] {
  background: var(--cmsn-ink, #231A14); color: #fff; border-color: var(--cmsn-ink, #231A14);
}
.cmsn-viewtoggle button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* "Use this image on the belt" designation (Phase 5 image placement) */
.cmsn-ref__use {
  display: inline-block; margin: .5rem 0 .1rem; font: inherit; font-size: .72rem;
  letter-spacing: .05em; text-transform: uppercase; padding: .42em .9em; cursor: pointer;
  background: transparent; color: var(--cmsn-ink, #231A14);
  border: 1px solid var(--cmsn-line, #E4DACC); border-radius: 999px;
}
.cmsn-ref__use[aria-pressed="true"] {
  background: var(--cmsn-accent, #6B3A20); color: #fff;
  border-color: var(--cmsn-accent, #6B3A20);
}
.cmsn-ref__use:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }

/* ---------------------------------------------------------------------------
   Product selector, hand-painting list and inline notes.
   Added with the Belt + Matching Collar work. These use the same tokens and
   the same card mechanics as the buckle/width cards, so a card behaves
   identically wherever it appears.
--------------------------------------------------------------------------- */

/* Three products read better than three squeezed columns on a phone. */
.cmsn-productcards { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

/* A short aside — lighter than body text, but not as faint as a field hint,
   because some of these carry real consequences (posting holds, workspace
   caps) and must not read as decoration. */
.cmsn-note {
  font-size: 0.85rem;
  opacity: 0.8;
  margin: 0.5em 0 0;
  padding-left: 0.75em;
  border-left: 2px solid var(--cmsn-line);
}

.cmsn-paintlist { display: flex; flex-direction: column; gap: 0.5rem; margin: 0.6em 0; }

/* One row per image: the checkbox and name on the left, the painted-inches
   input on the right. It wraps rather than shrinking the input, so the number
   stays typable on a phone. */
.cmsn-paintitem {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1rem;
  padding: 0.7em 0.85em;
  border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius);
  background: var(--color-surface);
}
.cmsn-paintitem > label { display: flex; align-items: center; gap: 0.5rem; margin: 0; }
.cmsn-paintitem__name { font-weight: 500; word-break: break-word; }

/* The width input is pushed right on wide rows and drops below on narrow ones. */
.cmsn-paintitem__size {
  display: flex; align-items: center; gap: 0.5rem;
  margin-left: auto; font-size: 0.85rem; opacity: 0.85;
}
.cmsn-paintitem__size input { width: 7.5em; margin: 0; }

@media (max-width: 480px) {
  .cmsn-paintitem__size { margin-left: 0; width: 100%; }
  .cmsn-paintitem__size input { width: 100%; }
}

/* ---------------------------------------------------------------------------
   Belt + Matching Collar previews, the expand viewing mode, the thumbnail
   remove control, and the Commission ID / Search Catalog row.
--------------------------------------------------------------------------- */

/* Two pieces stacked, each captioned, so the customer can read the collar
   against the belt rather than guessing which drawing is which. */
.cmsn-piece { margin: 0 0 1rem; }
.cmsn-piece:last-child { margin-bottom: 0; }
.cmsn-piece__label {
  font: 600 0.72rem/1.4 var(--font-heading-family, inherit);
  letter-spacing: .12em; text-transform: uppercase;
  opacity: .75; margin: 0 0 .3rem;
}
.cmsn-piece__meta { display: block; margin-top: .35em; }

/* Expand control lives in the panel heading. */
.cmsn-preview__label { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.cmsn-preview__expand {
  position: relative;                 /* anchors the enlarged hit area below */
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-surface); color: inherit; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;         /* no 300ms tap delay, no double-tap zoom */
}
/* THE WHOLE CONTROL IS CLICKABLE, MIDDLE INCLUDED.
   The icon is four corner brackets with an empty center, so the middle of the
   button is the part that LOOKS least like a target and the part a customer
   aims at. Two things guarantee it:
     1. the icon takes no pointer events at all, so every hit inside the button
        resolves to the BUTTON — there is no inner element to swallow it;
     2. an invisible 44x44 pad, centered on the button, meets the minimum touch
        target while the visible box stays 32x32 exactly where it was. */
.cmsn-preview__expand > * { pointer-events: none; }
.cmsn-preview__expand::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.cmsn-preview__expand:hover { border-color: var(--color-leather); color: var(--color-leather); }
.cmsn-preview__expand:focus-visible { outline: 2px solid var(--color-leather); outline-offset: 2px; }

/* EXPANDED: a temporary viewing mode pinned to the bottom third of the
   viewport. The element keeps its place in the DOM — only its painting
   changes — so collapsing restores the layout exactly, and the form above
   stays scrollable and usable underneath. */
.cmsn-preview.is-expanded {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  height: 34vh; min-height: 240px;
  margin: 0; border-radius: 0;
  border-top: 1px solid var(--cmsn-line);
  background: var(--color-background);
  box-shadow: 0 -8px 28px rgba(0,0,0,.18);
  overflow: auto; padding: .75rem 1rem 1rem;
}
.cmsn-preview.is-expanded .cmsn-preview__label {
  position: sticky; top: 0; background: var(--color-background); padding: .25rem 0; margin: 0 0 .4rem;
}
/* The DRAWING fills the expanded panel. Scoped to the stage: unscoped, this
   also stretched the collapse button's own 18px icon. */
.cmsn-preview.is-expanded .cmsn-preview__stage svg { width: 100%; height: auto; }
/* Keep the last of the form reachable above the panel. */
body.cmsn-preview-open .cmsn { padding-bottom: 36vh; }

/* Thumbnail remove control: a cross ON the image, top-left. */
.cmsn-ref__thumbwrap { position: relative; display: inline-block; line-height: 0; }
.cmsn-ref__x {
  position: absolute; top: 4px; left: 4px;
  width: 22px; height: 22px; padding: 0; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 700;
  border: 1px solid rgba(255,255,255,.85); border-radius: 50%;
  background: rgba(0,0,0,.62); color: #fff; cursor: pointer;
}
.cmsn-ref__x:hover { background: #B3261E; border-color: #B3261E; }
.cmsn-ref__x:focus-visible { outline: 2px solid var(--color-leather); outline-offset: 2px; }
.cmsn-ref__thumb--mini { width: 44px; height: 44px; object-fit: cover; border-radius: 4px; }

/* [ Commission ID ] [ Search Catalog ] on one row. */
.cmsn-refrow { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; }
.cmsn-refrow .cmsn-input { flex: 1 1 220px; max-width: 280px; margin: 0; }
.cmsn-refrow__btn { flex: 0 0 auto; white-space: nowrap; }

/* ===========================================================================
   ARTWORK LIBRARY, SELECTED ARTWORK, AND ARTWORK ON THE PREVIEW
   Phase 1 of the Concept Preview.
=========================================================================== */
.cmsn-art { margin-top: .75rem; }
.cmsn-art__search { margin-bottom: .75rem; }
.cmsn-art__search .cmsn-input { max-width: 100%; }

.cmsn-art__roles { display: flex; gap: .4rem; margin-bottom: .6rem; flex-wrap: wrap; }
.cmsn-art__role {
  font: 600 .72rem/1 var(--font-heading-family, inherit);
  letter-spacing: .1em; text-transform: uppercase;
  padding: .5rem .85rem; cursor: pointer;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-surface); color: inherit;
}
.cmsn-art__role.is-on { background: var(--color-leather); border-color: var(--color-leather); color: #fff; }

.cmsn-art__cats, .cmsn-art__subs { display: flex; gap: .35rem; flex-wrap: wrap; margin-bottom: .6rem; }
.cmsn-art__subs { padding-left: .5rem; border-left: 2px solid var(--cmsn-line); }
.cmsn-art__cat, .cmsn-art__sub {
  display: inline-flex; align-items: center; gap: .35em;
  font-size: .82rem; padding: .38rem .7rem; cursor: pointer;
  border: 1px solid var(--cmsn-line); border-radius: 999px;
  background: var(--color-background); color: inherit;
}
.cmsn-art__sub { font-size: .78rem; }
.cmsn-art__cat.is-on, .cmsn-art__sub.is-on { border-color: var(--color-leather); color: var(--color-leather); font-weight: 600; }
.cmsn-art__cat:hover, .cmsn-art__sub:hover, .cmsn-art__role:hover { border-color: var(--color-leather); }
.cmsn-art__n {
  font-size: .68rem; font-weight: 700; opacity: .6;
  background: rgba(0,0,0,.07); border-radius: 999px; padding: 0 .4em; min-width: 1.3em; text-align: center;
}

/* Tiles: a fixed thumbnail box so a wide flag and a tall crest line up. */
.cmsn-art__grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
  gap: .6rem; margin-top: .25rem;
}
.cmsn-art__tile {
  display: flex; flex-direction: column; gap: .3rem; padding: .6rem;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-surface); cursor: pointer; text-align: left; color: inherit;
}
.cmsn-art__tile:hover { border-color: var(--color-leather); }
/* The ARTWORK inside the tile is half what it was; the tile itself keeps its
   size so it stays an easy target and the library structure stays readable. */
.cmsn-art__thumb {
  display: flex; align-items: center; justify-content: center;
  /* BIG ENOUGH TO RECOGNIZE. 42px was a smudge — the customer is choosing a
     piece of artwork and could not see what it was. */
  height: 104px; background: #fff; border-radius: 3px; overflow: hidden;
  padding: .3rem;
}
.cmsn-art__thumb img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.cmsn-art__name { font-weight: 600; font-size: .85rem; line-height: 1.25; }
.cmsn-art__where { font-size: .72rem; opacity: .62; }
.cmsn-art__empty { font-size: .85rem; opacity: .75; margin: 1rem 0 0; }

/* Selected artwork list */
.cmsn-art__none { font-size: .88rem; opacity: .78; margin: .5rem 0 0; }
.cmsn-art__selected { display: flex; flex-direction: column; gap: .45rem; margin-top: .6rem; }
.cmsn-art__item {
  display: flex; align-items: stretch; gap: .5rem;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-surface);
}
.cmsn-art__item.is-on { border-color: var(--color-leather); box-shadow: inset 0 0 0 1px var(--color-leather); }
.cmsn-art__pick {
  display: flex; align-items: center; gap: .6rem; flex: 1 1 auto;
  padding: .55rem; background: none; border: 0; cursor: pointer; text-align: left; color: inherit;
}
.cmsn-art__itemthumb { width: 52px; height: 34px; object-fit: contain; flex: 0 0 auto; }
.cmsn-art__itemtext { display: flex; flex-direction: column; gap: .12em; }
.cmsn-art__meta { font-size: .74rem; opacity: .65; }
.cmsn-art__flag { font-size: .72rem; color: #8A5A00; font-weight: 600; }
.cmsn-art__flag--charge { color: #B3261E; }
.cmsn-art__x {
  flex: 0 0 auto; width: 34px; border: 0; border-left: 1px solid var(--cmsn-line);
  background: none; font-size: 18px; line-height: 1; cursor: pointer; color: inherit; opacity: .6;
}
.cmsn-art__x:hover { opacity: 1; color: #B3261E; }

/* Which piece is being designed — bundle only. One at a time, by design. */
.cmsn-art__products { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin: .6rem 0 .2rem; }
.cmsn-art__prod {
  display: inline-flex; align-items: center; gap: .4em;
  font: 600 .78rem/1 inherit; padding: .5rem .9rem; cursor: pointer;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-background); color: inherit; opacity: .5;
}
.cmsn-art__prod.is-on { opacity: 1; border-color: var(--color-leather); color: var(--color-leather); background: var(--color-surface); }
.cmsn-art__prodnote { font-size: .74rem; opacity: .7; }

/* Numeric controls for the selected piece */
.cmsn-art__tools {
  display: flex; flex-wrap: wrap; gap: .75rem; margin-top: .6rem; padding: .7rem;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius); background: var(--color-surface);
}
.cmsn-art__tool { display: flex; align-items: center; gap: .4rem; font-size: .8rem; }
.cmsn-art__tool > span:first-child { font-weight: 600; opacity: .75; }
.cmsn-art__tool output { min-width: 6.5em; font-variant-numeric: tabular-nums; }
.cmsn-art__tool .cmsn-input { padding: .35rem .5rem; font-size: .8rem; width: auto; }
.cmsn-art__paint { display: inline-flex; align-items: center; gap: .4em; cursor: pointer; }

/* On the preview itself */
/* Artwork is placed with the buttons, never grabbed, so it does not offer a
   hand it will not take. */
.cmsn-art__obj { cursor: pointer; }
.cmsn-art__sel { stroke: var(--color-leather, #7A4B22); stroke-width: 1.2; stroke-dasharray: 3 2; }
.cmsn-art__handle { fill: #fff; stroke: var(--color-leather, #7A4B22); stroke-width: 1.5; cursor: nwse-resize; }
.cmsn-art__handle--rot { cursor: pointer; }


/* ---- Phase 2A-1: chosen tiles, a scrolling library, quantity ------------ */

/* ABOUT 1.5 TILES TALL, whatever a tile happens to measure — so the library
   can grow to hundreds of pieces without Section 02 growing with it, and
   nothing here counts today's artwork. */
.cmsn-art__grid {
  max-height: calc((var(--cmsn-tile-h, 120px) + .6rem) * 1.5);
  overflow-y: auto; overscroll-behavior: contain;
  padding-right: .35rem;
  /* A scrollbar the customer can actually see. Left to the platform, macOS
     hides it until you scroll, which reads as "this is all there is". */
  scrollbar-width: thin;
  scrollbar-color: var(--color-leather, #7A4B22) rgba(0,0,0,.07);
}
.cmsn-art__grid::-webkit-scrollbar { width: 10px; }
.cmsn-art__grid::-webkit-scrollbar-track { background: rgba(0,0,0,.06); border-radius: 999px; }
.cmsn-art__grid::-webkit-scrollbar-thumb {
  background: var(--color-leather, #7A4B22); border-radius: 999px;
  border: 2px solid var(--color-background, #fff);
}
.cmsn-art__scrollnote { font-size: .72rem; opacity: .6; margin: .35rem 0 0; }

/* ALREADY CHOSEN. Obvious at a glance, and still clearly a control rather
   than a disabled thing — clicking it takes you to the piece in the list. */
.cmsn-art__tile { position: relative; }
.cmsn-art__tile.is-chosen {
  border-color: var(--color-leather, #7A4B22);
  box-shadow: inset 0 0 0 2px var(--color-leather, #7A4B22);
  background: color-mix(in srgb, var(--color-leather, #7A4B22) 7%, var(--color-surface));
}
/* The plate STAYS on a chosen tile. Clearing it is what made the artwork
   vanish the moment it was selected: the tile is white and the linework was
   white too, so "selected" read as "gone". */
.cmsn-art__tile.is-chosen .cmsn-art__thumb { background: #fff; }
.cmsn-art__chosen {
  position: absolute; top: .3rem; right: .3rem;
  font: 700 .6rem/1 var(--font-heading-family, inherit);
  letter-spacing: .08em; text-transform: uppercase;
  background: var(--color-leather, #7A4B22); color: #fff;
  padding: .25em .5em; border-radius: 999px;
}

/* Role reads as a badge, because foreground vs background is a real
   distinction in the design and eventually on the work order. */
.cmsn-art__role {
  display: inline-block; font: 700 .62rem/1 var(--font-heading-family, inherit);
  letter-spacing: .07em; text-transform: uppercase;
  padding: .22em .45em; border-radius: 3px; margin-right: .3em;
}
.cmsn-art__role--foreground { background: rgba(122,75,34,.14); color: #6B4220; }
.cmsn-art__role--background { background: rgba(40,80,110,.14); color: #2A5570; }

/* − 1 + */
.cmsn-art__qty {
  display: inline-flex; align-items: center; align-self: center;
  border-left: 1px solid var(--cmsn-line); flex: 0 0 auto;
}
.cmsn-art__qty button {
  width: 30px; height: 34px; border: 0; background: none; cursor: pointer;
  font-size: 15px; line-height: 1; color: inherit; opacity: .75;
}
.cmsn-art__qty button:hover:not(:disabled) { opacity: 1; color: var(--color-leather); }
.cmsn-art__qty button:disabled { opacity: .25; cursor: default; }
.cmsn-art__qty output {
  min-width: 1.6em; text-align: center; font-weight: 700;
  font-variant-numeric: tabular-nums; font-size: .88rem;
}
.cmsn-art__itemthumb { width: 52px; height: 34px; object-fit: contain; flex: 0 0 auto; }


/* ---- Phase 2A-2: inline artwork, leather-driven linework ---------------- */

/* The tile and list thumbnails are INLINE svg, so `color` reaches them and the
   linework follows the leather. Set on the browser and the list, not on each
   svg, so one rule covers however many tiles there are. */
.cmsn-art__grid, .cmsn-art__selected { color: #1B120C; }
.cmsn-art--dark .cmsn-art__grid,
.cmsn-art--dark .cmsn-art__selected { color: #F4EFE7; }
/* ---------------------------------------------------------------------------
   THUMBNAILS DO NOT FOLLOW THE LEATHER.
   A thumbnail identifies the artwork; the BELT shows what it will look like.
   Tying tiles to the leather color meant the library changed appearance when
   someone picked a color three steps away, and on dark leather it put white
   linework one CSS rule away from being invisible. White plate, black lines,
   always — on the library grid, the reorder strip and the verification list.
--------------------------------------------------------------------------- */
.cmsn-art__thumb, .cmsn-art__itemthumb,
.cmsn-chip3__thumb, .cmsn-verify__thumb {
  background: #fff !important;
  color: #111 !important;
}
/* A STROKE THAT SURVIVES THE SCALE-DOWN.
   The masters are ~3000 user units across and a thumbnail is ~130px, so a
   stroke-width of 10 user units lands at 0.4 CSS px — technically drawn and
   effectively invisible, which is why the tiles looked blank. non-scaling-stroke
   takes the width out of the coordinate system so it means CSS pixels, and it
   has to be set on the SHAPES as well as the root because that is where the
   property applies. */
.cmsn-art__thumb svg, .cmsn-art__itemthumb svg,
.cmsn-chip3__thumb svg, .cmsn-verify__thumb svg,
.cmsn-art__thumb svg *, .cmsn-art__itemthumb svg *,
.cmsn-chip3__thumb svg *, .cmsn-verify__thumb svg * {
  stroke: #111 !important;
  fill: none !important;
  stroke-width: 1.15px !important;
  vector-effect: non-scaling-stroke;
}
/* C19 is the shop's FILL layer: those shapes are scanned solid on the laser,
   so they must read as solid here too. The blanket rule above zeroes fill on
   every descendant to make open contours legible; this puts it back for the
   one layer that genuinely burns filled. Ink is hard-coded rather than
   currentColor because the chip and verify thumbs set color:#fff for the
   stroke, which would render the fill invisible against the white tile. */
.cmsn-art__thumb [data-fill="1"], .cmsn-art__itemthumb [data-fill="1"],
.cmsn-chip3__thumb [data-fill="1"], .cmsn-verify__thumb [data-fill="1"],
.cmsn-art__thumb [data-fill="1"] *, .cmsn-art__itemthumb [data-fill="1"] *,
.cmsn-chip3__thumb [data-fill="1"] *, .cmsn-verify__thumb [data-fill="1"] * {
  fill: #111 !important;
  stroke: none !important;
}

/* The C03 workspace rectangle is a reference mark inside the master, not part
   of the drawing — it must not be inked into a thumbnail. */
.cmsn-art__thumb [data-workspace], .cmsn-art__itemthumb [data-workspace],
.cmsn-chip3__thumb [data-workspace], .cmsn-verify__thumb [data-workspace] { display: none; }

.cmsn-art__thumb svg, .cmsn-art__itemthumb svg {
  display: block; width: 100%; height: 100%;
  fill: none; stroke: currentColor; vector-effect: non-scaling-stroke;
}
.cmsn-art__itemthumb {
  display: block; width: 52px; height: 34px; flex: 0 0 auto;
  background: rgba(0,0,0,.03); border-radius: 3px;
}
.cmsn-art__loading {
  display: block; width: 100%; height: 100%;
  background: linear-gradient(90deg, rgba(0,0,0,.04), rgba(0,0,0,.09), rgba(0,0,0,.04));
  background-size: 200% 100%; animation: cmsnShimmer 1.1s linear infinite;
}
@keyframes cmsnShimmer { to { background-position: -200% 0; } }


/* ---- Phase 2A-3: a design workspace, not a thumbnail ------------------- */

/* THE BELT GETS ROOM. It was a strip a few pixels tall in a narrow column,
   which is fine for confirming a color and useless for placing artwork. The
   aside is now wide enough to work in, and the drawing is given real height. */
@media (min-width: 900px) {
  .cmsn-layout { grid-template-columns: minmax(0, 1fr) minmax(420px, 46%); }
}
@media (min-width: 1400px) {
  .cmsn-layout { grid-template-columns: minmax(0, 1fr) minmax(560px, 50%); }
}

/* Scrolls HORIZONTALLY. At 1x the drawing fits and there is nothing to scroll;
   zoomed in, this is how the customer travels along the belt. */
.cmsn-preview__scroll {
  overflow-x: auto; overflow-y: hidden;
  overscroll-behavior-x: contain;
  padding-bottom: .35rem;
  scrollbar-width: thin;
  scrollbar-color: var(--color-leather, #7A4B22) rgba(0,0,0,.08);
}
.cmsn-preview__scroll::-webkit-scrollbar { height: 12px; }
.cmsn-preview__scroll::-webkit-scrollbar-track { background: rgba(0,0,0,.07); border-radius: 999px; }
.cmsn-preview__scroll::-webkit-scrollbar-thumb {
  background: var(--color-leather, #7A4B22); border-radius: 999px;
  border: 3px solid var(--color-background, #fff);
}
/* The stage is what zoom widens. width:100% at 1x, 300% at 3x — the viewBox is
   never touched, so no stored coordinate changes when the customer zooms. */
/* Width is set in PIXELS by setZoom(), not as a percentage: the percentage
   resolved against a containing block that was itself a scroller, so 300% came
   out the same size as 100%. Pixels are unambiguous. */
.cmsn-preview__stage { width: 100%; }
.cmsn-preview__stage svg { width: 100%; height: auto; display: block; }

/* Controls sit above the belt, always reachable. */
.cmsn-preview__tools {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin: 0 0 .5rem;
}
.cmsn-preview__zoomwrap {
  display: inline-flex; align-items: center;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-surface);
}
.cmsn-zoombtn {
  width: 32px; height: 30px; border: 0; background: none; cursor: pointer;
  font-size: 15px; line-height: 1; color: inherit;
}
.cmsn-zoombtn:disabled { opacity: .3; cursor: default; }
.cmsn-zoomval {
  min-width: 3.2em; text-align: center; font-size: .8rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.cmsn-preview__hint { font-size: .74rem; color: #8A5A00; flex: 1 1 100%; }

/* EXPANDED: most of the window, because placing artwork needs room. */
.cmsn-preview.is-expanded { height: 78vh; min-height: 420px; padding: .75rem 1rem 1rem; }
.cmsn-preview.is-expanded .cmsn-preview__scroll { max-height: calc(78vh - 130px); }
body.cmsn-preview-open .cmsn { padding-bottom: 80vh; }

/* THE INTERACTION LAYER. Drawn outside every clip path, so a placement pushed
   off the leather still shows where it went. */
.cmsn-art__ui { pointer-events: auto; cursor: pointer; }
.cmsn-art__handle {
  fill: #fff; stroke: var(--color-leather, #7A4B22); stroke-width: 2;
  cursor: nwse-resize; vector-effect: non-scaling-stroke;
}
.cmsn-art__handle--rot { cursor: pointer; }
.cmsn-art__sel {
  stroke: var(--color-leather, #7A4B22); stroke-width: 1.5; stroke-dasharray: 4 3;
  vector-effect: non-scaling-stroke;
}


/* ---- Phase 2A-4: choosing what gets hand painted ----------------------- */

/* One row per thing ON THE BELT, library artwork and customer references
   alike, each showing what it actually looks like. Picking from thumbnails is
   the point: a list of file names is not a design decision. */
.cmsn-paintlist { display: flex; flex-direction: column; gap: .4rem; margin-top: .6rem; }
.cmsn-paintitem {
  display: flex; align-items: center; gap: .6rem; padding: .5rem .6rem; cursor: pointer;
  border: 1px solid var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: var(--color-surface); color: inherit;
}
.cmsn-paintitem:hover { border-color: var(--color-leather); }
.cmsn-paintitem.is-on {
  border-color: var(--color-leather);
  box-shadow: inset 0 0 0 1px var(--color-leather);
}
.cmsn-paintitem input { flex: 0 0 auto; margin: 0; }
.cmsn-paintitem__thumb {
  flex: 0 0 auto; width: 46px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.04); border-radius: 3px; overflow: hidden; color: #1B120C;
}
.cmsn-paintitem__thumb svg { width: 100%; height: 100%; fill: none; stroke: currentColor; }
.cmsn-paintitem__thumb img { max-width: 100%; max-height: 100%; object-fit: contain; }
.cmsn-paintitem__text { display: flex; flex-direction: column; gap: .1em; min-width: 0; }
.cmsn-paintitem__name { font-weight: 600; font-size: .85rem; }
/* Says WHICH KIND of thing this is, because the two are not the same promise:
   one is artwork I hold, the other is a reference the artist still has to draw. */
.cmsn-paintitem__kind { font-size: .72rem; opacity: .62; }

/* A reference image on the belt reads as a reference, not as finished artwork. */
.cmsn-art__itemthumb img { width: 100%; height: 100%; object-fit: contain; }

/* ===========================================================================
   THE DESIGN EXPERIENCE — collapsed summary vs expanded workspace
   ---------------------------------------------------------------------------
   Collapsed: the whole piece, fitted, no scrolling, nothing to operate.
   Expanded : a working area with rows, controls and zoom.
   The two are one component in two modes rather than two components, so what
   the customer confirms in the small one is literally the same drawing.
=========================================================================== */

/* --- collapsed: fit, never scroll ---------------------------------------- */
.cmsn-preview:not(.is-expanded) .cmsn-preview__scroll { overflow: hidden; }
.cmsn-preview:not(.is-expanded) .cmsn-preview__stage { width: auto !important; }
.cmsn-preview:not(.is-expanded) .cmsn-preview__stage svg { width: 100%; height: auto; display: block; }
/* No handles, no grab cursor: there is nothing to operate down here. */
.cmsn-preview:not(.is-expanded) .cmsn-art__ui { display: none; }
.cmsn-preview:not(.is-expanded) .cmsn-art__obj { cursor: default; }
.cmsn-preview__tools[hidden] { display: none; }

/* --- expanded: product switch -------------------------------------------- */
.cmsn-preview__products { display: flex; gap: .4rem; margin: .5rem 0 .35rem; }
.cmsn-preview__products[hidden] { display: none; }
.cmsn-preview__prod {
  flex: 1; padding: .5em .9em; border: 1px solid var(--cmsn-line); background: transparent;
  font: inherit; font-weight: 600; cursor: pointer; border-radius: 2px; color: inherit;
}
.cmsn-preview__prod.is-on { background: var(--color-heading, #2B1B10); color: #fff; border-color: transparent; }

/* --- artwork rows --------------------------------------------------------- */
.cmsn-rows { margin-top: .6rem; }
.cmsn-rows[hidden] { display: none; }
.cmsn-row + .cmsn-row { margin-top: .5rem; }
.cmsn-row__label {
  margin: 0 0 .3em; font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  font-weight: 700; opacity: .75;
}
.cmsn-row__note { font-weight: 400; letter-spacing: 0; text-transform: none; opacity: .7; margin-left: .5em; }
/* ---- ONE GRID, TWO ROWS, COLUMN BY COLUMN ----
   grid-auto-flow: column fills row 1 then row 2 of a column before starting
   the next, so the renderer emits tile, slot, tile, slot and cell 2n lands
   directly under cell 2n-1. The column is as wide as the wider of the two,
   so a tile and the background behind it line up because they share a
   column — not because anything measured them. This replaces a second
   scroller whose tiles were given absolute offsets read off the first. */
.cmsn-row__grid {
  display: grid; grid-auto-flow: column; grid-auto-columns: min-content;
  grid-template-rows: auto auto;
  gap: .3rem .45rem; overflow: visible;
  padding: .2rem 0 .3rem; width: max-content; align-items: stretch;
}
/* Excluded artwork is not in the left-to-right order and has nothing behind
   it, so it takes the whole column rather than joining the alternation. */
.cmsn-chip3--fullcol { grid-row: 1 / span 2; align-self: start; }
.cmsn-row__empty { margin: 0; padding: .9em .2em; font-size: .85rem; opacity: .55; }

.cmsn-chip3 {
  position: relative; flex: 0 0 auto; width: 5.4rem; padding: .3rem;
  border: 1px solid var(--cmsn-line); border-radius: 3px; background: #fff;
  cursor: pointer; text-align: center; user-select: none;
}
.cmsn-chip3.is-on { border-color: var(--color-heading, #2B1B10); box-shadow: 0 0 0 2px rgba(43,27,16,.16); }
.cmsn-chip3__thumb { display: block; height: 2.5rem; background: #3A2A1C; border-radius: 2px; overflow: hidden; }
.cmsn-chip3__thumb svg, .cmsn-chip3__thumb img { width: 100%; height: 100%; object-fit: contain; color: #fff; }
.cmsn-chip3__name {
  display: block; font-size: .68rem; line-height: 1.2; margin-top: .25em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmsn-chip3__flip, .cmsn-chip3__x {
  position: absolute; top: .15rem; width: 1.15rem; height: 1.15rem; padding: 0;
  border: 0; border-radius: 50%; background: rgba(255,255,255,.92); color: #2B1B10;
  font-size: .72rem; line-height: 1.15rem; cursor: pointer;
}
.cmsn-chip3__flip { left: .15rem; }
.cmsn-chip3__x    { right: .15rem; }
.cmsn-chip3__flip[aria-pressed="true"] { background: #2B1B10; color: #fff; }

/* --- the control bar ------------------------------------------------------ */
.cmsn-artctl { margin-top: .55rem; padding: .55rem .6rem; border: 1px solid var(--cmsn-line); border-radius: 3px; }
.cmsn-artctl[hidden] { display: none; }
.cmsn-artctl__head { display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline; margin-bottom: .45rem; }
.cmsn-artctl__size { font-size: .78rem; opacity: .72; }
.cmsn-artctl__warn { color: #8C1D18; }
.cmsn-artctl__grid { display: flex; flex-wrap: wrap; gap: .5rem 1.1rem; }
.cmsn-artctl__grp { display: flex; align-items: center; gap: .3rem; }
.cmsn-artctl__grp > span:first-child {
  font-size: .72rem; letter-spacing: .05em; text-transform: uppercase; opacity: .7; margin-right: .15em;
}
.cmsn-artctl__deg { min-width: 2.9em; text-align: center; font-variant-numeric: tabular-nums; font-size: .85rem; }

/* --- step 03 verification list -------------------------------------------- */
.cmsn-verify__list { list-style: none; margin: .4rem 0 0; padding: 0; }
.cmsn-verify {
  display: flex; align-items: center; gap: .65rem; padding: .5rem 0;
  border-top: 1px solid var(--cmsn-line);
}
.cmsn-verify__thumb { flex: 0 0 3.4rem; height: 2.4rem; background: #3A2A1C; border-radius: 2px; overflow: hidden; }
.cmsn-verify__thumb svg, .cmsn-verify__thumb img { width: 100%; height: 100%; object-fit: contain; color: #fff; }
.cmsn-verify__meta { flex: 1 1 auto; min-width: 0; }
.cmsn-verify__title { display: block; font-weight: 600; font-size: .92rem; }
.cmsn-verify__kind { display: block; font-size: .76rem; opacity: .68; }
.cmsn-verify__where { display: flex; gap: .3rem; flex: 0 0 auto; }
.cmsn-verify__where--fixed { font-size: .78rem; opacity: .7; }
.cmsn-verify__x {
  flex: 0 0 auto; border: 0; background: transparent; font-size: 1.15rem; line-height: 1;
  cursor: pointer; opacity: .55; padding: .2em .3em; color: inherit;
}
.cmsn-verify__x:hover { opacity: 1; }

/* --- chips (destination + upload role) ------------------------------------ */
.cmsn-chip { display: inline-flex; align-items: center; gap: .3em; cursor: pointer; }
.cmsn-chip input { position: absolute; opacity: 0; width: 0; height: 0; }
.cmsn-chip > span {
  display: inline-block; padding: .28em .62em; border: 1px solid var(--cmsn-line);
  border-radius: 999px; font-size: .76rem; line-height: 1.3; white-space: nowrap;
}
.cmsn-chip input:checked + span { background: var(--color-heading, #2B1B10); color: #fff; border-color: transparent; }
.cmsn-chip input:focus-visible + span { outline: 2px solid #7A5C3E; outline-offset: 2px; }

/* --- reference images: ONE PER ROW ---------------------------------------- */
.cmsn-refs { display: flex; flex-direction: column; gap: .55rem; }
.cmsn-refs > .cmsn-ref { width: auto; max-width: none; float: none; }
.cmsn-ref__roles { display: flex; gap: .3rem; margin-top: .3em; }
.cmsn-ref__on { display: block; font-size: .74rem; opacity: .65; margin-top: .25em; }

/* --- lettering on the leather --------------------------------------------- */
.cmsn-piece__ctext {
  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 700; letter-spacing: .04em;
}
/* WESTERN CAPS at the tip. A heavy slab serif in all capitals with open
   letter-spacing is what tooled belt-tip lettering reads as; the actual
   lettering is drawn by hand, so this is a direction, not a typeface promise. */
.cmsn-piece__ttext {
  font-family: "Rockwell", "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 900; letter-spacing: .14em; text-transform: uppercase;
}

.cmsn-step__intro--do { font-weight: 600; }

/* ===========================================================================
   THE ARTWORK STRIP — one row, role on the tile
=========================================================================== */
/* Belt|Collar sits IN the tools bar, sized to match the zoom controls. */
/* ONE CONTROL ROW: title, product switch, zoom, expand. */
.cmsn-preview__bar { display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem; }
.cmsn-preview__bar .cmsn-preview__label { margin: 0; flex: 0 0 auto; }
.cmsn-preview__bar .cmsn-preview__expand { margin-left: auto; flex: 0 0 auto; }
.cmsn-preview__zoomwrap[hidden] { display: none; }
.cmsn-preview__products { display: inline-flex; gap: 2px; }
.cmsn-preview__products[hidden] { display: none; }
/* Height is MATCHED to the zoom buttons rather than left to the text metrics —
   they share a bar, and two control heights on one line reads as a mistake. */
.cmsn-preview__prod {
  height: 30px; padding: 0 .7em; border: 1px solid var(--cmsn-line); background: transparent;
  font: inherit; font-size: .78rem; font-weight: 600; line-height: 1;
  cursor: pointer; border-radius: 2px; color: inherit;
  display: inline-flex; align-items: center; justify-content: center;
}
.cmsn-preview__prod.is-on { background: var(--color-heading, #2B1B10); color: #fff; border-color: transparent; }

/* Bigger tiles: the artwork is the point, so it gets the space. */
.cmsn-row__grid { align-items: start; }
.cmsn-chip3 {
  /* Wider than the label needs, and a reserved band at the top so the SELECTED
     ribbon has somewhere to go without displacing anything. */
  width: 10.4rem; padding: 1.35rem .4rem .4rem;
}
.cmsn-chip3__thumb {
  height: 5.4rem; background: #fff; border-radius: 2px; padding: .2rem;
  display: flex; align-items: center; justify-content: center;
}
.cmsn-chip3__thumb svg, .cmsn-chip3__thumb img {
  width: 100%; height: 100%; object-fit: contain; fill: none; stroke: #111;
}
.cmsn-chip3__name { font-size: .72rem; margin-top: .2em; }

/* Role, as two small segmented buttons on the tile itself. */
.cmsn-chip3__roles { display: flex; gap: 2px; margin-top: .25em; }
.cmsn-chip3__role {
  flex: 1; padding: .18em 0; font: inherit; font-size: .64rem; font-weight: 700;
  letter-spacing: .03em; border: 1px solid var(--cmsn-line); background: #fff;
  color: #444; cursor: pointer; border-radius: 2px;
}
.cmsn-chip3__role.is-on { background: #2B1B10; color: #fff; border-color: transparent; }

/* Copies. */
.cmsn-chip3__qty { display: flex; align-items: center; justify-content: center; gap: .25em; margin-top: .25em; }
.cmsn-chip3__q {
  width: 1.4rem; height: 1.4rem; padding: 0; border: 1px solid var(--cmsn-line);
  background: #fff; color: #2B1B10; font: inherit; font-size: .8rem; line-height: 1;
  cursor: pointer; border-radius: 2px;
}
.cmsn-chip3__q[disabled] { opacity: .35; cursor: default; }
.cmsn-chip3__n { font-size: .78rem; font-variant-numeric: tabular-nums; min-width: 1.1em; text-align: center; }

/* Verification thumbs get room too. */
.cmsn-verify__thumb { flex: 0 0 4.6rem; height: 3.2rem; padding: .15rem; }

/* ---------------------------------------------------------------------------
   LETTERING ON THE LEATHER — the shop's own face, at a readable size.
--------------------------------------------------------------------------- */
.cmsn-piece__ctext {
  font-family: "GBCLeather", "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 700; letter-spacing: .02em;
}
.cmsn-piece__ttext {
  font-family: "GBCLeather", "Rockwell", "Playfair Display", Georgia, serif;
  font-weight: 900; letter-spacing: .14em; text-transform: uppercase;
}

/* ===========================================================================
   FINAL PASS — bar, per-copy tiles, flipped thumbnails, collar pool
=========================================================================== */
.cmsn-preview__bar .cmsn-zoombtn {
  height: 26px; min-width: 30px; padding: 0 .45em; font-size: .74rem; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.cmsn-preview__bar .cmsn-zoombtn.is-on {
  background: var(--color-heading, #2B1B10); color: #fff; border-color: transparent;
}
.cmsn-preview__bar .cmsn-preview__prod { height: 26px; font-size: .74rem; }
/* Inline in the control bar, to the right of the zoom. Ellipsised rather than
   wrapped so a long note can never push the bar onto a second line. */
.cmsn-preview__hint {
  font-size: .72rem; opacity: .7; margin: 0; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cmsn-preview__hint:empty { display: none; }

/* A FLIPPED PLACEMENT SHOWS FLIPPED IN ITS OWN TILE.
   Mirroring the thumbnail is a display transform on the tile only — the
   placement's flipH boolean stays the single source of truth and the master is
   never touched. Without this, flipping one of three copies gave no visible
   feedback about WHICH copy had been flipped. */
.cmsn-chip3__thumb.is-flipped svg,
.cmsn-chip3__thumb.is-flipped img { transform: scaleX(-1); }

/* Actions sit in one row under the tile. */
.cmsn-chip3__acts { display: flex; gap: .2rem; justify-content: center; margin-top: .25em; }
.cmsn-chip3__act {
  flex: 1; height: 1.5rem; padding: 0; border: 1px solid var(--cmsn-line);
  background: #fff; color: #2B1B10; font: inherit; font-size: .8rem; line-height: 1;
  cursor: pointer; border-radius: 2px;
}
.cmsn-chip3__act[aria-pressed="true"] { background: #2B1B10; color: #fff; border-color: transparent; }
.cmsn-chip3__act--x:hover { border-color: #8C1D18; color: #8C1D18; }

/* Artwork chosen but NOT on this piece — visible, clearly excluded, one click in. */
.cmsn-chip3--off { opacity: .62; border-style: dashed; }
.cmsn-chip3--off .cmsn-chip3__thumb { filter: grayscale(1); }
.cmsn-chip3__off {
  display: block; font-size: .64rem; letter-spacing: .03em; text-transform: uppercase;
  opacity: .7; margin-top: .2em;
}
.cmsn-chip3__add {
  width: 100%; margin-top: .25em; padding: .3em 0; border: 1px solid var(--color-heading, #2B1B10);
  background: #fff; color: #2B1B10; font: inherit; font-size: .68rem; font-weight: 700;
  cursor: pointer; border-radius: 2px;
}
.cmsn-chip3__add:hover { background: var(--color-heading, #2B1B10); color: #fff; }

/* THE SHOP'S OWN FACE, now that the file is in the theme. Fallbacks stay
   behind it because GBCLeather carries letters, digits and space only — any
   punctuation the customer types falls back, and a legible fallback is better
   than a missing glyph box. */
.cmsn-piece__ctext, .cmsn-piece__ttext {
  font-family: "GBCLeather", "Playfair Display", Georgia, "Times New Roman", serif;
}
.cmsn-piece__ctext { font-weight: 400; letter-spacing: .01em; }
.cmsn-piece__ttext { font-weight: 400; letter-spacing: .10em; text-transform: uppercase; }

/* ===========================================================================
   FINAL PASS — visible scrollbar, obvious selection, engraved lettering
=========================================================================== */

/* THE SCROLLBAR IS ALWAYS THERE, expanded only.
   macOS hides overlay scrollbars until you move, which reads as "this is all
   there is" — at 2x and 3x the belt continues off-screen and nothing said so.
   A permanent track says the preview scrolls before the customer has to
   discover it. Horizontal only: the drawing is fitted vertically, so a
   vertical bar would be a scrollbar for nothing. */
.cmsn-preview.is-expanded .cmsn-preview__scroll {
  overflow-x: scroll;
  overflow-y: hidden;
  /* auto, EXPLICITLY, to override the `thin` on the base rule. Chrome honors
     EITHER the standard properties OR the ::-webkit-scrollbar pseudo-elements,
     never both, and any non-initial `scrollbar-width` sends it down the
     standard path — which on macOS is an overlay bar that stays invisible
     until you move. Putting the property back to its initial value re-enables
     the pseudo-elements below, and a styled webkit scrollbar reserves real
     layout space and is drawn all the time, which is the requirement. */
  scrollbar-width: auto;
  scrollbar-color: auto;
  padding-bottom: 2px;
}
.cmsn-preview.is-expanded .cmsn-preview__scroll::-webkit-scrollbar {
  height: 12px;
  -webkit-appearance: none;
  appearance: none;
}
.cmsn-preview.is-expanded .cmsn-preview__scroll::-webkit-scrollbar-track {
  background: rgba(0,0,0,.08); border-radius: 999px;
}
.cmsn-preview.is-expanded .cmsn-preview__scroll::-webkit-scrollbar-thumb {
  background: var(--color-leather, #7A4B22); border-radius: 999px;
  border: 3px solid var(--color-background, #fff);
}
.cmsn-preview.is-expanded .cmsn-preview__scroll::-webkit-scrollbar-thumb:hover {
  background: var(--color-heading, #2B1B10);
}

/* SELECTED, in words and in weight. */
.cmsn-chip3 { position: relative; }
/* Matches the Story-step library tile: heavy border, tinted plate, obvious. */
.cmsn-chip3.is-on {
  border: 2px solid var(--color-heading, #2B1B10);
  box-shadow: inset 0 0 0 2px var(--color-leather, #7A4B22), 0 0 0 3px rgba(43,27,16,.18);
  background: color-mix(in srgb, var(--color-leather, #7A4B22) 7%, #fff);
  padding: calc(1.35rem - 1px) calc(.4rem - 1px) calc(.4rem - 1px);
}
/* SELECTED, IN FULL.
   The badge used to sit half outside the tile on a 9.4rem chip inside a strip
   that clips its overflow — so the word was cut at both ends. It is now a band
   ACROSS THE TOP of the tile, inside it, where a nine-character word has the
   whole tile width to sit in and nothing can crop it. The tile grew a little
   and reserves the band's height whether or not it is selected, so selecting
   a piece does not make the row jump. */
.cmsn-chip3__sel {
  position: absolute; top: 0; left: 0; right: 0;
  background: var(--color-heading, #2B1B10); color: #fff;
  font: 700 .62rem/1.7 var(--font-heading-family, inherit);
  letter-spacing: .12em; text-align: center;
  border-radius: 2px 2px 0 0;
  z-index: 2; pointer-events: none;
  overflow: visible; white-space: nowrap;
}
/* The artwork stays visible and white-plated whatever the selection state. */
.cmsn-chip3.is-on .cmsn-chip3__thumb { background: #fff !important; opacity: 1; }

/* Lettering: the face only. Fill vs stroke is decided by the LETTERING RULE
   and written onto the element as real SVG paint attributes — never here,
   because a CSS weight would look like line work without being line work. */
.cmsn-piece__ctext, .cmsn-piece__ttext {
  font-family: "GBCLeather", "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 400;
}
.cmsn-piece__ttext { letter-spacing: .06em; }


/* THE INSERTION LINE. A bold black rule exactly where the tile will land —
   including at the ends of the row, where highlighting a neighbor could never
   have said which side. */
.cmsn-dropline {
  flex: 0 0 auto; align-self: stretch; width: 4px; margin: 0 -2px;
  background: #000; border-radius: 2px; pointer-events: none;
}

/* FIXED LETTERING TILES. Present in the strip so artwork can be ordered around
   them, and visibly not artwork: no drag, no controls, a pin instead. */
.cmsn-chip3--fixed {
  cursor: default; border-style: dashed;
  background: color-mix(in srgb, var(--color-leather, #7A4B22) 5%, #fff);
}
.cmsn-chip3__pin {
  position: absolute; top: 0; left: 0; right: 0;
  background: #7A5C3E; color: #fff;
  font: 700 .58rem/1.7 var(--font-heading-family, inherit);
  letter-spacing: .12em; text-align: center; border-radius: 2px 2px 0 0;
}
.cmsn-chip3__lettering {
  display: flex; align-items: center; justify-content: center;
  height: 5.4rem; padding: .2rem; background: #fff; border-radius: 2px;
  font-family: "GBCLeather", Georgia, serif; font-size: 1.05rem;
  color: #111; overflow: hidden; text-align: center; line-height: 1.15;
  word-break: break-word;
}

/* ===========================================================================
   HAND PAINTING — one table per piece
=========================================================================== */
.cmsn-painttable { margin-top: 1rem; }
.cmsn-painttable[hidden] { display: none; }
.cmsn-painttable__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; margin: 0 0 .35rem;
}
.cmsn-painttable__title {
  font: 700 .8rem/1.3 var(--font-heading-family, inherit);
  letter-spacing: .06em; text-transform: uppercase;
}
.cmsn-selectall {
  border: 1px solid var(--cmsn-line); background: var(--color-surface);
  color: inherit; font: inherit; font-size: .74rem; font-weight: 700;
  padding: .3em .7em; border-radius: 2px; cursor: pointer; white-space: nowrap;
}
.cmsn-selectall:hover { border-color: var(--color-leather, #7A4B22); }
.cmsn-selectall[aria-pressed="true"] {
  background: var(--color-heading, #2B1B10); color: #fff; border-color: transparent;
}
.cmsn-painttable__both { margin: .9rem 0 0; }
.cmsn-painttable__both[hidden] { display: none; }
.cmsn-selectall--both { width: 100%; padding: .55em .7em; font-size: .8rem; }

/* LETTERING REVIEW in Materials — the same shape as the painting tables,
   because it sits beside them and is the same kind of list: what is going onto
   which piece. Read-only, so no control affordances. */
.cmsn-letterreview { margin-top: .75rem; }
.cmsn-letterrow {
  display: flex; align-items: baseline; gap: .75rem;
  cursor: default; padding: .5rem .6rem;
}
.cmsn-letterrow__place {
  flex: 0 0 auto; font-size: .78rem; font-weight: 700;
  letter-spacing: .04em; opacity: .72; min-width: 7.5rem;
}
.cmsn-letterrow__text {
  flex: 1 1 auto; min-width: 0;
  font-family: "GBCLeather", Georgia, serif; font-size: 1.15rem; line-height: 1.25;
  color: var(--color-heading, #2B1B10); word-break: break-word;
}
.cmsn-linkbtn {
  border: 0; background: none; padding: 0; font: inherit; color: inherit;
  text-decoration: underline; cursor: pointer;
}

/* ORDER ARROWS on the tile — replacing drag, which no phone and no keyboard
   could reach. Disabled at the ends rather than hidden, so the row does not
   reflow as pieces arrive at the edges. */
.cmsn-chip3__order { display: flex; gap: 2px; margin-bottom: .25em; }
.cmsn-chip3__ord {
  flex: 1; height: 1.4rem; padding: 0; border: 1px solid var(--cmsn-line);
  background: #fff; color: #2B1B10; font: inherit; font-size: .8rem; line-height: 1;
  cursor: pointer; border-radius: 2px;
}
.cmsn-chip3__ord:hover:not([disabled]) { border-color: var(--color-leather, #7A4B22); }
.cmsn-chip3__ord[disabled] { opacity: .3; cursor: default; }

/* ===========================================================================
   HAND-PAINT COLOR — the right-hand half of one decision
=========================================================================== */
.cmsn-paintitem { display: flex; align-items: center; gap: .6rem; }
.cmsn-paintitem__pick { display: flex; align-items: center; gap: .6rem; flex: 1 1 auto; min-width: 0; cursor: pointer; }
.cmsn-paintitem__color { display: flex; align-items: center; gap: .4rem; flex: 0 0 auto; }
.cmsn-swatch {
  width: 1.25rem; height: 1.25rem; border-radius: 3px; flex: 0 0 auto;
  border: 1px solid rgba(0,0,0,.28); box-shadow: inset 0 0 0 1px rgba(255,255,255,.18);
}
/* Nothing chosen yet reads as an empty well, not as a color. */
.cmsn-swatch[data-empty] {
  background: repeating-linear-gradient(45deg, #eee 0 4px, #fff 4px 8px) !important;
}
.cmsn-select--color { width: auto; min-width: 8.5rem; padding: .3em .5em; font-size: .8rem; }
/* Artwork whose colors are not a choice says so instead of offering one. */
.cmsn-paintitem__fixed {
  flex: 0 0 auto; font-size: .72rem; font-style: italic; opacity: .7;
  padding: .3em .5em; border: 1px dashed var(--cmsn-line); border-radius: 2px;
}

/* The house font, offered as a file rather than described in prose. */
.cmsn-fontdl { margin: .55rem 0 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem; }
.cmsn-fontdl__note { font-size: .78rem; opacity: .65; }

/* ===========================================================================
   TWO TILE ROWS — ARTWORK, AND THE BACKGROUNDS THAT RUN BEHIND IT
   ---------------------------------------------------------------------------
   The rows say two different things. The top one is the sequence along the
   leather; the bottom one is what sits behind that sequence, and each of its
   tiles is anchored to the GAP it was inserted at rather than floating in a
   row of its own concern.
=========================================================================== */
.cmsn-row__scroll { overflow-x: auto; overflow-y: visible; }

/* The cell under a piece: what is behind it, or an offer to put something
   there. It is a plain grid cell — no absolute position and no measured
   offset, because the column already says which piece it belongs to. */
.cmsn-bgslot { width: 5.4rem; display: flex; flex-direction: column; gap: .3rem; }
/* The lettering has no artwork behind it, and nor does a trailing orphan
   marker. The cell is still emitted so the next column does not slide up
   into the background row. */
.cmsn-bgslot--none { min-height: 0; }
/* A background tile is the same tile, read as a ground rather than a figure.
   A dashed edge and the column it sits in say what it is; the old row needed
   a printed caption per tile to say where it sat, and that caption is gone
   with the gap model that needed it. */
.cmsn-chip3--bg { background: #FAF6F0; border-style: dashed; width: 100%; }
/* Which piece this background sits behind — the arrows move it to the
   next column, which is the next piece along the leather. */
.cmsn-chip3__bgmove {
  display: flex; align-items: center; justify-content: center; gap: .2rem; margin-top: .2em;
}


/* Three layers need three buttons, so they are narrower than two were. */
.cmsn-chip3__roles { display: flex; gap: 2px; margin-top: .25em; }
.cmsn-chip3__role { font-size: .58rem; padding: .18em 0; }

/* ---- ROOM FOR TWO ROWS ----
   A second row of tiles needs real height and the leather must not pay for it.
   The panel becomes a COLUMN: the drawing takes the room it needs at the top
   and the tiles take what is left, each scrolling within itself. Before this
   the leather was allowed 86vh minus a fixed 150px — far more than a belt
   drawing ever uses — and the rows were left with whatever fell off the
   bottom, which is why the background row landed below the fold.

   The scrolling box keeps its own scrollbar exactly as it did: the rule that
   makes it visible is untouched, and it is still the element that scrolls. */
.cmsn-preview.is-expanded {
  height: 86vh; min-height: 520px;
  display: flex; flex-direction: column;
}
.cmsn-preview.is-expanded .cmsn-preview__scroll {
  flex: 0 0 auto;
  max-height: min(34vh, 260px);
}
.cmsn-preview.is-expanded .cmsn-rows {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
}
/* The tiles are the thing being operated; they keep their size. What gives is
   the space around them. */
.cmsn-preview.is-expanded .cmsn-row__label { margin-bottom: .15em; }

/* ===========================================================================
   ARTWORK LIBRARY TILE TEXT — READABLE, NOT WHISPERED
   ---------------------------------------------------------------------------
   THE LABELS WERE INHERITING THE LINEWORK COLOR. `color` is set on the grid
   so the artwork's currentColor strokes follow the chosen leather — that is
   what .cmsn-art--dark is for — but color inherits, so on a dark leather the
   NAME under each tile was being painted #F4EFE7 on a white tile. Near-white
   ink on white: measured contrast 1.11 to 1. The supporting lines were also
   held at 62–65% opacity, which fades ink toward whatever is behind it.

   The tile is white whatever the leather is, so its text is given its own
   color and stops inheriting one meant for the drawing. The thumbnails keep
   theirs — they are the artwork, and they already opt out on their own.

   Nothing about the tile's size, its artwork, its selection behavior or its
   ordering changes: this is contrast only.
=========================================================================== */
.cmsn-art__tile { color: #1B120C; }
.cmsn-art--dark .cmsn-art__tile { color: #1B120C; }
.cmsn-art__name { color: #1B120C; font-weight: 700; }
/* Opacity fades the ink toward the background; a darker color keeps it ink. */
.cmsn-art__tile .cmsn-art__where { opacity: 1; color: #4A3524; font-weight: 600; }
.cmsn-art__tile .cmsn-art__meta  { opacity: 1; color: #4A3524; }
.cmsn-art__tile .cmsn-art__role  { opacity: 1; color: #3A2A1C; }
/* SELECTED sits on the leather color and only needs to stay put. */
.cmsn-art__chosen { color: #fff; }
/* The thumbnail still takes the leather color, because it IS the artwork. */
.cmsn-art__grid .cmsn-art__thumb { color: #1B120C; }
.cmsn-art--dark .cmsn-art__grid .cmsn-art__thumb { color: #F4EFE7; }

/* The house face, shown as itself in the liner font picker. */
.cmsn-fontsample--house {
  font-family: "GBCLeather", "Rockwell", Georgia, serif; font-size: 1.15rem; letter-spacing: .04em;
}

/* ===========================================================================
   THE CHARACTERS THE HOUSE FACE CAN CUT
   ---------------------------------------------------------------------------
   Shown in the lettering the customer is reviewing, in the face itself, so
   what they see is what the machine will cut. Replaces the font download: the
   customer needs to know which characters exist, not to own the file.
=========================================================================== */
.cmsn-charset {
  margin-top: .7rem; padding: .7rem .8rem;
  border: 1px solid var(--cmsn-line); border-radius: 3px; background: #FCFAF6;
}
.cmsn-charset__head {
  margin: 0 0 .5em; font-size: .72rem; letter-spacing: .07em; text-transform: uppercase;
  font-weight: 700; color: #3A2A1C;
}
.cmsn-charset__row { display: flex; gap: .7rem; align-items: baseline; margin-bottom: .3em; }
.cmsn-charset__label {
  flex: 0 0 5.2rem; font-size: .7rem; text-transform: uppercase; letter-spacing: .05em;
  color: #4A3524;
}
/* Set in the real face: seeing the shapes is half the answer. */
.cmsn-charset__chars {
  font-family: "GBCLeather", Georgia, serif; font-size: 1rem; line-height: 1.5;
  letter-spacing: .02em; color: #1B120C; word-break: break-word;
}
.cmsn-charset__none {
  margin: .5em 0 0; font-size: .76rem; color: #4A3524; font-style: italic;
}
.cmsn-charset__warn {
  margin: .55em 0 0; padding: .5em .6em; font-size: .78rem; font-weight: 600;
  color: #7A2E12; background: #FDF1EA; border-left: 3px solid #7A2E12; border-radius: 2px;
}

/* ===========================================================================
   THE EXPAND CONTROL SAYS WHAT IT DOES
   ---------------------------------------------------------------------------
   The corners icon alone was an affordance for people who already knew the
   pattern; the artwork workspace sat behind it unfound. Words on the same
   button — not a second control, not a banner — in the site's own quiet
   register, and big enough to be a tap target on a phone.
=========================================================================== */
.cmsn-preview__expand {
  display: inline-flex; align-items: center; gap: .45rem;
  width: auto; height: auto; padding: .45em .75em;
  border: 1px solid var(--color-leather, #7A4B22); border-radius: 2px;
  background: var(--color-leather, #7A4B22); color: #fff;
  font: inherit; cursor: pointer;
}
.cmsn-preview__expand:hover { background: var(--color-heading, #2B1B10); border-color: var(--color-heading, #2B1B10); }
.cmsn-preview__expandtxt {
  font-size: .72rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  white-space: nowrap;
}
/* Expanded, the button is a way back and needs no sales pitch. */
.cmsn-preview.is-expanded .cmsn-preview__expand {
  background: transparent; color: inherit; border-color: var(--cmsn-line);
}
@media (max-width: 480px) {
  /* Still words, just shorter ones — never back to a bare icon. */
  .cmsn-preview__expandtxt { font-size: .68rem; letter-spacing: .05em; }
}

/* ===========================================================================
   THE POSITION CONTROLS ARE ALWAYS REACHABLE
   ---------------------------------------------------------------------------
   With enough tiles the control bar was pushed below the fold of the panel and
   the customer had to hunt past a long strip to find the arrows that move the
   artwork. The TILES scroll instead: the bar is pinned to the bottom of the
   expanded panel, the rows take what room is left, and the buttons keep their
   size. Nothing about zoom or the preview's own scrollbar changes.
=========================================================================== */
.cmsn-preview.is-expanded .cmsn-artctl {
  flex: 0 0 auto;                    /* the rows give up room, never this */
  margin-top: .5rem;
  background: var(--color-surface, #fff);
  box-shadow: 0 -6px 10px -8px rgba(0,0,0,.35);
}
/* The buttons keep their size; the tile strip is what yields. */
.cmsn-artctl__move .btn, .cmsn-artctl .btn { min-width: 2.4rem; }

/* A caveat the customer needs BEFORE they upload, set apart from the ordinary
   hint above it without being an alarm. */
.cmsn-field__hint--note {
  display: block; margin-top: .4em; padding-left: .6em;
  border-left: 2px solid var(--color-leather, #7A4B22);
  color: #4A3524; font-style: italic;
}

/* ===========================================================================
   THE CONCEPT PREVIEW HEADER DOES NOT MOVE
   ---------------------------------------------------------------------------
   The panel is already a flex column when expanded, and the header was simply
   the first child of it — so it took part in the column's own overflow and
   could be scrolled with everything else. Making it flex: 0 0 auto pins it: the
   column gives it its height first and the scrolling region takes what is
   left, which is the arrangement in which content cannot pass it at all.

   It is NOT sticky and it is NOT raised on z-index. Both of those let the
   content travel UNDER the header and rely on paint order to hide it, which is
   where the half-scrolled tile edges and translucent seams come from. Content
   that is outside the scrolling box has nothing to slide across.
=========================================================================== */
.cmsn-preview.is-expanded .cmsn-preview__bar {
  flex: 0 0 auto;
  margin-bottom: .5rem;
  /* Opaque, and drawn on the panel's own ground, so nothing shows through it
     even for the frame in which a redraw is in flight. */
  background: var(--color-surface, #fff);
  border-bottom: 1px solid var(--cmsn-line);
  padding-bottom: .5rem;
}
/* The scrolling regions are the ones BELOW it, and they clip their own
   content — the header is not in their box, so there is nothing to overlap. */
.cmsn-preview.is-expanded .cmsn-preview__scroll,
.cmsn-preview.is-expanded .cmsn-rows { overscroll-behavior: contain; }

/* ===========================================================================
   THE TILE ROWS ARE AS TALL AS THE TILES, AND NO TALLER
   ---------------------------------------------------------------------------
   The background track is absolutely positioned so its slots can stand under
   the gaps they name, and an absolutely positioned child contributes no height
   — so the track's height is set from JS. It used to be set to the deepest
   STACK of slots, and slots stacked downwards whenever two would collide; with
   seven tiles that reserved a tall empty strip below a row that had one tile
   in it. There is one row now, and the track is one slot tall.

   These rules stop the surrounding boxes adding their own slack on top.
=========================================================================== */
/* No stretch: a short row stays short instead of filling the column. */
.cmsn-preview.is-expanded .cmsn-rows { align-content: start; }
.cmsn-row__grid { align-items: start; }
/* The gap between the two rows is a separator, not a gutter. */
.cmsn-preview.is-expanded .cmsn-row__grid { padding-bottom: .15rem; }

/* ===========================================================================
   THE CONCEPT PREVIEW PASSES IN FRONT OF THE SITE HEADER
   ---------------------------------------------------------------------------
   The site header is sticky at z-index 100 and the preview column had no
   stacking order of its own, so on narrow screens — where the column scrolls
   normally rather than sticking — the preview slid UNDER the header and the
   header's ground showed through the top of the drawing.

   The column is given a position and a z-index one above the header, so the
   two overlap the right way round. The panel already paints an opaque ground,
   which is what stops any bleed-through where they cross. The expanded
   overlay stays above both at 200, and the mobile action bars below at 60/90.
=========================================================================== */
.cmsn-aside { position: relative; z-index: 101; }
@media (min-width: 1024px) { .cmsn-aside { position: sticky; top: 96px; z-index: 101; } }
/* Opaque, and its own layer, so nothing behind it can show through the seam. */
.cmsn-preview { position: relative; z-index: 1; background: var(--color-surface); }

/* The color choice sits to the LEFT of the piece it applies to, on the same
   line, because the checkbox and the word are one question. */
.cmsn-colorpick { display: inline-flex; align-items: center; gap: .45em; cursor: pointer; }
.cmsn-colorpick input { margin: 0; }

/* Said next to the field the character was removed from, not in a summary at
   the end — the customer needs to know while they are still typing the name. */
.cmsn-letternote {
  margin: .3em 0 0; font-size: .78rem; font-weight: 600; color: #7A2E12;
}
.cmsn-letternote[hidden] { display: none; }


/* ---------------------------------------------------------- PAINTED EDGES
   Its own block under the artwork list, because it is a different question
   about a different part of the belt. Swatches rather than words alone: the
   customer is choosing a color, and a color is easier to see than to read. */
.cmsn-edgepaint { margin-top: 1.1rem; padding-top: 1rem; border-top: 1px solid var(--cmsn-line); }
.cmsn-edgepaint__title {
  font-size: 0.72rem; letter-spacing: 0.11em; text-transform: uppercase;
  font-weight: 700; margin: 0 0 0.2rem;
}
.cmsn-edgepaint__opts { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.7rem; }
.cmsn-opt--swatch { flex: 0 0 auto; }
.cmsn-opt--swatch .cmsn-opt__box {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.5rem 0.85rem; border: 1px solid var(--cmsn-line);
  border-radius: var(--cmsn-radius); background: var(--color-surface);
  font-size: 0.9rem; cursor: pointer;
}
.cmsn-opt--swatch input { position: absolute; opacity: 0; width: 0; height: 0; }
.cmsn-opt--swatch input:checked + .cmsn-opt__box {
  border-color: var(--color-leather); box-shadow: inset 0 0 0 1px var(--color-leather);
}
.cmsn-opt--swatch input:focus-visible + .cmsn-opt__box { outline: 2px solid var(--color-brass); outline-offset: 2px; }
.cmsn-swatch {
  width: 16px; height: 16px; border-radius: 3px; display: inline-block;
  border: 1px solid rgba(0,0,0,.25);
}
.cmsn-swatch--none {
  background: repeating-linear-gradient(45deg, #fff 0 4px, #E2D9C8 4px 8px);
}
/* How many copies of this artwork the tick covers. */
.cmsn-paintitem__count {
  display: block; font-size: 0.74rem; color: var(--color-leather); font-weight: 600; margin-top: .1rem;
}

/* Said to a screen reader, not drawn. */
.cmsn-sr {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}
/* A BACKGROUND TILE IS A PICTURE AND ITS CONTROLS. The artwork's name under a
   background tile repeated the same word down the whole row; the foreground
   tiles keep theirs, where the pieces genuinely differ from one another. */
.cmsn-chip3--bg .cmsn-chip3__name { display: none; }

/* The notice under the concept drawing. Quiet: it is a statement of fact, not
   something the customer needs to read before choosing a buckle. */
.cmsn-preview__rights {
  margin: 0.55rem 0 0;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--cmsn-ink, inherit);
  opacity: 0.45;
}

/* A FROZEN CONTROL, not a missing one. Visibly present, visibly unavailable. */
.cmsn-chip3__act.is-frozen {
  opacity: 0.4; cursor: not-allowed;
}
.cmsn-chip3__act.is-frozen:hover { background: inherit; }

/* THE REFUSAL, at the foot of the screen and then gone. */
.cmsn-toast {
  position: fixed; left: 50%; bottom: 1.25rem; transform: translateX(-50%) translateY(0.5rem);
  z-index: 300; max-width: min(46rem, calc(100vw - 2rem));
  padding: 0.75rem 1.1rem; border-radius: var(--cmsn-radius);
  font-size: 0.9rem; line-height: 1.35; text-align: center;
  opacity: 0; pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
  box-shadow: 0 6px 22px rgba(0,0,0,.22);
}
.cmsn-toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }
.cmsn-toast--warn { background: #8C1D18; color: #fff; }
@media (prefers-reduced-motion: reduce) { .cmsn-toast { transition: none; } }

/* AN EMPTY BACKGROUND POSITION. Same footprint as a filled one so the row
   holds its shape, and plainly an invitation rather than a broken tile. */
.cmsn-bgslot--empty { align-items: stretch; }
.cmsn-bgempty {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .2rem; min-height: 3.4rem; padding: .45rem .35rem;
  border: 1px dashed var(--cmsn-line); border-radius: var(--cmsn-radius);
  background: transparent; color: var(--color-leather); cursor: pointer;
  font: inherit; text-align: center;
}
.cmsn-bgempty:hover, .cmsn-bgempty:focus-visible {
  border-color: var(--color-leather); background: rgba(0,0,0,.02);
}
.cmsn-bgempty__plus { font-size: 1.25rem; line-height: 1; opacity: .65; }
.cmsn-bgempty__label { font-size: .68rem; letter-spacing: .03em; line-height: 1.15; }

/* "SELECT BACKGROUND" — the refusal, in the slot that was pressed.
   The shop's error red, the same one .cmsn-alert--error uses, which measures
   8.6:1 against the panel. Bold and not italic, because it is an instruction
   rather than an aside. */
.cmsn-bgempty__need {
  margin: .3rem 0 0; padding: 0 .2rem;
  color: #8C1D18; font-size: .68rem; font-weight: 700;
  letter-spacing: .03em; line-height: 1.2; text-align: center;
}
.cmsn-bgslot--empty.is-needed .cmsn-bgempty { border-color: #8C1D18; }

/* THE CONTROLS AND THE KEY, ON ONE ROW.
   The legend explains the marks on the drawing, so it belongs beside the
   controls rather than in a row of its own above the artwork tiles — that row
   was costing the customer the vertical space they most need. */
.cmsn-ctlrow {
  display: flex; align-items: flex-start; gap: 1rem; flex-wrap: wrap;
  margin-top: .5rem;
}
.cmsn-ctlrow .cmsn-artctl { flex: 1 1 22rem; min-width: 0; margin: 0; }
.cmsn-ctlrow .cmsn-legend {
  flex: 0 1 auto; display: flex; flex-direction: column; gap: .25rem;
  margin: 0; padding-top: .2rem;
}
.cmsn-ctlrow .cmsn-artctl[hidden] + .cmsn-legend { flex-direction: row; flex-wrap: wrap; gap: .9rem; }

/* ONE LINE where the screen allows it. Wrapping on a phone is correct; a
   second paragraph on a laptop is not. */
.cmsn-preview__note--one { margin: .55rem 0 0; }
@media (min-width: 900px) {
  .cmsn-preview__note--one { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}

/* ===================== START FROM ONE OF MY DESIGNS =====================
   A row at the top of Step 02 and a dialog over the page. Not a page: the
   customer never leaves the studio, so there is nothing to come back from and
   no second configurator to keep in step with this one. */
.cmsn-tplstart{display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding:14px 16px;margin:0 0 22px;border:1px solid var(--cmsn-line,#D8CBB8);
  border-radius:6px;background:rgba(255,255,255,.55)}
.cmsn-tplstart[hidden]{display:none}
.cmsn-tplstart__text{flex:1 1 260px;min-width:0}
.cmsn-tplstart__label{display:block;font-weight:600;font-size:.95rem}
.cmsn-tplstart__hint{display:block;font-size:.8rem;opacity:.72;margin-top:2px}
.cmsn-tplstart__chosen{flex:1 1 100%;margin:6px 0 0;font-size:.82rem;opacity:.8}

/* The dialog itself. Fixed, so it covers the page it was opened from rather
   than pushing the form about underneath it. */
/* `display:flex` ON A CLASS BEATS `[hidden]` FROM THE BROWSER, which is how a
   closed dialog came to cover Step 02 invisibly and swallow every click at the
   top of the step — the button underneath it could not be pressed and nothing
   about the page looked wrong. Anything that sets display on an element the
   markup hides with `hidden` has to say so. */
.cmsn-tplmodal{position:fixed;inset:0;z-index:120;display:flex;align-items:center;
  justify-content:center;padding:18px;background:rgba(21,16,12,.55)}
.cmsn-tplmodal[hidden]{display:none}
.cmsn-tplmodal__sheet{width:100%;max-width:760px;max-height:86vh;display:flex;
  flex-direction:column;background:var(--cmsn-bg,#F7F2EA);border-radius:8px;
  box-shadow:0 18px 50px rgba(21,16,12,.35);overflow:hidden}
.cmsn-tplmodal__head{display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:14px 16px;border-bottom:1px solid var(--cmsn-line,#D8CBB8)}
.cmsn-tplmodal__title{margin:0;font-size:1.05rem}
.cmsn-tplmodal__x{border:0;background:none;font-size:1.5rem;line-height:1;
  cursor:pointer;padding:0 4px;color:inherit}
.cmsn-tplmodal__body{padding:14px 16px;overflow-y:auto;flex:1 1 auto}
.cmsn-tplmodal__foot{padding:12px 16px;border-top:1px solid var(--cmsn-line,#D8CBB8)}

/* One card per family, with its ranks inside it — two designs to choose
   between and then a rank, which is the decision the customer is making. */
.cmsn-tplfam{padding:12px 0;border-bottom:1px solid rgba(21,16,12,.1)}
.cmsn-tplfam:last-child{border-bottom:0}
.cmsn-tplfam__name{margin:0;font-size:1rem}
.cmsn-tplfam__sub{font-size:.78rem;text-transform:uppercase;letter-spacing:.06em;opacity:.6}
.cmsn-tplfam__desc{margin:4px 0 10px;font-size:.85rem;opacity:.85}
.cmsn-tplfam__ranks{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
/* THE RANK IS A CHOICE ON THE CARD, not a row of alternatives to the design.
   A family that does not vary has no label and no select, so nothing here
   appears beside a single button. */
.cmsn-tplfam__rlbl{font-size:.72rem;text-transform:uppercase;letter-spacing:.06em;opacity:.6}
.cmsn-tplfam__rsel{border:1px solid var(--cmsn-line,#D8CBB8);background:#fff;border-radius:4px;
  padding:7px 10px;font:inherit;font-size:.85rem;min-width:11rem}
.cmsn-tplpick{border:1px solid var(--cmsn-line,#D8CBB8);background:#fff;border-radius:4px;
  padding:7px 12px;font:inherit;font-size:.85rem;cursor:pointer}
.cmsn-tplpick:hover{border-color:var(--cmsn-ink,#15100C)}
.cmsn-tplmodal__note{font-size:.8rem;opacity:.75;margin:10px 0 0}
@media (max-width:600px){
  .cmsn-tplstart{align-items:flex-start}
  .cmsn-tplfam__ranks{flex-direction:column;align-items:stretch}
  .cmsn-tplfam__rsel{width:100%}
}

/* ===================== WHAT THE CUSTOMER SAYS ABOUT A PICTURE =============
   Three fields per uploaded image, inside its own card. Deliberately plain:
   the card already carries a thumbnail, a size, a status and a role toggle,
   and a boxed, bordered sub-form on top of that reads as a second application
   form rather than two questions and a note. */
.cmsn-artmeta {
  margin-top: .7rem;
  padding-top: .7rem;
  border-top: 1px solid rgba(107, 90, 72, .18);
}
.cmsn-artmeta__label {
  display: block;
  font-size: .82rem;
  font-weight: 600;
  color: var(--color-ink, #2B2118);
  margin: .55rem 0 .15em;
}
.cmsn-artmeta .cmsn-artmeta__label:first-child { margin-top: 0; }
.cmsn-artmeta__hint {
  display: block;
  font-size: .75rem;
  line-height: 1.45;
  opacity: .66;
  margin: 0 0 .35em;
}
.cmsn-artmeta .cmsn-input,
.cmsn-artmeta .cmsn-select,
.cmsn-artmeta .cmsn-textarea { width: 100%; box-sizing: border-box; margin: 0; }
.cmsn-artmeta .cmsn-textarea { min-height: 66px; margin-top: 0; }

/* REQUIRED IS MARKED, NOT ENFORCED BY SURPRISE. The asterisk is decorative and
   aria-hidden; the real announcement is a visually-hidden "(required)" in the
   label, so a screen reader hears the word rather than a punctuation mark. */
.cmsn-req { color: #B3261E; font-weight: 700; }

.cmsn-artmeta__err {
  margin: .3em 0 0;
  font-size: .78rem;
  line-height: 1.45;
  color: #8C1D18;
}
.cmsn-artmeta__file {
  margin: .6em 0 0;
  font-size: .72rem;
  opacity: .55;
  word-break: break-all;
}
/* An image waiting on its own description is not uploading, and must not be
   colored as though something were wrong either — nobody has made a mistake
   yet. */
.cmsn-ref__await { color: #6B5A48; }

/* ---------------- the review's own read-back of all of it ---------------- */
.cmsn-review__art { display: flex; flex-direction: column; gap: .8rem; }
.cmsn-reviewart { display: flex; gap: .75rem; align-items: flex-start; }
.cmsn-reviewart__thumb {
  width: 64px; height: 64px; object-fit: cover; border-radius: 4px; flex: 0 0 auto;
}
.cmsn-reviewart__body { min-width: 0; }
.cmsn-reviewart__title { margin: 0; font-weight: 600; font-size: .92rem; }
.cmsn-reviewart__cat { margin: .1em 0 0; font-size: .8rem; opacity: .72; }
.cmsn-reviewart__file { margin: .1em 0 0; font-size: .72rem; opacity: .5; word-break: break-all; }
.cmsn-reviewart__vision {
  margin: .4em 0 0;
  padding-left: .7rem;
  border-left: 2px solid rgba(107, 90, 72, .3);
  font-size: .82rem;
  line-height: 1.5;
  font-style: italic;
  opacity: .85;
  white-space: pre-wrap;
}

/* ============ THE FINAL REVIEW DIALOG ============
   The piece, the choices and the agreement in one frame, because until now
   they were never on screen together: the preview sat in the aside, below the
   fold on a phone, and the agreements were a thousand words further down. */
.cmsn-final{position:fixed;inset:0;z-index:140;display:flex;align-items:center;
  justify-content:center;padding:16px;background:rgba(21,16,12,.6)}
.cmsn-final[hidden]{display:none}
.cmsn-final__sheet{width:100%;max-width:720px;max-height:92vh;display:flex;
  flex-direction:column;background:var(--cmsn-bg,#F7F2EA);border-radius:8px;
  box-shadow:0 18px 50px rgba(21,16,12,.4);overflow:hidden}
.cmsn-final__head{display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:14px 16px;border-bottom:1px solid var(--cmsn-line,#D8CBB8)}
.cmsn-final__title{margin:0;font-size:1.1rem}
.cmsn-final__x{border:0;background:none;font-size:1.6rem;line-height:1;cursor:pointer;
  padding:0 6px;color:inherit}
.cmsn-final__body{padding:14px 16px;overflow-y:auto;flex:1 1 auto}
.cmsn-final__body:focus{outline:none}
/* THE FOOT DOES NOT SCROLL. The two choices stay on screen however long the
   terms are, so nobody has to scroll to find out how to get out of a dialog. */
.cmsn-final__foot{display:flex;gap:10px;flex-wrap:wrap;padding:12px 16px;
  border-top:1px solid var(--cmsn-line,#D8CBB8);background:var(--cmsn-bg,#F7F2EA)}
.cmsn-final__foot .btn{flex:1 1 180px}
.cmsn-final__h{margin:1.4rem 0 .6rem;font-size:.78rem;letter-spacing:.08em;
  text-transform:uppercase;opacity:.75}
/* min-width:0 ALL THE WAY DOWN, OR THE CLOSE-UP BLOWS THE DIALOG OPEN.
   A grid or flex item defaults to min-width:auto, which is its CONTENT's
   width — and the close-up strip is as wide as the belt is long. Measured:
   the sheet rendered 2698px wide inside a 1180px viewport, the "whole piece"
   view inherited that width through width:100%, and max-width:720px on the
   sheet did nothing because the content refused to shrink. */
.cmsn-final__sheet,.cmsn-final__body,.cmsn-final__preview,.cmsn-final__piece,
.cmsn-final__whole,.cmsn-final__detail{min-width:0}
.cmsn-final__whole,.cmsn-final__detail{max-width:100%}
.cmsn-final__preview{display:grid;gap:10px}
.cmsn-final__piece{margin:0}
/* THE WHOLE PIECE, FITTED. Honest proportions; thirty-odd pixels tall for a
   belt, because that is what a belt is. */
.cmsn-final__whole svg{width:100%;height:auto;display:block;
  border:1px solid var(--cmsn-line,#D8CBB8);border-radius:6px;background:#fff}
/* AND THE SAME DRAWING AT A HEIGHT SOMEBODY CAN READ. width:auto against a
   fixed height lets the viewBox decide the width, so the strip is as long as
   the belt is and scrolls sideways instead of shrinking to a line. */
.cmsn-final__detail{margin-top:8px;overflow-x:auto;overflow-y:hidden;
  border:1px solid var(--cmsn-line,#D8CBB8);border-radius:6px;background:#fff;
  -webkit-overflow-scrolling:touch}
.cmsn-final__detail:focus-visible{outline:2px solid var(--color-leather,#7A4A2C);
  outline-offset:2px}
.cmsn-final__detail svg{width:auto;max-width:none;display:block}

/* ---- THE GRAIN ONLY EXISTS WHERE IT CAN BLEND ----
   The rect is painted with mix-blend-mode:soft-light over the leather. Where
   that is unsupported the un-blended result is not "no grain": feColorMatrix
   emits mid-gray at up to ~0.28 alpha, so source-over lays a flat gray wash
   across the whole strap and desaturates the dyed-leather color the
   configurator exists to show. A gray veil is a worse answer than no
   texture, so the rect is hidden by default and only turned on where the
   blend works. */
.cmsn-grain{display:none}
@supports (mix-blend-mode: soft-light){
  .cmsn-grain{display:block;mix-blend-mode:soft-light}
}
/* AND NONE OF IT IN FORCED COLORS. SVG presentation-attribute fills are not
   substituted in forced-colors mode, so a high-contrast user would get grain,
   burnish and specular wash with no way to turn them off. Decoration goes;
   the drawing stays. */
@media (forced-colors: active){
  .cmsn-grain{display:none}
}
.cmsn-final__piece figcaption{font-size:.72rem;opacity:.7;margin-top:.3em}
.cmsn-final__caption{font-size:.78rem;opacity:.8;line-height:1.5;margin:.7em 0 0}
.cmsn-final__choices{display:grid;grid-template-columns:auto 1fr;gap:.3em .9em;
  margin:0;font-size:.85rem}
.cmsn-final__choices dt{font-weight:700;opacity:.7}
.cmsn-final__choices dd{margin:0}
.cmsn-final__note{font-size:.78rem;opacity:.75;margin:.4em 0 0;line-height:1.5}

/* The numbered list. One agreement over four clauses, so the clauses are
   numbered and the box is not inside them. */
/* The budget on inline styles in the built output is pinned at 72 and this
   would have been the 73rd. Satisfied rather than raised. */
.cmsn-terms__lede{margin:-.5rem 0 1rem}
.cmsn-terms{margin:0 0 1rem;padding:0 0 0 1.4rem}
.cmsn-terms .cmsn-term--numbered{display:list-item;list-style:decimal;
  padding:.7rem .9rem;margin-bottom:.6rem}
.cmsn-terms--compact .cmsn-term--numbered{padding:.45rem .7rem;margin-bottom:.4rem;
  font-size:.95em}
.cmsn-term--numbered .cmsn-term__text{display:block}
.cmsn-term__draft{display:block;margin-top:.5em;padding:.35em .5em;font-size:.72rem;
  background:#fff3cd;border-left:3px solid #b7791f;color:#4a3410}
.cmsn-term--agree{align-items:center;border-width:2px;border-color:var(--color-leather,#7A4A2C)}
.cmsn-term--agree .cmsn-term__text{font-size:.95rem;opacity:1}
.cmsn-term--consent{margin-bottom:.3rem}
/* The page behind a modal must not scroll under it. */
html[data-cmsn-modal-open="true"]{overflow:hidden}


/* ============ A QUESTION ASKED IN THE PAGE ============
   Replaces window.prompt(), which a screen reader cannot be relied on to
   reach, a phone renders as one cramped line, and a browser stops showing
   altogether once somebody ticks "prevent additional dialogs".

   Sized for a thumb: every control is at least 44px tall, the box is full
   width on a narrow screen, and the list scrolls inside the box rather than
   pushing the buttons off the bottom. */
.cmsn-dialog { position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
.cmsn-dialog__scrim { position: absolute; inset: 0; background: rgba(28, 22, 16, .58); }
.cmsn-dialog__box { position: relative; width: 100%; max-width: 30rem;
  max-height: calc(100vh - 32px); overflow: auto;
  background: #fff; color: #231a12; border-radius: 10px; padding: 20px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .34); }
.cmsn-dialog__title { margin: 0 0 .35rem; font-size: 1.15rem; line-height: 1.25; }
.cmsn-dialog__intro { margin: 0 0 .9rem; font-size: .95rem; line-height: 1.45; color: #5b4c3e; }
.cmsn-dialog__list { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .5rem; }
.cmsn-dialog__choice { display: block; width: 100%; min-height: 44px; text-align: left;
  padding: .7rem .85rem; border: 1px solid #c8b9a8; border-radius: 8px;
  background: #fbf7f1; font: inherit; font-size: 1rem; cursor: pointer; }
.cmsn-dialog__choice:hover { background: #f3ebe0; }
/* A VISIBLE FOCUS RING IS THE WHOLE POINT of moving focus in here. */
.cmsn-dialog__choice:focus-visible,
.cmsn-dialog .btn:focus-visible { outline: 3px solid #7a5c3a; outline-offset: 2px; }
.cmsn-dialog__choicename { display: block; font-weight: 600; }
.cmsn-dialog__choicehint { display: block; font-size: .85rem; color: #6b5a49; margin-top: .15rem; }
.cmsn-dialog__foot { display: flex; justify-content: flex-end; gap: .5rem; }
.cmsn-dialog__foot .btn { min-height: 44px; }

@media (max-width: 480px) {
  .cmsn-dialog { padding: 0; align-items: flex-end; }
  .cmsn-dialog__box { max-width: none; border-radius: 12px 12px 0 0; max-height: 85vh; }
}

/* The reading pane inside a content dialog. Scrolls on its own so the Close
   button stays reachable, and shows a focus ring because it is focusable --
   a scrollable region that cannot take focus cannot be scrolled by keyboard. */
.cmsn-dialog--wide .cmsn-dialog__box { max-width: 46rem; }
.cmsn-dialog__doc { max-height: 58vh; overflow: auto; margin: 0 0 1rem;
  padding: .25rem .9rem .25rem .25rem; font-size: .95rem; line-height: 1.55; }
.cmsn-dialog__doc:focus-visible { outline: 3px solid #7a5c3a; outline-offset: 2px; }
.cmsn-dialog__doc h2 { font-size: 1.02rem; margin: 1.15rem 0 .35rem; }
.cmsn-dialog__doc h3 { font-size: .95rem; margin: .9rem 0 .3rem; }
.cmsn-dialog__doc p, .cmsn-dialog__doc li { margin: 0 0 .55rem; }
.cmsn-dialog__doc ul, .cmsn-dialog__doc ol { padding-left: 1.2rem; }
.cmsn-dialog__loading { color: #6b5a49; font-style: italic; }
.cmsn-dialog__foot { align-items: center; }
.cmsn-dialog__foot .btn { text-decoration: none; display: inline-flex;
  align-items: center; justify-content: center; }
@media (max-width: 480px) { .cmsn-dialog__doc { max-height: 52vh; } }

/* A revealed field that follows a block rather than a label. A class rather
   than an inline style: scripts/test-site-build.mjs pins the number of inline
   styles in the output so a new one shows up as a number that moved, and this
   is not worth a pin going up. */
.cmsn-reveal--spaced { margin-top: 1.25rem; }

/* WHAT THE CONCEPT DRAWING IS PROMISING — one clause on the bar, not four
   lines above it. This was a paragraph; Garrett called it far too long on 26
   October and asked for a short note on the toolbar that was already there.

   IT MUST NOT WRAP THE BAR AT 375px. The bar carries the label, the piece
   tabs, the zoom buttons and the expand control, so this takes what is left
   and ellipsises rather than pushing the row onto a second line and making
   the whole panel jump taller. The full wording is one press away, so
   truncation costs nothing. */
.cmsn-preview__promise {
  flex: 1 1 auto; min-width: 0;
  font-size: .74rem; line-height: 1.3; color: #5b4c3e;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* The way into the full text. A superscript question mark rather than more
   words, because more words is the thing being fixed. */
.cmsn-preview__notemore {
  appearance: none; -webkit-appearance: none;
  border: 1px solid var(--cmsn-line, #d8cfc4); background: transparent;
  color: #5b4c3e; cursor: pointer;
  font: inherit; font-size: .68rem; line-height: 1;
  width: 1.15rem; height: 1.15rem; padding: 0; margin-left: .3rem;
  border-radius: 50%; vertical-align: baseline;
}
.cmsn-preview__notemore:hover,
.cmsn-preview__notemore:focus-visible { background: #efe7dc; color: #3a2d22; }

.cmsn-preview__promisetext { overflow: hidden; text-overflow: ellipsis; }

/* ON A PHONE THE WORDS GO AND THE WAY IN STAYS.
   At 375px this bar already wraps without any help from the note: the label
   is 109px and the expand control is 194px of the 298px available, so they
   were on two rows before 26 October. Giving the note a row of its own made
   that three, and a taller bar is exactly what removing the paragraph was
   meant to fix. So below 480px the sentence is dropped and the "?" rides
   beside the label, costing no row at all — the full wording is one press
   away either way, which is the whole reason it is safe to drop. */
@media (max-width: 480px) {
  .cmsn-preview__promise { flex: 0 0 auto; }
  .cmsn-preview__promisetext { display: none; }
}

