/* CodeClass - coding workspace (phase 5). */

/* CodeMirror surface shared by every editor in the product. */
.CodeMirror {
    height: 100%;
    font-family: var(--font-mono);
    font-size: var(--editor-font-size, 14px);
    line-height: 1.55;
    background: var(--bg-sunk);
    color: var(--ink);
}

.CodeMirror-gutters {
    background: transparent;
    border-right: 1px solid var(--line);
}

.CodeMirror-linenumber {
    color: var(--ink-4);
    font-size: 0.86em;
}

.CodeMirror-cursor {
    border-left: 2px solid var(--brand);
}

.CodeMirror-selected {
    background: color-mix(in srgb, var(--brand) 24%, transparent) !important;
}

.CodeMirror-focused .CodeMirror-selected {
    background: color-mix(in srgb, var(--brand) 30%, transparent) !important;
}

.CodeMirror-matchingbracket {
    color: var(--brand-ink) !important;
    border-bottom: 1px solid var(--brand);
}

.CodeMirror-placeholder {
    color: var(--ink-4);
}

.CodeMirror-hints {
    z-index: 200;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    background: var(--surface);
    border: 1px solid var(--line-2);
    border-radius: var(--r);
    box-shadow: var(--shadow-3);
    padding: 3px;
}

.CodeMirror-hint {
    color: var(--ink-2);
    border-radius: var(--r-sm);
    padding: 3px 8px;
}

li.CodeMirror-hint-active {
    background: var(--brand);
    color: var(--on-brand);
}

.code-view {
    margin: 0;
    padding: var(--s3) var(--s4);
    background: var(--bg-sunk);
    border: 1px solid var(--line);
    border-radius: var(--r);
    overflow: auto;
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    line-height: 1.5;
}

/* ==========================================================================
   Workspace: instructions | editor | output
   ========================================================================== */
.workspace-frame {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1;
}

.workspace {
    display: grid;
    flex: 1 1 auto;
    min-height: 0;
    background: var(--line);
}

.pane {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    background: var(--surface);
    overflow: hidden;
}

.pane-instructions {
    background: var(--surface);
}

.pane-body {
    padding: var(--s5);
    overflow-y: auto;
    flex: 1;
}

.prose-host {
    max-width: 68ch;
}

.pane-editor {
    background: var(--bg-sunk);
}

.pane-output {
    background: var(--surface);
}

/* ---- console ----------------------------------------------------------- */
.console {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.console-head {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s2) var(--s3);
    border-bottom: 1px solid var(--line);
    background: var(--surface-2);
    flex: 0 0 auto;
}

.console-status {
    font-size: var(--text-xs);
    color: var(--ink-3);
}

.console-status[data-tone='ok'] { color: var(--ok); }
.console-status[data-tone='warn'] { color: var(--warn); }
.console-status[data-tone='bad'] { color: var(--bad); }

.console-out {
    flex: 1 1 auto;
    margin: 0;
    padding: var(--s3);
    overflow: auto;
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    line-height: 1.5;
    color: var(--ink-2);
    background: var(--bg-sunk);
    white-space: pre-wrap;
    word-break: break-word;
    min-height: 60px;
}

.out-err { color: var(--bad); }
.out-system { color: var(--ink-4); font-style: italic; }
.out-echo { color: var(--brand-ink); }

/* Only on screen while a program is waiting for a line, so it is allowed to
   be loud. A caret alone reads as a program that has hung. */
/* Typing happens where the program is talking, at the end of what it has
   printed. A bar along the bottom puts the answer somewhere other than the
   question, and reading back what happened means jumping between the two. */
.console-inline {
    display: inline;
}

.console-input::placeholder {
    color: var(--ink-3);
    font-style: italic;
}

/* The name the answer is about to be stored in, when the program asked
   without printing a question. A hint, not something the program printed. */
.console-hint {
    color: var(--ink-3);
}

/* Barely there: a caret in the text, which is all a terminal gives you. The
   line under it says "type here" without drawing a box in the middle of the
   program's output. */
