/* The Generate screen, from the design handoff of 31 Aug 2026.
 *
 * ONE CARD, ONE SLOT, ONE WRITE BAR. The screen this replaces was five
 * rows in the order they were built, separated by identical hairlines,
 * so the row that writes to the database looked exactly like the row
 * that prints a printer-calibration strip. The design's answer:
 *
 *   - two FREE actions in one card at the top;
 *   - one RESULT SLOT that holds everything the generator produces —
 *     a question, a refusal, twelve rows, a traced outline — so there is
 *     never a second output on screen and nothing for two elements to
 *     draw a rule between;
 *   - the one action that WRITES lives inside the batch review, which
 *     you can only reach by looking at what you are about to write.
 *
 * INK MEANS CONSEQUENCE. The write bar is the only band of dark ink on
 * the surface. The marking is not a colour on a button, it is a change
 * of ground — you have scrolled off the parchment onto the one dark
 * thing on the page. The style guide forbids red buttons and is right to.
 *
 * COLOURS COME FROM tokens.css. Every value in the handoff already had a
 * token except the two below, which are new surface tints; they are
 * scoped here rather than added to the shared file until something else
 * needs them.
 */

#gen-root {
  /* The card's own header strip, a half-step off --warm-white. */
  --gen-strip: #FDFAF3;
  /* The empty slot: a half-step UNDER the frame, so "nothing here yet"
     reads as a recess rather than as another card. */
  --gen-empty: #F9F5EB;
  /* The write bar's field border — the one colour with no token, because
     it only exists against dark ink. */
  --gen-ink-edge: #7A5A30;
  /* The correct option's ground, inside the pass-green family. */
  --gen-correct-bg: #F4FAF4;
}

/* ── the flow card ──────────────────────────────────────────────────── */

.gen-flow {
  background: var(--warm-white);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-lg);
  padding: 22px 24px 20px;
}
.gen-flow-row {
  display: grid;
  grid-template-columns: minmax(240px, 400px) auto 88px;
  gap: 16px;
  align-items: end;
  justify-content: start;
}
/* A family with extra controls (ask, relation, options, shape) grows a
   second line rather than squeezing the first: the three that are always
   there keep one shape across every family.

   AND THE LINE IS ALWAYS THERE, empty or not. It used to be added only
   when a family had controls for it, so the card changed height as the
   family changed and the whole page below jumped — on the one screen
   whose commonest action is switching family to compare two generators.
   The min-height is one label plus one control, so an empty second line
   costs the same space as a full one. */
.gen-flow-extra {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 16px;
  min-height: 56px;
  align-content: start;
}
.gen-lab {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brown-ink);
  margin-bottom: 6px;
}
.gen-flow select,
.gen-flow input[type="text"],
.gen-flow input[type="number"] {
  width: 100%;
  background: var(--parchment);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-md);
  padding: 9px 11px;
  font-size: 14px;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* Difficulty is a segmented pill, not a select: three choices a tutor
   changes constantly, and a select hides two of them behind a click. */
.gen-seg {
  display: flex;
  gap: 3px;
  background: var(--sand-soft);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-pill);
  padding: 3px;
}
.gen-seg button {
  border: none;
  cursor: pointer;
  border-radius: var(--radius-pill);
  padding: 6px 16px;
  font-size: 13.5px;
  font-weight: 600;
  background: transparent;
  color: var(--brown-ink);
}
.gen-seg button.is-on { background: var(--deep-ink); color: var(--parchment); }
/* A BAND THIS KIND OF QUESTION DOES NOT HAVE. Struck through rather
   than merely faded: faded reads as "not selected", and this one cannot
   be selected at all. The reason is on the title, so hovering says
   which measurement decided it. */
/* A COUNT THAT IS NOT A CHOICE. Drawn where the dropdown would be, so
   the row does not reflow when the ask changes, and plainly not a
   control: it reads as the answer to "how many options", which it is. */
.gen-fixed {
  padding: 6px 8px;
  font-size: 14px;
  color: var(--brown-ink);
  opacity: 0.72;
}
.gen-seg button.is-off {
  cursor: not-allowed;
  color: var(--brown-ink);
  opacity: 0.38;
  text-decoration: line-through;
}

.gen-rule { height: 1px; background: var(--hairline); margin: 20px 0 16px; }

.gen-act {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.gen-act p {
  font-family: var(--font-reading);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-tertiary);
  margin: 0;
  max-width: 46ch;
}
.gen-act-btns { display: flex; gap: 10px; align-items: center; }

/* The two buttons of the free half. Weight, not colour, says which is
   the one you meant. */
