/* Dual selector (shadow plan Step 1.2): the item type scale must apply
   inside per-item shadow roots (:host, via the adopted copy) as well as
   on the page (body). */
:host,
body {
    font-size: 14pt;
}

/* <p> intentionally falls through to the browser default
   (display:block, inline content flow). An earlier
   `display:flex; flex-wrap:wrap;` rule broke prose whitespace:
   flex containers discard whitespace text nodes at flex-item
   boundaries, so the spaces around inline <strong>/<em>
   formatting disappeared in the runtime renderer while Quill
   (its own scope) was unaffected. If a specific layout needs
   flex paragraphs, opt in with a class. */

dialog {
    font-size: 14pt;
}
/* Base styles for all math content */
math {
    font-family: "Latin Modern Math", Cambria Math, serif; /* Good mathematical font choices */
    font-size: 1.1em; /* Slightly larger than body text for readability */
    line-height: 1.5; /* Can help with vertical spacing, especially for fractions */
    color: var(--foreground); /* follows the active color theme */
    /* MathML's own layout. inline-block alone turned it off: a <math> whose parts sit
       directly inside it (mi/mo/mn with no wrapping mrow - converted SBAC equations) then laid
       each part out as a block, one per line, so "n = 6" read as a fraction and whole choices
       stood one character wide (Smarter 183573, 2026-09-29). inline-block stays first as the
       fallback for a browser without MathML Core's display: math. */
    display: inline-block;
    display: math;
    vertical-align: middle; /* Align inline math vertically with text */
    /* For block-level math, you'd use: */
    /* display: block; margin: 1em auto; text-align: center; */
}

    /* Ensure responsiveness for all math elements */
    /* This is particularly important for long equations on small screens */
    /* An equation authored in the item body (it carries its source,
       data-eq-value) is laid out in DISPLAY style: inline style shrinks a
       fraction's numerator and denominator well below the text around it, so
       body equations read small in Preview (cert set 2026-10-01 item 19). */
    math[data-eq-value] {
        math-style: normal;
    }

    math[display="block"] {
        display: block; /* fallback, as above */
        display: block math; /* the rule above would otherwise make a display="block" equation inline */
        max-width: 100%;
        overflow-x: auto; /* Adds horizontal scrollbar if content overflows */
        padding-bottom: 0.5em; /* Prevent scrollbar from overlapping content */
    }

math .p-qti-error {
    font-size: 1.5em;
    color: red;
}

    math .p-qti-infocus {
        border: 2px solid red; 
    }

    math.p-qti-editbox {
        display: inline-block; /* the equation editor's input box keeps its box model (min-width, border) */
        border: 2px solid #d1d5db; /* gray-300 - subtle border */
        border-radius: 0.75rem; /* rounded-xl - more rounded corners */
        min-width: 30em;
        padding-top: 3px;
        padding-bottom: 3px;
    }

/* The equation editor's visible input surface (EquationEditorTextbox wraps
   the live <math> in this plain div). Sizing lives HERE because Safari's
   MathML layout ignores CSS min-width on <math> itself — on mac the box
   shrank to hug the equation. The frame also gives the caret clickable
   runway past the end of the content. Static renders that detach the bare
   <math> (assertion chips) keep the math.p-qti-editbox styling above;
   inside a frame the math goes borderless so the box isn't doubled. */
.p-qti-eq-frame {
    display: inline-block;
    border: 2px solid #d1d5db;
    border-radius: 0.75rem;
    min-width: 30em;
    padding: 3px 6px;
    box-sizing: border-box;
    cursor: text;
}

.p-qti-eq-frame > math.p-qti-editbox {
    border: none;
    border-radius: 0;
    min-width: 0;
    padding-top: 0;
    padding-bottom: 0;
}

/* Styling for specific MathML elements */
mi { /* Identifiers (variables, function names) */
    font-style: italic; /* Default for variables, can override if needed */
}

mn { /* Numbers */
    font-weight: normal; /* Numbers usually don't need bolding */
}

mo { /* Operators (+, -, =, etc.) */
    font-weight: bold;
}

mtext { /* Text within math (e.g., units, comments) */
    font-family: sans-serif; /* Use a readable sans-serif font for text */
    font-style: normal;
    color: #6c757d; /* Lighter color for annotations */
}

mo.p-qti-cursor {
    border: none;
    width: .2em;
    color: red;
    font-weight:lighter;
    z-index: 10;
}
/* S7c accessibility: the caret is no longer the focused element (focus is on
   the .p-qti-eq-frame textbox) and its `outline:none` is gone; while the
   editor has focus the caret is drawn bold, and the frame carries the focus
   ring (see the S7c block below). */
mo.p-qti-cursor:focus,
.p-qti-eq-frame:focus-within mo.p-qti-cursor {
    font-weight: bold;
}

/* S7c accessibility — equation editor */
/* Visible focus indicator for the equation textbox (WCAG 2.4.7 / 2.4.11 /
   1.4.11): a 3px dark-blue ring (#1d4ed8, 6.7:1 on white) outside the box —
   a change of shape and thickness, not of colour alone. The box's own border
   is darkened to #6b7280 (4.8:1) so the input's boundary is perceivable. */
.p-qti-eq-frame {
    border-color: #6b7280;
}
.p-qti-eq-frame:focus,
.p-qti-eq-frame:focus-visible {
    outline: 3px solid #1d4ed8;
    outline-offset: 2px;
}
/* The keypad show/hide toggle: a real button, at least 24x24 CSS px (2.5.8). */
.p-qti-eq-keypad-toggle {
    min-width: 24px;
    min-height: 24px;
    margin: .25em;
    vertical-align: middle;
}
/* End S7c accessibility — equation editor */

math msup.p-qti-cursor-highlight {
    color: red;
    font-weight: bold;
    border-color: red;
    border-style: dashed;
}

math .p-qti-selected,
table.p-qti-selected,
tr.p-qti-selected,
td.p-qti-selected,
div.p-qti-output-table .p-qti-selected {
    background-color: yellow;
}

math .p-qti-template {
    font-family: Courier, monospace;
    font-weight: bold;
    color: gray;
    border: 2px dashed lightgrey;
    padding: 3px 3px 3px 3px;
}

math .p-qti-cursor-highlight {
    color: red;
    font-weight: bold;
    outline: red;
}
math .p-qti-cursor-highlight:focus {
    outline: red;
}

math .p-qti-cursor-highlight-block {
    color: var(--foreground);
    font-weight: normal;
    outline: none;
}

img {
    max-width: 100%;
}
.p-qti-onscreen-keypad {
    width: fit-content;
    margin-top: 1em;
}
.p-qti-onscreen-keypad-key {
}

.p-qti-variable-name {
    font-family:Arial, Helvetica, sans-serif;
    font-style:oblique;
}

.p-qti-clickable {
    color: var(--blue);
    text-decoration: underline;
    text-decoration-color: var(--foreground);
    /* Visual breathing room from neighbouring text. The renderer's
       inline span sits flush against adjacent characters when the
       source has no whitespace between, which leaves the underline
       butting into the previous/next glyph. margin-inline adds the
       gap outside the underlined region. */
    margin-inline: 0.2em;
}

.p-qti-tool-button.p-qti-disable {
    background-color: lightgray;
}

.p-qti-nonbutton:disabled,
.p-qti-nonbutton {
    border:none;
    background-color: inherit;
}

