/* The question builder. Two panes, one bar, one editor.
 *
 * NO HEX CODES IN THIS FILE. Every colour is a token from tokens.css, which is the only file
 * allowed to name one — the same rule dash.css and survey.css follow. If you need a colour that
 * is not here, add a token; do not inline it, or the next theme costs a search-and-replace.
 *
 * NO BRAND HUE AND NO BAND HUE ANYWHERE ON THIS PAGE. --series-keune sits ΔE 3.5 from
 * --dash-warn under deuteranopia, and the Draft chip wears --dash-warn beside the brand toggle.
 * The console neutrals, --dash-accent and --dash-warn are the whole palette here. See the note
 * on --dash-warn in tokens.css.
 */

*, *::before, *::after { box-sizing: border-box; }

/* The `hidden` attribute is only `display: none` in the UA stylesheet, so ANY author display
   declaration beats it — .focusbtn is display:grid, and without this rule a hidden focus button
   stays on screen and in the tab order. Cheaper to state once than to remember per component. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--dash-bg);
  color: var(--dash-ink);
  font-family: var(--dash-font);
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

button, input, select, textarea { font: inherit; color: inherit; }

/* One visible focus treatment for the whole page. Never remove it — a keyboard user who cannot
   see where they are has no way back, and this page is operated by keyboard far more than the
   dashboard is: every drag has an Alt+arrow behind it. */
:focus-visible {
  outline: 2px solid var(--dash-accent);
  outline-offset: 2px;
  border-radius: 3px;
}

/* ---------------------------------------------------------------- top bar */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--dash-line);
  background: var(--dash-panel);
  flex-wrap: wrap;
}

.bar-title { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: .01em; }
.bar-sub { margin: 0; font-size: 12px; color: var(--dash-ink-3); }
.bar-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.bar-nav { display: inline-flex; gap: 10px; }
.bar-nav a {
  font-size: 11.5px;
  color: var(--dash-ink-3);
  text-decoration: none;
  border-bottom: 1px solid var(--dash-line);
}
.bar-nav a:hover { color: var(--dash-accent); border-bottom-color: var(--dash-accent); }

.themetoggle, .langpick {
  display: inline-flex;
  border: 1px solid var(--dash-line);
  border-radius: 7px;
  overflow: hidden;
  background: var(--dash-bg);
}
.themetoggle button, .lang-btn {
  border: 0; background: transparent; cursor: pointer;
  padding: 6px 9px; display: grid; place-items: center;
  color: var(--dash-ink-3);
}
.lang-btn { font-size: 11px; font-weight: 600; letter-spacing: .04em; }
.themetoggle svg { width: 15px; height: 15px; display: block; }
.themetoggle button[aria-pressed="true"], .lang-btn[aria-pressed="true"] {
  background: var(--dash-accent); color: var(--dash-accent-ink);
}

/* ---------------------------------------------------------------- frame */

/* height, not min-height. The panes below scroll INSIDE themselves, and a 1fr row can only be
   bounded if the grid itself is. With min-height the row grows to fit the library and the editor
   ends up below the fold — so clicking a question would scroll you away from the form that just
   opened for it. */
#admin { display: grid; grid-template-rows: auto 1fr; height: 100%; }

/* Three columns on a wide screen: pick a question, put it in the questionnaire, edit it. The
   library and the questionnaire are adjacent because the drag runs between them and a long drag
   is a bad drag; the editor takes the far column because it is a tall form and would strangle
   the list if it shared one.

   Placement is CSS only. There is one #editor element in the markup, moved between a column of
   its own and a slot under the library — two editor hosts would mean two ids and two states. */
.work {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr) minmax(0, 400px);
  grid-template-rows: minmax(0, 1fr);
  min-height: 0;
}

.pane {
  position: relative;              /* the focus button and the rail are positioned against it */
  padding: 16px 18px 28px;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  border-right: 1px solid var(--dash-line);
}
.pane--ed { border-right: 0; }

/* ---------------------------------------------------------------- focus
 *
 * One pane full width, the other two collapsed to labelled rails. data-focus on .work names the
 * expanded pane and drives the geometry; the .is-collapsed / .is-focused classes admin.js sets
 * drive what happens inside a pane. Two mechanisms because they answer two questions — how wide
 * is this column, and is its content on screen at all.
 */

:root { --rail-w: 44px; }

