/* lesson-learn.css - a Brainlag Code lesson laid out as brainlag.space's Learn player (owner, 12 Oct 2026: "Why
   different widths? Keep the same format as the other courses on brainlag for brainlag code please").
   Loaded on lesson pages only, after site.css and after Learn's own files (public/assets/learn/: house.css with the
   brainlag.css tokens scoped to body.ln-play, learn.css, learn-speech.css; copied by tools/learn_share.py, never edited).
   This file holds only what is Code's own: the editor as the lesson's figure, and the old site.css lesson rules that
   would otherwise fight Learn's. Learn's numbers: a 900 px stage (16 px gutters), from 1100 px a 1180 px stage with the
   figure in the left column (28 px apart), the 16 px progress bar, 44 px top-bar controls, 54 px action buttons.
   Code's modifier (coordinator, 12 Oct): the editor takes the wider column, and from 1400 px the stage is 1320 px (the
   width Learn gives a wide screen), so an 80-character line fits at 1440 without wrapping. */

body.ln-play { --f-body: var(--font); --f-mono: var(--mono); background: var(--paper); }
body.ln-play #main { display: block; }

/* ---- the top bar: Learn's, not the old Code lesson bar (site.css .lp-top / .lp-bar / .lp-loc) ---- */
body.ln-play .lp-top { position: sticky; top: 0; z-index: 100; height: auto; gap: 14px; padding: 12px max(16px, env(safe-area-inset-right)) 10px max(16px, env(safe-area-inset-left)); background: var(--paper); box-shadow: none; }
body.ln-play .lp-top .lp-bar { display: block; visibility: visible; flex: 1; min-width: 40px; height: 16px; border-radius: 8px; background: var(--sunk); }
:root[data-theme="dark"] body.ln-play .lp-top .lp-bar { background: var(--track); }
body.ln-play .lp-top .lp-bar > span { background: var(--study); }
body.ln-play .lp-top .lp-loc { flex: none; min-width: 0; color: var(--ink-3); font: 600 15px/1.2 var(--f-body); }
body.ln-play .lp-top .lp-x:hover, body.ln-play .lp-top .lp-snd:hover { color: var(--ink); background: var(--sunk); }
body.ln-play .lp-top .lp-meta .rail-combo { display: inline-flex; }
body.ln-play .ls-panel .ls-adapt:empty { display: none; }
body.ln-play .ls-panel .ls-adapt { padding: 6px 0; }
@media (max-width: 440px) { body.ln-play .lp-top { gap: 4px; padding-inline: max(8px, env(safe-area-inset-left)) max(8px, env(safe-area-inset-right)); } }

/* ---- the stage ---- */
body.ln-play .cbl-stage { width: 100%; box-sizing: border-box; max-width: 900px; margin: 0 auto; padding: 10px 16px calc(var(--lp-foot-h, 96px) + 24px); }
body.ln-play .env.cbl-lp { display: flex; flex-direction: column; gap: 20px; padding: 0; }
body.ln-play .env.cbl-lp .env-text { display: flex; flex-direction: column; min-height: 0; }
body.ln-play .env.cbl-lp .env-head, body.ln-play .env.cbl-lp .env-scroll { padding: 0; }
body.ln-play .env.cbl-lp .env-rail { display: none !important; }

/* type: Learn's question title, prose and labels */
body.ln-play .lh h1 { margin: 10px 0 0; font: 700 clamp(23px, 4.6vw, 30px)/1.15 var(--f-display); letter-spacing: 0; color: var(--ink); }
body.ln-play .lh-meta { margin: 6px 0 0; color: var(--ink-3); font: 600 15px/1.4 var(--f-body); }
body.ln-play .env-scroll { margin-top: 18px; }
body.ln-play .step > h2 { margin: 4px 0 10px; font: 700 clamp(21px, 3.4vw, 26px)/1.2 var(--f-display); letter-spacing: 0; }
body.ln-play .step .prose { font-size: 17.5px; line-height: 1.65; color: var(--ink); }
body.ln-play .step .prose p, body.ln-play .step .prose ul, body.ln-play .step .prose ol { max-width: 66ch; }
body.ln-play .step-lede, body.ln-play .ex-note { font-size: 16px; line-height: 1.55; color: var(--ink-2); }
body.ln-play .step-k { color: var(--ink-3); font: 700 14px/1.3 var(--f-body); }
body.ln-play .step-k .sk-stage { display: inline; height: auto; margin: 0; }   /* learn.css has its own .sk-stage (the streak screen) */
body.ln-play .soft-note { border-radius: var(--r1); background: var(--sunk); }

