/* ── The builder shell ───────────────────────────────────────────────────────
   One chrome for all four editors: the admin column-layout builder, the admin
   free canvas, the customer's Quick Build and the customer's free canvas.

   The shape is always the same — a thin toolbar across the top, a fixed-width
   sidebar of collapsible panels down the left, and the real newspaper filling
   whatever is left. Controls live in the sidebar, so the page you are actually
   judging gets the room.

   Everything is a `bx-` class driven by the custom properties below, which is
   what lets the admin (dark) and the customer (light) share one stylesheet:
   only the tokens change, never the rules. Add `.bx-dark` for the admin.

   Loaded on every page by `stylesheet_link_tag :app`, so every selector here is
   namespaced under a `bx-` class and can't leak into the rest of the site.
   ────────────────────────────────────────────────────────────────────────── */

.bx-shell {
  /* Surfaces */
  --bx-bg: #f1ede4;
  --bx-panel: #fffdf8;
  --bx-sunken: #fdfbf5;
  --bx-mat: #e9e6df;
  /* Lines */
  --bx-line: rgba(29, 24, 18, 0.12);
  --bx-line-strong: rgba(29, 24, 18, 0.2);
  /* Ink: body, secondary, faint labels */
  --bx-ink: #1d1812;
  --bx-ink-2: #6b6255;
  --bx-ink-3: #9a9082;
  /* Accent + the one destructive colour */
  --bx-accent: #b76e79;
  --bx-accent-ink: #8f4d57;
  --bx-accent-soft: rgba(183, 110, 121, 0.09);
  --bx-danger: #b4434f;
  --bx-danger-soft: rgba(180, 67, 79, 0.08);

  --bx-sidebar: 306px;
  --bx-radius: 9px;
  /* What's already pinned above the shell (the site header) and how tall the
     shell's own toolbar is. Measured by builder_shell_controller; the fallbacks
     are what a shell with no JavaScript yet gets. */
  --bx-top: 0px;
  --bx-toolbar-h: 3.3rem;

  display: flex;
  flex-direction: column;
  position: relative;
  background: var(--bx-bg);
  color: var(--bx-ink);
  font-family: "Jost", system-ui, -apple-system, sans-serif;
}

.bx-shell.bx-dark {
  --bx-bg: rgb(2 6 23);
  --bx-panel: rgb(15 23 42);
  --bx-sunken: rgb(2 6 23);
  --bx-line: rgb(30 41 59);
  --bx-line-strong: rgb(51 65 85);
  --bx-ink: rgb(226 232 240);
  --bx-ink-2: rgb(148 163 184);
  --bx-ink-3: rgb(100 116 139);
  --bx-accent: rgb(244 114 182);
  --bx-accent-ink: rgb(244 114 182);
  --bx-accent-soft: rgba(244, 114, 182, 0.1);
  --bx-danger: rgb(248 113 113);
  --bx-danger-soft: rgba(127, 29, 29, 0.35);
}

/* A builder that owns the whole window (the customer editors) rather than
   sitting inside a page of admin chrome. */
.bx-shell.bx-full { min-height: 100vh; }
/* A builder embedded in a page of other chrome (the admin) gets a card of its
   own. The corners are rounded on the children rather than clipped on the
   shell: an `overflow` here would make it the scroll container, and the sticky
   toolbar and sidebar inside would quietly stop sticking. */
.bx-shell.bx-boxed { border: 1px solid var(--bx-line); border-radius: 14px; }
.bx-boxed > .bx-toolbar { border-radius: 13px 13px 0 0; }
.bx-boxed > .bx-body > .bx-sidebar { border-bottom-left-radius: 13px; }
.bx-boxed > .bx-body > .bx-stage { border-bottom-right-radius: 13px; }

/* ── Top toolbar ─────────────────────────────────────────────────────────────
   Deliberately thin: the mode switch, how the save is going, and the one
   destructive button. Everything else belongs in the sidebar. */
.bx-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.9rem; flex-wrap: wrap;
  padding: 0.55rem 0.95rem;
  background: var(--bx-panel);
  border-bottom: 1px solid var(--bx-line);
}
.bx-toolbar-group { display: flex; align-items: center; gap: 0.55rem; min-width: 0; }
.bx-toolbar-group.is-tight { gap: 0.3rem; }
.bx-toolbar-sep { width: 1px; align-self: stretch; margin: 0.1rem 0.2rem; background: var(--bx-line); }
.bx-toolbar-label { display: block; font-size: 0.58rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--bx-ink-3); }
.bx-toolbar-name {
  min-width: 11rem; padding: 2px 0;
  border: 0; border-bottom: 1px solid var(--bx-line-strong); background: transparent;
  font-family: "Playfair Display", Georgia, serif; font-size: 1.02rem; color: var(--bx-ink);
}
.bx-toolbar-name:focus { outline: none; border-bottom-color: var(--bx-accent); }
.bx-back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; flex: none;
  border: 1px solid var(--bx-line); border-radius: 999px;
  color: var(--bx-ink-2); font-size: 1.05rem; text-decoration: none;
}
.bx-back:hover { border-color: var(--bx-accent); color: var(--bx-accent-ink); }

/* Which editor you're in. Two ways of building the same paper, so they read as
   one control with a side lit rather than as two rival buttons. */
