/* ============================================================================
   Mahi AI — front-end design system (P2-R3: blue, bigger, two-sided)
   MASTER_PLAN_V2 §Design language + AGENT_B3_UI.md. Light, restrained, ONE
   accent, no AI slop. A big calm canvas, the card floating in it as the print
   surface, the options in a rail, the conversation in a floating dock.

   EVERY colour below resolves from a CSS custom property that js/tenant.js sets
   from GET /api/ai/tenant/:id. The values in :root are neutral fallbacks used
   only if that fetch fails — nothing tenant-specific is hardcoded.

   P2-R3 colour rule (Harwen: "get rid of the green"): there is no green literal
   anywhere in this file. Every fallback is a flat grey or leans blue, and the
   gate parses the SERVED css and fails on any colour whose green channel is the
   dominant one.
   ========================================================================== */

:root {
  /* tenant-injected (fallbacks are deliberately neutral, not Mahi's) */
  --accent: #3A3F4B;
  --accent-ink: #FFFFFF;
  --ink: #16181C;
  --surface: #FAFAFB;
  --muted: #6B7080;

  /* derived at runtime by tenant.js; these keep the page sane pre-boot */
  --paper: #FFFFFF;
  --line: rgba(22, 24, 28, 0.10);
  --line-soft: rgba(22, 24, 28, 0.06);
  --accent-soft: rgba(58, 63, 75, 0.08);
  --accent-line: rgba(58, 63, 75, 0.28);
  --ink-70: rgba(22, 24, 28, 0.70);
  --ink-45: rgba(22, 24, 28, 0.45);
  --workspace: #F0F0F3;
  --workspace-dot: rgba(22, 24, 28, 0.085);

  /* the one non-tenant hue: "this will not print cleanly" */
  --warn: #C2603C;
  --warn-ink: #8C4425;
  --warn-soft: rgba(194, 96, 60, 0.07);

  --shadow-card:
    0 1px 1px rgba(20, 22, 28, 0.06),
    0 2px 6px rgba(20, 22, 28, 0.07),
    0 26px 52px -16px rgba(20, 22, 28, 0.28);
  --shadow-float:
    0 1px 2px rgba(20, 22, 28, 0.05),
    0 10px 30px -10px rgba(20, 22, 28, 0.20);
  --shadow-pop:
    0 2px 4px rgba(20, 22, 28, 0.06),
    0 18px 44px -12px rgba(20, 22, 28, 0.30);

  --r-sm: 8px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 26px;

  --gutter: 24px;
  --rail-w: 336px;

  /* The dock floats over the workspace, so the card has to know how tall it is.
     js/main.js writes --dock-h from a ResizeObserver; everything below follows
     from it, which is why collapsing the conversation genuinely grows the card
     instead of leaving a hole where the chat used to be. */
  --dock-h: 190px;
  /* The chrome row floats over the workspace and wraps on a narrow window, so
     the card is told how tall it actually is — same trick as --dock-h. */
  --chrome-h: 58px;
  /* ...and the same again for the front|back bar, which is now UNDER the card
     (owner review Sept 22). Measured, because it is absent on a one-sided card
     and two rows tall on a phone that is being offered a back. */
  --underbar-h: 0px;
  --scene-gap: 20px;

  /* THE VERTICAL ORDER OF THE WORKSPACE (owner review Sept 22, item 2).
     chrome · the CHAT BOX · the card · front|back.
     The chat used to be the last of those and a newcomer had to go looking for
     it. Everything above the card is --scene-top, everything below it is
     --scene-bottom, and the card is given whatever is left.

     The chrome row and the chat box now BOTH sit above the card, where the
     chat used to be below it, so the space each one takes is scrutinised: the
     clearances here are the smallest that still read as separate objects, and
     the thread is capped a little lower than it was (it scrolls; the card does
     not). Net, the card is the size it was before the swap. */
  --scene-top: calc(var(--chrome-h) + var(--dock-h) + 10px);
  --scene-bottom: calc(var(--underbar-h) + 12px);

  /* P2-R3: the card starts BIG. There is no top bar to pay for any more, and
     the cap is generous — this is a workspace, not a preview thumbnail. */
  /* the floor is a width for a card and a HEIGHT for a tall product: a 4x11in
     door hanger held to 260px wide would be 715px tall and run under the chat */
  --card-max: clamp(min(260px, calc(420px * var(--trim-ratio, 1.75))), calc((100dvh - var(--scene-top) - var(--scene-bottom)) * var(--trim-ratio, 1.75)), 1060px);

  /* everything one step up from round 2 */
  --fs-micro: 12px;
  --fs-small: 13.5px;
  --fs-body: 15.5px;
  --fs-lead: 17px;
  --fs-hero: clamp(19px, 1.9vw, 27px);

  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
  --dur: 220ms;
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* several components below set display on the same element the JS hides with the
   `hidden` attribute; author rules beat the UA sheet, so make `hidden` win. */
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: var(--fs-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; }
h1, h2, h3, p { margin: 0; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* ---------- app frame ---------- */
.app {
  height: 100dvh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.app[data-rail="collapsed"] { --rail-w: 74px; }

/* ---------- workspace ---------- */
.workspace {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  position: relative;
}

/* ============================== LEFT RAIL =============================== */

.rail {
  flex: 0 0 var(--rail-w);
  width: var(--rail-w);
  min-width: 0;
  display: flex;
  background: var(--paper);
  border-right: 1px solid var(--line-soft);
  transition: flex-basis var(--dur) var(--ease), width var(--dur) var(--ease);
  z-index: 8;
}

.rail__tabs {
  flex: 0 0 74px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 8px;
  border-right: 1px solid var(--line-soft);
}
.railtab {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 11px 2px 9px;
  border-radius: var(--r-md);
  color: var(--muted);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.railtab:hover { background: var(--line-soft); color: var(--ink); }
.railtab.is-on { background: var(--accent-soft); color: var(--accent); }
.railtab__label { font-size: var(--fs-micro); letter-spacing: .01em; font-weight: 500; }

.rail__body {
  flex: 1 1 auto;
  min-width: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px 18px 34px;
}
.app[data-rail="collapsed"] .rail__body { display: none; }

.panel { display: flex; flex-direction: column; gap: 12px; }
.panel__note { font-size: var(--fs-small); color: var(--muted); line-height: 1.5; }
.panel__note--lead { margin-bottom: 2px; }
.panel__label {
  font-size: var(--fs-micro); color: var(--muted);
  text-transform: uppercase; letter-spacing: .08em; font-weight: 500;
  margin-top: 8px;
}
.panel__label--inline { margin-top: 0; text-transform: none; letter-spacing: 0; font-size: var(--fs-small); }
.panel__row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 6px; }
.panel__empty {
  font-size: var(--fs-small); color: var(--muted); line-height: 1.5;
  border: 1px dashed var(--line); border-radius: var(--r-md);
  padding: 14px; text-align: left;
}

.rail-scrim { display: none; }

/* ---------- buttons ---------- */
.btn {
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  padding: 9px 13px;
  font-size: var(--fs-small);
  color: var(--ink-70);
  min-height: 40px;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn:hover:not(:disabled) { border-color: var(--accent-line); background: var(--accent-soft); color: var(--ink); }
.btn:disabled { opacity: .45; cursor: default; }
.btn--soft { background: var(--accent-soft); border-color: transparent; color: var(--accent); font-weight: 500; }
.btn--soft:hover:not(:disabled) { border-color: var(--accent-line); }
.btn--accent { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn--accent:hover:not(:disabled) { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); opacity: .92; }
.btn--tiny { font-size: var(--fs-micro); padding: 6px 10px; min-height: 34px; }

.stepbtn {
  width: 32px; height: 32px; border-radius: var(--r-sm);
  border: 1px solid var(--line);
  display: grid; place-items: center;
  color: var(--muted); font-size: 15px; line-height: 1;
}
.stepbtn:hover { color: var(--ink); border-color: var(--accent-line); background: var(--accent-soft); }

.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; }
.seg__btn { font-size: var(--fs-micro); padding: 6px 11px; color: var(--muted); min-height: 34px; }
.seg__btn + .seg__btn { border-left: 1px solid var(--line); }
.seg__btn.is-on { background: var(--accent-soft); color: var(--accent); font-weight: 500; }

/* ---------- assets panel ---------- */
.uploader__status {
  font-size: var(--fs-small); line-height: 1.45;
  padding: 10px 12px; border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-70);
  border-left: 2px solid var(--line);
}
.uploader__status.is-busy { border-left-color: var(--accent); }
.uploader__status.is-ok { border-left-color: var(--accent); background: var(--accent-soft); }
.uploader__status.is-warn { border-left-color: var(--warn); background: var(--warn-soft); color: var(--warn-ink); }

.acards { display: flex; flex-direction: column; gap: 10px; }
.acard {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 10px;
  display: flex; align-items: center; gap: 12px;
  background: var(--paper);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.acard__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.acard.is-placed { border-color: var(--accent-line); }
.acard.is-selected { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.acard.is-new { box-shadow: 0 0 0 3px var(--accent-soft); border-color: var(--accent); }

/* a checker behind the thumb so a cut-out (finalized) logo reads as transparent
   rather than as a logo on a white square — the difference finalize makes */
.acard__thumb {
  flex: 0 0 70px;
  width: 70px; height: 70px;
  border-radius: var(--r-sm);
  display: grid; place-items: center;
  overflow: hidden;
  cursor: grab;
  touch-action: none;
  background-color: var(--paper);
  background-image:
    linear-gradient(45deg, var(--line-soft) 25%, transparent 25%, transparent 75%, var(--line-soft) 75%),
    linear-gradient(45deg, var(--line-soft) 25%, transparent 25%, transparent 75%, var(--line-soft) 75%);
  background-size: 8px 8px;
  background-position: 0 0, 4px 4px;
}
.acard__thumb img { max-width: 84%; max-height: 84%; display: block; -webkit-user-drag: none; }
.acard__meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.acard__origin { font-size: var(--fs-micro); color: var(--muted); }
.badge {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; font-weight: 600;
  padding: 3px 6px; border-radius: 4px;
  background: var(--line-soft); color: var(--muted);
}
.badge--vector { background: var(--accent-soft); color: var(--accent); }
.acard__actions { display: flex; flex-wrap: wrap; gap: 6px; }
.acard__done { font-size: var(--fs-micro); color: var(--accent); align-self: center; }

.aselect {
  margin-top: 8px; padding: 14px;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--surface);
  display: flex; flex-direction: column; gap: 10px;
}
.aselect__title { font-size: var(--fs-small); font-weight: 600; }
.aselect__print { font-size: var(--fs-micro); color: var(--muted); line-height: 1.45; }
.aselect__print.is-outside { color: var(--warn-ink); }
.aselect__row { display: flex; align-items: center; gap: 8px; }
.aselect__label { font-size: var(--fs-micro); color: var(--muted); flex: 0 0 46px; }
.aselect__value { font-size: var(--fs-micro); color: var(--ink-70); flex: 1 1 auto; font-variant-numeric: tabular-nums; }
.aselect__actions { display: flex; gap: 7px; }
.aselect__actions .btn { flex: 1 1 0; }

.drag-proxy {
  position: fixed; z-index: 60;
  width: 110px; height: auto;
  transform: translate(-50%, -50%);
  pointer-events: none;
  filter: drop-shadow(0 8px 18px rgba(20, 22, 28, 0.28));
  opacity: .92;
}
body.is-dragging-asset { cursor: grabbing; }

/* ---------- details panel ---------- */
.details__grid { display: flex; flex-direction: column; gap: 12px; }
.field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.field__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.field__label {
  font-size: var(--fs-micro); color: var(--muted);
  text-transform: uppercase; letter-spacing: .07em; font-weight: 500;
}
.field__input {
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
  padding: 9px 12px;
  min-height: 44px;
  font-size: var(--fs-body);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.field__input::placeholder { color: var(--muted); opacity: .65; }
.field__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field.is-over .field__input { border-color: var(--warn); }

/* "printed on this side" — a switch per line, because the VALUES are shared by
   the two faces of the card and the placement is not */
.onswitch {
  flex: 0 0 auto;
  width: 38px; height: 22px; border-radius: 999px;
  background: var(--line); position: relative;
  transition: background var(--dur) var(--ease);
}
.onswitch__dot {
  position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(0,0,0,.22);
  transition: transform var(--dur) var(--ease);
}
.onswitch.is-on { background: var(--accent); }
.onswitch.is-on .onswitch__dot { transform: translateX(16px); }

.details__warn {
  font-size: var(--fs-small); color: var(--warn-ink);
  background: var(--warn-soft);
  border-left: 2px solid var(--warn);
  padding: 9px 12px; border-radius: 0 var(--r-sm) var(--r-sm) 0;
}

.inkpick { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-sm); overflow: hidden; }
.inkpick__btn { font-size: var(--fs-micro); padding: 6px 12px; color: var(--muted); min-height: 34px; }
.inkpick__btn + .inkpick__btn { border-left: 1px solid var(--line); }
.inkpick__btn.is-on { background: var(--accent-soft); color: var(--accent); font-weight: 500; }

/* ---------- type, under the details (P2-R3 item 5) ---------- */
.typeset {
  display: flex; flex-direction: column; gap: 10px;
  margin-top: 6px; padding-top: 16px;
  border-top: 1px solid var(--line-soft);
}

/* the trigger shows its own face IN that face — same rule as the list */
.fontbtn {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--paper);
  text-align: left;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.fontbtn:hover { border-color: var(--accent-line); }
.fontbtn[aria-expanded="true"] { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.fontbtn__label {
  font-size: 19px; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fontbtn__caret { color: var(--muted); font-size: 11px; flex: 0 0 auto; }
.fontbtn--sm { min-height: 40px; padding: 5px 11px; flex: 1 1 auto; width: auto; }
.fontbtn--sm .fontbtn__label { font-size: var(--fs-small); }

/* the live preview of the customer's OWN text in the chosen face */
.facepreview {
  font-size: 30px; line-height: 1.25;
  padding: 14px 14px 16px;
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.facepreview.is-placeholder { color: var(--ink-45); }

.foldout { border-top: 1px solid var(--line-soft); padding-top: 10px; }
.foldout__summary {
  font-size: var(--fs-small); color: var(--muted);
  cursor: pointer; list-style: none; min-height: 34px;
  display: flex; align-items: center; gap: 6px;
}
.foldout__summary::-webkit-details-marker { display: none; }
.foldout__summary::before { content: "＋"; font-size: 12px; }
.foldout[open] .foldout__summary::before { content: "－"; }
.foldout__summary:hover { color: var(--ink); }

.overrides { display: flex; flex-direction: column; gap: 8px; padding-top: 8px; }
.override { display: flex; align-items: center; gap: 10px; }
.override__label { font-size: var(--fs-micro); color: var(--muted); flex: 0 0 64px; }

/* ---------- the font picker popup ---------- */
.fontpop {
  position: fixed;
  z-index: 70;
  display: flex; flex-direction: column;
  max-height: min(64dvh, 460px);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
}
.fontpop[data-motion="in"] { animation: popIn 160ms var(--ease); }
@keyframes popIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

.fontpop__preview {
  flex: 0 0 auto;
  padding: 14px 16px 12px;
  border-bottom: 1px solid var(--line-soft);
  background: var(--surface);
  display: flex; flex-direction: column; gap: 2px;
  min-height: 74px;
}
.fontpop__preview-text {
  font-size: 26px; line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fontpop__preview-name { font-size: var(--fs-micro); color: var(--muted); }

.fontpop__list { overflow-y: auto; overscroll-behavior: contain; padding: 6px; }
.fontpop__group {
  font-size: var(--fs-micro); color: var(--muted);
  text-transform: uppercase; letter-spacing: .08em; font-weight: 500;
  padding: 10px 10px 4px;
}
.fontrow {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  width: 100%; min-height: 44px;
  padding: 7px 10px;
  border-radius: var(--r-sm);
  text-align: left;
}
.fontrow:hover, .fontrow:focus-visible { background: var(--accent-soft); }
.fontrow.is-on { background: var(--accent-soft); }
.fontrow.is-on .fontrow__name { color: var(--accent); }
.fontrow__name {
  font-size: 20px; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fontrow__role { font-size: 10.5px; color: var(--muted); flex: 0 0 auto; }

/* ========================= THE CANVAS / WORKSPACE ======================= */

.canvas {
  flex: 1 1 auto;
  min-width: 0;
  position: relative;
  overflow: hidden;
  background-color: var(--workspace);
  background-image: radial-gradient(var(--workspace-dot) 1px, transparent 1px);
  background-size: 24px 24px;
  background-position: -1px -1px;
  touch-action: none;
}
.canvas.is-panning { cursor: grabbing; }

.canvas__scene {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* --textwin-room: the Text window's column, while it is open (Text v2) */
  padding: var(--scene-top) calc(var(--gutter) + var(--textwin-room, 0px)) var(--scene-bottom) var(--gutter);
  transform-origin: 0 0;
  /* no will-change: it rasterizes the scene once at 100% and zooming then
     scales that bitmap — the customer's own type went blurry (Sept 28) */
}

.cardwrap {
  width: min(var(--card-max), 100%);
  display: flex;
  justify-content: center;
}

/* ---------- the floating chrome row ---------- */
.chrome {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 10;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: 16px 16px 0;
  pointer-events: none;
}
.chrome > * { pointer-events: auto; }

/* ---------- the wordmark, on the workspace and at size ---------- */
.wordmark {
  display: flex; align-items: center;
  flex: 0 0 auto;
  min-width: 0;
  padding-top: 2px;
}
.wordmark__img { display: none; height: 40px; width: auto; }
.wordmark__text {
  font-size: 25px; font-weight: 700; letter-spacing: -0.02em;
  color: var(--ink);
}
.wordmark[data-mark="image"] .wordmark__img { display: block; }
.wordmark[data-mark="image"] .wordmark__text { display: none; }
.wordmark[data-mark="pending"] .wordmark__text { visibility: hidden; }

/* ---------- the bar under the card ----------
   front | back, and whatever the card is offering about its second side, sits
   with the card rather than at the top of the workspace. It is pointer-
   transparent except for its own controls, so the workspace under it still
   pans and the card is never fenced off by an empty strip. */
.underbar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 9;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-end;
  gap: 10px 14px;
  padding: 0 var(--gutter) 12px;
  pointer-events: none;
}
.underbar > * { pointer-events: auto; }

/* THE NEXT STEP LIVES WITH THE CARD (desktop).
   It used to float at the top-right of the dock — which was right when the dock
   was at the foot of the workspace and wrong the moment the dock moved to the
   top, because it put "I'm happy with this — choose my card" as far from the
   card as the screen allows. It is one element with two homes: js/main.js moves
   it between the dock (phones, in flow between the thread and the composer) and
   the underbar (desktops, on the same line as Front|Back, directly under the
   card). One element, so it can never be shown twice and its click binding and
   its id survive the move.

   `flex-wrap` on the underbar does the rest: the pair sits as one centred bar
   when there is room, and the pill takes its own line when the side switcher is
   offering something wide. Either way --underbar-h is measured, so the card
   knows what the bar really costs it. */
.underbar .dock__next { justify-content: center; }
.underbar .nextbtn { min-height: 44px; }

/* ---------- front | back ---------- */
.sides {
  display: flex; flex-direction: column-reverse; align-items: center; gap: 8px;
  flex: 0 1 auto;
  max-width: 100%;
}
.sides__tabs {
  display: flex; align-items: center; gap: 3px;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  box-shadow: var(--shadow-float);
  padding: 4px 5px;
}
.sidetab {
  display: flex; align-items: center; gap: 7px;
  min-height: 36px;
  padding: 6px 15px;
  border-radius: 999px;
  color: var(--muted);
  font-size: var(--fs-small);
  font-weight: 500;
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.sidetab:hover { color: var(--ink); background: var(--line-soft); }
.sidetab.is-on { background: var(--accent); color: var(--accent-ink); }
.sidetab__dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; opacity: .28;
}
.sidetab__dot.is-filled { opacity: .85; }
.sidetab.is-new { animation: sideNew 1100ms var(--ease) 2; }
@keyframes sideNew {
  0%, 100% { box-shadow: 0 0 0 0 var(--accent-soft); }
  50% { box-shadow: 0 0 0 5px var(--accent-soft); }
}

.sideadd {
  display: flex; align-items: center; gap: 6px;
  min-height: 36px; padding: 6px 14px;
  border-radius: 999px;
  color: var(--accent);
  font-size: var(--fs-small); font-weight: 500;
  white-space: nowrap;
  border: 1px dashed var(--accent-line);
}
.sideadd:hover { background: var(--accent-soft); }
.sideadd.is-busy { opacity: .5; }
.sideadd__plus { font-size: 15px; line-height: 1; }

.sidedrop {
  min-height: 36px; padding: 6px 12px;
  margin-left: 4px;
  border-left: 1px solid var(--line-soft);
  border-radius: 0 999px 999px 0;
  border-radius: 999px;
  font-size: var(--fs-micro); color: var(--muted);
  white-space: nowrap;
}
.sidedrop:hover { color: var(--ink); background: var(--line-soft); }

.sides__tipinner {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  justify-content: center;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  box-shadow: var(--shadow-float);
  padding: 5px 7px 5px 14px;
  max-width: 100%;
}
.sidetip__lead { font-size: var(--fs-micro); color: var(--muted); }
.sidetip__btn {
  font-size: var(--fs-micro); font-weight: 500;
  white-space: nowrap;
  color: var(--accent);
  border: 1px solid var(--accent-line);
  border-radius: 999px;
  padding: 5px 12px; min-height: 32px;
}
.sidetip__btn:hover { background: var(--accent-soft); }

/* ---------- the three ways to make a back (P2-R4 item 1) ----------
   Three explicit paths instead of one assumed one. The cost is on the face of
   each button, because "which of these do I pay for" is the actual question a
   customer is asking here — and two of the three answers are "you don't". */
.backpick { padding: 5px 7px 5px 12px; gap: 10px; }
.backpick__lead {
  font-size: var(--fs-micro); color: var(--muted); white-space: nowrap;
}
.backpick__row { display: flex; align-items: stretch; gap: 6px; flex-wrap: wrap; }
.backpick__btn {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  text-align: left;
  border: 1px solid var(--accent-line);
  border-radius: 14px;
  padding: 5px 12px; min-height: 38px;
  background: var(--paper);
  transition: background .13s ease, border-color .13s ease;
}
.backpick__btn:hover:not(:disabled) { background: var(--accent-soft); }
.backpick__btn:disabled { opacity: .5; cursor: default; }
.backpick__label {
  font-size: var(--fs-micro); font-weight: 600; color: var(--accent);
  white-space: nowrap;
}
.backpick__cost {
  font-size: 10.5px; letter-spacing: .02em; color: var(--muted); white-space: nowrap;
}
.backpick__btn.is-free .backpick__cost { color: var(--ink-45); font-weight: 600; }

/* ---------- placement row, Details panel (P2-R4 item 2) ----------
   Three faces: an offer, a way back, or a plain statement that the card is
   already arranged. The statement has no button — see contact-panel.js. */
.placerow {
  display: flex; flex-direction: column; align-items: flex-start; gap: 7px;
  margin-top: 14px; padding: 11px 12px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-md);
  background: var(--surface);
}
.placerow[data-mode="offer"] { border-color: var(--accent-line); background: var(--accent-soft); }
.placerow__note {
  font-size: var(--fs-small); color: var(--muted); line-height: 1.45; margin: 0;
}
.placerow[data-mode="auto"] .placerow__note { color: var(--ink-45); }
.placebtn {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--fs-small); font-weight: 600;
  color: var(--accent);
  border: 1px solid var(--accent-line);
  border-radius: 999px;
  padding: 7px 14px; min-height: 36px;
  background: var(--paper);
}
.placebtn:hover { background: var(--accent-soft); }
.placebtn__icon { display: inline-flex; opacity: .85; }

/* ---------- floating workspace controls ---------- */
.hud {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap; justify-content: flex-end;
  flex: 0 1 auto;
}
.hud__group {
  display: flex; align-items: center; gap: 3px;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: 999px;
  box-shadow: var(--shadow-float);
  padding: 4px 6px;
}
.hud__group .switch { padding: 0 8px 0 4px; }

.newcard {
  display: flex; align-items: center; gap: 7px;
  white-space: nowrap;
  min-height: 34px; padding: 4px 12px 4px 9px;
  border-radius: 999px;
  color: var(--ink-70);
  font-size: var(--fs-small); font-weight: 500;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.newcard:hover { background: var(--accent-soft); color: var(--accent); }
.newcard.is-confirming { background: var(--accent); color: var(--accent-ink); }

.iconbtn {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  color: var(--muted); font-size: 17px; line-height: 1;
}
.iconbtn:hover { background: var(--line-soft); color: var(--ink); }
.iconbtn:disabled { opacity: .35; cursor: default; }
.iconbtn:disabled:hover { background: none; color: var(--muted); }
.app[data-rail="open"] .railtoggle { color: var(--accent); }
.hud__zoom {
  font-size: var(--fs-micro); color: var(--muted);
  min-width: 48px; height: 34px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.hud__zoom:hover { background: var(--line-soft); color: var(--ink); }
.versions__label {
  font-size: var(--fs-micro); color: var(--muted);
  font-variant-numeric: tabular-nums; min-width: 30px; text-align: center;
}

.meter { display: flex; align-items: center; gap: 8px; padding-right: 6px; }
.meter__bar {
  width: 54px; height: 3px; border-radius: 2px;
  background: var(--line); overflow: hidden; display: block;
}
.meter__bar > i {
  display: block; height: 100%; width: 0%;
  min-width: 5px; border-radius: 2px;
  background: var(--accent);
  transition: width var(--dur) var(--ease);
}
.meter__text { font-size: var(--fs-micro); color: var(--muted); font-variant-numeric: tabular-nums; }
.meter--capped .meter__bar > i { background: var(--muted); }

.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch__track {
  width: 30px; height: 17px; border-radius: 9px;
  background: var(--line); position: relative; display: block;
  transition: background var(--dur) var(--ease);
}
.switch__track > i {
  position: absolute; top: 2px; left: 2px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--paper); box-shadow: 0 1px 2px rgba(0,0,0,.2);
  transition: transform var(--dur) var(--ease);
}
.switch input:checked + .switch__track { background: var(--accent); }
.switch input:checked + .switch__track > i { transform: translateX(13px); }
.switch input:focus-visible + .switch__track { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch__label { font-size: var(--fs-micro); color: var(--muted); }

/* The bleed document is 3.75 x 2.25in; trim is 3.5 x 2in.
   Trim view clips the doc to the trim rect so the card reads at its true
   3.5x2 proportion (aspect 1.75). Bleed view reveals the full doc. */
.doc {
  position: relative;
  width: 100%;
  background: var(--paper);
  box-shadow: var(--shadow-card);
  transition: aspect-ratio var(--dur) var(--ease);
}
.doc[data-view="trim"]  { aspect-ratio: var(--trim-ratio, 1.75); }
.doc[data-view="bleed"] { aspect-ratio: var(--doc-ratio, 1.6667); box-shadow: none; outline: 1px solid var(--line); }

/* art fills the whole document (it bleeds); in trim view the doc IS the trim
   so cover-fit against the trim box is what the customer sees. */
.doc__art { position: absolute; inset: 0; overflow: hidden; background: var(--paper); }
.doc__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 320ms var(--ease);
}
.doc__img.is-shown { opacity: 1; }

.doc__blank {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px;
  background:
    repeating-linear-gradient(45deg,
      var(--paper) 0 7px,
      rgba(0, 0, 0, 0.014) 7px 14px);
}
.doc__blank-line { width: 34px; height: 1px; background: var(--line); }
.doc__blank-text { font-size: var(--fs-small); color: var(--muted); }
.doc__blank.is-hidden { display: none; }

/* Busy state must be unmistakable at ANY moment of the sweep cycle — a flat
   scrim carries "working", the sweep carries "still working". */
.doc__shimmer {
  position: absolute; inset: 0;
  background-color: rgba(255, 255, 255, 0.34);
  background-image: linear-gradient(100deg,
    rgba(255,255,255,0) 20%,
    rgba(255,255,255,0.55) 48%,
    rgba(255,255,255,0) 76%);
  background-size: 260% 100%;
  background-repeat: no-repeat;
  animation: sweep 1500ms linear infinite;
  pointer-events: none;
  z-index: 6;
}
@keyframes sweep {
  from { background-position: 150% 0; }
  to   { background-position: -110% 0; }
}

/* trim rect — the coordinate space every layer is defined in.
   In trim view it is the whole doc; in bleed view it is inset by the bleed. */
.trim {
  position: absolute;
  inset: 0;
  transition: inset var(--dur) var(--ease);
  /* layers size themselves in cqh (fractions of TRIM HEIGHT), so the same
     trim-relative layout renders correctly at any card size with no JS */
  container-type: size;
}
.doc[data-view="bleed"] .trim {
  /* 0.125in of 3.75in = 3.3333%   |   0.125in of 2.25in = 5.5556% */
  inset: var(--bleed-y, 5.5556%) var(--bleed-x, 3.3333%);
}
/* Each guide carries a halo in the opposite tone so it stays readable over any
   artwork — dark art, light art or a busy mid-tone. */
.trim__rule, .trim__safe { position: absolute; pointer-events: none; opacity: 0; transition: opacity var(--dur) var(--ease); z-index: 7; }
.trim__rule {
  inset: 0;
  outline: 1px dashed rgba(20, 22, 28, 0.78);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.45);
}
/* safe area = 0.125in inside trim: 3.5714% x / 6.25% y */
.trim__safe {
  inset: var(--safe-y, 6.25%) var(--safe-x, 3.5714%);
  outline: 1px dotted rgba(255, 255, 255, 0.9);
  box-shadow: 0 0 0 2px rgba(20, 22, 28, 0.22);
}
.doc[data-view="bleed"] .trim__rule { opacity: 1; }
.doc[data-view="bleed"] .trim__safe { opacity: .55; }

.doc__marks { position: absolute; inset: 0; opacity: 0; transition: opacity var(--dur) var(--ease); }
.doc[data-view="bleed"] .doc__marks { opacity: 1; }
.doc__marks > i {
  position: absolute; width: 10px; height: 10px;
  border: 0 solid rgba(20, 22, 28, 0.85);
  filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.95));
}
.doc__marks > i:nth-child(1) { top: 5.5556%; left: 3.3333%; border-top-width: 1px; border-left-width: 1px; transform: translate(-4px,-4px); }
.doc__marks > i:nth-child(2) { top: 5.5556%; right: 3.3333%; border-top-width: 1px; border-right-width: 1px; transform: translate(4px,-4px); }
.doc__marks > i:nth-child(3) { bottom: 5.5556%; left: 3.3333%; border-bottom-width: 1px; border-left-width: 1px; transform: translate(-4px,4px); }
.doc__marks > i:nth-child(4) { bottom: 5.5556%; right: 3.3333%; border-bottom-width: 1px; border-right-width: 1px; transform: translate(4px,4px); }

/* ---------- logo asset layers ---------- */
/* Three layers, in this order: the ART, the LOGOS, the typeset DETAILS. A logo
   can be moved in front of the details, which is what the second band is for. */
/* Every layer container spans the WHOLE trim, so each one has to be transparent
   to the pointer or it silently steals the events belonging to the layer beneath
   it. Only the objects themselves take input. */
.alayer { position: absolute; inset: 0; pointer-events: none; }
.alayer--ghost { z-index: 2; }
.aclip { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 2; }
.alayer--over { z-index: 4; }
.aclip--over { z-index: 4; }

.asset { position: absolute; }
.asset--full { pointer-events: none; }
.asset__img {
  width: 100%; height: 100%; display: block;
  object-fit: contain;
  -webkit-user-drag: none; user-select: none;
}
/* Only the IMAGE is faded, never the chrome — the selection ring and the resize
   handle have to stay legible while the artwork underneath them is a ghost. */
.asset--ghost .asset__img { opacity: .32; }
.asset--ghost {
  cursor: grab;
  touch-action: none;
  outline: none;
  pointer-events: auto;
}
.asset--ghost.is-dragging { cursor: grabbing; }
.asset--ghost::before {
  content: ""; position: absolute; inset: -2px;
  border-radius: 2px;
  pointer-events: none;
}
.asset--ghost:hover::before { outline: 1px solid var(--accent-line); }
.asset--ghost.is-selected::before { outline: 1.5px solid var(--accent); }
.asset--ghost:focus-visible::before { outline: 2px solid var(--accent); }
/* a logo that is not fully on the card says so at its own edge, not in a banner */
.asset--ghost[data-prints="false"]::before {
  outline: 1px dashed var(--ink-45);
}
.asset--ghost[data-prints="false"].is-selected::before { outline: 1.5px dashed var(--accent); }

.asset__handle {
  position: absolute; right: -7px; bottom: -7px;
  width: 14px; height: 14px;
  border-radius: 3px;
  background: var(--paper);
  border: 1.5px solid var(--accent);
  cursor: nwse-resize;
  display: none;
  touch-action: none;
}
.asset--ghost.is-selected .asset__handle { display: block; }

/* ---------- contact layer ---------- */
.contact-layer { position: absolute; inset: 0; z-index: 3; pointer-events: none; }

.cl-field {
  position: absolute;
  display: block;
  pointer-events: auto;
  cursor: grab;
  touch-action: none;
  /* a drag must never turn into a text selection */
  user-select: none;
  -webkit-user-select: none;
}
.cl-field.is-editing .cl-text {
  user-select: text;
  -webkit-user-select: text;
}
.cl-field::before {
  /* Enlarged hit target that does not change the printed box. The vertical
     expansion is --hit-y, written per field by contact-layer.js: half the gap
     to the nearest neighbour, capped at 4px. Seven stacked lines on a 2in card
     sit 1-3px apart at 390px, so a fixed expansion would overlap the NEXT line
     and steal its taps. Chrome controls all meet 44px; for editing the values
     with a 44px target, the Details panel is the equivalent path. */
  content: ""; position: absolute;
  inset: calc(-1 * var(--hit-y, 4px)) -6px;
  border-radius: 3px;
}
.cl-field:hover::before { background: rgba(127,127,127,0.10); }
.cl-field.is-selected::before {
  background: rgba(127,127,127,0.06);
  outline: 1px solid var(--accent);
}
/* Auto-placement moving a block the customer had already seen somewhere else
   (P2-R4 item 2). A jump reads as a glitch; a short glide reads as the
   assistant moving the type, which is what actually happened. It is added for
   one repaint only — a permanent transition would make every drag laggy. */
.contact-layer.is-gliding .cl-field {
  transition: left .42s cubic-bezier(.22,.61,.36,1), top .42s cubic-bezier(.22,.61,.36,1),
              width .42s cubic-bezier(.22,.61,.36,1);
}
@media (prefers-reduced-motion: reduce) {
  .contact-layer.is-gliding .cl-field { transition: none; }
}

.cl-field.is-dragging { cursor: grabbing; }
.cl-field.is-dragging::before { background: rgba(127,127,127,0.10); }
.cl-field.is-editing { cursor: text; }
.cl-field.is-editing::before { outline: 1.5px solid var(--accent); background: rgba(255,255,255,0.10); }
.cl-field.is-over::before { outline: 1px solid var(--warn); }

.cl-text {
  display: block;
  white-space: nowrap;
  line-height: 1.2;
  outline: none;
  position: relative;
  z-index: 1;
}
.cl-text[contenteditable="true"] { cursor: text; }

.snapline { position: absolute; background: var(--accent); z-index: 8; pointer-events: none; }
.snapline--v { top: -8%; bottom: -8%; width: 1px; }
.snapline--h { left: -8%; right: -8%; height: 1px; }

/* the one honest line about what the workspace edge means */
.canvas__hint {
  position: absolute;
  left: 16px;
  bottom: calc(var(--underbar-h) + 14px);
  z-index: 9;
  font-size: var(--fs-micro);
  color: var(--ink-70);
  background: var(--paper);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-float);
  border-radius: 999px;
  padding: 7px 15px;
  max-width: calc(100% - 200px);
  text-align: center;
}

.stage__collapse { display: none; }

/* ======================= FLOATING CONVERSATION DOCK =====================
   ABOVE THE CARD (owner review Sept 22, item 2). Harwen, watching a first-time
   customer: "you are given a big blank canvas and have to look for the chatbox."
   So it is no longer at the foot of the workspace — it sits directly under the
   chrome row and directly above the card, which is where the eye starts and
   where the first thing anyone has to do actually is.

   The order inside it is unchanged: the conversation, then the box you type in.
   That keeps the composer touching the card — the two halves of the same act —
   and keeps the thread reading downwards into it. */

.dock {
  position: fixed;
  top: calc(var(--chrome-h) + 4px);
  left: calc(var(--rail-w) + (100vw - var(--rail-w) - var(--textwin-room, 0px)) / 2);
  transform: translateX(-50%);
  width: min(880px, calc(100vw - var(--rail-w) - var(--textwin-room, 0px) - 2 * var(--gutter)));
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: 10px;
  transition: left var(--dur) var(--ease), width var(--dur) var(--ease);
}

/* The visible pill is 20px tall; the BOX is 34 (44 on a phone). The chrome that
   is easy to hit and the chrome that is quiet are not the same rectangle. */
.dock__toggle {
  align-self: center;
  position: relative;
  width: 56px; height: 34px;
  display: none; align-items: center; justify-content: center;
  color: var(--muted);
}
.dock__toggle::before {
  content: "";
  position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%);
  height: 22px; border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-float);
}
.dock__toggle svg { position: relative; z-index: 1; }
.dock__toggle:hover { color: var(--ink); }
.dock[data-thread="true"] .dock__toggle { display: flex; }
.dock__toggle svg { transition: transform var(--dur) var(--ease); }
.dock[data-open="false"] .dock__toggle svg { transform: rotate(180deg); }

