/* AI Leadership components: page frames and app components on top of Basecoat (shadcn/ui as plain HTML).
   Needs tokens.css and type.css. Load order: basecoat.css, tokens.css, type.css, components.css.
   The app uses only these classes; it defines no colors, fonts or components of its own. */

body { background: var(--background); color: var(--foreground); font-family: var(--font-sans); }
.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.muted { color: var(--muted-foreground); }
::placeholder { color: var(--placeholder); opacity: 1; }
.stack > * + * { margin-top: 16px; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.reading { max-width: 680px; }
.note { font-size: 14px; color: var(--muted-foreground); }
/* A note under a table, list, grid or form keeps a gap to it (0.45.1); form sections keep their own 20px. */
:where(table, ul, ol, dl, pre, figure, form, .medal-grid, .prompt, .data-table) + p.note { margin-top: 12px; }

/* ---- Button: the brand call to action (one per view). Other buttons use Basecoat variants. ---- */
.btn[data-variant="brand"], .btn-brand { background: var(--brand); color: var(--brand-foreground); border: 1px solid transparent; }
.btn[data-variant="brand"]:hover, .btn-brand:hover { background: color-mix(in srgb, var(--brand) 88%, var(--foreground)); }
:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }

/* ---- Site frame (guests) ---- */
/* ---- Wordmark with the AL mark (0.23.0): a.wordmark > svg.mark (dist/img/brand/ai-leadership-mark.svg, inline) + span.wordmark-name.
   The mark takes the colour of the text, so it follows light, dark and the header over an image. */
.wordmark { display: inline-flex; align-items: center; gap: .6em; white-space: nowrap; }
.wordmark .mark { height: 1.45em; width: auto; flex: none; }
.site-footer .wordmark, .app-footer .wordmark { color: var(--foreground); font-size: 13px; }
/* Mask mark (0.36.0): the mark of another instance, from an image file (SVG or transparent PNG) as a CSS mask filled with
   the text colour, so it follows light, dark and the header over an image like the inline mark. The file must come from
   the same origin (a mask needs CORS otherwise). Markup: span.mark.mark-mask[style="--mark: url(/brand/mark); --mark-ratio: 1.58"]
   with aria-hidden; --mark-ratio is width / height of the file. Sizes come from .mark in every place. */
.mark-mask { display: inline-block; aspect-ratio: var(--mark-ratio, 1); background: currentColor;
  -webkit-mask: var(--mark) center / contain no-repeat; mask: var(--mark) center / contain no-repeat; }
/* Small screens: the header shows the mark only; the name stays for screen readers (.visually-hidden rules). */
@media (max-width: 520px) {
  .site-header .wordmark .wordmark-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .site-header .wordmark .mark { height: 28px; }
}
/* Stacked variant (.wordmark-stacked, and always in the app sidebar): one word per line, the mark as high as the
   three lines (cap top to baseline). */
.app-sidebar .wordmark, .wordmark-stacked { white-space: normal; line-height: 1.3; gap: 12px; }
.app-sidebar .wordmark .mark, .wordmark-stacked .mark { height: 3.3em; }
.wordmark-stacked .wordmark-name { width: min-content; }
.site-header { position: absolute; inset: 0 0 auto 0; z-index: 10; }
.site-header-inner { display: flex; align-items: center; justify-content: space-between; height: 72px; }
.site-header .wordmark { color: var(--on-image); }
.site-header .btn { color: var(--on-image); }
.site-header-solid { position: static; border-bottom: 1px solid var(--border); }
.site-header-solid .wordmark, .site-header-solid .btn { color: var(--foreground); }
.site-footer { border-top: 1px solid var(--border); margin-top: 96px; }
.site-footer-inner { display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap; padding-top: 32px; padding-bottom: 48px; font-size: 13px; color: var(--muted-foreground); }
.site-footer a { color: var(--muted-foreground); text-decoration: none; }
.site-footer a:hover { color: var(--foreground); }

.section { padding: 96px 0; border-top: 1px solid var(--border); }
.hero-slider + .section { border-top: 0; }
.section-head { display: grid; gap: 12px; margin-bottom: 48px; max-width: 680px; }
.pillars { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; }
.pillar { padding-top: 16px; border-top: 1px solid var(--primary); }
.pillar h3 { font: 400 24px/1.25 var(--font-subtitle); margin: 12px 0 8px; }
.pillar p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted-foreground); }
@media (max-width: 900px) { .pillars { grid-template-columns: 1fr; } }

/* ---- Hero slider: dark photo, display title, lead, one brand call to action ----
   Markup: section.hero-slider > .hero-slide[data-active] (img.hero-image + .hero-copy) + nav.hero-dots.
   Motion: slow cross-fade with a gentle zoom; the copy rises 12 px. hero-slider.js turns the slides. */
.hero-slider { position: relative; min-height: min(92vh, 860px); overflow: hidden; background: var(--image-scrim); color: var(--on-image); isolation: isolate; }
.hero-slide { position: absolute; inset: 0; opacity: 0; visibility: hidden;
              transition: opacity 1400ms cubic-bezier(.4, 0, .2, 1), visibility 0s linear 1400ms; }
.hero-slide[data-active] { opacity: 1; visibility: visible; transition: opacity 1400ms cubic-bezier(.4, 0, .2, 1), visibility 0s; }
.hero-image { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scale(1.06);
              filter: grayscale(.35) contrast(1.02); transition: transform 9000ms linear; }
.hero-slide[data-active] .hero-image { transform: scale(1); }
.hero-slide::after { content: ""; position: absolute; inset: 0;
                     background: linear-gradient(90deg, color-mix(in srgb, var(--image-scrim) 82%, transparent) 0%,
                     color-mix(in srgb, var(--image-scrim) 55%, transparent) 45%, color-mix(in srgb, var(--image-scrim) 15%, transparent) 100%); }
/* Film grain: the touch of retro */
.hero-slider::after { content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: .14; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.hero-copy { position: relative; z-index: 1; height: 100%; display: flex; flex-direction: column; justify-content: center;
             max-width: 1200px; margin: 0 auto; padding: 120px 24px 140px; min-height: min(92vh, 860px); box-sizing: border-box; }
.hero-copy > * { max-width: 760px; opacity: 0; transform: translateY(12px);
                 transition: opacity 900ms ease-out, transform 900ms cubic-bezier(.2, .7, .2, 1); }
.hero-slide[data-active] .hero-copy > * { opacity: 1; transform: none; }
.hero-slide[data-active] .hero-copy > :nth-child(2) { transition-delay: 250ms; }
.hero-slide[data-active] .hero-copy > :nth-child(3) { transition-delay: 400ms; }
.hero-slide[data-active] .hero-copy > :nth-child(4) { transition-delay: 550ms; }
.hero-copy .eyebrow { color: color-mix(in srgb, var(--on-image) 72%, transparent); }
.hero-copy .display { margin-top: 20px; color: var(--on-image); }
.hero-copy .lead { margin-top: 24px; max-width: 600px; color: color-mix(in srgb, var(--on-image) 78%, transparent); }
.hero-copy .row { margin-top: 40px; }
.hero-copy .btn[data-variant="brand"] { border-color: color-mix(in srgb, var(--on-image) 22%, transparent); }
.hero-copy .btn[data-variant="ghost"] { color: var(--on-image); }
.hero-copy .btn[data-variant="ghost"]:hover { background: color-mix(in srgb, var(--on-image) 10%, transparent); }
.hero-dots { position: absolute; z-index: 3; left: 0; right: 0; bottom: 40px; max-width: 1200px; margin: 0 auto; padding: 0 24px;
             display: flex; align-items: center; gap: 20px; }
.hero-dots button { all: unset; cursor: pointer; display: flex; align-items: center; gap: 10px;
                    font: 400 14px var(--font-label); letter-spacing: .1em; text-transform: lowercase;
                    color: color-mix(in srgb, var(--on-image) 55%, transparent); }
.hero-dots button::after { content: ""; width: 48px; height: 1px; background: color-mix(in srgb, var(--on-image) 30%, transparent); }
.hero-dots button[aria-current="true"] { color: var(--on-image); }
.hero-dots button[aria-current="true"]::after { background: var(--on-image); }
.hero-dots button:focus-visible { outline: 2px solid var(--on-image); outline-offset: 4px; }
@media (prefers-reduced-motion: reduce) {
  .hero-slide, .hero-image, .hero-copy > * { transition: none !important; transform: none !important; }
}
@media (max-width: 700px) { .hero-dots button::after { width: 24px; } }

/* ---- Auth pages ---- */
.auth { max-width: 440px; margin: 96px auto; padding: 0 24px; }
.auth .display { margin: 12px 0 8px; }
.auth form { margin-top: 28px; display: grid; gap: 16px; }
/* Sign-in page of a product (0.52): .auth-split > .auth-media (img, one or up to three) + .auth. One image is a still;
   with data-gallery the images change slowly (dist/auth-gallery.js moves data-active). On a phone the image is a band
   above the form. */
.auth-split { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: center; gap: 0;
  min-height: calc(100vh - 160px); }
.auth-split .auth { margin: 64px auto; }
.auth-media { position: relative; align-self: stretch; min-height: 420px; overflow: hidden; border-radius: var(--radius); margin: 24px 0 24px 24px;
  background: var(--muted); }
.auth-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 1.6s ease; }
.auth-media img[data-active] { opacity: 1; }
@media (max-width: 860px) {
  .auth-split { grid-template-columns: minmax(0, 1fr); min-height: 0; }
  .auth-media { min-height: 0; aspect-ratio: 16 / 9; margin: 16px 16px 0; }
  .auth-split .auth { margin: 40px auto 64px; }
}
@media (prefers-reduced-motion: reduce) { .auth-media img { transition: none; } }
.code-input { font: 500 24px var(--font-mono); letter-spacing: .4em; text-align: center; height: 52px; }

/* ---- App shell (members): sidebar, header, content, footer ---- */
.app-shell { display: grid; grid-template-columns: 248px minmax(0, 1fr); min-height: 100vh; }
.app-sidebar { border-right: 1px solid var(--border); padding: 20px 14px; display: flex; flex-direction: column; gap: 2px;
               position: sticky; top: 0; height: 100vh; overflow-y: auto; background: var(--background); box-sizing: border-box; }
.app-sidebar .wordmark { padding: 6px 10px 20px; color: var(--foreground); }
.app-sidebar .eyebrow { padding: 18px 10px 6px; }
.nav-link { display: flex; align-items: center; gap: 10px; font-size: 14px; padding: 7px 10px; border-radius: 6px;
            text-decoration: none; color: var(--muted-foreground); }
.nav-link:hover { background: var(--accent); color: var(--foreground); }
.nav-link[aria-current="page"] { background: var(--accent); color: var(--foreground); }
.nav-link svg { width: 16px; height: 16px; flex: none; }
.app-main { display: flex; flex-direction: column; min-width: 0; }
.app-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 60px; padding: 0 32px;
              border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 5;
              background: color-mix(in srgb, var(--background) 88%, transparent); backdrop-filter: blur(10px); }
.app-header .crumbs { font-size: 14px; color: var(--muted-foreground); display: flex; gap: 8px; align-items: center; }
.app-header .crumbs a { color: inherit; text-decoration: none; }
.app-header .crumbs a:hover { color: var(--foreground); }
.app-header .crumbs > * { white-space: nowrap; }
.app-header .crumbs > :last-child { color: var(--foreground); overflow: hidden; text-overflow: ellipsis; }
.app-header .crumbs { min-width: 0; }
.app-user { display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--muted-foreground); }
.app-content { padding: 40px 32px 64px; flex: 1; }
.app-footer { border-top: 1px solid var(--border); padding: 20px 32px; display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap;
              font-size: 13px; color: var(--muted-foreground); }
.app-footer a { color: var(--muted-foreground); text-decoration: none; }
.menu-toggle { display: none; }
@media (max-width: 900px) {
  .app-shell { grid-template-columns: 1fr; }
  .app-sidebar { display: none; position: fixed; inset: 0 30% 0 0; z-index: 20; height: auto; box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--image-scrim) 30%, transparent); }
  .app-shell[data-menu="open"] .app-sidebar { display: flex; }
  .menu-toggle { display: inline-flex; }
  .app-header, .app-content, .app-footer { padding-left: 20px; padding-right: 20px; }
  /* Breadcrumbs: a small strip under the header border that stays with the sticky header. Only the last two steps
     show; "…" stands for the steps before them. */
  .app-header .crumbs { position: absolute; top: 100%; left: 0; right: 0; height: 28px; padding: 0 20px; gap: 6px;
                        font-size: 12px; border-bottom: 1px solid var(--border);
                        background: color-mix(in srgb, var(--background) 88%, transparent); backdrop-filter: blur(10px); }
  .app-header .crumbs > :not(:nth-last-child(-n+3)) { display: none; }
  .app-header .crumbs:has(> :nth-child(4))::before { content: "…"; }
  .app-content { padding-top: 60px; }
}

/* ---- Dashboard ---- */
.greeting { margin-bottom: 40px; }
.greeting .display { margin-top: 8px; }
.greeting .lead { margin-top: 16px; max-width: 680px; }
.split { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 40px; align-items: start; }
/* Even split (0.45): two equal columns, e.g. the rules and the recent list of the progress page. */
.split[data-even] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* A split after a grid or table keeps the section gap of a block head (0.45.2). */
:where(.medal-grid, .data-table, .card-grid) + .split { margin-top: 48px; }
/* Stacked, the aside comes last: it keeps a distance to the block after the split. */
@media (max-width: 1100px) { .split { grid-template-columns: 1fr; } .split > aside:last-child { margin-bottom: 40px; } }
.block-head { display: flex; align-items: baseline; justify-content: space-between; margin: 48px 0 16px; }
.block-head:first-child { margin-top: 0; }
.block-head a { font-size: 13px; color: var(--muted-foreground); }

/* ---- Product grid and cards ---- */
.product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
/* The grid follows the number of products (0.15, data-count on .product-grid): 1 is one wide horizontal card,
   2 two columns, 3 three, 4 two by two; 5 and more flow. On a phone always one column, cards vertical. */
.product-grid[data-count="1"] { grid-template-columns: 1fr; }
.product-grid[data-count="2"], .product-grid[data-count="4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.product-grid[data-count="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.product-grid[data-count="1"] .product-card { justify-content: center; gap: 10px; padding: 32px; min-height: clamp(240px, 26vw, 380px); }
.product-grid[data-count="1"] .product-card:has(.cover) { position: relative; padding-left: calc(50% + 32px); }
.product-grid[data-count="1"] .product-card .cover { position: absolute; inset: 0 50% 0 0; margin: 0; aspect-ratio: auto;
                                                     border-bottom: 0; border-right: 1px solid var(--border); }
.product-grid[data-count="1"] .product-card h3 { font-size: 32px; line-height: 1.15; }
.product-grid[data-count="1"] .product-card p { font-size: 16px; }
.product-grid[data-count="1"] .product-card .meta { margin-top: 8px; }
@media (max-width: 900px) { .product-grid[data-count="3"] { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px) {
  .product-grid[data-count] { grid-template-columns: 1fr; }
  .product-grid[data-count="1"] .product-card:has(.cover) { position: relative; padding: 20px; min-height: 0; }
  .product-grid[data-count="1"] .product-card .cover { position: relative; inset: auto; aspect-ratio: 16 / 9; margin: -20px -20px 8px;
                                                       border-right: 0; border-bottom: 1px solid var(--border); }
  .product-grid[data-count="1"] .product-card h3 { font-size: 24px; }
}
.product-card { display: flex; flex-direction: column; gap: 8px; padding: 20px; text-decoration: none; color: inherit; overflow: hidden;
                border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); transition: border-color .15s ease-out; }
.product-card:hover { border-color: var(--muted-foreground); }
.product-card .cover { aspect-ratio: 16 / 9; margin: -20px -20px 8px; background: var(--muted) center / cover no-repeat;
                       border-bottom: 1px solid var(--border); filter: grayscale(.35); }
/* Price: the current price, optionally a struck-through one before it and a note after it. */
.price { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-top: 4px; color: var(--primary); }
.price-now { font: 400 24px/1.2 var(--font-subtitle); }
.price-was { font-size: 16px; color: var(--muted-foreground); text-decoration: line-through; }
.price-note { font-size: 14px; color: var(--muted-foreground); }
.product-card h3 { font: 400 22px/1.25 var(--font-subtitle); margin: 0; color: var(--primary); }
.product-card p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--muted-foreground); }
/* The description on a card (0.46.1): cut off with an ellipsis, three lines, more where the card is wider. */
.product-card .card-description { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
.product-grid[data-count="2"] .card-description { -webkit-line-clamp: 4; line-clamp: 4; }
.product-grid[data-count="1"] .card-description { -webkit-line-clamp: 6; line-clamp: 6; }
.product-card .meta { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: auto; padding-top: 8px; font-size: 13px; color: var(--muted-foreground); }
/* Continue (0.27): a card with its own button. The card is a div; the title link stretches over the whole card, the
   Continue button sits above it. Markup: div.product-card > ... h3 > a.card-link ... + .meta + a.btn.card-continue */
div.product-card { position: relative; }
.product-card .card-link { color: inherit; text-decoration: none; }
.product-card .card-link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.product-card .card-link:focus-visible { outline: none; }
.product-card:has(.card-link:focus-visible) { outline: 2px solid var(--ring); outline-offset: 2px; }
div.product-card:has(.card-link:hover) { border-color: var(--muted-foreground); }
.product-card .card-continue { position: relative; z-index: 1; align-self: flex-start; margin-top: 4px; }
/* Continue in the product header: a brand button and the lesson it opens. Markup: .stats > .continue > a.btn + small */
.product-header .continue { display: grid; gap: 6px; justify-items: start; }
.product-header .continue small { font-size: 12px; color: inherit; opacity: .85; }
/* A video with a saved position (0.32): an overlay on the player blurs the thumbnail and replaces its play button.
   Markup: .video > iframe + div.video-resume > button.video-resume-play (svg + span "Continue at 12:34") + button.link */
.video { position: relative; }
.video-resume { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 14px;
  background: color-mix(in oklab, var(--image-scrim) 45%, transparent); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  color: var(--on-image); transition: opacity .2s ease-out; }
.video-resume[data-leaving] { opacity: 0; pointer-events: none; }
.video-resume-play { display: inline-flex; align-items: center; gap: 12px; padding: 10px 22px 10px 12px; border: 0; border-radius: 999px;
  background: var(--on-image); color: var(--image-scrim); font: inherit; font-size: 15px; font-weight: 500; line-height: 1; cursor: pointer; box-shadow: 0 8px 30px rgb(0 0 0 / .25);
  transition: transform .15s ease-out; }
.video-resume-play:hover { transform: scale(1.03); }
.video-resume-play svg { width: 36px; height: 36px; padding: 10px; border-radius: 50%; background: var(--brand); color: var(--on-image); }
.video-resume .link { padding: 0; border: 0; background: none; font: 400 13px/1.4 var(--font-mono); color: inherit; cursor: pointer;
  text-decoration: underline; text-decoration-color: color-mix(in oklab, currentColor 50%, transparent); text-underline-offset: 3px; }
.video-resume .link:hover { text-decoration-color: currentColor; }
.progress { height: 2px; background: var(--border); border-radius: 2px; overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--brand); }

