/* ========================================
   My Classling (js/student/classlings-home.js)
   A pupil's Classling Cup page for classes with Classlings on, in the reviewed design: the top bar
   with the logo, the title in Classlings' own lettering, the Locker | Collection | Rewards switch
   and Home; in the Locker their Classling in its display window beside eight picture slots and the
   open slot's drawer (Unlocked, then Locked); the Collection; and the level road. The tokens and
   the shared parts come from shared/css/classlings-pupil.css (.cla-pupil). On a Chromebook the
   page stays still in all three views and only what's too long scrolls, inside its own panel: the
   locker's drawer, the Collection's Classlings and the level road. On a phone the window stays in
   view while the drawer scrolls. Save and Undo are there only once they've tried something on.
   ======================================== */

body.cla-pupil-page { background: #ffffff; }

#classlingsHome { display: none; }
#classlingsHome.active { display: flex; }
/* The clouds sit under the window, where the page is empty however long the drawer gets (the sky
   world). --show-h is the display window's height. */
.clh { width: 100%; --show-h: 340px; --cloud-a: left 96px top 690px; --cloud-b: left 380px top 704px; }

/* ---------------------------------------------------------------- the top bar */

.clh-top { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-2) var(--gutter) 0; }
.clh-title { --title-scale: 3; white-space: nowrap; }
.clh-title.is-text { font-size: var(--t-m); }
.clh-views { margin: 0 auto; }
.clh-views .tool { padding: 0 var(--s-5); }
.clh-top > .btn { margin-left: auto; }
.clh-h { font: 700 var(--t-m) / 1.1 var(--display); }

.clh-body { padding: var(--s-3) var(--gutter) var(--gutter); }
.clh-body[hidden] { display: none; }

/* ---------------------------------------------------------------- the locker */

.clh-locker {
    display: grid;
    grid-template-columns: 540px minmax(0, 1fr);
    grid-template-areas: "banner banner" "side main";
    align-items: start;
    gap: var(--s-4) var(--s-6);
}
.clh-side { grid-area: side; display: grid; gap: var(--s-4); min-width: 0; }
.clh-main { grid-area: main; display: grid; align-content: start; gap: var(--s-4); min-width: 0; }

/* Until they pick a favourite: who they're playing as, and the way to choose. */
.clh-banner {
    grid-area: banner;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    padding: var(--s-3) var(--s-4) var(--s-1) var(--s-5);
    border-radius: var(--r-l);
}
.clh-banner p { font: 600 var(--t-ui) / 1.3 var(--display); }
/* A box waiting to be opened: gold, so it can't be missed (8 October). */
.cla-pupil .clh-banner.has-box { background: var(--gold-tint); }
.clh-banner.has-box p { font-size: var(--t-label); }

/* The display window, with a line from their Classling and a sparkle at two corners. */
.clh-window { position: relative; }
.clh-show {
    position: relative;
    width: 100%;
    height: var(--show-h);
    overflow: hidden;
    background: var(--wash);
    border: var(--edge) solid var(--ink);
    border-radius: var(--r-xl);
}
#clhStage { width: 100%; height: 100%; cursor: pointer; }
/* Their Classling's line: it speaks now and then, just above its head (classlings-home.js say), then the bubble goes. */
.clh-say { left: 0; top: 0; opacity: 0; visibility: hidden; transition: opacity 0.2s ease-out, visibility 0s linear 0.2s; }
.clh-say.is-saying { opacity: 1; visibility: visible; transition: opacity 0.15s ease-out; }
@media (prefers-reduced-motion: reduce) { .clh-say, .clh-say.is-saying { transition: none; } }
.clh-sp1 { right: -8px; top: -12px; }
.clh-sp2 { left: -8px; bottom: 12px; }
.clh-surprise { position: absolute; right: var(--s-3); top: var(--s-3); margin: 0; }

