/*
 * Old School Smarts — site styles.
 *
 * Design idea: a school exercise book. Slab-serif headings like a textbook
 * spine, a warm paper background instead of clinical white, and the ruled-paper
 * card as the signature element. The red-pen underline is used sparingly — it is
 * the one loud thing on the page, so it only ever marks the main heading.
 *
 * Bootstrap variables are overridden here rather than in markup so that every
 * app's existing btn-primary / text-muted classes inherit the brand for free.
 */

/*
 * The palette.
 *
 * This was originally a muted slate-and-brass scheme — handsome, but it read as
 * a grown-up's stationery catalogue, and the people actually using these sheets
 * are children. So the same structure now carries bright, cheerful colour.
 *
 * The VARIABLE NAMES ARE DELIBERATELY UNCHANGED. Around a hundred rules across
 * every app already reference --slate, --brass and --rule; renaming them would
 * mean editing all of those and would silently break any I missed. So `--slate`
 * is now a bright blue and `--brass` a sunny amber. The name is historical, the
 * value is what matters.
 *
 * Ink stays dark enough for real contrast on paper-white — bright must not mean
 * hard to read, especially for a child still decoding letters.
 */
:root {
    --slate: #2f6fd0;      /* Bright pencil blue — primary buttons and links. */
    --chalk: #e8f4ff;      /* Pale sky, for the nav bar and banded sections.  */
    --brass: #f5a524;      /* Sunny amber — highlights and the active cell.    */
    --ink: #1b2a3a;        /* Deep navy rather than near-black. Warmer.        */
    --rule: #b9d7ef;       /* Soft blue ruling instead of dusty beige.         */
    --red-pen: #ef4b5c;    /* Friendly coral, not a stern marking red.         */

    --paper: #fdfcff;      /* Clean bright white with the faintest cool cast.  */
    --muted-ink: #566b80;

    /* Extra brights, for the sheet's cheerful bits. */
    --grass: #2fb672;      /* Correct, well done, ticks.                       */
    --grape: #8b5cf6;      /* The bell and the speaking parts.                 */
    --sunshine: #ffd84d;   /* Celebration and progress fill.                   */

    --font-display: "Bitter", Georgia, "Times New Roman", serif;
    --font-body: "Source Sans 3", -apple-system, "Segoe UI", Roboto, sans-serif;

    /* Bootstrap overrides — themes buttons, links and focus rings site-wide. */
    --bs-primary: #2f6fd0;
    --bs-primary-rgb: 47, 111, 208;
    --bs-link-color: #2158ad;
    --bs-link-color-rgb: 33, 88, 173;
    --bs-link-hover-color: #ef4b5c;
    --bs-body-color: #1b2a3a;
    --bs-body-bg: #fdfcff;
    --bs-border-color: #b9d7ef;
    --bs-font-sans-serif: var(--font-body);
}

body {
    font-family: var(--font-body);
    background-color: var(--paper);
    color: var(--ink);
}

h1, h2, h3, h4, h5, .navbar-brand {
    font-family: var(--font-display);
    letter-spacing: -0.01em;
}

h1 { font-weight: 700; }
h2, h3 { font-weight: 600; }

/* Bootstrap's .text-muted is too light on a cream background to stay legible. */
.text-muted {
    color: var(--muted-ink) !important;
}

.btn-primary {
    --bs-btn-bg: var(--slate);
    --bs-btn-border-color: var(--slate);
    --bs-btn-hover-bg: #2158ad;
    --bs-btn-hover-border-color: #2158ad;
    --bs-btn-active-bg: #2158ad;
    --bs-btn-active-border-color: #2158ad;
}

/*
 * .btn-dark is used for the main child-facing actions on the sheet (take the
 * test, mark a test). Black-on-white is the wrong note there, so it inherits
 * the bright blue too rather than every template needing editing.
 */
.btn-dark {
    --bs-btn-bg: var(--slate);
    --bs-btn-border-color: var(--slate);
    --bs-btn-hover-bg: #2158ad;
    --bs-btn-hover-border-color: #2158ad;
    --bs-btn-active-bg: #2158ad;
    --bs-btn-active-border-color: #2158ad;
}

.btn-outline-primary {
    --bs-btn-color: var(--slate);
    --bs-btn-border-color: var(--slate);
    --bs-btn-hover-bg: var(--slate);
    --bs-btn-hover-border-color: var(--slate);
}

/* ---------------------------------------------------------------------------
 * Masthead and navigation
 * ------------------------------------------------------------------------ */
.site-nav {
    background: var(--chalk);
    border-bottom: 1px solid var(--rule);
}

.site-nav .navbar-brand {
    font-weight: 700;
    font-size: 1.35rem;
    color: var(--ink);
}

.site-nav .nav-link {
    color: #3d4a50;
    font-weight: 500;
}

.site-nav .nav-link:hover,
.site-nav .nav-link:focus {
    color: var(--red-pen);
}

/* The current section is marked with a pen underline rather than a background
   fill, so it reads as annotation rather than a selected tab. */
.site-nav .nav-link.is-active {
    color: var(--ink);
    box-shadow: inset 0 -2px 0 var(--red-pen);
}

/* ---------------------------------------------------------------------------
 * Signature element: the red-pen underline.
 * Used ONCE per page, on the main heading. Restraint is the point.
 * ------------------------------------------------------------------------ */
.pen-underline {
    position: relative;
    display: inline-block;
}

.pen-underline::after {
    content: "";
    position: absolute;
    left: 0;
    right: -0.15em;
    bottom: -0.18em;
    height: 0.28em;
    /* Slightly irregular so it reads as hand-drawn rather than a border. */
    background: var(--red-pen);
    opacity: 0.85;
    border-radius: 60% 40% 55% 45% / 100% 100% 60% 70%;
    transform: rotate(-0.5deg);
}

/* ---------------------------------------------------------------------------
 * Home page
 * ------------------------------------------------------------------------ */
.hero {
    background: var(--chalk);
    border-bottom: 1px solid var(--rule);
    padding: 4rem 0 4.25rem;
}

.hero__lead {
    font-size: 1.15rem;
    max-width: 34rem;
    color: #3d4a50;
}

.section-label {
    font-family: var(--font-body);
    font-size: 0.78rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--brass);
    margin-bottom: 0.4rem;
}

/* Plain content cards. Kept quiet so the ruled cards stand out by contrast. */
.plain-card {
    background: #fff;
    border: 1px solid var(--rule);
    border-radius: 4px;
    padding: 1.25rem;
    height: 100%;
}

.plain-card h3 {
    font-size: 1.1rem;
}

/* ---------------------------------------------------------------------------
 * Interior page headings
 *
 * Applied by selector rather than by adding a class to 27 templates, so every
 * existing and future page picks up the treatment automatically. The pen
 * underline is deliberately NOT used here — it stays exclusive to the home page
 * hero so it reads as a signature rather than decoration.
 * ------------------------------------------------------------------------ */
main > h1,
main > section > h1,
main > div > h1,
main > article > h1 {
    padding-bottom: 0.5rem;
    margin-bottom: 1.25rem;
    border-bottom: 2px solid var(--rule);
}

/* ---------------------------------------------------------------------------
 * Tables and forms — warm rules instead of Bootstrap's cool grey
 * ------------------------------------------------------------------------ */
.table > :not(caption) > * > * {
    border-bottom-color: var(--rule);
}

.card {
    border-color: var(--rule);
}

.form-control:focus,
.form-select:focus {
    border-color: var(--brass);
    box-shadow: 0 0 0 0.2rem rgba(245, 165, 36, 0.2);
}

/* ---------------------------------------------------------------------------
 * Footer
 * ------------------------------------------------------------------------ */
.site-footer {
    background: var(--slate);
    color: #d8d3c6;
    padding: 2.5rem 0 2rem;
}

.site-footer a {
    color: #ffffff;
    text-decoration: none;
}

.site-footer a:hover {
    text-decoration: underline;
}

.newsletter-signup {
    background: var(--chalk);
}

/* ---------------------------------------------------------------------------
 * AI disclaimer
 * Deliberately NOT a Bootstrap alert: no close button, no dismissal. A parent
 * should not be able to hide the caveat and then read the findings without it.
 * ------------------------------------------------------------------------ */
.ai-disclaimer {
    border: 2px solid var(--brass);
    border-left-width: 6px;
    border-radius: 4px;
    background: #fffdf7;
    padding: 0.9rem 1.1rem;
    margin: 1.25rem 0;
}

.ai-disclaimer__heading {
    font-weight: 700;
    color: #6d5325;
    margin: 0 0 0.35rem;
    font-size: 0.95rem;
}

.ai-disclaimer__body {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.5;
    color: #4a4235;
}

/* ---------------------------------------------------------------------------
 * Exercise-book ruled card — the signature visual element
 *
 * Ruled paper only works if the writing sits ON the lines. Previously the
 * rules were drawn at a fixed 1.65rem pitch while the text kept Bootstrap's
 * 1.5 line-height (1.5rem), so every line drifted 0.15rem further out of step
 * and the text was a full rule adrift by line eleven. That is harder to read
 * than plain paper, and it quietly teaches children that lines do not matter.
 *
 * So the pitch is now a single variable that BOTH the rules and the text obey.
 * Everything vertical inside the card — line-height, margins, padding — has to
 * be a whole multiple of it, or the following lines fall off the grid again.
 * ------------------------------------------------------------------------ */
.ruled-card {
    /* One number governs the rhythm. Change it here and the text follows. */
    --rule-pitch: 1.65rem;

    background-color: #fffef9;
    background-image: repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent calc(var(--rule-pitch) - 1px),
        var(--rule) calc(var(--rule-pitch) - 1px),
        var(--rule) var(--rule-pitch)
    );
    /* Anchor the ruling to the text box, not the border box, so the padding
     * below lines the first rule up under the first line of writing. */
    background-origin: content-box;
    background-clip: content-box;

    border: 1px solid var(--rule);
    border-radius: 4px;

    /* Whole multiples of the pitch, so the grid survives the padding. */
    padding: var(--rule-pitch) 1.25rem;

    /* The text now steps exactly one rule at a time. */
    line-height: var(--rule-pitch);
}

/* Prose inherits the rhythm; its spacing is a whole rule so nothing drifts. */
.ruled-card p,
.ruled-card li,
.ruled-card dd,
.ruled-card dt {
    line-height: var(--rule-pitch);
}