.dock__thread {
  display: none;
  max-height: min(24dvh, 230px);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 15px 18px;
  background: rgba(255, 255, 255, 0.86);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-float);
  flex-direction: column;
  gap: 16px;
}
@supports (backdrop-filter: blur(4px)) or (-webkit-backdrop-filter: blur(4px)) {
  .dock__thread {
    background: rgba(255, 255, 255, 0.78);
    -webkit-backdrop-filter: blur(16px) saturate(1.3);
    backdrop-filter: blur(16px) saturate(1.3);
  }
}
.dock[data-thread="true"][data-open="true"] .dock__thread { display: flex; }

.dock__panel {
  background: var(--paper);
  border: 1px solid var(--line-soft);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-float);
  padding: 12px 12px 9px;
  display: flex; flex-direction: column; gap: 8px;
}

/* ===================== THE FIRST-RUN BEACON ============================
   Owner review Sept 22, items 2 and 6: the chat box says "type here" once when
   the card has loaded, and the same mark then walks the main options so a new
   customer learns where Assets, Details and a real designer live.

   IT IS AN OUTLINE, NOT A PSEUDO-ELEMENT. An `::after` was the obvious way to
   draw it and it was wrong: several of these controls already own their ::after
   for something load-bearing — `.helplink::after` IS the 44px tap area that
   makes "Get help from a designer" hittable on a phone — and a second rule for
   the same pseudo-element merges into it. The beacon's `pointer-events: none`
   leaked straight onto that tap target and took it away. An outline cannot
   collide with anything: it takes no pointer events by nature, it is outside
   layout so nothing reflows, and it follows the element's own border-radius
   without being told what that radius is.

   Two slow ripples and it removes itself. There is no overlay, no scrim and no
   z-index war: the mark sits on the element, and the element stays clickable
   for the whole sequence. */