/* ---- Product page ---- */
.product-header { padding-bottom: 32px; margin-bottom: 40px; border-bottom: 1px solid var(--border);
                  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 32px; align-items: end; }
.product-header .display { margin: 10px 0 0; }
.product-header .lead { margin-top: 16px; }
/* The description inside the header (0.46): p.product-intro after the lead, on a cover too. */
.product-header .product-intro { margin: 12px 0 0; max-width: 62ch; font-size: 15px; line-height: 1.55; color: var(--muted-foreground); }
.product-header .stats { min-width: 220px; display: grid; gap: 8px; font-size: 13px; color: var(--muted-foreground); }
.product-header .cover { grid-column: 1 / -1; aspect-ratio: 21 / 7; border-radius: var(--radius); border: 1px solid var(--border);
                         background: var(--muted) center / cover no-repeat; order: -1; filter: grayscale(.35); }
.terms { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 16px; }
@media (max-width: 900px) { .product-header { grid-template-columns: 1fr; } }
/* Cover header (0.25): the texts, terms and progress sit on the cover, bottom-aligned, to save height.
   Markup: header.product-header[data-cover][data-tone] > .cover (img) + div (texts) + .stats.
   data-tone is the measured brightness of the lower part of the image (the app measures it at upload):
   dark (default) = light text on a dark scrim, light = dark text on a light scrim. The scrim keeps the text
   readable when the image is mixed. Without a cover the header stays as above. */
.product-header[data-cover] { position: relative; isolation: isolate; overflow: hidden; min-height: max(300px, calc((min(100vw, 1200px) - 64px) / 3));
  padding: 32px; border: 1px solid var(--border); border-radius: var(--radius); color: var(--on-image); --scrim: var(--image-scrim); --scrim-mid: 62%; }
.product-header[data-cover][data-tone="light"] { color: var(--foreground); --scrim: var(--background); --scrim-mid: 84%; }
.product-header[data-cover] > .cover { position: absolute; inset: 0; z-index: -2; grid-area: auto; aspect-ratio: auto; border: 0; border-radius: 0; }
.product-header[data-cover]::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(to top, color-mix(in srgb, var(--scrim) 90%, transparent) 0%, color-mix(in srgb, var(--scrim) var(--scrim-mid), transparent) 45%, transparent 90%); }
.product-header[data-cover] .display { color: inherit; }
.product-header[data-cover] .eyebrow, .product-header[data-cover] .eyebrow.brand { color: color-mix(in srgb, currentColor 74%, transparent); }
.product-header[data-cover] .lead, .product-header[data-cover] .product-intro, .product-header[data-cover] .stats { color: color-mix(in srgb, currentColor 84%, transparent); }
.product-header[data-cover] .badge[data-variant="outline"] { color: inherit; border-color: color-mix(in srgb, currentColor 40%, transparent); }
.product-header[data-cover] .progress { background: color-mix(in srgb, currentColor 28%, transparent); }
.product-header[data-cover] .progress > span { background: currentColor; }
@media (max-width: 900px) { .product-header[data-cover] { grid-template-columns: minmax(0, 1fr); gap: 20px; min-height: 360px; padding: 24px; } }
.module { margin-bottom: 40px; }
.module-head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding-bottom: 10px; }
.module-head h2 { font: 400 24px/1.25 var(--font-subtitle); margin: 4px 0 0; color: var(--primary); }
.module-head p { margin: 6px 0 0; font-size: 14px; color: var(--muted-foreground); }
/* A module title that links to its lessons or its lesson index (0.47). */
.module-head h2 a, .index-module h2 a { color: inherit; text-decoration: none; }
.module-head h2 a:hover, .index-module h2 a:hover { text-decoration: underline; text-underline-offset: 4px; }
.unit-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border); }
.unit-list li { border-bottom: 1px solid var(--border); }
.unit-list a, .unit-list .locked { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: 12px; align-items: center;
                                   padding: 12px 4px; text-decoration: none; color: inherit; font-size: 15px; }
.unit-list a:hover { background: var(--accent); }
.unit-list .locked { color: var(--muted-foreground); }
.unit-list .device { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 12px 4px; font-size: 15px; }
.unit-list .check { width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--border); display: grid; place-items: center; box-sizing: border-box; }
.unit-list .check[data-done] { background: var(--brand); border-color: var(--brand); color: var(--brand-foreground); }
.unit-list .check svg { width: 12px; height: 12px; }
.unit-list .info { font-size: 13px; color: var(--muted-foreground); }
/* In a module card (narrow) the info (length, opening date) goes under the title, so a long title keeps its width (0.50). */
.module-card .unit-list a, .module-card .unit-list .locked { grid-template-columns: 28px minmax(0, 1fr); row-gap: 2px; }
.module-card .unit-list .info { grid-column: 2; }
.module-card .unit-list .info:empty { display: none; }

/* Module layouts (0.34): .modules[data-layout] wraps the module index of a product page.
   list (default): .module sections as above. compact: the same markup, tighter, without module texts and with small
   headings. cards: .module-cards > a.module-card or div.module-card[data-locked] (cover, eyebrow, h3, p, .meta, .progress);
   the card opens the next lesson of the module. timeline: .module-timeline > .timeline-item (.timeline-date + .timeline-body
   with the module head and a compact unit list); items alternate left and right of the line, one side on a phone.
   The eyebrow "Module 01" is optional in every layout. */
.modules[data-layout="compact"] .module { margin-bottom: 24px; }
.modules[data-layout="compact"] .module-head { padding-bottom: 6px; }
.modules[data-layout="compact"] .module-head h2 { font-size: 18px; }
.modules[data-layout="compact"] .module-head p { display: none; }
.modules[data-layout="compact"] .unit-list a, .modules[data-layout="compact"] .unit-list .locked { padding: 7px 4px; font-size: 14px; grid-template-columns: 22px minmax(0, 1fr) auto; }
.modules[data-layout="compact"] .unit-list .check { width: 14px; height: 14px; }
.modules[data-layout="compact"] .unit-list .check svg { width: 9px; height: 9px; }
.module-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; margin-bottom: 40px; }
.module-card { display: flex; flex-direction: column; gap: 8px; padding: 20px; text-decoration: none; color: inherit; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); transition: border-color .15s ease-out; }
a.module-card:hover { border-color: var(--muted-foreground); }
.module-card .cover { aspect-ratio: 16 / 9; margin: -20px -20px 8px; background: var(--muted); border-bottom: 1px solid var(--border); overflow: hidden; filter: grayscale(.35); }
.module-card .cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.module-card h3 { font: 400 22px/1.25 var(--font-subtitle); margin: 0; color: var(--primary); }
.module-card p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--muted-foreground); }
.module-card .meta { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: auto; padding-top: 8px; font-size: 13px; color: var(--muted-foreground); }
.module-card[data-locked] { color: var(--muted-foreground); background: var(--muted); }
.module-card[data-locked] h3 { color: var(--muted-foreground); }
.module-timeline { position: relative; display: grid; gap: 32px; margin: 8px 0 48px; }
.module-timeline::before { content: ""; position: absolute; top: 6px; bottom: 6px; left: 50%; width: 1px; background: var(--border); }
.timeline-item { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 56px; }
.timeline-item::before { content: ""; position: absolute; top: 6px; left: calc(50% - 6px); width: 11px; height: 11px; border-radius: 50%;
  border: 1px solid var(--brand); background: var(--background); box-sizing: border-box; }
.timeline-item[data-open]::before { background: var(--brand); }
.timeline-date { justify-self: end; text-align: right; font: 400 13px/1.4 var(--font-mono); color: var(--muted-foreground); padding-top: 2px; }
.timeline-date strong { display: block; font: 400 22px/1.2 var(--font-subtitle); color: var(--primary); }
.timeline-item:nth-child(even) .timeline-date { order: 2; justify-self: start; text-align: left; }
.timeline-body .module-head { padding-bottom: 8px; }
.timeline-body .module-head h2 { margin-top: 0; }
.timeline-body .unit-list a, .timeline-body .unit-list .locked { padding: 7px 4px; font-size: 14px; grid-template-columns: 22px minmax(0, 1fr) auto; }
.timeline-body .unit-list .check { width: 14px; height: 14px; }
.timeline-body .unit-list .check svg { width: 9px; height: 9px; }
/* Milestones (0.40): the timeline as a release history. .module-timeline[data-milestones] > .timeline-item#<anchor>
   (.timeline-date with strong date and area, .timeline-body with .title-row > h2 + the icon button
   button.btn[data-variant=ghost][data-size=icon][data-copy-text] (svg.icon-copy + svg.icon-done), then p).
   The item in the URL hash gets a ring on its dot. */
.module-timeline[data-milestones] .timeline-item { scroll-margin-top: 96px; }
.module-timeline[data-milestones] .timeline-body h2 { margin: 4px 0 8px; font: 400 26px/1.25 var(--font-subtitle); color: var(--primary); }
.module-timeline[data-milestones] .timeline-body p { margin: 0 0 12px; font-size: 15px; line-height: 1.6; }
.module-timeline[data-milestones] .timeline-body .row { gap: 8px; }
/* A page title with icon actions on the right (0.40.2): .greeting > .title-row > h1 + .row of
   a.btn[data-variant=ghost][data-size=icon] with aria-label and title. */
.greeting > .title-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 8px; }
.greeting > .title-row .display { margin-top: 0; }
.greeting > .title-row .row { flex: none; gap: 4px; }
.greeting > .title-row .btn { color: var(--muted-foreground); }
.greeting > .title-row .btn:hover { color: var(--foreground); }
/* Click-to-edit title (0.51): .greeting > .title-row > form.inline-title[data-inline-save] > input.display.display-lg
   + .inline-status. The input reads as the heading; hover and focus show its edge. inline-save.js saves on leave
   (change) or Enter. A main action of the page (Publish: .btn[data-variant=brand]; Unpublish:
   .btn[data-variant=secondary]) sits in the .row with the icon buttons and keeps its own colours. */
.greeting > .title-row .inline-title { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; }
.inline-title > input.display { flex: 1; min-width: 0; width: 100%; padding: 2px 8px; margin: 0 0 0 -8px; border: 1px solid transparent;
  border-radius: var(--radius); background: none; color: inherit; font: inherit; font-family: var(--font-display);
  font-size: clamp(36px, 4.5vw, 48px); line-height: 1.08; cursor: text; }