.p-qti-blank-key {
    background-color: lightgray;
}
.p-qti-close-button {
    background-image: url('/images/x-square.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    float: right;
}

.p-qti-columns {
    display: grid;
}

/* A blank line the author typed (an empty editor paragraph; ItemTransformer.RestoreBlankLine
   exports it as <p class="p-qti-blank-line"><br/></p>). The editor shows paragraphs with no
   margins, so a blank line there is exactly one line of space. Rendered with the browser's
   1em paragraph margins as well, every blank line added a line AND two margins, and items
   spaced with blank lines (Staircase: 21 of 27 paragraphs) stood twice as far apart as the
   author laid them out (Hub, 2026-09-27). The blank line IS the spacing: it takes no margin,
   and the paragraphs on either side of it give up the margin they share with it. Paragraphs
   with no blank line between them keep their margins. */
p.p-qti-blank-line {
    margin-top: 0;
    margin-bottom: 0;
}

p:has(+ p.p-qti-blank-line) {
    margin-bottom: 0;
}

p.p-qti-blank-line + p {
    margin-top: 0;
}

.p-qti-red-x {
    background-image: url('/images/red-x-circle.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 1.5em;
    width: 1.5em;
    margin: .1em .1em .1em .1em;
}

.p-qti-add {
    background-image: url('/images/plus-square.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 1.5em;
    width: 1.5em;
    margin: .1em .1em .1em .1em;
}

.p-qti-subtract {
    background-image: url('/images/minus-square.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 1.5em;
    width: 1.5em;
    margin: .1em .1em .1em .1em;
}
/* Render multiply / divide as inline text glyphs so the buttons match
   the other operator keys (+, -, =, …) which are typeset characters.
   The legacy SVG-background pattern rendered a fixed-size icon inside
   buttons whose own size came from the keypad's inline font-size, so
   the icons looked off-scale and visually inconsistent with text keys.
   Authors typically set label: ' ' on these keys, so the visible glyph
   comes from this ::before content; data-value on the button still
   carries '*' / '/' for the keystroke dispatch. */
.p-qti-multiply-button::before {
    content: '\00d7';  /* × multiplication sign */
}

.p-qti-divide-button::before {
    content: '\00f7';  /* ÷ division sign */
}

.p-qti-enter-button {
    background-image: url('/images/corner-down-left.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    border: none;
}


.p-qti-green-check {
    background-image: url('/images/green-check-circle.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 1.5em;
    width: 1.5em;
    margin: .1em .1em .1em .1em;
}

.p-qti-add-expression-button {
    background-image: url('/images/addExpression.svg');
    background-repeat: no-repeat;
    background-size: auto;
    height: 2em;
    width: 3em;
    margin: .1em .1em .1em .1em;
    border: none;
}
.p-qti-add-expression-button:disabled {
    background-color: grey;
    opacity: .5;

}

.p-qti-text-and-speak-button button, .p-qti-speak-button {
    background-image: url('/images/volume-2.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    background-color: white;
}

.p-qti-sign-button {
    background-image: url('/images/american-sign-language-interpreting.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    background-color: white;
}
.p-qti-braille-embossed-button {
    background-image: url('/images/printer.svg');
    background-repeat: no-repeat;
    background-size: contain;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    background-color: white;
}
.p-qti-calculator-button {
    background-image: url('/images/grid.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
}

.p-qti-notepad-button {
    background-image: url('/images/file-text.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
}

.p-qti-tool-button {
    background-color: white;
    height: 30px;
    width: 40px;
    margin: .1em .1em .1em .1em;
    border: none;
}
.p-qti-selecttool-button {
    background-image: url('/images/mouse-pointer.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    border: none;
}

.p-qti-trash-button {
    background-image: url('/images/trash-2.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    border: none;
}


.p-qti-delete-button:not(.p-qti-onscreen-keypad-key) {
    background-image: url('/images/delete.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    border: none;
}

/* The Backspace KEY of an on-screen keypad is drawn like the keys around it:
   a typeset glyph on the ordinary key chrome, sized by the keypad's inline
   font-size (as multiply and divide are above), not the fixed white icon
   square the rule above draws for a stand-alone delete control. Its
   accessible name is the key's aria-label ("backspace"). */
.p-qti-onscreen-keypad-key.p-qti-delete-button::before {
    content: '\232b';  /* erase to the left */
}

.p-qti-rectangletool-button {
    background-image: url('/images/rectangletool.jpg');
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    border: none;
}
.p-qti-arrowtool-button {
    background-image: url('/images/arrowtool.jpg');
    background-repeat: no-repeat;
    background-size: contain;
    background-position: center;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
    border: none;
}

    /* S7b (WCAG 1.4.11 / 2.4.7): the selected tool is marked by a dark
       inset ring (>= 3:1 on white; the old #c1c1c1 blur was ~1.7:1), and
       the rule no longer removes the focus outline. */
    .p-qti-selecttool-button.p-qti-selected,
    .p-qti-tool-button.p-qti-selected {
        -webkit-box-shadow: inset 0 0 0 3px #1a1a1a;
        -moz-box-shadow: inset 0 0 0 3px #1a1a1a;
        box-shadow: inset 0 0 0 3px #1a1a1a;
    }

.p-qti-active {
    border: 2px solid black;
}

div.p-qti-numeric-keypad {
    display: grid;
    grid-template-columns: repeat(3,1fr);
    width:fit-content;
    height: fit-content;
}

div.p-qti-number-display {
    min-height: 2.5rem;
    width: 100%;
    text-align: center;
    font-size: 2rem;
}

div.p-qti-object-repeater > div.p-qti-controls > button.p-qti-add,
div.p-qti-object-repeater > div.p-qti-controls > button.p-qti-subtract,
div.p-qti-object-repeater > div.p-qti-controls > button.p-qti-enter-button,
div.p-qti-numeric-keypad button.p-qti-numeric-keypad-key {
    width: 4rem;
    height: 4rem;
    border: 3px groove lightgrey;
    padding: 0px 0px 0px 0px;
    margin: auto;
    font-size: 2rem;
}

div.p-qti-object-repeater > div.p-qti-controls > button.p-qti-add:focus,
div.p-qti-object-repeater > div.p-qti-controls > button.p-qti-subtract:focus,
div.p-qti-object-repeater > div.p-qti-controls > button.p-qti-enter-button:focus,
div.p-qti-numeric-keypad button.p-qti-numeric-keypad-key:focus {
    border-color: goldenrod;
    border-width: 5px;
}

div.p-qti-object-repeater div.p-qti-display {
    position: relative;
    margin-top: 4em;
}

    .p-qti-context-menu-row {
        position: fixed;
        z-index: 100;
        display: inline-flex;
        flex-direction: row;
        margin: 0 0 0 0;
        padding: 0 0 0 0;
    }
.p-qti-context-menu-row li {
    list-style-type: none;
}

.p-qti-dialog {
    border: 1px solid var(--foreground);
    background-color: var(--background);
}

/* InlineConfirm: the in-page replacement for window.confirm inside PCI frames. */
.p-qti-inline-confirm {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5em;
    margin: 0.25em 0;
    padding: 0.4em 0.6em;
    border: 1px solid var(--foreground);
    background-color: var(--background);
    color: var(--foreground);
}
.p-qti-inline-confirm button {
    min-height: 24px;
    min-width: 24px;
}
.p-qti-dialog-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
}


.p-qti-resize-handle {
    background: repeating-linear-gradient( 135deg, rgba(255,255,255,0) 0px, rgba(255,255,255,0) 4px, rgba(0,0,0,1) 6px );
    position: absolute;
    height: 15px;
    width: 15px;
    right: 0px;
    bottom: 0;
    /* Cursor on the BASE class, not just :hover — hover-only rules can
       show the underlying text I-beam while the pointer settles on the
       corner (seen on macOS). touch-action:none keeps a touch drag from
       scrolling instead of resizing. */
    cursor: nwse-resize;
    touch-action: none;
}

    .p-qti-resize-handle:focus, .p-qti-resize-handle:hover {
        cursor: nwse-resize;
    }

/* While a resize drag is live (ResizeHandle stamps this on <html>): the
   pointer easily outruns the 15px corner mid-drag, and without these the
   cursor flips to the text I-beam over surrounding content and the drag
   starts selecting text. */
html.p-qti-resizing,
html.p-qti-resizing * {
    cursor: nwse-resize !important;
    -webkit-user-select: none !important;
    user-select: none !important;
}

.p-qti-widget-title {
    width: 100%;
    min-height: 2em;
    background-color: lightgray;
    display: flex;
    align-items: center;
    box-sizing: border-box;
    padding: .5em;
}

.p-qti-widget-title .p-qti-close-button {
    float: none;
    flex: 0 0 auto;
    margin-left: auto;
}
.p-qti-dialog-title {
    width: 100%;
    height: 2em;
    background-color: lightgray;
    display: block;
}
.p-qti-moveable {
    position: absolute;
    width: 30%;
    height: auto;
    z-index: 100;
    border: 2px solid grey;
    background-color: aliceblue;
}

.p-qti-dragging-span {
    background-image: url('/images/move.svg');
    background-repeat: no-repeat;
    background-size: contain;
    display: flex;
    height: 2em;
    margin: 0px 0px 2px 2px;
    flex: 10;
}

.p-qti-moveable-display {
    position: relative;
    width: 100%;
    height: 80%;
    padding: .5em;
    box-sizing: border-box;
}

.p-qti-fill-parent {
    height: 100%;
    width: 100%;
}

.p-qti-moveable-display .p-qti-fill-parent video {
    height: 100%;
}

/* Catalog "from link" popup (glossary, keyword translation, long
   description ...). Cert-set 71: it inherited the page root's tiny serif
   text, named nothing and took 30% of the window whatever its content. It
   mounts on the document root, outside the item, so it sets its own
   readable type and a content-sized, viewport-capped width
   (RenderedContentMethods also keeps it inside the viewport). */
.p-qti-moveable.p-qti-catalog-popup {
    width: auto;
    min-width: min(18rem, calc(100vw - 16px));
    max-width: min(32rem, calc(100vw - 16px));
    max-height: calc(100vh - 16px);
    overflow: auto;
    box-sizing: border-box;
    font-family: "Segoe UI", system-ui, -apple-system, Roboto, Helvetica, Arial, sans-serif;
    font-size: 1.125rem;
    line-height: 1.5;
    color: #1a1a1a;
    background-color: #ffffff;
    border: 2px solid #1565c0;
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}

.p-qti-catalog-popup .p-qti-moveable-display {
    height: auto;
    padding: .25em .9em .9em .9em;
}

.p-qti-catalog-popup .p-qti-catalog-popup-heading {
    font-size: 1.25em;
    font-weight: 600;
    line-height: 1.3;
    margin: 0 0 .4em 0;
}

.p-qti-catalog-popup .p-qti-widget-title {
    background-color: #e3ecf8;
}

.p-qti-text-and-speak-button {
    display: grid;
    grid-template-columns: 10fr 1fr;
}

/* Loading overlay. Renders the same TestQuill spinner the rest of the app
   uses (WAF.WaitForEvent / TestQuillSpinnerSmall.png) on a rotating
   pseudo-element, matching the WAF waf-spin animation (1.2s linear). The
   image is served from the engine's host /images/ path — the same
   convention as the other /images/ assets in this file — so QTIScripts
   stays self-contained and does not reference /WAFScripts/ or Scripts/. */
.p-qti-waiter {
    position: fixed;
    top: 0px;
    left: 0px;
    width: 100%;
    height: 100%;
    z-index: 99;
    background-color: rgba(0,0,0,.5);
    display: flex;
    align-items: center;
    justify-content: center;
}

.p-qti-waiter::before {
    content: "";
    width: 100px;
    height: 100px;
    background-image: url(/images/TestQuillSpinnerSmall.png);
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
    animation: p-qti-waiter-spin 1.2s linear infinite;
}

@keyframes p-qti-waiter-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
/* general presentation */
header.p-qti-stimulus-header {

}

div.p-qti-stimulus {
    height: calc(100vh - 40px);
    overflow:auto;
}

div.p-qti-item-container {
    height: calc(100vh - 40px);
    overflow: auto;
}

/* Split-pane container. The stimulus + item panes used float-based
 * qti-layout-col5/col7 whose widths + margin summed to ~100.01% and were
 * influenced by their content, so the stimulus pane overran the item
 * pane on first render (and only an unrelated reflow — e.g. activating
 * the hottext — corrected it). Make the row a flex container (the
 * split-vertical / stacked layout-mode rules below already assume flex
 * via flex-direction: column). */
.qti-layout-row.p-qti-stim-split {
    display: flex;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 16px;
    width: 100%;
    box-sizing: border-box;
}

    /* Size the panes purely by a 5:7 grow ratio with a ZERO flex-basis
     * and min-width:0, so each pane is always a fixed fraction of the
     * row regardless of its content. This is what stops the stimulus
     * text from widening its pane into the item pane. */
    .qti-layout-row.p-qti-stim-split > .p-qti-stimulus,
    .qti-layout-row.p-qti-stim-split > .p-qti-item-container {
        float: none;
        margin: 0;
        min-width: 0;
        flex: 1 1 0;
        box-sizing: border-box;
    }

    .qti-layout-row.p-qti-stim-split > .p-qti-stimulus {
        flex-grow: 5;
    }

    .qti-layout-row.p-qti-stim-split > .p-qti-item-container {
        flex-grow: 7;
    }

    /* Stimulus content wraps at word boundaries; a word is only broken
     * mid-character when it alone is too long for the pane (otherwise it
     * would overflow). min-width:0 + flex-basis:0 above already keep the
     * pane content-independent, so break-word never widens it.
     * overflow-wrap is inherited, so setting it on the pane covers
     * descendants without an aggressive universal selector. */
    .qti-layout-row.p-qti-stim-split > .p-qti-stimulus {
        overflow-wrap: break-word;
    }

    .qti-layout-row.p-qti-stim-split > .p-qti-stimulus img,
    .qti-layout-row.p-qti-stim-split > .p-qti-stimulus table {
        max-width: 100%;
    }

/* Per-part Score button a container PCI places above each former item
   (frame hosts — PassageSet._placePartScoreButtons): a FULL-WIDTH bar in
   a contrasting dark teal-blue, so each part's scoring affordance reads
   as a section divider. White on #14506e is >= 7:1 (WCAG AAA). Mirrors
   the public demo's page-side .public-part-score-btn (ExamineeStyles.css)
   — keep the two in sync. */
.p-qti-part-score-btn {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 0.5em 1em;
    margin: 0.75em 0 0.5em;
    font-size: 0.95em;
    font-weight: 600;
    text-align: center;
    color: #fff;
    background: #14506e;
    border: 1px solid #0e3a51;
    border-radius: 4px;
    cursor: pointer;
}

.p-qti-part-score-btn:hover {
    background: #0e3a51;
}

.p-qti-part-score-btn:focus-visible {
    outline: 3px solid #0b4ea2;
    outline-offset: 2px;
}

/* ============================================================
 * Item-group presentation modes (StimulusPlan §Phase 7).
 *
 * SectionClass on PresentItemGroup carries layout + presentation
 * classes that the renderer applies to _presentationDiv. CSS rules
 * here handle the four authored layouts and three stimulus
 * presentation modes (stacked / tabs / highlight). Defaults match
 * today's behaviour — split-horizontal stacked.
 * ============================================================ */

.stimulus-layout-split-horizontal {
    /* Default — already provided by .qti-layout-row + .qti-layout-col5/7. */
}

.stimulus-layout-split-vertical {
    flex-direction: column;
}

    .stimulus-layout-split-vertical .qti-layout-col5,
    .stimulus-layout-split-vertical .qti-layout-col7 {
        width: 100% !important;
        max-width: 100%;
    }

.stimulus-layout-stacked {
    flex-direction: column;
}

    .stimulus-layout-stacked .p-qti-stimulus,
    .stimulus-layout-stacked .p-qti-item-container {
        height: auto;
        max-height: 50vh;
        width: 100%;
    }

.stimulus-layout-inline .p-qti-stimulus {
    /* Inline mode — stimulus rendered within the item body via
     * the SBAC-override path; the standalone stimulus pane is
     * suppressed. */
    display: none;
}

/* ============================================================
 * Stacked bilingual rendering (language variants, plan §10 / S6).
 * ONE composed artifact: each translated block keeps its element and
 * carries two child spans — the source reading and the translation
 * (lang-marked for assistive tech). The delivery layout class
 * (bilingual-source-top / bilingual-translation-top /
 * bilingual-side-by-side) picks the arrangement — pure CSS, never a
 * re-composition. DOM (reading) order is always source-first, so
 * screen readers hear one consistent order in every layout.
 * ============================================================ */

.p-qti-bilingual-pair > .p-qti-bilingual-source,
.p-qti-bilingual-pair > .p-qti-bilingual-translation {
    display: block;
}

.p-qti-bilingual-pair > .p-qti-bilingual-translation {
    margin-top: 0.25em;
}

.bilingual-translation-top .p-qti-bilingual-pair {
    display: flex;
    flex-direction: column-reverse;
}

    .bilingual-translation-top .p-qti-bilingual-pair > .p-qti-bilingual-translation {
        margin-top: 0;
        margin-bottom: 0.25em;
    }

.bilingual-side-by-side .p-qti-bilingual-pair {
    display: flex;
    flex-direction: row;
    gap: 1em;
}

    .bilingual-side-by-side .p-qti-bilingual-pair > .p-qti-bilingual-source,
    .bilingual-side-by-side .p-qti-bilingual-pair > .p-qti-bilingual-translation {
        flex: 1 1 0;
        min-width: 0;
        margin-top: 0;
    }

/* The translation side of a block whose response control lives in the
 * source reading shows a numbered marker at the translator's token —
 * 7:1 contrast on white per WCAG AAA. */
.p-qti-bilingual-token-marker {
    border: 1px solid #3c3c3c;
    border-radius: 999px;
    padding: 0 0.4em;
    font-size: 0.85em;
    color: #1a1a1a;
    background: #f2f2f2;
    white-space: nowrap;
}

/* Per-stimulus section wrappers inside the stimulus pane. */
section.p-qti-stimulus-entry {
    border-bottom: 1px solid #e0e0e0;
    padding: 8px 0;
}

    section.p-qti-stimulus-entry:last-child {
        border-bottom: none;
    }

/* Stacked is the default and needs no extra rules — sections
 * already stack via block layout. */

/* Tabs mode — tab strip lives at the top of _stimDiv with one
 * button per stimulus; only the active tabpanel is visible. */
.p-qti-stimulus-tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid #c7c7c7;
    margin-bottom: 6px;
}

.p-qti-stimulus-tab {
    background: #f3f3f3;
    border: 1px solid #c7c7c7;
    border-bottom: none;
    padding: 4px 10px;
    cursor: pointer;
    font-size: 0.9em;
    border-radius: 4px 4px 0 0;
}

    .p-qti-stimulus-tab[aria-selected="true"] {
        background: var(--background);
        font-weight: bold;
    }

/* Highlight mode — every stimulus stacked, but the ones the
 * focused item references get a visual emphasis class added/removed
 * by PresentationManager._prepareItemDiv's focusin handler. */
.p-qti-stimulus-highlight-mode section.p-qti-stimulus-entry {
    opacity: 0.55;
    transition: opacity 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

    .p-qti-stimulus-highlight-mode section.p-qti-stimulus-entry.p-qti-stimulus-active {
        opacity: 1;
        box-shadow: -3px 0 0 0 #2c7be5;
        background: #f8fbff;
    }

/*interactions*/

.p-qti-slider-interaction {
    display: grid;
    place-items: center;
    width: 100%;
    position: relative;
}

.p-qti-slider-interaction.p-qti-slider-vertical input[type=range] {
    appearance: slider-vertical;
    -webkit-appearance: slider-vertical;
    height: 250px;
    width: auto;
}

 div.p-qti-slider-interaction > div,
.p-qti-slider-interaction:first-child {
    width: 100%;
    position: relative;
    margin-top: 35px;
}

    div.p-qti-slider-interaction.p-qti-slider-vertical > div,
    .p-qti-slider-interaction.p-qti-slider-vertical:first-child {
       
        margin-top: 0px;
    }


    .p-qti-slider-interaction input[type=range] {
        -webkit-appearance: none; /* Override default CSS styles */
        appearance: none;
        width: 80%;
        height: 50px; /* Specified height */
        outline: none; /* Remove outline */
        opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
        -webkit-transition: .2s; /* 0.2 seconds transition on hover */
        transition: opacity .2s;
        margin-top: 0px;
        margin-bottom: 0px;
        padding: 0px 0px 0px 0px;
        padding-bottom: 0px;
        background: linear-gradient(.5turn,darkslategrey, white, darkslategrey);
    }
        .p-qti-slider-interaction input[type=range]::-webkit-slider-runnable-track {
            height: 100%;
            margin-top: 0px;
            margin-bottom: 0px;
        }
        .p-qti-slider-interaction input[type=range]::-webkit-slider-thumb {
            -webkit-appearance: none; /* Override default CSS styles */
            appearance: none;
            height: 100%;
            width: 15px;
            background-color: transparent;
            border-radius: 50%;
            border-left: 4px solid black;
            border-right: 3px solid darkslategrey;
            border-style: solid;
        }

        .p-qti-slider-interaction input[type=range]::-moz-range-thumb{
            appearance: none;
            height: 100%;
            width: 15px;
            background-color: transparent;
            border-radius: 50%;
            border: 1px solid #f50;
            border-style:double;
        }
        .p-qti-slider-interaction input[type=range]::-moz-range-track{
            background-color: yellow;
            height: 100%;
            margin-top: 0px;
            margin-bottom: 0px;
        }

        .p-qti-slider-interaction label {
            font-size: 25px;
            width: 10%;
            vertical-align: central;
        }
        .p-qti-slider-interaction.p-qti-slider-vertical .p-qti-slider-output {
            margin-top: 0px;
        }
        .p-qti-slider-interaction .p-qti-slider-output {
            border: none;
/*            height: 50px;
            width:  6em;
            border-radius: 50%;
*/            font-size: large;
            font-weight: bold;
/*            background-color: lightgray;
            text-align: center;
*/            position: absolute;
              width: min-content;
            margin-top: 5px;
        }
        .p-qti-slider-interaction .p-qti-slider-ticks {
            height: 80%;
            display:inline-flex;
            justify-content:space-evenly;
            position: absolute;
        }

/* PADDING, never margin: this class sits on the element the host hands the
   PCI (getInstance's dom), and a margin on that element lies OUTSIDE it. A
   host that sizes its frame from that element's box (amp-up.io's pci.html
   reports getBoundingClientRect().right/bottom) then loses the bottom margin
   to clipping and, worse, the right margin on EVERY re-measure: each DOM
   change narrowed the frame by 2em and the responsive canvas shrank with it.
   Inside Ments' own frames (body is a flow-root) padding and margin lay out
   identically. */
.p-qti-graphic-interaction {
    padding: 2em;
}

.p-qti-graphic-interaction>svg {
    outline:groove;
}

/* Background image fills the SVG canvas width while preserving its
 * intrinsic aspect ratio. Mirrors the authoring-side rule
 * (TestQuill.css: div.tq-graphic-canvas-editor > div.tq-svg-holder > svg > image)
 * so the image renders at the same size in the iframe runtime as it does
 * in the template editor. Without this, the SVG image relied on its
 * width/height attributes (which match the saved canvas dims), making
 * the rendered size brittle to attribute drift; the CSS rule decouples
 * visible size from saved attributes the same way authoring already does. */
.p-qti-graphic-interaction > svg > image.p-qti-background-image {
    width: 100%;
    height: auto;
}

.p-qti-graphic-interaction line.p-qti-added {
    color: red;
}

    .p-qti-graphic-interaction line.p-qti-added.p-qti-selected:focus,
    .p-qti-graphic-interaction line.p-qti-added.p-qti-selected {
        /* S7b: outline:none removed - the S7b block draws focus/selection */
        marker-start: url('#dot1');
        marker-end: url('#dot1');
        stroke: black;
        stroke-width: 1;
    }

.p-qti-graphic-interaction marker.dot1 > circle:hover {
    cursor: nesw-resize;
}


.p-qti-graphic-interaction line.p-qti-arrow,
.p-qti-graphic-interaction line.p-qti-added.p-qti-arrow {
    marker-end: url('#arrow1');
}
    .p-qti-graphic-interaction line.p-qti-added.p-qti-arrow.p-qti-selected {
        /* S7b: outline:none removed - the S7b block draws focus/selection */
        marker-start: url('#dot1');
        marker-end: url('#redarrow1');
    }


.p-qti-graphic-interaction svg line.p-qti-added.p-qti-arrow:focus {
    stroke-width: 1;
}
.p-qti-graphic-interaction svg line.p-qti-added.p-qti-arrow.p-qti-selected:focus {
    stroke-width: 1;
}


.p-qti-graphic-interaction svg line.p-qti-added:focus {
    /* S7b: outline:none removed - the S7b block draws focus/selection */
    stroke-width: 5;
}
.p-qti-graphic-interaction polyline.p-qti-added.p-qti-selected {
    /* S7b: outline:none removed - the S7b block draws focus/selection */
    marker-end: url('#dot1');
    marker-start: url('#dot1');
    marker-mid: url('#dot1');
}

/* A drawn circle has no vertices, so SVG marker-* (used by line/polyline above)
   can't apply. Highlight it the same way a selected hotspot is shown — a strong
   high-contrast stroke plus a halo — so it reads over any fill or pattern and
   meets the AAA visible-focus bar. */
.p-qti-graphic-interaction circle.p-qti-added.p-qti-selected:focus,
.p-qti-graphic-interaction circle.p-qti-added.p-qti-selected {
    /* S7b: outline:none removed - the S7b block draws focus/selection */
    stroke: #0066cc;
    stroke-width: 3;
    filter: drop-shadow(0 0 4px #0066cc);
}


.p-qti-graphic-interaction svg .p-qti-hotspot {
    fill: transparent;
    stroke: black;
}


.p-qti-graphic-interaction svg .p-qti-hotspot.p-qti-drop-ready {
    stroke: red;
    stroke-width: 3;
}

.p-qti-graphic-interaction svg .p-qti-hotspot.p-qti-hotspot-selected {
    fill: rgba(0, 102, 204, 0.25);
    stroke: #0066cc;
    stroke-width: 3;
}

/* The scoring screen's highlight of a selected hotspot entity (highlightEntity),
   red like a highlighted placed image. */
.p-qti-graphic-interaction svg .p-qti-hotspot.p-qti-selected {
    stroke: red;
    stroke-width: 4;
}

.p-qti-graphic-interaction svg .p-qti-hotspot:focus {
    outline: 2px solid #0066cc;
    outline-offset: 2px;
}

/* QTI 3 shared vocabulary hotspot themes (vocab §1.2.5 graphic gap match, §1.2.9 hotspot), read
   from the interaction's classes (GraphicResponse.js keeps them on the render target).
   qti-selections-light: lines and fills LIGHTER than usual, for a dark picture; qti-selections-dark:
   darker, for a light one. Each theme's selection is a thicker line and a fill, with a halo of the
   opposite tone so it holds its contrast over any part of the picture. */
.p-qti-graphic-interaction.qti-selections-light svg .p-qti-hotspot {
    stroke: #ffffff;
}

.p-qti-graphic-interaction.qti-selections-light svg .p-qti-hotspot.p-qti-hotspot-selected,
.p-qti-graphic-interaction.qti-selections-light svg .p-qti-hotspot.p-qti-drop-ready {
    fill: rgba(255, 255, 255, 0.35);
    stroke: #ffffff;
    stroke-width: 4;
    filter: drop-shadow(0 0 2px #000000);
}

.p-qti-graphic-interaction.qti-selections-dark svg .p-qti-hotspot {
    stroke: #000000;
}

.p-qti-graphic-interaction.qti-selections-dark svg .p-qti-hotspot.p-qti-hotspot-selected,
.p-qti-graphic-interaction.qti-selections-dark svg .p-qti-hotspot.p-qti-drop-ready {
    fill: rgba(0, 0, 0, 0.35);
    stroke: #000000;
    stroke-width: 4;
    filter: drop-shadow(0 0 2px #ffffff);
}

/* qti-unselected-hidden: an area that is not chosen draws no outline (only VISUALLY hidden - every
   hotspot stays a focusable radio / checkbox, vocab §1.2.9). A chosen area, a drop target being
   hovered and the FOCUSED area are still drawn, so a keyboard user always sees where they are. */
.p-qti-graphic-interaction.qti-unselected-hidden svg .p-qti-hotspot:not(.p-qti-hotspot-selected):not(.p-qti-drop-ready):not(:focus) {
    stroke: transparent;
}

.p-qti-graphic-interaction svg image.p-qti-added.p-qti-selected {
    outline: 3px solid red;
}

.p-qti-graphic-interaction svg.p-qti-dot-cursor {
    cursor:url(#dot1);
}


@keyframes circleThrob {
    from {
        r: 5;
    }

    to {
        r: 15;
    }
}



.p-qti-graphic-interaction svg circle.p-qti-encircle {
    fill: red;
    stroke: red;
    stroke-width: 3px;
    animation-duration: .33s;
    animation-iteration-count: infinite;
    animation-name: circleThrob;
}

.p-qti-graphic-interaction qti-gap-img {
    display: flex;
    flex-direction: row;
    gap: 0.5em;
}

.p-qti-graphic-interaction qti-gap-img img {
    margin: 0.5em;
    border: 2px solid #ccc;
    border-radius: 4px;
    cursor: grab;
    transition: all 0.2s;
}

.p-qti-graphic-interaction qti-gap-img img:hover {
    border-color: #0066cc;
    transform: scale(1.05);
}

.p-qti-graphic-interaction qti-gap-img img:active {
    cursor: grabbing;
}

.p-qti-graphic-interaction .p-qti-drag-pallette,
.p-qti-graphic-interaction .p-qti-drag-palette {
    display: flex;
    flex-direction: row;
    /* Wrap rather than squeeze: at a large text size the choices flow onto
       more rows instead of breaking their words (bug #89, WCAG 1.4.10). */
    flex-wrap: wrap;
    gap: 0.5em;
    margin-top: 1em;
    padding: 0.5em;
    border: 2px dashed #ccc;
    border-radius: 4px;
    background: #f9f9f9;
}

/* Drag palette images */
.p-qti-graphic-interaction .p-qti-drag-pallette img,
.p-qti-graphic-interaction .p-qti-drag-palette img {
    margin: 0.5em;
    border: 2px solid #ccc;
    border-radius: 4px;
    cursor: grab;
    transition: all 0.2s;
}

.p-qti-graphic-interaction .p-qti-drag-pallette img:hover,
.p-qti-graphic-interaction .p-qti-drag-palette img:hover {
    border-color: #0066cc;
    transform: scale(1.05);
}

.p-qti-graphic-interaction .p-qti-drag-pallette img:active,
.p-qti-graphic-interaction .p-qti-drag-palette img:active {
    cursor: grabbing;
}

/* Graphic gap match TEXT choices (qti-gap-text) are real text (cert bug #89):
   the palette chip is the item's own font, never smaller than body text, so it
   follows the reader's zoom and text-size setting; a long choice wraps. A
   placed choice's text is laid over its box by
   GraphicResponseUtilities.installGapTextLabels (inline styles there). */
.p-qti-graphic-interaction .p-qti-drag-pallette .p-qti-gap-text,
.p-qti-graphic-interaction .p-qti-drag-palette .p-qti-gap-text {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    align-self: flex-start;
    flex: 0 0 auto;
    min-height: 44px;
    min-width: 44px;
    max-width: 20em;
    margin: 0.5em;
    padding: 0.3em 0.75em;
    font-family: inherit;
    font-size: max(1em, 16px);
    line-height: 1.3;
    text-align: center;
    overflow-wrap: break-word;
    color: #1a1a1a;
    background: #ffffff;
    border: 2px solid #1a1a1a;
    border-radius: 4px;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
}

.p-qti-graphic-interaction .p-qti-drag-pallette .p-qti-gap-text:hover,
.p-qti-graphic-interaction .p-qti-drag-palette .p-qti-gap-text:hover {
    border-color: #0066cc;
}

.p-qti-graphic-interaction .p-qti-drag-pallette .p-qti-gap-text:focus-visible,
.p-qti-graphic-interaction .p-qti-drag-palette .p-qti-gap-text:focus-visible {
    outline: 3px solid #0066cc;
    outline-offset: 2px;
}

.p-qti-graphic-interaction .p-qti-drag-pallette .p-qti-gap-text:active,
.p-qti-graphic-interaction .p-qti-drag-palette .p-qti-gap-text:active {
    cursor: grabbing;
}

.p-qti-graphic-interaction .p-qti-drag-pallette .p-qti-gap-text[aria-disabled="true"],
.p-qti-graphic-interaction .p-qti-drag-palette .p-qti-gap-text[aria-disabled="true"] {
    cursor: default;
}

/* Image-palette placement (graphic gap match data-palette-position). Applied
   ONLY when an explicit p-qti-palette-<pos> class is present (set by
   GraphicResponseUtilities.positionDragPalette), so items with no attribute keep
   their historical block layout (palette below the canvas). The tool palette
   (Select/Delete) stays a full-width bar on top in every mode. */
.p-qti-graphic-interaction.p-qti-palette-above,
.p-qti-graphic-interaction.p-qti-palette-below {
    display: flex;
    flex-direction: column;
}

.p-qti-graphic-interaction.p-qti-palette-left,
.p-qti-graphic-interaction.p-qti-palette-right {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 1em;
}

    .p-qti-graphic-interaction.p-qti-palette-left > .p-qti-tool-palette,
    .p-qti-graphic-interaction.p-qti-palette-right > .p-qti-tool-palette {
        flex: 0 0 100%;               /* keep the Select/Delete bar on its own top row */
    }

    .p-qti-graphic-interaction.p-qti-palette-left > svg,
    .p-qti-graphic-interaction.p-qti-palette-right > svg {
        flex: 0 0 auto;
        max-width: 100%;
    }

    .p-qti-graphic-interaction.p-qti-palette-left > .p-qti-drag-pallette,
    .p-qti-graphic-interaction.p-qti-palette-right > .p-qti-drag-pallette {
        flex-direction: column;       /* a side palette stacks its images vertically */
        margin-top: 0;
    }

.p-qti-graphic-interaction.p-qti-palette-above > .p-qti-drag-pallette {
    margin-top: 0;
    margin-bottom: 1em;
}

/* Palette element ORIENTATION (graphic gap match data-palette-orientation),
   independent of the above/below/left/right placement. Absent / 'auto' applies
   no class, so the position-implied default stands (a side palette stacks, an
   above/below palette flows in a row — the historical look). These rules come
   AFTER the position rules so, on equal specificity, an explicit orientation
   wins — e.g. a LEFT palette can be forced to flow horizontally. */
.p-qti-graphic-interaction.p-qti-palette-orient-horizontal > .p-qti-drag-pallette,
.p-qti-graphic-interaction.p-qti-palette-orient-horizontal > .p-qti-drag-palette {
    flex-direction: row;
    flex-wrap: wrap;
}

.p-qti-graphic-interaction.p-qti-palette-orient-vertical > .p-qti-drag-pallette,
.p-qti-graphic-interaction.p-qti-palette-orient-vertical > .p-qti-drag-palette {
    flex-direction: column;
    flex-wrap: nowrap;
}

.p-qti-graphic-interaction .p-qti-prompt-container span.tq-image {
    display: inline-block;
    overflow: hidden;
}

.p-qti-graphic-interaction .p-qti-prompt-container span.tq-image img {
    max-width: 100%;
    max-height: 100%;
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.p-qti-extended-text-interaction {
    /* Block host: AUTO width fills the container minus the side
       margins. The old `width: 100%` + 1em side margins made the
       host 2em wider than every container, which kept the authoring
       stand-in iframe permanently scrollbarred (horizontal overflow
       → h-scrollbar → v-scrollbar) and spilled the editor's border
       past its container in delivery.
       PADDING, never margin (as .p-qti-graphic-interaction): this class
       sits on the element the host hands the PCI (getInstance's dom), and
       a margin there lies OUTSIDE that element. amp-up.io's pci.html sizes
       its frame from that element's box (clientHeight at PciReady,
       getBoundingClientRect().bottom on change), so the bottom 1em was
       clipped: frame 234px, content 250px (the floor book, 2026-09-24).
       The padding also stops the wrapper's bottom margin collapsing out
       through the host; the wrapper drops that margin below so the
       spacing stays 1em, as it was when the two collapsed together. Inside
       Ments' own frames (body is a flow-root) the frame is 250px before
       and after. In page flow the host's 1em no longer collapses with a
       neighbour's margin, so the gap to adjacent blocks can grow by up to
       1em there. */
    padding: 1em;
}

.p-inline-entry {
    display: inline-block;
}


ol.p-qti-no-linefeed > li > label > span > span > div:nth-child(1) {
    display: inline;
    padding: 0px;
    margin: 0px;
    border: 0px;
}

.p-qti-universal-number-line-interaction .p-grab-region {
    cursor: grab;
    fill: transparent;
    pointer-events: all;
}
.p-qti-universal-number-line-interaction svg {
    width: 98%;
    padding: 5px 5px 5px 5px;
}
.p-qti-universal-number-line-interaction svg:focus {
    /* S7b (2.4.7): a visible focus ring (was outline: none) */
    outline: 3px solid #005fcc;
    outline-offset: 2px;
}

.p-qti-universal-number-line-interaction svg line.p-dragging-thumb-line {
    stroke: red;
}

/* Tick marks and their labels are decoration: the thumb drags across them. */
.p-qti-universal-number-line-interaction svg .p-number-line-ticks,
.p-qti-universal-number-line-interaction svg .p-number-line-tick,
.p-qti-universal-number-line-interaction svg .p-number-line-tick-label {
    pointer-events: none;
}
.p-qti-universal-number-line-interaction svg .p-number-line-tick-label {
    font-family: sans-serif;
    user-select: none;
}

.p-qti-rapid-decompose,
.p-qti-rapid-choice,
.p-qti-rapid-compare {
    /* Containing block for the absolutely-positioned .p-qti-shield, which
       is appended here (RapidResponse.js). Without it the shield sizes to
       the nearest positioned ancestor and covers far more than the
       interaction. */
    position: relative;
    display: flex;
    flex-wrap: wrap;
    flex-direction: column;
    justify-content: center;
    align-content: center;
}
.p-qti-rapid-quantity {
    /* Containing block for the .p-qti-shield overlay — see above. */
    position: relative;
    display: grid;
    justify-content: center;
}

.p-qti-shield {
    background-color: aqua;
    position: absolute;
    z-index: 5;
    width: 100%;
    height: 100%;
    top: 0px;
    left: 0px;
    display: flex;
    justify-content: center;
    align-items: center;
}

div.p-qti-rapid-decompose div.p-qti-quantity-stimulus,
div.p-qti-rapid-quantity div.p-qti-quantity-stimulus {
    display: grid;
    width: fit-content;
    height: fit-content;
}

div.p-qti-rapid-decompose div.p-qti-quantity-stimulus {
    text-align: center;
}

div.p-qti-rapid-compare div.p-qti-quantity-stimulus{
    display: flex;
    justify-content: center;
}
div.p-qti-rapid-quantity div.p-qti-quantity-stimulus > svg {
    margin: 10px;
}
div.p-qti-rapid-choice div.p-qti-response,
div.p-qti-rapid-quantity div.p-qti-response {
    display: grid;
    width: auto;
    height: fit-content;
}

div.p-qti-rapid-choice div.p-qti-quantity-stimulus > div {
    font-weight: bold;
    border: outset;
    text-align: center;
    height: fit-content;
    align-self: center;
}

 
div.p-qti-rapid-compare div.p-qti-quantity-stimulus > div,
div.p-qti-rapid-quantity div.p-qti-response > div {
    background-color: lightgray;
    font-weight: bold;
    border: outset;
    text-align: center;
    height: fit-content;
}
div.p-qti-rapid-choice div.p-qti-response > div,
div.p-qti-rapid-compare div.p-qti-quantity-stimulus > div {
    margin: 40px;
    padding-left: 15px;
    padding-right: 15px;
}

/* Simulation: a restored row whose recorded outputs the current
   calculations no longer give (scoring audit N85). The dashed outline is a
   shape cue, not colour alone; the note above the table says what it means. */
.p-qti-output-table tr.p-qti-stale-output-row td {
    outline: 2px dashed var(--warning);
    outline-offset: -2px;
}

.p-qti-stale-outputs-note {
    margin: 0.5em 0;
    padding: 0.25em 0 0.25em 0.5em;
    border-left: 4px solid var(--warning);
    color: var(--foreground);
    background-color: var(--background);
    font-weight: 600;
}

/* Simulation table empty row styling */
.p-qti-output-table tr.p-qti-output-table-row-empty {
    background-color: transparent;
    border: none;
}

.p-qti-output-table tr.p-qti-output-table-row-empty td {
    background-color: transparent;
    border: none;
    min-height: 1.5em;
    height: 1.5em;
}

/* ========== WCAG 2.1 AA Accessibility Enhancements ========== */

/* Visually hidden but accessible to screen readers */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    border: 0;
}

/* High contrast focus indicators for widgets */
.p-qti-range-widget:focus,
.p-qti-numeric-widget:focus,
.p-qti-select-widget:focus,
.p-qti-checkbox-widget:focus,
.p-qti-radio-widget-group input[type="radio"]:focus {
    outline: 3px solid #0078D4;
    outline-offset: 2px;
}

/* Widget spacing for proper layout */
.p-qti-widget-wrapper {
    margin-bottom: 1rem;
}

/* Checkbox and radio spacing with minimum touch target size */
.p-qti-checkbox-wrapper,
.p-qti-radio-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 44px;
}

/* Delete button minimum touch target size */
.p-qti-delete-row-button {
    min-width: 44px;
    min-height: 44px;
}

/* Fieldset styling for radio groups */
.p-qti-radio-fieldset {
    border: 1px solid #ccc;
    padding: 0.5rem;
    margin-bottom: 1rem;
}

.p-qti-radio-fieldset legend {
    padding: 0 0.5rem;
    font-weight: bold;
}

/* Radio orientation: vertical (default) */
.p-qti-radio-widget-group.p-qti-radio-vertical {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

/* Radio orientation: horizontal with wrapping */
.p-qti-radio-widget-group.p-qti-radio-horizontal {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: center;
}

/* Button-style radio (hide input circles) */
.p-qti-radio-widget-group.p-qti-radio-hide-input input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.p-qti-radio-widget-group.p-qti-radio-hide-input .p-qti-radio-option {
    margin: 0;
}

.p-qti-radio-widget-group.p-qti-radio-hide-input label {
    display: inline-block;
    padding: 0.5rem 1rem;
    border: 2px solid #ccc;
    border-radius: 0.375rem;
    background-color: #f9fafb;
    cursor: pointer;
    transition: all 0.2s ease;
    user-select: none;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.p-qti-radio-widget-group.p-qti-radio-hide-input label:hover {
    background-color: #f3f4f6;
    border-color: #9ca3af;
}

/* Selected (depressed) state for button-style radio */
.p-qti-radio-widget-group.p-qti-radio-hide-input input[type="radio"]:checked + label {
    background-color: #2563eb;
    border-color: #1d4ed8;
    color: white;
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
    transform: translateY(1px);
}

/* Focus state for button-style radio */
.p-qti-radio-widget-group.p-qti-radio-hide-input input[type="radio"]:focus + label {
    outline: 3px solid #0078D4;
    outline-offset: 2px;
}

/* Button-style checkbox (hide input squares) */
.p-qti-checkbox-wrapper.p-qti-checkbox-hide-input input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.p-qti-checkbox-wrapper.p-qti-checkbox-hide-input label {
    display: inline-block;
    padding: 0.5rem 1rem;
    border: 2px solid #ccc;
    border-radius: 0.375rem;
    background-color: #f9fafb;
    cursor: pointer;
    transition: all 0.2s ease;
    user-select: none;
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.p-qti-checkbox-wrapper.p-qti-checkbox-hide-input label:hover {
    background-color: #f3f4f6;
    border-color: #9ca3af;
}

/* Checked state - shows as pressed/selected button */
.p-qti-checkbox-wrapper.p-qti-checkbox-hide-input input[type="checkbox"]:checked + label {
    background-color: #2563eb;
    border-color: #1d4ed8;
    color: white;
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
    transform: translateY(1px);
}

/* Focus state for accessibility */
.p-qti-checkbox-wrapper.p-qti-checkbox-hide-input input[type="checkbox"]:focus + label {
    outline: 3px solid #0078D4;
    outline-offset: 2px;
}

/* Checkbox images - consistent sizing */
.p-qti-checkbox-wrapper.p-qti-checkbox-hide-input label img {
    max-width: 100%;
    height: auto;
    object-fit: contain;
    display: block;
}

/* ========== Additional WCAG 2.1 AA Compliance Utilities ========== */

/* Screen reader only class (alias for .visually-hidden) */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border-width: 0;
}

/* ---- PCI live regions (QtiPciCompliancePlan S2b, PCIBase.announce) ----
   PCIBase puts its two aria-live regions INSIDE the interaction's own root
   (as <span>s, so they are valid inside inline interactions) instead of on
   document.body with the host's .sr-only. Visually hidden, still read by
   screen readers; display:inline-block keeps width/height meaningful on an
   inline element, and !important keeps a PCI's own descendant rules from
   un-hiding it. */
.p-qti-live-region {
    position: absolute !important;
    display: inline-block !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* General focus indicators for all interactive elements (WCAG 2.1 AA: 3:1 contrast) */
*:focus-visible {
    outline: 3px solid #005fcc;
    outline-offset: 2px;
    box-shadow: 0 0 0 6px rgba(0, 95, 204, 0.2);
}

/* The item card (role="article") is focused programmatically on load
   (ContentFactory targetDiv.focus()) so screen-reader/keyboard context lands
   on the new item. Its container, .p-qti-item-container, is overflow:auto, so
   the global OUTSET ring above is clipped to just the card's bottom edge —
   the stray partial blue line. Draw the ring INSET on the card instead so all
   four sides stay inside the clip box and render as a full ring. */
.p-qti-item-container > [role="article"]:focus-visible {
    outline: 3px solid #005fcc;
    outline-offset: -3px;
    box-shadow: none;
}

/* Touch targets for buttons within StandardInteractions only (WCAG 2.5.5: min 44x44px) */
[class*="p-qti-"] button,
[class*="p-qti-"] input[type="button"],
[class*="p-qti-"] input[type="submit"],
[class*="p-qti-"] input[type="reset"] {
    min-height: 44px;
    min-width: 44px;
/*    padding: 8px 16px;
*/}

[class*="p-qti-"] input[type="checkbox"],
[class*="p-qti-"] input[type="radio"] {
    width: 24px;
    height: 24px;
    margin: 10px; /* Creates 44x44 target with label */
}

/* Invalid state styling for form fields */
input[aria-invalid="true"],
textarea[aria-invalid="true"],
select[aria-invalid="true"] {
    border-color: #d32f2f;
    background-color: #ffebee;
}

/* Bug #88 (cert set 2026-10-03): the visible answer-rule message - a pattern the text does
   not match, a maximum reached, a minimum not met - beside its interaction
   (Utilities.showRuleMessage, PCIBase.setValidationState). It reached only a screen reader
   before. The text takes the active colour theme's foreground on its background, so it has
   the theme's contrast (AAA in every Ments theme); the left bar marks it, and a pattern error
   adds the theme's red to the bar - never colour alone, the words say what is wrong. */
.p-qti-rule-message {
    display: block;
    margin: 0.375rem 0;
    padding: 0.25rem 0.5rem;
    border-left: 4px solid var(--foreground, #1a1a1a);
    color: var(--foreground, #1a1a1a);
    background-color: var(--background, #ffffff);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.4;
    white-space: normal;
}

.p-qti-rule-message-error {
    border-left-color: var(--red, #c62828);
}

/* High contrast mode support */
@media (prefers-contrast: high) {
    *:focus-visible {
        outline-width: 4px;
        outline-offset: 3px;
    }
}

/* Reduced motion support */
/* S7b: re-enabled (WCAG 2.3.3 / 2.2.2). It was commented out with the
   simulation work (f3ad1bab) because the universal selector also collapsed
   the simulation ANIMATION SVG, whose motion is the item's content and
   whose timing the harness drives. The simulation SVG is exempt; every
   other animation and transition honours the preference. */
@media (prefers-reduced-motion: reduce) {
    *:not(.p-qti-animation-svg):not(.p-qti-animation-svg *),
    *:not(.p-qti-animation-svg *)::before,
    *:not(.p-qti-animation-svg *)::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
/* ========== Interaction-Specific WCAG Styles ========== */

/* TextEntry wrapper and label styling */
.p-qti-text-entry-wrapper {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.p-qti-text-entry-wrapper label {
    font-weight: 500;
}

.p-qti-text-entry-wrapper input {
    font-size: 1rem;
    padding: 0.5rem 0.5rem 0 0.5rem;
    margin-bottom: 0;
    /* TextEntry sizes the box from expected-length (1em a character), so a
       long expectation (the LLM text interaction's 200) asked for 200em =
       3200px: it overflowed its container, and a host sizing its frame from
       the content (amp-up.io) made the frame 3200px wide and clipped it.
       Never wider than the viewport. The viewport, not 100%: the entry's host
       is inline-block (p-inline-entry), a shrink-to-fit box whose width is
       decided BY the input, so a percentage cap left the host 2666px wide
       (measured, Chromium). An entry shorter than the viewport is untouched. */
    max-width: 100vw;
}

/* InlineChoice wrapper and label styling */
.p-qti-inline-choice-wrapper {
    display: inline-block;
    vertical-align: baseline;
}

.p-qti-inline-choice-wrapper .p-qti-custom-select {
    margin-bottom: 0;
    width: auto;
}

/* An inline choice sits IN a sentence: its closed button and its open option
   list read at the passage's own size and line height (they were held at the
   control size, 1rem, so the drop-down read smaller than the text around it -
   cert set 2026-10-01 item 32; gap match's words had the same fault, item 22).
   The button needs font-family too: a <button> does not inherit it. Scoped to
   the inline choice: the same widget elsewhere keeps its control font. */
.p-qti-inline-choice-wrapper .p-qti-custom-select,
.p-qti-inline-choice-wrapper .p-qti-custom-select-button,
.p-qti-inline-choice-wrapper .p-qti-custom-select-dropdown,
.p-qti-inline-choice-wrapper .p-qti-custom-select-option {
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
}

.p-qti-inline-choice-wrapper .p-qti-custom-select-value img,
.p-qti-inline-choice-wrapper .p-qti-custom-select-option img {
    max-height: none;
    max-width: 100%;
    height: auto;
}

/* ExtendedText wrapper and character counter */
.p-qti-extended-text-wrapper {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    /* No bottom margin: the host's 1em padding
       (.p-qti-extended-text-interaction) is the spacing below. While the
       host used a margin, this 1rem collapsed out through it and merged
       with it; against padding it would ADD, doubling the gap. */
    margin-bottom: 0;
}

.p-qti-extended-text-wrapper label {
    font-weight: 500;
}

.p-qti-extended-text-editor {
    font-size: 1rem;
    padding: 0.5rem;
    font-family: inherit;
    border: 1px solid #999;
    border-radius: 3px;
    background: var(--background);
    outline: none;
    overflow-y: auto;
}

.p-qti-extended-text-editor:focus {
    outline: 2px solid #005fcc;
    outline-offset: 1px;
}

.p-qti-extended-text-editor[data-placeholder]:empty::before {
    content: attr(data-placeholder);
    color: #888;
    pointer-events: none;
}

/* The rich (Squire) editor is never :empty - it always holds an empty
   <div><br></div> - so ExtendedText.js marks it p-qti-extended-text-empty
   while it holds no text, and the placeholder is laid over its first line
   (inside the box's 0.5rem padding). */
.p-qti-extended-text-editor[data-placeholder] {
    position: relative;
}
.p-qti-extended-text-editor.p-qti-extended-text-empty[data-placeholder]::before {
    content: attr(data-placeholder);
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    right: 0.5rem;
    color: #6c6c6c;
    pointer-events: none;
}

/* format="plain" / "preformatted" render as a native textarea. */
.p-qti-extended-text-editor.p-qti-extended-text-plain {
    width: 100%;
    resize: vertical;
}

.p-qti-extended-text-editor.p-qti-extended-text-preformatted {
    font-family: monospace;
    white-space: pre-wrap;
}

.p-qti-squire-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    padding: 0.25rem;
    border: 1px solid #ccc;
    border-radius: 3px;
    background: var(--well-bg);
}

.p-qti-squire-toolbar-button {
    min-width: 2rem;
    min-height: 2rem;
    padding: 0.25rem 0.5rem;
    border: 1px solid transparent;
    background: transparent;
    cursor: pointer;
    font-size: 1rem;
    /* Buttons do NOT inherit text color — without this the B/I/U glyphs
       stay UA-default black on the themed toolbar (illegible under
       default-reverse and every other dark theme). */
    color: var(--foreground);
}

.p-qti-squire-toolbar-button:hover,
.p-qti-squire-toolbar-button:focus {
    border-color: #999;
    background: var(--background);
    outline: none;
}

/* Pressed state through the theme tokens (was hardcoded #cde, which under
   a dark theme became a light chip with theme-white glyphs — invisible).
   Default theme keeps a light-gray chip with dark glyphs, dark themes get
   the inverse; the foreground border marks the toggle in every theme. */
.p-qti-squire-toolbar-button[aria-pressed="true"] {
    background: var(--secondary);
    color: var(--secondary-complement);
    border-color: var(--foreground);
}

.p-qti-character-counter {
    font-size: 0.875rem;
    color: var(--foreground);
    text-align: right;
}

/* Choice fieldset styling */
.p-qti-choice-fieldset {
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 1rem;
    margin-bottom: 1rem;
}

.p-qti-choice-fieldset legend {
    padding: 0 0.5rem;
    font-weight: 600;
    font-size: 1.1rem;
}

/* CHILD combinators on purpose: these rules style the CHOICES list (the
   fieldset's direct <ol> and its <li>s), never lists the author put
   INSIDE an option's content. As descendant selectors they flattened
   authored bullets/numbers — list-style:none killed <ol> numbering and
   display:flex on the <li> suppresses the marker box, so authored
   bullets vanished in delivery and the authoring/scoring previews. */
.p-qti-choice-fieldset > ol {
    list-style: none;
    padding: 0;
    margin: 0.5rem 0 0 0;
}

.p-qti-choice-fieldset > ol > li {
    padding: 0.5rem 0;
    /* Flex row so the generated choice label (li::before — "A)", "1.", …) sits
       inline before the flex <label>; without this the block-level label wraps
       and the number lands on its own line above the choice. */
    display: flex;
    align-items: baseline;
    gap: 0.25rem;
}

/* The control keeps its size and sits on the choice's FIRST line (cert #69).
   With align-items:center and the default flex-shrink:1 a choice whose text
   wrapped squeezed its radio/checkbox (24px → ~16px) and centred it between
   the lines. Now: the label packs to the top, the control never shrinks and
   its top margin centres it on one line box of the choice text (1lh, read
   against the inherited font + line-height), and the text span is the
   label's baseline item, so the li's "A)" marker lines up with the text's
   first line whatever the option content starts with. */
.p-qti-choice-fieldset > ol > li > label {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    cursor: pointer;
}

.p-qti-choice-fieldset > ol > li > label > span {
    align-self: baseline;
}

.p-qti-choice-fieldset > ol > li > label > input[type="radio"],
.p-qti-choice-fieldset > ol > li > label > input[type="checkbox"] {
    flex: 0 0 auto;
    font-size: inherit;
    line-height: inherit;
    margin-top: max(0px, calc((1lh - 24px) / 2));
    margin-bottom: 0;
}

.p-qti-choice-fieldset input[type="radio"],
.p-qti-choice-fieldset input[type="checkbox"] {
    cursor: pointer;
}

/* qti-input-control-hidden (QTI 3 shared vocabulary §1.2.1.7): no radio button or checkbox is
   drawn, and the CHOICE shows the selection. The input is only visually hidden - it stays in the
   accessibility tree, takes focus and is operated by the keyboard as before ("the controls MUST be
   available programmatically"). Each choice is a bordered box; the chosen one (Choice.js marks its
   <li> p-qti-choice-selected) has a 3px border and a fill, so the selection is not shown by colour
   alone, and the dark text keeps far more than 7:1 on the fill. Focus is a 4px double outline in
   the text colour (WCAG 2.4.13, as hot text draws it), a different shape from the selection. */
.p-qti-choice-fieldset > ol.qti-input-control-hidden > li > label {
    position: relative;
    flex: 1 1 auto;
    padding: 0.5rem 0.75rem;
    border: 1px solid currentColor;
    border-radius: 4px;
}

.p-qti-choice-fieldset > ol.qti-input-control-hidden > li > label > input[type="radio"],
.p-qti-choice-fieldset > ol.qti-input-control-hidden > li > label > input[type="checkbox"] {
    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;
}

.p-qti-choice-fieldset > ol.qti-input-control-hidden > li.p-qti-choice-selected > label {
    border-width: 3px;
    padding: calc(0.5rem - 2px) calc(0.75rem - 2px);
    background-color: #cce5ff;
    color: #1a1a1a;
}

.p-qti-choice-fieldset > ol.qti-input-control-hidden > li:focus-within > label {
    outline: 4px double var(--foreground, #1a1a1a);
    outline-offset: 3px;
}

@media (forced-colors: active) {
    .p-qti-choice-fieldset > ol.qti-input-control-hidden > li.p-qti-choice-selected > label {
        border-color: Highlight;
        outline: 2px solid Highlight;
    }
}

/* Slider wrapper styling */
.p-qti-slider-wrapper {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.p-qti-slider-wrapper label {
    font-weight: 500;
}

.p-qti-slider-output {
    font-weight: 600;
    font-size: 1.1rem;
    color: #005fcc;
    padding: 0.25rem 0.5rem;
    background-color: #e3f2fd;
    border-radius: 4px;
    display: inline-block;
    min-width: 3em;
    text-align: center;
}

/* Gap match passage (GapMatch.js .p-qti-gap-content; plan §37.5 B2.2). QTI 3 admits a gap only
   in a phrasing container, so the editor stores each line that holds a gap as a <p> - inside a
   bullet as <li><p>...</p></li> (GapMatchAuthoring.wrapGapLines). The editor shows those lines with
   no paragraph margins, and so did the older stored form (li / div lines); without this rule every
   such line gained the browser's 1em margins and a bulleted passage spread out. */
.p-qti-gap-content li > p,
.p-qti-gap-content p:has(.p-qti-gap) {
    margin-top: 0;
    margin-bottom: 0;
}

/* Match interaction wrapper and grid */
.p-qti-match-wrapper {
    margin-bottom: 1rem;
}

.p-qti-match-wrapper table {
    border-collapse: collapse;
    width: 100%;
    margin-top: 1rem;
}

/* The match grid's <caption> is the table's accessible name, not a visible
   heading — Match.js gives it .sr-only (BR-77). Styling it visibly here would
   also beat .sr-only on specificity, so there is deliberately no rule for it. */

.p-qti-match-wrapper th,
.p-qti-match-wrapper td {
    border: 1px solid #ccc;
    padding: 0.75rem;
    text-align: center;
}

.p-qti-match-wrapper th {
    background-color: #f5f5f5;
    font-weight: 600;
}

.p-qti-match-wrapper td.p-qti-active {
    outline: 3px solid #005fcc;
    outline-offset: -3px;
    background-color: #e3f2fd;
}

.p-qti-match-wrapper td input[type="checkbox"] {
    margin: 0;
}

/* qti-header-hidden (QTI 3 vocab §1.2.8.1): the column-header row is not displayed but stays in
   the accessibility tree - the headers are what name each cell for a screen reader. Match.js marks
   the row; its cells leave the layout, so the row takes no space. */
.p-qti-match-wrapper tr.p-qti-match-header-hidden > th {
    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;
}

/* Hide table visually but keep accessible to screen readers */
.p-qti-hidden-visually {
    position: absolute;
    left: -10000px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* Checkbox wrapper for hide table option */
.p-qti-hide-table-wrapper {
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.p-qti-hide-table-checkbox {
    width: 20px;
    height: 20px;
    cursor: pointer;
}

.p-qti-hide-table-label {
    cursor: pointer;
    user-select: none;
}

/* Rendered HTML labels in widgets */
.p-qti-widget-wrapper label,
.p-qti-radio-fieldset legend,
.p-qti-checkbox-wrapper label {
    display: block;
}

/* Cell lines + in-cell lists (authoring's cell-line model) — the delivery
   match to the editor rules in Scripts/css/TestQuill.css. qti-cell-line is
   a custom element (needs display:block); list lines group under
   qti-cell-list (role="list" / role="listitem" carry the semantics; the
   markers and numbering are CSS). */
qti-cell-line,
qti-col-line {
    display: block;
}

qti-cell-list {
    display: block;
    padding-left: 1.6em;
    counter-reset: tq-cell-ol;
}

qti-cell-list > qti-cell-line,
qti-cell-list > qti-col-line {
    display: list-item;
}

qti-cell-list[data-list-kind="bullet"] > qti-cell-line,
qti-cell-list[data-list-kind="bullet"] > qti-col-line {
    list-style-type: disc;
}

qti-cell-list[data-list-kind="ordered"] > qti-cell-line,
qti-cell-list[data-list-kind="ordered"] > qti-col-line {
    list-style-type: none;
    counter-increment: tq-cell-ol;
}

qti-cell-list[data-list-kind="ordered"] > qti-cell-line::before,
qti-cell-list[data-list-kind="ordered"] > qti-col-line::before {
    content: counter(tq-cell-ol) ". ";
}

/* Author-applied footnote block style (styles dropdown -> div.qti-footnote).
   Small, muted text set off by a top rule — the delivery match to the editor
   rule in Scripts/css/TestQuill.css. */
.qti-footnote {
    font-size: 0.85em;
    color: #475467;
    border-top: 1px solid #d0d5dd;
    margin-top: 0.75em;
    padding-top: 0.4em;
}

/* BEGIN paldroe-body-layout shared rules
   ONE rule source for two consumers: the engine (this sheet — Ments delivery,
   preview and the Hub, which renders QTI 3 exports as they stand) and the
   export's generated css/paldroe-body-layout.css. MentsEndpoint embeds this
   file and BodyLayoutStylesheet.Css copies the text between this comment and
   the END comment verbatim (BodyLayoutSharedRules), so the two cannot drift.
   The classes are the QTI 3 export's renames of Ments' own (footnote,
   strike-through, justify, indent, size; SharedVocabularyWireFormat). Rules
   here must name NO colour (BPIG §3.6.1): the export ships them to foreign
   players. Edit the rules, keep the markers. */
/* The columns grid also carries the QTI 3 shared-vocabulary layout classes (qti-layout-row /
   qti-layout-colN) for a player without this sheet. Here the grid governs: the vocabulary's
   clearfix pseudo-elements would be grid items, and its column widths and floats are not wanted. */
.p-qti-columns.qti-layout-row::before,
.p-qti-columns.qti-layout-row::after {
    content: none;
    display: none;
}

.p-qti-columns.qti-layout-row > .p-qti-holder {
    float: none;
    width: auto;
    margin-left: 0;
}

/* An author's footnote (the editor's footnote block style). */
.p-qti-footnote {
    font-size: 0.85em;
    border-top: 1px solid;
    margin-top: 0.75em;
    padding-top: 0.4em;
}

/* Struck-through text (the QTI 3 HTML subset has no s element, the vocabulary no class). */
.p-qti-strikethrough {
    text-decoration: line-through;
}

/* Justified text (the vocabulary has qti-align-left / center / right only). */
.p-qti-align-justify {
    text-align: justify;
}

/* The editor's font sizes. */
.p-qti-size-small {
    font-size: 0.75em;
}

.p-qti-size-large {
    font-size: 1.5em;
}

.p-qti-size-huge {
    font-size: 2.5em;
}

/* The editor's indent levels (3em a level; a list item keeps room for its marker). */
.p-qti-indent-1 {
    padding-inline-start: 3em;
}

li.p-qti-indent-1 {
    padding-inline-start: 4.5em;
}

.p-qti-indent-2 {
    padding-inline-start: 6em;
}

li.p-qti-indent-2 {
    padding-inline-start: 7.5em;
}

.p-qti-indent-3 {
    padding-inline-start: 9em;
}

li.p-qti-indent-3 {
    padding-inline-start: 10.5em;
}

.p-qti-indent-4 {
    padding-inline-start: 12em;
}

li.p-qti-indent-4 {
    padding-inline-start: 13.5em;
}

.p-qti-indent-5 {
    padding-inline-start: 15em;
}

li.p-qti-indent-5 {
    padding-inline-start: 16.5em;
}

.p-qti-indent-6 {
    padding-inline-start: 18em;
}

li.p-qti-indent-6 {
    padding-inline-start: 19.5em;
}

.p-qti-indent-7 {
    padding-inline-start: 21em;
}

li.p-qti-indent-7 {
    padding-inline-start: 22.5em;
}

.p-qti-indent-8 {
    padding-inline-start: 24em;
}

li.p-qti-indent-8 {
    padding-inline-start: 25.5em;
}

/* Our content table and asset-service media under their QTI names (the editor's tq-content-table /
   tq-asset-media, which ItemTransformer renames for every render and export, plan §37.6 and the
   owner rule of 2026-10-03). These present an exported table and figure in a foreign player; the
   engine adds its colours after the END marker. No colour here: the borders take the text colour. */
table.p-qti-content-table {
    border-collapse: collapse;
    margin: 0.6em 0;
}

table.p-qti-content-table > tbody > tr > th,
table.p-qti-content-table > tbody > tr > td {
    border: 1px solid;
    padding: 6px 10px;
    vertical-align: top;
    text-align: left;
}

table.p-qti-content-table > tbody > tr > th {
    font-weight: 600;
}

/* An exported picture. Every body figure leaves the QTI 3 export with the shared-vocabulary class
   qti-display-inline-block (SharedVocabularyWireFormat.FigureClass), which the vocabulary itself
   defines; the figure holds the author's geometry as a hoisted p-qti-st- rule (an aspect-ratio, and
   a width when the author resized it). Without the token a foreign player drew the figure as a
   full-width block, and the ratio made it as tall as the column is wide - a 480 x 320 photo left
   ~230px of blank space under it (image-size-export, 2026-10-02). Only figure-SCOPED rules here;
   the token's own definition is the vocabulary's (QtiBaseStyles.css for the engine): the box never
   grows wider than its column, and the picture fills the box (a block, as in the engine: an
   inline image leaves a descender gap of ~4px under it). KEEP IN SYNC with the engine's
   `figure` / `figure > img` rules (AUTHORED PICTURES, below). */
figure.qti-display-inline-block {
    max-width: 100%;
}

figure.qti-display-inline-block > img {
    display: block;
    width: 100%;
}

/* A picture's figcaption (the author's caption, a rights credit, or both): it wraps to the
   picture's width instead of widening the figure, which would stretch the picture with it
   (inline-size containment: it adds nothing to the inline-block's shrink-to-fit width). KEEP IN SYNC
   with the engine's `figure > figcaption` rule (AUTHORED PICTURES, below). */
figure.qti-display-inline-block > figcaption {
    contain: inline-size;
    box-sizing: border-box;
    overflow-wrap: anywhere;
}

.p-qti-asset-media {
    margin: 0;
}

/* A choice's "suppress first newline" (the dialog's p-qti-no-linefeed): the option's first
   paragraph runs on from its label, in the exported choice markup. Ments' own runtime draws the
   choice from its own list (QtiInteractionStyles.css / the ol.p-qti-no-linefeed rule). */
.p-qti-no-linefeed > qti-simple-choice > p:first-child,
.p-qti-no-linefeed > qti-simple-choice > div:first-child {
    display: inline;
    margin: 0;
    padding: 0;
}
/* END paldroe-body-layout shared rules */

/* Author-inserted content tables (TQTable). Delivery styling mirrors the
   authoring look in Scripts/css/TestQuill.css so a bordered, header-emphasized
   table renders the same for students as it did for the author. The rendered
   item carries p-qti-content-table (ItemTransformer renames the editor's
   tq-content-table: no tq-* class leaves the authoring system, owner rule
   2026-10-03); these engine-only rules sit AFTER the shared block on purpose,
   so the author's colours win over the colour-free export rules above. */
table.p-qti-content-table {
    border-collapse: collapse;
    margin: 0.6em 0;
}

table.p-qti-content-table > tbody > tr > th,
table.p-qti-content-table > tbody > tr > td {
    border: 1px solid #98a2b3;
    padding: 6px 10px;
    vertical-align: top;
    text-align: left;
}

table.p-qti-content-table > tbody > tr > th {
    background: #eef2f6;
    font-weight: 600;
}

/* Click-to-view box — NATIVE <details>/<summary>, pure HTML + CSS by owner
   constraint (2026-07-22): NO delivery JavaScript. The browser provides the
   toggle; this CSS provides the button face and the modal LOOK when open.
   Closing = clicking the button again, or its ✕ (a summary pseudo-element,
   so it is part of the native toggle). The backdrop is a pseudo-element of
   the <details> itself — clicks on it do NOT hit the summary and therefore
   do NOT close the box (owner decision preserved). No Esc-close and no
   focus trap: both would require script. Native <details> announces
   expanded/collapsed to assistive tech on its own.
   Contrast: #101828 on #f0f4f8 > 14:1. */
details.p-qti-click-to-view {
    display: block;
    margin: 0.5em 0;
}

details.p-qti-click-to-view > summary.p-qti-ctv-label {
    display: inline-block;
    padding: 8px 16px;
    border: 1px solid #475467;
    border-radius: 6px;
    background: #f0f4f8;
    color: #101828;
    cursor: pointer;
    /* Reads as a button, not a disclosure widget — hide the marker. */
    list-style: none;
}

details.p-qti-click-to-view > summary.p-qti-ctv-label::-webkit-details-marker {
    display: none;
}

details.p-qti-click-to-view > summary.p-qti-ctv-label:hover,
details.p-qti-click-to-view > summary.p-qti-ctv-label:focus {
    background: #e4e9f0;
}

details.p-qti-click-to-view > summary.p-qti-ctv-label:focus-visible {
    outline: 2px solid #1565c0;
    outline-offset: 2px;
}

/* Authored label lines arrive as <div> blocks; render them inline in the
   button face (images ride inline too). */
details.p-qti-click-to-view > summary.p-qti-ctv-label div {
    display: inline;
}

details.p-qti-click-to-view > summary.p-qti-ctv-label img {
    max-height: 3em;
    vertical-align: middle;
}

/* OPEN: dimmed backdrop drawn by the details element itself. Clicks here
   target the details (not the summary) — they don't toggle. */
details.p-qti-click-to-view[open]::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 800;
    background: rgba(16, 24, 40, 0.5);
}

/* The content becomes a top-anchored, centered, modal-looking panel. Top-
   anchored (not vertically centered) so the panel's top edge is a KNOWN
   viewport position the ✕ below can align to without script. */
details.p-qti-click-to-view[open] > .p-qti-ctv-content {
    position: fixed;
    top: 8vh;
    left: 50%;
    transform: translateX(-50%);
    z-index: 810;
    width: min(900px, 92vw);
    max-height: 84vh;
    overflow: auto;
    background: #ffffff;
    color: #101828;
    border-radius: 8px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
    padding: 20px 48px 20px 24px;
}

/* The summary stays above the backdrop — clicking the original button
   again closes the box… */
details.p-qti-click-to-view[open] > summary.p-qti-ctv-label {
    position: relative;
    z-index: 820;
}

/* …and a ✕ pinned to the panel's top-right corner closes it too: it is a
   pseudo-element OF THE SUMMARY, so clicking it is the native toggle.
   Position derives from the panel geometry above (top 8vh; half-width
   min(450px, 46vw)). */
details.p-qti-click-to-view[open] > summary.p-qti-ctv-label::after {
    content: '✕';
    position: fixed;
    top: calc(8vh + 8px);
    left: calc(50% + min(450px, 46vw) - 40px);
    z-index: 820;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #d0d5dd;
    border-radius: 6px;
    background: #ffffff;
    color: #101828;
    font-size: 15px;
    line-height: 1;
}

/* Rendered HTML labels in tables */
.p-qti-output-table th {
    vertical-align: top;
}

    /* Image sizing in labels */
    .p-qti-widget-wrapper label img,
    .p-qti-radio-fieldset legend img,
    .p-qti-checkbox-wrapper label img,
    .p-qti-output-table th img {
        max-width: 100%;
        height: auto;
        vertical-align: middle;
    }

/* Radio button images - consistent sizing based on tallest image */
.p-qti-radio-widget-group.p-qti-radio-hide-input label img {
    width: var(--radio-image-size, auto);
    height: var(--radio-image-size, auto);
    max-width: var(--radio-image-size, 100%);
    max-height: var(--radio-image-size, 100%);
    object-fit: contain;
    display: block;
}

/* ========== HOTTEXT INTERACTION ========== */

.p-qti-hottext-container {
    display: block;
    width: 100%;
    box-sizing: border-box;
}

.p-qti-hottext-passage {
    line-height: 1.8;
    display: block;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

.p-qti-hottext-passage p,
.p-qti-hottext-passage div {
    max-width: 100%;
    overflow-wrap: break-word;
}

.p-qti-hottext-prompt {
    margin-bottom: 0.75rem;
    font-style: italic;
}

/* A bare <qti-hottext> region — passage markup BEFORE the reader activates the
 * highlighter (or any preview where the runtime has not yet added
 * .p-qti-hottext-region) — has no padding, so two regions that kept their
 * trailing punctuation render butted together ("thereof;or abridging"). The
 * activated region's horizontal padding is what visually separates them; apply
 * the same padding to the bare element so the inter-region gap is present at all
 * times, not only after the highlighter is clicked. */
qti-hottext {
    padding: 1px 0;
}

/* No SIDE padding on a region (cert set 2026-10-01 item 44): 2px either side
 * showed as a stray space before the punctuation that follows a marked phrase
 * ("through ."), and doubled the space before one. Regions that touch with no
 * text between them (the butted case above) are given the space explicitly by
 * Hottext.js. */
.p-qti-hottext-after-region {
    margin-left: 0.25em;
}

.p-qti-hottext-region {
    cursor: default;
    border-bottom: 1px dashed transparent;
    border-radius: 2px;
    padding: 1px 0;
    transition: border-color 0.15s, background-color 0.15s;
    overflow-wrap: break-word;
}

/* Two forms: self-contained mode puts p-qti-hottext-active on the
 * passage ANCESTOR (descendant selector); passage-associated mode puts
 * both classes on the SAME <qti-hottext> region (compound selector). */
.p-qti-hottext-active .p-qti-hottext-region,
.p-qti-hottext-region.p-qti-hottext-active {
    cursor: pointer;
}

/* Selectable regions stay visually plain until hovered or keyboard-
 * focused (discover-by-interaction). Hover reveals only a dashed
 * underline. The base rule keeps a transparent dashed border so revealing
 * it doesn't shift the layout.
 *
 * FOCUS MUST NEVER LOOK SELECTED (owner 2026-09-29: a passage set opened
 * with its first sentence focused, and focus - a blue outline over a pale
 * blue tint - read as a chosen answer, because SELECTED is a blue tint too).
 * Focus is therefore a different SHAPE with NO fill: a 4px double outline
 * in the text colour. WCAG 2.4.13 Focus Appearance (AAA): a double line
 * of 4px draws about 2.7px of solid indicator all round (>= a 2px
 * perimeter), and the text colour against the page background is far
 * above the 3:1 change it requires, in the reversed themes as well.
 * Selected keeps its fill + solid underline, so focused-and-selected shows
 * both at once. :focus-visible (not :focus) so a mouse click does not
 * leave the ring lit. */
.p-qti-hottext-active .p-qti-hottext-region:hover,
.p-qti-hottext-region.p-qti-hottext-active:hover {
    border-bottom-color: var(--foreground, #1a1a1a);
}

.p-qti-hottext-region:focus-visible,
.p-qti-hottext-active .p-qti-hottext-region:focus-visible,
.p-qti-hottext-region.p-qti-hottext-active:focus-visible {
    outline: 4px double var(--foreground, #1a1a1a);
    outline-offset: 3px;
    box-shadow: none;
}

/* While the interaction is IN USE every selectable region is outlined
 * (owner design 2026-10-01): self-contained mode once focus is inside it or
 * it has been clicked (.p-qti-hottext-engaged on the container, Hottext.js),
 * passage mode while its highlighter is active. Never while the candidate is
 * first reading the passage. A 1px dashed outline in the text colour (well
 * above 3:1 against the page in every theme), offset so it does not touch
 * the text; it is a different shape from focus (4px double, below), which
 * wins on the focused region, and from selected (fill + solid underline),
 * which every selected region keeps throughout. */
.p-qti-hottext-engaged .p-qti-hottext-region,
.p-qti-hottext-region.p-qti-hottext-active {
    outline: 1px dashed var(--foreground, #1a1a1a);
    outline-offset: 1px;
}

.p-qti-hottext-engaged .p-qti-hottext-region:focus-visible,
.p-qti-hottext-region.p-qti-hottext-active:focus-visible {
    outline: 4px double var(--foreground, #1a1a1a);
    outline-offset: 3px;
}

/* qti-unselected-hidden (QTI 3 vocab §1.2.6.3): no visual indication of the regions that may be
 * chosen - no outline while the interaction is in use, no hover underline. Hottext.js marks each
 * region of such an interaction p-qti-hottext-unselected-hidden. A SELECTED region keeps its fill
 * and underline (below) and the FOCUSED one its 4px double outline (above): both are excluded
 * here, so the keyboard user still sees where they are. */
.p-qti-hottext-region.p-qti-hottext-unselected-hidden:not(.p-qti-hottext-selected):not(:focus-visible) {
    outline: none;
    border-bottom-color: transparent;
}

/* The hot-text status line is a screen-reader-only live region (.sr-only); its visible
   counterpart is the shared .p-qti-rule-message (bug #96). The standing min-choices hint
   (.p-qti-hottext-hint) is gone: the minimum now follows the shared rule message too. */

.p-qti-hottext-region.p-qti-hottext-selected {
    background-color: #cce5ff;
    border-bottom: 2px solid #004085;
}

@media (forced-colors: active) {
    .p-qti-hottext-region.p-qti-hottext-selected {
        outline: 2px solid Highlight;
    }
}

/* Highlighter icon (passage-associated mode) */
.p-qti-hottext-activator {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 2px solid #0078D4;
    border-radius: 6px;
    background: #f0f8ff;
    cursor: pointer;
    font-size: 1.2rem;
    transition: background 0.15s, box-shadow 0.15s;
}

.p-qti-hottext-activator:hover {
    background: #d6eaff;
}

.p-qti-hottext-activator.p-qti-hottext-icon-active {
    background: #0078D4;
    color: white;
    box-shadow: 0 0 0 3px rgba(0, 120, 212, 0.3);
}

.p-qti-hottext-activator:focus-visible {
    outline: 3px solid #0078D4;
    outline-offset: 2px;
}

/* Selected regions echoed inside the item while the interaction is not
 * focused (its passage highlights are hidden). */
.p-qti-hottext-in-item {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 0.5rem;
}

.p-qti-hottext-chosen {
    background-color: #cce5ff;
    border-bottom: 2px solid #004085;
    border-radius: 2px;
    padding: 1px 4px;
    overflow-wrap: break-word;
}

/* ========== CUSTOM SELECT WIDGET (Rich-Text Support) ========== */

.p-qti-custom-select {
    position: relative;
    display: inline-block;
    width: 100%;
    max-width: 400px;
}

.p-qti-custom-select-button {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    min-height: 44px;
    padding: 0.5rem;
    font-size: 1rem;
    background: white;
    border: 1px solid #ccc;
    border-radius: 4px;
    cursor: pointer;
    text-align: left;
}

.p-qti-custom-select-button:hover {
    border-color: #999;
}

.p-qti-custom-select-button:focus {
    outline: 3px solid #0078D4;
    outline-offset: 2px;
}

.p-qti-custom-select-button[aria-expanded="true"] {
    border-color: #0078D4;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}

.p-qti-custom-select-value {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.p-qti-custom-select-value img {
    max-height: 1.5rem;
    vertical-align: middle;
}

.p-qti-custom-select-arrow {
    margin-left: 0.5rem;
    font-size: 0.75rem;
    color: #666;
    transition: transform 0.2s;
}

.p-qti-custom-select-button[aria-expanded="true"] .p-qti-custom-select-arrow {
    transform: rotate(180deg);
}

.p-qti-custom-select-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1000;
    /* Match the button's control font (the rest of the widget uses 1rem); without
       this the list inherits the larger 14pt body font, so options looked bigger
       than the selected value shown in the closed button. */
    font-size: 1rem;
    max-height: 300px;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
    background: white;
    border: 1px solid #0078D4;
    border-top: none;
    border-radius: 0 0 4px 4px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.p-qti-custom-select-option {
    min-height: 44px;
    padding: 0.75rem;
    cursor: pointer;
    display: flex;
    align-items: center;
}

.p-qti-custom-select-option:hover,
.p-qti-custom-select-option.p-qti-focused {
    background-color: #f0f0f0;
}

.p-qti-custom-select-option[aria-selected="true"] {
    background-color: #e3f2fd;
    font-weight: bold;
}

.p-qti-custom-select-option[aria-selected="true"]::before {
    content: '? ';
    margin-right: 0.5rem;
    color: #0078D4;
}

.p-qti-custom-select-option img {
    max-height: 2rem;
    vertical-align: middle;
    margin-right: 0.5rem;
}

/* Disabled state */
.p-qti-custom-select-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* BabySim Prompt Container (Player) */
.p-qti-prompt-container {
    margin-bottom: 1.5rem;
    padding: 1rem;
    font-size: 1rem;
    line-height: 1.5;
}

.p-qti-prompt-container img {
    max-width: 100%;
    height: auto;
}

.p-qti-prompt-container p {
    margin: 0 0 0.5rem 0;
}

.p-qti-prompt-container p:last-child {
    margin-bottom: 0;
}

/* ========== GO BUTTON STYLING ========== */

.p-qti-go-button {
    background-color: #22c55e;
    color: white;
    border: none;
    border-radius: 4px;
    padding: 0.5rem 1.5rem;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.p-qti-go-button:hover {
    background-color: #16a34a;
}

.p-qti-go-button:focus {
    outline: 3px solid #0078D4;
    outline-offset: 2px;
}

.p-qti-go-button:disabled {
    background-color: #9ca3af;
    cursor: not-allowed;
}

/* ========== HORIZONTAL WIDGET LAYOUT ========== */

/* Horizontal widget layout */
.p-qti-widget-container.p-qti-widgets-horizontal {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-start;
}

.p-qti-widget-container.p-qti-widgets-horizontal .p-qti-widget-wrapper {
    margin-bottom: 0;
    flex: 0 1 auto;
}

/* Go button on its own line in horizontal layout */
.p-qti-widget-container.p-qti-widgets-horizontal .p-qti-go-button {
    flex-basis: 100%;
    width: auto;
    align-self: flex-start;
}

/* ========== LINE READER ========== */

.p-qti-line-reader-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 50;
    display: flex;
    flex-direction: column;
}

.p-qti-line-reader-shade-top,
.p-qti-line-reader-shade-bottom {
    background-color: rgba(0, 0, 0, 0.4);
    pointer-events: none;
}

.p-qti-line-reader-band {
    height: 2em;
    cursor: grab;
    pointer-events: auto;
    border: 2px solid;
    background-color: transparent;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: 4px;
}

.p-qti-line-reader-band:focus {
    outline: 3px solid #0078D4;
    outline-offset: -2px;
}

.p-qti-line-reader-band .p-qti-close-button {
    pointer-events: auto;
}

.p-qti-line-reader-button {
    background-image: url('/images/align-left.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
}

/* ========== NOTEPAD ========== */

.p-qti-notepad-textarea {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    resize: none;
    border: none;
    padding: 8px;
    font-size: 14px;
    font-family: sans-serif;
    box-sizing: border-box;
}

.p-qti-notepad-textarea:focus {
    outline: 3px solid #0078D4;
    outline-offset: -3px;
}

.p-qti-notepad-status {
    position: absolute;
    bottom: 4px;
    right: 8px;
    font-size: 12px;
    color: #555;
    pointer-events: none;
}

/* ========== CALCULATOR ========== */

.p-qti-calc-container {
    display: flex;
    flex-direction: column;
    height: 100%;
    gap: 4px;
    padding: 4px;
}

.p-qti-calc-equations {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.p-qti-calc-eq-row {
    display: flex;
    align-items: center;
    gap: 4px;
    min-height: 36px;
}

.p-qti-calc-color-swatch {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex-shrink: 0;
}

.p-qti-calc-eq-editor {
    flex: 1;
    min-width: 0;
}

.p-qti-calc-result {
    font-family: monospace;
    font-size: 14px;
    color: #333;
    padding: 0 4px;
    white-space: nowrap;
}

.p-qti-calc-graph {
    flex: 1;
    min-height: 200px;
    border-top: 1px solid #ccc;
}

.p-qti-calc-graph-canvas {
    width: 100%;
    height: 100%;
    cursor: grab;
}

.p-qti-calc-controls {
    display: flex;
    gap: 4px;
    padding: 2px 0;
}

.p-qti-calc-key {
    font-size: 14px;
    padding: 6px 12px;
    border: 1px solid #ccc;
    border-radius: 4px;
    cursor: pointer;
    background-color: #f8f8f8;
}

.p-qti-calc-key:hover {
    background-color: #e0e0e0;
}

.p-qti-calc-key:focus {
    outline: 3px solid #0078D4;
    outline-offset: 1px;
}

.p-qti-calc-key-equals {
    background-color: #4285f4;
    color: white;
    border-color: #3367d6;
}

.p-qti-calc-key-equals:hover {
    background-color: #3367d6;
}

.p-qti-calc-range {
    display: flex;
    gap: 8px;
    align-items: center;
    padding: 2px 0;
    flex-wrap: wrap;
}

.p-qti-calc-range label {
    display: flex;
    align-items: center;
    gap: 2px;
    font-size: 12px;
    color: #333;
}

.p-qti-calc-range-input {
    width: 60px;
    padding: 2px 4px;
    font-size: 12px;
    border: 1px solid #ccc;
    border-radius: 3px;
}

.p-qti-calc-range-input:focus {
    outline: 3px solid #0078D4;
    outline-offset: 0;
}

/* ========== TOOL BUTTONS (RULER, PROTRACTOR, DICTIONARY, THESAURUS) ========== */

.p-qti-ruler-button {
    background-image: url('/images/minus.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
}

.p-qti-protractor-button {
    background-image: url('/images/activity.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
}

.p-qti-dictionary-button {
    background-image: url('/images/book-open.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
}

.p-qti-thesaurus-button {
    background-image: url('/images/book.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-color: white;
    height: 2em;
    width: 2em;
    margin: .1em .1em .1em .1em;
}

/* ========== TOOL CANVAS (RULER & PROTRACTOR) ========== */

.p-qti-tool-wrapper {
    position: fixed;
    z-index: 9000;
    cursor: grab;
}

.p-qti-tool-canvas {
    display: block;
    pointer-events: none;
}

.p-qti-tool-close {
    position: absolute;
    top: -8px;
    right: -8px;
    z-index: 2;
    pointer-events: auto;
}

.p-qti-rotate-handle {
    position: absolute;
    bottom: -22px;
    right: -22px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background-color: transparent;
    border: none;
    cursor: grab;
    z-index: 1;
    pointer-events: auto;
}

.p-qti-rotate-handle::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background-color: #4285f4;
    border: 2px solid white;
}

.p-qti-rotate-handle:hover::after {
    background-color: #3367d6;
}

.p-qti-rotate-handle:focus {
    outline: 3px solid #0078D4;
    outline-offset: 1px;
}

.p-qti-ruler-container,
.p-qti-protractor-container {
    transform-origin: center center;
    cursor: grab;
}

/* ========== DICTIONARY & THESAURUS ========== */

.p-qti-dictionary-container,
.p-qti-thesaurus-container {
    padding: 16px;
    font-size: 14px;
    color: #555;
}

/* ========== SCORING-AUTHOR ENTITY HIGHLIGHT ========== */

/* .tq-highlight is the standard scoring-author hover-highlight class
   (ItemShield -> highlightEntity). Framed interactions add it to elements
   INSIDE the frame document, where the authoring page's TestQuill.css
   cannot reach — so the engine sheet must carry the rule. Inert during
   delivery: nothing adds the class outside the scoring-author surface.
   KEEP IN SYNC with the .tq-highlight declarations in Scripts/css/
   TestQuill.css (and the DefineItemScoringView inline scoring sheet). */
.tq-highlight {
    background-color: var(--color-primary-tint, #F3EEFF);
    cursor: pointer;
}

button.tq-highlight,
input.tq-highlight,
textarea.tq-highlight,
.p-qti-custom-select-button.tq-highlight {
    background-color: var(--color-primary-tint, #F3EEFF);
}

/* ========== AUTHORED PICTURES (bug report BR-46) ========== */

/* An authored image is a <figure> carrying the geometry the author gave it:
   an inline aspect-ratio, and a width too when they dragged the corner
   handle (Scripts/TestQuill/TQMarkup — the resizable image / asset-slot
   blots). Two rules made that work while authoring, BOTH on the page:
   TestQuill.css's `figure { display: inline-block }` and the embed
   wrappers' `span.tq-image-embed figure.tq-image > img { width: 100% }`.
   Items now render inside per-item SHADOW ROOTS, which page CSS cannot
   reach, and the engine sheets carried no figure rule at all — so a
   rendered figure fell back to a full-width BLOCK and its aspect-ratio
   then computed a height from the pane's width instead of the picture's.
   Measured in a 900px pane: a 283x178 picture in an 820px-wide figure
   516px tall — 338px of dead space under the image, and the interaction
   pushed down with it (BR-46: "extra blank lines ... a wide gap", right
   after the image). A figure the author had resized was the same fault
   the other way: the box grew, the picture stayed at its natural size.
   The geometry therefore belongs HERE, with the engine, where every
   surface gets it — authoring, review and delivery alike.
   KEEP IN SYNC with the editor's own rules in Scripts/css/TestQuill.css
   (`figure`, `span.tq-image-embed figure.tq-image`, and
   `span.tq-asset-slot figure.tq-asset-media`), which are what the author
   sees while writing. */
figure {
    display: inline-block;
    margin: 0.5em;
    padding: 0;
    text-align: center;
}

/* Asset-service media sits flush, as it does in the editor's asset slot. */
figure.p-qti-asset-media {
    margin: 0;
}

/* The picture fills the box the author sized — without this a resized
   figure keeps a natural-size image in a larger frame. */
figure > img,
figure > video {
    display: block;
    width: 100%;
    height: auto;
    object-fit: contain;
}

/* The picture's caption (the author's, a rights credit, or both — one figcaption, the
   figure's last child): under the picture, wrapped to its width so a long caption never
   widens the figure and stretches the picture. KEEP IN SYNC with the editor's
   span.tq-image-embed .tq-caption-view (Scripts/css/TestQuill.css). */
figure > figcaption {
    contain: inline-size;
    box-sizing: border-box;
    padding: 0.25em 0.5em 0;
    font-size: 0.9em;
    line-height: 1.4;
    overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------------------
   Record interaction — a spoken constructed response (BR-64).
   Deliberately plain: the controls are the affordance, and a speaking test is
   not the place for decoration that competes with the timer.
   --------------------------------------------------------------------------- */
.p-qti-record-interaction {
    display: flex;
    flex-direction: column;
    gap: 0.6em;
    max-width: 32em;
    padding: 0.8em;
    border: 1px solid #ccd3dd;
    border-radius: 4px;
}

.p-qti-record-status {
    font-weight: 600;
}

/* The live meter. It matters MORE than the check afterwards: a bar that moves
   while the examinee speaks prevents a blank take; the verdict only catches
   what prevention missed. aria-hidden because the status line does the talking
   -- a live region that updated 20 times a second would be unusable. */
.p-qti-record-meter {
    height: 0.75em;
    background: #eef1f5;
    border-radius: 0.4em;
    overflow: hidden;
}

.p-qti-record-meter-fill {
    height: 100%;
    width: 0;
    background: #3a7d44;
    /* Short, so the bar tracks the voice rather than lagging behind it. */
    transition: width 60ms linear;
}

.p-qti-record-timer {
    font-variant-numeric: tabular-nums;   /* the countdown must not jitter as digits change */
}

.p-qti-record-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5em;
}

.p-qti-record-button[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
}

.p-qti-record-player {
    width: 100%;
}

.p-qti-record-attempts:empty {
    display: none;
}

/* S7a accessibility — Rapid*, NumericKeypad, ObjectRepeater, TableInput,
   RecordInteraction (QtiPciCompliancePlan.md S7a). Focus rings use the theme
   foreground, so they keep >= 3:1 against the theme background in every colour
   theme (2.4.7 / 1.4.11); authored shape colours are left alone. */

/* Rapid response controls: visible focus (2.4.7) and at least 24x24 px (2.5.8). */
.tq-response-button {
    min-width: 24px;
    min-height: 24px;
    cursor: pointer;
}
.tq-response-button:focus,
.p-qti-shield:focus {
    outline: 3px solid var(--foreground);
    outline-offset: 3px;
}
/* The end-of-task message takes focus; its ring must sit inside the overlay. */
.p-qti-shield:focus {
    outline-offset: -6px;
}

/* Keypad keys and the count-widget buttons: the goldenrod focus border was
   about 2:1 on white. A theme-foreground outline replaces it (the border
   width stays as it was so the layout does not shift). */
div.p-qti-object-repeater > div.p-qti-controls > button:focus,
div.p-qti-numeric-keypad button.p-qti-numeric-keypad-key:focus {
    border-color: lightgrey;
    border-width: 3px;
    outline: 3px solid var(--foreground);
    outline-offset: 2px;
}

/* The count widget's controls stay in the normal flow (no position:fixed
   pinning), so they reflow at 400% zoom (1.4.10) and never cover focus. */
div.p-qti-object-repeater > div.p-qti-controls {
    position: static;
    display: flex;
    flex-wrap: wrap;
    gap: 0.25em;
}

/* The digits typed so far (RapidCompare / RapidQuantity). */
.p-qti-typed-response:empty {
    min-height: 0;
}

/* TableInput: the numeric-cell message is shown, not only spoken (3.3.1). */
.tableItem .ti-cell-error {
    display: block;
    margin-top: 0.2em;
    padding-left: 0.4em;
    border-left: 4px solid var(--foreground);
    color: var(--foreground);
    font-weight: 600;
    font-size: 0.9em;
}
.tableItem .ti-cell-error[hidden] {
    display: none;
}
.tableItem input[aria-readonly="true"],
.tableItem textarea[aria-readonly="true"] {
    cursor: default;
}

/* read-only status (QtiPciCompliancePlan C5): a custom PCI rendered with a
   non-interacting configuration.status (review / closed / solution /
   suspended) carries .p-qti-readonly; its controls stay focusable
   (aria-disabled / aria-readonly) but must LOOK unavailable. */
.p-qti-readonly button[aria-disabled="true"],
.p-qti-readonly button:disabled,
.p-qti-readonly [draggable][aria-disabled="true"] {
    cursor: not-allowed;
    opacity: 0.55;
}
.p-qti-readonly [aria-readonly="true"],
.p-qti-readonly svg[role="application"] {
    cursor: default;
}
.p-qti-readonly .p-qti-rapid-review-summary {
    margin: 0;
    font-weight: 600;
}

/* RecordInteraction: theme colours instead of fixed greys and green, so the
   panel follows every colour theme (1.4.3 / 1.4.11). */
.p-qti-record-interaction {
    border-color: var(--foreground);
    color: var(--foreground);
    background-color: var(--background);
}
.p-qti-record-meter {
    background: var(--background);
    border: 1px solid var(--foreground);
}
.p-qti-record-meter-fill {
    background: var(--foreground);
}
.p-qti-record-warning {
    padding-left: 0.5em;
    border-left: 4px solid var(--foreground);
    font-weight: 600;
}
.p-qti-record-warning[hidden] {
    display: none;
}
.p-qti-record-button[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
}
.p-qti-record-status:focus {
    outline: 3px solid var(--foreground);
    outline-offset: 2px;
}
/* End S7a accessibility */

/* S7b accessibility — GraphicResponse / CartesianGraph, UniversalNumberLine,
   SimulationResponse, PassageSet (QtiPciCompliancePlan §6 / S7). */

/* Graphic palette buttons: a visible keyboard focus ring (2.4.7). */
.p-qti-tool-palette button:focus-visible {
    outline: 3px solid #005fcc;
    outline-offset: 2px;
}

/* The drawing canvas itself (it takes arrow/Space/Delete keys). */
.p-qti-graphic-interaction > svg:focus-visible {
    outline: 3px solid #005fcc;
    outline-offset: 2px;
}

/* Drawn shapes: focus = solid blue ring; selection = dashed dark ring
   (plus the existing end markers); focused AND selected = dashed blue.
   Both indicators are >= 3:1 against white (1.4.11 / 2.4.7). */
.p-qti-graphic-interaction svg .p-qti-added:focus-visible {
    outline: 3px solid #005fcc;
    outline-offset: 3px;
}
.p-qti-graphic-interaction svg .p-qti-added.p-qti-selected {
    outline: 2px dashed #1a1a1a;
    outline-offset: 4px;
}
.p-qti-graphic-interaction svg .p-qti-added.p-qti-selected:focus-visible {
    outline: 3px dashed #005fcc;
    outline-offset: 4px;
}

/* Simulation Go button while a trial runs / the maximum is reached: it is
   aria-disabled (it keeps focus), so it must LOOK disabled too. */
.p-qti-go-button[aria-disabled="true"] {
    opacity: 0.55;
    cursor: not-allowed;
}

/* PassageSet reflow (1.4.10): below 800 CSS px — a narrow window, or 400%
   zoom of a 1280 px one — the two panes stack, and the fixed viewport
   height (which clipped content at high zoom) no longer applies. */
@media (max-width: 800px) {
    .qti-layout-row.p-qti-stim-split.p-qti-passage-set-split {
        flex-direction: column;
    }
    .qti-layout-row.p-qti-stim-split.p-qti-passage-set-split > .p-qti-stimulus,
    .qti-layout-row.p-qti-stim-split.p-qti-passage-set-split > .p-qti-item-container {
        height: auto;
        max-height: none;
        overflow: visible;
        flex: 0 0 auto;
    }
}

/* PassageSet in a foreign host: normal flow. The viewport-coupled panes
   (div.p-qti-stimulus / div.p-qti-item-container, height: calc(100vh - 40px))
   need a host that sizes the frame to the PAGE — Ments' frames do, and mark
   their document p-qti-fill-host (FrameRuntime.start). A third-party engine
   sizes its frame from the content it measures, so vh panes chase their own
   measurement down to nothing (amp-up.io: a 150px default frame reported
   ~110, then ~70, then 43 — an apparently blank passage set). Without the
   marker the panes size to their content and the host's measure is honest. */
html:not(.p-qti-fill-host) .qti-layout-row.p-qti-stim-split.p-qti-passage-set-split > .p-qti-stimulus,
html:not(.p-qti-fill-host) .qti-layout-row.p-qti-stim-split.p-qti-passage-set-split > .p-qti-item-container {
    height: auto;
    max-height: none;
    overflow: visible;
}

/* The passage scroller is focusable (keyboard scrolling) — show it. */
.p-qti-passage-set-split > .p-qti-stimulus:focus-visible {
    outline: 3px solid #005fcc;
    outline-offset: 2px;
}
/* End S7b accessibility */