.bx-modes {
  display: inline-flex; align-items: center; gap: 2px; padding: 2px;
  border: 1px solid var(--bx-line-strong); border-radius: 999px; background: var(--bx-sunken);
}
.bx-modes form { display: contents; }
.bx-mode {
  border: 0; border-radius: 999px; background: none;
  padding: 0.34rem 0.8rem;
  font: inherit; font-size: 0.73rem; line-height: 1.2; color: var(--bx-ink-2);
  white-space: nowrap; cursor: pointer; transition: background 0.12s, color 0.12s;
}
.bx-mode:hover:not(.is-on) { color: var(--bx-ink); }
.bx-mode.is-on { background: var(--bx-accent); color: #fff; cursor: default; }
.bx-dark .bx-mode.is-on { color: rgb(15 23 42); }

.bx-status { font-size: 0.76rem; color: var(--bx-ink-2); white-space: nowrap; }

/* ── Buttons ──────────────────────────────────────────────────────────────── */
.bx-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.35rem;
  border: 1px solid var(--bx-line-strong); border-radius: 8px;
  background: var(--bx-sunken); color: var(--bx-ink);
  font: inherit; font-size: 0.78rem; line-height: 1.2; padding: 0.44rem 0.7rem;
  cursor: pointer; transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.bx-btn:hover:not(:disabled) { border-color: var(--bx-accent); color: var(--bx-accent-ink); }
.bx-btn:disabled { opacity: 0.4; cursor: default; }
.bx-btn-block { width: 100%; }
.bx-btn-primary {
  border-color: var(--bx-accent); background: var(--bx-accent); color: #fff;
}
.bx-btn-primary:hover:not(:disabled) { filter: brightness(1.07); color: #fff; border-color: var(--bx-accent); }
.bx-dark .bx-btn-primary { color: rgb(15 23 42); }
.bx-dark .bx-btn-primary:hover:not(:disabled) { color: rgb(15 23 42); }
.bx-btn-go {
  border: 0; border-radius: 999px; background: var(--bx-ink); color: var(--bx-panel);
  font-size: 0.74rem; letter-spacing: 0.12em; text-transform: uppercase; padding: 0.6rem 1.2rem;
}
.bx-btn-go:hover:not(:disabled) { background: var(--bx-accent); color: #fff; border: 0; }
.bx-btn-danger:hover:not(:disabled) { border-color: var(--bx-danger); color: var(--bx-danger); background: var(--bx-danger-soft); }
/* The one button that empties a page: never a slip, so it says what it is. */
.bx-btn-wipe { border-color: var(--bx-danger); color: var(--bx-danger); }
.bx-btn-wipe:hover:not(:disabled) { background: var(--bx-danger); border-color: var(--bx-danger); color: #fff; }
.bx-icon-btn {
  width: 2rem; height: 2rem; flex: none; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--bx-line-strong); border-radius: 8px;
  background: var(--bx-sunken); color: var(--bx-ink);
  font: inherit; font-size: 0.9rem; line-height: 1;
  cursor: pointer; transition: border-color 0.12s, color 0.12s, background 0.12s, opacity 0.12s;
}
.bx-icon-btn:hover:not(:disabled) { border-color: var(--bx-accent); color: var(--bx-accent-ink); }
.bx-icon-btn:disabled { opacity: 0.35; cursor: default; }
/* Start over. Quiet until you mean it, and set apart from its neighbours so it
   isn't what you hit reaching for the button beside it. */
.bx-icon-btn.is-quiet { opacity: 0.55; margin: 0 0.15rem; }
.bx-icon-btn.is-quiet:hover, .bx-icon-btn.is-quiet:focus-visible {
  opacity: 1; border-color: var(--bx-danger); color: var(--bx-danger); background: var(--bx-danger-soft);
}
.bx-link {
  border: 0; background: none; padding: 0; font: inherit; font-size: 0.76rem;
  color: var(--bx-ink-2); text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer; white-space: nowrap;
}
.bx-link:hover { color: var(--bx-accent-ink); }
.bx-link-danger { color: var(--bx-danger); }

/* ── Body: fixed sidebar + everything else ───────────────────────────────────
   A fixed first column and minmax(0,1fr) for the rest: opening a panel or
   selecting a component can never shove the paper sideways. */
.bx-body {
  display: grid;
  grid-template-columns: var(--bx-sidebar) minmax(0, 1fr);
  align-items: start;
  flex: 1;
  min-height: 0;
}
/* The toolbar and the sidebar both stay put while the paper scrolls, each
   pinned below whatever is already stuck above it — so the save state and the
   controls are always to hand however far down the page you are. */
.bx-toolbar { position: sticky; top: var(--bx-top); z-index: 30; }
.bx-sidebar {
  position: sticky; top: calc(var(--bx-top) + var(--bx-toolbar-h)); align-self: start;
  width: var(--bx-sidebar);
  max-height: calc(100vh - var(--bx-top) - var(--bx-toolbar-h));
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--bx-panel);
  border-right: 1px solid var(--bx-line);
}
.bx-full .bx-sidebar { min-height: calc(100vh - var(--bx-top) - var(--bx-toolbar-h)); }
/* The phone sheet's furniture, built once by builder_shell and shown only by
   the phone media query — off a phone it isn't there at all. */
.bx-sheet-handle, .bx-sheet-scrim { display: none; }

/* ── The component palette ───────────────────────────────────────────────────
   One panel for every builder: type to filter, shelves you can scan, and what
   you reached for last at the top. Filtering hides tiles rather than redrawing
   them, so it never costs the focus or a flicker. */
.bx-pal-search { position: relative; margin-bottom: 0.55rem; }
.bx-pal-search-ico {
  position: absolute; left: 0.55rem; top: 50%; transform: translateY(-50%);
  font-size: 0.78rem; opacity: 0.55; pointer-events: none;
}
.bx-pal-input {
  width: 100%; padding: 0.46rem 0.6rem 0.46rem 1.85rem;
  border: 1px solid var(--bx-line-strong); border-radius: 999px;
  background: var(--bx-sunken); color: var(--bx-ink);
  font: inherit; font-size: 0.8rem;
}
.bx-pal-input:focus { outline: none; border-color: var(--bx-accent); background: var(--bx-panel); }
.bx-pal-input::-webkit-search-cancel-button { cursor: pointer; }

.bx-pal-list { display: flex; flex-direction: column; gap: 0.5rem; }
.bx-pal-shelf.is-out { display: none; }
.bx-pal-shelf-head {
  display: flex; align-items: center; gap: 0.35rem;
  margin: 0 0 0.3rem; padding: 0 0.1rem;
  font-size: 0.6rem; font-weight: 600; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--bx-ink-3);
}
.bx-pal-tiles { display: flex; flex-direction: column; gap: 0.25rem; }

.bx-pal-tile {
  display: flex; align-items: center; gap: 0.55rem; width: 100%;
  padding: 0.42rem 0.5rem;
  border: 1px solid transparent; border-radius: var(--bx-radius);
  background: none; color: var(--bx-ink); font: inherit; text-align: left;
  cursor: pointer; transition: background 0.12s, border-color 0.12s;
}
.bx-pal-tile:hover, .bx-pal-tile:focus-visible {
  background: var(--bx-accent-soft); border-color: var(--bx-accent); outline: none;
}
.bx-pal-tile.is-out { display: none; }
/* The icon in a tinted chip rather than loose against the text — it reads as a
   thing you can pick rather than a bullet. */
.bx-pal-ico {
  display: flex; align-items: center; justify-content: center; flex: none;
  width: 1.85rem; height: 1.85rem;
  border-radius: 7px; background: var(--bx-sunken); border: 1px solid var(--bx-line);
  font-size: 0.92rem; line-height: 1;
}
.bx-pal-tile:hover .bx-pal-ico { border-color: var(--bx-accent); }
.bx-pal-text { display: flex; flex-direction: column; min-width: 0; }
.bx-pal-name { font-size: 0.79rem; line-height: 1.25; }
.bx-pal-desc {
  font-size: 0.67rem; line-height: 1.3; color: var(--bx-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bx-pal-empty { margin: 0.4rem 0.1rem; font-size: 0.72rem; color: var(--bx-ink-3); }
.bx-pal-empty.hidden { display: none; }

/* Zoom: only worth the room on a touch screen, where the page is small and
   there's no other way in. On a desktop the paper is already legible. */
.bx-zoom { display: none; }
@media (hover: none), (max-width: 1024px) {
  .bx-zoom {
    display: flex; align-items: center; gap: 0.3rem;
    margin: 0 0 0.5rem auto; padding: 0.2rem;
    border: 1px solid var(--bx-line); border-radius: 999px;
    background: var(--bx-panel); width: fit-content;
  }
  .bx-zoom button {
    min-width: 38px; min-height: 38px; padding: 0 0.5rem;
    border: 0; border-radius: 999px; background: none;
    font: inherit; font-size: 0.9rem; color: var(--bx-ink); cursor: pointer;
  }
  .bx-zoom [data-zoom="reset"] { font-size: 0.72rem; }
  .bx-zoom [data-zoom-level] { min-width: 3.1rem; text-align: center; font-size: 0.72rem; color: var(--bx-ink-2); font-variant-numeric: tabular-nums; }
  .bx-zoom.is-zoomed { border-color: var(--bx-accent); }
}

/* ── A collapsible sidebar panel ─────────────────────────────────────────────
   The head is the whole button; the body animates open on grid-template-rows,
   which is the one way to transition to a content-sized height. */
.bx-panel { border-bottom: 1px solid var(--bx-line); }
.bx-panel:last-child { border-bottom: 0; }
.bx-panel-head {
  display: flex; align-items: center; gap: 0.55rem; width: 100%;
  padding: 0.7rem 0.85rem;
  border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--bx-ink-2); text-align: left;
  transition: color 0.12s;
}
.bx-panel-head:hover { color: var(--bx-ink); }
.bx-panel.is-open > .bx-panel-head { color: var(--bx-ink); }
.bx-panel-ico { flex: none; width: 1.05rem; text-align: center; font-size: 0.85rem; opacity: 0.9; }
.bx-panel-title { flex: 1; min-width: 0; }
/* A count or a one-word summary of what's inside, for a shut panel. */
.bx-panel-note {
  flex: none; font-size: 0.6rem; letter-spacing: 0.06em; text-transform: none;
  color: var(--bx-ink-3); max-width: 8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bx-panel-chev { flex: none; font-size: 0.6rem; opacity: 0.6; transition: transform 0.24s ease; }
.bx-panel.is-open > .bx-panel-head .bx-panel-chev { transform: rotate(90deg); }
.bx-panel-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.24s ease; }
.bx-panel.is-open > .bx-panel-body { grid-template-rows: 1fr; }
.bx-panel-clip { overflow: hidden; min-height: 0; }
.bx-panel-pad { padding: 0.15rem 0.85rem 1rem; }
/* The contextual panel: it only means anything with something selected. */
.bx-panel.is-idle > .bx-panel-head { opacity: 0.55; }
@media (prefers-reduced-motion: reduce) {
  .bx-panel-body { transition: none; }
  .bx-panel-chev { transition: none; }
}

/* ── Fields ──────────────────────────────────────────────────────────────── */
.bx-label {
  display: block; margin: 0.7rem 0 0.28rem;
  font-size: 0.63rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--bx-ink-3);
}
.bx-label:first-child { margin-top: 0; }
.bx-label .bx-label-note { text-transform: none; letter-spacing: normal; opacity: 0.85; }
.bx-input, .bx-select, .bx-textarea {
  width: 100%; border: 1px solid var(--bx-line-strong); border-radius: 8px;
  background: var(--bx-sunken); color: var(--bx-ink);
  font: inherit; font-size: 0.82rem; padding: 0.44rem 0.55rem;
}
.bx-input:focus, .bx-select:focus, .bx-textarea:focus {
  outline: none; border-color: var(--bx-accent); box-shadow: 0 0 0 1px var(--bx-accent);
}
.bx-textarea { line-height: 1.5; resize: vertical; }
.bx-select { cursor: pointer; }
.bx-row { display: flex; gap: 0.5rem; align-items: flex-end; }
.bx-row > * { flex: 1 1 0; min-width: 0; }
.bx-row > .bx-flex-none { flex: none; }
.bx-color {
  flex: none; width: 2.4rem; height: 2.1rem; padding: 2px; cursor: pointer;
  border: 1px solid var(--bx-line-strong); border-radius: 8px; background: var(--bx-sunken);
}
.bx-check {
  display: flex; align-items: flex-start; gap: 0.5rem; margin-bottom: 0.4rem;
  font-size: 0.79rem; line-height: 1.35; color: var(--bx-ink); cursor: pointer;
}
.bx-check input { flex: none; margin: 0.15rem 0 0; accent-color: var(--bx-accent); cursor: pointer; }
.bx-check small { display: block; font-size: 0.69rem; color: var(--bx-ink-3); line-height: 1.35; }
.bx-checks { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; }
.bx-hint { margin: 0.3rem 0 0; font-size: 0.7rem; line-height: 1.45; color: var(--bx-ink-3); }
.bx-hint strong { color: var(--bx-ink-2); font-weight: 600; }
.bx-rule { height: 1px; margin: 0.95rem 0 0.15rem; background: var(--bx-line); }
.bx-group { margin-top: 0.9rem; padding-top: 0.85rem; border-top: 1px solid var(--bx-line); }
.bx-group:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
/* A subtle heading inside a panel, for a second idea in the same section. */
.bx-subhead {
  display: flex; align-items: center; gap: 0.4rem; margin: 0 0 0.45rem;
  font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--bx-ink-3);
}
.bx-step { display: flex; align-items: center; gap: 0.45rem; }
.bx-step button {
  width: 2rem; height: 2rem; flex: none; padding: 0;
  border: 1px solid var(--bx-line-strong); border-radius: 8px;
  background: var(--bx-sunken); color: var(--bx-ink); font: inherit; font-size: 1rem; line-height: 1; cursor: pointer;
}
.bx-step button:hover { border-color: var(--bx-accent); color: var(--bx-accent-ink); }
.bx-step .bx-input { width: 4.4rem; flex: none; text-align: center; padding: 0.4rem 0.3rem; }
.bx-step-unit { font-size: 0.78rem; color: var(--bx-ink-3); }