.inline-title > input.display:hover { border-color: var(--border); }
.inline-title > input.display:focus { border-color: var(--ring, var(--brand)); outline: none; background: var(--background); }
.greeting > .title-row .row .btn[data-variant="brand"] { color: var(--brand-foreground, #fff); }
.greeting > .title-row .row .btn[data-variant="secondary"] { color: var(--secondary-foreground, var(--foreground)); }
.module-timeline[data-milestones] .title-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.module-timeline[data-milestones] .title-row .btn { flex: none; margin-top: 2px; color: var(--muted-foreground); }
.module-timeline[data-milestones] .title-row .btn:hover { color: var(--foreground); }
button[data-copy-text] .icon-done, button[data-copy-text][data-done] .icon-copy,
button[data-copy-url] .icon-done, button[data-copy-url][data-done] .icon-copy { display: none; }
button[data-copy-text][data-done] .icon-done, button[data-copy-url][data-done] .icon-done { display: inline; }
.module-timeline[data-milestones] .timeline-item:target::before { background: var(--brand); box-shadow: 0 0 0 5px var(--brand-soft); }
@media (max-width: 760px) {
  .module-timeline::before { left: 5px; }
  .timeline-item, .timeline-item:nth-child(even) { grid-template-columns: minmax(0, 1fr); padding-left: 28px; row-gap: 6px; }
  .timeline-item::before { left: 0; }
  .timeline-date, .timeline-item:nth-child(even) .timeline-date { order: 0; justify-self: start; text-align: left; }
}

/* Welcome block (0.34): shown at the top of a product page. .product-welcome[data-columns="1|2"] > .video (optional) +
   .prose. Two columns put the video left and the text right; one column stacks them. A phone always stacks. */
.product-welcome { display: grid; gap: 24px; margin-bottom: 48px; }
.product-welcome[data-columns="2"] { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); align-items: start; gap: 32px; }
/* data-split (0.49.4): the widths of video and text side by side; 1-2 = video 1/3, 1-1 = halves, 2-1 = video 2/3. */
.product-welcome[data-columns="2"][data-split="1-2"] { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
.product-welcome[data-columns="2"][data-split="1-1"] { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.product-welcome[data-columns="2"][data-split="2-1"] { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.product-welcome .prose > :first-child { margin-top: 0; }
@media (max-width: 900px) { .product-welcome[data-columns="2"], .product-welcome[data-columns="2"][data-split] { grid-template-columns: minmax(0, 1fr); } }

/* Links (0.34): entry points on a product page: a module, a lesson, another product, an external page.
   .link-section > .block-head + .links[data-style="list|buttons|cards"] > a.link-item (svg.link-icon optional,
   span.link-title, small.link-text). list: rows with an arrow; buttons: a row of outline buttons (the first may be
   brand); cards: a grid of small cards. An external link carries target="_blank" and data-external (the arrow turns). */
.link-section { margin-bottom: 48px; }
.links[data-style="list"] { display: grid; border-top: 1px solid var(--border); }
.links[data-style="list"] .link-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 16px; align-items: center; padding: 14px 4px;
  border-bottom: 1px solid var(--border); text-decoration: none; color: inherit; }
.links[data-style="list"] .link-item:hover { background: var(--accent); }
.links[data-style="list"] .link-item::after { content: "→"; grid-column: 2; grid-row: 1 / span 2; color: var(--muted-foreground); }
.links[data-style="list"] .link-item[data-external]::after { content: "↗"; }
.link-title { font-size: 15px; color: var(--primary); }
.link-text { font-size: 13px; color: var(--muted-foreground); }
.links[data-style="buttons"] { display: flex; flex-wrap: wrap; gap: 10px; }
.links[data-style="buttons"] .link-text { display: none; }
.links[data-style="buttons"] .link-title { font-size: inherit; color: inherit; }
.links[data-style="cards"] { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.links[data-style="cards"] .link-item { display: grid; gap: 4px; align-content: start; padding: 16px 18px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card); text-decoration: none; color: inherit; transition: border-color .15s ease-out; }
.links[data-style="cards"] .link-item:hover { border-color: var(--muted-foreground); }
.links[data-style="cards"] .link-title { font: 400 19px/1.3 var(--font-subtitle); }
.links[data-style="cards"] .link-item[data-external] .link-title::after { content: " ↗"; font-size: 14px; color: var(--muted-foreground); }

/* Audio player (0.34, dist/audio-player.js): an MP3 or M4A in a lesson or page. Markup: figure.audio-player > audio[controls]
   [src] + .audio-ui (button.audio-play, .audio-body > strong.audio-title + input.audio-seek[type=range] + .audio-meta >
   span.audio-time + button.audio-rate) + a.audio-download[download] (optional). Without the script the native player shows;
   the script hides it and turns the UI on (data-ready). data-playing switches the play icon. */
.audio-player { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 12px; margin: 24px 0; padding: 14px 16px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
.audio-player audio { width: 100%; }
.audio-player[data-ready] audio { display: none; }
.audio-ui { display: none; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 14px; }
.audio-player[data-ready] .audio-ui { display: grid; }
.audio-play { width: 44px; height: 44px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: var(--brand); color: var(--brand-foreground); transition: transform .15s ease-out; }
.audio-play:hover { transform: scale(1.05); }
.audio-play:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.audio-play svg { width: 18px; height: 18px; }
.audio-play .icon-pause, .audio-player[data-playing] .audio-play .icon-play { display: none; }
.audio-player[data-playing] .audio-play .icon-pause { display: block; }
.audio-body { display: grid; gap: 4px; min-width: 0; }
.audio-title { font: 400 17px/1.3 var(--font-subtitle); color: var(--primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.audio-seek { width: 100%; height: 18px; margin: 0; accent-color: var(--brand); cursor: pointer; }
.audio-meta { display: flex; justify-content: space-between; gap: 12px; font: 400 12px/1.4 var(--font-mono); color: var(--muted-foreground); }
.audio-rate { padding: 0 4px; border: 0; background: none; font: inherit; color: inherit; cursor: pointer; border-radius: 4px; }
.audio-rate:hover { color: var(--foreground); background: var(--accent); }
.audio-download { align-self: center; }
@media (max-width: 520px) { .audio-player { grid-template-columns: minmax(0, 1fr); } .audio-download { justify-self: start; } }
@media print { .audio-player { display: none; } }

/* ---- Unit page ---- */
.unit-page { max-width: 820px; }
.unit-page .display { margin: 10px 0 24px; }
.video { aspect-ratio: 16 / 9; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--muted); }
.video iframe { width: 100%; height: 100%; border: 0; }
.unit-page .lead { margin-top: 32px; }
.unit-body { margin-top: 32px; }
.unit-actions { margin-top: 32px; }
.unit-nav { display: flex; justify-content: space-between; gap: 16px; margin-top: 48px; padding-top: 24px; border-top: 1px solid var(--border); }

/* ---- Q&A under a unit (0.20): threads of a question and its replies, editorial and quiet.
   Markup: section.qa > .block-head + form.qa-form + .qa-thread* (+ a.btn "Older questions")
           .qa-thread[id=q-<id>][data-new][data-hidden] > .qa-post (the question) + .qa-replies > .qa-post* + form.qa-form
           .qa-post[data-hidden][data-deleted] > .avatar + div > .qa-meta (strong name, .badge, time) + .qa-body (+ .qa-actions)
   .qa-new marks a thread with unread posts; .nav-count is a small count after a sidebar link. ---- */
/* My notes (0.26): a private note under the lesson. details.notes-card[open when a note exists] > summary (title + hint)
   + form.notes-form (textarea.textarea.notes-input + .notes-foot: .notes-status aria-live; the script removes the Save button, kept for use without
   JavaScript) + .notes-print (the saved text as plain lines; shown only in print, where a textarea would be cut). */
.notes-card { margin-top: 40px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
.notes-card > summary { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 14px 18px; cursor: pointer;
  list-style: none; font: 400 19px/1.3 var(--font-subtitle); color: var(--primary); }
.notes-card > summary::-webkit-details-marker { display: none; }
.notes-card > summary::after { content: "+"; font-family: var(--font-mono); font-size: 16px; color: var(--muted-foreground); }
.notes-card[open] > summary::after { content: "−"; }
.notes-card > summary small { margin-left: auto; font: 400 12px/1.4 var(--font-sans); color: var(--muted-foreground); }
.notes-card .notes-body { padding: 0 18px 16px; }
.notes-input { width: 100%; min-height: 160px; resize: vertical; font: 400 17px/1.6 var(--font-subtitle); }
.notes-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 10px; }
.notes-status { font: 400 12px/1.4 var(--font-mono); color: var(--muted-foreground); }
.notes-status[data-state="error"] { color: var(--destructive); }
.notes-print { display: none; }
/* The notes overview and the [notes] list in a lesson: product > module > note. */
.notes-list { display: grid; gap: 0; }
.notes-list > h2 { margin: 32px 0 4px; }
.notes-list > .eyebrow { display: block; margin: 20px 0 6px; }
.note-item { padding: 16px 0; border-top: 1px solid var(--border); break-inside: avoid; }
.note-item h3 { margin: 0; font: 400 17px/1.3 var(--font-subtitle); color: var(--primary); }
.note-item h3 a { color: inherit; }
.note-item time { font: 400 12px/1.4 var(--font-mono); color: var(--muted-foreground); }
.note-item p { margin: 8px 0 0; white-space: pre-line; font: 400 17px/1.6 var(--font-subtitle); }
.qa { margin-top: 64px; padding-top: 32px; border-top: 1px solid var(--primary); }
.qa .block-head { margin-top: 0; }
.qa-thread { padding: 24px 0; border-top: 1px solid var(--border); scroll-margin-top: 96px; }
.qa-thread:first-of-type { border-top: 0; }
.qa-post { display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 14px; align-items: start; }
.qa-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13px; line-height: 28px; color: var(--muted-foreground); }
.qa-meta strong { color: var(--foreground); font-weight: 500; }
.qa-body { margin-top: 2px; font-size: 16px; line-height: 1.6; white-space: pre-line; overflow-wrap: anywhere; }
.qa-thread > .qa-post .qa-body { font-family: var(--font-serif); font-size: 18px; }
.qa-actions { margin-top: 6px; display: flex; gap: 12px; font-size: 13px; }
.qa-actions button, .qa-actions a { padding: 0; border: 0; background: none; color: var(--muted-foreground); font: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.qa-actions button:hover, .qa-actions a:hover { color: var(--foreground); }
.qa-replies { margin: 18px 0 0 42px; padding-left: 20px; border-left: 1px solid var(--border); display: grid; gap: 18px; }
.qa-replies .qa-form { margin-top: 0; }
.qa-post[data-deleted] .qa-body { font-style: italic; color: var(--muted-foreground); }
.qa-post[data-hidden], .qa-thread[data-hidden] > .qa-post { opacity: .55; }
.qa-form { margin-top: 20px; display: grid; gap: 10px; }
.qa-form .textarea { min-height: 96px; }
.qa-replies .qa-form .textarea { min-height: 64px; }
.qa-form .row { justify-content: space-between; }
.qa-new { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--brand); flex: none; }
.nav-count { margin-left: auto; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; display: inline-grid; place-items: center;
             background: var(--brand); color: var(--brand-foreground); font-size: 11px; font-weight: 600; line-height: 1; }
@media (max-width: 700px) { .qa-replies { margin-left: 14px; padding-left: 14px; } }

/* ---- Schedule: a list, not a month grid ---- */
.schedule-month { margin-bottom: 40px; }
.schedule-month > .eyebrow { display: block; margin-bottom: 8px; }
.schedule-item { display: grid; grid-template-columns: 140px minmax(0, 1fr) auto; gap: 24px; align-items: center;
                 padding: 16px 0; border-top: 1px solid var(--border); }
.schedule-item:last-child { border-bottom: 1px solid var(--border); }
.schedule-item h3 { margin: 0; font: 400 19px/1.3 var(--font-subtitle); color: var(--primary); }
.schedule-item p { margin: 4px 0 0; font-size: 14px; color: var(--muted-foreground); }
.schedule-item .when { font: 400 14px/1.4 var(--font-mono); color: var(--foreground); }
.schedule-item .when small { display: block; color: var(--muted-foreground); font-size: 12px; }
/* Dates (0.26): a row with more information links its title to the date page; the room link shows only in its window.
   Markup: .schedule-item h3 > a; before the window .join-later ("Room from 13:45") instead of the Join button. */
.schedule-item h3 a { color: inherit; text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 4px; }
.schedule-item h3 a:hover { text-decoration-color: currentColor; }
.join-later { font: 400 12px/1.4 var(--font-mono); color: var(--muted-foreground); white-space: nowrap; }
/* The date page: header like a lesson, a join panel with the state of the room, then the details.
   Markup: article.date-page > .eyebrow + h1.display + .date-when + .join-panel[data-state=open|later|over] + .prose */
.date-page { max-width: 820px; }
.date-page .display { margin: 10px 0 12px; }
.date-when { font: 400 14px/1.5 var(--font-mono); color: var(--foreground); }
.date-when span { color: var(--muted-foreground); }
.join-panel { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin: 28px 0 32px;
  padding: 16px 20px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 14px; color: var(--muted-foreground); }
.join-panel[data-state="open"] { border-color: var(--brand); background: var(--brand-soft); color: var(--foreground); }
.join-panel strong { display: block; font: 400 17px/1.3 var(--font-subtitle); color: var(--primary); }
.date-page .prose + .row { margin-top: 28px; }
/* Live now (0.26): no "Live" pill; while a date runs, a small broadcast signal sits next to its time.
   Markup: <span class="live-signal" role="img" aria-label="Live now"><svg ...two arcs + dot...></svg></span> in .when or .date-when.
   The arcs pulse gently; with reduced motion they stay still. */
.live-signal { display: inline-block; width: 16px; height: 16px; margin-left: 6px; vertical-align: -3px; color: var(--brand); }
.live-signal svg { display: block; width: 100%; height: 100%; overflow: visible; }
.live-signal .wave { animation: live-wave 2.4s ease-in-out infinite; }
.live-signal .wave + .wave { animation-delay: .4s; }
@keyframes live-wave { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .live-signal .wave { animation: none; opacity: .8; } }
/* New and rescheduled dates (0.26): a small word in small caps before the title, no pill. It goes away by itself
   after some days (the app decides). Markup: <h3><span class="date-flag">New</span>Title</h3>;
   rescheduled: <span class="date-flag" data-flag="moved" title="Was Mon 2 Nov, 18:00">Rescheduled</span>. */
.date-flag { display: inline-block; margin-right: 10px; font: 600 10.5px/1 var(--font-sans); letter-spacing: .08em;
  text-transform: uppercase; color: var(--brand); vertical-align: 3px; }
.date-flag[data-flag="moved"] { color: var(--foreground); text-decoration: underline; text-decoration-color: var(--brand);
  text-underline-offset: 3px; }
/* Phone: one column; the date and time on one line, then the title, then the badge or button. */
@media (max-width: 700px) {
  .schedule-item { grid-template-columns: minmax(0, 1fr); gap: 6px; align-items: start; }
  .schedule-item .when { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
  .schedule-item .when small { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
  .schedule-item > .row:not(:empty) { margin-top: 4px; }
}
/* Compact date (0.47): .schedule-item[data-compact] for a narrow column. Date and action share the first line; the title
   takes the whole width and ends with an ellipsis after two lines, the note after one. The full text goes into title. */
.schedule-item[data-compact] { grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; align-items: center; }
.schedule-item[data-compact] .when { grid-column: 1; grid-row: 1; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; }
.schedule-item[data-compact] .when small { display: inline-flex; align-items: center; gap: 6px; }
.schedule-item[data-compact] > .row { grid-column: 2; grid-row: 1; margin-top: 0; }
.schedule-item[data-compact] > .schedule-text { grid-column: 1 / -1; grid-row: 2; min-width: 0; }
.schedule-item[data-compact] h3 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; font-size: 17px; }
.schedule-item[data-compact] p { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

/* ---- Labels on badges: Latin Modern small caps, as in print (\badge{}) ---- */
.badge { font-family: var(--font-label); font-weight: 400; font-size: 13px; letter-spacing: .08em; text-transform: lowercase; }
/* Optical centring of short labels (badges, keys, avatar): the line box of a serif holds its deep descender, so the
   letters sit low. text-box trims the box to the letters (small caps reach the x-height, keys the cap height), and
   equal padding centres them. Browsers without text-box get a small lift instead. A badge is an inline-block with
   its own height: Basecoat's inline-flex and fixed 20 px height left text-box without effect (the letters sat low).
   One rule for every small-caps label in a box (0.41.3): a new pill, tab or chip with --font-label joins this list,
   so each one centres the same way. */
.badge, .lang-switch a { line-height: 1; text-box: trim-both ex alphabetic; }
.badge { display: inline-block; height: auto; vertical-align: middle; padding-block: 6px; }
.lang-switch a { display: inline-block; padding-block: 6px; }
.lang-float a { padding-block: 8px; }
.kbd { line-height: 1; padding-block: 5px; text-box: trim-both cap alphabetic; }
@supports not (text-box: trim-both cap alphabetic) {
  .badge, .lang-switch a { padding-block: 3px 5px; }
  .lang-float a { padding-block: 5px 7px; }
  .kbd { padding-block: 2px 4px; }
}

/* ---- Lesson content: the handout components on screen (same names as in ki-leadership.cls) ---- */
.callout, .caution { border-radius: 0 var(--radius) var(--radius) 0; padding: 16px 20px; font-size: 15px; font-family: var(--font-sans); }
.callout { background: var(--brand-soft); border-left: 2px solid var(--brand); }
.callout .eyebrow { color: var(--brand); }
.caution { background: var(--warning-soft); border-left: 2px solid var(--warning); }
.caution .eyebrow { color: var(--warning); }
.callout p, .caution p { margin: 4px 0 0; }
.prompt { position: relative; background: var(--muted); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px 20px; }
.prompt pre { margin: 8px 0 0; white-space: pre-wrap; font: 400 13px/1.7 var(--font-mono); color: var(--foreground); }
.prompt .btn { position: absolute; top: 10px; right: 10px; }
.pullquote { border-left: 1.5px solid var(--brand); padding: 4px 0 4px 24px; margin: 0; max-width: 760px;
             font: italic 400 28px/1.35 var(--font-subtitle); color: var(--primary); }
.pullquote cite { display: block; margin-top: 12px; font-style: normal; }
.steps { list-style: none; padding: 0; margin: 0; counter-reset: step; }
.steps li { counter-increment: step; display: grid; grid-template-columns: 40px 1fr; align-items: baseline; padding: 14px 0; border-top: 1px solid var(--border); }
.steps li::before { content: counter(step) "."; font: 700 16px/1.5 var(--font-serif); color: var(--brand); }
.checklist { list-style: none; padding: 0; margin: 0; }
.checklist li { display: flex; gap: 12px; align-items: center; padding: 6px 0; font-size: 15px; }
.checklist input { width: 16px; height: 16px; accent-color: var(--brand); margin: 0; }
.data-table { width: 100%; border-collapse: collapse; font-size: 14px; font-family: var(--font-sans); }
.data-table th { text-align: left; padding: 10px 12px 10px 0; border-bottom: 1px solid var(--primary); }
.data-table td { padding: 12px 12px 12px 0; border-bottom: 1px solid var(--border); vertical-align: top; }
.prose .callout, .prose .caution, .prose .prompt, .prose .steps, .prose .checklist, .prose .data-table, .prose .pullquote { margin: 1.5em 0; }
/* A button in text keeps the button face, not the serif of the text around it */
.prose .btn { font-family: var(--font-sans); font-style: normal; text-decoration: none; }

/* ---- Downloads (0.24): a file behind the app's proxy link (/download/<name>). Three templates for lesson text and
   pages, plus the list under a unit. The icon names the file type (dist/img/icons/files.svg: file, file-doc,
   file-image, file-archive, file-sheet, file-slides, file-audio, file-video, lock); it is a label, not decoration.
   The meta line is type and size in small caps, "PDF · 2.4 MB". Without access: data-locked, the lock icon and the
   reason instead of the download. ---- */
.file-icon { width: 1.25em; height: 1.25em; flex: none; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.download-size { font: 400 13px/1.4 var(--font-label); letter-spacing: .08em; text-transform: lowercase; color: var(--muted-foreground); white-space: nowrap; }
.download-card { display: grid; grid-template-columns: 112px 1fr; gap: 20px; align-items: start; margin: 24px 0; padding: 20px;
                 border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); font-family: var(--font-sans); }
.download-media { aspect-ratio: 1; display: grid; place-items: center; overflow: hidden; border-radius: calc(var(--radius) - 2px); background: var(--muted); color: var(--primary); }
.download-media img { width: 100%; height: 100%; object-fit: cover; }
.download-media .file-icon { width: 40px; height: 40px; stroke-width: 1.25; }
.download-card h3 { margin: 2px 0 6px; font: 400 21px/1.3 var(--font-subtitle); color: var(--primary); }
.download-card p { margin: 0 0 14px; font-size: 15px; line-height: 1.55; color: var(--muted-foreground); }
.download-card[data-locked] .download-media { color: var(--muted-foreground); }
.download-locked { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--muted-foreground); }
@media (max-width: 520px) { .download-card { grid-template-columns: 64px 1fr; gap: 14px; padding: 16px; } .download-media .file-icon { width: 28px; height: 28px; } }
.btn.download-button { gap: 8px; }
.btn.download-button .download-size { font-size: 12px; }
.download-link { display: inline-flex; align-items: baseline; gap: 6px; color: var(--primary); text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 3px; }
.download-link:hover { text-decoration-color: currentColor; }
.download-link .file-icon { align-self: center; width: 1.05em; height: 1.05em; }
.download-link[data-locked] { color: var(--muted-foreground); text-decoration: none; }
.download-list { list-style: none; margin: 32px 0 0; padding: 0; border-top: 1px solid var(--border); font-family: var(--font-sans); }
.download-list li > a, .download-list li > span { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 12px; padding: 14px 4px;
                 border-bottom: 1px solid var(--border); color: var(--foreground); text-decoration: none; }
.download-list li > a:hover .download-title { text-decoration: underline; text-underline-offset: 3px; }
.download-list .file-icon { color: var(--primary); }
.download-list li > span { color: var(--muted-foreground); }
.download-list li > span .file-icon { color: inherit; }

/* Download menu (0.24): all downloads of a lesson or module in one dropdown, on the product page, so a member does
   not open each lesson. <details class="download-menu"> in .module-head or after the link of a .unit-list row; the
   summary is a small ghost button (archive icon and the count), the panel the .menu-panel of the user menu with one
   .menu-item per file. dist/menu.js closes it on an outside click and Escape. */
.download-menu { position: relative; flex: none; }
.download-menu > summary { list-style: none; display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px; cursor: pointer; user-select: none;
                           border: 1px solid transparent; border-radius: calc(var(--radius) - 2px); font-size: 13px; color: var(--muted-foreground); }
.download-menu > summary::-webkit-details-marker { display: none; }
.download-menu > summary:hover, .download-menu[open] > summary { border-color: var(--border); background: var(--card); color: var(--foreground); }
.download-menu .menu-panel { min-width: 340px; max-width: min(420px, calc(100vw - 32px)); }
.download-menu .menu-item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; }
.download-menu .menu-item .file-icon { color: var(--primary); }
.download-menu .menu-item > span:nth-child(2) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.unit-list li:has(> .download-menu) { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 8px; }
.unit-list li > .download-menu { margin-right: 4px; }

/* ---- Window frame for product shots and page previews ---- */
.frame { border: 1px solid var(--border); border-radius: 12px; overflow: hidden; background: var(--card); }
.frame-bar { display: flex; align-items: center; gap: 6px; height: 36px; padding: 0 14px; border-bottom: 1px solid var(--border); background: var(--muted); }
.frame-bar i { width: 10px; height: 10px; border-radius: 50%; background: var(--border); }
.frame-bar span { margin-left: 12px; font: 400 12px var(--font-mono); color: var(--muted-foreground); }
.frame-body { background: var(--background); }

/* ---- Empty state ---- */
.empty { padding: 32px; border: 1px dashed var(--border); border-radius: var(--radius); color: var(--muted-foreground); font-size: 14px; text-align: center; }

/* ---- Images: uploads as <img srcset> in covers, figures in lesson text ---- */
.cover { position: relative; overflow: hidden; }
.cover > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.unit-body img { max-width: 100%; height: auto; }
.figure { margin: 1.5em 0; }
.figure img { display: block; width: 100%; height: auto; border: 1px solid var(--border); border-radius: var(--radius); }
.figure figcaption { margin-top: 8px; font-size: 13px; color: var(--muted-foreground); }

/* ---- Admin: the same app shell; toolbar, numbers, forms, tables, media library ---- */
.toolbar { display: flex; gap: 12px; align-items: center; justify-content: space-between; flex-wrap: wrap; margin-bottom: 24px; }
.toolbar form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.toolbar .input { width: 260px; }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 24px; margin-bottom: 48px; }
.stat { border-top: 1px solid var(--primary); padding-top: 12px; }
.stat strong { display: block; font: 400 40px/1.1 var(--font-display); color: var(--primary); }
.stat span { font-size: 13px; color: var(--muted-foreground); }
/* Integrations (0.9): one tile per service, a rule on top as .stat, linking to its section below.
   Markup: .integration-grid > a.integration[data-on] > strong (name) + span.integration-state (.input-state + text) + p */
.integration-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 24px; margin-bottom: 48px; }
.integration { display: block; border-top: 1px solid var(--primary); padding-top: 12px; color: inherit; text-decoration: none; }
.integration strong { display: block; font: 400 22px/1.25 var(--font-subtitle); color: var(--primary); }
.integration-state { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 13px; color: var(--muted-foreground); }
.integration-state .input-state { width: 16px; height: 16px; }
.integration[data-on] .integration-state { color: var(--foreground); }
.integration p { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: var(--muted-foreground); }
.integration:hover strong { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px; }
.integration:focus-visible { outline: 2px solid var(--ring); outline-offset: 4px; }
.form-section { padding: 28px 0; border-top: 1px solid var(--border); }
.form-section:first-child { border-top: 0; padding-top: 0; }
.form-section > h2 { font: 400 22px/1.3 var(--font-subtitle); margin: 0 0 4px; color: var(--primary); }
.form-section > p { margin: 0 0 20px; font-size: 14px; color: var(--muted-foreground); }
/* Parts after the heading and note (copy box, table, field grid, buttons) keep 20 px between them */
.form-section > :not(h2, p) + * { margin-top: 20px; }
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 24px; }
.form-grid .wide { grid-column: 1 / -1; }
/* Stored secret: the masked value as placeholder in ink, and a check (or a cross) right of the field */
.input-secret { display: flex; align-items: center; gap: 10px; }
.input-secret .input { flex: 1; min-width: 0; }
.input-secret[data-set] .input::placeholder { color: var(--muted-foreground); font-family: var(--font-mono); letter-spacing: .08em; }
/* Remove a stored secret: an icon button right of the field. It opens a small confirmation; its button submits a
   form outside the settings form (form="..."), so the forms do not nest.
   Markup: details.input-remove > summary.btn[data-variant=ghost][data-size=icon] svg + .confirm > .note + button.btn[data-variant=destructive][form] */
.input-remove { position: relative; flex: none; }
.input-remove > summary { list-style: none; color: var(--muted-foreground); }
.input-remove > summary::-webkit-details-marker { display: none; }
.input-remove > summary svg { width: 16px; height: 16px; }
.input-remove[open] > summary, .input-remove > summary:hover { color: var(--destructive); }
/* A confirmation that deletes nothing (0.44.2): data-tone="neutral" keeps the ink colour; data-active marks the current state. */
.input-remove[data-tone="neutral"][open] > summary, .input-remove[data-tone="neutral"] > summary:hover { color: var(--foreground); }
.input-remove[data-active] > summary { color: var(--brand); }
.input-remove .confirm { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; display: grid; gap: 10px; justify-items: start;
                         width: max-content; max-width: 300px; padding: 12px; background: var(--popover); color: var(--popover-foreground);
                         border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 8px 24px rgb(0 0 0 / .08); }
.input-state { flex: none; display: inline-flex; width: 20px; height: 20px; color: var(--success); }
.input-secret[data-state="error"] .input-state { color: var(--destructive); }
.input-state svg { width: 100%; height: 100%; }
.form-grid .check-field { display: flex; gap: 10px; align-items: center; font-size: 14px; }
.form-grid .check-field input { width: 16px; height: 16px; accent-color: var(--brand); margin: 0; }
@media (max-width: 700px) { .form-grid { grid-template-columns: 1fr; } }
.form-actions { display: flex; gap: 12px; align-items: center; margin-top: 24px; }
.code-area { font: 400 13px/1.6 var(--font-mono); min-height: 280px; }
.data-table a { color: var(--primary); text-decoration: none; }
.data-table a:hover { text-decoration: underline; }
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table .actions { text-align: right; white-space: nowrap; }
.data-table .actions form { display: inline; }
/* Icon actions of a row (0.44.2): .actions > .row of ghost icon buttons and details.input-remove, on one line. */
.data-table .actions > .row { justify-content: flex-end; flex-wrap: nowrap; gap: 2px; }
.data-table .actions > .row > .btn, .data-table .actions .input-remove > summary { color: var(--muted-foreground); }
.data-table .actions > .row > .btn:hover { color: var(--foreground); }
.data-table .actions .input-remove .confirm { text-align: left; white-space: normal; }
.data-table .mono, .mono { font: 400 12px/1.5 var(--font-mono); }
.media-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; }
.media-tile { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--card); display: flex; flex-direction: column; }
.media-tile .thumb { aspect-ratio: 4 / 3; background: var(--muted); position: relative; display: grid; place-items: center;
                     font: 400 13px var(--font-mono); color: var(--muted-foreground); }