.work[data-focus="lib"]  { grid-template-columns: minmax(0, 1fr) var(--rail-w) var(--rail-w); }
.work[data-focus="flow"] { grid-template-columns: var(--rail-w) minmax(0, 1fr) var(--rail-w); }
.work[data-focus="ed"]   { grid-template-columns: var(--rail-w) var(--rail-w) minmax(0, 1fr); }

/* The columns slide rather than jump, so it is obvious the two panes collapsed rather than
   vanished. prefers-reduced-motion zeroes this at the foot of the file. */
.work { transition: grid-template-columns 220ms var(--ease); }

.pane.is-collapsed { padding: 0; overflow: hidden; }
.pane.is-collapsed > .pane-in { display: none; }

/* A pane given the whole window is not more readable for it — a 1200px-wide text field is
   harder to read than a 700px one. The content keeps a measure and centres. */
.pane.is-focused > .pane-in { max-width: 900px; margin: 0 auto; }
.pane--ed.is-focused > .pane-in { max-width: 720px; }

.focusbtn {
  position: absolute; top: 12px; right: 14px; z-index: 2;
  width: 26px; height: 26px; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  border: 1px solid var(--dash-line); border-radius: 6px;
  background: var(--dash-bg); color: var(--dash-ink-3);
}
.pane--flow .focusbtn { background: var(--dash-panel); }
.focusbtn:hover { border-color: var(--dash-accent); color: var(--dash-accent); }
.focusbtn[aria-expanded="true"] { border-color: var(--dash-accent); color: var(--dash-accent); }
.focusbtn svg { width: 13px; height: 13px; display: block; }

/* The rail IS the collapsed pane: it fills it, so there is no small target to find. Vertical
   text because a 44px column cannot hold "QUESTION LIBRARY" any other way, and rotated 180 so
   it reads bottom-to-top like a book spine rather than upside down. */
.railbtn {
  position: absolute; inset: 0; z-index: 3;
  border: 0; background: transparent; cursor: pointer;
  padding: 16px 0; width: 100%;
  color: var(--dash-ink-3);
  writing-mode: vertical-rl; transform: rotate(180deg);
  font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-align: center;
}
.railbtn:hover { color: var(--dash-accent); background: var(--dash-panel-2); }

/* The heads must not run under the focus button. */
.pane-head, .ed-head { padding-right: 34px; }

/* The library never scrolls as a whole: its head and its search box stay put and the list
   scrolls under them. Hunting for the search box by scrolling up is the opposite of searching. */
.pane--lib { display: flex; flex-direction: column; overflow: hidden; }
.library { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; }
.library .list { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 4px; }

/* The questionnaire is the thing being built, so it gets the raised surface and the library
   stays on the page ground. Without that the panes read as equals and the eye has nowhere to
   land. */
.pane--flow { background: var(--dash-panel); }

.pane-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; margin-bottom: 12px;
}
.pane-title {
  margin: 0; font-size: 10px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--dash-ink-3);
}
.pane-count { font-size: 11px; color: var(--dash-ink-3); font-variant-numeric: tabular-nums; }

.pane-tools { display: flex; gap: 8px; margin-bottom: 12px; }

.search {
  flex: 1 1 auto; min-width: 0;
  padding: 7px 10px;
  border: 1px solid var(--dash-line); border-radius: 6px;
  background: var(--dash-bg); color: var(--dash-ink);
  font-size: 12.5px;
}
.search::placeholder { color: var(--dash-ink-3); }

/* ---------------------------------------------------------------- lists and rows */

.list { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; }

/* A questionnaire with nothing in it still needs to be a target you can drop onto, so the empty
   list keeps a height rather than collapsing to a line. */
.list--flow { min-height: 120px; }

.list-empty {
  padding: 18px 12px;
  border: 1px dashed var(--dash-line); border-radius: 7px;
  color: var(--dash-ink-3); font-size: 12px; text-align: center;
}

.row {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 9px;
  border: 1px solid var(--dash-line); border-radius: 7px;
  background: var(--dash-bg);
  cursor: pointer;
  position: relative;
}
.pane--flow .row { background: var(--dash-panel-2); }
.row:hover { border-color: var(--dash-ink-3); }
.row.is-selected { border-color: var(--dash-accent); }

/* A question already in the open questionnaire is dimmed in the library rather than hidden.
   Hiding it would make the library shrink as you build, which reads as questions disappearing. */
.row--lib.is-in-flow { opacity: .5; }

/* A step that is written but not Active. It keeps its place in the list — it is still part of
   the questionnaire's shape — but it is visibly not being asked, and it takes no number. */
.row--step.is-quiet { opacity: .62; border-style: dashed; }