/* Their level and the next mystery box. */
.clh-level { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-2) var(--s-5) var(--s-2) var(--s-2); border-radius: var(--r-l); }
.clh-level .cookie { width: 84px; height: 84px; }
.clh-level .cookie b { font-size: var(--t-m); }
.clh-level p { flex: 1; font-size: var(--t-body); line-height: 1.4; text-wrap: balance; }
.clh-level p b { display: block; font: 600 var(--t-label) / 1.15 var(--display); }
.clh-level canvas { flex: none; width: 84px; height: 66px; }
/* The next box: a mystery box, a rare box, or both side by side every thirtieth level (#86). */
.clh-boxes { flex: none; display: flex; align-items: flex-end; gap: var(--s-1); }
.clh-boxes.both canvas { width: 66px; height: 52px; }

/* Undo and Save my look: kept in their place but out of sight (not faded: not there) until something
   changes, then they come in gently. While a save is on its way they wait (aria-disabled). */
.clh-save { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-4); }
.clh-save .btn { min-width: 0; }
.clh-save .btn.is-huge { padding: 0 var(--s-6); }
.clh-save .btn[aria-disabled="true"] { cursor: progress; }
.clh-problem { grid-column: 1 / -1; }
.clh-side > .clh-save { transition: opacity 0.2s ease-out, transform 0.2s ease-out, visibility 0s; }
.clh:not(.dirty) .clh-side > .clh-save {
    visibility: hidden;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.15s ease-in, transform 0.15s ease-in, visibility 0s linear 0.15s;
}

/* The eight picture slots, each with a picture of its own (js/student/slot-pictures.js). */
.clh-slots { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: var(--s-2); }
.clh-slot {
    appearance: none;
    position: relative;
    display: grid;
    justify-items: center;
    align-content: start;
    gap: var(--s-1);
    min-width: 0;
    padding: var(--s-2) 2px;
    color: var(--ink);
    font: 600 var(--t-small) / 1.1 var(--display);
    letter-spacing: 0;
    background: var(--page);
    border: var(--edge) solid var(--wash-2);
    border-radius: var(--r-m);
    cursor: pointer;
    transition: transform var(--settle) var(--spring);
}
.clh-slot:active { transform: scale(0.95); transition-duration: var(--press); }
.clh-slot .pic { display: grid; place-items: center; width: 60px; height: 60px; overflow: hidden; background: var(--wash); border-radius: var(--r-s); }
.clh-slot .pic canvas { width: 56px; height: 56px; }
.clh-slot .name { white-space: nowrap; }
.clh-slot.is-on { background: var(--grape-tint); border-color: var(--grape-deep); box-shadow: inset 0 0 0 var(--edge) var(--grape-deep); }
.clh-slot.is-on .pic { background: var(--page); }
.clh-slot .tick { position: absolute; top: -10px; right: -8px; display: grid; place-items: center; width: 30px; height: 30px; background: var(--grape); border: 2px solid var(--grape-deep); border-radius: 50%; }
.clh-slot .tick .cla-ic.is-px { width: 12px; height: 12px; }
/* Changed and not saved yet: a gold dot. */
.clh-slot.changed::after {
    content: '';
    position: absolute;
    top: -7px;
    left: -7px;
    width: 16px;
    height: 16px;
    background: var(--gold);
    border: 2px solid var(--gold-deep);
    border-radius: 50%;
}

/* The open slot's drawer: Unlocked, then Locked. */
.clh-drawer { display: grid; align-content: start; gap: var(--s-2); }
.clh-drawer h3 { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-3); padding-top: var(--s-2); font: 600 var(--t-ui) / 1.2 var(--display); }
.clh-drawer h3 span { font: 400 var(--t-small) / 1.3 var(--body); color: var(--ink-2); }
.clh-drawer-top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-3); }
.clh-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: var(--s-3); }
.clh-row.wide { grid-template-columns: repeat(auto-fill, minmax(176px, 1fr)); }
.clh-tile { min-height: 140px; }
.clh-tile canvas { width: 104px; height: 90px; }
.clh-tile .name { max-width: 100%; margin-top: var(--s-1); overflow-wrap: anywhere; hyphens: auto; }
.clh-row.wide .clh-tile canvas { width: 156px; height: 100px; }
.clh-tile .on.is-new { background: var(--gold); border-color: var(--gold-deep); }
/* "15 wins with Kit" (mastery) is longer than "Level 23": it wraps under the padlock. */
.clh-tile .lvl.is-wins { white-space: normal; text-align: left; }
/* A locked name tag stays readable: the padlock and its words say it's locked (#86). */
.clh-drawer[data-slot="tag"] .clh-tile.locked canvas { opacity: 1; filter: none; }
.clh-tile.shake { animation: clh-shake 0.4s; }
@keyframes clh-shake {
    20%, 60% { transform: translateX(-4px); }
    40%, 80% { transform: translateX(4px); }
}
.clh-tile.pop { animation: clh-pop 0.25s; }
@keyframes clh-pop {
    50% { transform: scale(1.06); }
}
.clh-empty { padding: var(--s-4); color: var(--ink-2); background: var(--page); border: var(--edge) dashed var(--wash-2); border-radius: var(--r-m); }
.clh-hint { font-size: var(--t-small); line-height: 1.4; color: var(--ink-2); }