.ruled-card p {
    margin-bottom: var(--rule-pitch);
}

.ruled-card > :last-child {
    margin-bottom: 0;
}

/*
 * Headings need two rules of space, but the line box must be ONE rule tall,
 * not two. A two-rule line box centres the text between the rules with
 * half-leading above and below, which is why headings floated off the line.
 * Instead: a one-rule line box sitting on the grid, with a blank rule of
 * space pushed above it. Same total height, but the letters land on a rule.
 *
 * The font is also capped so a large heading cannot overflow its rule and
 * drag the following text out of step.
 */
.ruled-card h1,
.ruled-card h2,
.ruled-card h3,
.ruled-card h4,
.ruled-card h5,
.ruled-card h6 {
    line-height: var(--rule-pitch);
    font-size: 1.2rem;
    margin-top: var(--rule-pitch);
    margin-bottom: 0;
}

/* The first heading needs no blank rule above it; the padding already gives one. */
.ruled-card > :first-child {
    margin-top: 0;
}

/*
 * Anything that is not running prose cannot honour a baseline grid — a form,
 * a row of buttons, a badge or a chart sets its own heights. Drawing rules
 * behind those is the very mismatch this block exists to prevent, so those
 * cards keep the paper colour and the border but lose the ruling.
 */
.ruled-card--plain {
    background-image: none;
}

/* ---------------------------------------------------------------------------
 * Analyser findings
 * ------------------------------------------------------------------------ */
.finding-card {
    border: 1px solid var(--rule);
    border-left: 4px solid var(--slate);
    border-radius: 4px;
    padding: 1rem 1.1rem;
    margin-bottom: 1rem;
    background: #fff;
}

.finding-card__header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    margin-bottom: 0.5rem;
}

.finding-card__suggestion {
    background: var(--chalk);
    border-radius: 3px;
    padding: 0.6rem 0.75rem;
    font-size: 0.95rem;
}

/*
 * Confidence badges describe how much evidence there was, never how likely the
 * analyser is to be right. Wording in the template is "Seen often" rather than
 * "High confidence" for exactly that reason, and the colours stay muted — a
 * green "strong" badge would read as a verified conclusion.
 */
.confidence {
    flex-shrink: 0;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
    border: 1px solid var(--rule);
    color: #5c5344;
    background: var(--chalk);
    white-space: nowrap;
}

.confidence--strong {
    border-color: var(--brass);
    color: #6d5325;
}

@media print {
    .ai-disclaimer {
        /* The caveat must survive printing — a printed report handed to someone
           else is exactly when the context is most easily lost. */
        border-color: #000;
    }
}

/* ------------------------------------------------------------------
   Worksheet index — subjects as separate sections
   Times tables and spelling are different kinds of practice, so each
   gets its own paper texture. Squared paper for sums, ruled paper for
   words. The texture is the divider, so no heavy borders are needed.
   ------------------------------------------------------------------ */

.ws-upsell {
    border: 1px solid var(--rule);
    border-left: 4px solid var(--brass);
    border-radius: 2px;
    padding: 1rem 1.25rem;
    background: var(--paper);
}

.ws-subject {
    margin: 2.5rem 0;
    border: 1px solid var(--rule);
    border-radius: 2px;
    overflow: hidden;
    background: var(--paper);
}

.ws-subject__head {
    padding: 1rem 1.25rem 0.75rem;
    border-bottom: 1px solid var(--rule);
}

.ws-subject__title {
    margin: 0;
    font-size: 1.35rem;
    letter-spacing: 0.01em;
}

/* The coloured rule under each title is what tells the two sections
   apart at a glance, before you've read a word. */
.ws-subject__title::after {
    content: "";
    display: block;
    width: 2.5rem;
    height: 3px;
    margin-top: 0.5rem;
    background: var(--brass);
}

.ws-subject__desc {
    margin: 0.5rem 0 0;
    color: var(--muted-ink);
}

.ws-subject__body {
    padding: 1.25rem;
}

.ws-subject__subhead {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--muted-ink);
    margin: 0 0 0.75rem;
}

/* Times tables: squared exercise paper. */
.ws-subject--multiplication .ws-subject__body {
    background-image:
        linear-gradient(to right, rgba(47, 111, 208, 0.13) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(47, 111, 208, 0.13) 1px, transparent 1px);
    background-size: 22px 22px;
}

.ws-subject--multiplication .ws-subject__title::after {
    background: var(--slate);
}

/* Spelling: ruled writing paper. */
.ws-subject--spelling .ws-subject__body {
    background-image:
        linear-gradient(to bottom, rgba(245, 165, 36, 0.28) 1px, transparent 1px);
    background-size: 100% 28px;
}

.ws-subject--spelling .ws-subject__title::after {
    background: var(--brass);
}

.ws-sheet-list {
    list-style: none;
    padding: 0;
    margin: 0 0 1.25rem;
}

.ws-sheet-list__item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.5rem 0.65rem;
    background: rgba(232, 244, 255, 0.85);
    border-bottom: 1px solid var(--rule);
}

.ws-sheet-list__item:last-child {
    border-bottom: 0;
}

.ws-sheet-list__link {
    font-weight: 600;
    text-decoration: none;
}

.ws-sheet-list__link:hover {
    text-decoration: underline;
}

.ws-sheet-list__print {
    flex-shrink: 0;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted-ink);
}

.ws-subject__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.ws-upcoming {
    margin-top: 3rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--rule);
    color: var(--muted-ink);
}

.ws-upcoming__list {
    margin: 0;
    padding-left: 1.1rem;
}

/* Home page subject cards carry the same colour cue as their section on
   the worksheet index, so the two subjects read as distinct from the
   very first page. */
.subject-card {
    border-top: 3px solid var(--rule);
}

.subject-card--multiplication {
    border-top-color: var(--slate);
}

.subject-card--spelling {
    border-top-color: var(--brass);
}

/* ==========================================================================
   The Look, Say, Cover, Write, Check sheet
   --------------------------------------------------------------------------
   Modelled on a real exercise-book page rather than a web table. Two ruled
   writing lines per word, and a brass "cover" flap between the word and the
   writing columns which is what actually makes the method work on screen.
   ========================================================================== */

.lscwc {
    max-width: 60rem;
    margin: 0 auto;
}

.lscwc__head {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-items: flex-end;
    justify-content: space-between;
    margin-bottom: 1.25rem;
}

.lscwc__eyebrow {
    margin: 0;
    font-size: 0.8rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--muted-ink);
}

.lscwc__title {
    font-family: var(--font-display);
    font-size: clamp(1.6rem, 4vw, 2.3rem);
    margin: 0.1rem 0 0.15rem;
    color: var(--ink);
}

/* The method line is the signature: hand-underlined in red pen. */
.lscwc__method {
    display: inline-block;
    margin: 0;
    padding-bottom: 0.2rem;
    font-family: var(--font-display);
    font-size: 0.95rem;
    letter-spacing: 0.04em;
    color: var(--slate);
    border-bottom: 2px solid var(--red-pen);
    border-radius: 40% 60% 55% 45% / 100% 100% 100% 100%;
}

.lscwc__actions {
    display: flex;
    gap: 0.5rem;
}

.lscwc__note {
    padding: 0.65rem 0.9rem;
    margin-bottom: 1rem;
    font-size: 0.93rem;
    background: #fff;
    border-left: 3px solid var(--brass);
}

.lscwc__note--redo {
    border-left-color: var(--red-pen);
}

/* --- the sheet itself --- */

.lscwc__sheet {
    background: #fff;
    border: 1px solid var(--rule);
    box-shadow: 0 1px 0 var(--rule), 0 12px 28px rgba(27, 42, 58, 0.07);
}

.lscwc__legend,
.lscwc__row {
    display: grid;
    grid-template-columns: minmax(8.5rem, 1.55fr) repeat(5, 1fr) minmax(6rem, 1.35fr);
    align-items: stretch;
}

.lscwc__legend {
    background: var(--slate);
    color: var(--chalk);
    font-size: 0.72rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.lscwc__legend span {
    padding: 0.55rem 0.5rem;
    border-right: 1px solid rgba(255, 255, 255, 0.18);
    text-align: center;
}

/* The two end columns are named, so they read left-aligned like headings. */
.lscwc__legend-word { text-align: left !important; padding-left: 0.85rem !important; }

/* The test column is the point of the sheet, so the brass marks it out. */
.lscwc__legend-test {
    color: var(--brass);
    background: rgba(245, 165, 36, 0.14);
}

.lscwc__legend span:last-child {
    border-right: 0;
}

.lscwc__list {
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: lscwc;
}

.lscwc__row {
    border-top: 1px solid var(--rule);
    min-height: 3.3rem;
}

.lscwc__list > .lscwc__row:first-child {
    border-top: 0;
}

.lscwc__row.is-carried {
    background: rgba(245, 165, 36, 0.07);
}

.lscwc__word {
    position: relative;
    padding: 0.7rem 0.85rem;
    border-right: 1px solid var(--rule);
    counter-increment: lscwc;
}

.lscwc__word::before {
    content: counter(lscwc) ".";
    margin-right: 0.4rem;
    font-size: 0.8rem;
    color: var(--muted-ink);
}

.lscwc__spell {
    font-family: var(--font-display);
    font-size: 1.28rem;
    font-weight: 600;
    color: var(--ink);
}

.lscwc__flag {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.4rem;
    font-size: 0.66rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #fff;
    background: var(--brass);
    border-radius: 2px;
    vertical-align: 0.15rem;
}

.lscwc__meaning {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.8rem;
    line-height: 1.35;
    color: var(--muted-ink);
}

/*
 * The cover step, on screen.
 *
 * On paper the child folds the page over the word. Here the flap actually does
 * that: hinged on its left edge, it swings a half turn and lands over the word,
 * hiding it. It is the one moment of movement on the page, so it is worth doing
 * properly — the fold is what makes this the same exercise as the paper one
 * rather than a typing game.
 *
 * The row must not grow when the flap covers it, so the flap is absolutely
 * positioned and the word cell keeps its own height.
 */
.lscwc__word {
    perspective: 700px;
}

.lscwc__flap {
    position: absolute;
    top: 0;
    /* Hinged on the cell's left edge, folded open and out of the way. */
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    transform-origin: left center;
    transform: rotateY(-180deg);
    transform-style: preserve-3d;
    backface-visibility: hidden;
    pointer-events: none;
    opacity: 0;
    transition: transform 0.45s ease, opacity 0.2s ease 0.25s;

    /* The brass cross-hatch of the old cover, and a crease on the hinge. */
    background-color: #cbb489;
    background-image:
        repeating-linear-gradient(
            45deg,
            rgba(255, 255, 255, 0.22) 0 2px,
            transparent 2px 5px
        ),
        repeating-linear-gradient(
            -45deg,
            rgba(47, 111, 208, 0.14) 0 2px,
            transparent 2px 5px
        );
    border-left: 2px solid #8d6f42;
    box-shadow: 3px 0 10px rgba(27, 42, 58, 0.22);
}

.lscwc__row.is-covered .lscwc__flap {
    /* Folded across: it now sits over the word. */
    transform: rotateY(0deg);
    opacity: 1;
}

.lscwc__flap-label {
    font-size: 0.6rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #4a3a20;
}

/* The paper instruction. Only useful when nothing can fold, i.e. in print. */
.lscwc__foldhint {
    display: none;
    margin-top: 0.3rem;
    font-size: 0.6rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--brass);
}