.gen-btn {
  border-radius: var(--radius-pill);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  font-family: var(--font-ui);
}
.gen-btn-primary {
  background: var(--deep-ink);
  border: none;
  color: var(--parchment);
  padding: 10.5px 22px;
}
.gen-btn-primary:hover { background: var(--ink-hover); }
.gen-btn-ghost {
  background: transparent;
  border: 1.5px solid var(--deep-ink);
  color: var(--deep-ink);
  padding: 9px 20px;
}
.gen-btn-ghost:hover { background: var(--sand-soft); }
.gen-btn:disabled { opacity: 0.55; cursor: default; }
/* On the refusal's own ground the ordinary hover disappears, so the
   outlined button gets the warmer one the design specifies. */
.gen-bad .gen-btn-ghost:hover,
.gen-outline .gen-btn-ghost:hover { background: #F6EFE2; }

.gen-note {
  margin-top: 14px;
  background: var(--state-attention-bg);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: 9px 13px;
  font-size: 12.5px;
  color: var(--text-tertiary);
}

/* ── the one result slot ────────────────────────────────────────────── */

.gen-slot { margin-top: 22px; }

.gen-resting {
  border: 1px dashed var(--warm-stone);
  border-radius: var(--radius-lg);
  padding: 52px 24px;
  text-align: center;
  background: var(--gen-empty);
}
.gen-resting p { margin: 0; color: var(--text-tertiary); }
.gen-resting .gen-resting-lead {
  font-family: var(--font-reading);
  font-size: 15px;
  margin-bottom: 4px;
}
.gen-resting .gen-resting-sub { font-size: 12.5px; }

.gen-card2 {
  background: var(--warm-white);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.gen-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 22px;
  border-bottom: 1px solid var(--hairline);
  background: var(--gen-strip);
  flex-wrap: wrap;
}
.gen-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brown-ink);
}
.gen-pass {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--correct-text);
  background: var(--correct-bg);
  border: 1px solid var(--correct-border);
  border-radius: var(--radius-pill);
  padding: 2px 10px;
}
.gen-meta {
  font-size: 12px;
  color: var(--text-tertiary);
  font-variant-numeric: tabular-nums;
}
.gen-btn-sm {
  border-radius: var(--radius-pill);
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  background: transparent;
  border: 1.5px solid var(--deep-ink);
  color: var(--deep-ink);
  font-family: var(--font-ui);
}
.gen-btn-sm:hover { background: var(--sand-soft); }

.gen-body { padding: 24px 22px 22px; }
.gen-stem2 {
  font-family: var(--font-reading);
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--text-primary);
  margin: 0 0 20px;
  max-width: 62ch;
}
.gen-figrow {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-bottom: 26px;
  flex-wrap: wrap;
}
/* THE THING TO READ IS NOT THE SMALLEST THING ON THE PAGE.
   Measured on a matrix card: the stimulus drew at 150x150 while each of
   its four options drew at 157x157 — and the stimulus holds NINE cells
   where an option holds one glyph, so a child compared 40px cells
   against 157px ones. The 150px cap was doing that; it was chosen when
   a stimulus was a single small figure.
   Capped by the card's width now, and by a share of the viewport rather
   than a fixed number, so a nine-cell matrix and a five-frame strip
   both get the room their content needs. */
.gen-figrow img {
  display: block;
  max-height: min(58vh, 520px);
  max-width: 100%;
  width: auto;
}
.gen-figcap {
  font-size: 12px;
  color: var(--text-tertiary);
  font-family: var(--font-reading);
  max-width: 22ch;
  line-height: 1.5;
}

.gen-opts2 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.gen-opts2.is-five { grid-template-columns: repeat(5, 1fr); }
.gen-opt2 {
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: 12px;
  background: var(--warm-white);
}
.gen-opt2.is-key {
  border: 2px solid var(--correct-border);
  background: var(--gen-correct-bg);
}
.gen-opt2-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 10px;
}
.gen-opt2-letter {
  font-family: var(--font-reading);
  font-size: 14px;
  font-weight: 700;
}
.gen-opt2-tag {
  font-size: 11px;
  font-weight: 700;
  color: var(--correct-text);
  letter-spacing: 0.04em;
}
.gen-opt2 img { display: block; width: 100%; height: auto; }
.gen-opt2-why {
  font-family: var(--font-reading);
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-secondary);
  margin: 10px 0 0;
}

/* ── the inspect fold ───────────────────────────────────────────────── */