.row-n {
  flex: 0 0 18px; text-align: right;
  font-size: 11.5px; color: var(--dash-ink-3);
  font-variant-numeric: tabular-nums; padding-top: 1px;
}

.grip {
  flex: 0 0 auto; width: 9px; height: 14px; margin-top: 2px;
  background-image: radial-gradient(currentColor 1px, transparent 1px);
  background-size: 4px 4px;
  color: var(--dash-ink-3);
  opacity: .8;
  cursor: grab;
}

.row-main { flex: 1 1 auto; min-width: 0; display: grid; gap: 4px; }
.row-text { font-size: 12.5px; line-height: 1.35; overflow-wrap: anywhere; }
.row-meta { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.row-used { font-size: 10.5px; color: var(--dash-ink-3); }

.row-add, .row-x {
  flex: 0 0 auto; width: 24px; height: 24px;
  display: grid; place-items: center; cursor: pointer;
  border: 1px solid var(--dash-line); border-radius: 6px;
  background: transparent; color: var(--dash-ink-2);
  font-size: 15px; line-height: 1;
}
.row-add:hover:not(:disabled) { border-color: var(--dash-accent); color: var(--dash-accent); }
.row-x:hover { border-color: var(--dash-warn); color: var(--dash-warn); }
.row-add:disabled { opacity: .3; cursor: default; }

/* ---------------------------------------------------------------- chips */

/* Every chip carries a word. None of them is colour-alone, which is the rule that lets a page
   use only two chromatic tokens and still say four different things. */
.chip {
  display: inline-flex; align-items: center;
  padding: 1px 6px; border-radius: 999px;
  font-size: 10px; font-weight: 600; letter-spacing: .04em;
  border: 1px solid var(--dash-line);
  color: var(--dash-ink-3);
  white-space: nowrap;
}
.chip--active   { border-color: var(--dash-accent); color: var(--dash-accent); }
.chip--inactive { border-style: dashed; }
.chip--draft    { border-color: var(--dash-warn); color: var(--dash-warn); }
.chip--type     { font-weight: 500; letter-spacing: 0; font-family: var(--dash-mono); font-size: 9.5px; }
.chip--quiet    { border-style: dashed; }
.chip--cond     { border-style: dotted; cursor: help; }
.chip--brand    { border-style: dashed; }

.chip--saved    { border-color: var(--dash-accent); color: var(--dash-accent); }
.chip--shipped  { color: var(--dash-ink-3); }

/* ---------------------------------------------------------------- dragging */

.is-dragging { opacity: .4; }

/* The insertion line, drawn on the row the pointer is over. It has to be unmistakable about
   which side of the row the step will land on, or the drop feels random. */
.is-over-before::before, .is-over-after::after {
  content: "";
  position: absolute; left: 0; right: 0; height: 2px;
  background: var(--dash-accent);
}
.is-over-before::before { top: -4px; }
.is-over-after::after { bottom: -4px; }

/* The whole pane lights up when the drop would go to the end, or when a step is being carried
   back to the library to be taken out. Marking the container rather than a row is the only way
   to say "anywhere here" — and an empty questionnaire has no row to mark. */
.is-drop-target { outline: 2px dashed var(--dash-accent); outline-offset: -6px; }

/* ---------------------------------------------------------------- flow pane */

.flow-meta {
  display: flex; flex-wrap: wrap; gap: 18px;
  margin: 14px 0;
  padding: 12px; border: 1px solid var(--dash-line); border-radius: 7px;
  background: var(--dash-bg);
}
.meta-block { flex: 1 1 180px; min-width: 0; }

.flow-actions { display: flex; gap: 8px; margin-top: 16px; }

.hint { margin: 10px 0 0; font-size: 11px; color: var(--dash-ink-3); }

/* ---------------------------------------------------------------- warnings and notices */

/* A warning here is never a blocked action — everything this page warns about is allowed. It is
   saying what the consequence will be, which is why it reads as a sentence and not an alert. */
.warn {
  margin: 10px 0 0; padding: 8px 10px;
  border-left: 2px solid var(--dash-line); border-radius: 0 4px 4px 0;
  background: var(--dash-bg);
  font-size: 11.5px; color: var(--dash-ink-2);
}
.warn--hard { border-left-color: var(--dash-warn); color: var(--dash-warn); }

.notice {
  margin: 12px 0 0; padding: 8px 10px; border-radius: 6px;
  font-size: 12px; border: 1px solid var(--dash-line);
}
.notice--ok { border-color: var(--dash-accent); color: var(--dash-accent); }
.notice--warn { border-color: var(--dash-warn); color: var(--dash-warn); }

/* ---------------------------------------------------------------- buttons */

.btn {
  padding: 7px 12px; cursor: pointer;
  border: 1px solid var(--dash-line); border-radius: 6px;
  background: var(--dash-bg); color: var(--dash-ink-2); font-size: 12px;
}
.btn:hover:not(:disabled) { border-color: var(--dash-ink-3); color: var(--dash-ink); }
.btn:disabled { opacity: .4; cursor: default; }
.btn--sm { padding: 5px 9px; font-size: 11px; }
.btn--auto { width: auto; }
.btn--primary {
  background: var(--dash-accent); border-color: var(--dash-accent);
  color: var(--dash-accent-ink); font-weight: 600;
}
.btn--primary:hover:not(:disabled) { color: var(--dash-accent-ink); }
.btn--danger { color: var(--dash-warn); border-color: var(--dash-warn); }
.btn--danger:hover:not(:disabled) { color: var(--dash-warn); }

.seg { display: flex; flex-wrap: wrap; gap: 4px; }
.seg-btn {
  flex: 1 1 auto; min-width: 0;
  padding: 6px 10px; cursor: pointer;
  border: 1px solid var(--dash-line); border-radius: 6px;
  background: var(--dash-bg); color: var(--dash-ink-2);
  font-size: 11.5px; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pane--flow .seg-btn { background: var(--dash-panel-2); }
.seg-btn:hover { border-color: var(--dash-ink-3); }
.seg-btn[aria-pressed="true"] {
  background: var(--dash-accent); border-color: var(--dash-accent);
  color: var(--dash-accent-ink); font-weight: 600;
}
.seg--tight .seg-btn { flex: 0 1 auto; padding: 5px 10px; }

/* ---------------------------------------------------------------- the editor */

.ed-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.ed-title {
  margin: 0 0 12px; font-size: 10px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--dash-ink-3);
}
.ed-key, .ed-optkey, .ed-cond code {
  font-family: var(--dash-mono); font-size: 10.5px; color: var(--dash-ink-3);
}
.ed-empty { display: grid; gap: 12px; justify-items: start; font-size: 12px; color: var(--dash-ink-3); }
.ed-empty p { margin: 0; }
/* Expanded, the empty state sits alone in a very tall column. Pushed down a little so it reads
   as a placeholder rather than as a heading the page forgot to finish. */
.pane--ed.is-focused .ed-empty { justify-items: center; text-align: center; padding-top: 12vh; }

.ed-field { margin-bottom: 14px; }
.ed-label {
  margin: 0 0 6px; font-size: 11px; font-weight: 600;
  letter-spacing: .03em; color: var(--dash-ink-2);
}
.ed-note { margin: 6px 0 0; font-size: 10.5px; line-height: 1.45; color: var(--dash-ink-3); }
.ed-note--key { display: block; margin-top: 18px; }

.ed-in {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--dash-line); border-radius: 6px;
  background: var(--dash-bg); color: var(--dash-ink);
  font-size: 12.5px;
}
.pane--ed .ed-in { background: var(--dash-panel); }
.ed-in::placeholder { color: var(--dash-ink-3); }
.ed-text { resize: vertical; min-height: 62px; line-height: 1.4; }