.media-tile .thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.media-tile .meta { padding: 10px 12px; display: grid; gap: 6px; font-size: 12px; color: var(--muted-foreground); }
.media-tile .meta strong { font-weight: 500; color: var(--foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.media-tile .meta input { font: 400 11px var(--font-mono); height: 28px; }
/* Media library (0.14): a tile is a link to the detail page; badges name issues (no alt text, unused, in the trash) */
a.media-tile { color: inherit; text-decoration: none; transition: border-color .15s ease-out; }
a.media-tile:hover { border-color: var(--muted-foreground); }
.media-tile .badges { display: flex; flex-wrap: wrap; gap: 4px; }
.media-tile[data-trashed] .thumb { opacity: .45; }
/* Media detail: the preview left, the facts right; variants and uses below as data tables.
   Markup: .media-detail > .media-preview (img or file type) + aside > dl.facts + forms */
.media-detail { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 32px; align-items: start; }
.media-preview { border: 1px solid var(--border); border-radius: var(--radius); background: var(--muted); min-height: 200px;
                 display: grid; place-items: center; overflow: hidden; font: 500 14px var(--font-mono); color: var(--muted-foreground); }
.media-preview img { display: block; width: 100%; height: auto; }
.media-detail aside { display: grid; gap: 20px; }
dl.facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 8px 16px; margin: 0; font-size: 14px; }
dl.facts dt { color: var(--muted-foreground); }
dl.facts dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 800px) { .media-detail { grid-template-columns: 1fr; } }

/* ---- Modal (0.29): Basecoat dialog.dialog with its backdrop, opened by dist/dialog.js ([data-dialog="<id>"]).
        Live search: form[data-live-search="<results id>"] (dist/live-search.js) shimmers its input while it loads.
        .btn-label: the text of a button that has an icon; on small screens only the icon shows ---- */
.dialog > * { max-width: min(560px, calc(100% - 2rem)); }
.dialog[data-wide] > * { max-width: min(860px, calc(100% - 2rem)); }
.dialog > * > section { overflow-y: auto; }
.dialog::backdrop { background-color: color-mix(in oklab, var(--foreground) 35%, transparent); }
form[data-live-search][aria-busy] .input { background-image: linear-gradient(90deg, transparent, var(--muted), transparent);
                                          background-size: 200% 100%; animation: live-search 1s linear infinite; }
@keyframes live-search { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) { form[data-live-search][aria-busy] .input { animation: none; } }
.btn > svg { width: 16px; height: 16px; flex-shrink: 0; }
@media (max-width: 640px) { .btn .btn-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } }

/* ---- Page drop (0.30): files dragged over a page with form[data-drop-upload] show this target over the whole
        window (dist/drop-upload.js); the text is the form's data-drop-upload ---- */
.drop-overlay { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 24px;
                background: color-mix(in oklab, var(--background) 80%, transparent); backdrop-filter: blur(2px); pointer-events: none; }
.drop-overlay > div { width: min(640px, 100%); aspect-ratio: 16 / 7; display: grid; place-content: center; gap: 8px; text-align: center;
                      border: 2px dashed var(--brand); border-radius: var(--radius); background: var(--brand-soft); }
.drop-overlay strong { font: 400 28px/1.2 var(--font-subtitle); color: var(--primary); }
.drop-overlay span { font-size: 13px; color: var(--muted-foreground); min-height: 1.4em; }
.drop-overlay[data-busy] > div { border-style: solid; }

/* ---- Sort list (0.28): rows in their order; a drag handle shows on hover and moves a row. dist/sort-list.js saves
        the new order on drop. Arrow keys on the handle move a row too.
   Markup: ol.sort-list[data-sort-url][data-csrf] > li[data-id] > button.sort-handle + .sort-main (link, mono slug)
           + .sort-meta (cells) ---- */
.sort-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--primary); font-size: 14px; }
.sort-list > li { display: grid; grid-template-columns: 24px minmax(0, 1fr) auto; gap: 12px; align-items: center;
                  padding: 12px 12px 12px 0; border-bottom: 1px solid var(--border); background: var(--background); }