/* 'Cover it' — offered only on the row being worked on. */
.lscwc__cover {
    display: none;
    margin-top: 0.35rem;
    padding: 0.1rem 0.5rem;
    font-family: var(--font-body);
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--slate);
    background: transparent;
    border: 1px solid var(--brass);
    border-radius: 2px;
    cursor: pointer;
}

.lscwc__cover:hover {
    color: #fff;
    background: var(--brass);
}

.lscwc__row.is-active .lscwc__cover {
    display: inline-block;
}

.lscwc__row.is-covered .lscwc__cover {
    /* Nothing to press while it is already covered. */
    visibility: hidden;
}

/*
 * Which row matters. The active row is lifted and the rest are dimmed, so a
 * child working alone is never in any doubt about where they are.
 */
.lscwc__row.is-active {
    background: #fff;
    box-shadow: inset 3px 0 0 var(--slate);
}

.lscwc__row.is-quiet {
    opacity: 0.62;
}

.lscwc__row.is-quiet:hover {
    opacity: 0.85;
}

/* What they wrote, kept in their own words with a quiet tick. */
.lscwc__written {
    display: block;
    width: 100%;
    padding-bottom: 0.1rem;
    font-family: var(--font-display);
    font-size: 0.95rem;
    color: var(--slate);
    border-bottom: 1px solid var(--rule);
}

.lscwc__write.is-done {
    background: rgba(245, 165, 36, 0.07);
}

.lscwc__write.is-done::after {
    content: "\2713";
    margin-left: 0.2rem;
    font-size: 0.7rem;
    color: var(--brass);
}

/* The one cell that accepts typing. Ruled like the rest, not boxed like a form. */

.lscwc__input {
    width: 100%;
    padding: 0 0 0.1rem;
    font-family: var(--font-display);
    font-size: 0.95rem;
    color: var(--ink);
    background: transparent;
    border: 0;
    border-bottom: 2px solid var(--slate);
    border-radius: 0;
}

.lscwc__input:focus {
    outline: none;
    border-bottom-color: var(--red-pen);
}

/*
 * The tally, and the thing that opens the test. Deliberately plain: it is a
 * record of work done, not a scoreboard.
 */
.practice {
    margin: 1.25rem 0 0.85rem;
    padding: 0.9rem 1.1rem;
    background: #fff;
    border: 1px solid var(--rule);
    border-left: 3px solid var(--slate);
}

.practice__status {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    justify-content: space-between;
    align-items: baseline;
}

.practice__where {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 600;
    color: var(--ink);
}

.practice__tally {
    margin: 0;
    font-size: 0.82rem;
    color: var(--muted-ink);
}

.practice__track {
    height: 6px;
    margin: 0.6rem 0 0.5rem;
    background: rgba(47, 111, 208, 0.1);
    overflow: hidden;
}

.practice__fill {
    height: 100%;
    background: var(--brass);
    transition: width 0.3s ease;
}

.practice__hint {
    margin: 0;
    font-size: 0.85rem;
    color: var(--muted-ink);
}

.practice__warning {
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
    color: var(--red-pen);
}

/* Grown-up controls: available, but not the obvious thing to press. */
.practice__grownup {
    margin-top: 1.5rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--rule);
}

.practice__grownup-title {
    margin: 0 0 0.5rem;
    font-size: 0.7rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted-ink);
}

.practice__grownup-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.practice__grownup-note {
    margin: 0.5rem 0 0;
    font-size: 0.78rem;
    color: var(--muted-ink);
}

/* A fold that snaps is worse than no fold for anyone who asked for less motion. */
@media (prefers-reduced-motion: reduce) {
    .lscwc__flap,
    .practice__fill {
        transition: none;
    }
}

/* Writing columns: a ruled line sitting low, as in a real book. */
.lscwc__write {
    display: flex;
    align-items: flex-end;
    padding: 0 0.4rem 0.75rem;
    border-right: 1px solid var(--rule);
}

/*
 * The test column. Tinted and separated by a heavier rule so a child can see at
 * a glance that this one is the real attempt, not another practice go.
 */
.lscwc__test {
    display: flex;
    align-items: flex-end;
    padding: 0 0.6rem 0.75rem;
    border-left: 2px solid var(--slate);
    background: rgba(245, 165, 36, 0.06);
}

.lscwc__ruleline {
    display: block;
    width: 100%;
    border-bottom: 1px solid var(--rule);
}

.lscwc__dictation {
    margin-top: 1.5rem;
    padding: 1.1rem 1.25rem;
    background: #fff;
    border: 1px solid var(--rule);
    border-top: 3px solid var(--slate);
}

.lscwc__dictation h2 {
    font-family: var(--font-display);
    font-size: 1.15rem;
    margin: 0 0 0.2rem;
}

.lscwc__dictation-lead {
    margin: 0 0 0.7rem;
    font-size: 0.86rem;
    color: var(--muted-ink);
}

.lscwc__dictation ol {
    margin: 0;
    padding-left: 1.3rem;
    line-height: 2.1;
}

.lscwc__foot {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    justify-content: space-between;
    margin-top: 1.1rem;
    font-size: 0.87rem;
    color: var(--muted-ink);
}

.lscwc__foot p {
    margin: 0;
}

/*
 * On a phone seven columns is unreadable, so the word sits on its own line with
 * the five practice boxes in a row beneath it and the test box full width. This
 * is a screen compromise only - the printed sheet always keeps the true grid.
 */
@media (max-width: 48rem) {
    .lscwc__legend {
        display: none;
    }

    .lscwc__row {
        grid-template-columns: repeat(5, 1fr);
        grid-template-areas:
            "word word word word word"
            "w1   w2   w3   w4   w5"
            "test test test test test";
        row-gap: 0.2rem;
        padding-bottom: 0.5rem;
    }

    .lscwc__word { grid-area: word; border-right: 0; }
    .lscwc__write:nth-of-type(1) { grid-area: w1; }
    .lscwc__write:nth-of-type(2) { grid-area: w2; }
    .lscwc__write:nth-of-type(3) { grid-area: w3; }
    .lscwc__write:nth-of-type(4) { grid-area: w4; }
    .lscwc__write:nth-of-type(5) { grid-area: w5; }
    .lscwc__write { padding-top: 1.3rem; }
    .lscwc__write:last-of-type { border-right: 0; }

    /* The correction card sits under the whole row on a phone too. */
    .checker {
        grid-column: 1 / -1;
        grid-row: 4;
    }

    .lscwc__test {
        grid-area: test;
        border-left: 0;
        border-top: 2px solid var(--slate);
        padding-top: 1.5rem;
        margin: 0 0.85rem;
    }
}

/* Printing: no site furniture, no shadows, never split a word across pages. */
@media print {
    .lscwc__actions,
    .lscwc__foot a,
    /* Nothing interactive belongs on paper. The flap becomes a fold line again
       and the boxes go back to blank ruled lines for handwriting. */
    .practice,
    .practice__grownup,
    .lscwc__cover,
    .lscwc__flap,
    .lscwc__input,
    .lscwc__go {
        display: none !important;
    }

    .lscwc__foldhint {
        display: block;
    }

    .lscwc__row.is-quiet,
    .lscwc__row.is-active {
        opacity: 1;
        background: transparent;
        box-shadow: none;
    }

    .lscwc__write.is-done,
    .lscwc__write.is-open {
        background: transparent;
    }

    .lscwc__write.is-done::after {
        content: "";
    }

    .lscwc__sheet {
        box-shadow: none;
    }

    .lscwc__row {
        break-inside: avoid;
        min-height: 3.5rem;
    }

    /* Keep the tint on paper: a grey wash prints legibly, colour may not. */
    .lscwc__test {
        background: #f2f2f2;
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }

    .lscwc__legend {
        background: #fff;
        color: var(--ink);
        border-bottom: 1.5px solid var(--ink);
    }
}

/* --- programme dashboard, level picker and marking list --- */

.prog-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 1rem;
    margin-top: 1.25rem;
}

.prog-card {
    padding: 1rem 1.1rem;
    background: #fff;
    border: 1px solid var(--rule);
    border-top: 3px solid var(--brass);
}

.prog-card__name {
    font-family: var(--font-display);
    font-size: 1.15rem;
    margin: 0 0 0.35rem;
}

.prog-card__levels {
    margin: 0 0 0.75rem;
    padding-left: 1.1rem;
}

.prog-card--choice {
    display: block;
    cursor: pointer;
}

.prog-card--choice:has(input:checked) {
    border-color: var(--slate);
    border-top-color: var(--slate);
    box-shadow: 0 0 0 2px rgba(47, 111, 208, 0.12);
}

.ladder__now {
    padding: 1rem 1.15rem;
    margin: 1.25rem 0 2rem;
    background: #fff;
    border: 1px solid var(--rule);
    border-left: 3px solid var(--slate);
}

.ladder__now-title {
    font-size: 0.78rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted-ink);
    margin: 0 0 0.3rem;
}

.ladder__now-what {
    font-family: var(--font-display);
    font-size: 1.3rem;
    margin: 0 0 0.8rem;
}

.ladder__now-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.ladder__history-title {
    font-family: var(--font-display);
    font-size: 1.1rem;
}

