/* CBT Engine — shared styles, defined ONCE for every screen: the admin
 * preview (Step 2), the exercise block (Step 5) and the exam rooms (Steps
 * 6, 7 and every exam family after them).
 *
 * Rules of this file
 *  - Every colour, size and radius is a variable declared below. Nothing
 *    is typed twice; the theme-colour settings of the plugin override the
 *    first seven variables with an inline style (CBT_Admin::theme_css()).
 *  - No !important anywhere. The plugin owns its own regions: everything
 *    the plugin draws sits inside a `.cbt-ui` wrapper and every element it
 *    creates gets its own explicit style, so the theme cannot bleed in.
 *  - Margins and alignment are written with logical properties (start /
 *    end), never left / right: a right-to-left language flips the whole
 *    layout without a second stylesheet.
 *  - Line height is a little taller than usual for Japanese, Korean and
 *    Chinese text.
 *
 * The four question pieces every exam reuses (Steps 6 and 7 only assemble
 * them):  a) .cbt-qnum  the question-number circle
 *         b) .cbt-mcq-letter  the letter badge before a choice
 *         c) .cbt-mcq-option  the choice row with a round (one) or square (many) box
 *         d) .cbt-group-head  the group heading + the instruction line of the paper
 * Taken from the Reading / Listening code that ran in production for
 * months; hard-coded colours became variables. */

:root {
	/* ---- Seven settings (CBT Engine → Settings → Theme colours). ---- */
	--cbt-primary: #2598a3;
	--cbt-primary-light: #37b7c3;
	--cbt-correct: #059669;
	--cbt-wrong: #e53e3e;
	--cbt-blank: #64748b;
	--cbt-font-size: 16px;
	--cbt-radius: 8px;

	/* ---- Derived from the settings; not settings themselves. ---- */
	--cbt-primary-hover: color-mix(in srgb, var(--cbt-primary) 85%, black);
	--cbt-primary-tint: color-mix(in srgb, var(--cbt-primary-light) 20%, white);
	--cbt-correct-bg: color-mix(in srgb, var(--cbt-correct) 14%, white);
	--cbt-wrong-bg: color-mix(in srgb, var(--cbt-wrong) 12%, white);
	--cbt-blank-bg: color-mix(in srgb, var(--cbt-blank) 12%, white);
	--cbt-focus-ring: color-mix(in srgb, var(--cbt-primary-light) 30%, transparent);

	/* ---- Fixed palette of the plugin (neutral greys). ---- */
	--cbt-text: #2d3748;
	--cbt-text-dark: #1a202c;
	--cbt-text-muted: #4a5568;
	--cbt-bg: #f8fafc;
	--cbt-bg-soft: #f1f5f9;
	--cbt-border: #cbd5e0;
	--cbt-border-soft: #e2e8f0;
	--cbt-white: #ffffff;
	--cbt-letter-bg: #e2e8f0;
	--cbt-letter-hover: #cbd5e0;

	--cbt-line-height: 1.75;
	--cbt-radius-pill: 999px;
	--cbt-font: inherit;

	/* The choice row (one / two): gap between the number column and the
	 * content, and how far the 26px circle moves down to sit on the first
	 * text line. */
	--cbt-row-gap: 10px;
	--cbt-row-circle-offset: calc((1em * var(--cbt-line-height) - 26px) / 2);

	/* The typed-answer box: ONE width for every gap (about twelve
	 * characters, two words), never sized from the answer. The short one is
	 * the single-letter box of matching questions. */
	--cbt-gap-width: calc(12ch + 24px);
	--cbt-gap-width-short: calc(3ch + 24px);

	/* Images in a paper (0.5.0b4): three ceilings for the picture frame.
	 * Medium is the default; the author picks narrow / wide with a class
	 * on the frame (is-narrow / is-wide). Settings → Theme colours can
	 * override the three (0.5.0b5); blank there = these defaults. */
	--cbt-image-narrow: 300px;
	--cbt-image-medium: 510px;
	--cbt-image-wide: 720px;
}

/* ------------------------------------------------------------------ */
/* Wrapper: the plugin's own region inside any theme.                  */
/* ------------------------------------------------------------------ */
.cbt-ui {
	font-family: var(--cbt-font);
	font-size: var(--cbt-font-size);
	line-height: var(--cbt-line-height);
	color: var(--cbt-text);
	box-sizing: border-box;
	text-align: start;
	/* A flex/grid parent refuses to shrink below its content by default;
	 * this lets the scroll frames of tables (below) work inside any layout. */
	min-width: 0;
	max-width: 100%;
}
.cbt-ui *,
.cbt-ui *::before,
.cbt-ui *::after {
	box-sizing: inherit;
}
.cbt-ui p {
	margin: 0 0 0.75em;
}
.cbt-ui ul,
.cbt-ui ol {
	margin: 0 0 0.75em;
	padding-inline-start: 1.4em;
}
.cbt-ui li {
	margin: 0 0 0.25em;
}
.cbt-ui table {
	border-collapse: collapse;
	width: auto;
	max-width: 100%;
	margin: 0 0 1em;
}
/* A7: the builder wraps every table of the paper in this frame. On a
 * narrow screen the TABLE scrolls sideways; the page never does. The frame
 * is as wide as its parent at most, and the table keeps a minimum width so
 * its cells are not crushed. Every ancestor the plugin draws has
 * min-width: 0 so the frame can shrink inside flex/grid layouts. */
.cbt-ui .cbt-table-scroll {
	display: block;
	width: auto;
	max-width: 100%;
	min-width: 0;
	overflow-x: auto;
	overflow-y: hidden;
	-webkit-overflow-scrolling: touch;
	margin: 0 0 1em;
	/* 0.5.0b2 — the reason a scroll frame fails inside a theme: the frame's
	 * content (the table) is what an ancestor flex/grid item measures as
	 * its minimum width, so THAT ancestor grows to the table, "100 %" grows
	 * with it and the frame never overflows; whatever clips the page then
	 * cuts the table. Inline-size containment makes the frame report NO
	 * intrinsic width of its own: every ancestor keeps its normal width,
	 * the frame fills it, and the table overflows the frame — which is the
	 * scrolling. The plugin needs nothing from the theme for this. */
	contain: inline-size;
	touch-action: pan-x pan-y;
}
.cbt-ui .cbt-table-scroll > table {
	max-width: none;
	margin: 0;
}
/* Three columns or more: keep a minimum width so the cells are not crushed
 * (a two-column table fits a phone as it is). */