/* The selected component's name, and the one way to remove it. */
.bx-prop-head {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  margin-bottom: 0.7rem; padding-bottom: 0.6rem; border-bottom: 1px solid var(--bx-line);
}
.bx-prop-type { font-size: 0.63rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--bx-accent-ink); }
.bx-empty { padding: 0.4rem 0 0.6rem; }
.bx-empty-title { margin: 0 0 0.3rem; font-family: "Playfair Display", Georgia, serif; font-size: 0.95rem; color: var(--bx-ink); }
.bx-empty-desc { margin: 0; font-size: 0.76rem; line-height: 1.55; color: var(--bx-ink-3); }
.bx-empty-desc strong { color: var(--bx-ink-2); }
/* A keyboard shortcut, wherever one is worth mentioning. */
.bx-keys { display: flex; flex-wrap: wrap; gap: 0.3rem 0.5rem; margin-top: 0.6rem; font-size: 0.68rem; color: var(--bx-ink-3); }
.bx-key {
  display: inline-block; padding: 0.05rem 0.32rem; border: 1px solid var(--bx-line-strong); border-radius: 4px;
  background: var(--bx-sunken); font-size: 0.64rem; color: var(--bx-ink-2);
}

/* A structured editor dropped into the panel. The partials are written for the
   order form's roomier column, so they're given a little breathing room here
   and their inputs are allowed to be compact. */
.bx-rich { margin-top: 0.15rem; }
.bx-rich [data-rf-row] { padding: 0.5rem; padding-right: 1.9rem; }
.bx-rich input[type="text"], .bx-rich select, .bx-rich textarea { font-size: 0.8rem; padding: 0.35rem 0.5rem; }
.bx-rich .rf-icon-swatch { width: 2rem; height: 2rem; }
/* The partials lay their fields out two-up for the order form's wide column.
   The sidebar is half that, and Tailwind's `sm:` is viewport-based so it can't
   know — stack them instead. Specificity beats the utility rather than
   !important, since Tailwind's stylesheet loads after this one. */
.bx-shell .bx-rich [data-rf-row] .grid { grid-template-columns: 1fr; }
/* …and the spans with it: a child still asking for two columns makes the grid
   grow an implicit second one, which is what kept the fields side by side even
   with a single-track template above. */