.gen-foot {
  border-top: 1px solid var(--hairline);
  background: var(--gen-strip);
  padding: 14px 22px;
}
.gen-foot-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.gen-foot-said { font-family: var(--font-reading); font-size: 14px;
                 color: var(--text-secondary); }
.gen-link {
  background: transparent;
  border: none;
  color: var(--brown-ink);
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: var(--warm-stone);
  padding: 0;
  font-family: var(--font-ui);
}
.gen-gate {
  display: grid;
  grid-template-columns: 170px 1fr auto;
  gap: 16px;
  align-items: baseline;
  padding: 9px 0;
  border-top: 1px solid var(--hairline);
}
.gen-gate-id {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11.5px;
  color: var(--text-tertiary);
}
.gen-gate-said {
  font-family: var(--font-reading);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--text-primary);
}
.gen-gate-fig {
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--correct-text);
}
.gen-gate-fig.is-bad { color: var(--state-bad-text); }
.gen-raw {
  margin-top: 12px;
  background: var(--sand-soft);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  overflow-x: auto;
}
.gen-raw-row {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 14px;
  padding: 3px 0;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11.5px;
  line-height: 1.6;
}
.gen-raw-k { color: var(--state-bad-text); }
.gen-raw-v { color: var(--brown-ink); word-break: break-all; }
.gen-pill {
  background: transparent;
  border: 1px solid var(--border-card);
  color: var(--brown-ink);
  border-radius: var(--radius-pill);
  padding: 5px 14px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  font-family: var(--font-ui);
}
.gen-pill:hover { background: var(--sand-soft); }

/* ── refusals, three levels ─────────────────────────────────────────── */

.gen-bad {
  background: var(--state-bad-bg);
  border: 1px solid var(--state-bad-border);
  border-radius: var(--radius-lg);
  padding: 24px 26px;
}
.gen-bad-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--state-bad-text);
  margin-bottom: 8px;
}
.gen-bad h2, .gen-bad h3 {
  font-family: var(--font-reading);
  font-weight: 700;
  margin: 0 0 10px;
}
.gen-bad h2 { font-size: 20px; }
.gen-bad h3 { font-size: 18px; margin-bottom: 8px; }
.gen-bad p {
  font-family: var(--font-reading);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--text-secondary);
  margin: 0 0 16px;
  max-width: 62ch;
}
/* The gate's OWN words, quoted rather than paraphrased. */
.gen-quote {
  background: var(--warm-white);
  border: 1px solid var(--state-bad-border);
  border-radius: var(--radius-md);
  padding: 13px 15px;
  margin-bottom: 18px;
  max-width: 70ch;
}
.gen-quote-id {
  font-family: ui-monospace, Menlo, monospace;
  font-size: 11px;
  color: var(--state-bad-text);
  margin-bottom: 5px;
}
.gen-quote-said {
  font-family: var(--font-reading);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-primary);
}
.gen-bad-acts { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* ── the batch table ────────────────────────────────────────────────── */

.gen-batch-head { padding: 18px 22px 14px; border-bottom: 1px solid var(--hairline); }
.gen-batch-head-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.gen-batch-head h2 {
  font-family: var(--font-reading);
  font-size: 19px;
  font-weight: 700;
  margin: 0;
}
.gen-warn2 {
  background: var(--state-warn-bg);
  border-bottom: 1px solid var(--state-warn-border);
  padding: 12px 22px;
  display: flex;
  gap: 10px;
  align-items: baseline;
}
.gen-warn2-lab {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--state-warn-text);
  flex-shrink: 0;
}
.gen-warn2 p {
  font-family: var(--font-reading);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--brown-ink);
  margin: 0;
}

.gen-row {
  display: grid;
  grid-template-columns: 24px 46px 1fr 58px 74px 224px 70px;
  gap: 14px;
  align-items: center;
  padding: 11px 22px;
  border-bottom: 1px solid var(--hairline);
  background: var(--warm-white);
}
.gen-row.is-head {
  padding: 9px 22px;
  background: var(--gen-strip);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.gen-row.is-flagged { background: var(--state-attention-bg); }
.gen-row input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer;
                                  accent-color: var(--deep-ink); margin: 0; }
.gen-thumb {
  width: 46px;
  height: 46px;
  border: 1px solid var(--warm-stone);
  background: #FFFFFF;
  object-fit: contain;
  display: block;
}
.gen-row-stem {
  font-family: var(--font-reading);
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--text-primary);
}
.gen-row-meta { font-size: 11.5px; color: var(--text-tertiary); margin-top: 2px; }
.gen-row-ans {
  font-family: var(--font-reading);
  font-size: 15px;
  font-weight: 700;
}
.gen-row-checks { font-size: 12px; color: var(--correct-text); font-weight: 600; }
.gen-row-checks.is-bad { color: var(--state-bad-text); }
.gen-flag {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--state-warn-text);
  background: var(--state-attention-bg);
  border: 1px solid var(--state-warn-border);
  border-radius: var(--radius-pill);
  padding: 2px 10px;
}