.cbt-ui .cbt-table-scroll > table.cbt-table-wide {
	min-width: 28em;
}
.cbt-ui .cbt-block,
.cbt-ui .cbt-group,
.cbt-ui .cbt-passage {
	min-width: 0;
	max-width: 100%;
}
.cbt-ui td,
.cbt-ui th {
	padding: 6px 10px;
	vertical-align: top;
	text-align: start;
	border: 1px solid var(--cbt-border-soft);
}
.cbt-ui img {
	max-width: 100%;
	height: auto;
}
/* 0.5.0b4: the picture frame. The builder wraps every image of the paper
 * that stands on its own in .cbt-figure (an authored <figure> is reused).
 * The FRAME has the ceiling — the smaller of the size variable and its
 * parent — and centres itself; the image is at most as wide as the frame
 * (never stretched up), height by ratio. */
.cbt-ui .cbt-figure {
	display: block;
	box-sizing: border-box;
	width: auto;
	max-width: min(var(--cbt-image-medium), 100%);
	margin: 0 auto 1em;
	padding: 0;
	text-align: center;
}
.cbt-ui .cbt-figure.is-narrow {
	max-width: min(var(--cbt-image-narrow), 100%);
}
.cbt-ui .cbt-figure.is-wide {
	max-width: min(var(--cbt-image-wide), 100%);
}
.cbt-ui .cbt-figure img {
	display: inline-block;
	max-width: 100%;
	width: auto;
	height: auto;
	vertical-align: middle;
}
.cbt-ui .cbt-figure figcaption,
.cbt-ui .cbt-figure .cbt-figure-caption {
	display: block;
	font-size: 0.875em;
	color: var(--cbt-text-muted);
	text-align: center;
	margin: 6px 0 0;
}
.cbt-ui h2,
.cbt-ui h3 {
	color: var(--cbt-text-dark);
	line-height: 1.35;
	margin: 0 0 0.6em;
}
/* 0.5.2: <h2> is the section label the author types at the top of the
 * paper ("READING PASSAGE 1", "PART 1"): one step above the <h3> title of
 * the passage, sized from the plugin's own base size. */
.cbt-ui h2 {
	font-size: calc(var(--cbt-font-size) * 1.5);
	font-weight: 700;
}
/* 0.5.6: every <h3> the author types INSIDE the paper is centred — the
 * title of the passage and the headings in the question groups alike.
 * Scoped to the two content regions every builder uses (.cbt-passage and
 * .cbt-group-body: exam room, exercise block live + static, "View as a
 * student"), so an <h3> of the WordPress page outside the block, or one the
 * plugin itself makes (exercise title, dialog titles), is never touched.
 * <h2> (section label) and <h4> keep their alignment. An old
 * <h3 style="text-align:center"> agrees with this rule; any inline style
 * the author typed still wins, as inline styles always do. */
.cbt-ui .cbt-passage h3,
.cbt-ui .cbt-group-body h3 {
	text-align: center;
}

/* ------------------------------------------------------------------ */
/* a) Question number: the circle the machine prints for every number.  */
/* (A hand-typed <span class="cbt-qnum"> in old pasted HTML is removed */
/* by the compiler; this class is only ever generated.)                 */
/* ------------------------------------------------------------------ */
.cbt-qnum {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	background-color: var(--cbt-primary-light);
	color: var(--cbt-white);
	border-radius: 50%;
	font-weight: 700;
	font-size: 13px;
	line-height: 1;
	margin-inline-end: 2px;
	vertical-align: middle;
	flex: 0 0 auto;
	font-style: normal;
	text-decoration: none;
	transition: background-color 0.2s ease;
}
.cbt-qnum.is-correct {
	background-color: var(--cbt-correct);
}
.cbt-qnum.is-wrong {
	background-color: var(--cbt-wrong);
}
.cbt-qnum.is-blank {
	background-color: var(--cbt-blank);
}

/* ------------------------------------------------------------------ */
/* Lettered options WITHOUT a control (boxes, admin preview).           */
/* The letter is data from the compiler; the layout never counts.       */
/* Wrapped lines stay under the text, never under the letter.           */
/* ------------------------------------------------------------------ */
.cbt-opts {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin: 6px 0 2px;
}
.cbt-opt {
	display: flex;
	align-items: flex-start;
}
.cbt-opt-letter {
	flex: 0 0 auto;
	min-width: 1.4em;
	margin-inline-end: 1.6em;
	font-weight: 700;
	text-transform: uppercase;
	text-align: start;
	color: var(--cbt-text-dark);
}
.cbt-opt-text {
	flex: 1 1 auto;
	min-width: 0;
}
.cbt-opt.is-correct .cbt-opt-letter,
.cbt-opt.is-correct .cbt-opt-text {
	color: var(--cbt-correct);
	font-weight: 600;
}

/* ------------------------------------------------------------------ */
/* d) Group heading + instruction line.                                 */
/* ------------------------------------------------------------------ */
.cbt-group {
	margin: 0 0 2em;
}
.cbt-group-head {
	margin: 0 0 0.75em;
}
.cbt-group-title {
	color: var(--cbt-primary-light);
	font-size: 1.125em;
	font-weight: 700;
	line-height: 1.4;
	margin: 0.6em 0 0.35em;
	display: flex;
	align-items: center;
	gap: 15px;
}
.cbt-group-instruction {
	font-style: italic;
	margin: 0 0 0.5em;
	color: var(--cbt-text);
}
.cbt-group-instruction b,
.cbt-group-instruction strong {
	font-weight: 700;
}
.cbt-listen-from {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 0.8em;
	font-weight: 600;
	font-style: normal;
	color: var(--cbt-primary);
	background: var(--cbt-primary-tint);
	border-radius: var(--cbt-radius-pill);
	padding: 2px 12px;
	border: 0;
	cursor: pointer;
	font-family: inherit;
}
.cbt-group-body {
	min-width: 0;
}

/* The passage / intro above the groups. */
.cbt-passage {
	margin: 0 0 1.5em;
}