.ladder__pill {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    font-size: 0.75rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border: 1px solid var(--rule);
    border-radius: 2px;
    color: var(--muted-ink);
}

.ladder__pill--pass {
    color: #2c5c3c;
    border-color: #2c5c3c;
}

.ladder__pill--fail {
    color: var(--red-pen);
    border-color: var(--red-pen);
}

.marking__list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: 0.4rem;
    margin: 1.25rem 0;
    padding: 0;
    list-style: none;
}

.marking__item label {
    display: flex;
    gap: 0.6rem;
    align-items: center;
    padding: 0.6rem 0.8rem;
    background: #fff;
    border: 1px solid var(--rule);
    cursor: pointer;
}

.marking__item label:has(input:checked) {
    border-color: #2c5c3c;
    background: rgba(44, 92, 60, 0.05);
}

.marking__word {
    font-family: var(--font-display);
    font-size: 1.05rem;
}

/* ---------------------------------------------------------------------------
   Online dictation test
   The words are never shown, so the listen button carries the weight here.
   --------------------------------------------------------------------------- */

.dictation { max-width: 44rem; }

.dictation__intro { color: var(--muted-ink); max-width: 34rem; }

.dictation__note {
  border-left: 3px solid var(--brass);
  padding-left: .75rem;
  font-style: italic;
  color: var(--muted-ink);
}

.dictation__unsupported {
  border: 1px solid var(--red-pen);
  background: rgba(239, 75, 92, .06);
  border-radius: 3px;
  padding: .75rem 1rem;
  margin-bottom: 1.25rem;
}

.dictation__list {
  list-style: decimal;
  padding-left: 2rem;
  margin: 1.5rem 0;
}

.dictation__item {
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .5rem 0;
  border-bottom: 1px solid var(--rule);
}

.dictation__listen {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  border: 1px solid var(--slate);
  background: var(--slate);
  color: var(--paper);
  border-radius: 3px;
  padding: .35rem .75rem;
  font-size: .9rem;
  cursor: pointer;
  flex: 0 0 auto;
}

.dictation__listen:hover { background: #1f272b; }
.dictation__listen.is-failed { background: var(--red-pen); border-color: var(--red-pen); }

.dictation__answer {
  flex: 1 1 auto;
  min-width: 0;
  border: 0;
  border-bottom: 2px solid var(--rule);
  background: transparent;
  font-family: var(--font-display, inherit);
  font-size: 1.25rem;
  padding: .2rem .25rem;
}

.dictation__answer:focus {
  outline: none;
  border-bottom-color: var(--brass);
}

.dictation__sentence {
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--muted-ink);
  border-radius: 3px;
  padding: .3rem .6rem;
  font-size: .8rem;
  cursor: pointer;
  flex: 0 0 auto;
}

@media (max-width: 480px) {
  .dictation__item { flex-wrap: wrap; }
  .dictation__answer { flex-basis: 100%; order: 3; }
}

/*
 * The visible way to save a go. Enter alone was invisible to a child (and to an
 * adult) — nothing on screen said the keyboard was the mechanism.
 */
.lscwc__go {
    flex: 0 0 auto;
    margin-left: 0.3rem;
    padding: 0.05rem 0.4rem;
    font-family: var(--font-body);
    font-size: 0.62rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #fff;
    background: var(--slate);
    border: 0;
    border-radius: 2px;
    cursor: pointer;
}

.lscwc__go:hover,
.lscwc__go:focus-visible {
    background: var(--ink);
}

/* Make the one live cell genuinely obvious among seventy ruled lines. */
.lscwc__write.is-open {
    background: rgba(245, 165, 36, 0.16);
    box-shadow: inset 0 0 0 2px var(--brass);
}

/* ==========================================================================
   The screen sheet's interactive parts
   --------------------------------------------------------------------------
   The bell, the stacked attempts, the child's own marking card and the finish
   panel. These are screen-only by definition, so the print block at the end
   hides every one of them.
   ========================================================================== */

/* --- the bell: the 'Say' step for a child working alone --- */
.lscwc__bell {
    display: inline-flex;
    align-items: center;
    gap: 0.28rem;
    margin-left: 0.4rem;
    padding: 0.22rem 0.6rem;
    font-family: var(--font-body);
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1.2;
    color: #fff;
    background: var(--grape);
    border: 0;
    border-radius: 999px;
    cursor: pointer;
    transition: transform 0.15s ease;
}

.lscwc__bell-label {
    white-space: nowrap;
}

.lscwc__bell:hover,
.lscwc__bell:focus-visible {
    transform: scale(1.06);
}

/*
 * A faded row must never fade its own sound button. A child working alone
 * needs to hear any word on the list, not only the active one.
 */
.lscwc__row.is-quiet .lscwc__bell {
    opacity: 1;
}

/*
 * Every attempt, stacked. A wrong try is struck through in coral and STAYS on
 * the page under the next one. That is the record of what actually happened,
 * and it is what tells a parent which words are genuinely shaky.
 */
.lscwc__attempt {
    display: block;
    width: 100%;
    font-family: var(--font-display);
    font-size: 0.82rem;
    line-height: 1.35;
    word-break: break-all;
}

.lscwc__attempt.is-right {
    color: var(--grass);
    font-weight: 600;
}

.lscwc__attempt.is-wrong {
    color: var(--red-pen);
    text-decoration: line-through;
    opacity: 0.85;
}

/* A cell can now hold several stacked attempts, so it stacks rather than rows. */
.lscwc__write {
    flex-direction: column;
    justify-content: flex-end;
    gap: 0.05rem;
}

.lscwc__write.is-done {
    background: rgba(47, 182, 114, 0.12);
}

.lscwc__write.is-done::after {
    content: "\2713";
    align-self: flex-start;
    color: var(--grass);
}

/* Three tries used and still wrong. Marked, not scolded. */
.lscwc__write.is-wrong {
    background: rgba(239, 75, 92, 0.09);
}

.lscwc__write.is-open {
    background: rgba(245, 165, 36, 0.2);
    box-shadow: inset 0 0 0 2px var(--brass);
}

/*
 * The check step, done by the child.
 *
 * This used to be a fixed overlay in the middle of the screen, which meant the
 * correction appeared miles away from the cell the child had just written in.
 * It now sits INSIDE the row, spanning the full width directly beneath the
 * word they got wrong, so the mistake and the fix are in the same place their
 * eyes already are.
 */
.checker {
    grid-column: 1 / -1;
    padding: 0.4rem 0.5rem 0.7rem;
    background: #fff;
    border-top: 2px dashed var(--rule);
}

.checker__card {
    width: 100%;
    padding: 0.9rem 1rem;
    text-align: center;
    background: var(--paper);
    border-radius: 12px;
    border-left: 6px solid var(--brass);
    box-shadow: 0 4px 14px rgba(27, 42, 58, 0.12);
}

.checker__lead {
    margin: 0 0 0.5rem;
    font-family: var(--font-display);
    font-size: 1rem;
    color: var(--ink);
}

/*
 * Inline, the two spellings read better side by side than stacked: it keeps the
 * whole card short enough to sit inside a row without pushing the next word off
 * the screen.
 */
.checker__compare {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 2rem;
    justify-content: center;
    align-items: flex-end;
}

.checker__label {
    margin: 0 0 0.1rem;
    font-size: 0.7rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--muted-ink);
}

/* What they wrote and what the word is, big enough to compare letter by letter. */
.checker__yours,
.checker__truth {
    margin: 0;
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    word-break: break-all;
}

.checker__yours { color: var(--slate); }
.checker__truth { color: var(--grape); }

/*
 * The corrected spelling, letter by letter. Only the letters that differ are
 * marked, so the eye goes straight to the one that slipped rather than
 * scanning a word that is entirely red.
 */
.checker__yours .letter,
.checker__truth .letter {
    display: inline-block;
    padding: 0 0.04em;
    border-radius: 4px;
}

.checker__yours .letter.is-off {
    color: #fff;
    background: var(--red-pen);
}

.checker__truth .letter.is-off {
    color: #fff;
    background: var(--grass);
}

/* Letters they left off the end. Shown as dots, not as the actual letters. */
.checker__yours .letter.is-missing {
    color: var(--red-pen);
    background: rgba(0, 0, 0, 0.05);
}

.checker__buttons {
    display: flex;
    gap: 0.6rem;
    margin-top: 1.2rem;
}

.checker__tick,
.checker__cross {
    flex: 1 1 0;
    padding: 0.65rem 0.5rem;
    font-family: var(--font-body);
    font-size: 0.95rem;
    font-weight: 600;
    color: #fff;
    border: 0;
    border-radius: 10px;
    cursor: pointer;
}

.checker__tick { background: var(--grass); }
.checker__cross { background: var(--red-pen); }

/*
 * The tick is now the only button on the card — the marking is already done,
 * so this press means "I have read the correction". It is sized generously
 * because it is the single thing to do, and a child should not have to hunt.
 */
.checker__card > .checker__tick {
    width: auto;
    min-width: 16rem;
    margin-top: 0.8rem;
    padding: 0.7rem 1.4rem;
    font-size: 1rem;
}

.checker__tick:hover, .checker__cross:hover { filter: brightness(1.08); }

.checker__verdict {
    margin: 0.7rem 0 0;
    font-size: 0.95rem;
    line-height: 1.45;
}

/* Right first time. */
.checker__verdict.is-agreed { color: var(--grass); font-weight: 600; }

/* Wrong, corrected on the spot. Stated plainly, without telling them off. */
.checker__verdict.is-corrected { color: var(--slate); font-weight: 600; }

.checker__next {
    margin-top: 1rem;
    padding: 0.6rem 1.4rem;
    font-family: var(--font-body);
    font-size: 0.95rem;
    font-weight: 600;
    color: #fff;
    background: var(--slate);
    border: 0;
    border-radius: 10px;
    cursor: pointer;
}

/* --- finish: how the week actually went --- */
.finish {
    margin-top: 1.5rem;
    text-align: center;
}

.finish__button {
    padding: 0.8rem 1.8rem;
    font-family: var(--font-display);
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--ink);
    background: var(--sunshine);
    border: 0;
    border-radius: 999px;
    cursor: pointer;
    box-shadow: 0 4px 0 #d9b526;
}

.finish__button:active { transform: translateY(2px); box-shadow: 0 2px 0 #d9b526; }

.finish__result {
    margin: 1.25rem auto 0;
    max-width: 30rem;
    padding: 1.25rem;
    background: #fff;
    border: 2px solid var(--rule);
    border-radius: 14px;
}

.finish__score {
    margin: 0 0 0.35rem;
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--slate);
}