.is-beacon {
  outline: 3px solid transparent;
  outline-offset: 3px;
  animation: beacon 1450ms var(--ease) 2;
}

@keyframes beacon {
  0%   { outline-color: rgba(0, 0, 0, 0);   outline-offset: 1px; }
  20%  { outline-color: var(--accent);      outline-offset: 3px; }
  65%  { outline-color: var(--accent-line); outline-offset: 7px; }
  100% { outline-color: rgba(0, 0, 0, 0);   outline-offset: 9px; }
}

/* ---------- messages ---------- */
.msg { display: flex; flex-direction: column; max-width: 100%; }
.msg__body { font-size: var(--fs-body); line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }

.msg--user { align-items: flex-end; }
.msg--user .msg__body {
  background: var(--accent-soft);
  padding: 10px 15px;
  border-radius: 16px 16px 4px 16px;
  max-width: 88%;
}
.msg--user.is-pending .msg__body { opacity: .55; }

.msg--ai { align-items: flex-start; }
.msg--ai .msg__body { padding-left: 15px; border-left: 1px solid var(--line); }

.msg--refused .msg__body {
  border-left: 2px solid var(--accent-line);
  background: var(--accent-soft);
  padding: 11px 15px;
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.msg--system .msg__body {
  border-left: 2px solid var(--warn);
  background: var(--warn-soft);
  padding: 11px 15px;
  border-radius: 0 var(--r-md) var(--r-md) 0;
  font-size: var(--fs-small);
}
.msg--handoff .msg__body {
  border: 1px solid var(--line);
  border-left: 2px solid var(--accent);
  background: var(--surface);
  padding: 13px 16px;
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.msg--asset .msg__body { border-left-color: var(--accent); }

/* ---------- a guided question (OWNER_REVIEW_SEPT22 §4) ----------
   Harwen asked for "bolded questions that are obvious and easy to follow". So
   the question is the loudest thing in the bubble and the hint is the quietest,
   and they share the assistant's own left rule — this is the assistant talking,
   not a form that has appeared in the conversation. */
.msg--guide { align-items: flex-start; }
.msg--guide .guide__q,
.msg--guide .guide__hint {
  padding-left: 15px;
  border-left: 1px solid var(--line);
  max-width: 100%;
}
.msg--guide .msg__body { padding-bottom: 2px; }
.msg--guide .guide__q {
  font-size: var(--fs-lead);
  line-height: 1.4;
  color: var(--ink);
  padding-top: 6px;
}
.msg--guide .guide__q strong { font-weight: 700; }
.msg--guide .guide__hint {
  font-size: var(--fs-small);
  color: var(--muted);
  padding-top: 3px;
  line-height: 1.5;
}
/* the upload, offered where it was asked for */
.guide__upload { font-weight: 600; }
/* a notice about something that WORKED wears the accent, not the error colour */
.msg--system.msg--ok .msg__body {
  border-left-color: var(--accent);
  background: var(--accent-soft);
  color: var(--ink-70);
}
.msg__action {
  align-self: flex-start;
  margin: 8px 0 0 15px;
  font-size: var(--fs-small);
  color: var(--accent);
  font-weight: 500;
  border: 1px solid var(--accent-line);
  border-radius: 999px;
  padding: 5px 13px;
  min-height: 34px;
}
.msg__action:hover { background: var(--accent-soft); }

.retry {
  margin-top: 9px; font-size: var(--fs-small); color: var(--accent);
  font-weight: 500; text-decoration: underline; text-underline-offset: 2px;
  min-height: 34px;
}

/* staged progress — never a frozen screen */
.thinking { display: flex; flex-direction: column; gap: 9px; padding-left: 15px; border-left: 1px solid var(--line); }
.thinking__row { display: flex; align-items: baseline; gap: 9px; }
.thinking__label { font-size: var(--fs-body); color: var(--ink-70); }
.thinking__time { font-size: var(--fs-micro); color: var(--muted); font-variant-numeric: tabular-nums; }
.thinking__bar { height: 2px; width: 128px; border-radius: 2px; background: var(--line); overflow: hidden; }
.thinking__bar > i {
  display: block; height: 100%; width: 38%; border-radius: 2px;
  background: var(--accent);
  animation: track 1500ms var(--ease) infinite;
}
@keyframes track {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(268%); }
}

/* ---------- the hero invitation (P2-R3 item 3) ---------- */
/* The largest type on the page, directly above the box it is asking you to type
   in. It is a button: taking it fills the composer and hands over the caret. */
.hero { padding: 2px 4px 0; }
.hero__line {
  display: block;
  width: 100%;
  /* Two lines are ALWAYS reserved. The line cycles every few seconds, and a
     dock that grew and shrank with each one would resize the card underneath
     it — the card sizes itself from --dock-h. Reserving the space makes the
     rotation a change of words and nothing else.
     box-sizing is border-box here, so the reservation has to carry the padding
     with it; --hero-pad is that padding, restated wherever the padding changes. */
  --hero-pad: 10px;
  min-height: calc(2 * 1.25em + var(--hero-pad));
  text-align: left;
  font-size: var(--fs-hero);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--ink);
  padding: 4px 6px 6px;
  border-radius: var(--r-sm);
  transition: opacity 240ms var(--ease), transform 240ms var(--ease), color var(--dur) var(--ease);
}
.hero__line:hover { color: var(--accent); }
.hero__line.is-out { opacity: 0; transform: translateY(-5px); }
.hero__line.is-in { animation: heroIn 240ms var(--ease); }
@keyframes heroIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.cap {
  padding: 12px 14px;
  border: 1px solid var(--line); border-left: 2px solid var(--accent);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--surface);
}
.cap__text { font-size: var(--fs-small); color: var(--ink-70); }