/* ------------------------------------------------------------------ */
/* Placement (0.5.0b).                                                  */
/*                                                                      */
/* fill / tfng / ynng / pick — the question is an INLINE CLUSTER         */
/*   span.cbt-q.cbt-q-inline > span.cbt-q-nums (the .cbt-qnum circles) */
/*                           + the control                              */
/* that behaves like a word of the sentence: no block, no width 100 %,   */
/* no float. The words before and after it stay on its line, the        */
/* paragraph wraps like any paragraph and wrapped lines return to the    */
/* margin (no hanging indent). The cluster itself never splits           */
/* (white-space: nowrap) and is vertically centred on the text line so  */
/* it does not jump. The builder puts tfng / ynng / pick clusters at     */
/* the START of their line: [n] [control] statement.                    */
/*                                                                      */
/* one / two — the 0.5.0a row (kept): number column + content column,   */
/*   top-aligned; the option list keeps its hanging indent.             */
/*   .cbt-row / .cbt-row-num / .cbt-row-body / .cbt-row-prompt          */
/* ------------------------------------------------------------------ */
.cbt-ui .cbt-row {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	gap: 0 var(--cbt-row-gap);
	list-style: none;
	min-width: 0;
	max-width: 100%;
}
.cbt-ui ul:has(> .cbt-row),
.cbt-ui ol:has(> .cbt-row) {
	padding-inline-start: 0;
	list-style-position: inside;
}
.cbt-ui li.cbt-row {
	padding-inline-start: 0;
}
.cbt-ui td.cbt-row,
.cbt-ui th.cbt-row {
	display: flex;
}
.cbt-row-num {
	display: inline-flex;
	flex: 0 0 auto;
	gap: 4px;
	align-items: center;
	margin-block-start: var(--cbt-row-circle-offset);
}
.cbt-row-num .cbt-qnum {
	margin-inline-end: 0;
}
.cbt-row-num:empty {
	display: none;
}
.cbt-row-body {
	flex: 1 1 0;
	min-width: 0;
}
.cbt-row-body > p:last-child,
.cbt-row-body > .cbt-row-prompt {
	margin-block-end: 0;
}
.cbt-row-prompt {
	margin: 0 0 0.35em;
}
.cbt-line {
	margin: 0 0 0.75em;
}

/* ------------------------------------------------------------------ */
/* Question widgets.                                                    */
/*   .cbt-q             one question (span for inline, div for choice)  */
/*   .cbt-q-inline      fill / tfng / ynng / pick — the inline cluster  */
/*   .cbt-q-nums        the number circles inside the cluster           */
/*   .cbt-q-choice      one / two — a row of its own                    */
/* ------------------------------------------------------------------ */
.cbt-q {
	position: relative;
}
.cbt-ui .cbt-q-inline {
	display: inline-flex;
	align-items: center;
	flex-wrap: nowrap;
	gap: 5px;
	vertical-align: middle;
	white-space: nowrap;
	max-width: 100%;
	margin: 0;
	padding: 0;
	line-height: 1;
}
.cbt-ui .cbt-q-inline .cbt-q-nums {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	flex: 0 0 auto;
}
.cbt-ui .cbt-q-inline .cbt-qnum {
	margin-inline-end: 0;
	vertical-align: middle;
}
/* 0.5.0b3: the number leads its block when the control is the last thing
 * of a block that holds one control ("⑦ Article on invasive lionfish ▢").
 * Same circles, standing alone at the start of the line. */
.cbt-ui .cbt-q-nums-lead {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	vertical-align: middle;
	margin-inline-end: 2px;
}
.cbt-ui .cbt-q-nums-lead .cbt-qnum {
	margin-inline-end: 0;
}
/* Once graded the cluster carries a tick/cross and the correct answer,
 * which may be long: those extra pieces may drop to the next line. */
.cbt-ui .cbt-q-inline.is-graded {
	flex-wrap: wrap;
	row-gap: 4px;
}
/* The revealed key may be long ("industrial revolution"): it wraps inside
 * itself and may drop below the box, never widening the cluster. */
.cbt-ui .cbt-q-inline .cbt-key {
	white-space: normal;
	flex: 0 1 auto;
	min-width: 0;
}

/* Typed answer (fill in). ONE fixed width for every gap — about twelve
 * characters, room for two words — whatever the length of the answer, so
 * the box never gives away how long the answer is. Longer typing scrolls
 * inside the box; the box never grows. */
.cbt-ui input[type="text"].cbt-gap {
	appearance: none;
	-webkit-appearance: none;
	display: inline-block;
	flex: 0 0 auto;
	border: 1px solid var(--cbt-border);
	border-radius: calc(var(--cbt-radius) * 2);
	padding: 0 12px;
	height: 30px;
	font-size: 0.95em;
	font-family: inherit;
	line-height: 1.4;
	outline: none;
	min-width: 0;
	max-width: 100%;
	width: var(--cbt-gap-width);
	background-color: var(--cbt-white);
	color: var(--cbt-text-dark);
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
	box-shadow: none;
	vertical-align: middle;
	margin: 0;
	overflow: hidden;
	text-overflow: clip;
}
.cbt-ui input[type="text"].cbt-gap:focus {
	border-color: var(--cbt-primary-light);
	box-shadow: 0 0 0 2px var(--cbt-focus-ring);
}
.cbt-ui input[type="text"].cbt-gap.is-short {
	width: var(--cbt-gap-width-short);
	min-width: 0;
	text-align: center;
	text-transform: uppercase;
}