.bx-shell .bx-rich [data-rf-row] .grid > * { grid-column: auto; }
.bx-rich .rf-icon-menu { grid-template-columns: repeat(5, 1fr); width: 12rem; }
/* The puzzle editor builds its clue rows for the order form's wide column:
   a fixed-width answer, the clue filling the rest, then the remove button. At
   sidebar width that adds up to more than the row, and the button — the only
   way to delete a clue — gets pushed off the edge. Let the row wrap, let the
   inputs shrink (an input won't go below its intrinsic width without this),
   and drop the clue onto its own line. */
.bx-rich [data-role="rows"] > div { flex-wrap: wrap; }
.bx-rich [data-role="rows"] input { min-width: 0; }
.bx-rich [data-role="rows"] [data-role="answer"] { width: auto; flex: 1 1 6rem; }
.bx-rich [data-role="rows"] [data-role="clue"] { order: 3; flex: 1 1 100%; }
/* The panel scrolls, so an absolutely-positioned icon menu must sit above the
   fields under it rather than being clipped by the row it belongs to. */
.bx-rich [data-rf-icon-control] { position: relative; z-index: 5; }

/* A photo waiting to be uploaded, and the one that has been. */
.bx-photo {
  display: flex; align-items: center; justify-content: center;
  height: 7rem; overflow: hidden;
  border: 1px dashed var(--bx-line-strong); border-radius: var(--bx-radius);
  background: var(--bx-sunken); color: var(--bx-ink-3); font-size: 0.75rem;
}
.bx-photo img { width: 100%; height: 100%; object-fit: cover; }

/* ── Layout cards ─────────────────────────────────────────────────────────
   A shape you pick once, so they're small: three across, a thumbnail-sized
   diagram, and a name clamped to two lines so every card is the same height
   however long the layout is called. */
.bx-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.3rem; }
.bx-card {
  display: flex; flex-direction: column; align-items: center; gap: 0.25rem;
  padding: 0.3rem 0.25rem;
  border: 1px solid var(--bx-line-strong); border-radius: 7px;
  background: var(--bx-sunken); color: var(--bx-ink-2);
  cursor: pointer; transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.bx-card:hover { border-color: var(--bx-accent); color: var(--bx-ink); }
.bx-card.is-active { border-color: var(--bx-accent); color: var(--bx-accent-ink); background: var(--bx-accent-soft); }
.bx-card-name {
  font-size: 0.53rem; line-height: 1.15; text-align: center;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 1.22rem;
}
.bx-card-diagram { width: 100%; height: 24px; }
.bx-card .pl-diagram-slot { background: currentColor; opacity: 0.32; border-radius: 2px; }
.bx-card.is-active .pl-diagram-slot { opacity: 0.6; }
/* A component card in the free canvas's "add" list — a wide row, since these
   have a name and a line about what they are. */
.bx-tiles { display: flex; flex-direction: column; gap: 0.35rem; }
.bx-tile {
  display: flex; align-items: center; gap: 0.55rem; width: 100%; text-align: left;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--bx-line); border-radius: var(--bx-radius);
  background: var(--bx-sunken); color: var(--bx-ink);
  cursor: pointer; transition: border-color 0.12s, background 0.12s, transform 0.12s;
}
.bx-tile:hover { border-color: var(--bx-accent); transform: translateY(-1px); }
.bx-tile-ico { flex: none; width: 1.5rem; text-align: center; font-size: 1.1rem; line-height: 1; }
.bx-tile-text { display: flex; flex-direction: column; min-width: 0; }
.bx-tile-name { font-size: 0.79rem; font-weight: 600; line-height: 1.25; }
.bx-tile-desc { font-size: 0.67rem; line-height: 1.25; color: var(--bx-ink-3); }
.bx-more {
  width: 100%; margin-top: 0.5rem; padding: 0.42rem;
  border: 1px dashed var(--bx-line-strong); border-radius: var(--bx-radius);
  background: none; color: var(--bx-ink-2); font: inherit; font-size: 0.74rem; cursor: pointer;
}
.bx-more:hover { border-color: var(--bx-accent); color: var(--bx-accent-ink); }

/* ── Toggle pills: the chrome bands and the rules ───────────────────────────
   Each is one switch with its own line about what it does, stacked so the
   sidebar reads as a list of decisions rather than a wall of pills. */