.finish__note { margin: 0; color: var(--muted-ink); }

/* Words worth another look before the test. */
.finish__tricky {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    justify-content: center;
    margin: 0.9rem 0 0;
    padding: 0;
    list-style: none;
}

.finish__tricky li {
    padding: 0.15rem 0.6rem;
    font-family: var(--font-display);
    font-size: 0.9rem;
    color: #8a2a35;
    background: rgba(239, 75, 92, 0.12);
    border-radius: 999px;
}

.practice__fill { background: var(--sunshine); }

@media (prefers-reduced-motion: reduce) {
    .lscwc__bell { transition: none; }
}

/* None of this belongs on paper — and sheet_print.html is the real printable. */
@media print {
    .lscwc__bell,
    .lscwc__attempt,
    .checker,
    .finish {
        display: none !important;
    }
}

/* ---------------------------------------------------------------------------
   The mistake review
   ---------------------------------------------------------------------------
   Deliberately quieter than the sheet. The sheet is a child's workbook and can
   be bright; this is a parent reading a summary, so the words themselves carry
   the emphasis and nothing else competes with them. */

.review {
    max-width: 60rem;
    margin: 0 auto;
    padding: 1.5rem 1rem 3rem;
}

.review__filters {
    margin: 1rem 0 2rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.review__block {
    margin: 0 0 2.5rem;
}

.review__title {
    font-size: 1.15rem;
    margin: 0 0 0.85rem;
    padding-bottom: 0.4rem;
    border-bottom: 2px solid var(--rule);
}

/* The repeat-offender words. Sized up because these are the answer to the
   question the page exists to ask. */
.review__words {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
}

.review__word {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    padding: 0.45rem 0.8rem;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: 0.5rem;
}

.review__word-text {
    font-weight: 600;
    font-size: 1.05rem;
    color: var(--ink);
}

.review__word-count {
    font-size: 0.8rem;
    color: var(--muted-ink);
}

.review__patterns {
    list-style: none;
    margin: 0;
    padding: 0;
}

.review__pattern {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    padding: 0.5rem 0;
    border-bottom: 1px dotted var(--rule);
}

.review__pattern-count {
    font-weight: 600;
    color: var(--slate);
}

.review__table {
    font-size: 0.92rem;
}

.review__cell-word {
    font-weight: 600;
}

/* What the child actually wrote, in the marking pen. */
.review__cell-given {
    color: var(--red-pen);
}

.review__cell-where {
    color: var(--muted-ink);
    font-size: 0.85rem;
}

.review__empty {
    padding: 2rem 0;
}

.review__back {
    margin-top: 2rem;
}

@media print {
    .review__filters,
    .review__back {
        display: none;
    }
}

/* --- Picking words from the bank ------------------------------------------
   A dense grid, because a parent scanning for the words they want is doing a
   visual search: many small targets beat a long scrolling list. */
.word-pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: .5rem;
}
.word-pick {
  display: block;
  position: relative;
  padding: .5rem .6rem;
  border: 1px solid var(--rule);
  border-radius: .4rem;
  background: var(--paper);
  cursor: pointer;
}
.word-pick:hover { border-color: var(--slate); }
.word-pick__box { position: absolute; opacity: 0; pointer-events: none; }
.word-pick__word { display: block; font-weight: 600; }
.word-pick__meta { display: block; font-size: .75rem; color: var(--muted-ink); }
.word-pick:has(.word-pick__box:checked) {
  border-color: var(--slate);
  box-shadow: inset 0 0 0 2px var(--slate);
}
/* Already proved. Dimmed rather than hidden: a parent may still want it. */
.word-pick--known { opacity: .55; }
.word-pick--known .word-pick__word { text-decoration: line-through; }

/* ---------------------------------------------------------------------------
   Checking the dictation sentences
   ---------------------------------------------------------------------------
   A grown-up screen, not a child's one: quiet, roomy, and built for reading
   fifty short sentences without fatigue. The word being taught is set large in
   the display face so the eye lands on it first and the sentence is judged
   against it, which is the whole job.
--------------------------------------------------------------------------- */

.sentence-tally .progress {
    background: var(--rule);
}

.sentence-card__word {
    font-family: var(--font-display);
    font-size: 2rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--ink);
}

.sentence-card__input {
    font-family: var(--font-body);
    font-size: 1.15rem;
    line-height: 1.6;
    border-color: var(--rule);
}

.sentence-card__input:focus {
    border-color: var(--brass);
    box-shadow: 0 0 0 .2rem rgba(176, 141, 87, .25);
}

/* ---------------------------------------------------------------------------
   Checking screens \u2014 sentences and rule tags
   ---------------------------------------------------------------------------
   Both are the same job: one item at a time, with a running tally so the day's
   work has a visible end. The tally is deliberately plain; it is a progress
   marker, not a trophy. */

.check-tally {
    padding: 0.6rem 0.9rem;
    background: var(--chalk);
    border-left: 4px solid var(--slate);
    border-radius: 0.35rem;
    font-size: 0.95rem;
}

.rule-check-card {
    border: 2px solid var(--rule);
    border-radius: 0.6rem;
}

/* The word is the thing being judged, so it gets the size. Everything else on
   the card is supporting detail. */
.rule-check-word {
    font-family: var(--font-display);
    font-size: 2.1rem;
    font-weight: 700;
    color: var(--ink);
    line-height: 1.1;
}

/* Rule chips beside a word on the practice sheet. Deliberately quiet: the word
   is what the child is learning, and a loud label beside it competes with the
   thing that matters. Off by default, per child. */
.lscwc__rules {
    display: block;
    margin-top: 0.15rem;
}

.lscwc__rule {
    display: inline-block;
    margin: 0.1rem 0.2rem 0 0;
    padding: 0.05rem 0.4rem;
    font-size: 0.7rem;
    line-height: 1.5;
    color: var(--muted-ink);
    background: var(--chalk);
    border: 1px solid var(--rule);
    border-radius: 0.6rem;
}

/* Never on paper. A printed sheet with the rules on it is a cheat sheet, and a
   printed test with them on it is most of the answer. */
@media print {
    .lscwc__rules { display: none !important; }
}

/* ---------------------------------------------------------------------------
   Games
   A games band on each subject page, carrying that subject's own accent so it
   reads as part of the subject rather than a bolted-on extra: amber ruling for
   spelling, pencil blue for times tables, matching the .ws-subject-- bands.
   --------------------------------------------------------------------------- */

.ws-games {
    margin: 2rem 0;
    padding: 1.25rem 1.5rem;
    border: 1px solid var(--rule);
    border-radius: 10px;
    background: var(--paper);
}

.ws-games__title {
    margin: 0 0 .25rem;
    font-family: var(--font-display);
}

.ws-games__lead {
    margin: 0 0 .75rem;
    color: var(--muted-ink);
}

.ws-subject--spelling.ws-games { border-left: 5px solid var(--brass); }
.ws-subject--multiplication.ws-games { border-left: 5px solid var(--slate); }

.ws-game-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.ws-game-list__item {
    padding: .75rem 0;
    border-bottom: 1px solid var(--rule);
}

.ws-game-list__item:last-child { border-bottom: 0; }

.ws-game-list__link {
    font-family: var(--font-display);
    font-weight: 600;
}

.ws-game-list__summary { margin: .25rem 0 0; }

.ws-game-list__meta {
    margin: .15rem 0 0;
    font-size: .875rem;
    color: var(--muted-ink);
}

/* The "N games to play together" line on the subject list page. */
.ws-subject__games {
    margin: .75rem 0 0;
    font-size: .9375rem;
}

/* A single game's page. Steps are the meat, so they get room to breathe. */
.game__meta { margin-bottom: 1rem; }

.game__kit,
.game__variations { padding-left: 1.25rem; }

.game__steps { padding-left: 1.5rem; }

.game__steps li { margin-bottom: .6rem; }

.game__kit li,
.game__variations li { margin-bottom: .35rem; }

/* ---------------------------------------------------------------------------
   Game question bank

   A question-and-answer game carries a bank of questions grouped by kind. Laid
   out in columns so forty questions read as a browsable list rather than an
   intimidating scroll, and the harder ones are flagged inline so a parent can
   pick by eye without switching screens.
   --------------------------------------------------------------------------- */

.game-q {
    columns: 2;
    column-gap: 2rem;
    margin-bottom: 1.5rem;
}

@media (max-width: 640px) {
    .game-q { columns: 1; }
}

.game-q__group {
    break-inside: avoid;
    margin-bottom: 1.25rem;
}

.game-q__heading {
    font-family: var(--font-display);
    font-size: 0.95rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted-ink);
    margin: 0 0 0.4rem;
    padding-bottom: 0.25rem;
    border-bottom: 2px solid var(--rule);
}

.game-q__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.game-q__item {
    padding: 0.3rem 0 0.3rem 0.9rem;
    border-left: 3px solid var(--rule);
    margin-bottom: 0.2rem;
    line-height: 1.4;
}

.game-q__item--harder {
    border-left-color: var(--brass);
}

.game-q__text { display: block; }

.game-q__flag {
    display: inline-block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    background: var(--brass);
    color: var(--paper);
    border-radius: 3px;
    padding: 0 0.35rem;
    vertical-align: 1px;
}

.game-q__note {
    display: block;
    font-size: 0.85rem;
    color: var(--muted-ink);
    font-style: italic;
}

/* ---------------------------------------------------------------------------
   Which lists a game suits.

   Games are a guide for grown-ups, not a ladder a child climbs. Playdough
   suits a five-year-old having a break from the pencil; it is a poor use of a
   Year 8 afternoon. So each game says who it is for, and this styles that
   note. Quiet on purpose - it is guidance, not a warning.
   --------------------------------------------------------------------------- */

.game__suits {
  margin: 1.25rem 0 0;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--brass);
  background: color-mix(in srgb, var(--brass) 7%, var(--paper));
  border-radius: 0 6px 6px 0;
}

.game__suits-heading {
  margin: 0 0 0.4rem;
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-ink);
}

.game__suits-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.game__suits-tags li {
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--paper);
  font-size: 0.85rem;
}

.game__suits-note {
  margin: 0.5rem 0 0;
  font-size: 0.9rem;
  color: var(--muted-ink);
}