/* ── the one band of ink ────────────────────────────────────────────── */

.gen-ink {
  background: var(--deep-ink);
  /* The paper grain the style guide reserves for ink, at 6%. */
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.06'/%3E%3C/svg%3E");
  background-size: 180px;
  padding: 20px 22px;
}
.gen-ink-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.gen-ink-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--warm-stone);
  margin-bottom: 6px;
}
.gen-ink p {
  font-family: var(--font-reading);
  font-size: 14px;
  line-height: 1.6;
  color: var(--parchment);
  margin: 0;
  opacity: 0.86;
  max-width: 52ch;
}
.gen-ink-lab {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--warm-stone);
  margin-bottom: 5px;
}
.gen-ink input[type="text"], .gen-ink select {
  width: 230px;
  background: rgba(250, 246, 238, 0.07);
  border: 1px solid var(--gen-ink-edge);
  border-radius: var(--radius-md);
  padding: 9px 12px;
  font-size: 13.5px;
  color: var(--parchment);
  font-family: var(--font-ui);
}
.gen-ink input::placeholder { color: var(--warm-stone); opacity: 0.75; }
.gen-ink-acts { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.gen-ink-ghost {
  background: transparent;
  border: 1.5px solid var(--warm-stone);
  color: var(--parchment);
  border-radius: var(--radius-pill);
  padding: 9px 18px;
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  font-family: var(--font-ui);
}
.gen-ink-ghost:hover { border-color: var(--parchment); }
.gen-ink-go {
  background: var(--parchment);
  border: none;
  color: var(--deep-ink);
  border-radius: var(--radius-pill);
  padding: 10.5px 22px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  font-family: var(--font-ui);
}
.gen-ink-go:hover { background: #FFFFFF; }
.gen-ink-go:disabled, .gen-ink-ghost:disabled { opacity: 0.55; cursor: default; }
.gen-ink-link {
  background: transparent;
  border: none;
  color: var(--warm-stone);
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: underline;
  padding: 0;
  font-family: var(--font-ui);
}
.gen-exports { display: flex; gap: 10px; flex-wrap: wrap; }
.gen-export {
  text-align: left;
  background: rgba(250, 246, 238, 0.07);
  border: 1px solid var(--gen-ink-edge);
  border-radius: 12px;
  padding: 11px 16px;
  cursor: pointer;
  min-width: 186px;
  font-family: var(--font-ui);
}
.gen-export:hover { border-color: var(--warm-stone); }
.gen-export b { display: block; font-size: 13.5px; font-weight: 700;
                color: var(--parchment); }
.gen-export span { display: block; font-size: 11.5px; color: var(--warm-stone);
                   margin-top: 3px; }

/* A write that was refused REPLACES the ink band rather than decorating
   it: the thing that would have written is not there any more. */
.gen-writebad {
  background: var(--state-bad-bg);
  border-top: 1px solid var(--state-bad-border);
  padding: 20px 22px;
}

/* ── the traced outline ─────────────────────────────────────────────── */

.gen-outline {
  background: var(--state-attention-bg);
  border: 1px solid var(--state-warn-border);
  border-radius: var(--radius-lg);
  padding: 22px 24px;
}
.gen-outline-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--state-warn-text);
  margin-bottom: 8px;
}
.gen-outline h2 {
  font-family: var(--font-reading);
  font-size: 19px;
  font-weight: 700;
  margin: 0 0 8px;
}
.gen-outline p {
  font-family: var(--font-reading);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-secondary);
  margin: 0 0 18px;
}
.gen-outline-row {
  display: flex;
  gap: 20px;
  align-items: flex-start;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.gen-outline-pane {
  flex: 1;
  min-width: 280px;
  border-left: 1px solid var(--state-warn-border);
  padding-left: 20px;
}
.gen-outline-fig {
  width: 190px;
  height: 190px;
  border: 1px solid var(--border-card);
  background: #FFFFFF;
  object-fit: contain;
  display: block;
}
.gen-outline-cap { font-size: 11px; color: var(--text-tertiary); margin-top: 6px; }
.gen-arrow { font-size: 22px; color: var(--text-muted); align-self: center; }

/* ── the errands, off the flow ──────────────────────────────────────── */

.gen-errands {
  margin-top: 44px;
  padding-top: 18px;
  border-top: 1px solid var(--hairline);
}
.gen-errands-lab {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-bottom: 12px;
}
.gen-errands-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  max-width: 800px;
}
.gen-errands p {
  font-family: var(--font-reading);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-tertiary);
  margin: 0;
}
.gen-errands .gen-link { margin-bottom: 4px; font-size: 13.5px; display: block; }

