/* Public Marketplace pages.
   Deliberately the same design language as the landing page and the app: cream
   paper with a grain, Nunito, vivid blue, amber swashes and chunky tactile
   buttons. Someone arriving from a shared link should land somewhere that
   plainly belongs to the same product they are then asked to sign up for.
   Standalone rather than app.css because these pages carry none of the app
   chrome – but the tokens below are copied from app.css :root, not invented.
   slides.css is loaded alongside this and owns everything inside a slide. */

/* Nunito is loaded by a <link> in the page head rather than imported here: an
   @import cannot start until this file has been fetched and parsed, which puts
   three serial round trips in front of first paint. See layout() in
   routes/marketplacePublic.js – these pages have no other entry point, so the
   link is guaranteed to be there. */

:root {
    --mp-paper: #f5efe7;
    --mp-card: #fffdf9;
    --mp-ink: #1e1b2e;
    --mp-ink-soft: #6b6580;
    --mp-line: rgba(221, 213, 200, 0.95);
    --mp-blue: #3660ff;
    --mp-blue-dark: #2448d8;
    --mp-amber: #f4b447;
    --mp-green: #00c78d;
    --mp-shadow: 0 18px 48px rgba(30, 27, 46, 0.08);
    --mp-radius: 14px;
}

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

body {
    min-height: 100vh;
    background: linear-gradient(160deg, #f5efe7 0%, #efe6db 46%, #f7f1ea 100%);
    background-attachment: fixed;
    color: var(--mp-ink);
    font-family: "Nunito", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    position: relative;
}

/* The same tinted glow the app body carries, so the background is not flat. */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    background:
        radial-gradient(circle at 18% 22%, rgba(54, 96, 255, 0.055) 0%, transparent 40%),
        radial-gradient(circle at 82% 68%, rgba(244, 180, 71, 0.08) 0%, transparent 38%);
    pointer-events: none;
    z-index: 0;
}
body > * { position: relative; z-index: 1; }

a { color: inherit; }

/* ── Nav ──────────────────────────────────────────────── */
.mp-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    max-width: 1140px;
    margin: 0 auto;
    padding: 18px 24px;
}
/* Sign-up sits here rather than in the hero: it is the one thing on the page
   that is not browsing, and it should not interrupt the browse. */
.mp-nav-auth {
    display: flex;
    align-items: center;
    gap: 8px;
}
.mp-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 1.22rem;
    font-weight: 900;
    letter-spacing: -0.02em;
    text-decoration: none;
}
/* The same tilted mark the landing nav uses. */
.mp-brand-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 10px;
    background: var(--mp-blue);
    color: #fff;
    font-size: 0.82rem;
    font-weight: 900;
    box-shadow: 0 5px 14px rgba(54, 96, 255, 0.4);
    transform: rotate(-4deg);
    transition: transform 0.2s ease;
}
.mp-brand:hover .mp-brand-mark { transform: rotate(4deg) scale(1.06); }
.mp-brand em {
    font-style: normal;
    font-weight: 700;
    color: var(--mp-ink-soft);
}

/* ── Chunky tactile buttons, as everywhere else ───────── */
.mp-btn,
.mp-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 26px;
    border: 2px solid var(--mp-ink);
    border-radius: 999px;
    box-shadow: 0 4px 0 var(--mp-ink);
    background: var(--mp-blue);
    color: #fff;
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 800;
    white-space: nowrap;
    text-decoration: none;
    transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.mp-btn:hover,
.mp-cta:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 0 var(--mp-ink);
    background: var(--mp-blue-dark);
}
.mp-btn:active,
.mp-cta:active {
    transform: translateY(2px);
    box-shadow: 0 1px 0 var(--mp-ink);
}
.mp-btn-sm { padding: 8px 18px; font-size: 0.85rem; box-shadow: 0 3px 0 var(--mp-ink); }
/* Same metrics as .mp-btn-sm, so a paired ghost and primary match in the nav. */
.mp-cta-sm { padding: 8px 18px; font-size: 0.85rem; box-shadow: 0 3px 0 var(--mp-ink); }
.mp-btn-ghost { background: var(--mp-card); color: var(--mp-ink); }
.mp-btn-ghost:hover { background: #fff; }

.mp-main {
    max-width: 1140px;
    margin: 0 auto;
    padding: 16px 24px 56px;
}

/* ── Hero ─────────────────────────────────────────────── */
.mp-hero { margin-bottom: 30px; }
.mp-hero h1 {
    margin: 0 0 10px;
    font-size: clamp(1.9rem, 4.4vw, 3rem);
    font-weight: 900;
    line-height: 1.12;
    letter-spacing: -0.02em;
}
.mp-hero p {
    margin: 0 0 20px;
    max-width: 62ch;
    font-size: 1.02rem;
    color: var(--mp-ink-soft);
}
/* Amber swash under a key phrase, lifted from the landing page. */
.mp-swash {
    background-image: linear-gradient(100deg,
        rgba(244, 180, 71, 0) 2%,
        rgba(244, 180, 71, 0.7) 10%,
        rgba(244, 180, 71, 0.7) 90%,
        rgba(244, 180, 71, 0) 98%);
    background-repeat: no-repeat;
    background-size: 100% 38%;
    background-position: 0 88%;
    padding: 0 0.1em;
}

/* ── Browse controls ──────────────────────────────────────
   A plain GET form. marketplace-public.js submits it on change and hides the
   Search button; without JavaScript the button is how you apply a filter, so it
   is styled as a real control rather than assumed away. */
.mp-filter-form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
}
.mp-search {
    position: relative;
    flex: 1 1 260px;
    min-width: 0;
}
.mp-search-icon {
    position: absolute;
    top: 50%;
    left: 14px;
    transform: translateY(-50%);
    display: flex;
    color: var(--mp-ink-soft);
    pointer-events: none;
}
.mp-search input {
    width: 100%;
    padding: 11px 16px 11px 40px;
    border: 2px solid var(--mp-line);
    border-radius: 999px;
    background: var(--mp-card);
    color: var(--mp-ink);
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    transition: border-color 0.15s ease;
}
.mp-search input::placeholder { color: var(--mp-ink-soft); font-weight: 600; }
.mp-search input:focus { outline: none; border-color: var(--mp-blue); }
/* Safari draws its own clear affordance on type=search, at a size that fights
   the pill's right padding. */