.bx-toggles { display: flex; flex-direction: column; gap: 0.35rem; }
.bx-toggle {
  display: flex; align-items: flex-start; gap: 0.5rem;
  padding: 0.42rem 0.55rem;
  border: 1.5px solid var(--bx-line-strong); border-radius: var(--bx-radius);
  background: var(--bx-sunken); color: var(--bx-ink-2);
  font-size: 0.74rem; line-height: 1.3; cursor: pointer;
  transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.bx-toggle:hover { border-color: var(--bx-accent); }
.bx-toggle:focus-within { border-color: var(--bx-accent); }
.bx-toggle input { flex: none; margin: 0.16rem 0 0; accent-color: var(--bx-accent); cursor: pointer; }
.bx-toggle strong { display: block; font-weight: 600; color: var(--bx-ink); }
.bx-toggle small { display: block; font-size: 0.67rem; opacity: 0.85; }
.bx-toggle.is-on { border-color: var(--bx-accent); background: var(--bx-accent-soft); }
.bx-toggle.is-on strong { color: var(--bx-accent-ink); }

/* ── Page thumbnails ─────────────────────────────────────────────────────────
   A strip of small sheets rather than a grid of large ones: which page you're
   on is a glance, not a gallery. They run along one line and scroll sideways
   when an edition has more than the sidebar can hold. */
.bx-thumbs {
  display: flex; gap: 0.3rem; align-items: flex-start;
  overflow-x: auto; overscroll-behavior-x: contain;
  padding-bottom: 0.2rem;
  scrollbar-width: thin;
}
.bx-thumb {
  position: relative; display: block; flex: 0 0 auto; width: 44px; padding: 0; overflow: hidden;
  border: 1px solid var(--bx-line-strong); border-radius: 5px;
  background: var(--bx-sunken); color: var(--bx-ink-2);
  cursor: pointer; text-decoration: none; text-align: center;
  transition: border-color 0.12s, box-shadow 0.12s, color 0.12s;
}
.bx-thumb:hover { border-color: var(--bx-accent); color: var(--bx-ink); }
.bx-thumb.is-active { border-color: var(--bx-accent); color: var(--bx-accent-ink); box-shadow: 0 0 0 2px var(--bx-accent-soft); }
.bx-thumb-sheet {
  /* A span, so it has to be told to be a block — an inline box ignores
     aspect-ratio and the sheet collapses to the height of its contents. */
  display: block; aspect-ratio: 1 / 1.414; padding: 2px;
  background: var(--bx-panel); border-bottom: 1px solid var(--bx-line);
}
.bx-thumb-sheet .bx-card-diagram { height: 100%; }
.bx-thumb-sheet .pl-diagram-slot { background: currentColor; opacity: 0.3; border-radius: 1.5px; }
.bx-thumb.is-active .bx-thumb-sheet .pl-diagram-slot { opacity: 0.55; }
/* Just the page number under each sheet — the full name is on the tooltip.
   At this size a name would only ever be three ellipsised letters. */
.bx-thumb-name {
  display: block; padding: 0.1rem 0.15rem;
  font-size: 0.55rem; line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bx-thumb-add {
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto; width: 44px; aspect-ratio: 1 / 1.414;
  border: 1px dashed var(--bx-line-strong); border-radius: 5px;
  background: none; color: var(--bx-ink-3); font-size: 0.95rem; cursor: pointer;
}
.bx-thumb-add:hover { border-color: var(--bx-accent); color: var(--bx-accent-ink); }
/* Removing a page sits beside adding one, so it says which it is on hover. */
.bx-thumb-add.is-danger:hover { border-color: var(--bx-danger); color: var(--bx-danger); background: var(--bx-danger-soft); }
/* Page count: how many sheets the edition runs to. */
.bx-counts { display: flex; gap: 0.35rem; }
.bx-count {
  width: 2.2rem; height: 2.2rem;
  border: 1.5px solid var(--bx-line-strong); border-radius: 8px;
  background: var(--bx-sunken); color: var(--bx-ink); font: inherit; font-size: 0.9rem; cursor: pointer;
}
.bx-count:hover { border-color: var(--bx-accent); }
.bx-count.is-active { border-color: var(--bx-accent); background: var(--bx-accent); color: #fff; }
.bx-dark .bx-count.is-active { color: rgb(15 23 42); }

/* ── Stage: the paper, and the pages it's one of ─────────────────────────── */
.bx-stage { display: flex; flex-direction: column; min-width: 0; padding: 1.1rem 1.2rem 1.4rem; }

/* The page tabs, sitting right above the paper. Which page you're on is the
   move you make most often, so it's a named tab at the top of the work rather
   than a thumbnail down the sidebar. Both builders draw this same bar. */
.bx-tabs {
  display: flex; align-items: flex-end; gap: 0.25rem;
  margin-bottom: -1px; padding: 0 0.15rem;
  overflow-x: auto; scrollbar-width: thin;
}
.bx-tab {
  flex: 0 0 auto; max-width: 15rem;
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--bx-line); border-bottom-color: transparent;
  border-radius: 8px 8px 0 0;
  background: var(--bx-sunken); color: var(--bx-ink-2);
  font: inherit; font-size: 0.79rem; line-height: 1.3; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  cursor: pointer; transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.bx-tab:hover { background: var(--bx-panel); color: var(--bx-ink); border-color: var(--bx-line-strong); }
/* The page you're on reads as the front sheet of the pile: it carries the
   accent, and its bottom edge is open onto the mat below. */
.bx-tab.is-active {
  background: var(--bx-mat); color: var(--bx-accent-ink);
  border-color: var(--bx-line-strong); border-bottom-color: var(--bx-mat);
  font-weight: 600;
  box-shadow: inset 0 2px 0 var(--bx-accent);
}
/* The number, so a named page still says where it falls in the edition. */
.bx-tab-n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.15rem; height: 1.15rem; padding: 0 0.25rem;
  border-radius: 5px; background: var(--bx-line); color: var(--bx-ink-2);
  font-size: 0.63rem; font-weight: 700; font-variant-numeric: tabular-nums;
}
.bx-tab.is-active .bx-tab-n { background: var(--bx-accent); color: #fff; }
.bx-dark .bx-tab.is-active .bx-tab-n { color: rgb(15 23 42); }
.bx-tab-add { border-style: dashed; color: var(--bx-ink-3); font-size: 0.9rem; padding: 0.45rem 0.7rem; }
.bx-viewport {
  border-radius: 12px; background: var(--bx-mat); padding: 16px; overflow: hidden;
}
.bx-viewport.is-roomy { display: flex; justify-content: center; padding: 20px; }
/* The stage the open paper sits on. Flex-centred so the spread stays on the
   middle of the desk while it's being measured — at full size it's wider than
   the stage, and it's that full size the scale is worked out from. */
.bx-canvas { position: relative; width: 100%; display: flex; justify-content: center; align-items: flex-start; }
.bx-canvas .np-paper { box-shadow: 0 10px 34px rgba(0, 0, 0, 0.22); margin: 0 auto; }

/* ── The paper, open ─────────────────────────────────────────────────────────
   The editor shows the edition the way it's read: two facing pages at a time,
   turned by hand. Not a preview of the work — it IS the work, so both pages
   carry the builder's handles and either can be edited where it lies.

   The leaves, the crease and the turn are the book viewer's (book.css); this
   is the same object with the handles left on. --bx-book-scale is set by the
   controller once it knows how much room the spread has. */
.bx-book {
  position: relative;
  display: flex;
  /* Sized by the pages it holds, not by the stage it's on. Left to fill the
     stage it reports the stage's width, the scale works out as 1, and the
     spread runs off both sides at full size. */
  width: max-content;
  flex: 0 0 auto;
  align-items: flex-start;
  justify-content: center;
  transform: scale(var(--bx-book-scale, 1));
  transform-origin: top center;
  transform-style: preserve-3d;
}
.bx-leaf {
  position: relative;
  flex: 0 0 auto;
  transform-style: preserve-3d;
}
.bx-leaf .np-paper { box-shadow: 0 18px 45px -20px rgba(0, 0, 0, 0.5); }
/* The blank half of the cover spread and of a last odd page. It keeps the
   spread two pages wide, so the paper doesn't change size as it's turned. */
.bx-leaf.is-blank { width: 210mm; height: 297mm; }
.bx-leaf.is-blank .np-paper { display: none; }
/* One page to a spread — a narrow screen, or a paper of one page. */
.bx-book.is-solo .bx-leaf.is-blank { display: none; }

/* The fold. Two facing pages of one folded sheet curve away into the spine. */
.bx-leaf:not(.is-blank)::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 7%;
  opacity: 0.5;
  pointer-events: none;
  z-index: 5;
}
.bx-book:not(.is-solo) .bx-leaf-l:not(.is-blank)::after {
  right: 0;
  background: linear-gradient(to right, rgba(29, 24, 18, 0) 0%, rgba(29, 24, 18, 0.14) 100%);
}
.bx-book:not(.is-solo) .bx-leaf-r:not(.is-blank)::after {
  left: 0;
  background: linear-gradient(to left, rgba(29, 24, 18, 0) 0%, rgba(29, 24, 18, 0.14) 100%);
}

/* The turn, hinged on the spine — the same movement as the reader's, and the
   same keyframes (book.css), so the two can't drift apart. */
.bx-leaf.bk-turn-away-fwd, .bx-leaf.bk-turn-in-fwd,
.bx-leaf.bk-turn-away-back, .bx-leaf.bk-turn-in-back { z-index: 6; }

/* Turning the page, from either side of the paper. */
.bx-page-arrow {
  position: absolute;
  top: 50%;
  z-index: 7;
  display: flex; height: 2.4rem; width: 2.4rem;
  transform: translateY(-50%);
  align-items: center; justify-content: center;
  border-radius: 999px;
  border: 1px solid var(--bx-line);
  background: var(--bx-panel);
  color: var(--bx-ink-2);
  box-shadow: 0 4px 14px -6px rgba(0, 0, 0, 0.5);
  cursor: pointer;
}
.bx-page-arrow:hover:not(:disabled) { border-color: var(--bx-accent); color: var(--bx-accent); }
.bx-page-arrow:disabled { opacity: 0; pointer-events: none; }
.bx-page-arrow-prev { left: 0.35rem; }
.bx-page-arrow-next { right: 0.35rem; }

/* Which pages are open, under the paper. The tabs above it still name every
   page; this says what you're looking at. */
.bx-spread-label {
  margin: 0.85rem 0 0;
  text-align: center;
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--bx-ink-3);
}
.bx-canvas-note { padding: 3rem 1rem; text-align: center; font-size: 0.82rem; color: var(--bx-ink-3); }
.bx-canvas-note.is-error { color: var(--bx-danger); }
.bx-stage-hint { margin: 0.75rem 0 0; text-align: center; font-size: 0.71rem; line-height: 1.5; color: var(--bx-ink-3); }
/* Content that won't fit its column. A slot clips whatever runs past its bottom
   edge, so this is the only warning between a too-long paragraph and a sign-off
   sliced in half on the printed paper. */
.bx-warning {
  margin: 0 0 0.75rem;
  padding: 0.6rem 0.85rem;
  border: 1px solid #e0b34a; border-radius: var(--bx-radius);
  background: #fdf6e3; color: #7a5b1e;
  font-size: 0.76rem; line-height: 1.45;
}
.bx-warning.hidden { display: none; }
.bx-stage-hint strong { color: var(--bx-ink-2); font-weight: 600; }
.bx-notice {
  display: none;
  padding: 0.65rem 1.1rem; background: #fff4d6; color: #7a5b1e;
  border-bottom: 1px solid var(--bx-line); font-size: 0.78rem;
}

/* ── Dragging a component between slots ──────────────────────────────────────
   The page renderer draws the boxes; these are the states the builder puts on
   them. A grabbed component fades and tilts a little so it reads as picked up,
   the slot under the pointer lights, and a solid line shows the exact place it
   will land — the drop used to be a guess until you let go. */
.np-lay-item.sb-dragging { opacity: 0.35; transform: rotate(-0.6deg) scale(0.985); }
.np-lay-slot.sb-drop-over { background: var(--np-drop-tint, rgba(183, 110, 121, 0.1)); outline: 2px dashed #b76e79; outline-offset: 2px; }
.sb-drop-line {
  position: relative; height: 0; margin: 1px 0; pointer-events: none;
  border-top: 2px solid #b76e79; border-radius: 2px;
  box-shadow: 0 0 0 3px rgba(183, 110, 121, 0.18);
}
.sb-drop-line::before, .sb-drop-line::after {
  content: ""; position: absolute; top: -3px; width: 5px; height: 5px; border-radius: 50%; background: #b76e79;
}
.sb-drop-line::before { left: -2px; }
.sb-drop-line::after { right: -2px; }

/* ── The "what goes here?" picker ────────────────────────────────────────────
   Opened from a slot's ＋ (or the free canvas's category rows) and appended to
   the shell, so it takes the shell's theme wherever it's used. */
.bx-shell .sb-picker {
  position: absolute; z-index: 60; width: 300px;
  display: flex; flex-direction: column; gap: 8px; padding: 8px;
  border: 1px solid var(--bx-line-strong); border-radius: 10px;
  background: var(--bx-panel); color: var(--bx-ink);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.3);
}
.bx-shell .sb-picker.hidden { display: none; }
.bx-shell .sb-picker-head { padding: 2px 4px 0; font-size: 0.76rem; color: var(--bx-ink-2); }
.bx-shell .sb-picker-search {
  width: 100%; padding: 8px 10px; outline: none;
  border: 1px solid var(--bx-line-strong); border-radius: 8px;
  background: var(--bx-sunken); color: var(--bx-ink); font: inherit; font-size: 0.8rem;
}
.bx-shell .sb-picker-search:focus { border-color: var(--bx-accent); }
.bx-shell .sb-picker-list { display: flex; flex-direction: column; gap: 2px; max-height: 320px; overflow-y: auto; }
.bx-shell .sb-picker-group {
  padding: 8px 8px 4px; font-size: 0.6rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--bx-ink-3);
}
.bx-shell .sb-picker-item {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 8px; text-align: left;
  border: 0; border-radius: 8px; background: none; color: var(--bx-ink); font: inherit; cursor: pointer;
}
.bx-shell .sb-picker-item:hover, .bx-shell .sb-picker-item.is-active { background: var(--bx-accent-soft); }
.bx-shell .sb-picker-item.hidden, .bx-shell .sb-picker-grp.hidden, .bx-shell .sb-picker-empty.hidden { display: none; }
.bx-shell .sb-picker-empty { padding: 14px 8px; text-align: center; font-size: 0.76rem; color: var(--bx-ink-3); }
.bx-shell .sb-picker-ico { flex: none; width: 22px; text-align: center; font-size: 1rem; }
.bx-shell .sb-picker-text { display: flex; flex-direction: column; min-width: 0; }
.bx-shell .sb-picker-name { font-size: 0.8rem; font-weight: 600; line-height: 1.2; }
.bx-shell .sb-picker-desc {
  font-size: 0.68rem; line-height: 1.2; color: var(--bx-ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Something the builder wants you to look at — the layout picker after a page
   has been cleared, say. Lights briefly, then gets out of the way. */
.bx-flash { animation: bxflash 0.9s ease-out; border-radius: 8px; }
@keyframes bxflash {
  0%, 45% { background: var(--bx-accent-soft); box-shadow: 0 0 0 1px var(--bx-accent); }
  100% { background: transparent; box-shadow: none; }
}

/* ── Phones and tablets ─────────────────────────────────────────────────────
   A column of controls beside the paper doesn't survive 375px: half the screen
   goes to the sidebar and the paper is too small to read. So below the desktop
   width the paper takes the whole screen and the sidebar becomes a sheet at the
   bottom of it, pulled up when it's wanted and pushed down when it isn't. Same
   panels, same order — only where they sit changes.

   It covers tablets too. They used to lay the sidebar out as a band above the
   paper, which meant scrolling past every control to reach the page you were
   trying to judge.

   The sheet is `fixed`, so it rides above the paper rather than pushing it, and
   selecting a component brings it up by itself (see builder_shell). */
@media (max-width: 1024px) {
  .bx-body { grid-template-columns: minmax(0, 1fr); }
  .bx-stage { padding: 0.6rem 0.5rem calc(var(--bx-sheet-peek, 3.1rem) + 1rem); }
  .bx-toolbar { position: sticky; top: var(--bx-top, 0px); z-index: 30; }
  .bx-viewport { padding: 8px; border-radius: 8px; }
  .bx-viewport.is-roomy { padding: 8px; }
  .bx-viewport.is-roomy .bx-canvas { max-width: none; }

  .bx-sidebar {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto;
    width: auto; max-width: none; z-index: 60;
    max-height: 85vh; min-height: 0;
    border: 0; border-top: 1px solid var(--bx-line-strong);
    border-radius: 16px 16px 0 0;
    background: var(--bx-panel);
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.16);
    /* Shut, only the handle shows. */
    transform: translateY(calc(100% - var(--bx-sheet-peek, 3.1rem)));
    transition: transform 0.24s ease;
    overscroll-behavior: contain;
  }
  .bx-sidebar.is-sheet-open { transform: translateY(0); }

  /* The grab bar: the whole thing is the tap target, and it says what's in
     there rather than being a bare grey pill. The sidebar is already its own
     scroller, so the handle just sticks to the top of it and the panels run
     underneath — no extra wrapper, and desktop is untouched. */
  .bx-sheet-handle {
    position: sticky; top: 0; z-index: 1;
    display: flex; align-items: center; justify-content: center; gap: 0.5rem;
    width: 100%; min-height: var(--bx-sheet-peek, 3.1rem); padding: 0.5rem 1rem;
    border: 0; border-radius: 16px 16px 0 0; background: var(--bx-panel);
    font: inherit; font-size: 0.82rem; color: var(--bx-ink); cursor: pointer;
    touch-action: none;
  }
  .bx-sheet-grip { position: absolute; top: 6px; left: 50%; transform: translateX(-50%); width: 34px; height: 4px; border-radius: 999px; background: var(--bx-line-strong); }
  .bx-sheet-label { font-weight: 600; }
  .bx-sheet-hint { color: var(--bx-ink-3); font-size: 0.74rem; }
  /* Tapping off the sheet puts it away — the usual way out of a sheet. */
  .bx-sheet-scrim {
    display: block;
    position: fixed; inset: 0; z-index: 55;
    background: rgba(15, 12, 8, 0.32);
    opacity: 0; pointer-events: none; transition: opacity 0.24s ease;
  }
  .bx-sheet-scrim.is-on { opacity: 1; pointer-events: auto; }

  /* Touch targets. A 44px minimum is the difference between a toolbar you can
     use with a thumb and one you keep missing. */
  .bx-toolbar { gap: 0.5rem; padding: 0.45rem 0.6rem; }
  .bx-toolbar .bx-btn,
  .bx-toolbar .bx-icon-btn,
  .bx-back { min-height: 44px; min-width: 44px; }
  .bx-toolbar .bx-btn { padding: 0.5rem 0.8rem; font-size: 0.82rem; }
  .bx-mode { min-height: 40px; padding: 0.5rem 0.85rem; font-size: 0.8rem; }
  .bx-toolbar-name { min-width: 0; width: 100%; font-size: 1rem; }
  .bx-toolbar-label { font-size: 0.54rem; }
  /* The status text is the first thing worth losing when the bar is tight. */
  .bx-status { font-size: 0.7rem; }

  /* Page tabs: one row, swiped through, never wrapped. */
  .bx-tabs { -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity; padding-bottom: 2px; }
  .bx-tab { scroll-snap-align: start; min-height: 40px; font-size: 0.8rem; }

  /* Panel innards get the full width, and anything that was two-up goes to one. */
  .bx-panel-pad { padding: 0.7rem 0.85rem 0.95rem; }
  .bx-cards { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.4rem; }
  .bx-card-diagram { height: 34px; }
  .bx-card-name { font-size: 0.62rem; }
  .bx-thumb { width: 52px; }
  .bx-row { flex-wrap: wrap; }
  .bx-input, .bx-select, .bx-textarea { font-size: 16px; min-height: 42px; }
  .bx-btn { min-height: 40px; }
  /* 16px on inputs is deliberate: iOS zooms the page in on any smaller font
     when a field takes focus, and never zooms back out. */

  /* Rich editors: their rows are laid out for a sidebar twice this wide. */
  .bx-rich [data-rf-row] .grid,
  .bx-rich [data-role="rows"] > div { grid-template-columns: 1fr; }
  .bx-rich [data-role="rows"] > div { flex-wrap: wrap; gap: 0.4rem; }
  .bx-rich input, .bx-rich textarea, .bx-rich select { min-width: 0; width: 100%; font-size: 16px; }
  .bx-rich table { display: block; overflow-x: auto; }
}

/* ══ New editor UX (iteration) ═══════════════════════════════════════════════
   Clicking the paper is the primary move in both editors now: the panels react
   to what's selected rather than being the place you go first. Everything in
   this block is behind an opt-in class so the admin builders are untouched.
   ────────────────────────────────────────────────────────────────────────── */

/* A contextual panel with nothing selected simply isn't there. It used to sit
   dimmed at the foot of the sidebar, which reads as "broken" rather than
   "waiting". */
.bx-shell .bx-panel.is-vacant { display: none; }

/* ── The picker, at pill density ────────────────────────────────────────────
   Same buttons, same search, same shelves as the full palette — just chips
   instead of full-width rows, so the whole shelf is readable in one glance.
   Both editors use this density, so adding a piece looks the same in each. */
/* flex-direction has to be reset, not just wrap added: the full-density list is
   a column, and a wrapping column still stacks one per line and stretches each
   to the full width — which is the full-width row this density exists to
   replace. */
.bx-pal-list.is-compact .bx-pal-tiles { display: flex; flex-direction: row; flex-wrap: wrap; gap: 0.3rem; }
.bx-pal-tile.is-pill {
  display: inline-flex; align-items: center; gap: 0.3rem;
  width: auto; padding: 0.32rem 0.6rem;
  border: 1px solid var(--bx-line-strong); border-radius: 999px;
  background: var(--bx-sunken); color: var(--bx-ink);
  font: inherit; font-size: 0.72rem; line-height: 1.2; text-align: left;
  cursor: pointer; transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.bx-pal-tile.is-pill:hover { border-color: var(--bx-accent); color: var(--bx-accent-ink); background: var(--bx-accent-soft); }
/* The icon loses its tinted chip at this density — at pill size the chip is
   most of the pill. */
.bx-pal-tile.is-pill .bx-pal-ico {
  width: auto; height: auto; border: 0; background: none; border-radius: 0;
  font-size: 0.82rem; line-height: 1;
}
.bx-pal-tile.is-out { display: none; }

/* ── The free canvas's three-column shell ───────────────────────────────────
   A slim rail of tools on the left, the paper in the middle, and the detail
   panel on the right — so the paper keeps the centre of the screen and the
   controls sit either side of it rather than in front of it. */
.bx-shell.bx-rails > .bx-body {
  grid-template-columns: var(--bx-rail) minmax(0, 1fr) var(--bx-props);
}
.bx-shell.bx-rails { --bx-rail: 62px; --bx-props: 288px; }

.bx-rail {
  position: sticky; top: calc(var(--bx-top) + var(--bx-toolbar-h)); align-self: start;
  display: flex; flex-direction: column; align-items: center; gap: 0.25rem;
  padding: 0.6rem 0.35rem;
  height: calc(100vh - var(--bx-top) - var(--bx-toolbar-h));
  overflow-y: auto;
  background: var(--bx-panel); border-right: 1px solid var(--bx-line);
}
.bx-rail-btn {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  width: 100%; padding: 0.5rem 0.2rem;
  border: 1px solid transparent; border-radius: 10px;
  background: none; color: var(--bx-ink-2);
  font: inherit; font-size: 0.52rem; letter-spacing: 0.04em; text-transform: uppercase;
  cursor: pointer; transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.bx-rail-btn:hover { background: var(--bx-accent-soft); color: var(--bx-ink); }
.bx-rail-btn.is-on { background: var(--bx-accent-soft); border-color: var(--bx-accent); color: var(--bx-accent-ink); }
.bx-rail-ico { font-size: 1.05rem; line-height: 1; }

/* The detail panel on the right. Same panels as before, just re-homed. */
.bx-props {
  position: sticky; top: calc(var(--bx-top) + var(--bx-toolbar-h)); align-self: start;
  width: var(--bx-props);
  height: calc(100vh - var(--bx-top) - var(--bx-toolbar-h));
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--bx-panel); border-left: 1px solid var(--bx-line);
}
.bx-props-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
  padding: 0.7rem 0.85rem 0.5rem;
  border-bottom: 1px solid var(--bx-line);
  font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--bx-ink-3);
}
.bx-props-body { padding: 0.75rem 0.85rem 1.2rem; }
/* X / Y / W / H in one tidy block. */
.bx-quad { display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem; }