/* Colour: which part, then the palette in families. */
.clh-seg .tool { font-size: var(--t-ui-s); }
.clh-families { display: grid; gap: var(--s-2); }
.clh-family { display: grid; grid-template-columns: 96px minmax(0, 1fr); align-items: center; gap: var(--s-2); }
.clh-family > span { font: 600 var(--t-small) / 1.2 var(--display); color: var(--ink-2); }
.clh-swatches { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.clh-swatch {
    appearance: none;
    position: relative;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    margin: 0 0 3px;
    padding: 0;
    color: var(--tick, #ffffff);
    background: var(--swatch);
    border: var(--edge) solid var(--ink);
    border-radius: 10px;
    box-shadow: 0 3px 0 var(--ink);
    cursor: pointer;
}
.clh-swatch .cla-ic.is-px { width: 24px; height: 24px; }
.clh-swatch.is-on { box-shadow: 0 0 0 3px var(--page), 0 0 0 6px var(--grape-deep), 0 3px 0 var(--ink); }
.clh-match[aria-pressed="true"] { --c: var(--grape-tint); --c-line: var(--grape-deep); --c-deep: var(--grape-deep); }

/* ---------------------------------------------------------------- the collection */

.clh-coll-top { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-4); padding-bottom: var(--s-4); }
.clh-coll-top b { font: 700 var(--t-xl) / 1 var(--display); }
.clh-coll-top span { font: 600 var(--t-label) / 1.2 var(--display); }
.clh-coll-top p { margin-left: auto; font-size: var(--t-body); color: var(--ink-2); }
.clh-filters { display: inline-flex; flex-wrap: wrap; margin-bottom: var(--s-4); }
.clh-filters .tool { padding: 0 var(--s-3); font-size: var(--t-ui-s); }
.clh-dex { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: var(--s-2); }
.clh-dex li { display: grid; }
.clh-mon { width: 100%; padding: var(--s-3) 0 var(--s-2); border-radius: var(--r-m); }
.clh-mon canvas { width: 80px; height: 80px; }
.clh-mon.missing { background: var(--page); border: 2px solid var(--wash-2); cursor: default; }
.clh-coll-foot { display: flex; align-items: center; gap: var(--s-4); margin-top: var(--s-5); padding: var(--s-3) var(--s-5); border-radius: var(--r-l); font: 600 var(--t-label) / 1.2 var(--display); }
.clh-coll-foot canvas { flex: none; width: 84px; height: 66px; }

/* ---------------------------------------------------------------- rewards: the level road */

.clh-rewards { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 360px); align-items: start; gap: var(--s-4) var(--s-6); }
.clh-road-top { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-4); }
.clh-road-top h2 { font: 700 var(--t-s) / 1.1 var(--display); }
.clh-road-top p { font-size: var(--t-body); color: var(--ink-2); }
.clh-road { overflow: hidden; background: var(--page); border: var(--edge) solid var(--wash-2); border-radius: var(--r-xl); }
.clh-map { position: relative; }
/* The road itself, its places, stones and rewards: css/level-road.css. */
.clh-aside { position: sticky; top: 12px; display: grid; gap: var(--s-4); }
.clh-aside .panel { display: grid; gap: var(--s-3); padding: var(--s-4) var(--s-5); border-radius: var(--r-l); }
.clh-aside h3 { font: 600 var(--t-label) / 1.1 var(--display); }
.clh-aside p { color: var(--ink-2); }
.clh-stars { display: flex; gap: var(--s-2); }
.clh-star { flex: 1; display: grid; gap: 2px; justify-items: center; padding: var(--s-2) var(--s-1); text-align: center; background: var(--page); border: 2px solid var(--wash-2); border-radius: var(--r-s); }
.clh-star b { display: flex; align-items: center; justify-content: center; gap: 2px; min-height: 20px; }
.clh-star .bdg { display: block; flex: none; width: 20px; height: 20px; }
.clh-star span { font: 600 var(--t-small) / 1.2 var(--display); color: var(--ink-2); }
/* A mastery step still to win is greyed, dashed and padlocked, as a locked tile is; one won has a tick. */
.clh-star:not(.is-got) { background: var(--wash); border-style: dashed; }
.clh-star:not(.is-got) .bdg { filter: grayscale(1); opacity: 0.45; }
.clh-star span .cla-ic.is-px { width: 12px; height: 12px; margin-right: 3px; vertical-align: -1px; }
.clh-star span .cla-ic.is-lock { width: 10px; height: 13px; }
.clh-box-art { display: block; width: 100%; height: 120px; border: var(--edge) solid var(--ink); border-radius: var(--r-m); }