.mp-search input::-webkit-search-decoration,
.mp-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.mp-select {
    flex: 0 1 auto;
    max-width: 100%;
    padding: 10px 34px 10px 14px;
    border: 2px solid var(--mp-line);
    border-radius: 999px;
    background: var(--mp-card) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b6580' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 12px center / 13px;
    color: var(--mp-ink);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    appearance: none;
    cursor: pointer;
    transition: border-color 0.15s ease;
}
.mp-select:hover { border-color: var(--mp-blue); }
.mp-select:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 2px; }
.mp-filter-go[hidden] { display: none; }

/* ── What the current browse is narrowed to ───────────────
   The count answers "is it worth scrolling?"; each pill is a link that removes
   one filter, so undoing a search never means editing the URL. */
.mp-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 20px;
    font-size: 0.82rem;
}
.mp-summary-count { font-weight: 800; color: var(--mp-ink-soft); }
.mp-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border: 2px solid var(--mp-line);
    border-radius: 999px;
    background: var(--mp-card);
    font-size: 0.76rem;
    font-weight: 700;
    text-decoration: none;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.mp-pill:hover { border-color: var(--mp-blue); color: var(--mp-blue); }
.mp-pill:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 2px; }
.mp-pill-key { color: var(--mp-ink-soft); font-weight: 600; }
.mp-pill-x { font-size: 0.95rem; line-height: 1; color: var(--mp-ink-soft); }
.mp-pill-clear { border-style: dashed; }

/* Visible to a screen reader, not on the page: the pills say "Search: photosynthesis"
   and need to also say what pressing them does. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ── Subject filters (plain links, no JS) ─────────────── */
.mp-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 26px;
}
.mp-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border: 2px solid var(--mp-line);
    border-radius: 999px;
    background: var(--mp-card);
    font-size: 0.82rem;
    font-weight: 700;
    text-decoration: none;
    transition: border-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.mp-chip span { color: var(--mp-ink-soft); font-weight: 600; }
.mp-chip:hover { border-color: var(--mp-blue); color: var(--mp-blue); transform: translateY(-1px); }
.mp-chip.active {
    border-color: var(--mp-ink);
    background: var(--mp-blue);
    color: #fff;
    box-shadow: 0 3px 0 var(--mp-ink);
}
.mp-chip.active span { color: rgba(255, 255, 255, 0.78); }

/* ── Catalogue grid ───────────────────────────────────── */
.mp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 20px;
}
.mp-card {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--mp-line);
    border-radius: var(--mp-radius);
    background: var(--mp-card);
    overflow: hidden;
    text-decoration: none;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.mp-card:hover {
    transform: translateY(-3px);
    border-color: var(--mp-blue);
    box-shadow: var(--mp-shadow);
}
.mp-card-thumb {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: rgba(244, 238, 230, 0.92);
    border-bottom: 1px solid var(--mp-line);
}
.mp-card-count {
    position: absolute;
    right: 8px;
    bottom: 8px;
    padding: 2px 9px;
    border-radius: 999px;
    background: rgba(30, 27, 46, 0.78);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 700;
}
.mp-card-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1;
    padding: 13px 14px 14px;
}
.mp-card-title {
    margin: 0;
    font-size: 0.97rem;
    font-weight: 800;
    line-height: 1.32;
    letter-spacing: -0.01em;
}
.mp-card-author {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 2px 0 0;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--mp-blue);
}
.mp-card-meta,
.mp-card-desc,
.mp-card-uses {
    margin: 0;
    font-size: 0.8rem;
    color: var(--mp-ink-soft);
}
.mp-card-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.mp-card-title a { text-decoration: none; }
/* Stretched link: the title anchor covers the whole card, so clicking anywhere
   opens the listing without nesting anchors inside one another. */
.mp-card-link::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
}

.mp-card-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: auto;
    padding-top: 10px;
}
.mp-card-uses { font-size: 0.75rem; font-weight: 700; }
/* "Used by 4 teachers" is a statistic and reads as quiet grey text like the
   rest of the metadata. "New" is a badge – a listing published this week has no
   use count to show and this is the only thing on the card arguing for it, so
   it is allowed to look like a label rather than a footnote. Green rather than
   blue: blue is the colour of everything clickable here, and this is not. */
.mp-card-new {
    padding: 2px 9px;
    border-radius: 999px;
    background: rgba(0, 199, 141, 0.14);
    color: #04794f;
    font-size: 0.7rem;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}
/* Above the stretched link, so it is its own target rather than part of the
   card's click area. */
.mp-card-dl {
    position: relative;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    padding: 4px 10px;
    border: 2px solid var(--mp-line);
    border-radius: 999px;
    background: var(--mp-card);
    font-size: 0.72rem;
    font-weight: 800;
    text-decoration: none;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.mp-card-dl:hover { border-color: var(--mp-blue); color: var(--mp-blue); }
.mp-card-dl:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 2px; }

.mp-card-acts { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* Square rather than a pill: it is an icon on its own, and a pill around a
   single glyph reads as a button missing its label. */
.mp-card-save {
    position: relative;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 27px;
    height: 27px;
    border: 2px solid var(--mp-line);
    border-radius: 9px;
    background: var(--mp-card);
    color: var(--mp-ink-soft);
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.mp-card-save:hover { border-color: var(--mp-blue); color: var(--mp-blue); }
.mp-card-save:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 2px; }
.mp-card-save.saved {
    border-color: var(--mp-blue);
    background: var(--mp-blue);
    color: #fff;
}
.mp-card-save.saved svg { fill: currentColor; }

.mp-avatar {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(54, 96, 255, 0.14);
    color: var(--mp-blue);
    font-size: 0.62rem;
    font-weight: 800;
}

.mp-empty {
    padding: 56px 24px;
    border: 2px dashed var(--mp-line);
    border-radius: var(--mp-radius);
    text-align: center;
    color: var(--mp-ink-soft);
}

.mp-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 34px;
    padding-top: 22px;
    border-top: 1px solid var(--mp-line);
    font-size: 0.88rem;
}
.mp-pager-link { font-weight: 800; color: var(--mp-blue); text-decoration: none; }
.mp-pager-link:hover { text-decoration: underline; }
.mp-pager-at { color: var(--mp-ink-soft); font-weight: 600; }