/* The type helper. It is not decoration: it is where the difference between the 0–10 question
   and the 0–5 faces is stated, and that difference is the one measurement rule a question
   builder is most likely to erase. */
.ed-help { margin: 6px 0 0; font-size: 11px; line-height: 1.45; color: var(--dash-ink-3); }
.ed-help--loud { color: var(--dash-warn); }

.ed-shared {
  margin: 0 0 12px; padding: 7px 9px;
  border: 1px solid var(--dash-line); border-radius: 6px;
  font-size: 11px; color: var(--dash-ink-2);
}

/* ---- language tabs */

.ed-langs { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.ed-langtabs { display: inline-flex; border: 1px solid var(--dash-line); border-radius: 6px; overflow: hidden; }
.ed-langtab {
  position: relative;
  border: 0; background: transparent; cursor: pointer;
  padding: 4px 9px; font-size: 10.5px; font-weight: 600; letter-spacing: .04em;
  color: var(--dash-ink-3);
}
.ed-langtab[aria-pressed="true"] { background: var(--dash-accent); color: var(--dash-accent-ink); }

/* A dot on the tab of a language with no wording, so the gap is visible before you click into
   it. The sentence beside it says which languages, because a dot alone is not a message. */
.ed-gap {
  position: absolute; top: 3px; right: 3px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--dash-warn);
}
.ed-langtab[aria-pressed="true"] .ed-gap { background: var(--dash-accent-ink); }
.ed-warn { margin: 0; font-size: 11px; font-weight: 600; color: var(--dash-warn); }