/* Drop-down answer (True/False/Not Given, letter from a box). */
.cbt-ui select.cbt-select {
	appearance: auto;
	display: inline-block;
	border: 1px solid var(--cbt-border);
	border-radius: calc(var(--cbt-radius) * 2);
	padding: 0 32px 0 12px;
	height: 30px;
	font-size: 0.95em;
	font-family: inherit;
	line-height: 1.4;
	outline: none;
	min-width: 0;
	width: auto;
	max-width: 100%;
	flex: 0 0 auto;
	background-color: var(--cbt-white);
	color: var(--cbt-text-dark);
	vertical-align: middle;
	margin: 0;
	cursor: pointer;
	box-shadow: none;
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.cbt-ui select.cbt-select:focus {
	border-color: var(--cbt-primary-light);
	box-shadow: 0 0 0 2px var(--cbt-focus-ring);
}
.cbt-ui select.cbt-select.is-empty {
	color: var(--cbt-text-muted);
}

/* ------------------------------------------------------------------ */
/* b) + c) Choice rows: letter badge + round (one) or square (many) box. */
/* Structure: label.cbt-mcq-option > input + span.cbt-mcq-letter +      */
/*            span.cbt-mcq-text                                          */
/* ------------------------------------------------------------------ */
.cbt-q-choice {
	margin: 0.5em 0 1.5em;
}
.cbt-mcq-container {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin: 4px 0 0;
}
.cbt-mcq-option {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	gap: 15px;
	margin: 0;
	padding: 3px 0;
	cursor: pointer;
	position: relative;
	user-select: text;
	-webkit-user-select: text;
	font-weight: normal;
	color: var(--cbt-text);
	line-height: var(--cbt-line-height);
	background: transparent;
	border: 0;
	width: auto;
	max-width: 100%;
	font-size: 1em;
	text-transform: none;
}
/* The real control stays in the document for the keyboard and screen
 * readers; the drawn box is on .cbt-mcq-text::before. */
.cbt-mcq-option input[type="radio"],
.cbt-mcq-option input[type="checkbox"] {
	position: absolute;
	inset-inline-start: 0;
	top: 0;
	width: 1px;
	height: 1px;
	margin: 0;
	padding: 0;
	opacity: 0;
	pointer-events: none;
}
.cbt-mcq-letter {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	background-color: var(--cbt-letter-bg);
	color: var(--cbt-text-dark);
	border-radius: 50%;
	font-weight: 800;
	font-size: 14px;
	line-height: 1;
	flex: 0 0 28px;
	text-transform: uppercase;
	transition: background-color 0.2s ease, color 0.2s ease;
	border: 1px solid transparent;
	margin-block-start: 0.1em;
}
.cbt-mcq-text {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	flex: 1 1 auto;
	min-width: 0;
	color: var(--cbt-text);
}
.cbt-mcq-text::before {
	content: '';
	display: inline-block;
	width: 24px;
	height: 24px;
	border: 2px solid var(--cbt-primary-light);
	flex: 0 0 24px;
	background-color: transparent;
	transition: background-color 0.2s ease, border-color 0.2s ease;
	margin-block-start: 0.2em;
	background-size: 75%;
	background-position: center;
	background-repeat: no-repeat;
}
.cbt-mcq-option input[type="checkbox"] ~ .cbt-mcq-text::before {
	border-radius: 4px;
}
.cbt-mcq-option input[type="radio"] ~ .cbt-mcq-text::before {
	border-radius: 50%;
}
.cbt-mcq-option:hover .cbt-mcq-text::before {
	border-color: var(--cbt-primary-hover);
}
.cbt-mcq-option:hover .cbt-mcq-letter {
	background-color: var(--cbt-letter-hover);
}
.cbt-mcq-option input:checked ~ .cbt-mcq-letter {
	background-color: var(--cbt-primary);
	color: var(--cbt-white);
}
.cbt-mcq-option input:checked ~ .cbt-mcq-text::before {
	background-color: var(--cbt-primary);
	border-color: var(--cbt-primary);
	background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
}
.cbt-mcq-option input:focus-visible ~ .cbt-mcq-text::before {
	box-shadow: 0 0 0 3px var(--cbt-focus-ring);
}
.cbt-mcq-option input:disabled ~ .cbt-mcq-letter,
.cbt-mcq-option input:disabled ~ .cbt-mcq-text {
	cursor: default;
}
.cbt-mcq-text-inner {
	flex: 1 1 auto;
	min-width: 0;
}

/* "You can choose only TWO" — shown for a moment when a further box is
 * refused. It never removes a choice the student already made. */
.cbt-choice-notice {
	display: block;
	margin: 6px 0 0;
	font-size: 0.875em;
	font-weight: 600;
	color: var(--cbt-wrong);
	opacity: 0;
	transition: opacity 0.3s ease;
	min-height: 1.2em;
}
.cbt-choice-notice.is-visible {
	opacity: 1;
}

/* ------------------------------------------------------------------ */
/* Put in order (0.5.3): one line per item, in the typed order —        */
/* [number circle][two-digit box] item text. Two boxes holding the same */
/* number are tinted (is-dup), never blocked. After grading each line   */
/* carries its own mark and, when wrong or empty, the correct position. */
/* ------------------------------------------------------------------ */
.cbt-ui .cbt-q-order {
	display: block;
	margin: 6px 0 2px;
}
.cbt-ui .cbt-order-item {
	display: flex;
	align-items: flex-start;
	flex-wrap: wrap;
	gap: 5px 8px;
	padding: 4px 6px;
	border-radius: var(--cbt-radius);
	line-height: var(--cbt-line-height);
}
.cbt-ui .cbt-order-head {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 4px;
}
.cbt-ui .cbt-order-label {
	flex: 0 0 auto;
	min-width: 1.6em;
	margin-top: 2px;
	font-weight: 700;
	color: var(--cbt-primary);
}
.cbt-ui .cbt-order-score {
	font-weight: 700;
	font-size: 0.875em;
	padding: 1px 10px;
	border-radius: var(--cbt-radius-pill);
	color: var(--cbt-white);
	background-color: var(--cbt-wrong);
}
.cbt-ui .cbt-order-score.is-correct {
	background-color: var(--cbt-correct);
}
.cbt-ui .cbt-order-score.is-blank {
	background-color: var(--cbt-blank);
}
.cbt-ui .cbt-order-item .cbt-order-input,
.cbt-ui .cbt-order-item .cbt-mark,
.cbt-ui .cbt-order-item .cbt-key {
	flex: 0 0 auto;
	margin-top: 2px;
}
.cbt-ui .cbt-order-item .cbt-order-text {
	flex: 1 1 12em;
	min-width: 0;
}
.cbt-ui .cbt-order-item.is-dup {
	background-color: var(--cbt-wrong-bg);
}
.cbt-ui .cbt-order-item.is-dup .cbt-order-input {
	border-color: var(--cbt-wrong);
}
.cbt-ui .cbt-order-item.is-correct .cbt-order-input {
	border-color: var(--cbt-correct);
	background-color: var(--cbt-correct-bg);
}
.cbt-ui .cbt-order-item.is-wrong .cbt-order-input {
	border-color: var(--cbt-wrong);
	background-color: var(--cbt-wrong-bg);
	text-decoration: line-through;
}
.cbt-ui .cbt-order-item.is-blank .cbt-order-input {
	border-color: var(--cbt-blank);
}

/* ------------------------------------------------------------------ */
/* Option box for pick: questions (headings, information, features…).  */
/* ------------------------------------------------------------------ */
.cbt-box {
	background-color: var(--cbt-bg);
	border: 1px solid var(--cbt-border);
	border-radius: var(--cbt-radius);
	padding: 15px 20px;
	margin: 12px 0 20px;
}
.cbt-box-title {
	font-weight: 700;
	color: var(--cbt-text);
	margin: 0 0 10px;
}
.cbt-box .cbt-opts {
	gap: 8px;
	margin: 0;
}
.cbt-box .cbt-opt-letter {
	margin-inline-end: 0.9em;
}
/* 0.5.5: a letter-only box ([[box:info A-G]]) is hidden from the eye
 * again (as before 0.5.0b): the instruction of the paper already names
 * the range, so the row only repeated it. It stays IN the page and is
 * read by screen readers ("A B C D E F G"), so no display:none. Only the
 * shorthand box carries .is-shorthand — a box that lists option texts
 * (headings, people, word list, options) is never touched by this rule.
 * The drop-down lists its letters from the paper data, not from this box. */
.cbt-box.is-shorthand {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}
/* The row layout below is kept for the day the box is shown again. */
.cbt-box .cbt-opts-letters {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	gap: 6px 18px;
}
.cbt-box .cbt-opts-letters .cbt-opt-letter {
	margin-inline-end: 0;
	min-width: 0;
}
/* A6: the True/False/Not Given box the builder prints under the
 * instruction: two columns, the "if the statement…" texts aligned. */
.cbt-ui .cbt-def-box {
	display: grid;
	grid-template-columns: max-content minmax(0, 1fr);
	gap: 4px 1.4em;
	align-items: baseline;
}
.cbt-ui .cbt-def-row {
	display: contents;
}
.cbt-ui .cbt-def-key {
	font-weight: 700;
	color: var(--cbt-text-dark);
	white-space: nowrap;
}
.cbt-ui .cbt-def-text {
	font-style: italic;
	color: var(--cbt-text);
	min-width: 0;
}
/* A box of many SHORT options (six or more, a few words each — decided by
 * the builder, class .is-columns) is laid out in columns, like a printed
 * paper. The grid fills ROW BY ROW, so the declared order reads across:
 * A B C on the first row, D E F on the next — the letters are data and
 * never change. At most three columns; fewer as the screen narrows; one
 * column on a phone. */
.cbt-box.is-columns .cbt-opts {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(max(11em, 30%), 1fr));
	grid-auto-flow: row;
	gap: 6px 24px;
}
.cbt-box.is-columns .cbt-opt {
	min-width: 0;
}
@media (max-width: 600px) {
	.cbt-box.is-columns .cbt-opts {
		grid-template-columns: 1fr;
	}
}