/* "Learn these by heart" (the music courses' marker, brainlag.space music-learn.css; "::: memorise" in a lesson) */
body.ln-play .bl-memorise { margin: 8px 0 18px; }
body.ln-play .bl-memorise-tag { display: inline-flex; align-items: center; gap: 8px; margin: 0 0 8px; padding: 6px 12px; border-radius: 10px; background: var(--study-tint); color: var(--study-ink); font: 700 15px/1.2 var(--f-display); }

/* the OCR / AQA / Python style switch is brainlag.space's segmented control (house.css .segc): exam.css's look off */
body.ln-play .xl-tabs.segc { display: inline-grid; margin: 0 0 8px; padding: 4px; gap: 4px; border-radius: 12px; background: var(--seg-track); }
body.ln-play .xl-tabs.segc > button { min-width: 72px; min-height: 40px; border-radius: 9px; font: 700 15px/1.15 var(--f-body); box-shadow: none; }
body.ln-play .xl-tabs.segc > button[aria-pressed="false"] { background: transparent; color: var(--ink-2); }
body.ln-play .xl-tabs.segc > button[aria-pressed="true"] { background: var(--study-btn); color: var(--on-study-btn); }
:root[data-theme="dark"] body.ln-play .xl-tabs.segc > button[aria-pressed="true"] { color: #04161c; }
body.ln-play .slab .xl-tabs.segc, body.ln-play .codeblock .xl-tabs.segc { --seg-track: rgba(157, 179, 201, .14); }
body.ln-play .slab .xl-tabs.segc > button[aria-pressed="false"], body.ln-play .codeblock .xl-tabs.segc > button[aria-pressed="false"] { color: #c8d7e8; }
@media (pointer: coarse) { body.ln-play .xl-tabs.segc > button { min-height: 44px; } }

/* ---- the guide: Learn's speaker and bubble (learn.css .lq-sayu; brainlag.css .bl-bubble, bl-bubble.js) ---- */
body.ln-play .coach-lesson { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 24px; align-items: center; margin: 22px 0 0; padding: 0; }
body.ln-play .coach-lesson .coach-art { width: 76px; }
body.ln-play .coach-lesson .coach-say { justify-self: start; width: fit-content; max-width: min(46ch, 100%); min-width: 7em; margin: 0; padding: 12px 16px; border: 0; border-radius: 18px; background: none; box-shadow: none; }
body.ln-play .coach-lesson .coach-say:not(.is-drawn) { background: var(--surface); border: 2px solid var(--say-edge); }
body.ln-play .coach-lesson .coach-tail { display: none; }
body.ln-play .coach-lesson .coach-line { color: var(--ink); font: 600 17px/1.4 var(--f-body); }
body.ln-play .coach-lesson .coach-more { color: var(--ink-2); }
body.ln-play .env.coach-quiet .coach-lesson .coach-say { visibility: hidden; }
@media (max-width: 699px) {
  body.ln-play .coach-lesson { grid-template-columns: 56px minmax(0, 1fr); gap: 22px; }
  body.ln-play .coach-lesson .coach-art { width: 56px; }
  body.ln-play .coach-lesson .coach-line { font-size: 16.5px; line-height: 1.45; }
}
body.ln-play .pass-coach .coach-lesson { margin: 0; }

/* ---- the figure: the editor, its toolbar and the output, Learn's radius ---- */
body.ln-play .env.cbl-lp .env-code { position: static; height: auto; min-height: 0; margin: 0; border-radius: 20px; overflow: clip; }
body.ln-play .env.cbl-lp .env-code > .runbox { flex: none; }
body.ln-play .env.cbl-lp .env-code .rb-head { border-radius: 20px 20px 0 0; }
/* the editor as tall as its code plus two empty lines, growing as it is typed into (owner, 19 Oct 2026: ten empty lines
   under five of code pushed the output down); the static copy shown before the editor loads is the same height, so
   nothing moves when it arrives */
body.ln-play .env.cbl-lp .env-code .editor .cm-editor { min-height: 0; }
body.ln-play .env.cbl-lp .env-code .editor .cm-content { padding-bottom: calc(16px + 3.5em) !important; }
body.ln-play .env.cbl-lp .env-code .editor pre.code-static { padding: 16px 18px calc(16px + 3.5em) 52px; border-radius: 0; font-size: 14.5px; line-height: 1.75; }
body.ln-play .env.cbl-lp .env-code .rb-results { max-height: none; }

/* Run, Reset and Open in playground stay in the editor's toolbar on every width (only Check moves to the bar on a phone) */
@media (max-width: 899.98px) {
  body.ln-play .env-code .runbox[data-kind="exercise"] .toolbar [data-act="run"]:not([hidden]) { display: inline-flex; }
  body.ln-play .env.cbl-lp .env-code { margin: 0 -4px; }
}

/* from 1000 px: the explanation first, in a reading column on the left, then the editor and its output on the right,
   held in view while the explanation scrolls (owner, 19 Oct 2026: people read left to right and met the code first) */
@media (min-width: 1000px) {
  body.ln-play .cbl-stage { max-width: 1180px; }
  body.ln-play .env.cbl-lp { display: grid; grid-template-columns: minmax(0, 46fr) minmax(0, 54fr); grid-template-rows: auto auto auto 1fr;
    grid-template-areas: "head head" "text fig" "coach fig" ". fig"; column-gap: 32px; row-gap: 0; align-items: start; }
  body.ln-play .env.cbl-lp .env-scroll, body.ln-play .env.cbl-lp .env-head { max-width: 65ch; }
  body.ln-play .env.cbl-lp .env-text { display: contents; }
  body.ln-play .env.cbl-lp .env-head { grid-area: head; margin-bottom: 18px; }
  body.ln-play .env.cbl-lp .env-scroll { grid-area: text; margin-top: 0; }
  body.ln-play .env.cbl-lp .coach-lesson { grid-area: coach; }
  /* as tall as the code and its output need, never more than the screen between the bar on top and the footer */
  body.ln-play .env.cbl-lp .env-code { grid-area: fig; position: sticky; top: 82px; display: flex; flex-direction: column; height: auto;
    max-height: calc(100dvh - 82px - var(--cbl-head-h, 0px) - var(--lp-foot-h, 96px) - 20px); }
  body.ln-play .env.cbl-lp .env-code > .runbox.is-shown { flex: 0 1 auto; min-height: 0; }
  body.ln-play .env.cbl-lp .env-code .editor .cm-editor { min-height: 0; max-height: 100%; }
  body.ln-play .env.cbl-lp .env-code .rb-results { max-height: 40%; }
  /* the editor's text size is the lesson's, not the column's (site.css container sizes): 80 columns fit at 1440 */
  body.ln-play .env.cbl-lp .env-code .cm-editor { font-size: 14.5px; }
  body.ln-play .env.cbl-lp .env-code .cm-lineNumbers .cm-gutterElement { min-width: 36px; }
  /* the result is one column again, at Learn's width */
  body.ln-play .env.cbl-lp.is-passed { display: block; max-width: 900px; margin: 0 auto; }
}
@media (min-width: 1400px) { body.ln-play .cbl-stage { max-width: 1320px; } }

/* ---- the action bar: Learn's .lp-foot and .lp-actions, as wide as the stage, so the main button ends at its edge ---- */
/* a solid bar on the page's own paper, never see-through: the explanation scrolls under it and stops 24 px clear of it
   at the bottom (the stage's padding above, coordinator 19 Oct 2026) */
body.ln-play .lp-foot { z-index: 95; transform: translateY(calc(-1 * var(--kb, 0px))); padding-bottom: 0; background: var(--paper); }
/* the bar's contents as wide as the lesson's own column, so Continue ends at the column's right edge and never in the
   screen's corner; 24 px of bar under it plus the safe area (owner, 19 Oct 2026: flush in the corner, the bar cut off) */
body.ln-play { --cbl-col: 900px; }
@media (min-width: 1000px) { body.ln-play { --cbl-col: 1180px; } }
@media (min-width: 1400px) { body.ln-play { --cbl-col: 1320px; } }
body.ln-play .lp-foot > .step-nav, body.ln-play .dock .step-nav, body.ln-play .lp-foot > .lp-actions { position: static; width: 100%; box-sizing: border-box; max-width: var(--cbl-col); margin: 0 auto; padding: 14px 16px calc(24px + env(safe-area-inset-bottom)); background: none; box-shadow: none; }
body.ln-play .lp-foot .lp-btn, body.ln-play .lp-foot .sn-next, body.ln-play .lp-foot .sn-prev { min-height: 52px; }
body.ln-play .lp-foot > .step-nav[hidden] { display: none; }
body.ln-play .lp-foot .lp-btn { height: auto; font: 700 17px/1.2 var(--f-body); }
body.ln-play .lp-foot .sn-next { min-width: 180px; margin-left: 0; }
@media (min-width: 700px) { body.ln-play .lp-foot > .step-nav { justify-content: flex-end; } }
body.ln-play .lp-foot .lp-btn:disabled { display: none; }
body.ln-play .lp-foot .lp-sheet:empty { display: none; }
body.ln-play .lp-foot .lp-sheet { max-width: none; margin: 0; padding: 0; }
body.ln-play .lp-foot .blk-sheet { position: relative; }
body.ln-play .lp-foot .blk-sheet-in { width: 100%; box-sizing: border-box; max-width: 868px; margin: 0 auto; padding: 16px 16px 12px; flex-wrap: wrap; gap: 12px 14px; }
body.ln-play .lp-foot .blk-sheet-h { font: 700 22px/1.2 var(--f-display); }
/* the verdict colours the whole bar, as Learn's result band does (learn.css .lp-foot:has(.lp-sheet.is-right)) */
body.ln-play .lp-foot:has(> .lp-sheet:not(:empty)) { display: block; min-height: 0; padding: 0; }
body.ln-play .lp-foot:has(.blk-sheet.is-ok:not([hidden])) { background: var(--ln-right-bg); }
body.ln-play .lp-foot:has(.blk-sheet.is-no:not([hidden])) { background: var(--ln-wrong-bg); }
body.ln-play .lp-foot .blk-sheet.is-ok, body.ln-play .lp-foot .blk-sheet.is-no { background: none; }
body.ln-play .lp-foot .blk-sheet.is-ok { color: var(--ln-right-ink, var(--ln-right)); }
body.ln-play .lp-foot .blk-sheet.is-no { color: var(--ln-wrong); }
body.ln-play .lp-foot .blk-sheet-in { padding: 20px 16px calc(20px + env(safe-area-inset-bottom)); }
body.ln-play .lp-foot .blk-sheet-d { color: var(--ink-2); }
body.ln-play .lp-foot .blk-sheet-go { min-height: 54px; min-width: 180px; border-radius: 16px; font: 700 17px/1.2 var(--f-body); }
html.blk-sheet-open body.ln-play .lp-foot > .step-nav { display: none; }
body.ln-play .lp-foot .sn-prev:not(:disabled) { display: inline-flex; }   /* Back stays on a phone too (Code's dock hid it) */
body.ln-play:has(.env.is-passed) .lp-foot { display: none; }
body.ln-play:has(.env-premium) .lp-foot > .step-nav { display: none; }
@media (max-width: 699px) { body.ln-play .lp-foot .blk-sheet-act { flex: 1 1 100%; } body.ln-play .lp-foot .blk-sheet-go { width: 100%; } body.ln-play .lp-foot .sn-next { min-width: 0; } }
@media (min-width: 1100px) {
  body.ln-play .lp-foot > .step-nav, body.ln-play .lp-foot .blk-sheet-in { max-width: 1180px; }
}
@media (min-width: 1400px) {
  body.ln-play .lp-foot > .step-nav, body.ln-play .lp-foot .blk-sheet-in { max-width: 1320px; }
}
/* on a phone the output sheet sits on the bar (dock.js); the old bottom padding for the Code dock is the bar's now */
@media (max-width: 899.98px) {
  body.ln-play .env.cbl-lp { padding-bottom: 0; }
  .page-lesson.ln-play .env-code > .runbox.is-shown.has-out .rb-results { bottom: calc(var(--lp-foot-h, 76px) + var(--kb, 0px)); }
}
@media (min-width: 700px) { body.ln-play .lp-foot .blk-sheet-in { flex-wrap: nowrap; } }
body.ln-play .bl-memorise-tag::before{content:"";width:16px;height:16px;flex:none;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a7 7 0 0 0-7 7c0 2.6 1.4 4.3 2.6 5.5.8.8 1.4 1.6 1.4 2.5v1h6v-1c0-.9.6-1.7 1.4-2.5C17.6 14.3 19 12.6 19 10a7 7 0 0 0-7-7zm-3 18h6v1H9z'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a7 7 0 0 0-7 7c0 2.6 1.4 4.3 2.6 5.5.8.8 1.4 1.6 1.4 2.5v1h6v-1c0-.9.6-1.7 1.4-2.5C17.6 14.3 19 12.6 19 10a7 7 0 0 0-7-7zm-3 18h6v1H9z'/%3E%3C/svg%3E") center/contain no-repeat}
body.ln-play .bl-memorise > :last-child { margin-bottom: 0; }
body.ln-play .codeblock .xl-tabs.segc > button[aria-pressed="false"]:hover, body.ln-play .slab .xl-tabs.segc > button[aria-pressed="false"]:hover { color: #fff; }
/* the meta line is never shortened (adapt.js): when it and the level meter do not fit on one line, the meter wraps under it */
body.ln-play .lh-meta.has-ad.ad-wrap { flex-wrap: wrap; white-space: normal; }
body.ln-play .lh-meta.has-ad.ad-wrap .meta { overflow: visible; }

/* ---- Find my level and Review on the same stage (tools/build.py build_placement / build_review, place-foot.js) ---- */
body.ln-play .env.cbl-place .pl-intro, body.ln-play .env.cbl-place .pl-item, body.ln-play .env.cbl-place .pl-result { order: 0; padding: 0; }
body.ln-play .env.cbl-place .coach-place { order: 0; }
body.ln-play .pl-intro h1 { margin: 10px 0 0; font: 700 clamp(23px, 4.6vw, 30px)/1.15 var(--f-display); letter-spacing: 0; }
body.ln-play .pl-t, body.ln-play .pl-rh { margin: 4px 0 10px; font: 700 clamp(21px, 3.4vw, 26px)/1.2 var(--f-display); letter-spacing: 0; }
body.ln-play .pl-lede { font-size: 17.5px; line-height: 1.65; color: var(--ink); max-width: 66ch; }
body.ln-play .env.cbl-place .prose { font-size: 17.5px; line-height: 1.65; }
/* the actions live in the bar, side by side, never stacked */
body.ln-play .lp-foot .pl-bar { display: contents; }
body.ln-play .lp-foot .pl-bar[hidden] { display: none; }
body.ln-play .lp-foot .pl-bar .lp-btn { min-width: 0; margin: 0; text-decoration: none; white-space: nowrap; }
body.ln-play .lp-foot .pl-bar .lp-btn[hidden] { display: none; }
@media (max-width: 699px) { body.ln-play .lp-foot > .step-nav:has(.pl-bar) { flex-wrap: nowrap; } body.ln-play .lp-foot .pl-bar .lp-btn { flex: 1 1 0; padding: 0 10px; font-size: 16px; } }
@media (min-width: 700px) { body.ln-play .lp-foot .pl-bar .lp-btn { min-width: 160px; } }
/* the problem's main button is the bar's (place-foot.js presses the toolbar's): the toolbar's own steps aside */
body.ln-play .place.pl-at-problem .env-code .toolbar :is([data-act="predict"], [data-act="check"], [data-act="explain"]) { display: none; }
/* no problem on screen (the intro, the result before any problem): one column at Learn's width, no empty editor */
body.ln-play .place:not(.pl-at-problem):has(.pl-board:empty) .env-code { display: none; }
body.ln-play .place:not(.pl-at-problem):has(.pl-board:empty) .env.cbl-place { display: flex; max-width: 900px; margin: 0 auto; }
/* review: how it works in one line; with nothing due, only Rook's line and Back to the course */
body.ln-play .rv-how { margin: 6px 0 0; }
body.ln-play .rv-how > summary { display: inline-flex; align-items: center; min-height: 44px; color: var(--study-ink); font: 700 15.5px/1.2 var(--f-body); cursor: pointer; }
body.ln-play .rv-how > .pl-lede { margin: 4px 0 8px; }
body.ln-play .rv-empty .rv-how, body.ln-play .rv-empty [data-rv-note], body.ln-play .rv-empty [data-rv-list] { display: none; }
body.ln-play .rv-empty #rv-h { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
body.ln-play .rv-empty .coach-place { margin-top: 12px; }
@media (min-width: 1100px) {
  body.ln-play .env.cbl-place { grid-template-rows: auto auto 1fr; grid-template-areas: "fig text" "fig coach" "fig ."; }
  body.ln-play .env.cbl-place .env-text > section { grid-area: text; }
  body.ln-play .env.cbl-place .coach-place { grid-area: coach; }
  body.ln-play .env.cbl-place .env-code { height: calc(100dvh - 82px - var(--lp-foot-h, 96px) - 20px); }
}
body.ln-play .lp-foot .pl-bar .lp-btn.quiet { order: -1; }
/* review with nothing due: Rook, bigger, celebrating, in the middle of the stage, his bubble beside him */
body.ln-play .rv-empty .env.cbl-place { min-height: calc(100dvh - 82px - var(--lp-foot-h, 96px) - 40px); justify-content: center; align-items: center; }
body.ln-play .rv-empty .env.cbl-place .pl-intro { margin: 0; }
body.ln-play .rv-empty .coach-place { grid-template-columns: 120px auto; margin: 0; }
body.ln-play .rv-empty .coach-place .coach-art { width: 120px; }

/* a locked lesson's card (assets/js/premium.js): nothing to buy shows until the account has answered (the buy rules by age),
   and the store app shows no price (html.bl-native already hides Get Code, build.py) */
body.ln-play .gate-checking [data-gate] :is(.gate-price, .gate-act, .gate-alt, .lk-value) { visibility: hidden; }
html.bl-native body.ln-play [data-gate] .gate-price { display: none; }
/* the meta line never cuts a word: the level meter wraps under it when they do not fit side by side */
body.ln-play .lh-meta.has-ad { flex-wrap: wrap; white-space: normal; }
body.ln-play .lh-meta.has-ad .meta { overflow: visible; }

/* a locked lesson (owner review, 13 Oct 2026: "Spacing!!", "Does it really need to show the language?", "Needs to look
   even better"): one lock card, no fake editor. The hook, then one soft card in the course's tint with the course's character
   over its top edge: the line, the count, what Brainlag Code opens, the billing period and the price, and the one action
   for the age band. One rhythm: 24 px between sections, 8 to 12 px within. */
body.ln-play .env.cbl-lp.env-premium .env-code { display: none; }
body.ln-play .env.cbl-lp.env-premium { display: flex; flex-direction: column; max-width: 900px; margin: 0 auto; }
body.ln-play .env.cbl-lp.env-premium .env-text { display: flex; width: 100%; }
body.ln-play .env.cbl-lp.env-premium .env-head { margin: 0; }
body.ln-play .env.cbl-lp.env-premium .env-scroll { margin-top: 20px; }
body.ln-play .env-premium .lk-hook { margin: 0; font-size: 19px; line-height: 1.5; color: var(--ink); max-width: 46ch; }
body.ln-play .lk-one { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; width: min(100%, 480px); box-sizing: border-box;
  margin: 50px auto 4px; padding: 50px 20px 18px; border-radius: 24px; background: color-mix(in srgb, var(--tc, var(--study)) 11%, var(--surface)); text-align: center; }
:root[data-theme="dark"] body.ln-play .lk-one { background: var(--surface-up, color-mix(in srgb, #fff 6%, var(--surface))); }   /* dark: the site's navy card a step above --surface, so the --surface tiles still separate; never the track colour mixed in (yellow on navy read olive; owner: no olive or brown dark surfaces, 18 Oct 2026) */
:root[data-theme="dark"] body.ln-play .lk-ic { background: var(--surface-up, color-mix(in srgb, #fff 6%, var(--surface))); }
body.ln-play .lk-one .lk-art { position: absolute; top: -50px; left: 50%; width: 96px; margin: 0 0 0 -48px; }
body.ln-play .lk-one .gate-h { margin: 0; font: 700 clamp(22px, 4.2vw, 26px)/1.2 var(--f-display); }
body.ln-play .lk-one .lk-n { margin: 0; color: var(--ink-2); font-size: 15.5px; line-height: 1.4; }
body.ln-play .lk-strip { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 0; padding: 0; list-style: none; }
body.ln-play .lk-strip li { width: 12px; height: 12px; border-radius: 50%; box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--ink) 30%, transparent); }
body.ln-play .lk-value { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; width: 100%; margin: 8px 0 0; padding: 0; list-style: none; }
body.ln-play .lk-value li { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 9px 8px; border-radius: 14px; background: var(--surface); color: var(--ink); font: 700 15px/1.2 var(--f-body); }
body.ln-play .lk-ic { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 11px; background: color-mix(in srgb, var(--tc, var(--study)) 14%, var(--surface)); color: var(--tc-text, var(--study-ink)); }
body.ln-play .lk-ic .icon { width: 20px; height: 20px; stroke-width: 2.4; }
@media (max-width: 339px) {
  body.ln-play .lk-value { grid-template-columns: minmax(0, 1fr); }
  body.ln-play .lk-value li { flex-direction: row; justify-content: flex-start; padding: 8px 10px; }
}
body.ln-play .lk-price { display: grid; justify-items: center; gap: 6px; width: 100%; margin: 10px 0 0; }
body.ln-play .lk-per { width: 100%; }
body.ln-play .lk-per > button { min-height: 44px; padding: 0 16px; }
/* "2 months free" (the pricing page's words) and the monthly price struck through, centred under the yearly price */
/* Yearly first: the month figure large, the yearly charge on the line under it; "2 months free" beside Yearly in the same
   button (owner, 18 Oct 2026: no struck-through price, no badge) */
body.ln-play .lk-per [data-per="y"] { display: inline-flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap; }
body.ln-play .lk-per-save { font-size: 12.5px; font-weight: 700; opacity: .9; white-space: nowrap; }
body.ln-play .lk-bill { margin: 2px 0 0; color: var(--ink-2); font-size: 14px; line-height: 1.35; }
body.ln-play .lk-bill[hidden] { display: none; }
body.ln-play .lk-amt { margin: 2px 0 0; color: var(--ink-2); font-size: 16px; }
body.ln-play .lk-amt[hidden] { display: none; }
/* the price in brainlag.space's shared format (copied from brainlag.space/public/assets/css/brainlag.css, "A price";
   markup by build.py price_html, a port of includes/components/price.php); the figure's size is the lock card's */
/*      A price (owner, 13 Oct: "£99 a year needs to look nicer"; includes/components/price.php, assets/js/bl-price.js):
   the figure large, its sign and any pence small and raised, tabular numerals; the period small and muted on the same
   baseline. The figure takes its size from where it sits (.pl-price b, .hm-pl-pr, .pm-price ...); 0.5em of it for the
   sign and pence. */
.bl-pr{display:inline-flex;align-items:baseline;flex-wrap:wrap;gap:0 6px;font-variant-numeric:tabular-nums lining-nums}
body.ln-play .lk-amt .bl-pr { gap: 0 4px; flex-wrap: nowrap; }
body.ln-play .lk-amt .bl-pr-v { align-items: baseline; }
body.ln-play .lk-amt .bl-pr-v :is(.bl-pr-c, .bl-pr-d) { position: relative; top: -.62em; margin-top: 0; }
.bl-pr-v{display:inline-flex;align-items:flex-start;line-height:1;font-variant-numeric:tabular-nums lining-nums;white-space:nowrap}
.bl-pr-v .bl-pr-c,.bl-pr-v .bl-pr-d{font-size:.5em;line-height:1;margin-top:.12em;font-weight:inherit;letter-spacing:0}
.bl-pr-v .bl-pr-c{margin-inline-end:.08em}
.bl-pr-v .bl-pr-ca{margin-inline:.12em 0}
.bl-pr-v .bl-pr-d{margin-inline-start:.02em}
.bl-pr-per{font-size:15px;line-height:1.2;font-weight:500;color:var(--ink-2)}
body.ln-play .lk-amt .bl-pr-v { color: var(--ink); font: 700 36px/1 var(--f-display); }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
body.ln-play .lk-one .gate-act { display: flex; width: 100%; margin: 6px 0 0; }
body.ln-play .lk-one .gate-act .btn { flex: 1 1 auto; min-height: 54px; border-radius: 16px; font-size: 17px; }
body.ln-play .lk-one .gate-alt, body.ln-play .lk-one .gate-note { margin: 2px 0 0; font-size: 14.5px; color: var(--ink-3); }
body.ln-play .lk-one .gate-alt a { color: var(--study-ink); font-weight: 700; }
/* not a known adult (build.py adult_only): no price and no Get Code, one plain link to what the plan includes */
body.ln-play .lk-one .gate-inc { margin: 6px 0 4px; font-size: 16px; }
body.ln-play .gate-checking [data-gate] .gate-inc { visibility: hidden; }
body.ln-play .lk-one .gate-inc a { display: inline-flex; align-items: center; min-height: 44px; color: var(--study-ink); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
body.ln-play .lk-minor { margin: 4px 0 0; max-width: 38ch; color: var(--ink-2); font-size: 16px; line-height: 1.5; }
html.bl-native body.ln-play .lk-one .gate-act, html.bl-native body.ln-play .lk-one .lk-value, html.bl-native body.ln-play .lk-one .gate-price { display: none; }

/* the lock card's motion (owner, 13 Oct 2026: "could be even more dynamic"), once, when the card shows what it should
   (premium.js adds .lk-go): the character rises from the card's edge, the exercise circles tick one by one and clear,
   the tiles come in 60 ms apart, and the buy button gives one soft pulse (adults only: nothing pulls at an under-18).
   Afterwards only the character's small idle sway. Never with reduced motion or Show animations off (data-motion). */
@media (prefers-reduced-motion: no-preference) {
  html:not([data-motion="off"]) body.ln-play .lk-go .lk-art { animation: lkRise .3s cubic-bezier(.22, 1, .36, 1) both, lkSway 5s 1.2s ease-in-out infinite; transform-origin: 50% 100%; }
  html:not([data-motion="off"]) body.ln-play .lk-go .lk-strip li { animation: lkTick 1.8s calc(.35s + var(--i) * .16s) both; }
  html:not([data-motion="off"]) body.ln-play .lk-go .lk-value li { animation: lkIn .32s calc(.25s + var(--i) * .06s) cubic-bezier(.22, 1, .36, 1) both; }
  html:not([data-motion="off"]) body.ln-play .lk-go:is([data-age="out"], [data-age="adult"]) .gate-act .btn { animation: lkPulse .6s 1.1s ease-out 1 both; }
}
@keyframes lkRise { from { opacity: 0; translate: 0 28px; } to { opacity: 1; translate: none; } }
@keyframes lkSway { 0%, 86%, 100% { rotate: 0deg; } 90% { rotate: -4deg; } 94% { rotate: 3deg; } 97% { rotate: -1deg; } }
@keyframes lkIn { from { opacity: 0; translate: 0 8px; } to { opacity: 1; translate: none; } }
@keyframes lkPulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--prem, #6a4bc4) 45%, transparent); } 100% { box-shadow: 0 0 0 12px transparent; } }
@keyframes lkTick { 0% { background: transparent; } 12%, 70% { background: var(--study); box-shadow: inset 0 0 0 2px var(--study); } 100% { background: transparent; } }
body.ln-play .lk-strip li { position: relative; }
body.ln-play .lk-strip li::after { content: ""; position: absolute; left: 4px; top: 2px; width: 3px; height: 6px; border: solid #fff; border-width: 0 2px 2px 0; rotate: 45deg; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  html:not([data-motion="off"]) body.ln-play .lk-go .lk-strip li::after { animation: lkMark 1.8s calc(.35s + var(--i) * .16s) both; }
}
@keyframes lkMark { 0%, 10% { opacity: 0; } 14%, 70% { opacity: 1; } 100% { opacity: 0; } }

/* the prerequisite note (owner review, 13 Oct 2026: "Spacing!"): one soft banner under the lesson's title row, its words
   and the dismiss button centred on one line, a 44 px target, 16 px from the title row and from the step under it */
body.ln-play .soft-note { display: flex; flex-wrap: nowrap; align-items: center; gap: 8px; margin: 0 0 16px; padding: 6px 6px 6px 16px; border-radius: 14px; background: var(--sunk); white-space: normal; }
body.ln-play .soft-note .sn-t { flex: 1 1 auto; min-width: 0; margin: 0; padding: 6px 0; color: var(--ink-2); font-size: 15px; line-height: 1.45; }
body.ln-play .soft-note .sn-t a { color: var(--study-ink); font-weight: 700; white-space: nowrap; }
body.ln-play .soft-note .sn-x { flex: none; width: 44px; height: 44px; margin: 0; border-radius: 12px; }
body.ln-play .soft-note .sn-x:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
@media (max-width: 1099.98px) { body.ln-play .env.cbl-lp:not(.env-premium) .env-scroll { margin-top: 16px; } }
@media (min-width: 1100px) { body.ln-play .env.cbl-lp .env-head { margin-bottom: 16px; } }

/* the top bar's right-hand controls (owner review, 13 Oct 2026: "Spacing?"): Code has no Sparks counter, so the slot Learn
   keeps for it goes, and Lesson settings and sound sit together 8 px apart at the right edge; the progress bar fills the
   room between, 16 px clear of each side. The place line: the course in full, the lesson count quieter beside it. */
body.ln-play .lp-top { gap: 16px; }
body.ln-play .lp-top::after { content: none; display: none; }
body.ln-play .lp-top > .lp-snd { margin-inline-start: -8px; }
body.ln-play .lp-top .lp-bar { flex: 1 1 auto; }
body.ln-play .lp-loc .lp-loc-c { color: var(--ink-2); }
body.ln-play .lp-loc .lp-loc-n { display: inline; margin-inline-start: 6px; color: var(--ink-3); font-weight: 500; }   /* site.css hid the old short form */
@media (max-width: 440px) { body.ln-play .lp-top { gap: 12px; } body.ln-play .lp-top > .lp-snd { margin-inline-start: -4px; } }
body.ln-play .lp-top > .lp-meta:not(:has(.blk-combo:not([hidden]))) { margin-inline-start: -16px; }   /* an empty combo slot takes no gap */
@media (max-width: 440px) { body.ln-play .lp-top > .lp-meta:not(:has(.blk-combo:not([hidden]))) { margin-inline-start: -12px; } }

/* typing on a phone (dock.js): Run pinned at the end of the symbol row, and room below the code for the keyboard and the
   dock, so the caret can always be scrolled above them (P0 sweep, 19 Oct 2026: at 320 px the caret ended up behind the
   dock, the page having nothing more to scroll) */
.kbar:not([hidden]) { display: flex; align-items: center; }
.kbar .kb-row { flex: 1 1 auto; min-width: 0; }
.kbar .kb-run { flex: none; height: 44px; margin: 0 8px 0 2px; padding: 0 18px; border: 0; border-radius: 10px; background: var(--teal-btn); color: #fff; font: 700 15.5px/1 var(--font); cursor: pointer; touch-action: manipulation; }
.kbar .kb-run:focus-visible { outline: 3px solid var(--teal-text); outline-offset: 2px; }
html.kb-open body.ln-play .cbl-stage { padding-bottom: calc(var(--dock-h, 96px) + var(--kb, 0px) + 24px); }