/* ---------- composer: the hero control of the whole product ---------- */
.composer {
  display: flex; align-items: flex-end; gap: 10px;
  border: 1.5px solid var(--line);
  border-radius: var(--r-lg);
  padding: 6px 6px 6px 18px;
  background: var(--paper);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.composer:focus-within { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.composer__input {
  flex: 1 1 auto; min-width: 0;
  border: 0; outline: none; resize: none; background: none;
  padding: 11px 0; max-height: 150px; line-height: 1.5;
  font-size: var(--fs-lead);
}
.composer__input::placeholder { color: var(--muted); }
.sendbtn {
  flex: 0 0 auto;
  width: 46px; height: 46px; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink);
  display: grid; place-items: center;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.sendbtn:disabled { opacity: .3; cursor: default; }
.sendbtn:not(:disabled):hover { transform: scale(1.04); }
.sendbtn svg { margin-left: -1px; }

/* the disclosure required by MASTER_PLAN_V2 §Guardrails — small, honest, and in
   the one place that is always on screen: under the thing that makes the art */
.disclosure {
  font-size: var(--fs-micro);
  line-height: 1.45;
  color: var(--muted);
  padding: 0 6px;
}

/* ========================== BRAND MOMENT =============================== */

.brandmoment {
  position: fixed; inset: 0; z-index: 50;
  display: grid; place-items: center;
  background: var(--surface);
  pointer-events: none;
}
.brandmoment__inner {
  display: flex; flex-direction: column; align-items: center; gap: 0;
}
.brandmoment__word {
  display: block;
  /* the wipe: revealed from the baseline up, once */
  clip-path: inset(100% 0 0 0);
  transform: translateY(14px);
}
.brandmoment__img { display: none; width: min(62vw, 560px); height: auto; }
.brandmoment__text {
  font-size: clamp(52px, 11vw, 132px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink);
}
.brandmoment__inner[data-mark="image"] .brandmoment__img { display: block; }
.brandmoment__inner[data-mark="image"] .brandmoment__text { display: none; }
.brandmoment__rule {
  display: block; height: 1px; width: 0;
  background: var(--accent);
  margin-top: 26px;
}

.brandmoment.is-in .brandmoment__word {
  clip-path: inset(0 0 0 0);
  transform: none;
  transition: clip-path 680ms var(--ease) 120ms, transform 680ms var(--ease) 120ms;
}
.brandmoment.is-in .brandmoment__rule {
  width: 148px;
  transition: width 520ms var(--ease) 420ms;
}
.brandmoment.is-out {
  opacity: 0;
  transition: opacity 400ms var(--ease);
}
.brandmoment.is-out .brandmoment__inner {
  transform: scale(.965);
  transition: transform 400ms var(--ease);
}

/* static fallback: the same composition, arrived at without movement */
.brandmoment[data-reduced="true"] .brandmoment__word { clip-path: none; transform: none; transition: none; }
.brandmoment[data-reduced="true"] .brandmoment__rule { width: 148px; transition: none; }

/* ---------- boot ---------- */
.boot {
  position: fixed; inset: 0; background: var(--surface);
  display: grid; place-items: center; align-content: center; z-index: 40;
  transition: opacity 260ms var(--ease);
}
.boot__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); animation: pulse 1.1s var(--ease) infinite; }
@keyframes pulse { 0%,100% { opacity: .25; } 50% { opacity: 1; } }
.app:not([data-boot="loading"]) .boot { opacity: 0; pointer-events: none; }
.boot__recover { display: grid; gap: 12px; justify-items: center; margin-top: 20px; }
.boot__recover[hidden] { display: none; }
.boot__note { margin: 0; font-size: 14px; color: var(--muted); }
.boot__detail {
  margin: 0; max-width: 34ch; text-align: center;
  font-size: 12px; line-height: 1.5; color: var(--ink-45);
}
.boot__reset {
  border: 1px solid var(--accent-line); border-radius: 999px;
  padding: 9px 18px; font-size: 14px; font-weight: 600;
  color: var(--accent); text-decoration: none; background: var(--accent-soft);
}

/* ======================= MOBILE — 390px target ========================== */
@media (max-width: 899px) {
  :root {
    --gutter: 12px;
    --rail-w: 0px;
    --scene-gap: 16px;
    --fs-hero: 20px;
  }
  .app[data-rail="collapsed"] { --rail-w: 0px; }

  .canvas__scene { align-items: flex-start; }

  /* TWO rows on a phone, never three — every row of chrome is taken straight
     out of the card, which is the thing the customer came to look at.
     Row 1: the mark.  Row 2: one merged control pill. (The side switcher used
     to share row 1; it is under the card now, which is a row back for free.) */
  .chrome { flex-wrap: wrap; gap: 8px; padding: 8px 10px 0; }
  .wordmark { order: 1; flex: 0 0 auto; padding-top: 6px; }
  .hud { order: 3; flex: 1 0 100%; justify-content: center; gap: 0;
         background: var(--paper);
         border: 1px solid var(--line-soft);
         border-radius: 999px;
         box-shadow: var(--shadow-float);
         padding: 3px 6px; }
  .hud__group { background: none; border: 0; box-shadow: none; padding: 0 2px; }
  .wordmark__img { height: 24px; }
  .wordmark__text { font-size: 18px; }

  /* the label is the tooltip's job here; the icon carries it in the pill */
  .newcard { width: 44px; padding: 4px; justify-content: center; }
  .newcard__label { display: none; }
  .newcard.is-confirming { width: auto; padding: 4px 12px; }
  .newcard.is-confirming .newcard__label { display: inline; }
  .switch__label { font-size: 11px; }
  .switch__long { display: none; }
  /* the count carries the meaning; the bar is what does not fit, and a
     second row of chrome costs the card more than the bar is worth */
  .meter__bar { display: none; }
  .meter { gap: 0; padding-right: 2px; }
  .hud__zoom { min-width: 46px; }
  .hud__group { padding: 0; }
  .sides__tabs { padding: 3px 4px; }
  .sides__tip { display: flex; justify-content: center; width: 100%; }
  .underbar { padding: 0 10px calc(10px + env(safe-area-inset-bottom)); }

  /* the rail becomes a bottom drawer over the canvas */
  .rail {
    position: fixed; left: 0; right: 0; bottom: 0;
    width: auto; flex: none;
    z-index: 30;
    max-height: 82dvh;
    flex-direction: column;
    border-right: 0;
    border-top: 1px solid var(--line);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    box-shadow: 0 -8px 40px -12px rgba(0,0,0,.28);
    transform: translateY(101%);
    transition: transform 280ms var(--ease);
  }
  .app[data-drawer="true"] .rail { transform: translateY(0); }
  .rail__tabs {
    flex: 0 0 auto;
    flex-direction: row;
    justify-content: space-around;
    border-right: 0;
    border-bottom: 1px solid var(--line-soft);
    padding: 7px 8px;
  }
  .railtab { flex: 1 1 0; min-height: 52px; justify-content: center; }
  .railtab__label { font-size: var(--fs-small); }
  .rail__body {
    padding: 16px var(--gutter) calc(24px + env(safe-area-inset-bottom));
    max-height: calc(82dvh - 70px);
  }
  .app[data-rail="collapsed"] .rail__body { display: block; }

  .rail-scrim {
    display: block; position: fixed; inset: 0; z-index: 29;
    background: rgba(20,22,28,.34);
    opacity: 0; transition: opacity var(--dur) var(--ease);
  }
  .rail-scrim.is-open { opacity: 1; }

  /* the dock spans the phone, under the chrome and over the card */
  .dock {
    left: 50%;
    width: calc(100vw - 2 * var(--gutter));
    top: calc(var(--chrome-h) + 6px);
  }
  .dock__thread { max-height: min(26dvh, 224px); padding: 14px 15px; gap: 14px; }
  .dock__panel { padding: 12px 12px 9px; }

  .canvas__hint { left: 10px; right: 10px; bottom: calc(var(--underbar-h) + 10px); max-width: none; }

  .fontpop { max-height: min(58dvh, 420px); }

  /* tap targets >= 44px */
  .iconbtn { width: 44px; height: 44px; }
  .hud__zoom { height: 44px; min-width: 50px; }
  .btn { min-height: 44px; }
  .btn--tiny { min-height: 44px; }
  .stepbtn { width: 44px; height: 44px; }
  .seg__btn { min-height: 44px; min-width: 44px; }
  .sendbtn { width: 48px; height: 48px; }
  .switch { min-height: 44px; }
  .inkpick__btn { min-height: 44px; min-width: 44px; padding: 0 13px; }
  .field__input { min-height: 46px; }
  .newcard { min-height: 44px; }
  .dock__toggle { width: 56px; height: 44px; }
  .sidetab { min-height: 44px; padding: 8px 18px; }
  .sideadd { min-height: 44px; padding: 8px 16px; }
  .sidedrop { min-height: 44px; padding: 8px 14px; }
  .sidetip__btn { min-height: 44px; }
  .onswitch { width: 46px; height: 28px; }
  .onswitch__dot { width: 22px; height: 22px; }
  .onswitch.is-on .onswitch__dot { transform: translateX(18px); }
  .fontbtn { min-height: 52px; }
  .fontbtn--sm { min-height: 44px; }
  .fontrow { min-height: 48px; }
  .foldout__summary { min-height: 44px; }
  .hero__line { padding: 8px 6px; --hero-pad: 16px; }

  /* keyboard up: collapse the canvas to a thumbnail so the composer and the
     last messages stay visible (g6: canvas fully covered while typing).
     The dock is at the TOP now, so the keyboard cannot reach it — but the
     chrome it is measured against is hidden, so it is pinned explicitly under
     the "Show card" strip rather than left following a stale --chrome-h. */
  .app.kb-up .canvas__scene,
  .app.kb-up .chrome,
  .app.kb-up .underbar,
  .app.kb-up .canvas__hint { display: none; }
  .app.kb-up .stage__collapse { display: flex; }
  .app.kb-up .dock { top: 66px; }
  .app.kb-up .dock__thread { max-height: min(28dvh, 210px); }

  .stage__collapse {
    position: absolute; top: 10px; left: var(--gutter); right: var(--gutter);
    z-index: 11;
    align-items: center; gap: 10px;
    min-height: 46px;
    padding: 7px 11px;
    border: 1px solid var(--line); border-radius: var(--r-md);
    background: var(--paper);
  }
  .stage__collapse-thumb {
    width: 53px; height: 30px; flex: 0 0 auto;
    border-radius: 3px; background: var(--line-soft);
    background-size: cover; background-position: center;
    box-shadow: 0 1px 2px rgba(0,0,0,.14);
  }
  .stage__collapse-label { font-size: var(--fs-small); color: var(--muted); }
}

@media (min-width: 900px) {
  .stage__collapse { display: none !important; }
}

/* ===================== prefers-reduced-motion ========================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .doc__shimmer {
    animation: none;
    background-image: none;
    background-color: rgba(255,255,255,0.34);
  }
  .thinking__bar > i { animation: none; width: 100%; opacity: .5; }
  .boot__dot { animation: none; opacity: .7; }
  .sendbtn:not(:disabled):hover { transform: none; }
  /* The beacon says the same thing without moving: a stronger, static edge,
     held a little longer by js/beacon.js so it is still noticed. The blanket
     rule above would otherwise reduce the ripple to an invisible 0.001ms. */
  .is-beacon {
    animation: none !important;
    outline-color: var(--accent);
    outline-offset: 4px;
  }
  /* the hero still CYCLES under reduced motion (the words are the point) but
     nothing slides or fades: chat.js swaps the text outright */
  .hero__line.is-out { opacity: 1; transform: none; }
  .hero__line.is-in { animation: none; }
  .sidetab.is-new { animation: none; box-shadow: 0 0 0 3px var(--accent-soft); }
}