.console-input {
    display: inline-block;
    /* A starting size only: the width is set from what has been typed. */
    width: 24ch;
    max-width: 100%;
    padding: 0;
    border: 0;
    border-bottom: 1px solid color-mix(in srgb, var(--ink-3) 40%, transparent);
    border-radius: 0;
    background: transparent;
    color: var(--ink);
    font: inherit;
    line-height: inherit;
    outline: none;
    caret-color: var(--brand);
}

/* The app's focus ring is a rounded box-shadow, which around a field sitting
   inside a line of program output draws exactly the frame this was meant to
   get rid of. The caret and a stronger rule under the answer say where the
   focus is, so the ring is turned off here specifically. */
.console-input:focus,
.console-input:focus-visible {
    outline: none;
    box-shadow: none;
    border-bottom-color: var(--brand);
}

.console-input-pane {
    border-top: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    flex: 0 0 auto;
}

.console-input-pane .textarea {
    border: 0;
    border-radius: 0;
    background: var(--surface-2);
    resize: vertical;
    min-height: 60px;
}

/* ---- stage (graphics) --------------------------------------------------
   The drawing is the work on these challenges, so it takes the room and the
   printed text takes what is left. The surface inside is sized in JS
   (edit/console.js) to fit this box with its shape kept - a drawing that is
   cut off at the edge, which is what a fixed height gave, is the one thing a
   drawing must never be.
   ------------------------------------------------------------------------ */
.stage {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    place-items: center;
    padding: var(--s3);
    background: var(--surface-2);
    border-bottom: 1px solid var(--line);
    overflow: hidden;
}

/* Full screen. The stage is lifted over the page rather than only asking the
   browser, which refuses often enough - a policy, a kiosk, a missing gesture -
   that the drawing would sometimes simply not grow. Under the modals and the
   toasts, so a dialog opened from behind it is still reachable. */
.stage.stage-full {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer);
    padding: var(--s4);
    border-bottom: 0;
    background: #05070a;
}

.stage-exit {
    position: absolute;
    top: var(--s3);
    right: var(--s3);
    z-index: 1;
    opacity: 0.55;
    transition: opacity var(--dur) var(--ease);
}

.stage-exit:hover,
.stage-exit:focus-visible {
    opacity: 1;
}

/* Only on screen while it is the only way back. */
.stage:not(.stage-full) .stage-exit {
    display: none;
}

.turtle-host {
    background: #ffffff;
    border-radius: var(--r);
    box-shadow: var(--shadow-1);
    overflow: hidden;
}

.game-canvas {
    display: block;
    background: #0b0d10;
    border-radius: var(--r);
    box-shadow: var(--shadow-1);
}

.stage-tools {
    display: flex;
    align-items: center;
    gap: 2px;
}

/* These two are modes, not actions: they have to look switched on. */
.stage-tools .btn[aria-pressed='true'] {
    background: var(--brand-soft);
    color: var(--brand-soft-ink);
}

/* With a drawing on screen the output is a caption, not the main event: as
   tall as what was printed and no taller, so an empty one costs nothing. */
.console[data-stage]:not([data-stage='']) .console-out {
    flex: 0 1 auto;
    min-height: 0;
    max-height: 38%;
}

.game-canvas:focus-visible {
    outline: 2px solid var(--brand);
}

/* ---- tests ------------------------------------------------------------- */
.tests-wrap {
    border-top: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    max-height: 45%;
    flex: 0 0 auto;
    overflow: hidden;
}

.tests-panel {
    overflow-y: auto;
    padding: var(--s2);
    display: flex;
    flex-direction: column;
    gap: var(--s1);
}

.test-result {
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--surface);
}

.test-result > summary {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s2);
    cursor: pointer;
    font-size: var(--text-sm);
    list-style: none;
}

.test-result > summary::-webkit-details-marker { display: none; }

/* Put back what hiding the marker took away: something that says this opens. */
.test-caret {
    flex: 0 0 auto;
    opacity: 0.5;
    transition: transform var(--dur-fast) var(--ease);
}

.test-result[open] > summary .test-caret { transform: rotate(180deg); }
.test-result > summary:hover .test-caret { opacity: 1; }

.test-detail {
    padding: 0 var(--s3) var(--s3);
    display: flex;
    flex-direction: column;
    gap: var(--s2);
}

.test-detail pre {
    margin: 0;
    padding: var(--s2);
    background: var(--bg-sunk);
    border-radius: var(--r-sm);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    white-space: pre-wrap;
    max-height: 120px;
    overflow: auto;
}