.sort-list .sort-main a { color: var(--primary); text-decoration: none; }
.sort-list .sort-main a:hover { text-decoration: underline; }
.sort-list .sort-meta { display: flex; gap: 24px; align-items: center; color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
.sort-handle { display: grid; place-items: center; width: 24px; height: 28px; padding: 0; border: 0; border-radius: calc(var(--radius) - 4px);
               background: none; color: var(--muted-foreground); cursor: grab; touch-action: none; opacity: 0; transition: opacity .15s ease-out; }
.sort-handle svg { width: 16px; height: 16px; }
.sort-list > li:hover .sort-handle, .sort-handle:focus-visible, .sort-list > li[data-dragging] .sort-handle { opacity: 1; }
.sort-handle:hover { background: var(--muted); color: var(--foreground); }
@media (hover: none) { .sort-handle { opacity: 1; } }
.sort-list > li[data-dragging] { position: relative; z-index: 1; box-shadow: 0 8px 24px -12px rgb(0 0 0 / .35); cursor: grabbing; }
.sort-list > li[data-dragging] .sort-handle { cursor: grabbing; }
.sort-list[data-busy] { opacity: .6; pointer-events: none; }
/* Table rows in a form (0.50): tbody[data-sort-rows] > tr > td > button.sort-handle. Without data-sort-url the rows
   only move; the form saves them in their new order. */
[data-sort-rows] > tr:hover .sort-handle, [data-sort-rows] > tr[data-dragging] .sort-handle { opacity: 1; }
[data-sort-rows] > tr[data-dragging] { position: relative; z-index: 1; background: var(--background); box-shadow: 0 8px 24px -12px rgb(0 0 0 / .35); }
[data-sort-rows] > tr[data-dragging] .sort-handle { cursor: grabbing; }
[data-sort-rows] > tr > td:has(> .sort-handle) { width: 24px; padding-right: 0; }
/* A row with a target select (0.50.1): select[data-target] picks a module, a lesson, a product or "url"; the field
   [data-url-field] of the row shows only for "url". */
tr:has(select[data-target]):not(:has(select[data-target] option[value="url"]:checked)) [data-url-field] { visibility: hidden; }

/* ---- Image field and media picker (0.28): a form field that shows the chosen image; "Choose" opens one shared
        dialog with upload, the library and a detail pane (alt text, open in the library, move to trash).
   Field: .image-field > .image-field-preview (img or .empty) + .image-field-body (strong name, span note,
          .row of buttons) + input[type=hidden]
   Dialog: dialog.dialog.media-picker > div > header + section.media-picker-body (.media-picker-main: .drop-zone,
           .picker-grid > button.picker-item[aria-pressed] > img + span) + aside.media-picker-detail) + footer ---- */
.image-field { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 16px; align-items: center;
               padding: 12px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
.image-field-preview { aspect-ratio: 16 / 9; border-radius: calc(var(--radius) - 4px); overflow: hidden; background: var(--muted);
                       display: grid; place-items: center; color: var(--muted-foreground); font-size: 12px; }
.image-field[data-square] .image-field-preview { aspect-ratio: 1; width: 90px; }
.image-field-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.image-field-body { display: grid; gap: 4px; min-width: 0; font-size: 14px; }
.image-field-body strong { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.image-field-body span { color: var(--muted-foreground); font-size: 12px; }
.image-field-body .row { margin-top: 6px; }

.media-picker > * { max-width: min(1080px, calc(100% - 2rem)); height: min(760px, calc(100% - 2rem)); }
.media-picker-body { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; min-height: 0; overflow: hidden; }
.media-picker-main { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 16px; min-height: 0; }
.drop-zone { display: flex; gap: 12px; align-items: center; justify-content: center; padding: 18px; font-size: 14px;
             border: 1px dashed var(--border); border-radius: var(--radius); color: var(--muted-foreground); background: var(--muted);
             transition: border-color .15s ease-out, background-color .15s ease-out; }
.drop-zone[data-over] { border-color: var(--brand); background: var(--brand-soft); color: var(--foreground); }
.drop-zone[data-busy] { opacity: .6; }
.picker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 12px; align-content: start;
               overflow-y: auto; padding: 2px; }
.picker-item { display: grid; gap: 6px; padding: 0; border: 0; background: none; text-align: left; cursor: pointer; font-size: 12px;
               color: var(--muted-foreground); min-width: 0; }
.picker-item img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: calc(var(--radius) - 4px); background: var(--muted);
                   outline: 1px solid var(--border); outline-offset: -1px; transition: outline-color .15s ease-out; }
.picker-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-item:hover img { outline-color: var(--muted-foreground); }
.picker-item[aria-pressed="true"] img { outline: 2px solid var(--brand); outline-offset: 2px; }
.picker-item[aria-pressed="true"] span { color: var(--foreground); }
.media-picker-detail { display: grid; align-content: start; gap: 14px; overflow-y: auto; padding-left: 24px; border-left: 1px solid var(--border); font-size: 14px; }
.media-picker-detail img { width: 100%; border-radius: calc(var(--radius) - 4px); background: var(--muted); }
.media-picker-detail .empty { padding: 32px 0; }
/* 0.31: dist/media-picker.js. The body keeps its own scroll areas; the error line sits above the grid. */
.media-picker .media-picker-body { overflow: hidden; }
.media-picker [hidden] { display: none; }
.media-picker-detail [data-detail="body"]:not([hidden]), .media-picker-detail [data-detail="library"]:not([hidden]) { display: grid; gap: 14px; }
.drop-zone input[type=file] { display: none; }
@media (max-width: 800px) {
  .media-picker .media-picker-body { grid-template-columns: 1fr; overflow-y: auto; }
  .media-picker-detail { padding-left: 0; border-left: 0; border-top: 1px solid var(--border); padding-top: 16px; }
  .image-field { grid-template-columns: 112px minmax(0, 1fr); }
}

/* ---- Language switch: "EN | DE" in small caps. Inline in footers; as .lang-float a pill bottom right until the
        visitor chooses (the app then sets a cookie and shows only the footer switch) ---- */
.lang-switch { display: inline-flex; align-items: center; gap: 0; font-family: var(--font-label);
               font-size: 14px; letter-spacing: .08em; text-transform: lowercase; line-height: 1; }
.lang-switch a { color: var(--muted-foreground); text-decoration: none; padding-inline: 8px; border-radius: calc(var(--radius) - 2px);
                 transition: color .15s ease-out; }
.lang-switch a + a { border-left: 1px solid var(--border); border-radius: 0; }
.lang-switch a:hover { color: var(--foreground); }
.lang-switch a[aria-current="true"] { color: var(--primary); }
.lang-switch a:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.site-footer .lang-switch a, .app-footer .lang-switch a { color: var(--muted-foreground); }
.site-footer .lang-switch a[aria-current="true"], .app-footer .lang-switch a[aria-current="true"] { color: var(--foreground); }
.lang-float { position: fixed; z-index: 30; right: max(20px, env(safe-area-inset-right)); bottom: max(20px, env(safe-area-inset-bottom));
              padding: 6px 8px; background: var(--card); border: 1px solid var(--border); border-radius: 999px;
              box-shadow: 0 6px 24px -10px color-mix(in srgb, var(--image-scrim) 45%, transparent);
              animation: lang-float-in .4s cubic-bezier(.2, .7, .2, 1) .6s both; }
.lang-float a { padding-inline: 10px; }
@keyframes lang-float-in { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: reduce) { .lang-float { animation: none; } }
/* Print (0.26): lessons, dates and notes print like a handout: black on white, Latin Modern, no app frame, no controls.
   A .print-button (window.print) sits in the page; it does not print itself. */
@page { size: A4; margin: 20mm 22mm; }
@media print {
  :root, .dark { --background: #fff; --foreground: #000; --primary: #000; --muted-foreground: #333; --border: #999; --brand: #000; --brand-soft: #fff; --card: #fff; }
  html, body { background: #fff !important; color: #000; font-size: 11pt; }
  .lang-float, .app-sidebar, .app-header, .app-footer, .crumbs, .menu-toggle, .user-menu, .site-header, .site-footer,
  .btn, button, form:not(.notes-form), .notes-input, .qa, .download-menu, .video, .video-resume, iframe, video, .unit-nav, .unit-actions, .alert, .print-button, .notes-foot,
  .notes-card > summary::after, .notes-card > summary small { display: none !important; }
  .app-shell { display: block; }
  .app-content { padding: 0; }
  .unit-page, .date-page { max-width: none; }
  .prose, .note-item p { color: #000; }
  .notes-card { border: 0; margin-top: 24pt; }
  .notes-card > summary { padding: 0 0 6pt; }
  .notes-card .notes-body { padding: 0; }
  .notes-print { display: block; white-space: pre-line; font: 400 11pt/1.5 var(--font-subtitle); }
  .notes-card:not([open]) { display: none; }
  .callout, .caution, .prompt, .join-panel { background: #fff !important; border-color: #000; }
  a { color: #000; text-decoration: none; }
  .prose a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; word-break: break-all; }
  h1, h2, h3 { break-after: avoid; }
  figure, table, .prompt, .callout, .note-item { break-inside: avoid; }
}

/* ---- User menu: top right. Guests see the sign-in button; members a <details> menu with monogram, name and the
        account links; "Sign out" is its last item. Works without JavaScript; dist/menu.js closes it on an outside
        click and Escape ---- */
.user-menu { position: relative; }
.user-menu > summary { list-style: none; display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none;
                       padding: 4px 12px 4px 4px; border: 1px solid transparent; border-radius: 999px; font-size: 14px;
                       color: var(--foreground); transition: border-color .15s ease-out, background-color .15s ease-out; }
.user-menu > summary::-webkit-details-marker { display: none; }
.user-menu > summary:hover, .user-menu[open] > summary { border-color: var(--border); background: var(--card); }
.user-menu .chevron { width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
                      transform: translateY(-2px) rotate(45deg); opacity: .55; transition: transform .2s ease-out; }
.user-menu[open] .chevron { transform: translateY(2px) rotate(-135deg); }
.avatar { width: 28px; height: 28px; flex: none; border-radius: 999px; display: inline-grid; place-items: center;
          background: var(--primary); color: var(--primary-foreground); font-family: var(--font-serif);
          font-size: 12px; letter-spacing: .06em; line-height: 1; text-box: trim-both cap alphabetic; }
/* Without text-box the serif's deep descender pulls the capitals down: lift them a little */
@supports not (text-box: trim-both cap alphabetic) { .avatar { padding-bottom: 2px; } }
.menu-panel { position: absolute; z-index: 40; right: 0; top: calc(100% + 8px); min-width: 248px; padding: 6px;
              background: var(--popover); color: var(--popover-foreground); border: 1px solid var(--border); border-radius: var(--radius);
              box-shadow: 0 16px 40px -16px color-mix(in srgb, var(--image-scrim) 40%, transparent);
              animation: menu-in .16s ease-out both; transform-origin: top right; }
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px) scale(.98); } }
.menu-head { padding: 10px 10px 12px; margin-bottom: 6px; border-bottom: 1px solid var(--border); display: grid; gap: 2px; }
.menu-head strong { font-weight: 500; font-size: 14px; }
.menu-head span { font-size: 12px; color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu-item { display: flex; align-items: center; width: 100%; padding: 8px 10px; border: 0; border-radius: calc(var(--radius) - 2px);
             background: none; color: var(--foreground); font: inherit; font-size: 14px; text-align: left; text-decoration: none; cursor: pointer; }
.menu-item:hover, .menu-item:focus-visible { background: var(--accent); color: var(--accent-foreground); outline: none; }
.menu-sep { height: 1px; margin: 6px 0; background: var(--border); }
.menu-panel form { margin: 0; }
.site-header:not(.site-header-solid) .user-menu > summary { color: var(--on-image); }
.site-header:not(.site-header-solid) .user-menu > summary:hover, .site-header:not(.site-header-solid) .user-menu[open] > summary {
  background: color-mix(in srgb, var(--on-image) 10%, transparent); border-color: color-mix(in srgb, var(--on-image) 25%, transparent); }
@media (max-width: 640px) { .user-menu .user-name { display: none; } .user-menu > summary { padding-right: 10px; } }
@media (prefers-reduced-motion: reduce) { .menu-panel { animation: none; } }

/* ---- Hamburger: the menu button of the app shell on small screens (.menu-toggle > .hamburger). Three rules that
        turn into a cross while the sidebar is open (aria-expanded="true", set by dist/app-shell.js) ---- */
.menu-toggle { width: 36px; height: 36px; padding: 0; justify-content: center; align-items: center; }
.hamburger { position: relative; display: block; width: 18px; height: 12px; }
.hamburger::before, .hamburger::after, .hamburger > span { content: ""; position: absolute; left: 0; right: 0; height: 1.5px;
  background: currentColor; border-radius: 1px; transition: transform .22s cubic-bezier(.2, .7, .2, 1), opacity .15s ease-out, top .22s ease-out; }
.hamburger::before { top: 0; }
.hamburger > span { top: 5.25px; }
.hamburger::after { top: 10.5px; }
.menu-toggle[aria-expanded="true"] .hamburger::before { top: 5.25px; transform: rotate(45deg); }
.menu-toggle[aria-expanded="true"] .hamburger > span { opacity: 0; }
.menu-toggle[aria-expanded="true"] .hamburger::after { top: 5.25px; transform: rotate(-45deg); }
@media (prefers-reduced-motion: reduce) { .hamburger::before, .hamburger::after, .hamburger > span { transition: none; } }

/* ---- Site navigation: menu "site-header" between the wordmark and the user menu. On small screens one row that
        scrolls sideways ---- */
.site-header-inner { gap: 24px; }
.site-nav { display: flex; align-items: center; gap: 28px; margin-left: auto; font-size: 14px; }
.site-nav a { color: var(--on-image); opacity: .78; text-decoration: none; white-space: nowrap; transition: opacity .15s ease-out; }
.site-nav a:hover, .site-nav a[aria-current="page"] { opacity: 1; }
.site-header-solid .site-nav a { color: var(--foreground); opacity: .7; }
.site-header-solid .site-nav a:hover, .site-header-solid .site-nav a[aria-current="page"] { opacity: 1; }
@media (max-width: 720px) { .site-nav { gap: 18px; overflow-x: auto; scrollbar-width: none; mask-image: linear-gradient(to right, #000 85%, transparent); }
  .site-nav::-webkit-scrollbar { display: none; } }

/* ---- Page: a free page (/<slug>), one reading column. .page-frame: the space below the solid site header ---- */
.page-frame { padding-top: 72px; }
.page { max-width: 760px; }
.page > .display { margin: 0 0 20px; }
/* Unit teaser (0.10): the public face of a unit, for sharing. Product and module as eyebrow, title, summary, the
   image (or a preview video in .video), then, as a paywall, a preview text that fades out above a brand call to
   action (.block-cta[data-tone="brand"]). Markup: article.page.teaser > .eyebrow + h1 + .lead + .teaser-media + .paywall-preview */
.teaser .teaser-media { margin: 32px 0 0; aspect-ratio: 16 / 9; }
.teaser .teaser-media.cover { border: 1px solid var(--border); border-radius: var(--radius); background: var(--muted); }
.paywall-preview { position: relative; margin-top: 32px; max-height: 420px; overflow: hidden;
                   -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent); mask-image: linear-gradient(to bottom, #000 55%, transparent); }
.teaser + .block-cta { margin-top: 24px; }
.page > .lead { margin: 0 0 40px; }
.page > .alert { margin-bottom: 32px; }

/* ==== Blocks: the parts a page is built from (app: src/Blocks.php, one template per type). Every block is a
   section.block with three presets that map to tokens, never to raw values:
     data-tone    light (default) | muted | brand (brand-soft paper) | dark (the .dark tokens inside the block)
     data-width   reading (760) | wide (1200, default) | full (edge to edge)
     data-spacing compact | normal (default) | spacious
     data-show    mobile | desktop (see Show below; also on single links and buttons)
   Markup: section.block.block-<type>[data-*] > .block-inner > content ==== */
.block { padding-block: 80px; background: var(--background); color: var(--foreground); }
.block[data-spacing="compact"] { padding-block: 40px; }
.block[data-spacing="spacious"] { padding-block: 128px; }
.block[data-tone="muted"] { background: var(--muted); }
.block[data-tone="brand"] { background: var(--brand-soft); }
.block-inner { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.block[data-width="reading"] .block-inner { max-width: 808px; }
.block[data-width="full"] .block-inner { max-width: none; padding: 0; }
/* Two blocks of the same tone in a row share one gap */
.block[data-tone="light"] + .block[data-tone="light"], .block[data-tone="muted"] + .block[data-tone="muted"],
.block[data-tone="brand"] + .block[data-tone="brand"], .block[data-tone="dark"] + .block[data-tone="dark"] { padding-top: 0; }
.block .eyebrow + .display { margin-top: 14px; }
.block .display + .lead { margin-top: 18px; }
.block .block-head { display: block; margin: 0 0 40px; max-width: 760px; }
/* Inside the members' app the content column frames the blocks: tinted blocks become panels */
.app-content .block { padding-block: 48px; }
.app-content .block .block-inner { padding: 0; }
.app-content .block:not([data-tone="light"]) { padding-inline: 32px; border-radius: var(--radius); margin-block: 16px; }
.app-content .block[data-tone="light"]:first-child { padding-top: 0; }

/* Page header: title and summary, when the page does not start with a hero */
.block-title .display { margin: 0; }
.block-title .lead { margin-top: 18px; max-width: 680px; }

/* Hero: a dark photograph with scrim (image given) or a quiet typographic opening (no image) */
.block-hero { position: relative; overflow: hidden; }
.block-hero[data-image] { min-height: min(78vh, 760px); display: flex; align-items: flex-end; padding-block: 120px 88px;
                          background: var(--image-scrim); color: var(--on-image); }
.block-hero[data-image] .block-inner { position: relative; z-index: 1; width: 100%; }
.block-hero > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: .62; }
.block-hero[data-image]::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, color-mix(in srgb, var(--image-scrim) 82%, transparent), transparent 70%); }
.block-hero[data-image] .eyebrow { color: color-mix(in srgb, var(--on-image) 72%, transparent); }
.block-hero[data-image] .display { color: var(--on-image); }
.block-hero[data-image] .lead { color: color-mix(in srgb, var(--on-image) 80%, transparent); }
.block-hero[data-align="center"] { text-align: center; padding-block: 168px; }
.block-hero[data-align="center"] .display, .block-hero[data-align="center"] .lead { margin-inline: auto; }
.block-hero[data-align="center"] .row { justify-content: center; }
.block-hero[data-image] .btn[data-variant="ghost"] { color: var(--on-image); }
.block-hero .display { max-width: 880px; }
.block-hero .lead { max-width: 620px; }
.block-hero .row { margin-top: 36px; }

/* Text: prose from the editor (lesson components allowed) */
.block-text .prose > :first-child { margin-top: 0; }
.block-text .prose > :last-child { margin-bottom: 0; }

/* Callout: the lesson callout in a reading column */
.block-callout .callout, .block-callout .caution { margin: 0; }
.block-callout h3 { margin: 0 0 6px; font-family: var(--font-sans); font-size: 15px; font-weight: 600; }

/* Image */
.block-image figure { margin: 0; }
.block-image img { display: block; width: 100%; height: auto; border-radius: var(--radius); border: 1px solid var(--border); }
.block-image[data-width="full"] img { border-radius: 0; border-inline: 0; }
.block-image figcaption { margin-top: 12px; font-size: 13px; color: var(--muted-foreground); }
.block-image[data-width="full"] figcaption { padding: 0 24px; }

/* Columns: two to four short items with a rule on top, as in print */
.block-columns .cols { display: grid; gap: 40px 32px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.block-columns .col { border-top: 1px solid var(--primary); padding-top: 18px; }
.block-columns .col h3 { margin: 10px 0 8px; font-family: var(--font-subtitle); font-weight: 400; font-size: 22px; line-height: 1.25; }
.block-columns .col p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--muted-foreground); }
.block-columns .col:has(> .col-image) { border-top: 0; padding-top: 0; }
.block-columns .col-image { display: block; width: 100%; max-width: 320px; aspect-ratio: 1; object-fit: cover; object-position: center 20%; border-radius: var(--radius); margin-bottom: 18px; }
.block-columns .col a { display: inline-block; margin-top: 12px; font-size: 14px; color: var(--primary); }

/* Quote: a citation with its author, an optional portrait and an optional source.
   Markup: section.block.block-quote[data-layout] > .block-inner > figure.citation >
           blockquote + figcaption > (img.citation-portrait) + .citation-by > strong + .citation-role + cite (> a)
   data-layout  simple (default): the quote mark above, the author below
                editorial: the quote mark hangs in the margin, a rule over the author, the portrait larger */
.block-quote figure { margin: 0; }
.block-quote blockquote { margin: 0; font-family: var(--font-serif); font-style: italic; font-size: clamp(24px, 3vw, 32px); line-height: 1.35; text-wrap: pretty; }
.block-quote blockquote::before { content: "“"; display: block; height: .5em; font-size: 2.4em; line-height: 1; color: var(--brand); font-style: normal; }
.block-quote figcaption { display: flex; align-items: center; gap: 14px; margin-top: 24px; font-size: 14px; line-height: 1.45; color: var(--muted-foreground); }
.block-quote figcaption strong { color: var(--foreground); font-weight: 500; }
.citation-by { display: flex; flex-direction: column; }
.citation-by cite { font-style: italic; }
.citation-by cite a { color: inherit; text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 3px; }
.citation-by cite a:hover { text-decoration-color: currentColor; }
.citation-portrait { flex: none; width: 48px; height: 48px; border-radius: 50%; object-fit: cover; object-position: center 20%; }

.block-quote[data-layout="editorial"] blockquote { position: relative; font-family: var(--font-subtitle); font-size: clamp(26px, 3.6vw, 40px); line-height: 1.28; }
.block-quote[data-layout="editorial"] blockquote::before { position: absolute; right: 100%; top: -.12em; height: auto; margin-right: .12em; font-size: 2.6em; line-height: .9; }
.block-quote[data-layout="editorial"] figcaption { margin-top: 32px; padding-top: 18px; border-top: 1px solid var(--primary); gap: 18px; font-size: 15px; }
.block-quote[data-layout="editorial"] .citation-portrait { width: 72px; height: 72px; }
@media (max-width: 900px) {
  .block-quote[data-layout="editorial"] blockquote::before { position: static; display: block; height: .5em; margin: 0; }
}

/* FAQ: questions as <details>, no JavaScript */
.block-faq .faq { border-top: 1px solid var(--border); }
.block-faq details { border-bottom: 1px solid var(--border); }
.block-faq summary { list-style: none; cursor: pointer; display: flex; justify-content: space-between; gap: 24px; padding: 20px 0;
                     font-family: var(--font-subtitle); font-size: 20px; line-height: 1.35; }
.block-faq summary::-webkit-details-marker { display: none; }
.block-faq summary::after { content: "+"; font-family: var(--font-sans); font-weight: 300; color: var(--muted-foreground); transition: transform .2s ease-out; }
.block-faq details[open] summary::after { transform: rotate(45deg); }
.block-faq .answer { padding: 0 0 22px; max-width: 680px; }

/* Call to action: one decision, centred */
.block-cta { text-align: center; }
.block-cta .block-inner { max-width: 760px; }
.block-cta .lead { margin-inline: auto; }
.block-cta .row { justify-content: center; margin-top: 32px; }

/* Reveal on scroll: blocks below the fold fade in and rise 12 px as they come into view. dist/reveal.js sets
   html.reveal and data-revealed; without the script (or with reduced motion) every block shows at once. */
@media (prefers-reduced-motion: no-preference) {
  html.reveal .block:not([data-revealed]) { opacity: 0; transform: translateY(12px); }
  html.reveal .block { transition: opacity 800ms ease-out, transform 800ms cubic-bezier(.2, .7, .2, 1); }
}

/* Zigzag: big image rows with little text, sides swap per row (0.11).
   Markup: .zigzag > .zigzag-row > .zigzag-copy (h3, p, a) + .zigzag-media (img) */
.zigzag { display: grid; gap: 72px; }
.zigzag-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); padding: 14px; background: var(--muted); border-radius: var(--radius); }
.zigzag-row:nth-child(even) { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.zigzag-row:nth-child(even) .zigzag-copy { order: 2; }
.zigzag-copy { align-self: center; padding: 24px 32px; }
.zigzag-copy h3 { margin: 0 0 6px; font-family: var(--font-subtitle); font-weight: 400; font-size: 26px; line-height: 1.25; }
.zigzag-copy p { margin: 0; font-family: var(--font-subtitle); font-size: 20px; line-height: 1.45; color: var(--muted-foreground); }
.zigzag-copy a { display: inline-block; margin-top: 16px; font-size: 15px; color: var(--brand); }
.zigzag-media img { display: block; width: 100%; height: 100%; aspect-ratio: 16 / 10; object-fit: cover; border-radius: calc(var(--radius) - 2px); }
.block[data-tone="muted"] .zigzag-row { background: var(--background); }
.zigzag-copy .eyebrow { display: block; margin-bottom: 8px; }
/* Image left in every row, no swap */
.zigzag[data-sides="left"] .zigzag-row { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.zigzag[data-sides="left"] .zigzag-copy { order: 2; }
/* Small: square 240 px images without a card, for portraits */
.zigzag[data-size="small"] { gap: 56px; }
.zigzag[data-size="small"] .zigzag-row { grid-template-columns: minmax(0, 1fr) 240px; gap: 40px; align-items: center; padding: 0; background: none; }
.zigzag[data-size="small"] .zigzag-row:nth-child(even) { grid-template-columns: 240px minmax(0, 1fr); }
.zigzag[data-size="small"][data-sides="left"] .zigzag-row { grid-template-columns: 240px minmax(0, 1fr); }
.zigzag[data-size="small"] .zigzag-copy { padding: 0; }
.zigzag[data-size="small"] .zigzag-copy p { font-size: 18px; }
.zigzag[data-size="small"] .zigzag-media img { height: auto; aspect-ratio: 1; object-position: center 20%; border-radius: var(--radius); }

/* Product grid: the catalogue grid inside a block */
.block-products .product-grid { margin-top: 0; }

@media (max-width: 900px) {
  .zigzag { gap: 32px; }
  .zigzag-row, .zigzag-row:nth-child(even) { grid-template-columns: minmax(0, 1fr); }
  .zigzag-row .zigzag-copy, .zigzag-row:nth-child(even) .zigzag-copy { order: 2; padding: 20px 10px 10px; }
  .zigzag-media img { height: auto; }
  .zigzag[data-size="small"] .zigzag-row, .zigzag[data-size="small"] .zigzag-row:nth-child(even) { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .zigzag[data-size="small"] .zigzag-row .zigzag-copy { padding: 0; }
  .zigzag[data-sides="left"] .zigzag-row, .zigzag[data-size="small"][data-sides="left"] .zigzag-row { grid-template-columns: minmax(0, 1fr); }
  .zigzag[data-size="small"] .zigzag-media { max-width: 240px; }
}

@media (max-width: 720px) {
  .block { padding-block: 56px; }
  .block[data-spacing="spacious"] { padding-block: 80px; }
  .block-hero[data-image] { min-height: 70vh; padding-block: 96px 56px; }
}

/* Show: an element for one screen size only. The edge is the app menu's 900 px: at or below it counts as mobile.
   Works on any element: a block (section.block[data-show]), a link of a column or zigzag item, a link or button in text. */
@media (min-width: 901px) { [data-show="mobile"] { display: none !important; } }
@media (max-width: 900px) { [data-show="desktop"] { display: none !important; } }

/* ---- Save in place and tag input (0.33): dist/inline-save.js, dist/tag-input.js.
   Row form: form[data-inline-save] (data-saving, data-saved, data-failed) > fields + .inline-status (+ .inline-submit
   without JS). Tag input: .tag-input[data-name] > .tag (span + button.tag-remove + input[type=hidden]) + input.tag-entry[list] ---- */
.inline-form { display: flex; align-items: center; gap: 8px; min-width: 0; }
.inline-form .select { height: 32px; padding-block: 0; font-size: 13px; }
.inline-status { font: 400 12px/1.3 var(--font-mono); color: var(--muted-foreground); white-space: nowrap; }
.inline-status[data-state="saved"] { color: var(--brand); }
.inline-status[data-state="error"] { color: var(--destructive); white-space: normal; }
.tag-input { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 32px; padding: 3px 6px; min-width: 180px;
  border: 1px solid var(--input, var(--border)); border-radius: calc(var(--radius) - 2px); background: var(--background); cursor: text; }
.tag-input:focus-within { outline: 2px solid var(--ring, var(--brand)); outline-offset: 1px; }
.tag { display: inline-flex; align-items: center; gap: 4px; padding: 2px 4px 2px 8px; border-radius: 999px; font-size: 12px; line-height: 1.4;
  background: var(--brand-soft); color: var(--foreground); }
.tag-remove { display: grid; place-items: center; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 50%; background: none;
  color: var(--muted-foreground); font-size: 14px; line-height: 1; cursor: pointer; }
.tag-remove:hover { background: color-mix(in oklab, var(--foreground) 10%, transparent); color: var(--foreground); }
.tag-entry { flex: 1 1 80px; min-width: 80px; height: 24px; padding: 0 2px; border: 0; outline: 0; background: none; font: inherit; font-size: 13px; color: var(--foreground); }

/* ---- Lessons in the module index (0.37): .modules[data-lessons="shown|collapsed|hidden"], in every layout.
   collapsed: details.module-units > summary (the lesson count) + ul.unit-list, closed until a member opens it.
   Cards with lessons: div.module-card[data-units] > a.module-card-link (cover, eyebrow, h3, p, .meta, .progress) and
   below it the compact .unit-list or the details.module-units; without lessons the whole card stays one link. ---- */
.module-units > summary { list-style: none; display: inline-flex; align-items: center; gap: 8px; padding: 6px 0; cursor: pointer; user-select: none;
  font-size: 13px; color: var(--muted-foreground); }
.module-units > summary::-webkit-details-marker { display: none; }
.module-units > summary::after { content: ""; width: 6px; height: 6px; margin-top: -3px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform .15s ease-out, margin .15s ease-out; }
.module-units[open] > summary::after { margin-top: 3px; transform: rotate(-135deg); }
.module-units > summary:hover, .module-units > summary:focus-visible { color: var(--foreground); }
.module-units[open] > summary { margin-bottom: 6px; }
.module-card[data-units] { gap: 12px; }
.module-card-link { display: flex; flex-direction: column; gap: 8px; color: inherit; text-decoration: none; }
.module-card[data-units]:has(> .module-card-link:hover) { border-color: var(--muted-foreground); }
.module-card .unit-list a, .module-card .unit-list .locked { padding: 6px 2px; gap: 8px; font-size: 13px; grid-template-columns: 16px minmax(0, 1fr) auto; }
.module-card .unit-list .check { width: 12px; height: 12px; }
.module-card .unit-list .check svg { width: 8px; height: 8px; }
.module-card .module-units > summary { padding: 0; }

/* ---- Shortcode menu (0.37): every shortcode an admin can place, grouped, with the live names of downloads, audio
   files and products. details.shortcode-menu > summary + .menu-panel.shortcode-panel > input.shortcode-filter +
   .shortcode-group (.menu-label + .shortcode-item: button.menu-item[data-insert] with strong + code, and
   button.shortcode-copy[data-copy]). In the editor a click inserts the shortcode; the copy button puts it on the
   clipboard for any other field. dist/html-editor.js runs both, dist/menu.js closes the panel. ---- */
.shortcode-menu { position: relative; }
.shortcode-menu > summary { list-style: none; }
.shortcode-menu > summary::-webkit-details-marker { display: none; }
.shortcode-panel { left: 0; right: auto; width: min(440px, calc(100vw - 32px)); max-height: min(420px, 70vh); overflow: auto; transform-origin: top left; }
.shortcode-filter { width: 100%; height: 32px; margin-bottom: 6px; font-size: 13px; }
.shortcode-group + .shortcode-group { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); }
.menu-label { display: block; padding: 6px 10px 2px; font: 400 11px/1.4 var(--font-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--muted-foreground); }
.shortcode-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 2px; }
.shortcode-item .menu-item { display: grid; gap: 2px; padding-block: 6px; }
.shortcode-item .menu-item strong { font-weight: 500; font-size: 13px; }
.shortcode-item .menu-item code { font: 400 12px/1.4 var(--font-mono); color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shortcode-copy { display: grid; place-items: center; width: 30px; height: 30px; padding: 0; border: 0; border-radius: calc(var(--radius) - 2px);
  background: none; color: var(--muted-foreground); cursor: pointer; }
.shortcode-copy:hover, .shortcode-copy:focus-visible { background: var(--accent); color: var(--foreground); outline: none; }
.shortcode-copy svg { width: 15px; height: 15px; }
.shortcode-copy[data-copied] { color: var(--brand); }
.shortcode-item[hidden], .shortcode-group[hidden] { display: none; }

/* ---- HTML editor (0.37): a lean visual editor over a textarea, without outside code. dist/html-editor.js.
   .html-editor > .html-editor-bar[role=toolbar] (select.html-editor-block, button.tool[data-cmd] with an icon,
   .tool-sep, the .shortcode-menu, .html-editor-link (input + apply button), spacer, button.tool[data-cmd=source]) +
   .html-editor-surface.prose[contenteditable] + the textarea (the field that is sent; the HTML view) and, with an image
   picker on the page, a hidden .image-field. Without JavaScript only the textarea shows. HTML the toolbar does not know
   (figures, classes, iframes, shortcodes) stays as it is. ---- */
.html-editor { border: 1px solid var(--input, var(--border)); border-radius: var(--radius); background: var(--background); }
.html-editor:focus-within { outline: 2px solid var(--ring, var(--brand)); outline-offset: 1px; }
.html-editor-bar { position: sticky; top: 0; z-index: 2; display: flex; flex-wrap: wrap; align-items: center; gap: 2px; padding: 4px;
  border-bottom: 1px solid var(--border); border-radius: var(--radius) var(--radius) 0 0; background: var(--card); }
.html-editor-bar[hidden] { display: none; }
.html-editor-bar .select { height: 30px; width: auto; padding-block: 0; font-size: 13px; }
.html-editor-bar .tool { display: inline-grid; place-items: center; min-width: 30px; height: 30px; padding: 0 6px; border: 0; border-radius: calc(var(--radius) - 2px);
  background: none; color: var(--foreground); font: 500 12px/1 var(--font-mono); cursor: pointer; }
.html-editor-bar .tool:hover, .html-editor-bar .tool:focus-visible { background: var(--accent); outline: none; }
.html-editor-bar .tool[aria-pressed="true"] { background: var(--brand-soft); color: var(--primary); }
.html-editor-bar .tool:disabled { opacity: .4; cursor: default; background: none; }
.html-editor-bar .tool svg { width: 16px; height: 16px; }
.html-editor-bar .tool-sep { width: 1px; height: 20px; margin: 0 4px; background: var(--border); }
.html-editor-bar .tool-space { flex: 1; }
.html-editor-bar .shortcode-menu > summary { display: inline-flex; align-items: center; gap: 6px; width: auto; font: 400 13px/1 var(--font-sans); }
.html-editor-link { display: flex; flex-basis: 100%; gap: 6px; padding: 4px 2px 2px; }
.html-editor-link[hidden] { display: none; }
.html-editor-link .input { flex: 1; height: 30px; font-size: 13px; }
.html-editor-surface { min-height: 10em; max-height: 70vh; overflow: auto; padding: 14px 16px; outline: none; }
.html-editor-surface[hidden] { display: none; }
.html-editor-surface > :first-child { margin-top: 0; }
.html-editor-surface:empty::before { content: attr(data-placeholder); color: var(--muted-foreground); }
.html-editor-surface img { max-width: 100%; height: auto; }
.html-editor-surface iframe { max-width: 100%; pointer-events: none; }
.html-editor > .textarea { display: block; width: 100%; border: 0; border-radius: 0 0 var(--radius) var(--radius); }
.html-editor > .textarea:focus { outline: none; box-shadow: none; }
.html-editor > .image-field { display: none; }

/* ---- Side tabs (0.37): one choice of several, when a reader needs only one of them (the shop of a product, say).
   Basecoat tabs with a vertical tablist: .tabs.side-tabs > nav[role=tablist][aria-orientation=vertical] >
   button[role=tab] (span + optional .tab-count) + div[role=tabpanel]. A tab with content carries data-set: its count
   shows in the brand colour. On a phone the tabs sit in one row above the panel. ---- */
.side-tabs { display: grid; grid-template-columns: minmax(150px, 200px) minmax(0, 1fr); gap: 24px; align-items: start; }
.side-tabs > [role="tablist"] { display: flex; flex-direction: column; gap: 2px; width: auto; height: auto; padding: 0 12px 0 0; margin: 0;
  border: 0; border-right: 1px solid var(--border); border-radius: 0; background: none; }
.side-tabs > [role="tablist"] > [role="tab"] { display: flex; justify-content: space-between; align-items: center; gap: 8px; width: 100%; height: auto;
  padding: 8px 10px; border: 0; border-radius: calc(var(--radius) - 2px); background: none; box-shadow: none; cursor: pointer;
  font: 400 14px/1.3 var(--font-sans); color: var(--muted-foreground); text-align: left; }
.side-tabs > [role="tablist"] > [role="tab"]:hover { color: var(--foreground); background: var(--accent); }
.side-tabs > [role="tablist"] > [role="tab"][aria-selected="true"] { color: var(--foreground); background: var(--accent); font-weight: 500;
  box-shadow: inset 2px 0 0 var(--primary); }
.side-tabs .tab-count { font: 400 12px/1 var(--font-mono); color: var(--muted-foreground); }
.side-tabs [role="tab"][data-set] .tab-count { color: var(--brand); }
.side-tabs > [role="tabpanel"] { padding: 0; min-width: 0; }
.side-tabs > [role="tabpanel"] > :first-child { margin-top: 0; }
/* 0.51: the parts of a side-tab panel and a nested row of tabs keep a gap above and below. */
.side-tabs > [role="tabpanel"] > * + * { margin-top: 16px; }
.side-tabs > [role="tabpanel"] .tabs:not(.side-tabs) { margin-block: 8px; }
.side-tabs > [role="tabpanel"] > .tabs:not(.side-tabs):first-child { margin-top: 0; }
@media (max-width: 700px) {
  .side-tabs { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .side-tabs > [role="tablist"] { flex-direction: row; overflow-x: auto; padding: 0 0 8px; border-right: 0; border-bottom: 1px solid var(--border); }
  .side-tabs > [role="tablist"] > [role="tab"] { width: auto; flex: none; }
  .side-tabs > [role="tablist"] > [role="tab"][aria-selected="true"] { box-shadow: inset 0 -2px 0 var(--primary); }
}
/* A field's description (0.37): .field > label + control + p.note, one short line under the control. */
.field > .note { margin: 2px 0 0; font-size: 13px; line-height: 1.45; }

/* ---- Disclosure (0.37.3): optional settings, closed until someone wants them. details.disclosure > summary (the
   topic and a count) + content. The same chevron as the lesson list of a module. A shortcode menu outside the editor
   bar is a small outlined button. ---- */
.disclosure { margin: 8px 0; }
.disclosure > summary { list-style: none; display: inline-flex; align-items: center; gap: 8px; padding: 6px 0; cursor: pointer; user-select: none;
  font-size: 14px; color: var(--muted-foreground); }
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary::after { content: ""; width: 6px; height: 6px; margin-top: -3px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform .15s ease-out, margin .15s ease-out; }
.disclosure[open] > summary::after { margin-top: 3px; transform: rotate(-135deg); }
.disclosure > summary:hover, .disclosure > summary:focus-visible { color: var(--foreground); }
.disclosure[open] > summary { margin-bottom: 10px; }
.shortcode-menu > summary { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; cursor: pointer;
  border: 1px solid var(--border); border-radius: calc(var(--radius) - 2px); font: 400 13px/1 var(--font-sans); color: var(--muted-foreground); background: none; }
.shortcode-menu > summary:hover, .shortcode-menu[open] > summary { color: var(--foreground); background: var(--accent); }
.shortcode-menu > summary svg { width: 15px; height: 15px; }

/* ---- Lesson page (0.38): video first, then a short head, then the lesson in tabs. ----
   Head: .lesson-head > .eyebrow + h1.display + .lesson-meta (spans; a .btn may close the row). ---- */
.lesson-head { margin: 20px 0 24px; }
.lesson-head .display { margin: 6px 0 0; }
.lesson-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-top: 12px; font-size: 13px; color: var(--muted-foreground); }
.lesson-meta > span + span::before { content: "·"; margin-right: 14px; }
.lesson-meta > .btn { margin-left: auto; }
.lesson-meta > .btn + .btn { margin-left: 0; }
.lesson-head .lead { margin: 20px 0 0; padding-left: 16px; border-left: 2px solid var(--border); }
@media (max-width: 640px) { .lesson-meta > .btn { margin-left: 0; } }

/* Chapters (0.38): a bar under the video, one segment per chapter, as wide as the chapter is long. A segment seeks the
   video. ol.chapter-bar > li[data-current]? (flex-grow from the length, data-driven) > button[data-seek="197"] >
   span.chapter-track > span.chapter-fill (width set by dist/lesson.js) + span.chapter-label > b (a, b, c) + time + span.chapter-title. */
.chapter-bar { list-style: none; display: flex; gap: 6px; margin: 10px 0 0; padding: 0; }
.chapter-bar > li { flex: 1 1 0; min-width: 72px; overflow: hidden; }
.chapter-bar button { display: grid; gap: 7px; width: 100%; padding: 4px 0; border: 0; background: none; color: var(--muted-foreground); cursor: pointer; text-align: left; font: inherit; }
.chapter-track { display: block; height: 3px; border-radius: 3px; background: var(--border); overflow: hidden; }
.chapter-fill { display: block; width: 0; height: 100%; background: var(--primary); transition: width .3s linear; }
.chapter-label { display: flex; align-items: center; gap: 6px; min-width: 0; font: 400 12px/1.2 var(--font-mono); }
.chapter-label b { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 4px; box-sizing: border-box; border: 1px solid var(--border);
  border-radius: 4px; font-weight: 500; color: var(--foreground); }
.chapter-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-sans); }
.chapter-bar button:hover .chapter-label, .chapter-bar li[data-current] .chapter-label { color: var(--foreground); }
.chapter-bar li[data-current] .chapter-label b { background: var(--primary); border-color: var(--primary); color: var(--primary-foreground); }
@media (max-width: 640px) { .chapter-title { display: none; } }

/* Lesson tabs (0.38): Basecoat tabs with pill tabs in one scrollable row. .tabs.lesson-tabs > nav[role=tablist] >
   button[role=tab] (text + optional .tab-count) + div[role=tabpanel]. Empty tabs are left out. */
.lesson-tabs { margin-top: 28px; }
.lesson-tabs > [role="tablist"] { display: flex; width: 100%; max-width: 100%; overflow-x: auto; scrollbar-width: none; justify-content: flex-start; }
.lesson-tabs > [role="tablist"] > [role="tab"] { flex: none; gap: 6px; }
.lesson-tabs .tab-count { font: 400 12px/1 var(--font-mono); color: var(--muted-foreground); }
.lesson-tabs > [role="tabpanel"] { padding-top: 24px; min-width: 0; }

/* Lesson parts (0.38): the fixed end of a lesson. section.lesson-part > h3.lesson-part-label (Do, Think, Land on) +
   content: a .task-list, a list of questions, or p.takeaway, the one sentence to keep. Parts sit between thin lines. */
.lesson-part { padding: 24px 0; border-top: 1px solid var(--border); }
.lesson-part-label { margin: 0 0 12px; font: 500 13px/1.3 var(--font-sans); color: var(--muted-foreground); }
.lesson-part ol, .lesson-part ul:not(.task-list) { margin: 0; padding-left: 20px; list-style: decimal; display: grid; gap: 8px; font-size: 16px; }
.takeaway { margin: 0; font: 400 21px/1.45 var(--font-subtitle); color: var(--primary); }

/* Task list (0.38): things a member ticks off, saved per member. A box with rows: .task-list-box > .task-list-head
   (h2 + span "1 of 2") + ul.task-list > li > label.task (input[type=checkbox] + span) + optional a.task-go (arrow
   or text link). A ticked task is struck through. Inside a lesson part the box has no head. */
.task-list-box { border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); overflow: hidden; }
.task-list-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--border); }
.task-list-head h2 { margin: 0; font: 500 15px/1.3 var(--font-sans); color: var(--foreground); }
.task-list-head span { font: 400 13px/1 var(--font-mono); color: var(--muted-foreground); }
.task-list { list-style: none; margin: 0; padding: 0; }
.task-list > li { display: flex; align-items: center; gap: 12px; padding: 12px 18px; }
.task-list > li + li { border-top: 1px solid var(--border); }
.task { display: flex; align-items: flex-start; gap: 12px; flex: 1; min-width: 0; cursor: pointer; font-size: 15px; line-height: 1.5; }
.task input { flex: none; width: 20px; height: 20px; margin: 1px 0 0; border-radius: 50%; accent-color: var(--brand); cursor: pointer; }
.task input:checked + span { color: var(--muted-foreground); text-decoration: line-through; text-decoration-color: color-mix(in oklab, currentColor 60%, transparent); }
.task-go { flex: none; display: inline-grid; place-items: center; min-width: 32px; height: 32px; padding: 0 8px; box-sizing: border-box; border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 2px); font-size: 13px; color: var(--foreground); text-decoration: none; }
.task-go:hover { background: var(--accent); }
.task-go svg { width: 15px; height: 15px; }