/* ── The floating toolbar on the selected box ───────────────────────────────
   The edits worth making without leaving the paper. It follows the selection
   and sits just above it, flipping below when there's no room. */
.bx-float {
  position: absolute; z-index: 40;
  display: flex; align-items: center; gap: 2px;
  padding: 3px;
  border: 1px solid var(--bx-line-strong); border-radius: 999px;
  background: var(--bx-panel);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.16);
  white-space: nowrap;
}
.bx-float.hidden { display: none; }
.bx-float button, .bx-float select {
  border: 0; border-radius: 999px; background: none; color: var(--bx-ink);
  font: inherit; font-size: 0.74rem; line-height: 1;
  padding: 0.35rem 0.5rem; cursor: pointer;
}
.bx-float button:hover { background: var(--bx-accent-soft); color: var(--bx-accent-ink); }
.bx-float select { max-width: 8.5rem; padding-right: 0.2rem; }
.bx-float-grip { cursor: move; opacity: 0.55; padding: 0.35rem 0.4rem; }
.bx-float-sep { width: 1px; align-self: stretch; margin: 0.15rem 1px; background: var(--bx-line); }
.bx-float-del:hover { background: var(--bx-danger-soft); color: var(--bx-danger); }

/* Zoom, parked in the corner of the screen rather than on a line above the
   paper. Fixed, not absolute: the stage is a whole A4 sheet tall, so anything
   anchored to its bottom edge would sit a page and a half below the fold. */