/* The same information on the subject page list, kept to one compact line so
   a parent can scan seven games without seven paragraphs. */

.ws-game-list__suits {
  margin: 0.25rem 0 0;
  font-size: 0.85rem;
  color: var(--muted-ink);
}

.ws-game-list__suits-label {
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-size: 0.72rem;
}

.ws-game-list__suit {
  display: inline-block;
  margin-left: 0.3rem;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--paper);
}

/* ------------------------------------------------------------------ */
/* Parent quick-reference guides                                       */
/*                                                                     */
/* The sound panel is the signature element: three words side by side, */
/* one outlined box per SOUND. The boxes are deliberately uniform so   */
/* the eye compares box count against letter count and notices they    */
/* disagree.                                                           */
/* ------------------------------------------------------------------ */

.sound-panel {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin: 0 0 1.5rem;
}

.sound-panel__col {
    flex: 1 1 12rem;
    padding: 1rem;
    background: var(--paper);
    border: 1px solid var(--rule);
    border-radius: 4px;
}

.sound-panel__word {
    margin: 0 0 0.6rem;
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--ink);
}

.sound-panel__boxes {
    display: flex;
    gap: 0.35rem;
    margin: 0 0 0.6rem;
}

.sound-panel__box {
    min-width: 2.4rem;
    padding: 0.5rem 0.3rem;
    border: 2px solid var(--slate);
    border-radius: 3px;
    text-align: center;
    font-weight: 600;
    color: var(--ink);
    background: #fff;
}

.sound-panel__count {
    margin: 0 0 0.35rem;
    font-weight: 600;
    color: var(--brass);
}

.sound-panel__note {
    margin: 0;
    font-size: 0.9rem;
    color: var(--muted-ink);
}

/* The glossary itself. Term names carry the display face so they read as
   headings without needing a real heading level for each one. */

.guide-terms dt {
    margin-top: 1rem;
    font-family: var(--font-display);
    font-size: 1.1rem;
    color: var(--ink);
}

.guide-terms dd {
    margin: 0.2rem 0 0;
    border-left: 3px solid var(--rule);
    padding-left: 0.85rem;
}

.guide-terms__example {
    font-style: italic;
    color: var(--muted-ink);
}

/* ---------------------------------------------------------------------------
   The maths ladder
   ---------------------------------------------------------------------------
   Carried facts are tinted with --brass and labelled, exactly as carried
   spelling words are on the weekly sheet. A child should be able to tell at a
   glance which of these they have met before, and it should look the same in
   both subjects. */

.fact-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.fact-list__item {
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 0.4rem 0.7rem;
  background: var(--paper);
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
}

.fact-list__item--again {
  border-color: var(--brass);
  background: rgba(180, 141, 62, 0.08);
}

.fact-list__item--slow {
  border-color: var(--slate);
}

.fact-list__sum {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.fact-list__again,
.fact-list__seconds {
  font-size: 0.75rem;
  color: var(--muted-ink);
}

/* The one thing on the screen, made big enough to be the only thing looked at.
   A child answering a sum should not be hunting for the box. */

.fact-practice__card,
.fact-test__card {
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 1.5rem;
  max-width: 30rem;
  text-align: center;
  background: var(--paper);
}

.fact-practice__progress,
.fact-test__progress {
  font-size: 0.8rem;
  color: var(--muted-ink);
  margin: 0 0 0.5rem;
}

.fact-practice__sum,
.fact-test__sum {
  font-size: 2.75rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin: 0 0 1rem;
}

.fact-practice__input,
.fact-test__input {
  font-size: 1.75rem;
  width: 6rem;
  text-align: center;
  border: 2px solid var(--slate);
  border-radius: 4px;
  padding: 0.3rem 0.4rem;
  margin-right: 0.5rem;
}

.fact-practice__verdict,
.fact-test__note {
  margin: 1rem 0 0;
  font-weight: 600;
}

.fact-practice__verdict--right { color: var(--slate); }
.fact-practice__verdict--quick { color: var(--brass); }
.fact-practice__verdict--wrong { color: var(--ink); }

/* Failures are shown, never swallowed. A silent one looks to a child like a
   broken button, and they will just keep pressing it. */
.fact-practice__verdict--error,
.fact-test__note--error {
  color: #b3261e;
}

.fact-practice__next { margin-top: 0.75rem; }

/* The speaker sits under the sum rather than beside it, so it never crowds the
   numbers — the sum is the thing being read, and it has to stay the biggest
   thing on the card. */
.fact-practice__say {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin: 0 0 1rem;
}

.fact-practice__speak {
  white-space: nowrap;
}

/* Held narrow on purpose. This is a quiet setting a child may never touch, and
   a full-width select would read as the main thing to do on the page. */
.fact-practice__wording {
  max-width: 11rem;
  border-color: var(--rule);
  color: var(--muted-ink);
}

.fact-practice__finished-line {
  font-size: 1.25rem;
  color: var(--ink);
  margin-bottom: 0.75rem;
}

/* The two retry buttons sit side by side but wrap on a narrow screen, so
   neither ends up half off the edge on a phone. */
.fact-practice__again {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 1rem;
}

.fact-mark {
  list-style: none;
  padding: 0;
  margin: 0;
}

.fact-mark__item {
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--rule);
  font-variant-numeric: tabular-nums;
}

.fact-mark__item--again {
  border-left: 3px solid var(--brass);
}

.fact-tables { display: flex; flex-wrap: wrap; }

@media (max-width: 480px) {
  .fact-practice__sum,
  .fact-test__sum { font-size: 2.25rem; }
  .fact-practice__card,
  .fact-test__card { padding: 1rem; }
}

/* The interactive screens are not printables. If one is printed by accident,
   hide the working parts rather than wasting a page on a dead input box. */
@media print {
  .fact-practice,
  .fact-test { display: none; }
}

/* Practice pack: the note about facts that come round twice.
   Deliberately quiet -- brass rather than red. A child who missed a fact
   yesterday does not need it flagged like an error, just explained. */
.fact-practice__repeats {
  border-left: 3px solid var(--brass);
  padding-left: 0.75rem;
  margin-bottom: 1rem;
  color: var(--muted-ink);
  font-size: 0.95rem;
}

/* Listen-first mode: what stands in for the sum before it has been heard.
   Sized like the sum it replaces so the card does not jump when the fact
   appears -- a shifting layout is what makes a child lose their place. */
.fact-practice__hidden {
  font-size: 1.5rem;
  color: var(--muted-ink);
  margin: 0.5rem 0;
  min-height: 2.5rem;
}
.fact-practice__mode {
  max-width: 14rem;
}

/* ---------------------------------------------------------------------------
   Game categories

   The heading is deliberately quieter than the section title above it: the
   groups are a way of finding a game, not three separate features. The tag
   repeats the category on each game because a game listed under two headings
   should say so, otherwise it reads as a duplicate entry by mistake.
   --------------------------------------------------------------------------- */
.ws-games__group {
    margin: 1.75rem 0 0.5rem;
    color: var(--slate);
    letter-spacing: 0.02em;
}

.ws-games__group:first-of-type {
    margin-top: 1rem;
}

.ws-game-list__cats,
.game__cats {
    margin: 0.35rem 0 0;
}

.ws-game-cat {
    display: inline-block;
    margin: 0 0.3rem 0.3rem 0;
    padding: 0.05rem 0.45rem;
    border: 1px solid var(--rule);
    border-radius: 0.6rem;
    background: var(--paper);
    color: var(--muted-ink);
    font-size: 0.75rem;
    letter-spacing: 0.03em;
}

.game__kit-note {
    margin-bottom: 0.4rem;
}

.game__kit-links {
    margin: 0;
    padding-left: 1.2rem;
}

/* ---------------------------------------------------------------------------
   Comprehension: a reading laid out as a real textbook page.

   Week two teaches that the furniture of a page - banner, subheadings,
   pictures, captions - tells you the topic before you read a word. It used to
   render as one plain block with "[PICTURE: a fish]" typed into a paragraph,
   which taught nothing. So the furniture is now real furniture.

   Readings with no spread still render as plain prose, which is correct for
   the chronicle entry and the method box: those are deliberately bare, and
   that contrast is the lesson.
   --------------------------------------------------------------------------- */
.comp-spread {
    background: #fff;
    border: 1px solid var(--rule);
    border-radius: 4px;
    padding: 1.25rem 1.25rem 0.75rem;
}

.comp-spread__banner {
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 4vw, 2rem);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-align: center;
    color: var(--ink);
    margin: 0 0 0.5rem;
    padding-bottom: 0.5rem;
    border-bottom: 3px double var(--ink);
}

.comp-spread__standfirst {
    font-size: 1.05rem;
    font-style: italic;
    color: var(--muted-ink);
    margin: 0 0 1.25rem;
}

.comp-spread__section + .comp-spread__section { margin-top: 1.25rem; }

.comp-spread__heading {
    font-family: var(--font-display);
    font-size: 0.95rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--slate);
    margin: 0 0 0.5rem;
    padding-bottom: 0.25rem;
    border-bottom: 1px solid var(--rule);
}

.comp-spread__body--figure {
    display: flex;
    gap: 1.25rem;
    align-items: flex-start;
}

.comp-spread__text { flex: 1 1 auto; min-width: 0; }
.comp-spread__text p { margin-bottom: 0.6rem; }
.comp-spread__text p:last-child { margin-bottom: 0; }

.comp-fig {
    flex: 0 0 11rem;
    margin: 0;
    border: 1px solid var(--rule);
    border-radius: 3px;
    padding: 0.5rem;
    background: var(--paper);
}

.comp-fig svg {
    width: 100%;
    height: auto;
    display: block;
    color: var(--ink);
}

.comp-fig figcaption {
    font-size: 0.8rem;
    font-style: italic;
    color: var(--muted-ink);
    text-align: center;
    margin-top: 0.35rem;
}

/* A figure beside a narrow column squeezes the text to nothing, so on small
   screens it drops below and goes full width. */
@media (max-width: 575.98px) {
    .comp-spread__body--figure { display: block; }
    .comp-fig { margin-top: 0.75rem; width: 100%; }
}