/* Long text (0.38): a lesson text taller than about one screen folds to that height with a fade and a button.
   div.clamp > div.clamp-body + button.clamp-toggle (hidden until dist/lesson.js measures; data-open unfolds). */
.clamp-body { position: relative; }
.clamp[data-clamped]:not([data-open]) .clamp-body { max-height: 30rem; overflow: hidden; }
.clamp[data-clamped]:not([data-open]) .clamp-body::after { content: ""; position: absolute; inset: auto 0 0; height: 6rem; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--background)); }
.clamp-toggle { margin-top: 12px; }
.clamp:not([data-clamped]) .clamp-toggle { display: none; }

/* Transcript (0.38): .transcript > .transcript-tools (label with a switch "Follow along" + download links) +
   ol.transcript-lines > li[data-current]? > button.transcript-time[data-seek] + p. With Follow along the line that
   plays stays in view and the other lines step back. Without times the lines are plain paragraphs. */
.transcript-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 20px; margin-bottom: 20px; font-size: 14px; }
.transcript-tools label { display: inline-flex; align-items: center; gap: 10px; color: var(--muted-foreground); cursor: pointer; }
.transcript-tools a { display: inline-flex; align-items: center; gap: 6px; color: var(--foreground); font-weight: 500; text-decoration: none; }
.transcript-tools a:hover { text-decoration: underline; text-underline-offset: 3px; }
.transcript-tools svg { width: 16px; height: 16px; }
.transcript-lines { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.transcript-lines > li { display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 12px; align-items: baseline; scroll-margin: 30vh 0; }
.transcript-lines > li:not(:has(.transcript-time)) { grid-template-columns: minmax(0, 1fr); }
.transcript-lines p { margin: 0; font: 400 17px/1.6 var(--font-serif); transition: color .2s ease-out; }
.transcript-time { padding: 0; border: 0; background: none; font: 400 12px/1.6 var(--font-mono); color: var(--muted-foreground); cursor: pointer; text-align: left; }
.transcript-time:hover { color: var(--foreground); text-decoration: underline; text-underline-offset: 3px; }
.transcript[data-follow] .transcript-lines p { color: var(--muted-foreground); }
.transcript[data-follow] .transcript-lines > li[data-current] p { color: var(--foreground); }
.transcript-lines > li[data-current] .transcript-time { color: var(--brand); }

/* Up next (0.38): a card at the end of a lesson. a.up-next > small "Up next" + span.up-next-title (span.num + text) + span.up-next-meta. */
.up-next { display: grid; gap: 4px; margin-top: 32px; padding: 16px 20px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card);
  color: inherit; text-decoration: none; transition: border-color .15s ease-out; }