/* ── One listing ──────────────────────────────────────── */
.mp-listing { max-width: 900px; }
.mp-crumbs {
    margin-bottom: 18px;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--mp-ink-soft);
}
.mp-crumbs a { color: var(--mp-blue); text-decoration: none; }
.mp-crumbs a:hover { text-decoration: underline; }
.mp-crumbs span { padding: 0 5px; }

.mp-listing-head { margin-bottom: 22px; }
.mp-listing-head h1 {
    margin: 0 0 10px;
    font-size: clamp(1.6rem, 3.6vw, 2.3rem);
    font-weight: 900;
    line-height: 1.18;
    letter-spacing: -0.02em;
}
.mp-listing-author {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0 0 4px;
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--mp-blue);
}
.mp-listing-meta { margin: 0; font-size: 0.84rem; font-weight: 600; color: var(--mp-ink-soft); }
/* "Five teachers have taught this" is the best reason on the page to trust the
   lesson, so it is stated at the top in the one green the marketplace uses for
   claims made by people – not buried in the grey meta line beside the slide
   count, and not left as a clause in a panel three-quarters of the way down.
   Hidden rather than absent when nobody has, so pressing the button below can
   fill it in. */
.mp-listing-taught {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 10px 0 0;
    padding: 5px 13px;
    border-radius: 999px;
    background: rgba(0, 199, 141, 0.15);
    color: #04794f;
    font-size: 0.86rem;
    font-weight: 800;
}
.mp-listing-taught[hidden] { display: none; }
.mp-listing-desc {
    margin: 14px 0 0;
    max-width: 65ch;
    font-size: 1.02rem;
    white-space: pre-wrap;
}

/* Repeated at the top and the bottom: someone who has scrolled every slide has
   shown more intent than someone who bounced off the header. */
/* Stacked rather than a row: the line plus three buttons never fit side by
   side at the column's width, so a row only ever wrapped into a worse-looking
   version of this. */
.mp-take {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    margin-bottom: 28px;
    padding: 18px 20px;
    border: 2px solid var(--mp-ink);
    border-radius: var(--mp-radius);
    background: var(--mp-card);
    box-shadow: 0 4px 0 var(--mp-ink);
}
.mp-take p {
    margin: 0;
    max-width: 60ch;
    font-size: 0.92rem;
    color: var(--mp-ink-soft);
    text-wrap: pretty;
}
.mp-take strong { color: var(--mp-ink); font-weight: 800; }
.mp-take-end { margin: 34px 0 0; }

/* ── Slide viewer ─────────────────────────────────────── */
.mp-viewer {
    margin-bottom: 26px;
    border: 1px solid var(--mp-line);
    border-radius: var(--mp-radius);
    overflow: hidden;
    background: var(--mp-card);
    box-shadow: var(--mp-shadow);
}
.mp-panel { position: relative; }
.mp-panel[hidden] { display: none; }

/* Its own element so the viewer bar is not inside the height the scaling
   script assigns. Falls back to a clipped 16:9 window if that never runs. */
.mp-slide-box {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
}

/* Locked slides are not in the page at all; this is the empty ground the
   prompt sits on, so it carries no content of its own to collide with. */
.mp-locked {
    background: repeating-linear-gradient(
        -45deg,
        rgba(244, 238, 230, 0.9) 0 14px,
        rgba(238, 231, 221, 0.9) 14px 28px);
}
/* What is behind the lock, named. Sits above the padlock so it reads as the
   subject of the offer rather than as a caption to it: the slide number is the
   quiet part and the slide's own heading is the part worth an account. */
.mp-locked-peek {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin: 0;
    max-width: 30ch;
    text-shadow: 0 1px 0 rgba(255, 253, 249, 0.9);
}
.mp-locked-num {
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}
.mp-locked-name {
    font-size: clamp(0.95rem, 2vw, 1.15rem);
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--mp-ink);
}
.mp-locked-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: var(--mp-card);
    border: 2px solid var(--mp-line);
    color: var(--mp-ink-soft);
}

/* The prompt sits over the slide rather than under it, so the thing being
   offered and the way to get it are never separated by a scroll. */
.mp-lock {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 20px;
    text-align: center;
}
.mp-lock-title {
    margin: 0;
    max-width: 26ch;
    font-size: clamp(1rem, 2.2vw, 1.3rem);
    font-weight: 900;
    letter-spacing: -0.01em;
    color: var(--mp-ink);
    text-shadow: 0 1px 0 rgba(255, 253, 249, 0.9);
}
.mp-lock-sub { margin: 0; font-size: 0.82rem; font-weight: 600; color: var(--mp-ink-soft); }
/* A button, because it opens the sign-in dialog rather than going anywhere –
   styled to read as the link it replaced. */
.mp-lock-sub button {
    padding: 0;
    border: 0;
    background: none;
    color: var(--mp-blue);
    font-family: inherit;
    font-size: inherit;
    font-weight: 800;
    text-decoration: underline;
    cursor: pointer;
}

.mp-viewer-bar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 10px 14px;
    border-top: 1px solid var(--mp-line);
}
.mp-viewer-at {
    min-width: 120px;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--mp-ink-soft);
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.mp-step {
    width: 36px;
    height: 32px;
    border: 2px solid var(--mp-line);
    border-radius: 9px;
    background: var(--mp-card);
    color: var(--mp-ink);
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 800;
    cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease;
}
.mp-step:hover:not(:disabled) { border-color: var(--mp-blue); color: var(--mp-blue); }
.mp-step:disabled { opacity: 0.4; cursor: default; }
.mp-step:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 2px; }

/* ── Actions ──────────────────────────────────────────── */
.mp-take-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}
.mp-dl { display: flex; flex-wrap: wrap; gap: 8px; }
.mp-dl .mp-btn { padding: 10px 16px; font-size: 0.85rem; }
/* Saved is a state, not an action, so it reads as filled-in rather than as one
   more thing left to press. */
.mp-save.saved {
    background: var(--mp-blue);
    color: #fff;
}
.mp-save.saved:hover { background: var(--mp-blue-dark); }