/* (the round-4 start overlay lived here; P4 made the start screen a page —
   see "THE ORDERING FLOW" at the end of this file) */
@media (max-width: 860px) {
  .backpick { padding: 5px 6px 5px 10px; }
  .backpick__btn { min-height: 44px; }
  .placebtn { min-height: 44px; }
}

/* Undo / redo live INSIDE the New card group, not beside it: on a 390px phone
   the control row already wraps to two lines, and a third costs the card about
   50px of width — which is the thing the whole workspace is paid in. */
.undogroup { display: inline-flex; align-items: center; gap: 4px; }
@media (max-width: 860px) {
  .undogroup .iconbtn { min-width: 34px; width: 34px; }
}

/* The two homes for undo/redo. Desktop: icons in the control row. Phone: a
   labelled pair in Details, because the control row has no width left and a
   phone has no Ctrl+Z. Exactly one is ever visible. */
.undorow { display: none; gap: 8px; margin: 2px 0 16px; }
.undorow__btn {
  flex: 1 1 0;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--paper); color: var(--ink);
  font-size: var(--fs-small); font-weight: 600;
}
.undorow__btn:disabled { opacity: .38; cursor: default; }
.undorow__icon { display: inline-flex; opacity: .8; }

@media (max-width: 860px) {
  .undogroup { display: none; }
  .undorow { display: flex; }
}

/* ══════════════════════════ THE ORDERING FLOW (P4) ═══════════════════════════
   Start -> designer -> your card -> order placed, plus reorder and "get help
   from a designer". One product, one language: the same tenant tokens, the
   same workspace surface the card was designed on, one accent. Every flow
   screen is a full PAGE laid over the designer (js/pages.js), which stays alive
   and inert underneath. Every colour below is a tenant token or a neutral. */

:root {
  --fs-page: clamp(28px, 2.6vw, 38px);
  --fs-price: clamp(30px, 2.6vw, 36px);
  --bar-h: 64px;
  --order-w: 468px;
  /* a card lying on the table: a hairline of edge, a near shadow, a long soft one */
  --shadow-paper:
    0 0 0 0.5px rgba(20, 22, 28, 0.10),
    0 1px 2px rgba(20, 22, 28, 0.10),
    0 6px 14px -6px rgba(20, 22, 28, 0.16),
    0 30px 50px -24px rgba(20, 22, 28, 0.40);
}

/* ---------- the page shell ---------- */
.page {
  position: fixed; inset: 0; z-index: 35;
  display: flex; flex-direction: column;
  background: var(--surface);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  animation: pageIn .22s var(--ease) both;
}
@keyframes pageIn { from { opacity: 0; } to { opacity: 1; } }

.pagebar {
  position: sticky; top: 0; z-index: 3;
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 20px;
  min-height: var(--bar-h);
  padding: 10px 28px;
  background: var(--surface);
  border-bottom: 1px solid var(--line-soft);
}
@supports (backdrop-filter: blur(6px)) or (-webkit-backdrop-filter: blur(6px)) {
  .pagebar {
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    -webkit-backdrop-filter: blur(12px) saturate(1.2);
    backdrop-filter: blur(12px) saturate(1.2);
  }
}
.pagebar__left, .pagebar__right { flex: 1 1 0; min-width: 0; display: flex; align-items: center; }
.pagebar__right { justify-content: flex-end; }