.up-next:hover { border-color: var(--muted-foreground); }
.up-next small { font-size: 13px; color: var(--muted-foreground); }
.up-next-title { font: 500 17px/1.35 var(--font-sans); }
.up-next-title .num { margin-right: 10px; font: 400 14px/1 var(--font-mono); color: var(--muted-foreground); }
.up-next-meta { font-size: 13px; color: var(--muted-foreground); }
.up-next-meta::after { content: " →"; }

/* ---- Product page parts (0.38) ----
   Start card: the lesson to start or continue. .start-card > a.start-cover (img or empty + span.start-play) +
   .start-body > .eyebrow + h2 (span.num + text) + .start-meta + a.btn[data-variant=primary] (span.dot + text). */
.start-card { display: grid; grid-template-columns: minmax(0, 440px) minmax(0, 1fr); margin-bottom: 32px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--card); overflow: hidden; }
.start-cover { position: relative; display: block; aspect-ratio: 16 / 9; background: var(--muted); }
.start-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.start-play { position: absolute; left: 16px; bottom: 16px; display: grid; place-items: center; width: 52px; height: 52px; border-radius: 50%;
  background: var(--card); color: var(--foreground); box-shadow: 0 6px 20px rgb(0 0 0 / .18); }
.start-play svg { width: 20px; height: 20px; margin-left: 3px; }
.start-body { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding: 24px; }
.start-body h2 { margin: 0; font: 500 22px/1.3 var(--font-sans); color: var(--foreground); }
.start-body h2 .num { margin-right: 8px; color: var(--muted-foreground); font-weight: 400; }
.start-meta { font-size: 13px; color: var(--muted-foreground); }
.start-body .btn { margin-top: 12px; gap: 10px; }
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); flex: none; }
.btn[data-variant="primary"] .dot, .btn:not([data-variant]) .dot { background: var(--brand-soft); }
@media (max-width: 760px) { .start-card { grid-template-columns: minmax(0, 1fr); } }

/* Author note (0.38): a short personal line from the author; a member closes it for good. aside.author-note >
   span.author-mark (img or initials) + div (p + strong) + button.author-note-close[aria-label]. */