/* ---------------------------------------------------------------- saving, and little messages */

.clh-savebar {
    position: fixed;
    left: var(--gutter);
    right: var(--gutter);
    bottom: 12px;
    z-index: 40;
    display: none;
    gap: var(--s-2);
    padding: var(--s-2) var(--s-2) 0;
    background: var(--page);
    border: var(--edge) solid var(--ink);
    border-radius: var(--r-l);
    box-shadow: var(--float);
}
.clh-savebar .clh-save { grid-template-columns: 1fr 2fr; gap: var(--s-2); }
.clh-toast {
    position: fixed;
    left: 50%;
    top: 84px;
    z-index: 50;
    padding: 10px 16px;
    font: 600 var(--t-ui) / 1 var(--display);
    color: var(--ink);
    background: var(--lime);
    border: var(--edge) solid var(--lime-deep);
    border-radius: var(--r-s);
    box-shadow: var(--float);
    opacity: 0;
    transform: translate(-50%, -12px);
    transition: opacity 0.2s, transform 0.2s;
    pointer-events: none;
}
.clh-toast.show { opacity: 1; transform: translate(-50%, 0); }
.clh-toast.dark { background: var(--page); border-color: var(--ink); }

/* ---------------------------------------------------------------- choosing a first favourite, and the cheer */

.clh-pickbody { display: grid; gap: var(--s-4); max-width: 960px; margin: 0 auto; width: 100%; }
.classling-choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--s-4); }
.classling-choice {
    appearance: none;
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
    color: var(--ink);
    text-align: left;
    background: var(--page);
    border: var(--edge) solid var(--wash-2);
    border-radius: var(--r-l);
    cursor: pointer;
    transition: transform var(--settle) var(--spring);
}
.classling-choice:active { transform: scale(0.96); transition-duration: var(--press); }
.classling-choice canvas { display: block; width: 100%; height: 140px; }
.classling-label { display: grid; gap: 2px; padding: var(--s-2) var(--s-3) var(--s-3); }
.classling-label strong { font: 700 var(--t-label) / 1.1 var(--display); }
.classling-label > span { font-size: var(--t-small); color: var(--ink-2); }
.classling-label .classling-now { justify-self: start; margin-top: 4px; padding: 2px 8px; font: 600 var(--t-small) / 1.2 var(--display); color: var(--ink); background: var(--gold); border: 2px solid var(--gold-deep); border-radius: var(--r-s); }
.classling-choice[aria-pressed="true"] { border-color: var(--grape-deep); background: var(--grape-tint); box-shadow: inset 0 0 0 var(--edge) var(--grape-deep); }
.classling-cheer { position: fixed; inset: 0; z-index: 900; display: grid; place-items: center; padding: var(--s-4); background: rgba(30, 27, 58, 0.45); }
.classling-cheer[hidden] { display: none; }
.classling-cheer-card {
    width: min(460px, 100%);
    display: grid;
    gap: var(--s-3);
    justify-items: center;
    text-align: center;
    padding: var(--s-4) var(--s-4) var(--s-5);
    background: var(--page);
    border: var(--edge) solid var(--ink);
    border-radius: var(--r-xl);
    box-shadow: var(--float);
}
.classling-cheer-card canvas { display: block; width: 100%; aspect-ratio: 2 / 1; border: var(--edge) solid var(--ink); border-radius: var(--r-l); }
.classling-cheer-card h2 { font: 700 var(--t-m) / 1.15 var(--display); text-wrap: balance; }
.classling-cheer-card p { color: var(--ink-2); line-height: 1.45; }