/* ---- options, checkboxes, status */

.ed-opts { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 6px; }
.ed-opt { display: flex; align-items: center; gap: 7px; }
.ed-opt-label { flex: 1 1 auto; min-width: 0; }
.ed-x {
  flex: 0 0 auto; width: 24px; height: 24px;
  display: grid; place-items: center; cursor: pointer;
  border: 1px solid var(--dash-line); border-radius: 6px;
  background: transparent; color: var(--dash-ink-3); font-size: 15px; line-height: 1;
}
.ed-x:hover { border-color: var(--dash-warn); color: var(--dash-warn); }

.ed-check {
  display: flex; align-items: center; gap: 8px;
  margin: 10px 0; font-size: 12px; color: var(--dash-ink-2); cursor: pointer;
}
.ed-check input { accent-color: var(--dash-accent); }

/* A real fieldset with real radios. Arrow keys, the group name and the checked state all work
   with no JavaScript at all — the same reason survey.js renders the choice step this way. */
.ed-status {
  margin: 14px 0 0; padding: 10px 12px;
  border: 1px solid var(--dash-line); border-radius: 7px;
}
.ed-status legend { padding: 0 4px; }
.ed-radio {
  display: inline-flex; align-items: center; gap: 6px;
  margin-right: 14px; font-size: 12px; color: var(--dash-ink-2); cursor: pointer;
}
.ed-radio input { accent-color: var(--dash-accent); }

.ed-cond { margin: 0; font-size: 12px; color: var(--dash-ink-2); }

/* ---------------------------------------------------------------- narrow screens */

/* Below two columns the panes stack. Drag still works between them — the lists are simply
   further apart — but the "+" and "x" buttons are what make the page usable at this width, and
   on a touch screen they are the only thing that works at all: HTML5 drag has no touch story. */
/* Two columns. The editor loses its own column and takes a row under the library, where it is
   still beside the questionnaire it is editing into. */
@media (max-width: 1279px) {
  .work {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1.15fr) minmax(0, 1fr);
  }
  .pane--lib  { grid-column: 1; grid-row: 1; }
  .pane--flow { grid-column: 2; grid-row: 1 / span 2; }
  .pane--ed   { grid-column: 1; grid-row: 2; border-right: 1px solid var(--dash-line);
                border-top: 1px solid var(--dash-line); }
}

@media (max-width: 899px) {
  /* Stacked, and the PAGE scrolls rather than each pane. Three independently scrolling boxes on
     a phone is a trap: the outer scroll stops working and the content below is unreachable.

     Focus is off here too — the panes are already one per row, so there is nothing beside
     anything to collapse. admin.js refuses to apply it below the same width; these rules only
     make sure a stale attribute in storage cannot leave a rail on a phone screen. */
  #admin { height: auto; min-height: 100%; }
  .focusbtn, .railbtn { display: none !important; }
  .work[data-focus] { grid-template-columns: minmax(0, 1fr); }
  .pane.is-collapsed > .pane-in { display: block; }
  .pane--lib.is-collapsed > .pane-in { display: flex; }
  .pane.is-focused > .pane-in { max-width: none; margin: 0; }
  .pane-head, .ed-head { padding-right: 0; }
  .work { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; }
  .pane--lib  { grid-column: 1; grid-row: 1; display: block; overflow: visible; }
  .pane--flow { grid-column: 1; grid-row: 2; }
  .pane--ed   { grid-column: 1; grid-row: 3; border-top: 1px solid var(--dash-line); }
  .pane {
    padding: 14px 14px 22px; overflow: visible;
    border-right: 0; border-bottom: 1px solid var(--dash-line);
  }
  .library .list { overflow-y: visible; padding-right: 0; }
}

@media (max-width: 480px) {
  .bar { gap: 10px; padding: 10px 12px; }
  .bar-nav { display: none; }        /* two more links than a 375px bar can hold */
  .flow-meta { gap: 12px; padding: 10px; }
  .ed-radio { margin-right: 10px; }
}

/* Nothing on this page animates, and that is on purpose — but the transitions inherited from a
   future edit should still respect the setting, so the rule is here rather than forgotten. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