.bx-stage { position: relative; }
/* On the free canvas zoom earns its place at every width — boxes are placed by
   hand there, so being able to pull back and see the whole sheet, or come in
   close to line two things up, is part of the job rather than a small-screen
   concession. The base .bx-zoom is desktop-hidden, so the styling is repeated
   here rather than inherited. */
.bx-zoom-corner {
  display: flex; align-items: center; gap: 0.3rem;
  position: fixed; right: calc(var(--bx-props) + 1.1rem); bottom: 1.4rem; z-index: 30;
  margin: 0; padding: 0.2rem; width: fit-content;
  border: 1px solid var(--bx-line-strong); border-radius: 999px;
  background: var(--bx-panel);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14);
}
.bx-zoom-corner button {
  min-width: 34px; min-height: 34px; padding: 0 0.5rem;
  border: 0; border-radius: 999px; background: none;
  font: inherit; font-size: 0.9rem; color: var(--bx-ink); cursor: pointer;
}
.bx-zoom-corner button:hover { background: var(--bx-accent-soft); color: var(--bx-accent-ink); }
.bx-zoom-corner [data-zoom="reset"] { font-size: 0.72rem; }
.bx-zoom-corner [data-zoom-level] {
  min-width: 3.1rem; text-align: center; font-size: 0.72rem;
  color: var(--bx-ink-2); font-variant-numeric: tabular-nums;
}
.bx-zoom-corner.is-zoomed { border-color: var(--bx-accent); }