/* ---------------------------------------------------------------- narrower screens */

@media (max-width: 1179px) {
    .clh { --show-h: 300px; }
    .clh-views .tool { padding: 0 var(--s-4); font-size: var(--t-ui-s); }
    .clh-locker { grid-template-columns: minmax(380px, 440px) minmax(0, 1fr); }
    .clh-save .btn.is-huge { padding: 0 var(--s-4); font-size: var(--t-s); }
    .clh-slots { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .clh-rewards { grid-template-columns: minmax(0, 1fr); }
    .clh-aside { position: static; }
}

/* A Chromebook: the page stays still in all three views. The top bar keeps its place, the open view
   fills the rest of the screen, and only what's too long for it scrolls, inside its own panel. A
   screen too short for that scrolls as a page.
   - The locker (2026-10-03): the window, their level and Save keep their place on the left; on the
     right the slots stay put and only the open drawer scrolls.
   - The collection: the count and the kinds stay put and the Classlings scroll (2026-10-03).
   - Rewards: the level road scrolls, with mastery and the mystery boxes beside it (2026-10-03). */
@media (min-width: 1024px) and (min-height: 560px) {
    .clh[data-view] { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; }
    .clh[data-view] > .clh-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
    .clh-locker { flex: 1; min-height: 0; grid-template-rows: auto minmax(0, 1fr); align-items: stretch; }
    .clh-side { display: flex; flex-direction: column; min-height: 0; }
    .clh-window { flex: 0 1 var(--show-h); min-height: 180px; }
    .clh-show { height: 100%; }
    .clh-level, .clh-side > .clh-save { flex: none; }
    /* A save that didn't work says so just above Undo and Save. The page has no room to spare (on a 600 px laptop
       the window is already at its smallest), so the words stand where the level panel was, and the window, the
       words and both buttons all stay on the screen. The level comes back with the next try or Undo. */
    .clh.has-problem .clh-level { display: none; }
    .clh-main { display: flex; flex-direction: column; min-height: 0; }
    .clh-slots { flex: none; }

    /* The Collection's and the road's panels reach down to the grass, so the clouds stay hidden
       behind them, as when the page scrolled. */
    .clh:is([data-view="collection"], [data-view="rewards"]) { --cloud-a: left -400px top 0; --cloud-b: left -400px top 0; }

    .clh-collection { flex: 1; min-height: 0; display: flex; flex-direction: column; }
    .clh-coll-top { flex: none; }
    .clh-filters { flex: none; align-self: flex-start; }

    /* The road's heading sits over the road; mastery and the boxes stand beside both. */
    .clh-rewards {
        flex: 1;
        min-height: 0;
        grid-template-columns: minmax(0, 1fr) minmax(0, 360px);
        grid-template-rows: auto minmax(0, 1fr);
        grid-template-areas: "top aside" "road aside";
        align-items: stretch;
    }
    .clh-road-top { grid-area: top; }
    /* Beside mastery the note can take two lines: even ones, not one word left on its own. */
    .clh-road-top p { text-wrap: balance; }
    .clh-road { grid-area: road; }
    /* On a shorter screen the box's picture gives up height first (fitBoxArt in classlings-home.js);
       the column scrolls only if even that isn't enough. */
    .clh-aside {
        grid-area: aside;
        position: static;
        align-content: start;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        scrollbar-width: thin;
        scrollbar-color: var(--wash-2) transparent;
    }

    /* The panel that scrolls: the drawer, the Classlings and the road, alike. */
    .clh-drawer, .clh-shelf, .clh-road {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        scrollbar-gutter: stable;
        scrollbar-width: thin;
        scrollbar-color: var(--wash-2) transparent;
        padding: var(--s-1) var(--s-3) var(--s-4) var(--s-4);
        background: var(--page);
        border: var(--edge) solid var(--wash-2);
        border-radius: var(--r-xl);
    }
    .clh-shelf { padding-top: var(--s-3); }
    .clh-road { padding: 0; }
    .cla-pupil[data-world="sky"] :is(.clh-drawer, .clh-shelf, .clh-road) { border-color: var(--line-soft); }
}

/* A laptop too short for the still page (a 1366 x 768 school laptop leaves 540 to 600 px of page): the page
   scrolls, so the window's Save would sit below the bottom edge while they try on things from a long drawer.
   The floating save bar comes up instead, under the window's column, as on tablets and phones, and the page
   keeps room for it at its foot (#86's fix of 7 October, #102). Keep this whenever the still page's height
   changes: only a screen that keeps the window's Save in view may switch the bar off. */
@media (min-width: 1024px) and (max-height: 559px) {
    .clh { --bar-w: 540px; }
    .clh-side > .clh-save { display: none; }
    .clh-savebar {
        display: grid;
        right: auto;
        width: var(--bar-w);
        visibility: hidden;
        transform: translateY(calc(100% + 24px));
        transition: transform 0.2s ease-in, visibility 0s linear 0.2s;
    }
    .clh.dirty .clh-savebar { visibility: visible; transform: none; transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s; }
    .clh[data-view="locker"] .clh-body { padding-bottom: 140px; }
    /* A save that didn't work: the bar reaches across and the words stand beside Undo and Save, which stay exactly
       where they were. The bar is no taller than before, so it never climbs over the Classling in the window. */
    .clh.has-problem .clh-savebar {
        right: var(--gutter);
        width: auto;
        grid-template-columns: calc(var(--bar-w) - 2 * (var(--s-2) + var(--edge))) minmax(0, 1fr);
        align-items: start;
        column-gap: var(--s-3);
    }
    .clh.has-problem .clh-savebar .clh-problem { grid-column: 2; grid-row: 1; align-self: center; }
    .clh.has-problem .clh-savebar .clh-save { grid-column: 1; grid-row: 1; }
}
@media (min-width: 1024px) and (max-width: 1179px) and (max-height: 559px) {
    .clh { --bar-w: 440px; }
}

/* A shorter Chromebook screen: mastery and the boxes sit a little closer, so both fit beside the road. */
@media (min-width: 1024px) and (min-height: 560px) and (max-height: 700px) {
    .clh-aside { gap: var(--s-3); }
    .clh-aside .panel { gap: var(--s-2); padding-top: var(--s-3); padding-bottom: var(--s-3); }
}

/* A tablet or a phone: one column in the mock-up's order (the window, the slots, the drawer, then
   the level), with the window staying in view while the drawer scrolls. Save and Undo come up in a
   bar from the foot once something has changed, and go down again once it's saved or undone. */
@media (max-width: 1023px) {
    /* No clouds: the page scrolls here, so they'd drift behind the drawer. */
    .clh { --show-h: 260px; --cloud-a: left -400px top 0; --cloud-b: left -400px top 0; }
    .clh-top { flex-wrap: wrap; row-gap: var(--s-3); }
    .clh-title { order: 3; width: 100%; margin-bottom: 0; }
    .clh-views { order: 4; width: 100%; margin: 0; }
    .clh-views .tool { flex: 1; }
    .clh-locker { grid-template-columns: minmax(0, 1fr); grid-template-areas: "banner" "window" "slots" "drawer" "level"; }
    .clh-side, .clh-main { display: contents; }
    .clh-window { grid-area: window; position: sticky; top: 8px; z-index: 20; }
    .clh-slots { grid-area: slots; grid-template-columns: repeat(auto-fill, minmax(76px, 1fr)); }
    .clh-drawer { grid-area: drawer; }
    .clh-side > .clh-save { display: none; }
    .clh-level { grid-area: level; }
    .clh-savebar {
        display: grid;
        visibility: hidden;
        transform: translateY(calc(100% + 24px));
        transition: transform 0.2s ease-in, visibility 0s linear 0.2s;
    }
    .clh.dirty .clh-savebar { visibility: visible; transform: none; transition: transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1), visibility 0s; }
    /* The bar's room is kept at the foot of the locker, so nothing moves when it comes or goes. */
    .clh[data-view="locker"] .clh-body, .clh.dirty .clh-body { padding-bottom: 120px; }
}