/* ---------------------------------------------------------------------------
   Document skins.

   Weeks 1 and 2 teach that you can tell what a text IS before you read a word
   of it, from its furniture alone. A safety notice does not look like a poem,
   and a news report does not look like a chat log. That lesson only works if
   the pages on this site actually look different from each other, and until
   now every reading rendered as the same column of grey prose - which quietly
   taught the opposite.

   So each `document_kind` gets its own skin. The skin carries no information
   of its own; it is the shape a child recognises before reading.

   `.comp-doc--plain` is deliberately given NOTHING. The readings that use it -
   the unbroken block, the chronicle entry, the paragraphs with no diagram -
   are the controls in the experiment. They are supposed to feel harder. Do not
   style them.
   --------------------------------------------------------------------------- */

.comp-doc { margin-bottom: 0.5rem; }

/* A notice shouts. Heavy top rule, boxed, generous padding, and the first line
   set as a label so it reads as posted rather than written. */
.comp-doc--notice {
    border: 1px solid var(--ink);
    border-top: 6px solid var(--ink);
    border-radius: 2px;
    padding: 1rem 1.15rem;
    background: #fff;
}

.comp-doc--notice .comp-passage > p:first-child {
    font-family: var(--font-display);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 0.95rem;
    margin-bottom: 0.6rem;
}

/* A news report has a masthead rule and sets in columns. */
.comp-doc--news {
    border-top: 3px double var(--ink);
    padding-top: 0.85rem;
}

.comp-doc--news .comp-passage > p:first-child {
    font-variant-caps: small-caps;
    letter-spacing: 0.06em;
    color: var(--muted-ink);
    font-size: 0.9rem;
}

@media (min-width: 768px) {
    .comp-doc--news .comp-passage {
        column-count: 2;
        column-gap: 1.75rem;
        column-rule: 1px solid var(--rule);
    }
}

/* An article leads with a drop cap, the way a magazine opens. */
.comp-doc--article .comp-passage > p:first-child::first-letter {
    float: left;
    font-family: var(--font-display);
    font-size: 3.1rem;
    line-height: 0.82;
    font-weight: 700;
    padding: 0.1rem 0.5rem 0 0;
    color: var(--ink);
}

/* A chat log is turns, not prose. The template splits it on 'Name:' and each
   turn becomes a bubble, alternating side so the two voices are obvious. */
.comp-chat { display: flex; flex-direction: column; gap: 0.5rem; }

.comp-chat__turn { max-width: 82%; }
.comp-chat__turn--right { align-self: flex-end; text-align: right; }

.comp-chat__who {
    display: block;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--muted-ink);
    margin-bottom: 0.15rem;
}

.comp-chat__bubble {
    display: inline-block;
    text-align: left;
    border: 1px solid var(--rule);
    border-radius: 12px;
    padding: 0.45rem 0.7rem;
    background: var(--paper);
}

.comp-chat__turn--right .comp-chat__bubble {
    background: #fff;
    border-color: var(--ink);
}

/* ------------------------------------------------------------------
   Real texts.

   Most passages in this programme are our own words on a real topic.
   A few are the real thing, quoted verbatim - an out-of-copyright
   newspaper report, a dictionary entry, a poem, a Creative Commons
   article. Saying so plainly changes how a child reads it: this is not
   a school exercise, it is a page an adult wrote for adults, and it is
   allowed to be harder than they are used to.
   ------------------------------------------------------------------ */
.comp-real-badge {
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-weight: 600;
    vertical-align: 0.15em;
}

/* Attribution is a licence condition, not decoration. The Conversation is
   CC BY-ND and Wiktionary is CC BY-SA, and both require visible credit.
   Quiet, but never hidden and never behind a toggle. */
.comp-attribution {
    font-size: 0.78rem;
    line-height: 1.4;
}

.comp-attribution__licence { white-space: nowrap; }

/* A worksheet is a frame with room to write in. */
.comp-doc--worksheet {
    border: 2px solid var(--ink);
    border-radius: 3px;
    padding: 1rem 1.15rem;
    background: #fff;
}

.comp-doc--worksheet .comp-passage {
    font-variant-numeric: tabular-nums;
}

/* A chronicle is a narrow justified serif measure with the year in the gutter. */
.comp-doc--chronicle .comp-passage {
    max-width: 34rem;
    text-align: justify;
    hyphens: auto;
    border-left: 3px solid var(--rule);
    padding-left: 1rem;
}

/* Verse is centred, and its line breaks are the point, so nothing is justified
   and nothing is collapsed. */
.comp-doc--poem .comp-passage {
    text-align: center;
    line-height: 1.9;
    font-style: italic;
}

/* Instructions are steps with tools listed first. */
.comp-doc--instructions .comp-passage {
    border-left: 4px solid var(--slate);
    padding-left: 1rem;
}

.comp-doc--instructions .comp-passage > p {
    padding-left: 0.25rem;
}

/* A lab report: ruled headings, table and key sitting inline with the text. */
.comp-doc--experiment .comp-spread { border-width: 2px; }

.comp-doc--experiment .comp-spread__banner {
    font-size: clamp(1.15rem, 3vw, 1.4rem);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    border-bottom-style: solid;
    border-bottom-width: 2px;
}

/* A reference list is term-and-meaning, so it sets as pairs. */
.comp-doc--reference .comp-passage {
    font-size: 0.97rem;
}

.comp-doc--reference .comp-passage > p {
    padding-left: 1.25rem;
    text-indent: -1.25rem;
    margin-bottom: 0.35rem;
}

/* Where the table IS the text, the prose steps back. */
.comp-doc--table .comp-passage {
    font-size: 0.95rem;
    color: var(--muted-ink);
}

/* ---------------------------------------------------------------------------
   Furniture: tables, keys, callouts, credits.
   --------------------------------------------------------------------------- */

.comp-table {
    width: 100%;
    border-collapse: collapse;
    margin: 0.75rem 0 0.25rem;
    font-size: 0.95rem;
}

.comp-table caption {
    caption-side: bottom;
    font-size: 0.8rem;
    font-style: italic;
    color: var(--muted-ink);
    text-align: left;
    padding-top: 0.35rem;
}

.comp-table th,
.comp-table td {
    border-bottom: 1px solid var(--rule);
    padding: 0.35rem 0.5rem;
    text-align: left;
    vertical-align: top;
}

.comp-table thead th {
    border-bottom: 2px solid var(--ink);
    font-family: var(--font-display);
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
}

.comp-table__note {
    font-size: 0.85rem;
    color: var(--muted-ink);
    margin: 0.35rem 0 0;
}

.comp-key {
    flex: 0 0 12rem;
    border: 1px solid var(--rule);
    border-left: 4px solid var(--slate);
    border-radius: 3px;
    padding: 0.6rem 0.75rem;
    background: var(--paper);
    margin: 0.75rem 0 0;
}

.comp-key__title {
    font-family: var(--font-display);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--slate);
    margin: 0 0 0.35rem;
}

.comp-key__list { margin: 0; font-size: 0.88rem; }
.comp-key__list dt { font-weight: 700; }
.comp-key__list dd { margin: 0 0 0.35rem; color: var(--muted-ink); }
.comp-key__list dd:last-child { margin-bottom: 0; }

.comp-callout {
    border: 1px dashed var(--slate);
    border-radius: 3px;
    padding: 0.6rem 0.75rem;
    margin-top: 0.75rem;
    background: var(--paper);
}

.comp-callout__label {
    font-family: var(--font-display);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--slate);
}

.comp-callout__text { margin: 0.2rem 0 0; font-size: 0.9rem; }

/* An image needs a fixed frame or a tall photograph shoves the text off the
   page. The credit sits under the caption because several of these licences
   require attribution and it has to survive printing. */
.comp-fig__img {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 2px;
}

.comp-fig__credit {
    display: block;
    font-size: 0.7rem;
    font-style: normal;
    color: var(--muted-ink);
    margin-top: 0.2rem;
    text-align: center;
}

/* Everything collapses to one column on a phone. A two-column news report or a
   key floated beside a narrow measure is unreadable at that width. */
@media (max-width: 639.98px) {
    .comp-doc--news .comp-passage { column-count: 1; }
    .comp-key { width: 100%; flex-basis: auto; }
    .comp-chat__turn { max-width: 100%; }
    .comp-doc--chronicle .comp-passage { text-align: left; }
    .comp-table { font-size: 0.88rem; }
}

/* Collapsible lesson steps.
   Lessons were one long column of prose, which read as a wall of text. Each
   step now sits behind its own heading so the whole lesson skims in seconds
   and only the part being read is open. The first step opens by default so
   the page never looks empty. */
.lesson-step {
    border-bottom: 1px solid rgba(0, 0, 0, 0.12);
    padding-bottom: 0.75rem;
}