.mp-listing-share { margin: 14px 0 0; }

/* ── More like this ───────────────────────────────────────
   Every listing page ends up linking to six others, which is most of what makes
   any of them findable – by a reader and by a crawler. */
.mp-related {
    margin-top: 44px;
    padding-top: 30px;
    border-top: 1px solid var(--mp-line);
}
.mp-related h2 {
    margin-bottom: 20px;
    font-size: 1.3rem;
    font-weight: 900;
    letter-spacing: -0.02em;
}
/* The listing page is narrower than the catalogue, so the same auto-fill grid
   would leave a lone stretched card on a wide screen. */
.mp-related .mp-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }

/* ── Author ───────────────────────────────────────────── */
/* Above the card's stretched link, so it opens the teacher rather than the
   listing it happens to sit on. */
.mp-card-author .mp-author-link {
    position: relative;
    z-index: 2;
}
.mp-author-link {
    color: inherit;
    text-decoration: none;
}
.mp-author-link:hover { text-decoration: underline; }
.mp-author-link:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 2px; border-radius: 4px; }

.mp-author-hero {
    display: flex;
    align-items: center;
    gap: 16px;
}
.mp-avatar-lg {
    width: 60px;
    height: 60px;
    flex-shrink: 0;
    font-size: 1.3rem;
}
.mp-author-hero h1 { margin-bottom: 4px; }
.mp-author-hero p { margin: 0; font-size: 0.9rem; font-weight: 600; }

/* ── Report ───────────────────────────────────────────── */
/* Quiet and last: a real route out, but it must never compete with using the
   lesson, which is what almost everyone is here to do. */
.mp-report-row { margin-top: 22px; text-align: center; }
.mp-report {
    padding: 0;
    border: 0;
    background: none;
    color: var(--mp-ink-soft);
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    text-decoration: underline;
    cursor: pointer;
}
.mp-report:hover { color: var(--mp-ink); }
.mp-report:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 3px; border-radius: 4px; }
.mp-report-done { font-size: 0.82rem; font-weight: 700; color: var(--mp-green); }

#mp-report-modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
#mp-report-modal[hidden] { display: none; }
.mp-modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(30, 27, 46, 0.45);
    backdrop-filter: blur(8px) saturate(1.1);
    -webkit-backdrop-filter: blur(8px) saturate(1.1);
}
.mp-modal {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 460px;
    max-height: 90vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 2px solid var(--mp-ink);
    border-radius: var(--mp-radius);
    background: var(--mp-card);
    box-shadow: 0 6px 0 var(--mp-ink);
}
.mp-modal-head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 15px 18px 12px;
    border-bottom: 1px solid var(--mp-line);
}
.mp-modal-head > div { flex: 1; min-width: 0; }
.mp-modal-head h2 { margin: 0; font-size: 1.02rem; font-weight: 900; letter-spacing: -0.01em; }
.mp-modal-head p { margin: 3px 0 0; font-size: 0.79rem; color: var(--mp-ink-soft); }
.mp-modal-close {
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    border: 0;
    border-radius: 8px;
    background: none;
    color: var(--mp-ink-soft);
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
}
.mp-modal-close:hover { background: rgba(0, 0, 0, 0.05); color: var(--mp-ink); }
.mp-modal-body { flex: 1; overflow-y: auto; padding: 15px 18px; }
.mp-modal-foot {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding: 12px 18px;
    border-top: 1px solid var(--mp-line);
}
.mp-modal-foot .mp-cta { padding: 9px 18px; font-size: 0.86rem; }

.mp-reasons { border: 0; padding: 0; margin: 0 0 14px; }
.mp-reasons legend { margin-bottom: 8px; font-size: 0.84rem; font-weight: 800; }
.mp-reasons label {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 6px;
    padding: 8px 10px;
    border: 2px solid var(--mp-line);
    border-radius: 9px;
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s ease;
}
.mp-reasons label:hover { border-color: var(--mp-blue); }
.mp-note-label {
    display: block;
    margin-bottom: 5px;
    font-size: 0.82rem;
    font-weight: 700;
}
.mp-note-label span { font-size: 0.72rem; font-weight: 600; color: var(--mp-ink-soft); }
#mp-report-note {
    width: 100%;
    padding: 9px 11px;
    border: 2px solid var(--mp-line);
    border-radius: 9px;
    background: var(--mp-bg);
    color: var(--mp-ink);
    font-family: inherit;
    font-size: 0.86rem;
    resize: vertical;
}
#mp-report-note:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 1px; }
.mp-modal-body .mp-inline-error { margin-top: 12px; }

/* ── Auth modal ───────────────────────────────────────────
   Matched to the landing page's own sign-in modal (.auth-card in app.css):
   same cream card, 2px ink border, 24px radius and hard offset shadow, same
   BA mark, tab bar, field and button treatment. Someone who opens this from a
   shared listing and someone who opens it from the front page should not feel
   they are signing up to two different products. Duplicated rather than shared
   because these pages deliberately do not load app.css – if the landing modal
   is restyled, this needs the same edit. */
#mp-auth-modal {
    position: fixed;
    inset: 0;
    z-index: 110;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    overflow-y: auto;
}
#mp-auth-modal[hidden] { display: none; }
.mp-auth-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(26, 26, 46, 0.55);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}
.mp-auth-card {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 420px;
    margin: auto;
    padding: 34px 32px 30px;
    border: 2px solid var(--mp-ink);
    border-radius: 24px;
    background: #fffdf8;
    box-shadow: 8px 8px 0 rgba(30, 27, 46, 0.9);
}
.mp-auth-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--mp-line);
    border-radius: 50%;
    background: var(--mp-card);
    color: var(--mp-ink-soft);
    cursor: pointer;
}
.mp-auth-close:hover { color: var(--mp-ink); border-color: var(--mp-ink); }
.mp-auth-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin-bottom: 14px;
    border-radius: 13px;
    background: var(--mp-blue);
    color: #fff;
    font-size: 0.95rem;
    font-weight: 900;
    box-shadow: 0 5px 14px rgba(54, 96, 255, 0.4);
}
.mp-auth-card h2 {
    margin: 0 0 4px;
    font-size: 1.32rem;
    font-weight: 800;
    letter-spacing: -0.01em;
}
.mp-auth-sub {
    margin: 0 0 20px;
    font-size: 0.84rem;
    color: var(--mp-ink-soft);
}