@media (max-width: 600px) {
    .clh { --show-h: 230px; }
    .clh-views .tool { padding: 0 var(--s-2); }
    .clh-top > .btn { min-height: 48px; padding: 0 var(--s-4); font-size: var(--t-ui-s); --lift: 4px; border-radius: var(--r-s); }
    .clh-body { padding-top: var(--s-4); }
    .clh-sp2 { bottom: 20px; }
    .clh-slots { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-3) var(--s-2); }
    .clh-slot { font-size: 15px; }
    .clh-slot .pic { width: 56px; height: 56px; }
    .clh-slot .pic canvas { width: 52px; height: 52px; }
    /* Three to a row, so the longest one-word names (Whiteboard, Playground) fit their tiles whole; the
       four backdrops two by two. */
    .clh-row, .clh-row.later { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-2); }
    .clh-row.wide { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
    /* The Colour drawer's three parts share the width. */
    .clh-seg { display: flex; width: 100%; }
    .clh-seg .tool { flex: 1 1 auto; padding: 0 var(--s-2); }
    /* .cla-pupil, so these win over the shared .pick (shared/css/classlings-pupil.css). */
    .cla-pupil .clh-tile { min-height: 120px; padding: var(--s-2) 2px; border-radius: var(--r-m); }
    .clh-tile .name { font-size: 15px; }
    .clh-tile canvas, .clh-row.wide .clh-tile canvas { width: 64px; height: 64px; }
    .clh-tile .on { right: -4px; padding: 2px 6px 2px 4px; }
    .cla-pupil .clh-tile .lvl { gap: 2px; padding: 2px 5px 2px 3px; font-size: 14px; }
    .clh-level { padding-right: var(--s-3); gap: var(--s-3); }
    .clh-level .cookie { width: 72px; height: 72px; }
    .clh-level canvas, .clh-boxes { display: none; }
    .clh-level p b { font-size: 20px; }
    .clh-save { grid-template-columns: 1fr 2fr; gap: var(--s-3); }
    .clh-save .btn { padding: 0 var(--s-3); }
    .clh-save .btn.is-huge { padding: 0 var(--s-3); font-size: var(--t-s); }
    .clh-family { grid-template-columns: minmax(0, 1fr); gap: var(--s-1); }
    .clh-coll-top b { font-size: var(--t-huge); }
    .clh-dex { grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .clh-mon canvas { width: 64px; height: 64px; }
    .clh-savebar { left: var(--gutter); right: var(--gutter); }
}

@media (prefers-reduced-motion: reduce) {
    .clh-tile.shake, .clh-tile.pop { animation: none; }
    .clh-toast { transition: none; }
    .clh-slot:active, .classling-choice:active { transform: none; }
}

/* A school laptop's page, 560 to 640 px high: the level panel's picture is the phone's 72 px, not 84, so that Undo and Save my
   look and their lift end above the bottom of the page and not 4 px past it (walk-through of 14 October). */
@media (min-width: 1024px) and (min-height: 560px) and (max-height: 640px) {
    .clh-level .cookie { width: 72px; height: 72px; }
    .clh-level canvas { width: 72px; height: 56px; }
}
/* And at 560 to 574 px the display window may go a little smaller still (160 px, not 180). */
@media (min-width: 1024px) and (min-height: 560px) and (max-height: 574px) {
    .clh-window { min-height: 160px; }
}