.lesson-step-heading {
    cursor: pointer;
    padding: 0.6rem 0;
    list-style: none;
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

.lesson-step-heading::-webkit-details-marker {
    display: none;
}

.lesson-step-heading::before {
    content: "+";
    font-weight: 700;
    opacity: 0.55;
    width: 1rem;
    flex: 0 0 1rem;
}

.lesson-step[open] > .lesson-step-heading::before {
    content: "\2013";
}

.lesson-step-heading:hover {
    opacity: 0.75;
}

/* On paper, an unopened step would silently vanish. Print every step open. */
@media print {
    .lesson-step-body {
        display: block !important;
    }
    .lesson-step-heading::before {
        content: "";
    }
}

/* ---------------------------------------------------------------------------
   Reading preferences carried over from the text lab.

   Deliberately narrow. These rules only reach prose a child actually reads -
   passages, spread body text and activity steps. Headings, buttons, tables and
   figure captions are left alone, because a child who chose 22px for reading
   did not choose to blow up the whole interface, and because forcing a chosen
   line width onto a laid-out spread breaks the page rather than helping.
   --------------------------------------------------------------------------- */
.reading-prefs-on {
  --read-font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --read-size: 18px;
  --read-line: 1.6;
  --read-letter: 0em;
  --read-word: 0em;
  --read-paper: #ffffff;
  --read-ink: #1a1a1a;
}

.reading-prefs-on .comp-passage,
.reading-prefs-on .comp-spread__body,
.reading-prefs-on .comp-activity__steps {
  font-family: var(--read-font);
  font-size: var(--read-size);
  line-height: var(--read-line);
  letter-spacing: var(--read-letter);
  word-spacing: var(--read-word);
  background: var(--read-paper);
  color: var(--read-ink);
}

/* The paper colour needs breathing room or it reads as a highlighter stripe. */
.reading-prefs-on .comp-passage,
.reading-prefs-on .comp-spread__body {
  padding: 0.75rem 1rem;
  border-radius: 4px;
}

/* Print takes the site's ink-saving defaults back. A cream background chosen
   on screen must never become a full page of coloured ink. */
@media print {
  .reading-prefs-on .comp-passage,
  .reading-prefs-on .comp-spread__body,
  .reading-prefs-on .comp-activity__steps {
    background: #ffffff;
    color: #000000;
  }
}

.reading-prefs-note {
  font-size: 0.875rem;
}

/* ---------------------------------------------------------------- illustrations
   Named line drawings from templates/partials/_illustration.html.

   Two rules make these safe to sprinkle anywhere:

   1. Strokes inherit currentColor, so a drawing takes the colour of whatever
      text it sits beside, and prints as black line rather than a grey smear.
   2. The single decorative fill is a palette variable at low opacity, never a
      raw hex value, so a palette retune carries these along with it.
*/
.oss-ill {
    display: inline-block;
    width: 2.5rem;
    height: 2.5rem;
    flex: 0 0 auto;
    line-height: 0;
    vertical-align: middle;
}

.oss-ill svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

/* The one tinted shape in each drawing. Defaults to the brass wash so a
   drawing looks finished even when no accent is passed. */
.oss-ill__accent {
    fill: var(--brass);
    opacity: 0.18;
}

.oss-ill--accent-brass    .oss-ill__accent { fill: var(--brass); }
.oss-ill--accent-slate    .oss-ill__accent { fill: var(--slate); }
.oss-ill--accent-grass    .oss-ill__accent { fill: var(--grass); }
.oss-ill--accent-grape    .oss-ill__accent { fill: var(--grape); }
.oss-ill--accent-sunshine .oss-ill__accent { fill: var(--sunshine); opacity: 0.28; }
.oss-ill--accent-red-pen  .oss-ill__accent { fill: var(--red-pen); }

/* Sizes. Named rather than numeric so call sites read as intent. */
.oss-ill--sm { width: 1.5rem;  height: 1.5rem; }
.oss-ill--lg { width: 4rem;    height: 4rem; }
.oss-ill--xl { width: 6.5rem;  height: 6.5rem; }

/* A drawing used as a card's mark: pushed to the top with breathing room. */
.oss-ill--mark {
    width: 3rem;
    height: 3rem;
    margin-bottom: 0.75rem;
    color: var(--muted-ink);
}

@media (prefers-reduced-motion: no-preference) {
    /* Deliberately no animation. These are furniture, not entertainment, and a
       page of gently bobbing icons is harder to read, not friendlier. The empty
       block is left as the note explaining that absence. */
}

@media print {
    /* Ink discipline: line only, no washes, on every printable. */
    .oss-ill { color: #000; }
    .oss-ill__accent { fill: none; opacity: 1; }

    /* A child's tile is a doorway, never something to print. */
    .practice-tiles { display: none; }
}

/* ---------------------------------------------------------------------------
   Headings that carry a line drawing
   ---------------------------------------------------------------------------
   Flex rather than letting the drawing sit as an inline span, because an inline
   drawing drops onto its own line the moment a long subject name wraps, leaving
   a stranded picture above a heading. Flex keeps the two together at any width.

   The mark size carries a bottom margin so it works as a card's top mark. That
   margin shoves heading text off-centre, so it is cleared inside a heading.
--------------------------------------------------------------------------- */
.ws-subject-title,
.game-title {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.ws-subject-title .oss-ill--mark,
.game-title .oss-ill--mark {
    margin-bottom: 0;
    color: var(--muted-ink);
}

/* The three game category headings. Small drawing, tight to its label. */
.ws-games__group {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

/* ---------------------------------------------------------------------------
   Practice tiles — the front door for a child.

   Big, obvious targets rather than a list of links, because the person using
   this page is a child looking for their own name. Uses only palette
   variables that exist: --slate, --brass, --paper, --rule, --ink, --muted-ink.
   --------------------------------------------------------------------------- */
.practice-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: 1.25rem;
    margin: 1.5rem 0;
}

.practice-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 1.5rem 1rem;
    background: var(--paper);
    border: 2px solid var(--rule);
    border-radius: 10px;
    text-decoration: none;
    color: var(--ink);
    transition: border-color 0.15s ease, transform 0.15s ease;
}

.practice-tile:hover,
.practice-tile:focus {
    border-color: var(--slate);
    transform: translateY(-2px);
    text-decoration: none;
    color: var(--ink);
}

.practice-tile__art {
    color: var(--slate);
    margin-bottom: 0.75rem;
}

.practice-tile__who {
    font-family: var(--font-display, inherit);
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.2;
}

.practice-tile__what {
    color: var(--muted-ink);
    font-size: 0.95rem;
}

.practice-tile__week {
    color: var(--brass);
    font-weight: 600;
    margin-top: 0.25rem;
}

.practice-tile__go {
    margin-top: 1rem;
    padding: 0.5rem 1.5rem;
    background: var(--slate);
    color: #fff;
    border-radius: 6px;
    font-weight: 600;
}

/* ---- RUS brand ---- */
:root{--rus-ink:#1f2a44;--rus-paper:#fbf8f1;--rus-green:#2f7d4f;--rus-red:#b8412e;--rus-ochre:#d9a441;--rus-rule:#d8d1c0}
body{background:var(--rus-paper);color:var(--rus-ink)}
.rus-header{background:var(--rus-ink);color:#fff;border-bottom:4px solid var(--rus-ochre)}
.rus-brand{text-decoration:none;color:#fff;display:flex;align-items:baseline;gap:.75rem}
.rus-wordmark{font-family:Bitter,serif;font-weight:700;font-size:1.9rem;letter-spacing:.12em}
.rus-tagline{font-size:.95rem;opacity:.8;font-style:italic}
.rus-nav a{color:#fff;text-decoration:none;margin-left:1.1rem;font-weight:500}
.rus-nav a:hover{color:var(--rus-ochre)}
.rus-footer{border-top:1px solid var(--rus-rule);color:#6b6558}

.rus-hero{padding:3.5rem 0 3rem;background:repeating-linear-gradient(var(--rus-paper) 0 31px,#e7e0cf 31px 32px);border-bottom:1px solid var(--rus-rule);margin-top:-1.5rem}
.rus-hero h1{font-family:Bitter,serif;font-size:clamp(2rem,4vw,3.2rem);max-width:18ch;line-height:1.15}
.rus-hero h1 span{background:linear-gradient(transparent 60%,var(--rus-ochre) 60%)}
.rus-kicker{text-transform:uppercase;letter-spacing:.14em;font-weight:600;color:var(--rus-green);font-size:.85rem}
.btn-rus{background:var(--rus-green);color:#fff;border:0}.btn-rus:hover{background:#25643f;color:#fff}
.rus-card{background:#fff;border:1px solid var(--rus-rule);border-left:5px solid var(--rus-green);padding:1.5rem;border-radius:4px}
.rus-card-alt{border-left-color:var(--rus-ochre)}
.rus-card h3,.rus-card h2{font-family:Bitter,serif}
.rus-linkbtn{background:none;border:0;color:#fff;margin-left:1.1rem;font-weight:500;padding:0}
.rus-prose{max-width:760px}
.rus-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:.75rem}
.rus-gridweek{background:#fff;border:1px solid var(--rus-rule);border-radius:4px;padding:.75rem}
.rus-gridhead{font-weight:600;margin-bottom:.5rem}
.rus-subj{color:#fff;font-size:.72rem;padding:.1rem .45rem;border-radius:3px;margin-right:.35rem;text-transform:uppercase;letter-spacing:.05em}
.rus-cell{min-width:2.4rem;padding:.35rem .5rem;border-radius:4px;text-align:center;color:#fff;text-decoration:none;font-weight:600}
.rus-cell.is-done{background:var(--rus-green)}.rus-cell.is-todo{background:var(--rus-red)}
.rus-cell.is-next{outline:3px solid var(--rus-ochre);outline-offset:2px}
.rus-cell:hover{color:#fff;filter:brightness(1.1)}
.rus-dot{display:inline-block;width:14px;height:14px;border-radius:50%}.rus-dot.is-done{background:var(--rus-green)}.rus-dot.is-todo{background:var(--rus-red)}
.rus-lessonbar{background:#fff;border:1px solid var(--rus-rule);border-left:5px solid var(--rus-ochre);padding:.6rem 1rem;border-radius:4px}
.rus-termlink{padding:.4rem 0;border-top:1px solid var(--rus-rule);text-decoration:none}
.rus-staffnav{background:#efe9db;border-bottom:1px solid var(--rus-rule);margin-top:-1.5rem}
.rus-staffnav a{text-decoration:none}
.rus-weekchip{background:#fff;border:1px solid var(--rus-rule);border-radius:4px;padding:.35rem .55rem;font-size:.82rem;min-width:110px}
.rus-msg{background:#fff;border:1px solid var(--rus-rule);border-left:4px solid #999;border-radius:4px;padding:.7rem 1rem;margin-bottom:.6rem}
.rus-msg.is-staff{border-left-color:var(--rus-green)}.rus-msg.is-note{background:#fff8e1;border-left-color:var(--rus-ochre)}

.rus-cell{position:relative}.rus-cell.is-part{background:var(--rus-ochre);color:#1f2a44}
.rus-cellpct{font-size:.7rem;font-weight:500;opacity:.9}
.rus-wait{position:absolute;top:-4px;right:-4px;width:11px;height:11px;border-radius:50%;background:#f0b429;border:2px solid #fff;box-shadow:0 0 0 1px #b07d10}
.rus-progress{height:8px;background:#ece5d4}.rus-progress .progress-bar{background:var(--rus-green)}
.rus-section{border-top:1px dashed var(--rus-rule);padding-top:.5rem;font-size:.9rem}
.rus-section.is-done .rus-section-label{color:var(--rus-green);font-weight:600}
.rus-section.is-waiting .rus-section-label{color:#8a5d00;font-weight:600}
.rus-pct{display:inline-block;min-width:2.6rem;padding:.1rem .3rem;border-radius:3px;font-size:.75rem;font-weight:600;color:#fff}
.rus-pct.is-done{background:var(--rus-green)}.rus-pct.is-todo{background:var(--rus-red)}.rus-pct.is-part{background:var(--rus-ochre);color:#1f2a44}