/* ------------------------------------------------------------------ */
/* 0.6.3 — Drag and drop ([[dragbox:…]], pick: questions).              */
/*   .cbt-box.is-drag   the box of option cards; sticky while its group */
/*                      scrolls, when short enough (.is-sticky, 0.6.3.1) */
/*   .cbt-drag-slot     ONE FIXED place per option: the list never      */
/*                      reorders; a used option leaves its slot empty   */
/*                      at the same size (the card is only hidden)      */
/*   .cbt-drag-chip     the card: the option text, no letter            */
/*   .cbt-q-drag        a pick: question answered by dropping           */
/*   .cbt-drop          its gap: the number circle when empty, the      */
/*                      option text and × when filled                    */
/*   .cbt-drag-ghost    the card that follows the pointer (on <body>)    */
/* A plain [[box:…]] never gets any of these classes.                   */
/* ------------------------------------------------------------------ */
.cbt-ui .cbt-box.is-drag.is-sticky {
	/* Sticky: the box stays at the top of its scroller (the page, or the
	 * question column of an exam room, which scrolls by itself) while the
	 * questions of its group scroll under it, and leaves with the group.
	 * 0.6.3.1: ONLY a short box — the builder adds .is-sticky when the box
	 * is at most about 40 % of the screen high (CBTRender, fitLayout()); a
	 * taller box (seven paragraphs…) scrolls away like the rest of the page
	 * instead of covering what the student has to read. Same rule on top
	 * and beside the questions.
	 * Sticky silently stops working when an ANCESTOR sets overflow: nothing
	 * the plugin draws between the box and its scroller does — keep it so.
	 * --cbt-stick-offset: the height a page keeps pinned above (0 if unset).
	 * --cbt-drag-pad: the top padding of the scroller, measured by the
	 * builder (sticky counts from inside it; this takes the box to the edge). */
	position: sticky;
	top: calc(var(--cbt-stick-offset, 0px) - var(--cbt-drag-pad, 0px));
	z-index: 1;
}
/* Graded or frozen: a plain list again, in the flow. */
.cbt-ui .cbt-box.is-drag.is-locked {
	position: static;
}
.cbt-ui .cbt-drag-opts {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 8px;
	margin: 0;
	padding: 0;
}
.cbt-ui .cbt-drag-slot {
	display: inline-flex;
	flex: 0 1 auto;
	min-width: 0;
	max-width: 100%;
	border-radius: var(--cbt-radius);
}
.cbt-ui .cbt-drag-slot.is-used {
	background-color: var(--cbt-bg-soft);
	outline: 1px dashed var(--cbt-border);
	outline-offset: -1px;
}
.cbt-ui .cbt-drag-chip {
	display: inline-block;
	min-width: 0;
	max-width: 100%;
	margin: 0;
	padding: 4px 12px;
	border: 1px solid var(--cbt-border);
	border-radius: var(--cbt-radius);
	background-color: var(--cbt-white);
	color: var(--cbt-text-dark);
	font-weight: 500;
	line-height: 1.4;
	white-space: normal;
	overflow-wrap: anywhere;
	cursor: grab;
	/* The finger drags the card instead of scrolling the page; no text selection, no iOS callout. */
	touch-action: none;
	user-select: none;
	-webkit-user-select: none;
	-webkit-touch-callout: none;
	transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
}
.cbt-ui .cbt-drag-chip:hover {
	border-color: var(--cbt-primary-light);
}
.cbt-ui .cbt-drag-chip:focus {
	outline: none;
}
.cbt-ui .cbt-drag-chip:focus-visible {
	border-color: var(--cbt-primary-light);
	box-shadow: 0 0 0 3px var(--cbt-focus-ring);
}
.cbt-ui .cbt-drag-chip.is-selected {
	border-color: var(--cbt-primary);
	background-color: var(--cbt-primary-tint);
	box-shadow: 0 0 0 2px var(--cbt-focus-ring);
}
.cbt-ui .cbt-drag-chip.is-lifted {
	opacity: 0.4;
}
.cbt-ui .cbt-drag-chip.is-used {
	visibility: hidden;
}
.cbt-ui .cbt-box.is-drag.is-locked .cbt-drag-chip {
	cursor: default;
}
.cbt-ui .cbt-box.is-drag.is-locked .cbt-drag-chip:hover {
	border-color: var(--cbt-border);
}