.mp-auth-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 20px;
    padding: 4px;
    border-radius: 999px;
    background: rgba(244, 238, 230, 0.92);
}
.mp-auth-tab {
    flex: 1;
    padding: 9px 12px;
    border: 2px solid transparent;
    border-radius: 999px;
    background: none;
    color: var(--mp-ink-soft);
    font-family: inherit;
    font-size: 0.88rem;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.mp-auth-tab.active {
    border-color: var(--mp-ink);
    background: #fffdf8;
    color: var(--mp-ink);
    font-weight: 800;
}
.mp-auth-tab:focus-visible { outline: 2px solid var(--mp-blue); outline-offset: 2px; }

.mp-auth-form[hidden] { display: none; }
.mp-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.mp-field { margin-bottom: 14px; }
.mp-field label {
    display: block;
    margin-bottom: 6px;
    font-size: 0.82rem;
    font-weight: 700;
}
.mp-field label span { font-weight: 400; color: var(--mp-ink-soft); }
.mp-field input {
    width: 100%;
    padding: 10px 14px;
    border: 2px solid rgba(30, 27, 46, 0.18);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.72);
    color: var(--mp-ink);
    font-family: inherit;
    font-size: 0.95rem;
    transition: border-color 0.15s ease;
}
.mp-field input:focus {
    outline: none;
    border-color: var(--mp-blue);
}

.mp-auth-note {
    margin: 0 0 16px;
    font-size: 0.83rem;
    line-height: 1.55;
    color: var(--mp-ink-soft);
}
.mp-auth-note a { color: var(--mp-blue); font-weight: 700; }
/* The landing modal's primary button is a blue gradient pill with the same
   hard shadow as every other button in the product. */