@media (max-width: 1024px) {
  /* The rail and the detail panel fold back into the bottom sheet on a phone. */
  .bx-shell.bx-rails > .bx-body { grid-template-columns: minmax(0, 1fr); }
  .bx-rail { position: static; flex-direction: row; height: auto; border-right: 0;
             border-bottom: 1px solid var(--bx-line); overflow-x: auto; }
  .bx-rail-btn { width: auto; min-width: 62px; }
  /* Stacked, the detail panel would sit below a full A4 sheet — a long scroll
     from the box you just tapped. So on a touch layout it comes up from the
     bottom instead, over the paper, and only when there's something to say. */
  .bx-props {
    position: fixed; left: 0; right: 0; bottom: 0; top: auto;
    width: auto; height: auto; max-height: 52vh; z-index: 45;
    border-left: 0; border-top: 1px solid var(--bx-line-strong);
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -8px 28px rgba(0, 0, 0, 0.16);
    transform: translateY(101%); transition: transform 0.18s ease-out;
  }
  .bx-props.is-open { transform: none; }
  .bx-props-head { position: sticky; top: 0; background: var(--bx-panel); border-radius: 14px 14px 0 0; }
  /* Room to scroll the paper clear of the sheet. */
  .bx-shell.bx-rails.has-sheet .bx-stage { padding-bottom: 52vh; }
  /* Stacked, so there's no panel to sit clear of. */
  .bx-zoom-corner { right: 1.1rem; }
}

/* ── "Moving your paper…" ────────────────────────────────────────────────────
   Switching editors saves, converts and then navigates, which takes a beat.
   That used to be announced by a line of text in the top-right corner of the
   toolbar, which is the last place anyone is looking — their eyes are on the
   paper. So the paper is what gets covered.

   Fixed rather than absolute: the stage is a whole A4 sheet tall, so an
   overlay filling it would centre its spinner somewhere below the fold. Fixed
   to the window, inset past the rail and the panel, it covers exactly the
   column the paper is in and centres in what the couple can actually see. */
.bx-busy {
  position: fixed;
  top: calc(var(--bx-top) + var(--bx-toolbar-h));
  left: var(--bx-rail, 0px);
  right: var(--bx-props, 0px);
  bottom: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  padding: 1.5rem;
  text-align: center;
  background: color-mix(in srgb, var(--bx-bg) 82%, transparent);
  backdrop-filter: blur(2px);
  animation: bx-busy-in 0.14s ease-out;
}
/* min(), not a flat 22rem: on a narrow phone a flat cap is wider than the
   space left after the padding, and the line runs off the edge. */
.bx-busy-text, .bx-busy-sub { max-width: min(22rem, 100%); margin: 0; }
.bx-busy.hidden { display: none; }
@keyframes bx-busy-in { from { opacity: 0 } to { opacity: 1 } }

.bx-busy-ring {
  width: 2.4rem; height: 2.4rem;
  /* The track is faint and the leading segment is the accent, so what the eye
     follows is the moving part rather than the ring. */
  border: 3px solid color-mix(in srgb, var(--bx-ink) 12%, transparent);
  border-top-color: var(--bx-accent);
  border-radius: 50%;
  animation: bx-spin 0.75s linear infinite;
}
@keyframes bx-spin { to { transform: rotate(360deg) } }

.bx-busy-text {
  font-family: "Playfair Display", Georgia, serif;
  font-size: 1.05rem;
  color: var(--bx-ink);
}
.bx-busy-sub { font-size: 0.76rem; color: var(--bx-ink-2); }

/* A spinner that never stops is the one bit of motion worth turning off. */
@media (prefers-reduced-motion: reduce) {
  .bx-busy { animation: none; }
  .bx-busy-ring { animation-duration: 2.4s; }
}

/* On a touch layout the rail sits above the paper rather than beside it, and
   the toolbar wraps — so there's no reliable height to start below. The whole
   screen is covered instead, which is also the clearer thing on a phone: the
   page is about to be replaced either way. */
@media (max-width: 1024px) {
  .bx-busy { inset: 0; }
}