/* The question: its gap may hold a long option, so the cluster may wrap. */
.cbt-ui .cbt-q-inline.cbt-q-drag {
	flex-wrap: wrap;
	row-gap: 4px;
	white-space: normal;
}
.cbt-ui .cbt-drop {
	display: inline-flex;
	align-items: center;
	flex: 0 1 auto;
	gap: 6px;
	min-width: var(--cbt-gap-width);
	max-width: 100%;
	min-height: 30px;
	margin: 0;
	padding: 1px 8px 1px 2px;
	border: 1px dashed var(--cbt-border);
	border-radius: calc(var(--cbt-radius) * 2);
	background-color: var(--cbt-white);
	color: var(--cbt-text-dark);
	line-height: 1.4;
	vertical-align: middle;
	cursor: pointer;
	user-select: none;
	-webkit-user-select: none;
	-webkit-touch-callout: none;
	transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
}
.cbt-ui .cbt-drop:focus {
	outline: none;
}
.cbt-ui .cbt-drop:focus-visible {
	border-color: var(--cbt-primary-light);
	box-shadow: 0 0 0 3px var(--cbt-focus-ring);
}
.cbt-ui .cbt-drop .cbt-q-nums {
	flex: 0 0 auto;
}
.cbt-ui .cbt-drop-text {
	flex: 0 1 auto;
	min-width: 0;
	font-size: 0.95em;
	white-space: normal;
	overflow-wrap: anywhere;
}
.cbt-ui .cbt-drop-clear {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	color: var(--cbt-text-muted);
	font-size: 16px;
	line-height: 1;
	cursor: pointer;
}
.cbt-ui .cbt-drop-clear:hover {
	background-color: var(--cbt-wrong-bg);
	color: var(--cbt-wrong);
}
.cbt-ui .cbt-drop.is-empty .cbt-drop-text,
.cbt-ui .cbt-drop.is-empty .cbt-drop-clear {
	display: none;
}
/* A filled gap is a card too: the finger drags it out instead of scrolling. */
.cbt-ui .cbt-drop.is-filled {
	border-style: solid;
	border-color: var(--cbt-primary-light);
	cursor: grab;
	touch-action: none;
}
.cbt-ui .cbt-drop.is-lifted .cbt-drop-text {
	opacity: 0.4;
}
/* A card is chosen (tap): every free gap of its box shows it can take it. */
.cbt-ui .cbt-drop.is-target {
	border-color: var(--cbt-primary);
	background-color: var(--cbt-primary-tint);
}
/* A card is dragged over this gap. */
.cbt-ui .cbt-drop.is-over {
	border-style: solid;
	border-color: var(--cbt-primary);
	background-color: var(--cbt-primary-tint);
	box-shadow: 0 0 0 3px var(--cbt-focus-ring);
}
.cbt-ui .cbt-drop[aria-disabled="true"] {
	cursor: default;
	touch-action: auto;
}
.cbt-ui .cbt-drop[aria-disabled="true"] .cbt-drop-clear {
	display: none;
}

/* The card under the pointer: on <body>, above the page and above an
 * exam overlay (2147480000), the notepad (2147481000) and the highlight
 * tip (2147481500); below the core's modal (2147482000) and toast. */
.cbt-drag-ghost {
	position: fixed;
	top: 0;
	left: 0;
	z-index: 2147481800;
	max-width: min(28em, 90vw);
	margin: 0;
	padding: 4px 12px;
	border: 1px solid var(--cbt-primary);
	border-radius: var(--cbt-radius);
	background-color: var(--cbt-white);
	color: var(--cbt-text-dark);
	font-weight: 500;
	line-height: 1.4;
	white-space: normal;
	overflow-wrap: anywhere;
	box-shadow: 0 6px 18px color-mix(in srgb, var(--cbt-text-dark) 25%, transparent);
	pointer-events: none;
	will-change: transform;
}
/* During a drag nothing on the page is selected by accident. */
html.cbt-is-dragging,
html.cbt-is-dragging * {
	cursor: grabbing;
	user-select: none;
	-webkit-user-select: none;
}

/* ------------------------------------------------------------------ */
/* 0.6.3.1 — the box BESIDE the questions: [[box:type/side …]] and      */
/* [[box:type/split …]] (box: and dragbox: alike). A box with no suffix */
/* gets none of this.                                                   */
/*   .cbt-group-body.cbt-layout-side | .cbt-layout-split               */
/*     > .cbt-side-aside   the box — first in the page: read first, and */
/*                         on top whenever the two do not fit           */
/*     > .cbt-side-main    everything else of the group, in its order   */
/* The group heading and instruction are outside the body: full width. */
/* State, set by the builder from a measure of the GROUP itself (never  */
/* of the window — in an exam room the group lives in a column the      */
/* student can narrow): .is-side (side by side) or .is-stacked (the box */
/* above, looking exactly like a box on top). Before the first measure, */
/* flex-wrap does the same job on its own.                              */
/* ------------------------------------------------------------------ */
.cbt-ui .cbt-group-body.cbt-layout-side,
.cbt-ui .cbt-group-body.cbt-layout-split {
	--cbt-side-gap: 24px;
	display: flex;
	flex-direction: row-reverse; /* the box (first in the page) stands on the right… */
	flex-wrap: wrap;             /* …and wraps ABOVE the questions when the line is too short */
	justify-content: flex-end;   /* packed from the start edge: any free space stays after the box */
	align-items: first baseline; /* 0.6.4: the FIRST LINE of text of each block level (was: top edges) */
	column-gap: var(--cbt-side-gap);
	row-gap: 0;
}
.cbt-ui .cbt-group-body.is-side {
	flex-wrap: nowrap;
}
/* NEVER remove these min-width: 0 — the table frame of 0.5.0b2 scrolls
 * inside the column only because no column insists on its content's
 * width. No fixed width on the question column either: its width is a
 * flex basis it can shrink from. */
.cbt-ui .cbt-side-main,
.cbt-ui .cbt-side-aside {
	min-width: 0;
	max-width: 100%;
}
/* /side (short words, questions often a table): the questions keep their
 * NATURAL width (--cbt-side-main, measured from the content), the box is
 * as wide as its longest option, 280 px at the very most (a longer option
 * wraps inside its card). On a wide screen, free space stays to the right. */