.pagemark { display: inline-flex; align-items: center; }
.pagemark__img { display: none; height: 30px; width: auto; }
.pagemark__text { font-size: 21px; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.pagemark[data-mark="image"] .pagemark__img { display: block; }
.pagemark[data-mark="image"] .pagemark__text { display: none; }
.pagemark[data-mark="pending"] .pagemark__text { visibility: hidden; }

/* Design · Your card · Order placed — one quiet line that asks nothing */
.steps {
  list-style: none; margin: 0; padding: 0;
  display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-small); color: var(--muted);
}
.steps__item { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.steps__item + .steps__item::before {
  content: ""; width: 26px; height: 1px; background: var(--line); margin-right: 2px;
}
.steps__dot {
  width: 9px; height: 9px; border-radius: 50%;
  border: 1.5px solid var(--ink-45); background: var(--paper);
  flex: 0 0 auto;
}
.steps__item.is-done { color: var(--ink-70); }
.steps__item.is-done .steps__dot { background: var(--accent); border-color: var(--accent); }
.steps__item.is-on { color: var(--ink); font-weight: 600; }
.steps__item.is-on .steps__dot { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ---------- buttons of the flow ---------- */
.btn-primary {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 50px; padding: 0 26px;
  border-radius: 999px;
  background: var(--accent); color: var(--accent-ink);
  font-size: var(--fs-body); font-weight: 600; letter-spacing: -0.005em;
  box-shadow: 0 1px 2px rgba(20, 22, 28, 0.10), 0 10px 24px -14px var(--accent);
  transition: filter var(--dur) var(--ease), opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.1); }
.btn-primary:active:not(:disabled) { transform: translateY(1px); }
.btn-primary:disabled { opacity: .5; cursor: default; box-shadow: none; }
.btn-primary--small { min-height: 42px; padding: 0 18px; font-size: var(--fs-small); }
/* working: a small ring, so a long wait never looks like a dead button */
.btn-primary.is-working::before {
  content: ""; width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.btn-quiet {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 0 16px;
  border-radius: 999px;
  color: var(--accent); font-size: var(--fs-small); font-weight: 600;
  transition: background var(--dur) var(--ease);
}
.btn-quiet:hover:not(:disabled) { background: var(--accent-soft); }
.btn-quiet--inline {
  min-height: 36px; padding: 0 14px; margin-top: 10px;
  border: 1px solid var(--accent-line);
}

.backlink {
  display: inline-flex; align-items: center; gap: 4px;
  min-height: 40px; padding: 0 14px 0 8px;
  border-radius: 999px;
  color: var(--ink-70); font-size: var(--fs-small); font-weight: 500;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.backlink:hover { color: var(--ink); background: var(--accent-soft); }

/* ---------- segmented choice: a white thumb on a quiet track ---------- */
.segctl {
  display: inline-flex; gap: 3px; padding: 3px;
  border-radius: 999px;
  background: var(--workspace);
  border: 1px solid var(--line-soft);
  max-width: 100%;
}
.segctl__btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 40px; padding: 0 16px;
  border-radius: 999px;
  font-size: var(--fs-small); font-weight: 500; color: var(--ink-70);
  white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.segctl__btn:hover:not(:disabled):not(.is-on) { color: var(--ink); }
.segctl__btn.is-on {
  background: var(--paper); color: var(--ink); font-weight: 600;
  box-shadow: 0 1px 2px rgba(20, 22, 28, 0.08), 0 3px 10px -4px rgba(20, 22, 28, 0.18);
}
.segctl__btn:disabled { cursor: default; opacity: .55; }
.segctl__btn.is-soft .segctl__label { color: var(--muted); }
.segctl__sub { color: var(--muted); font-weight: 500; font-variant-numeric: tabular-nums; }
.segctl__btn.is-on .segctl__sub { color: var(--accent); }

/* ---------- form fields ---------- */
.formgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.ofield { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ofield--wide { grid-column: 1 / -1; }
.ofield__label {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font-size: var(--fs-small); font-weight: 500; color: var(--ink-70);
}
.ofield__opt { font-size: 12px; font-weight: 400; color: var(--muted); }
.ofield__input {
  width: 100%;
  min-height: 48px; padding: 10px 14px;
  border: 1.5px solid var(--line); border-radius: var(--r-md);
  background: var(--paper);
  font-size: 16px; line-height: 1.4; color: var(--ink);   /* 16px: iOS never zooms */
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ofield__input:hover { border-color: var(--accent-line); }
.ofield__input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.ofield__input:disabled { opacity: .6; }
.ofield__input--area { resize: vertical; min-height: 110px; }
.ofield__input--code { font-size: 24px; letter-spacing: .28em; font-variant-numeric: tabular-nums; max-width: 260px; }
.ofield.is-invalid .ofield__input { border-color: var(--warn); }
.ofield.is-invalid .ofield__input:focus { box-shadow: 0 0 0 4px var(--warn-soft); }
.ofield__error { font-size: 13px; line-height: 1.45; color: var(--warn-ink); }
.ofield__hint { font-size: 13px; color: var(--muted); }

/* ═══════════════════════════════ START ═══════════════════════════════════ */

.page--start .start__inner {
  width: 100%; max-width: 980px;
  margin: 0 auto;
  padding: clamp(32px, 6vh, 64px) 28px 64px;
  display: flex; flex-direction: column; align-items: center; gap: 30px;
}
.start__title {
  margin: 0;
  font-size: clamp(32px, 4.2vw, 52px); font-weight: 700;
  letter-spacing: -0.035em; line-height: 1.06;
  text-align: center; color: var(--ink);
}
.start__title:focus { outline: none; }
.start__grid {
  width: 100%;
  display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 16px;
}
.ptile-wrap { display: flex; }

.ptile {
  width: 100%;
  display: flex; flex-direction: column; align-items: stretch; gap: 0;
  padding: 0; overflow: hidden;
  text-align: left;
  border: 1.5px solid var(--line-soft);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--shadow-float);
  transition: border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.ptile:not(.ptile--soon):hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow-pop); }
.ptile:not(.ptile--soon):focus-visible { outline-offset: 3px; }
.ptile:disabled { cursor: progress; }

/* the thing itself, lying on the workspace — a card is a card-shaped card */
.ptile-wrap .ptile {
  background:
    linear-gradient(var(--workspace), var(--workspace)) top / 100% 178px no-repeat,
    var(--paper);
}
.ptile__shape {
  position: relative; display: block;
  width: 56%; margin: 34px auto 30px;
  aspect-ratio: var(--ratio, 1.75);
  background: var(--paper);
  border-radius: 3px;
  box-shadow: var(--shadow-paper);
}
.ptile__shape.is-portrait { width: auto; height: 150px; }
.ptile__shape i { position: absolute; left: 10%; height: 5px; border-radius: 3px; background: var(--line); }
.ptile__shape i:nth-child(1) { top: 16%; width: 18%; height: auto; aspect-ratio: 1; border-radius: 50%; background: var(--accent); opacity: .9; }
.ptile__shape i:nth-child(2) { bottom: 32%; width: 46%; background: var(--ink-70); opacity: .8; }
.ptile__shape i:nth-child(3) { bottom: 18%; width: 30%; }
.ptile__text { display: flex; flex-direction: column; gap: 4px; padding: 18px 22px 20px; }
.ptile__label { font-size: 21px; font-weight: 700; letter-spacing: -0.015em; color: var(--ink); }
.ptile__meta { font-size: var(--fs-small); color: var(--muted); }
.ptile__go {
  margin-top: 10px;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-small); font-weight: 600; color: var(--accent);
}
.ptile__go::after { content: "\2192"; transition: transform .16s ease; }
.ptile:hover .ptile__go::after { transform: translateX(3px); }

/* coming soon: visible, honest, not a button — nothing to press, no dead click */
.ptile--soon {
  cursor: default;
  background: transparent;
  box-shadow: none;
  border: 1.5px dashed var(--line);
  align-items: flex-start;
  padding: 26px 22px 20px;
  gap: 18px;
}
.ptile__glyph { display: block; height: 104px; color: var(--ink-45); }
.ptile__glyph svg { height: 100%; width: auto; display: block; }
.ptile--soon .ptile__text { padding: 0; }
.ptile--soon .ptile__label { color: var(--ink-70); }
.ptile__badge {
  align-self: flex-start; margin-top: 6px;
  font-size: 12px; font-weight: 600; letter-spacing: .02em;
  color: var(--accent); background: var(--accent-soft);
  padding: 3px 10px; border-radius: 999px;
}

.page--start .start__sizes { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.start__sizenote { margin: 0; font-size: var(--fs-small); color: var(--ink-70); }
.start__sizelist { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.sizechip {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 8px 15px; min-height: 40px;
  border: 1px solid var(--accent-line); border-radius: 999px;
  background: var(--paper); color: var(--ink); font-size: var(--fs-small);
}
.sizechip[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.sizechip__label { font-weight: 600; }
.sizechip__note { font-size: var(--fs-micro); color: var(--muted); }
.start__go {
  min-height: 48px; padding: 0 30px; border-radius: 999px;
  background: var(--accent); color: var(--accent-ink);
  font-size: var(--fs-body); font-weight: 600; box-shadow: var(--shadow-float);
}
.start__go:disabled { opacity: .45; cursor: default; }

/* the lesser actions: clearly lesser */
.start__more { display: flex; justify-content: center; }
.start__reorder {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: 48px; padding: 0 22px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--paper); color: var(--ink);
  font-size: var(--fs-body); font-weight: 500;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.start__reorder svg { color: var(--accent); }
.start__reorder:hover { border-color: var(--accent-line); background: var(--accent-soft); }

.page--start .start__recent {
  width: 100%; margin-top: 6px; padding-top: 24px;
  border-top: 1px solid var(--line-soft);
  display: flex; flex-direction: column; gap: 4px;
}
.start__subtitle {
  margin: 0; font-size: var(--fs-small); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
}
.start__recentnote { margin: 0 0 12px; font-size: var(--fs-micro); color: var(--ink-45); }
.start__recentlist { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 12px; }
.rcard {
  display: flex; flex-direction: column; gap: 8px; padding: 8px;
  background: var(--paper);
  border: 1px solid var(--line-soft); border-radius: var(--r-md);
  text-align: left;
  transition: border-color .14s ease, transform .14s ease;
}
.rcard:hover { border-color: var(--accent-line); transform: translateY(-1px); }
.rcard__thumb { display: block; aspect-ratio: 1.75; width: 100%; border-radius: 4px; overflow: hidden; background: var(--workspace); }
.rcard__thumb.is-blank { display: flex; align-items: center; justify-content: center; border: 1px dashed var(--line); }
.rcard__blank { font-size: 10.5px; color: var(--ink-45); }
.rcard__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rcard__meta { display: flex; flex-direction: column; gap: 1px; min-width: 0; padding: 0 2px 2px; }
.rcard__title { font-size: var(--fs-small); font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rcard__when { font-size: var(--fs-micro); color: var(--muted); }
.rcard__ordered {
  align-self: flex-start; margin-top: 4px;
  font-size: 11.5px; font-weight: 600; color: var(--accent);
  background: var(--accent-soft); padding: 2px 8px; border-radius: 999px;
}

/* ═══════════════════════════ YOUR CARD ═══════════════════════════════════ */

.page--card { overflow: hidden; }
.cardpage {
  flex: 1 1 auto; min-height: 0;
  display: grid; grid-template-columns: minmax(0, 1fr) var(--order-w);
}

/* left: the proof, on the same workspace the card was designed on */
.cardpage__proof {
  position: relative; min-width: 0; min-height: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px;
  padding: 64px clamp(40px, 4vw, 72px) 36px;
  background-color: var(--workspace);
  background-image: radial-gradient(var(--workspace-dot) 1px, transparent 1px);
  background-size: 24px 24px;
  background-position: -1px -1px;
  overflow: hidden;
}
.cardpage__proof > .backlink { position: absolute; top: 14px; left: 18px; z-index: 2; background: var(--paper); box-shadow: var(--shadow-float); }
.cardpage__proof > .backlink:hover { background: var(--paper); color: var(--accent); }
.cardpage .mock {
  /* as big as the table allows, never taller than the room left for it */
  width: min(680px, 100%, calc((100dvh - var(--bar-h) - 300px) * var(--mock-ratio, 1.75)));
}

.proofnote {
  max-width: 540px; margin: 4px 0 0;
  text-align: center; font-size: var(--fs-small); line-height: 1.5; color: var(--ink-70);
}
.proofnote__strong { font-weight: 600; color: var(--ink); }
.proofnote--warn {
  text-align: left; margin: 0;
  color: var(--warn-ink); background: var(--warn-soft);
  border-left: 2px solid var(--warn);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 10px 14px;
}
.prooflink {
  font-size: var(--fs-small); font-weight: 600; color: var(--accent);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px;
  min-height: 32px; display: inline-flex; align-items: center;
}

/* right: the choices, and the price answering every one of them */
.cardpage__order {
  min-height: 0; min-width: 0;
  display: flex; flex-direction: column;
  background: var(--paper);
  border-left: 1px solid var(--line-soft);
}
.order__scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 30px 32px 28px; }
.order__title { margin: 0; font-size: var(--fs-page); font-weight: 700; letter-spacing: -0.03em; line-height: 1.1; color: var(--ink); }
.order__title:focus { outline: none; }
.order__lead { margin-top: 8px; font-size: var(--fs-small); color: var(--ink-70); line-height: 1.55; }
.order__notice {
  margin-top: 18px; padding: 12px 16px;
  border-left: 2px solid var(--warn); background: var(--warn-soft);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: var(--fs-small); color: var(--ink-70);
}
.order__noticetitle { font-weight: 600; color: var(--warn-ink); }

.osec { margin-top: 26px; }
.osec__title {
  margin: 0 0 10px;
  font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
}
.osec__lead { margin: -4px 0 12px; font-size: var(--fs-small); color: var(--muted); line-height: 1.5; }
.osec__note { margin-top: 8px; font-size: 13px; color: var(--muted); line-height: 1.5; }
.osec__note--action {
  padding: 12px 14px; border-radius: var(--r-md);
  background: var(--accent-soft); color: var(--ink-70);
}
.osec__ctl .segctl { display: flex; width: 100%; }
.osec__ctl .segctl__btn { flex: 1 1 0; }

/* paper */
.stocks { display: flex; flex-direction: column; gap: 8px; }
.stock {
  border: 1.5px solid var(--line); border-radius: var(--r-md);
  background: var(--paper);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.stock:hover { border-color: var(--accent-line); }
.stock.is-on { border-color: var(--accent); background: var(--accent-soft); }
.stock__pick {
  width: 100%; min-height: 62px;
  display: grid; grid-template-columns: 20px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  padding: 12px 16px;
  text-align: left;
}
.stock__dot { position: relative; width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid var(--ink-45); background: var(--paper); }
.stock.is-on .stock__dot { border-color: var(--accent); }
.stock.is-on .stock__dot::after { content: ""; position: absolute; inset: 3.5px; border-radius: 50%; background: var(--accent); }
.stock__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.stock__name { font-size: var(--fs-body); font-weight: 600; color: var(--ink); }
.stock__blurb { font-size: 13px; line-height: 1.4; color: var(--muted); }
.stock__price { display: flex; flex-direction: column; align-items: flex-end; text-align: right; }
.stock__amount { font-size: var(--fs-body); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); }
.stock__for { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.stock__finish { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 0 16px 14px 48px; }
.stock__finishlabel { font-size: 13px; font-weight: 500; color: var(--ink-70); }
.stock.is-on .segctl { background: var(--paper); }
.stock.is-on .segctl__btn.is-on { background: var(--accent); color: var(--accent-ink); box-shadow: none; }

/* quantity */
.qtys { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.qty {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  min-height: 60px; padding: 10px 14px;
  border: 1.5px solid var(--line); border-radius: var(--r-md);
  background: var(--paper); text-align: left;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.qty:hover { border-color: var(--accent-line); }
.qty.is-on { border-color: var(--accent); background: var(--accent-soft); }
.qty__n { font-size: var(--fs-body); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); }
.qty__p { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--muted); }
.qty.is-on .qty__p { color: var(--accent); font-weight: 600; }

/* colour, corners */
.printopts { display: flex; flex-direction: column; gap: 10px; }
.printopt { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.printopt__label { font-size: 13.5px; font-weight: 500; color: var(--ink-70); }

/* rush: a switch row */
.rush {
  position: relative;
  display: flex; align-items: center; gap: 14px;
  padding: 13px 16px; min-height: 62px;
  border: 1.5px solid var(--line); border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.rush:hover { border-color: var(--accent-line); }
.rush:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.rush:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.rush input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.rush__text { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.rush__title { font-size: var(--fs-body); font-weight: 600; color: var(--ink); }
.rush__sub { font-size: 13px; color: var(--muted); }
.rush__fee { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink-70); }
.rush__track {
  position: relative; flex: 0 0 auto;
  width: 44px; height: 26px; border-radius: 999px;
  background: var(--line);
  transition: background var(--dur) var(--ease);
}
.rush__track i {
  position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--paper); box-shadow: 0 1px 3px rgba(20, 22, 28, 0.25);
  transition: transform var(--dur) var(--ease);
}
.rush input:checked ~ .rush__track { background: var(--accent); }
.rush input:checked ~ .rush__track i { transform: translateX(18px); }

.cardpage .formgrid { grid-template-columns: 1fr; }
.order__footnote, .order__helpm { display: none; }

/* the summary: always in view, the price first */
.order__summary {
  flex: 0 0 auto;
  display: flex; flex-direction: column; gap: 9px;
  padding: 18px 32px calc(20px + env(safe-area-inset-bottom));
  background: var(--paper);
  border-top: 1px solid var(--line-soft);
  box-shadow: 0 -14px 28px -24px rgba(20, 22, 28, 0.35);
}
.sum__text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sum__price { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.sum__total {
  font-size: var(--fs-price); font-weight: 700; letter-spacing: -0.025em; line-height: 1.1;
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.sum__unit { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sum__line { font-size: var(--fs-small); color: var(--ink-70); }
.sum__turn { font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sum__place { width: 100%; min-height: 54px; font-size: var(--fs-lead); margin-top: 2px; }
.sum__help { align-self: center; }
.sum__error {
  padding: 11px 14px;
  border-left: 2px solid var(--warn); background: var(--warn-soft);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.sum__errtitle { font-size: var(--fs-small); font-weight: 600; color: var(--warn-ink); }
.sum__errbody { font-size: var(--fs-small); color: var(--ink-70); line-height: 1.5; }

/* ---------- the mockup ---------- */
.mock { position: relative; display: flex; flex-direction: column; align-items: center; }
.mock__stage { position: relative; width: 100%; aspect-ratio: var(--mock-ratio, 1.75); perspective: 1800px; }
.mock__card {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transition: transform .75s cubic-bezier(.2, .7, .2, 1);
}
.mock[data-sides="2"][data-state="ready"] .mock__card { cursor: pointer; }
.mock[data-showing="back"] .mock__card { transform: rotateY(180deg); }
.mock.is-instant .mock__card { transition: none; }
.mock__face {
  position: absolute; inset: 0;
  overflow: hidden;
  background: var(--paper);
  border-radius: 1.5px;
  box-shadow: var(--shadow-paper);
  -webkit-backface-visibility: hidden; backface-visibility: hidden;
  transition: border-radius .25s var(--ease);
}
.mock__face--back { transform: rotateY(180deg); }
.mock[data-sides="1"] .mock__face--back { visibility: hidden; }
.mock[data-corners="rounded"] .mock__face { border-radius: var(--mock-rx) / var(--mock-ry); }
.mock__img { display: block; width: 100%; height: 100%; object-fit: cover; user-select: none; -webkit-user-select: none; transition: filter .3s var(--ease); }
.mock[data-color="bw"] .mock__img { filter: grayscale(1); }
.mock__sheen {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: linear-gradient(115deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, 0.30) 46%, rgba(255, 255, 255, 0) 60%);
  mix-blend-mode: screen;
  transition: opacity .3s var(--ease);
}
.mock[data-finish="gloss"] .mock__sheen { opacity: 1; }
.mock[data-finish="coated"] .mock__sheen { opacity: .35; }

/* the trim, ruled beside the card the way a proof sheet marks it */
.mock__dim { position: absolute; pointer-events: none; color: var(--muted); font-size: 11.5px; letter-spacing: .02em; font-variant-numeric: tabular-nums; }
.mock__dim::before { content: ""; position: absolute; background: var(--ink-45); opacity: .55; }
.mock__dim--w { left: 0; right: 0; bottom: -28px; height: 11px; border-left: 1px solid var(--ink-45); border-right: 1px solid var(--ink-45); display: flex; align-items: center; justify-content: center; }
.mock__dim--w::before { left: 0; right: 0; top: 50%; height: 1px; }
.mock__dim--h { top: 0; bottom: 0; right: -28px; width: 11px; border-top: 1px solid var(--ink-45); border-bottom: 1px solid var(--ink-45); display: flex; align-items: center; justify-content: center; }
.mock__dim--h::before { top: 0; bottom: 0; left: 50%; width: 1px; }
.mock__dimlabel { position: relative; padding: 0 7px; background: var(--workspace); line-height: 1; white-space: nowrap; }
.mock__dim--h .mock__dimlabel { padding: 7px 0; writing-mode: vertical-rl; }
.mock[data-state="loading"] .mock__dim { opacity: .35; }

.mock__loading, .mock__error {
  position: absolute; inset: 0; z-index: 2;
  display: none; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  padding: 18px; text-align: center;
  border-radius: 1.5px;
}
.mock__loading { background: var(--paper); box-shadow: var(--shadow-paper); }
.mock[data-state="loading"] .mock__loading { display: flex; }
.mock[data-state="loading"] .mock__card { visibility: hidden; }
.mock[data-state="refreshing"] .mock__loading { display: flex; background: rgba(255, 255, 255, 0.74); box-shadow: none; }
.mock__loadingbar { position: relative; width: 132px; height: 2px; border-radius: 2px; background: var(--line); overflow: hidden; }
.mock__loadingbar::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 38%;
  border-radius: 2px; background: var(--accent);
  animation: track 1500ms var(--ease) infinite;
}
.mock__loadingtext { font-size: var(--fs-small); color: var(--ink-70); }
.mock__error { background: var(--paper); border: 1.5px dashed var(--line); }
.mock[data-state="error"] .mock__error { display: flex; }
.mock[data-state="error"] .mock__card { visibility: hidden; }
.mock__errtitle { font-weight: 600; color: var(--ink); }
.mock__errbody { font-size: var(--fs-small); color: var(--ink-70); max-width: 380px; }
.mock__erractions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }

.mock__controls { display: flex; align-items: center; gap: 12px; margin-top: 44px; min-height: 44px; }
.mock[data-state="loading"] .mock__controls, .mock[data-state="error"] .mock__controls { visibility: hidden; }
.mock__seg {
  display: inline-flex; gap: 3px; padding: 3px;
  border-radius: 999px; background: var(--paper);
  border: 1px solid var(--line-soft); box-shadow: var(--shadow-float);
}
.mock__tab { min-height: 38px; padding: 0 18px; border-radius: 999px; font-size: var(--fs-small); font-weight: 500; color: var(--ink-70); }
.mock__tab.is-on { background: var(--accent); color: var(--accent-ink); font-weight: 600; }
.mock[data-sides="1"] .mock__seg { display: none; }
.mock__single { font-size: var(--fs-small); color: var(--muted); }
.mock[data-sides="2"] .mock__single { display: none; }
.mock__tag {
  display: none;
  font-size: 12px; font-weight: 600; color: var(--ink-70);
  background: var(--paper); border: 1px solid var(--line); border-radius: 999px; padding: 3px 10px;
}
.mock[data-color="bw"] .mock__tag { display: inline-block; }

/* ═══════════════════════════ CONFIRMATIONS ═══════════════════════════════ */

.done {
  width: 100%; max-width: 900px; margin: 0 auto;
  padding: 44px 28px 72px;
  display: flex; flex-direction: column; gap: 22px;
}
.done__head { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.done__check {
  width: 54px; height: 54px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: var(--accent-ink);
  box-shadow: 0 0 0 7px var(--accent-soft);
  animation: donePop .45s cubic-bezier(.2, .9, .3, 1.3) both;
}
@keyframes donePop { from { transform: scale(.6); opacity: 0; } to { transform: none; opacity: 1; } }
.done__title { margin: 4px 0 0; font-size: clamp(30px, 3.4vw, 44px); font-weight: 700; letter-spacing: -0.035em; line-height: 1.06; color: var(--ink); }
.done__title:focus { outline: none; }
.done__lead { font-size: var(--fs-lead); color: var(--ink-70); }
.done__num { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }

.done__grid {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: 32px; align-items: center;
  padding: 36px 32px;
  border-radius: var(--r-lg);
  background-color: var(--workspace);
  background-image: radial-gradient(var(--workspace-dot) 1px, transparent 1px);
  background-size: 24px 24px;
}
.done__mock .mock__controls { margin-top: 18px; }
.done__facts {
  margin: 0; padding: 4px 18px;
  background: var(--paper);
  border: 1px solid var(--line-soft); border-radius: var(--r-md);
  box-shadow: var(--shadow-float);
}
.done__fact { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
.done__fact:last-child { border-bottom: 0; }
.done__fact dt { font-size: 13px; color: var(--muted); }
.done__fact dd { margin: 0; font-size: var(--fs-small); font-weight: 600; color: var(--ink); text-align: right; overflow-wrap: anywhere; }

.done__notice {
  padding: 16px 20px;
  border-left: 2px solid var(--accent); background: var(--accent-soft);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.done__noticetitle { font-weight: 700; color: var(--ink); }
.done__noticebody { margin-top: 4px; color: var(--ink-70); line-height: 1.55; }
.done__lede { font-weight: 600; color: var(--ink); margin-top: 2px; }
.done__steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.done__step {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 16px; border: 1px solid var(--line-soft); border-radius: var(--r-md); background: var(--paper);
}
.done__stepn {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent); font-size: 13px; font-weight: 700;
}
.done__steptext { display: flex; flex-direction: column; gap: 2px; }
.done__steptitle { font-weight: 600; color: var(--ink); line-height: 1.35; }
.done__stepwhen { font-size: 13px; color: var(--muted); }
.done__small { font-size: var(--fs-small); color: var(--muted); }
.done__phone { color: var(--accent); font-weight: 600; text-decoration: none; }
.done__phone:hover { text-decoration: underline; }
.done__actions { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 6px; }

/* ════════════════════ REORDER · GET HELP FROM A DESIGNER ═════════════════ */

.flowcol {
  width: 100%; max-width: 580px; margin: 0 auto;
  padding: 26px 24px 72px;
  display: flex; flex-direction: column; align-items: stretch; gap: 16px;
}
.flowcol > .backlink { align-self: flex-start; margin-left: -8px; }
.flowcol--help { max-width: 720px; }
.flow__title { margin: 6px 0 0; font-size: var(--fs-page); font-weight: 700; letter-spacing: -0.03em; line-height: 1.1; color: var(--ink); }
.flow__title:focus { outline: none; }
.flow__lead { font-size: var(--fs-lead); line-height: 1.55; color: var(--ink-70); }
.flow__lead strong { color: var(--ink); overflow-wrap: anywhere; }
.flow__small { font-size: var(--fs-small); line-height: 1.55; color: var(--muted); }
.flow__small a { color: var(--accent); font-weight: 600; }
.flow__form { display: flex; flex-direction: column; align-items: stretch; gap: 14px; margin-top: 4px; }
.flow__form > .btn-primary { align-self: flex-start; }
.flow__links { display: flex; gap: 6px; flex-wrap: wrap; margin-left: -12px; }
.flow__error {
  padding: 12px 16px;
  border-left: 2px solid var(--warn); background: var(--warn-soft);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.flow__error.is-ok { border-left-color: var(--accent); background: var(--accent-soft); }
.flow__errtitle { font-weight: 600; color: var(--warn-ink); }
.flow__error.is-ok .flow__errtitle { color: var(--accent); }
.flow__errbody { font-size: var(--fs-small); color: var(--ink-70); line-height: 1.5; }
.flow__fee {
  padding: 14px 18px;
  border-left: 2px solid var(--accent); background: var(--accent-soft);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.flow__feetitle { font-weight: 700; color: var(--ink); }
.flow__feebody { margin-top: 2px; color: var(--ink-70); line-height: 1.5; }
.flow__attach {
  display: flex; align-items: center; gap: 16px;
  padding: 12px; border: 1px solid var(--line-soft); border-radius: var(--r-md); background: var(--paper);
}
.flow__thumb {
  flex: 0 0 auto; width: 108px; aspect-ratio: 1.75;
  border-radius: 2px; overflow: hidden; background: var(--workspace);
  box-shadow: var(--shadow-paper);
}
.flow__thumb.is-blank { box-shadow: none; border: 1px dashed var(--line); }
.flow__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.flow__attachtext { font-size: var(--fs-small); color: var(--ink-70); line-height: 1.5; }
.flowcol--help .formgrid { margin-top: 4px; }

.porders { display: flex; flex-direction: column; gap: 8px; }
.porder {
  display: grid; grid-template-columns: 72px minmax(0, 1fr) auto; align-items: center; gap: 14px;
  min-height: 70px; padding: 12px 16px;
  border: 1.5px solid var(--line); border-radius: var(--r-md); background: var(--paper);
  text-align: left;
  transition: border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.porder:hover { border-color: var(--accent); transform: translateY(-1px); }
.porder__thumb { width: 72px; aspect-ratio: 1.75; border-radius: 2px; overflow: hidden; background: var(--workspace); box-shadow: var(--shadow-paper); }
.porder__thumb.is-blank { box-shadow: none; border: 1px dashed var(--line); }
.porder__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.porder__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.porder__title { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.porder__meta { font-size: 13px; color: var(--muted); }
.porder__price { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink); }
.reorder__card { padding: 14px 18px; border: 1px solid var(--line-soft); border-radius: var(--r-md); background: var(--paper); }
.reorder__what { font-weight: 600; color: var(--ink); }
.reorder__last { margin-top: 2px; font-size: var(--fs-small); color: var(--muted); }

/* ═════════════════ the designer's two new doors (P4) ═════════════════════ */

.dock__next { display: flex; justify-content: flex-end; }
.nextbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 48px; padding: 0 20px 0 24px;
  border-radius: 999px;
  background: var(--accent); color: var(--accent-ink);
  font-size: var(--fs-body); font-weight: 600; letter-spacing: -0.005em;
  box-shadow: 0 1px 2px rgba(20, 22, 28, 0.10), 0 12px 28px -14px var(--accent);
  transition: filter var(--dur) var(--ease), transform var(--dur) var(--ease);
  animation: nextIn .32s var(--ease) both;
}
@keyframes nextIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.nextbtn:hover { filter: brightness(1.1); transform: translateY(-1px); }
.nextbtn svg { transition: transform var(--dur) var(--ease); }
.nextbtn:hover svg { transform: translateX(2px); }

.dock__foot { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.dock__foot .disclosure { flex: 1 1 auto; min-width: 0; }
.helplink {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 28px; margin-top: -4px; padding: 0 10px;
  border-radius: 999px;
  font-size: var(--fs-micro); font-weight: 600; color: var(--accent);
  white-space: nowrap;
  transition: background var(--dur) var(--ease);
}
.helplink:hover { background: var(--accent-soft); }
.cap__help {
  margin-top: 9px; min-height: 36px; padding: 0 14px;
  border: 1px solid var(--accent-line); border-radius: 999px;
  font-size: var(--fs-small); font-weight: 600; color: var(--accent);
}
.cap__help:hover { background: var(--accent-soft); }

/* ═══════════════════════════ PHONES (390px) ══════════════════════════════ */
@media (max-width: 899px) {
  :root { --bar-h: 56px; }
  .pagebar { padding: 8px 16px; gap: 12px; }
  .pagemark__img { height: 22px; }
  .pagemark__text { font-size: 17px; }
  /* one line of chrome: the dots, and only the current step's word */
  .steps { gap: 6px; }
  .steps__item + .steps__item::before { width: 12px; }
  .steps__item:not(.is-on) .steps__label { display: none; }
  .pagebar__right { display: none; }

  .btn-primary { min-height: 52px; }
  .segctl__btn { min-height: 44px; padding: 0 14px; }
  .formgrid { grid-template-columns: 1fr; }

  /* start */
  .page--start .start__inner { padding: 28px 16px 48px; gap: 22px; }
  .start__title { font-size: 31px; }
  .start__grid { grid-template-columns: 1fr 1fr; gap: 12px; }
  .ptile-wrap { grid-column: 1 / -1; }
  .ptile-wrap .ptile {
    background:
      linear-gradient(var(--workspace), var(--workspace)) top / 100% 150px no-repeat,
      var(--paper);
  }
  .ptile__shape { width: 52%; margin: 28px auto 26px; }
  .ptile__text { padding: 14px 18px 16px; }
  .ptile__label { font-size: 19px; }
  .ptile--soon { padding: 18px 16px 16px; gap: 12px; }
  .ptile__glyph { height: 64px; }
  .ptile--soon .ptile__label { font-size: 16px; }
  .start__reorder { width: 100%; justify-content: center; min-height: 52px; }
  .start__recentlist { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }

  /* your card: one column, the proof first, the price pinned to the bottom */
  .page--card { overflow-y: auto; }
  .cardpage { display: block; }
  .cardpage__proof { padding: 62px 44px 22px 16px; gap: 10px; justify-content: flex-start; overflow: visible; }
  .cardpage__proof > .backlink { top: 10px; left: 12px; }
  .cardpage .mock { width: 100%; }
  .mock__dim--w { bottom: -24px; }
  .mock__dim--h { right: -24px; }
  .mock__controls { margin-top: 36px; }
  .mock__tab { min-height: 44px; }
  .proofnote { font-size: 13px; }
  .cardpage__order { border-left: 0; border-top: 1px solid var(--line-soft); }
  .order__scroll { overflow: visible; padding: 22px 16px 16px; }
  .osec { margin-top: 24px; }
  .stock__pick { padding: 12px 14px; gap: 10px; }
  .stock__finish { padding: 0 14px 14px; }
  .qty { min-height: 58px; padding: 9px 12px; }
  .printopt { flex-direction: column; align-items: stretch; gap: 6px; }
  .printopt .segctl { display: flex; }
  .printopt .segctl__btn { flex: 1 1 0; }
  .order__footnote { display: block; margin-top: 22px; font-size: 13px; line-height: 1.5; color: var(--muted); }
  .order__helpm { display: flex; margin: 10px auto 0; }
  .order__summary {
    position: sticky; bottom: 0; z-index: 2;
    flex-direction: row; flex-wrap: wrap; align-items: center; gap: 8px 12px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  }
  .sum__text { flex: 1 1 auto; }
  .sum__total { font-size: 25px; }
  .sum__unit, .sum__turn, .sum__help { display: none; }
  .sum__line { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .sum__place { width: auto; flex: 0 0 auto; min-height: 52px; padding: 0 22px; font-size: var(--fs-body); margin: 0; }
  .sum__error { flex: 1 0 100%; order: -1; }

  /* confirmations */
  .done { padding: 26px 16px 56px; gap: 18px; }
  .done__grid { grid-template-columns: 1fr; padding: 26px 18px; gap: 22px; }
  .done__steps { grid-template-columns: 1fr; }
  .done__actions .btn-primary, .done__actions .btn-quiet { flex: 1 1 100%; }

  /* flows */
  .flowcol { padding: 16px 16px 56px; gap: 14px; }
  .flow__lead { font-size: var(--fs-body); }
  .flow__form > .btn-primary { align-self: stretch; }
  .porder { grid-template-columns: 60px minmax(0, 1fr) auto; padding: 10px 12px; gap: 12px; }
  .porder__thumb { width: 60px; }
  .flow__thumb { width: 88px; }

  /* the designer on a phone: the card is paid for in dock height, so the next
     step takes its own row but the thread gives that row back while it shows,
     and the help link rides on the disclosure line (an invisible 44px hit area
     around it instead of a 44px row) */
  .dock__next .nextbtn { width: 100%; min-height: 52px; }
  .app.kb-up .dock__next { display: none; }
  .dock[data-next="true"] .dock__thread { max-height: min(17dvh, 150px); }
  .dock__foot { display: block; padding: 0 6px; }
  .dock__foot .disclosure { display: inline; padding: 0; }
  .helplink {
    position: relative; display: inline-flex; vertical-align: baseline;
    min-height: 0; margin: 0 0 0 5px; padding: 0;
    font-size: var(--fs-micro); line-height: 1.45;
  }
  .helplink:hover { background: none; text-decoration: underline; }
  .helplink svg { display: none; }
  .helplink::after { content: ""; position: absolute; inset: -14px -8px; }
  .cap__help { min-height: 44px; }
  .sum__text { flex: 1 1 0; }
  .porder__title { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
}

/* the designer on a desktop: the next step sits in the dock's top row, beside
   the collapse pill, so it costs the card no height at all */
@media (min-width: 900px) {
  /* R6b: the next step is no longer tucked into the dock's top row — it moved
     to the underbar, with the card (see ".underbar .dock__next" above). The
     absolute positioning that used to keep it from costing the card any height
     is gone with it: in the underbar it shares a line that already exists. */
}

@media (prefers-reduced-motion: reduce) {
  .page, .nextbtn, .done__check { animation: none; }
  .mock__card { transition: none; }
  .mock__loadingbar::after { animation: none; width: 100%; opacity: .5; }
  .btn-primary.is-working::before { animation: none; border-right-color: currentColor; opacity: .6; }
  .ptile:not(.ptile--soon):hover, .rcard:hover, .porder:hover { transform: none; }
}

/* ─────────────────────────── Text window (Text v2, Sept 28) ───────────────────────────
   Owner: "The text box should not come up on the canvas like the floating text
   tool... it should just come on the side... a small rectangular kind of like a
   window... You can stack the options." A compact window at the right of the
   workspace; the font list and colour picker open INSIDE it (never past its
   edge); on a phone it is a sheet along the bottom. */
@media (min-width: 900px) {
  html.has-textwin { --textwin-room: 288px; }
}
.textwin {
  /* no green in this studio (owner, P2-R3): reads-well is the accent */
  --tw-good: var(--accent);
  --tw-okay: #9A6B12;
  --tw-poor: #B23A2E;
  position: absolute;
  top: calc(var(--chrome-h, 64px) + 4px);
  right: 16px;
  z-index: 30;
  width: 272px;
  max-height: calc(100% - var(--chrome-h, 64px) - 20px);
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-pop);
  overflow: hidden;
  animation: textwin-in .16s ease-out;
}
.textwin[hidden] { display: none; }
@keyframes textwin-in { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .textwin { animation: none; } }

.textwin__head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 10px 10px 14px;
  border-bottom: 1px solid var(--line-soft);
  flex: none;
}
.textwin__title { margin: 0; font-size: 13px; font-weight: 700; color: var(--ink); }
.textwin__which {
  flex: 1; min-width: 0; font-size: 12px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.textwin__close {
  display: inline-grid; place-items: center; width: 28px; height: 28px;
  border: 0; border-radius: var(--r-sm); background: transparent; color: var(--muted); cursor: pointer;
}
.textwin__close:hover { background: var(--accent-soft); color: var(--ink); }

.textwin__body {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px;
  padding: 12px 14px 14px;
  overflow-y: auto; overscroll-behavior: contain;
}
.textwin__group { min-width: 0; }
.textwin__label {
  margin: 0 0 6px; font-size: 10.5px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--muted);
}
.textwin__labelrow { display: flex; justify-content: space-between; align-items: baseline; }
.textwin__val { font-size: 12px; color: var(--ink); font-variant-numeric: tabular-nums; }

.textwin__font { width: 100%; }
.textwin__fontslot:empty { display: none; }
.textwin__fontslot { margin-top: 6px; }

.textwin__sizerow { display: flex; gap: 8px; align-items: center; }
.textwin__size {
  flex: 1; display: inline-flex; align-items: center; height: 34px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper);
}
.textwin__step {
  display: inline-grid; place-items: center; width: 32px; height: 32px;
  border: 0; background: transparent; color: var(--ink); cursor: pointer; border-radius: var(--r-sm);
}
.textwin__sizein {
  width: 100%; min-width: 0; border: 0; background: transparent; text-align: center;
  font: inherit; font-size: 13px; color: var(--ink); font-variant-numeric: tabular-nums;
}
.textwin__sizein:focus { outline: none; }
.textwin__unit { font-size: 12px; color: var(--muted); padding-right: 2px; }

.textwin__tog {
  display: inline-grid; place-items: center; min-width: 34px; height: 34px; padding: 0 8px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper);
  color: var(--ink); cursor: pointer; font: inherit; font-size: 14px;
}
.textwin__bold { font-weight: 800; }
.textwin__seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.textwin__seg .textwin__tog { width: 100%; }

.textwin__step:hover:not([aria-disabled="true"]),
.textwin__tog:hover:not([aria-disabled="true"]) { background: var(--accent-soft); }
.textwin__tog[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.textwin [aria-disabled="true"] { color: rgba(22, 24, 28, .28); cursor: not-allowed; background: var(--surface); }

.textwin__note, .textwin__fit { margin: 6px 0 0; font-size: 12px; line-height: 1.35; }
.textwin__note { color: var(--tw-okay); }
.textwin__fit { color: var(--muted); }

.textwin__range { width: 100%; margin: 0; accent-color: var(--accent); }

.textwin__colbtn {
  width: 100%; display: flex; align-items: center; gap: 10px; height: 38px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); cursor: pointer; font: inherit;
}
.textwin__colbtn:hover { border-color: var(--accent-line); }
.textwin__dot {
  width: 20px; height: 20px; flex: none; border-radius: 50%;
  border: 1px solid var(--line); box-shadow: inset 0 0 0 2px var(--paper);
}
.textwin__hex { font-size: 12.5px; color: var(--ink); font-variant-numeric: tabular-nums; }
.textwin__pill {
  margin-left: auto; font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 999px;
  color: #fff; background: var(--muted); font-variant-numeric: tabular-nums;
}
.textwin__pill:empty { display: none; }
.textwin__pill[data-tone="good"] { background: var(--tw-good); }
.textwin__pill[data-tone="okay"] { background: var(--tw-okay); }
.textwin__pill[data-tone="poor"] { background: var(--tw-poor); }

.textwin__cp {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; margin-top: 8px; padding: 12px;
  border: 1px solid var(--line-soft); border-radius: var(--r-sm); background: var(--surface);
}
.textwin__cp[hidden] { display: none; }
.textwin__cp .textwin__label { margin: 2px 0 -4px; }
.textwin__cp [hidden] { display: none; }
.textwin__auto {
  justify-self: start; height: 30px; padding: 0 12px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--paper); cursor: pointer; font: inherit; font-size: 12.5px; color: var(--ink);
}
.textwin__auto[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.textwin__chips { display: flex; flex-wrap: wrap; gap: 7px; }
.textwin__chip {
  width: 26px; height: 26px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid var(--line); box-shadow: inset 0 0 0 2px var(--paper);
}
.textwin__chip[aria-pressed="true"] { outline: 2px solid var(--accent); outline-offset: 2px; }
.textwin__best { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6px; }
.textwin__bestbtn {
  display: flex; align-items: center; gap: 7px; min-width: 0; padding: 6px 7px; text-align: left;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); cursor: pointer; font: inherit;
}
.textwin__bestbtn:hover { border-color: var(--accent-line); }
.textwin__besttxt { min-width: 0; overflow: hidden; }
.textwin__besttxt b { display: block; font-size: 12px; font-variant-numeric: tabular-nums; }
.textwin__besttxt small { display: block; font-size: 10.5px; color: var(--muted); }
.textwin__sv {
  position: relative; height: 120px; border-radius: var(--r-sm); cursor: crosshair; touch-action: none;
  background: linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, hsl(var(--h, 0) 100% 50%));
}
.textwin__knob {
  position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px; border-radius: 50%; pointer-events: none;
  border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.35), 0 2px 6px rgba(0,0,0,.3);
}
.textwin__hue {
  -webkit-appearance: none; appearance: none; width: 100%; height: 12px; margin: 0; border-radius: 6px;
  /* the full spectrum, written in hue like the shade square beside it. It is the
     customer's colour choice, so it has to include green; the studio's own
     chrome stays green-free (the designer gate's sweep checks that). */
  background: linear-gradient(to right, hsl(0 100% 50%), hsl(60 100% 50%), hsl(120 100% 50%),
    hsl(180 100% 50%), hsl(240 100% 50%), hsl(300 100% 50%), hsl(360 100% 50%));
}
.textwin__hue::-webkit-slider-thumb {
  -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%; cursor: pointer;
  background: #fff; border: 1px solid rgba(0,0,0,.3); box-shadow: 0 1px 4px rgba(0,0,0,.3);
}
.textwin__hue::-moz-range-thumb { width: 16px; height: 16px; border-radius: 50%; background: #fff; border: 1px solid rgba(0,0,0,.3); cursor: pointer; }
.textwin__hexrow { display: flex; gap: 6px; }
.textwin__hexin {
  flex: 1; min-width: 0; height: 32px; padding: 0 8px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--paper); color: var(--ink); font: 500 13px/1 ui-monospace, 'SFMono-Regular', Menlo, monospace;
  text-transform: uppercase;
}
.textwin__pick {
  display: inline-flex; align-items: center; gap: 5px; height: 32px; padding: 0 9px; white-space: nowrap;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); cursor: pointer;
  font: inherit; font-size: 12px; color: var(--ink);
}
.textwin__pick[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.textwin__verdict { margin: 0; font-size: 12px; color: var(--muted); line-height: 1.35; }
.textwin__verdict[data-tone="poor"] { color: var(--tw-poor); }

.textwin__foot { padding-top: 12px; border-top: 1px solid var(--line-soft); }
.textwin__remove {
  width: 100%; height: 34px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--paper); color: var(--ink); cursor: pointer; font: inherit; font-size: 13px;
}
.textwin__remove:hover { background: var(--warn-soft); border-color: var(--warn); color: var(--warn-ink); }

/* the eyedropper is armed: the whole card is a colour to take */
.is-picking-colour .trim, .is-picking-colour .trim * { cursor: crosshair !important; }

/* the typeface list, opened inside the Text window rather than over the page */
.fontpop.fontpop--inline {
  position: static; width: auto !important; max-height: 260px;
  box-shadow: none; border: 1px solid var(--line); border-radius: var(--r-sm);
}

/* one explainer for every control (tips.js) */
.tip {
  position: fixed; z-index: 1000; left: 0; top: 0; max-width: 240px; pointer-events: none;
  padding: 6px 9px; border-radius: 7px; background: var(--ink); color: #fff;
  font-size: 12px; line-height: 1.35; box-shadow: 0 6px 18px rgba(0,0,0,.18);
  opacity: 0; transition: opacity .1s ease;
}
.tip.is-on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .tip { transition: none; } }

@media (max-width: 899px) {
  .textwin {
    position: fixed; top: auto; left: 8px; right: 8px; bottom: 8px; width: auto;
    max-height: 56vh; z-index: 60; border-radius: var(--r-lg);
    animation-name: textwin-up;
  }
  @keyframes textwin-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
}

/* ─────────────── Text v2 step 2: the box is as big as the words ───────────────
   The words are an inline box, as wide as they are; the line's box stays the
   (invisible) room it may grow into. Selection, hover and editing outline the
   WORDS, and the selected line gets four corner handles that scale the type. */
.cl-field .cl-text { display: inline-block; vertical-align: top; }
.cl-field.is-selected::before, .cl-field.is-editing::before { outline: none; background: transparent; }
.cl-field:hover:not(.is-selected):not(.is-dragging) .cl-text { outline: 1px dashed rgba(127, 127, 127, .6); outline-offset: 3px; }
.cl-field.is-editing .cl-text { outline: 1.5px solid var(--accent); outline-offset: 3px; }
.cl-frame {
  position: absolute; z-index: 4; box-sizing: content-box;
  margin: -4px 0 0 -4px; padding: 3px;
  border: 1.5px solid var(--accent); border-radius: 3px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .65);
  pointer-events: none;
}
.cl-frame[hidden] { display: none; }
.cl-handle {
  position: absolute; width: 10px; height: 10px; box-sizing: border-box;
  background: #fff; border: 1.5px solid var(--accent); border-radius: 50%;
  pointer-events: auto; touch-action: none;
}
.cl-handle[data-h="nw"] { left: -6px; top: -6px; cursor: nwse-resize; }
.cl-handle[data-h="ne"] { right: -6px; top: -6px; cursor: nesw-resize; }
.cl-handle[data-h="sw"] { left: -6px; bottom: -6px; cursor: nesw-resize; }
.cl-handle[data-h="se"] { right: -6px; bottom: -6px; cursor: nwse-resize; }
@media (pointer: coarse) {
  .cl-handle { width: 16px; height: 16px; }
  .cl-handle[data-h="nw"], .cl-handle[data-h="sw"] { left: -9px; }
  .cl-handle[data-h="ne"], .cl-handle[data-h="se"] { right: -9px; }
  .cl-handle[data-h="nw"], .cl-handle[data-h="ne"] { top: -9px; }
  .cl-handle[data-h="sw"], .cl-handle[data-h="se"] { bottom: -9px; }
}

/* ─────────────── Text v2 step 2b: the grab area hugs the words too ───────────────
   The line's box is only the room it may grow into — stretched as the words
   grow, scaled by a corner — and can be far wider than the words. Taking the
   pointer across the whole box stole a logo's drag and the next line's taps.
   So the box ignores the pointer; the WORDS take it, with the same vertical
   allowance as before (--hit-y: half the gap to the nearest line, up to 4px). */
.cl-field { pointer-events: none; }
.cl-field::before { content: none; }
.cl-field .cl-text { pointer-events: auto; cursor: grab; }
.cl-field.is-dragging .cl-text { cursor: grabbing; }
.cl-field.is-editing .cl-text { cursor: text; }
.cl-field .cl-text::before {
  content: ""; position: absolute; z-index: -1;
  inset: calc(-1 * var(--hit-y, 4px)) -6px;
  border-radius: 3px;
}
.cl-field.is-dragging .cl-text::before { background: rgba(127, 127, 127, .10); }
.cl-field.is-over .cl-text::before { outline: 1px solid var(--warn); }
/* The words are an inline box: without this the line box would add its own
   font's strut under them, every box would grow a few px taller than its
   words, and stacked lines would overlap. The words set their own size inline. */
.cl-field { font-size: 0; line-height: 0; }
.textwin__italic { font-family: Georgia, 'Times New Roman', serif; font-style: italic; font-size: 16px; }

/* Text v2 step 4: free text keeps the customer's own line breaks */
.cl-field.is-free .cl-text { white-space: pre; }
.addtextbtn {
  width: 100%; min-height: 44px; margin: 4px 0 2px; border: 1px dashed var(--accent-line);
  border-radius: var(--r-md); background: transparent; color: var(--accent); font: inherit; font-weight: 600;
  cursor: pointer;
}
.addtextbtn:hover { background: var(--accent-soft); }
/* an address fitted onto two lines shows the break the press prints */
.cl-field.is-two-line .cl-text { white-space: pre; }

/* Contact icons (owner, Oct 6): a line icon in front of the phone, email,
   website and address, in the line's colour. Its size and place are set in em
   of the line's own type by contact-layer.js (contact-icons.js holds the
   numbers the composer prints with); this only shows and hides it. */
.cl-field .cl-icon { display: none; }
.cl-field.has-icon .cl-icon {
  display: inline-block; overflow: visible;
  position: relative; z-index: 1; pointer-events: none;
}

/* the Text window's icons switch */
.textwin__switch {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  height: 38px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper);
  color: var(--ink); cursor: pointer; font: inherit; font-size: 13px; text-align: left;
}
.textwin__switch:hover { border-color: var(--accent-line); }
.textwin__knobtrack {
  flex: none; position: relative; width: 32px; height: 18px; border-radius: 9px;
  background: var(--line); transition: background .15s ease;
}
.textwin__knobtrack::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
  border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .25);
  transition: transform .15s ease;
}
.textwin__switch[aria-checked="true"] .textwin__knobtrack { background: var(--accent); }
.textwin__switch[aria-checked="true"] .textwin__knobtrack::after { transform: translateX(14px); }
@media (prefers-reduced-motion: reduce) {
  .textwin__knobtrack, .textwin__knobtrack::after { transition: none; }
}

/* F2: a die-cut product's cut, on the canvas only (door hangers). The press's
   cut line is magenta by trade convention; the inside reads as cut away. */
.die-overlay { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 6; overflow: visible; }
.die-overlay .die-cut {
  fill: var(--workspace);
  stroke: #D6247F; stroke-width: 1.5px; stroke-dasharray: 5 3;
  vector-effect: non-scaling-stroke;
}