.mp-auth-submit {
    width: 100%;
    justify-content: center;
    background: linear-gradient(135deg, #3660ff 0%, #5b8bff 100%);
}
.mp-auth-submit:hover { background: linear-gradient(135deg, #2448d8 0%, #3660ff 100%); }
.mp-auth-alt {
    margin: 16px 0 0;
    text-align: center;
    font-size: 0.8rem;
    font-weight: 600;
}
.mp-auth-alt a { color: var(--mp-ink-soft); }

@media (max-width: 480px) {
    .mp-auth-card { padding: 28px 20px 24px; box-shadow: 5px 5px 0 rgba(30, 27, 46, 0.9); }
    .mp-field-row { grid-template-columns: 1fr; gap: 0; }
}

.mp-inline-error {
    margin-top: 14px;
    padding: 10px 14px;
    border: 2px solid #b14637;
    border-radius: 10px;
    background: rgba(177, 70, 55, 0.08);
    color: #b14637;
    font-size: 0.86rem;
    font-weight: 700;
}
.mp-inline-error[hidden] { display: none; }

/* "Did you mean…?" on a sign-up address that looks mistyped. A question with
   two answers, so it borrows the error's box and none of its red. */
.mp-inline-ask {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 14px;
    margin-top: 14px;
    padding: 10px 14px;
    border: 1px solid rgba(54, 96, 255, 0.25);
    border-radius: 10px;
    background: rgba(54, 96, 255, 0.07);
    color: var(--mp-ink);
    font-size: 0.86rem;
    font-weight: 600;
}
.mp-inline-ask[hidden] { display: none; }
.mp-inline-ask p { flex: 1 1 auto; margin: 0; }
.mp-inline-ask strong { overflow-wrap: anywhere; }
.mp-inline-ask-actions { display: flex; align-items: center; gap: 14px; }
.mp-inline-ask-yes,
.mp-inline-ask-no {
    border: 0;
    font: inherit;
    font-size: 0.85rem;
    font-weight: 700;
    line-height: 1.2;
    cursor: pointer;
}
.mp-inline-ask-yes { padding: 7px 12px; border-radius: 8px; background: #3660ff; color: #fff; }
.mp-inline-ask-yes:hover { background: #2448d8; }
.mp-inline-ask-no {
    padding: 7px 0;
    background: none;
    color: #6b6580;
    text-decoration: underline;
    text-underline-offset: 2px;
}
.mp-inline-ask-no:hover { color: var(--mp-ink); }
.mp-inline-ask-yes:focus-visible,
.mp-inline-ask-no:focus-visible { outline: 2px solid #3660ff; outline-offset: 2px; }

/* Authored at a fixed 960x540 and scaled to fit; see marketplace-public.js.
   Absolutely positioned because a transform leaves the element's layout box at
   its original size, which would otherwise force the page wider than the
   viewport. */
.slide-scale {
    position: absolute;
    top: 0;
    left: 0;
    width: 960px;
    height: 540px;
    transform-origin: top left;
    pointer-events: none;
    user-select: none;
}

/* ── Endorsement: "I taught this" ─────────────────────── */
/* Green, and the only green control on these pages, because it is the one
   thing here that is a claim by a person rather than a count by the system.
   Never colour alone – the wording says what it means. */
.mp-card-endorsed {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 9px;
    border-radius: 999px;
    background: rgba(0, 199, 141, 0.15);
    color: #04794f;
    font-size: 0.72rem;
    font-weight: 800;
    /* Never wraps. In a three-column grid this badge shares one line with the
       save and download controls, and letting it break stacked it into three
       lines and pushed the whole card footer out of shape. */
    white-space: nowrap;
}
.mp-card-endorsed svg { flex-shrink: 0; }

/* Its own panel, drawn like the take panel above it, because as a loose pill
   between two boxes it read as page furniture and went unnoticed. The panel
   itself stays neutral – the green belongs to the button, which is the part
   that is a claim by a person. */
.mp-endorse-panel {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 28px;
    padding: 18px 20px;
    border: 2px solid var(--mp-ink);
    border-radius: var(--mp-radius);
    background: var(--mp-card);
    box-shadow: 0 4px 0 var(--mp-ink);
}
.mp-endorse-copy { flex: 1 1 22ch; }
.mp-endorse-copy h2 {
    margin-bottom: 3px;
    font-size: 1.02rem;
    font-weight: 800;
    color: var(--mp-ink);
}
.mp-endorse-copy p {
    max-width: 56ch;
    font-size: 0.88rem;
    color: var(--mp-ink-soft);
    text-wrap: pretty;
}
.mp-endorse {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 11px 22px;
    border: 2px solid var(--mp-ink);
    border-radius: 999px;
    box-shadow: 0 4px 0 var(--mp-ink);
    background: var(--mp-green);
    color: #05372a;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 800;
    white-space: nowrap;
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.mp-endorse:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 0 var(--mp-ink);
    background: #00b37f;
}
.mp-endorse:active {
    transform: translateY(2px);
    box-shadow: 0 1px 0 var(--mp-ink);
}
.mp-endorse-tick { flex-shrink: 0; }
/* Endorsed is a state, not an action: the tick fills in and the button steps
   back so it stops asking to be pressed. Never colour alone – the label
   changes to "You taught this" at the same time. */
.mp-endorse.on {
    background: rgba(0, 199, 141, 0.16);
    color: #04794f;
    box-shadow: 0 2px 0 var(--mp-ink);
    transform: none;
}
.mp-endorse.on:hover { background: rgba(0, 199, 141, 0.24); transform: none; box-shadow: 0 2px 0 var(--mp-ink); }
.mp-endorse:disabled { opacity: 0.6; cursor: default; }
/* The explanation someone gets instead of a control they cannot use. A
   disabled button with no reason is the thing this replaces. */
.mp-endorse-locked { color: var(--mp-ink-soft); }

@media (prefers-reduced-motion: reduce) {
    .mp-endorse { transition: background 0.15s ease; }
    .mp-endorse:hover, .mp-endorse:active { transform: none; }
}

/* ── Where this lesson came from ──────────────────────── */
/* Quiet by design. It is a disclosure, not a selling point: it should be easy
   to find and read, and should not compete with the lesson above it. */
.mp-provenance {
    margin-top: 30px;
    padding: 18px 20px;
    border: 1px solid var(--mp-line);
    border-radius: var(--mp-radius);
    background: rgba(255, 253, 249, 0.6);
}
.mp-provenance h2 {
    margin-bottom: 6px;
    font-size: 0.75rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}
.mp-provenance p {
    font-size: 0.9rem;
    line-height: 1.6;
}
.mp-provenance-sub {
    margin-top: 6px;
    color: var(--mp-ink-soft);
    font-size: 0.85rem;
}

/* ── Author profile ───────────────────────────────────── */
.mp-author-teaches {
    margin-top: 2px;
    font-size: 1rem;
    font-weight: 700;
    color: var(--mp-ink);
}
.mp-author-stats {
    margin-top: 4px;
    font-size: 0.88rem;
    color: var(--mp-ink-soft);
}
.mp-author-bio {
    margin-top: 10px;
    max-width: 60ch;
    font-size: 0.95rem;
    line-height: 1.6;
}

/* ── What's in this lesson (signed-out only) ──────────── */
/* Fourteen named slides is a lesson; "14 slides" is a number. This is the
   strongest argument the gated page can make, and it is also the only real
   text a crawler gets from a listing whose slides are withheld and whose
   author may have left the description blank.

   It sits below the take and endorse panels, and is deliberately lighter than
   both: it is a reference list, not an ask, and at full card weight it was the
   heaviest thing on the page. */
.mp-outline {
    margin-bottom: 28px;
    padding: 14px 16px;
    border: 1px solid var(--mp-line);
    border-radius: var(--mp-radius);
    background: var(--mp-card);
}
.mp-outline h2 {
    margin-bottom: 8px;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}
.mp-outline-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 0 22px;
    list-style: none;
    counter-reset: none;
}
.mp-outline-list li {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 4px 0;
    border-bottom: 1px solid rgba(221, 213, 200, 0.5);
    font-size: 0.82rem;
}
.mp-outline-num {
    flex-shrink: 0;
    min-width: 1.5em;
    font-size: 0.72rem;
    font-weight: 800;
    color: var(--mp-ink-soft);
    font-variant-numeric: tabular-nums;
}
.mp-outline-name { flex: 1; }
/* The slides already readable, marked as such – so the list reads as "here is
   the whole lesson, and you can see these now" rather than as a locked index. */
.mp-outline-free .mp-outline-name { font-weight: 700; }
.mp-outline-tag {
    flex-shrink: 0;
    font-size: 0.64rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: #04794f;
}

/* ── Closest matches, when nothing matched ────────────── */
/* Sits under the "no lessons match that" line, so it has to read as an offer
   rather than as results – hence the rule above it and the subheading naming
   which filter was let go. Without that, cards appearing beneath a "nothing
   matched" message look like a bug. */
.mp-nearmiss {
    margin-top: 26px;
    padding-top: 24px;
    border-top: 1px solid var(--mp-line);
}
.mp-nearmiss h2 {
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: -0.01em;
}
.mp-nearmiss-sub {
    margin: 4px 0 20px;
    font-size: 0.86rem;
    color: var(--mp-ink-soft);
}
.mp-nearmiss-sub a { color: var(--mp-blue); font-weight: 700; }

/* ── Browse by subject ────────────────────────────────── */
/* Deliberately plain and at the foot of the page. Its job is to link every
   subject landing page from every browse page – the chip row above the grid
   only does that on an unfiltered browse – and it should read as a directory,
   not compete with the chips for the same decision. */
.mp-subject-dir {
    margin-top: 44px;
    padding-top: 22px;
    border-top: 1px solid var(--mp-line);
}
.mp-subject-dir h2 {
    margin-bottom: 12px;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}
.mp-subject-dir ul {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 20px;
    list-style: none;
}
.mp-subject-dir a {
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--mp-blue);
    text-decoration: none;
}
.mp-subject-dir a:hover { text-decoration: underline; }
.mp-subject-dir [aria-current] {
    font-size: 0.88rem;
    font-weight: 800;
    color: var(--mp-ink);
}

.mp-footer {
    max-width: 1140px;
    margin: 0 auto;
    padding: 28px 24px 40px;
    border-top: 1px solid var(--mp-line);
    text-align: center;
    font-size: 0.82rem;
    color: var(--mp-ink-soft);
}
.mp-footer p { margin: 4px 0; }
.mp-footer a { color: var(--mp-blue); font-weight: 700; text-decoration: none; }
.mp-footer a:hover { text-decoration: underline; }

@media (prefers-reduced-motion: reduce) {
    .mp-card, .mp-btn, .mp-cta, .mp-chip, .mp-step,
    .mp-pill, .mp-card-save, .mp-select, .mp-search input { transition: none; }
    .mp-card:hover, .mp-btn:hover, .mp-cta:hover, .mp-chip:hover { transform: none; }
}

@media (max-width: 640px) {
    .mp-main { padding: 12px 16px 40px; }
    /* The search takes the full row and the dropdowns share the next one,
       rather than three controls squeezed to unreadable widths. */
    .mp-search { flex-basis: 100%; }
    .mp-select { flex: 1 1 132px; }
    .mp-nav { padding: 14px 16px; gap: 10px; }
    /* Brand shortens to the wordmark so both auth buttons stay on one row. */
    .mp-brand em { display: none; }
    .mp-nav-auth { gap: 6px; }
    .mp-nav-auth .mp-btn, .mp-nav-auth .mp-cta { padding: 8px 12px; font-size: 0.8rem; }
    /* Wrapped under its own copy, the endorse button takes the full row rather
       than sitting as a short pill against the left edge. */
    .mp-endorse { width: 100%; justify-content: center; }
}

/* Narrowest phones: the mark alone carries the brand so the nav still fits. */
@media (max-width: 400px) {
    .mp-nav { padding: 12px; gap: 8px; }
    .mp-brand { font-size: 0; gap: 0; }
    .mp-brand-mark { font-size: 0.82rem; }
}

/* ── Series ───────────────────────────────────────────────
   A series is an ordered run of one teacher's lessons. The catalogue could only
   ever offer one lesson at a time, so a teacher who had written a whole unit had
   no way to say so, and a visitor who found part three of it had no way to reach
   the other seven. Everything here exists to do two things: make a lesson say
   what it is part of, and make the set takeable in one press.

   The weights are picked against the page each block lands on rather than
   against each other. On the series page the take panel is the only thing
   asking to be pressed; on a listing page it is the take panel that already
   holds that job, so the series nav below it stays quiet or the page has two
   things shouting at once. */

/* ── One series ───────────────────────────────────────── */
.mp-series-head { margin-bottom: 20px; }
.mp-series-head h1 {
    margin: 0 0 10px;
    font-size: clamp(1.6rem, 3.6vw, 2.3rem);
    font-weight: 900;
    line-height: 1.18;
    letter-spacing: -0.02em;
}
/* Says what kind of page this is before the title says what it is about. Soft
   ink rather than the amber swash: amber is the heading accent, and a kicker is
   not a heading. */
.mp-series-kicker {
    margin-bottom: 4px;
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}

/* The one thing on this page that asks to be pressed, so it takes the same
   weight .mp-take does on a listing page. It sits ABOVE the list, unlike that
   one, because here the list is the content and it is long – an offer under
   eight cards is an offer nobody scrolls to. */
.mp-series-take {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    margin-bottom: 26px;
    padding: 18px 20px;
    border: 2px solid var(--mp-ink);
    border-radius: var(--mp-radius);
    background: var(--mp-card);
    box-shadow: 0 4px 0 var(--mp-ink);
}
.mp-series-take p { margin: 0; max-width: 60ch; }
.mp-series-take-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}

/* The lessons, numbered outside the cards. The number is the claim the page is
   making – these are meant to be taught in this order – and putting it inside
   the card would make it look like part of the lesson's own title. */
.mp-series-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin-bottom: 30px;
    list-style: none;
}
.mp-series-item {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: start;
    gap: 14px;
}
.mp-series-num {
    padding-top: 4px;
    min-width: 1.4em;
    font-size: 1.05rem;
    font-weight: 900;
    color: var(--mp-ink-soft);
    font-variant-numeric: tabular-nums;
}

/* ── A series card ────────────────────────────────────── */
/* Content in a grid, so the same medium weight .mp-card carries. A series card
   drawn louder than the lesson cards beside it would be claiming to matter more
   than the lessons it is made of. */
.mp-series-card .mp-card-thumb { position: relative; }
/* Two offset paper edges behind the cover slide – the one affordance that says
   "a set of things" without a word of text. */
.mp-series-card .mp-card-thumb::before,
.mp-series-card .mp-card-thumb::after {
    content: '';
    position: absolute;
    inset: 6px 6px auto auto;
    width: 34px;
    height: 22px;
    border: 1px solid var(--mp-line);
    border-radius: 3px;
    background: var(--mp-card);
    transform: rotate(4deg);
    pointer-events: none;
}
.mp-series-card .mp-card-thumb::after { transform: rotate(-3deg) translate(-5px, 3px); }

/* ── A lesson's place in its series ───────────────────── */
/* Above the <h1>, because "Lesson 3 of 8 of Rates of Reaction" is the frame the
   title should be read inside – below it, it reads as an afterthought about a
   page you have already finished judging.

   Built as a pill because that is what a small labelled fact with a link in it
   already is here. Deliberately not green: green on these pages means a claim a
   person made, and being third in a list is a fact about a file. */
.mp-series-eyebrow {
    display: inline-flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
    padding: 5px 14px;
    border: 2px solid var(--mp-line);
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 700;
}
.mp-series-eyebrow-kicker {
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}
.mp-series-eyebrow-link { color: var(--mp-blue); text-decoration: none; }
.mp-series-eyebrow-link:hover { text-decoration: underline; }
.mp-series-eyebrow-at { color: var(--mp-ink-soft); font-weight: 600; }

/* Prev/next, straight after the take panel: someone who has just decided
   whether to take this lesson is exactly where "and here is the next one"
   lands. Quiet, not heavy – it is disclosure that the lesson has neighbours,
   and at the take panel's weight two blocks would be competing to be pressed. */
.mp-series-nav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 12px;
    margin-bottom: 28px;
    padding: 12px 16px;
    border: 1px solid var(--mp-line);
    border-radius: var(--mp-radius);
    background: rgba(255, 253, 249, 0.6);
}
.mp-series-step {
    display: flex;
    flex-direction: column;
    gap: 2px;
    color: inherit;
    font-size: 0.84rem;
    text-decoration: none;
    min-width: 0;
}
.mp-series-step-fwd { text-align: right; }
.mp-series-step-dir {
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}
.mp-series-step-name {
    font-weight: 700;
    /* One line each side. Two lesson titles at full length turn a three-column
       strip into a paragraph with arrows in it. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.mp-series-step:hover .mp-series-step-name { color: var(--mp-blue); text-decoration: underline; }
.mp-series-step-all {
    flex-direction: row;
    align-items: center;
    padding: 6px 14px;
    border: 2px solid var(--mp-line);
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 800;
    white-space: nowrap;
}
.mp-series-step-all:hover { border-color: var(--mp-blue); color: var(--mp-blue); text-decoration: none; }

/* The whole running order, on the lesson's own page. Titles rather than cards:
   a second grid of cards here would read as another related strip, and the
   question this answers is "what else is in this" rather than "what else might
   I like". Medium weight, so it reads as a sibling of the outline above it. */
.mp-series-full {
    margin-bottom: 28px;
    padding: 14px 16px;
    border: 1px solid var(--mp-line);
    border-radius: var(--mp-radius);
    background: var(--mp-card);
}
.mp-series-full h2 {
    margin-bottom: 8px;
    font-size: 0.82rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--mp-ink-soft);
}
.mp-series-full ol { list-style: none; counter-reset: none; }
/* The same numbering as the series page, at the size of a line of text rather
   than of a card – here it labels a row, there it labels a whole lesson. */
.mp-series-full .mp-series-num {
    padding-top: 0;
    min-width: 1.6em;
    font-size: 0.76rem;
    font-weight: 800;
}
.mp-series-full li {
    display: flex;
    align-items: baseline;
    gap: 10px;
    padding: 5px 0;
    border-bottom: 1px solid rgba(221, 213, 200, 0.5);
    font-size: 0.86rem;
}
.mp-series-full li:last-child { border-bottom: 0; }
.mp-series-full a { color: var(--mp-blue); text-decoration: none; }
.mp-series-full a:hover { text-decoration: underline; }
/* Where you are now. Never colour alone – it is also the only row that is not a
   link, which is the stronger signal and the one that survives a screenshot. */
.mp-series-full [aria-current] {
    font-weight: 800;
    color: var(--mp-ink);
}

/* ── Series elsewhere in the catalogue ────────────────── */
/* A heading over a strip of cards, the pattern .mp-related already establishes,
   so no container of its own. */
.mp-series-strip,
.mp-author-series {
    margin-bottom: 34px;
    padding-bottom: 30px;
    border-bottom: 1px solid var(--mp-line);
}
.mp-series-strip h2,
.mp-author-series h2 {
    font-size: 1.15rem;
    font-weight: 800;
    letter-spacing: -0.01em;
}
.mp-series-strip-sub {
    margin: 4px 0 18px;
    max-width: 62ch;
    font-size: 0.9rem;
    color: var(--mp-ink-soft);
}
.mp-author-series h2 { margin-bottom: 18px; }
.mp-series-strip-more {
    margin-top: 16px;
    font-size: 0.88rem;
    font-weight: 700;
}
.mp-series-strip-more a { color: var(--mp-blue); text-decoration: none; }
.mp-series-strip-more a:hover { text-decoration: underline; }

@media (max-width: 640px) {
    /* One lesson title per row rather than three columns of ellipsis. */
    .mp-series-nav { grid-template-columns: 1fr; text-align: left; }
    .mp-series-step-fwd { text-align: left; }
    .mp-series-step-all { align-self: flex-start; }
    .mp-series-item { grid-template-columns: 1fr; gap: 4px; }
    .mp-series-take .mp-cta { width: 100%; text-align: center; }
}

/* ── Slide templates ──────────────────────────────────────────────────────
   A template listing is one slide and a button, so it needs none of the
   viewer, pager or download machinery a lesson listing carries. */
.mp-template-acts { margin: 18px 0 0; }
.mp-template-note {
    margin: 10px 0 0;
    font-size: 0.9rem;
    color: var(--mp-muted, #6b6580);
}
.mp-template-about { margin-top: 28px; max-width: 46rem; }
.mp-template-about h2 { font-size: 1.15rem; margin-bottom: 8px; }
.mp-template-about p { margin: 0 0 10px; line-height: 1.6; }

/* Marketplace sections, on every page. Lessons, series and templates are three
   different things to come here for, and only the first of them used to be
   reachable without knowing the URL. */
.mp-nav-links {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-right: auto;
    margin-left: 8px;
}
.mp-nav-link {
    padding: 7px 12px;
    border-radius: 8px;
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--mp-muted, #6b6580);
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.14s ease, color 0.14s ease;
}
.mp-nav-link:hover { background: rgba(30, 27, 46, 0.06); color: var(--mp-ink, #1e1b2e); }
.mp-nav-link.is-current { color: var(--mp-ink, #1e1b2e); background: rgba(54, 96, 255, 0.1); }

/* The brand keeps the row on its own at narrow widths and the sections wrap
   underneath it, rather than the three of them squeezing the sign-up button
   off the edge. */
@media (max-width: 820px) {
    .mp-nav { flex-wrap: wrap; }
    .mp-nav-links {
        order: 3;
        width: 100%;
        margin: 2px 0 0;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .mp-nav-link { padding: 6px 10px; font-size: 0.86rem; }
}

/* The templates pitch on the lessons browse. A band rather than a card in the
   grid: it is a different kind of thing from the lessons around it, and one
   dressed as a lesson would just be a lesson nobody can open. */
.mp-section-band {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
    margin: 28px 0 4px;
    padding: 20px 24px;
    border: 1px solid rgba(54, 96, 255, 0.22);
    border-radius: 16px;
    background: linear-gradient(100deg, rgba(54, 96, 255, 0.07), rgba(244, 180, 71, 0.07));
}
.mp-section-band-text { flex: 1 1 320px; min-width: 0; }
.mp-section-band h2 { font-size: 1.15rem; margin: 0 0 4px; }
.mp-section-band p { margin: 0; line-height: 1.55; color: var(--mp-muted, #6b6580); }
.mp-section-band .mp-cta { flex: 0 0 auto; }