.cbt-ui .cbt-layout-side > .cbt-side-main {
	flex: 0 1 var(--cbt-side-main, auto);
}
.cbt-ui .cbt-layout-side > .cbt-side-aside {
	flex: 0 0 auto;
}
.cbt-ui .cbt-layout-side:not(.is-stacked) > .cbt-side-aside > .cbt-box {
	width: max-content;
	max-width: min(280px, 100%);
}
/* /split (sentences, paragraphs): the box about 42 %, the questions the
 * rest, no free space. Below 12em for the box or 16em for the questions
 * the text is unreadable: the line wraps (the builder uses the same numbers). */
.cbt-ui .cbt-layout-split > .cbt-side-main {
	flex: 1 1 16em;
}
.cbt-ui .cbt-layout-split > .cbt-side-aside {
	flex: 0 0 calc((100% - var(--cbt-side-gap)) * 0.42);
	min-width: min(12em, 100%);
}
/* Side by side: the first lines level (above); options one under the other, left-aligned. */
.cbt-ui .cbt-group-body:not(.is-stacked) > .cbt-side-aside > .cbt-box {
	margin-top: 0;
}
/* 0.6.4 — pinned beside the questions. Aligned on the first line, the box
 * column is only as tall as its box: a box made sticky inside it would have
 * nowhere to travel. So, side by side, the COLUMN is the one that stays at
 * the top while the questions of the group scroll by, and leaves with the
 * group. SAME RULE as a box on top (0.6.3.1): the builder marks the column
 * .is-sticky only when each of its boxes is a drag box short enough to be
 * pinned (fitLayout), and puts the padding of the scroller in --cbt-drag-pad. */
.cbt-ui .cbt-group-body.is-side > .cbt-side-aside.is-sticky {
	position: sticky;
	top: calc(var(--cbt-stick-offset, 0px) - var(--cbt-drag-pad, 0px));
	z-index: 1;
}
/* 0.6.4 — a table at the top of the questions (the usual /side case). Its
 * cells are aligned to the top (above), and for a row with no cell aligned
 * on the text a browser takes the BOTTOM of the cells as the row's first
 * line — the box would be levelled with nothing. Side by side only, the
 * first row of a table lines its cells up on their text instead: for a row
 * of one-line cells it looks exactly the same, and the box's first line now
 * meets the table's. */
.cbt-ui .cbt-group-body.is-side > .cbt-side-main table > :is(thead, tbody):first-child > tr:first-child > :is(th, td) {
	vertical-align: baseline;
}
.cbt-ui .cbt-group-body:not(.is-stacked) > .cbt-side-aside .cbt-drag-opts {
	flex-direction: column;
	flex-wrap: nowrap;
	align-items: flex-start;
}
.cbt-ui .cbt-group-body:not(.is-stacked) > .cbt-side-aside .cbt-box.is-columns .cbt-opts {
	display: flex;
	flex-direction: column;
}
/* Not enough room: no columns at all — the box stands above and is laid
 * out like a box on top (options side by side, full width). */
.cbt-ui .cbt-group-body.is-stacked {
	display: block;
}
.cbt-ui .cbt-group-body.is-stacked > .cbt-side-aside {
	display: contents; /* the box is a child of the group again: it pins over the whole group, as on top */
}
/* The builder's measuring pass (one call, never painted): each block at its own width. */
.cbt-ui .cbt-group-body.is-measuring {
	display: block;
}
.cbt-ui .cbt-group-body.is-measuring > .cbt-side-main,
.cbt-ui .cbt-group-body.is-measuring > .cbt-side-aside {
	display: block;
	width: max-content;
}
.cbt-ui .cbt-group-body.is-measuring > .cbt-side-main .cbt-table-scroll > table {
	width: max-content;
}
/* The gap of a /side box stands alone (usually in a table cell): a card
 * of its own, as wide as the widest option card (--cbt-side-card,
 * measured) plus room for the number and the ×; the number in the middle
 * when empty, the option text in the middle when filled. /split gaps sit
 * inside running text and keep the inline gap of 0.6.3. */
.cbt-ui .cbt-layout-side .cbt-drop {
	justify-content: center;
	min-width: calc(var(--cbt-side-card, 8em) + 46px);
	padding: 2px 6px;
	border-radius: var(--cbt-radius);
}
.cbt-ui .cbt-layout-side .cbt-drop.is-filled .cbt-drop-text {
	flex: 1 1 auto;
	text-align: center;
}

/* ------------------------------------------------------------------ */
/* Result state of a question (applied by CBTRender.applyResult).       */
/* ------------------------------------------------------------------ */
.cbt-ui .cbt-q.is-correct input[type="text"].cbt-gap,
.cbt-ui .cbt-q.is-correct select.cbt-select {
	border-color: var(--cbt-correct);
	background-color: var(--cbt-correct-bg);
	color: var(--cbt-correct);
	font-weight: 700;
}
.cbt-ui .cbt-q.is-wrong input[type="text"].cbt-gap,
.cbt-ui .cbt-q.is-wrong select.cbt-select {
	border-color: var(--cbt-wrong);
	background-color: var(--cbt-wrong-bg);
	color: var(--cbt-wrong);
	font-weight: 700;
	text-decoration: line-through;
}
.cbt-ui .cbt-q.is-blank input[type="text"].cbt-gap,
.cbt-ui .cbt-q.is-blank select.cbt-select {
	border-color: var(--cbt-blank);
	background-color: var(--cbt-blank-bg);
}
.cbt-ui .cbt-q.is-graded input[type="text"].cbt-gap,
.cbt-ui .cbt-q.is-graded select.cbt-select {
	pointer-events: none;
}
.cbt-ui .cbt-q.is-graded .cbt-mcq-option {
	pointer-events: none;
	cursor: default;
}
/* 0.6.3: the gap of a drag box, graded like a drop-down. */
.cbt-ui .cbt-q.is-correct .cbt-drop {
	border-style: solid;
	border-color: var(--cbt-correct);
	background-color: var(--cbt-correct-bg);
	color: var(--cbt-correct);
	font-weight: 700;
}
.cbt-ui .cbt-q.is-wrong .cbt-drop {
	border-style: solid;
	border-color: var(--cbt-wrong);
	background-color: var(--cbt-wrong-bg);
	color: var(--cbt-wrong);
	font-weight: 700;
}
.cbt-ui .cbt-q.is-wrong .cbt-drop-text {
	text-decoration: line-through;
}
.cbt-ui .cbt-q.is-blank .cbt-drop {
	border-color: var(--cbt-blank);
	background-color: var(--cbt-blank-bg);
}
.cbt-ui .cbt-q.is-graded .cbt-drop {
	pointer-events: none;
	cursor: default;
}