@media (max-width: 900px) {
  .gen-flow-row { grid-template-columns: 1fr; }
  .gen-opts2, .gen-opts2.is-five { grid-template-columns: repeat(2, 1fr); }
  .gen-row, .gen-row.is-head { grid-template-columns: 24px 46px 1fr auto; }
  .gen-row > :nth-child(5), .gen-row > :nth-child(6) { display: none; }
  .gen-errands-grid { grid-template-columns: 1fr; }
}

/* The refused/wrote band reuses the refusal's own type, inside the card. */
.gen-writebad .gen-bad-h3 {
  font-family: var(--font-reading);
  font-size: 18px;
  font-weight: 700;
  margin: 0 0 8px;
}
.gen-writebad .gen-bad-p {
  font-family: var(--font-reading);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-secondary);
  margin: 0 0 14px;
  max-width: 62ch;
}
.gen-writebad .gen-done {
  font-family: var(--font-reading);
  font-size: 15px;
  color: var(--correct-text);
  margin: 0 0 12px;
}

/* Stepping through an opened batch question, and deciding about it while
   you can still see it. Both sit in the header beside "Back to the
   batch", because that button used to be the only way out of a question
   opened from a list of twelve. */
.gen-step {
  display: flex;
  align-items: center;
  gap: 10px;
}
.gen-step-of {
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
}
.gen-step .gen-check {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  white-space: nowrap;
}
.gen-step .gen-btn[disabled] {
  opacity: 0.4;
  cursor: default;
}

/* An honest wait. The bar is INDETERMINATE - the server sends one reply
   at the end, so nothing on this page knows what fraction is done, and a
   bar that creeps to 90% and stops is a lie told smoothly. It moves to
   show work is happening; the seconds beside it are the real number. */
.gen-bar {
  position: relative;
  height: 4px;
  margin: 14px auto 10px;
  max-width: 280px;
  border-radius: 999px;
  background: var(--border-card);
  overflow: hidden;
}
.gen-bar-run {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 32%;
  border-radius: 999px;
  background: var(--brown-ink);
  animation: gen-bar-slide 1.15s ease-in-out infinite;
}
@keyframes gen-bar-slide {
  0%   { left: -34%; }
  100% { left: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .gen-bar-run { animation: none; left: 0; width: 100%; opacity: 0.45; }
}

/* HOW MANY BUILDERS ARE FREE, said where the build buttons are.
 *
 * A build takes a permit before it starts and there are only so many,
 * because one builder peaks near 300 MB and going over a container's
 * memory limit does not lose a build — it restarts the service, and
 * takes every child sitting a paper with it. With none free a build
 * queues rather than fails, for up to a quarter of an hour, so the
 * cost of saying nothing is a person watching a screen do nothing and
 * concluding the generator is broken.
 *
 * WARN, NOT BAD. The scale in tokens.css says bad is "something a
 * student would actually hit" and warn is "a decision waiting on a
 * person". A full generator is the second: nothing is broken, and the
 * only question is whether this person wants to wait. Dressing it in
 * the bad colours would make a busy afternoon look like a fault. */
.gen-capacity {
  /* A ROW OF ITS OWN, ALWAYS. `.gen-act` is a space-between flex row, so
   * a third child sits wherever its width leaves it: beside the sentence
   * when the line is short, wrapped below when it is long. That made the
   * line MOVE as the state changed, which is the same fault the
   * `.gen-flow-extra` note above this file describes and fixes for the
   * family controls. Full basis pins it to its own line at every length,
   * so the state changes and nothing else does. */
  flex: 0 0 100%;
  order: 99;
  font-family: var(--font-reading);
  font-size: 12.5px;
  line-height: 1.5;
  margin: 8px 0 0;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  color: var(--text-muted);
  max-width: 46ch;
}
.gen-capacity:empty { display: none; }
.gen-capacity.is-busy {
  background: var(--state-attention-bg);
  border-color: var(--border);
  color: var(--text-secondary);
}
.gen-capacity.is-full {
  background: var(--state-warn-bg);
  border-color: var(--state-warn-border);
  color: var(--state-warn-text);
}