.author-note { position: relative; display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 16px; margin-bottom: 32px; padding: 20px 48px 20px 20px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
.author-note[hidden] { display: none; }
.author-mark { display: grid; place-items: center; width: 40px; height: 40px; border-radius: calc(var(--radius) - 2px); overflow: hidden; background: var(--brand); color: var(--brand-foreground);
  font: 500 14px/1 var(--font-sans); }
.author-mark img { width: 100%; height: 100%; object-fit: cover; }
.author-note p { margin: 0; font-size: 17px; line-height: 1.55; }
.author-note strong { display: block; margin-top: 10px; font-weight: 500; font-size: 15px; }
.author-note-close { position: absolute; top: 12px; right: 12px; display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: var(--muted-foreground); cursor: pointer; }
.author-note-close:hover { background: var(--accent); color: var(--foreground); }
.author-note-close svg { width: 14px; height: 14px; }

/* Index layout of the module list (0.38): a numbered table of contents. .modules[data-layout="index"] >
   .index-head (h2 + span "29 lessons · 4 h 20 min") + details.index-module[data-locked]? (open when its lessons
   show) > summary (span.index-num "01" + div > h2 + p + small.index-opens + the chevron) + ol.index-lessons >
   li[data-current]? > a or div.locked (span.check + span.num "1.2" + span title + span.info).
   A module with one lesson: div.index-module[data-single] with a.index-single (thumbnail, title, length) instead of the list.
   Not yet open: the module steps back, its lessons are titles only. */
.index-head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.index-head h2 { margin: 0; font: 400 26px/1.2 var(--font-subtitle); color: var(--primary); }
.index-head span { font-size: 13px; color: var(--muted-foreground); }
.index-module { border-bottom: 1px solid var(--border); }
.index-module > summary, .index-module > .index-summary { list-style: none; display: grid; grid-template-columns: 52px minmax(0, 1fr) 16px; gap: 4px; align-items: start; padding: 20px 0; cursor: pointer; }
.index-module > .index-summary { cursor: default; grid-template-columns: 52px minmax(0, 1fr); }
.index-module > summary::-webkit-details-marker { display: none; }
.index-module > summary::after { content: ""; width: 7px; height: 7px; margin-top: 8px; border-right: 1.5px solid var(--muted-foreground); border-bottom: 1.5px solid var(--muted-foreground);
  transform: rotate(45deg); transition: transform .15s ease-out, margin .15s ease-out; }
.index-module[open] > summary::after { margin-top: 12px; transform: rotate(-135deg); }
.index-num { font: 400 22px/1.2 var(--font-subtitle); color: var(--muted-foreground); }
.index-module h2 { margin: 0; font: 500 17px/1.35 var(--font-sans); color: var(--foreground); }
.index-module summary p, .index-module .index-summary p { margin: 6px 0 0; font-size: 15px; line-height: 1.55; color: var(--muted-foreground); }
.index-opens { display: block; margin-top: 6px; font-size: 13px; color: var(--muted-foreground); }
.index-module[data-locked] h2, .index-module[data-locked] .index-num { color: var(--muted-foreground); }
.index-lessons { list-style: none; margin: 0 0 16px; padding: 0; }
.index-lessons > li > a, .index-lessons > li > .locked { display: grid; grid-template-columns: 22px 36px minmax(0, 1fr) auto; gap: 8px; align-items: baseline; padding: 10px 8px 10px 0;
  border-radius: calc(var(--radius) - 2px); color: inherit; text-decoration: none; font-size: 16px; line-height: 1.45; }
.index-lessons > li > a:hover { background: var(--accent); }
.index-lessons > li[data-current] > a { background: var(--accent); }
.index-lessons .check { align-self: center; width: 16px; height: 16px; border-radius: 50%; border: 1px solid var(--border); box-sizing: border-box; display: grid; place-items: center; }
.index-lessons .check[data-done] { background: var(--brand); border-color: var(--brand); color: var(--brand-foreground); }
.index-lessons .check svg { width: 10px; height: 10px; }
.index-lessons li[data-current] .check:not([data-done]) { border: 0; background: radial-gradient(circle, var(--brand) 0 3.5px, transparent 4px); }
.index-lessons .num { font: 400 13px/1.45 var(--font-mono); color: var(--muted-foreground); }
.index-lessons .info { font-size: 13px; color: var(--muted-foreground); white-space: nowrap; }
.index-lessons .locked { color: var(--muted-foreground); }
.index-lessons .locked .check { border-color: transparent; }
.index-single { display: grid; grid-template-columns: 160px minmax(0, 1fr); gap: 16px; align-items: center; margin: 0 0 20px 52px; color: inherit; text-decoration: none; }
.index-single .cover { aspect-ratio: 16 / 9; border-radius: calc(var(--radius) - 2px); overflow: hidden; background: var(--muted); }
.index-single .cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.index-single span { display: block; font-size: 13px; color: var(--muted-foreground); }
.index-single strong { font-weight: 500; }
.index-single:hover strong { text-decoration: underline; text-underline-offset: 3px; }
@media (max-width: 640px) { .index-single { margin-left: 0; grid-template-columns: 120px minmax(0, 1fr); } }

/* Product sections (0.38): a membership shows each included product as a section of its own page, under its title
   (Welcome, the main course, Bonus). section.product-section > .block-head (h2) + the module list of that product. */
.product-section { margin-top: 56px; }
.product-section > .block-head h2 { margin: 0; font: 400 28px/1.2 var(--font-display); color: var(--primary); }
/* On a product page the checklist keeps the same distance to the module list as the start card. */
.product-header ~ .task-list-box { margin-bottom: 40px; }

/* ---- Progress and game (0.39): points, level, a weekly streak and badges. Calm, not loud: no confetti, no ranking.
   Progress card: .game-card > .game-level (span.eyebrow "Level 3" + strong points + .progress + small "60 to level 4") +
   .game-streak (svg + strong "3 weeks in a row" + .week-dots) + optional .medal-row. On the dashboard it sits in the aside. ---- */
.game-card { display: grid; align-self: start; align-content: start; gap: 18px; padding: 20px; margin-bottom: 32px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
/* Below other content (the dates of the dashboard aside) the card keeps a section gap (0.45.3). */
* + .game-card { margin-top: 32px; }
.game-card > * + * { padding-top: 18px; border-top: 1px solid var(--border); }
.game-level { display: grid; gap: 6px; }
.game-level strong { font: 400 30px/1.1 var(--font-display); color: var(--primary); }
.game-level small, .game-streak small { font-size: 13px; color: var(--muted-foreground); }
.game-level .progress { height: 4px; margin-top: 4px; }
.game-streak { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 4px 10px; align-items: center; }
.game-streak > svg { width: 22px; height: 22px; color: var(--brand); }
.game-streak strong { font-weight: 500; font-size: 15px; }
.game-streak .week-dots, .game-streak small { grid-column: 2; }
.game-card a.game-more { font-size: 13px; color: var(--muted-foreground); }
/* Week dots: Monday to Sunday of this week. ol.week-dots > li[data-active]? [data-today]? > span (the letter, visually hidden text in title). */
.week-dots { list-style: none; display: flex; gap: 6px; margin: 4px 0 0; padding: 0; }
.week-dots li { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--border); font: 400 11px/1 var(--font-mono); color: var(--muted-foreground); }
.week-dots li[data-active] { background: var(--brand); border-color: var(--brand); color: var(--brand-foreground); }
.week-dots li[data-today]:not([data-active]) { border-color: var(--brand); color: var(--brand); }

/* Medals (badges): a round mark with the brand colour; a medal not earned yet is an outline and shows how to earn it.
   .medal[data-locked]? > span.medal-mark (svg) + strong + small. .medal-grid holds many, .medal-row a few small ones. */
.medal-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.medal { display: grid; justify-items: center; gap: 6px; padding: 18px 12px; text-align: center; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
.medal-mark { display: grid; place-items: center; width: 52px; height: 52px; border-radius: 50%; background: var(--brand); color: var(--brand-foreground);
  box-shadow: inset 0 0 0 3px color-mix(in oklab, var(--brand-foreground) 30%, transparent); }
.medal-mark svg { width: 24px; height: 24px; }
.medal strong { font-weight: 500; font-size: 14px; line-height: 1.3; }
.medal small { font-size: 12px; line-height: 1.4; color: var(--muted-foreground); }
.medal[data-locked] { background: none; }
.medal[data-locked] .medal-mark { background: none; color: var(--muted-foreground); box-shadow: inset 0 0 0 1.5px var(--border); }
.medal[data-locked] strong { color: var(--muted-foreground); }
.medal-row { display: flex; flex-wrap: wrap; gap: 8px; }
.medal-row .medal-mark { width: 34px; height: 34px; }
.medal-row .medal-mark svg { width: 16px; height: 16px; }
/* Compact medals (0.45): .medal-grid[data-compact] puts the mark left of the text, for a full-width list of badges. */
.medal-grid[data-compact] { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 8px; }
.medal-grid[data-compact] .medal { grid-template-columns: 36px minmax(0, 1fr); justify-items: start; align-items: center; align-content: center; gap: 2px 12px; padding: 12px 14px; text-align: left; }
.medal-grid[data-compact] .medal-mark { grid-row: span 2; width: 36px; height: 36px; }
.medal-grid[data-compact] .medal-mark svg { width: 18px; height: 18px; }
/* Wide progress card (0.45): .game-card[data-wide] runs across the page with its parts side by side. */
.game-card[data-wide] { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px; }
.game-card[data-wide] > * + * { padding-top: 0; border-top: 0; padding-left: 24px; border-left: 1px solid var(--border); }
@media (max-width: 720px) { .game-card[data-wide] > * + * { padding: 18px 0 0; border-left: 0; border-top: 1px solid var(--border); } }

/* Activity: what earned points lately. ul.activity-list > li > span (text) + small (when) + span.points "+10". */
.activity-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border); }
.activity-list li { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 16px; padding: 10px 0; border-bottom: 1px solid var(--border); font-size: 15px; }
.activity-list small { grid-column: 1; font-size: 12px; color: var(--muted-foreground); }
.activity-list .points { grid-row: 1 / span 2; grid-column: 2; align-self: center; font: 500 13px/1 var(--font-mono); color: var(--brand); }

/* Earned (toast): one short sentence after an action, plus the points when there are any; bottom centre, gone after a
   few seconds (dist/game.js). div.earned-toast[role=status] > span.medal-mark (small) + div (strong + small, the points;
   an empty small hides). */
.earned-toast { position: fixed; left: 50%; bottom: 20px; z-index: 60; display: flex; gap: 10px; align-items: center;
  width: max-content; max-width: calc(100vw - 32px); padding: 8px 16px 8px 8px; border: 1px solid var(--border); border-radius: 999px; background: var(--popover);
  color: var(--popover-foreground); box-shadow: 0 10px 30px rgb(0 0 0 / .12); transform: translate(-50%, 12px); opacity: 0; transition: transform .25s ease-out, opacity .25s ease-out; }
.earned-toast[data-show] { transform: translate(-50%, 0); opacity: 1; }
.earned-toast .medal-mark { flex: none; width: 28px; height: 28px; }
.earned-toast .medal-mark svg { width: 14px; height: 14px; }
.earned-toast > div { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
.earned-toast strong { font-weight: 500; font-size: 14px; }
.earned-toast small { flex: none; font-size: 13px; font-weight: 500; color: var(--brand); font-variant-numeric: tabular-nums; }
.earned-toast small:empty { display: none; }
@media (prefers-reduced-motion: reduce) { .earned-toast { transition: none; } }

/* Connection box (0.39): how a member connects an own AI agent. Uses .prompt for the command. */
.connect-steps { margin: 0; padding-left: 20px; display: grid; gap: 6px; font-size: 15px; list-style: decimal; }

/* Block editor (0.41): the blocks of a page as cards (dist/block-editor.js). ol.block-list > li.block-card >
   .block-card-head (sort handle, type, preview, icon buttons) + .block-card-body (.form-grid, details.block-card-more
   with the settings every block has). A closed card [data-closed] shows only its head. List fields: .block-items >
   .block-item cards inside the body. The foot holds the button that opens the type dialog (.block-types). */
.block-editor { display: grid; gap: 12px; }
.block-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.block-card { border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); }
.block-card[data-dragging] { position: relative; z-index: 2; box-shadow: 0 8px 24px rgb(0 0 0 / .12); }
.block-card-head { display: grid; grid-template-columns: 24px auto minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 8px 8px 8px 12px; }
.block-card-head strong { font: 400 18px/1.3 var(--font-subtitle); color: var(--primary); }
.block-card-preview { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 14px; color: var(--muted-foreground); }
.block-card-head .row { gap: 2px; flex-wrap: nowrap; }
.block-card-head .btn { color: var(--muted-foreground); }
.block-card-head .btn:hover { color: var(--foreground); }
.block-card .sort-handle { opacity: 1; cursor: grab; }
.block-card .sort-handle { touch-action: none; }
.block-card[data-dragging] { user-select: none; }
.block-card-head strong, .block-card-preview { cursor: pointer; }
.block-card-body { padding: 4px 16px 16px; border-top: 1px solid var(--border); display: grid; gap: 16px; padding-top: 16px; }
.block-card[data-closed] .block-card-body { display: none; }
.block-card[data-closed] [data-act="toggle"] svg { transform: rotate(-90deg); }
.block-card-more > summary { cursor: pointer; font-size: 13px; color: var(--muted-foreground); }
.block-card-more[open] > summary { margin-bottom: 12px; }
.block-items-wrap { display: grid; gap: 8px; justify-items: start; }
.block-items { display: grid; gap: 8px; width: 100%; }
.block-item { border: 1px solid var(--border); border-radius: calc(var(--radius) - 2px); padding: 8px 12px 12px; background: var(--muted); }
.block-item-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-size: 12px; color: var(--muted-foreground); }
.block-item-head .row { gap: 2px; }
.block-item-head { justify-content: flex-start; gap: 6px; }
.block-item-head .mono { flex: 1; }
.block-item[data-dragging] { position: relative; z-index: 2; user-select: none; box-shadow: 0 8px 24px rgb(0 0 0 / .12); }
.block-editor-foot { display: flex; gap: 12px; align-items: center; }
/* Export and import (0.42): icon buttons top right of the editor. .block-editor-tools > button.btn[data-variant=ghost]
   [data-size=icon] (download, copy, import); after an export the button shows a check for a moment (svg.icon-done). */
.block-editor-tools { display: flex; justify-content: flex-end; gap: 2px; margin-bottom: -4px; }
.block-editor-tools .btn { color: var(--muted-foreground); }
.block-editor-tools .btn:hover { color: var(--foreground); }
.block-editor-tools .icon-done, .block-editor-tools [data-done] .icon-main { display: none; }
.block-editor-tools [data-done] .icon-done { display: inline; }
/* 0.52: an editor with tabs (Text, Blocks, Source) puts the tools on the right of its tab row:
   .tabs.editor-tabs > nav[role=tablist] + .block-editor-tools#<id>, the editor root with data-tools="<id>". The tab
   row keeps a larger gap to the fields above, so it reads as the head of the content below. */
.tabs.editor-tabs { position: relative; margin-top: 32px; }
.tabs.editor-tabs > .block-editor-tools { position: absolute; top: 0; right: 0; height: 36px; align-items: center; margin: 0; }
.import-dialog textarea { width: 100%; min-height: 220px; }
.import-dialog .drop-line { display: flex; gap: 12px; align-items: center; margin-top: 12px; font-size: 14px; color: var(--muted-foreground); }
/* Lock (0.44): the text editor of a page while the page has blocks. .blocks-lock > .alert (with
   button[data-blocks-clear]) + .blocks-lock-body; data-locked dims the body, block-editor.js makes it inert. */
.blocks-lock > .alert { margin-bottom: 16px; }
.blocks-lock > .alert .btn { margin-top: 10px; justify-self: start; width: fit-content; grid-column: 1 / -1; }
.blocks-lock[data-locked] .blocks-lock-body { opacity: .45; }
.block-editor[data-empty] .block-list::before { content: attr(data-empty-text); font-size: 14px; color: var(--muted-foreground); }
.block-types { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.block-type { display: grid; gap: 2px; align-content: start; text-align: left; padding: 10px 12px; border: 1px solid var(--border); border-radius: calc(var(--radius) - 2px);
  background: var(--card); color: inherit; font: inherit; cursor: pointer; }
.block-type:hover { border-color: var(--muted-foreground); }
.block-type strong { font-size: 14px; font-weight: 500; color: var(--primary); }
.block-type span { font-size: 12px; line-height: 1.45; color: var(--muted-foreground); }
@media (max-width: 700px) {
  .block-types { grid-template-columns: 1fr; }
  .block-card-head { grid-template-columns: 24px minmax(0, 1fr) auto; }
  .block-card-preview { display: none; }
}

/* Install banner (0.48): mobile only, fixed above the bottom edge. .install-banner[hidden] > p + .row (button.btn + close icon button). */
.install-banner { position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 15; display: flex; align-items: center; gap: 12px; padding: 12px 14px;
                  background: var(--background); border: 1px solid var(--border); border-radius: var(--radius-lg, 10px); box-shadow: 0 8px 24px color-mix(in srgb, var(--foreground) 14%, transparent); }
.install-banner[hidden] { display: none; }
.install-banner p { flex: 1; min-width: 0; margin: 0; font-size: 14px; line-height: 1.35; }
.install-banner .row { flex: none; flex-wrap: nowrap; }
@media (min-width: 901px) { .install-banner { display: none; } }

/* Lesson on a phone held upright (0.48): the video and the tab row stay on screen while the panel scrolls. */
@media (max-width: 640px) and (orientation: portrait) {
  .unit-page { --lesson-top: 89px; }
  .unit-page:has(> .video) { --lesson-tabs-top: calc(var(--lesson-top) + (100vw - 40px) * 9 / 16); }
  .unit-page > .video { position: sticky; top: var(--lesson-top); z-index: 4; background: var(--background); }
  .lesson-tabs > [role="tablist"] { position: sticky; top: var(--lesson-tabs-top, var(--lesson-top)); z-index: 3; background: var(--background); padding-block: 8px; }
}

/* Video overlays (0.49). Chapters: .video > button.chapter-toggle + div.chapter-panel[hidden] > button[data-seek] (span title +
   small length + time). End screen: .video > div.video-end[hidden] > small + strong + .row. Both sit on a dark scrim, so
   they read over any picture. */
.chapter-toggle { position: absolute; top: 10px; right: 10px; z-index: 3; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 0;
                  border-radius: 50%; background: color-mix(in srgb, var(--image-scrim) 72%, transparent); color: var(--on-image); cursor: pointer; }
.chapter-toggle svg { width: 18px; height: 18px; }
.chapter-panel { position: absolute; top: 54px; right: 10px; bottom: 10px; z-index: 3; width: min(340px, calc(100% - 20px)); overflow-y: auto; padding: 6px; border-radius: 10px;
                 background: color-mix(in srgb, var(--image-scrim) 92%, transparent); color: var(--on-image); }
.chapter-panel[hidden] { display: none; }
.chapter-panel button { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px; width: 100%; padding: 8px 10px; border: 0; border-radius: 6px; background: none;
                        color: inherit; font: inherit; font-size: 14px; line-height: 1.3; text-align: left; cursor: pointer; }
.chapter-panel button:hover, .chapter-panel button[data-current] { background: color-mix(in srgb, var(--on-image) 14%, transparent); }
.chapter-panel small { grid-column: 1; font-size: 12px; opacity: .7; }
.chapter-panel .num { grid-column: 2; grid-row: 1; font: 400 12px/1.4 var(--font-mono); opacity: .8; }
.video-end { position: absolute; inset: 0; z-index: 2; display: grid; place-content: center; justify-items: center; gap: 10px; padding: 16px; text-align: center;
             background: color-mix(in srgb, var(--image-scrim) 86%, transparent); color: var(--on-image); }
.video-end[hidden] { display: none; }
.video-end small { font: 400 12px/1.4 var(--font-mono); opacity: .8; }
.video-end strong { max-width: 34em; font-size: 17px; font-weight: 500; line-height: 1.3; }
.video-end .num { margin-right: 8px; opacity: .7; }
.video-end .btn[data-variant="ghost"] { color: inherit; }

/* Sources of a lesson (0.49): ol.lesson-sources of plain links, numbered, like a bibliography. */
.lesson-sources a { overflow-wrap: anywhere; color: var(--brand); text-decoration: underline; text-underline-offset: 3px; }

/* Lesson head (0.49.2): a draft pill sits inline with the title; div.lesson-step keeps back and next together, right of the facts. */
.lesson-head h1 .badge { margin-left: 10px; vertical-align: middle; }
.lesson-meta > .lesson-step { display: flex; flex-wrap: nowrap; gap: 8px; margin-left: auto; }
@media (max-width: 640px) { .lesson-meta > .lesson-step { margin-left: 0; width: 100%; } }