/* The correct answer, revealed next to a wrong or blank answer. */
.cbt-key {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	color: var(--cbt-correct);
	background-color: var(--cbt-correct-bg);
	border: 1px solid var(--cbt-correct);
	border-radius: calc(var(--cbt-radius) - 2px);
	padding: 2px 10px;
	font-weight: 700;
	font-size: 0.9em;
	line-height: 1.5;
	vertical-align: middle;
	white-space: normal;
	overflow-wrap: anywhere;
}
.cbt-mark {
	display: inline-flex;
	align-items: center;
	vertical-align: middle;
	flex: 0 0 auto;
}
.cbt-mark svg {
	width: 20px;
	height: 20px;
	display: block;
}
.cbt-mark.is-correct svg {
	stroke: var(--cbt-correct);
}
.cbt-mark.is-wrong svg {
	stroke: var(--cbt-wrong);
}

/* Choice results: the key letters go green, a wrong choice goes red. */
.cbt-mcq-letter.mcq-bg-correct {
	background-color: var(--cbt-correct-bg);
	color: var(--cbt-correct);
	border-color: var(--cbt-correct);
}
.cbt-mcq-letter.mcq-bg-wrong {
	background-color: var(--cbt-wrong-bg);
	color: var(--cbt-wrong);
	border-color: var(--cbt-wrong);
}
.cbt-mcq-text.mcq-result-correct {
	color: var(--cbt-correct);
	font-weight: 700;
}
.cbt-mcq-text.mcq-result-wrong {
	color: var(--cbt-wrong);
	font-weight: 600;
}
.cbt-q.is-graded .cbt-mcq-option input:checked ~ .cbt-mcq-letter.mcq-bg-wrong {
	background-color: var(--cbt-wrong-bg);
	color: var(--cbt-wrong);
}
.cbt-q.is-graded .cbt-mcq-option input:checked ~ .cbt-mcq-letter.mcq-bg-correct {
	background-color: var(--cbt-correct);
	color: var(--cbt-white);
}

/* Explanation under a question after grading. */
.cbt-explain {
	display: block;
	margin: 6px 0 12px;
	padding: 8px 14px;
	border-inline-start: 3px solid var(--cbt-primary-light);
	background-color: var(--cbt-bg);
	border-radius: 0 var(--cbt-radius) var(--cbt-radius) 0;
	font-size: 0.95em;
	color: var(--cbt-text);
}
.cbt-explain-label {
	font-weight: 700;
	color: var(--cbt-primary);
	margin-inline-end: 6px;
}
.cbt-q-inline + .cbt-explain {
	margin-top: 8px;
}

/* ------------------------------------------------------------------ */
/* Summary line (top of a graded block / result page).                  */
/* ------------------------------------------------------------------ */
.cbt-summary {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 18px;
	padding: 14px 18px;
	margin: 0 0 1.25em;
	border: 1px solid var(--cbt-border);
	border-radius: var(--cbt-radius);
	background-color: var(--cbt-white);
	box-shadow: 0 6px 18px rgba(0, 0, 0, 0.05);
}
.cbt-summary-score {
	font-size: 1.25em;
	font-weight: 800;
	color: var(--cbt-text-dark);
}
.cbt-summary-score b {
	color: var(--cbt-primary);
	font-size: 1.3em;
}
.cbt-summary-detail {
	color: var(--cbt-text-muted);
	font-size: 0.9em;
	display: flex;
	flex-wrap: wrap;
	gap: 4px 14px;
}
.cbt-summary-detail .is-correct {
	color: var(--cbt-correct);
	font-weight: 600;
}
.cbt-summary-detail .is-wrong {
	color: var(--cbt-wrong);
	font-weight: 600;
}
.cbt-summary-detail .is-blank {
	color: var(--cbt-blank);
	font-weight: 600;
}
.cbt-summary-actions {
	margin-inline-start: auto;
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
}
.cbt-summary-note {
	flex: 1 0 100%;
	font-size: 0.85em;
	color: var(--cbt-text-muted);
	margin: 0;
}

/* ------------------------------------------------------------------ */
/* Buttons.                                                             */
/* ------------------------------------------------------------------ */
.cbt-ui .cbt-btn {
	appearance: none;
	-webkit-appearance: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	background-color: var(--cbt-primary);
	color: var(--cbt-white);
	border: 1px solid var(--cbt-primary);
	padding: 10px 26px;
	border-radius: var(--cbt-radius-pill);
	cursor: pointer;
	font-weight: 700;
	font-size: 0.95em;
	font-family: inherit;
	line-height: 1.3;
	text-decoration: none;
	text-transform: none;
	letter-spacing: 0;
	box-shadow: 0 4px 10px color-mix(in srgb, var(--cbt-primary) 30%, transparent);
	transition: background-color 0.2s ease, border-color 0.2s ease;
	margin: 0;
}
.cbt-ui .cbt-btn:hover,
.cbt-ui .cbt-btn:focus-visible {
	background-color: var(--cbt-primary-hover);
	border-color: var(--cbt-primary-hover);
	color: var(--cbt-white);
	outline: none;
}
.cbt-ui .cbt-btn:disabled {
	opacity: 0.55;
	cursor: not-allowed;
}
.cbt-ui .cbt-btn-secondary {
	background-color: var(--cbt-white);
	color: var(--cbt-primary);
	border-color: var(--cbt-border);
	box-shadow: none;
}
.cbt-ui .cbt-btn-secondary:hover,
.cbt-ui .cbt-btn-secondary:focus-visible {
	background-color: var(--cbt-bg);
	color: var(--cbt-primary);
	border-color: var(--cbt-primary-light);
}
.cbt-ui .cbt-btn svg {
	width: 18px;
	height: 18px;
	stroke: currentColor;
}

/* Small status / error line under the buttons. */
.cbt-status {
	margin: 8px 0 0;
	font-size: 0.9em;
	color: var(--cbt-text-muted);
	min-height: 1.2em;
}
.cbt-status.is-error {
	color: var(--cbt-wrong);
	font-weight: 600;
}

/* Native audio for a listening exercise (the full player is Step 7). */
.cbt-ui audio.cbt-audio {
	display: block;
	width: 100%;
	max-width: 520px;
	margin: 0 0 1em;
}