/* Everything except the drawing folded away. The panes are still built and
   still hold their state; they are only not on screen. */
.workspace[data-layout='stage'] > .pane-editor,
.workspace[data-layout='stage'] > .pane-instructions,
.workspace[data-layout='stage'] > .resizer {
    display: none;
}

@media (max-width: 1000px) {
    .workspace {
        grid-template-columns: 1fr !important;
        grid-auto-rows: minmax(200px, auto);
    }
    .resizer-v { display: none; }
    /* Stacked, the panes read top to bottom, which put the drawing last -
       below the instructions and below the editor, off the bottom of the
       screen. On these challenges the drawing is the thing being made, so it
       goes first and takes most of the height; the code sits under it. */
    .workspace[data-stage='true'] > .pane-output {
        order: -1;
        min-height: 55vh;
    }
}

/* ==========================================================================
   Shared editor chrome (used by the student workspace and the content editor)
   ========================================================================== */
.editor-host {
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
    background: var(--bg-sunk);
}

.pane-head {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s2) var(--s3);
    border-bottom: 1px solid var(--line);
    background: var(--surface-2);
    min-height: 38px;
    flex: 0 0 auto;
}

.pane-title {
    font-size: var(--text-2xs);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.pane-scroll {
    overflow-y: auto;
    flex: 1;
}

.file-tabs {
    display: flex;
    align-items: stretch;
    gap: 2px;
    padding: var(--s1) var(--s2);
    background: var(--surface-2);
    border-bottom: 1px solid var(--line);
    overflow-x: auto;
    flex: 0 0 auto;
}

.file-tab {
    display: flex;
    align-items: center;
    gap: var(--s1);
    padding: 0 var(--s1) 0 var(--s2);
    border-radius: var(--r-sm);
    background: transparent;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    color: var(--ink-3);
    white-space: nowrap;
}

.file-tab[data-active='true'] {
    background: var(--bg-sunk);
    color: var(--ink);
}

.file-tab button {
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
    padding: var(--s2) 0;
    cursor: pointer;
}

.file-main {
    font-size: 9px;
    padding: 0 4px;
    border-radius: var(--r-sm);
    background: var(--brand-soft);
    color: var(--brand-soft-ink);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-family: var(--font-ui);
}

.file-x {
    border: 0;
    background: transparent;
    color: var(--ink-4);
    cursor: pointer;
    padding: 0 3px;
    border-radius: var(--r-sm);
}

.file-x:hover {
    background: var(--bad-soft);
    color: var(--bad);
}

.file-add {
    display: grid;
    place-items: center;
    width: 26px;
    border: 0;
    background: transparent;
    color: var(--ink-3);
    cursor: pointer;
    border-radius: var(--r-sm);
}

.file-add:hover {
    background: var(--surface-3);
    color: var(--ink);
}

/* ==========================================================================
   Editor theme
   ==========================================================================
   The editor follows the page: CodeMirror's built-in light theme in light
   mode, darcula in dark mode. Two darcula token colours were measured below
   WCAG AA against their own background (strings 3.52:1, keywords 4.25:1) and
   are corrected here.
   ========================================================================== */

.cm-s-darcula span.cm-string,
.cm-s-darcula span.cm-string-2 {
    color: #9dbc7f; /* was #6A8759 - now 6.4:1 on #2B2B2B */
}

.cm-s-darcula span.cm-keyword {
    color: #e8a15f; /* was #CC7832 - now 6.6:1 on #2B2B2B */
}

.cm-s-darcula span.cm-comment {
    color: #7fae6d; /* was #61A151 - a little lighter for small text */
}

/* The light theme is CodeMirror's default; only the chrome needs adjusting. */
.cm-s-default.CodeMirror {
    background: var(--surface);
    color: var(--ink);
}

.cm-s-default .CodeMirror-gutters {
    background: var(--surface-2);
    border-right: 1px solid var(--line);
}

.cm-s-default .CodeMirror-linenumber {
    color: var(--ink-4);
}

.cm-s-default span.cm-comment { color: #6b6250; }
.cm-s-default span.cm-string { color: #a3253d; }
.cm-s-default span.cm-keyword { color: #7a3e9d; font-weight: 600; }
.cm-s-default span.cm-number { color: #0f6f66; }
.cm-s-default span.cm-def { color: #1d4ed8; }
.cm-s-default span.cm-builtin { color: #0f6f66; }

/* ---- instruction keywords ---------------------------------------------
   Three weights, because there are three things going on. A keyword the
   teacher wrote is the strongest mark on the line. The three that fill
   themselves in are set apart, since editing what follows them does nothing.
   A `---` is structure with no words in it and stays quiet.
   ------------------------------------------------------------------------ */

/* `.CodeMirror pre span` rather than `.CodeMirror span`: an indented keyword
   is an indented code block to the markdown mode, and the theme's own comment
   colour ties on specificity and wins on load order. A keyword is a keyword at
   any indentation, so this has to outrank it. */
.CodeMirror pre span.cm-cc-keyword {
    color: var(--brand-ink);
    font-weight: 700;
    font-style: normal;
}

.CodeMirror pre span.cm-cc-generated {
    color: var(--warn);
    font-weight: 700;
    font-style: italic;
}

.CodeMirror pre span.cm-cc-break {
    color: var(--ink-4);
    font-weight: 700;
}

/* ---- editor toolbar ---------------------------------------------------- */
.editor-tools {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: var(--s1) var(--s2);
    background: var(--surface-2);
    border-bottom: 1px solid var(--line);
    flex: 0 0 auto;
    min-height: 34px;
}

.editor-tools .file-tabs {
    background: transparent;
    border-bottom: 0;
    padding: 0;
    flex: 0 1 auto;
}

.tool-group {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 0 var(--s1);
    border-radius: var(--r-sm);
}

.tool-value {
    min-width: 18px;
    text-align: center;
    font-size: var(--text-2xs);
    color: var(--ink-3);
    font-variant-numeric: tabular-nums;
}

/* ---- find and replace -------------------------------------------------- */
.find-host {
    flex: 0 0 auto;
}

.find-bar {
    display: flex;
    flex-direction: column;
    gap: var(--s1);
    padding: var(--s2);
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-1);
}

.find-row {
    display: flex;
    align-items: center;
    gap: var(--s1);
}

.find-input {
    flex: 1 1 auto;
    min-width: 80px;
    height: 28px;
    font-size: var(--text-xs);
}

.find-count {
    font-size: var(--text-2xs);
    color: var(--ink-3);
    white-space: nowrap;
    min-width: 62px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.find-count[data-tone='bad'] { color: var(--bad); }

.find-bar .btn.is-on {
    background: var(--brand-soft);
    color: var(--brand-soft-ink);
    border-color: color-mix(in srgb, var(--brand) 40%, transparent);
}

.cc-find-hit {
    background: color-mix(in srgb, var(--attn) 34%, transparent);
    border-radius: 2px;
}

.cc-find-current {
    background: color-mix(in srgb, var(--attn) 72%, transparent);
    border-radius: 2px;
    color: #1a1206;
}

/* ---- locked scaffold regions ------------------------------------------- */
.CodeMirror-line.cc-locked-line,
.cc-locked-line {
    background: color-mix(in srgb, var(--ink-3) 12%, transparent);
}

.cc-locked-gutter {
    border-left: 2px solid var(--line-strong);
}

.cc-locked {
    opacity: 0.92;
}

/* ---- completion menu --------------------------------------------------- */
.CodeMirror-hint.cc-hint-yours {
    color: var(--brand-ink);
    font-weight: 600;
}

.CodeMirror-hint.cc-hint-python {
    color: var(--ink-3);
}

li.CodeMirror-hint-active.cc-hint-yours,
li.CodeMirror-hint-active.cc-hint-python {
    background: var(--brand);
    color: var(--on-brand);
}

/* Escape released the Tab key: say so rather than leaving it a secret. */
.editor-host[data-tab-released='true']::after {
    content: 'Tab now moves to the next control';
    position: absolute;
    right: var(--s2);
    bottom: var(--s2);
    z-index: 6;
    padding: 2px var(--s2);
    border-radius: var(--r-sm);
    background: var(--ink);
    color: var(--bg);
    font-family: var(--font-ui);
    font-size: var(--text-2xs);
    pointer-events: none;
}
